1*49149Sbostic /*- 2*49149Sbostic * Copyright (c) 1982, 1988 The Regents of the University of California. 3*49149Sbostic * All rights reserved. 4*49149Sbostic * 5*49149Sbostic * %sccs.include.proprietary.c% 6*49149Sbostic * 7*49149Sbostic * @(#)open.c 7.1 (Berkeley) 05/05/91 8*49149Sbostic */ 9*49149Sbostic 10*49149Sbostic #include <sys/param.h> 11*49149Sbostic #include <sys/reboot.h> 12*49149Sbostic #include <ufs/dir.h> 13*49149Sbostic #include "saio.h" 14*49149Sbostic 15*49149Sbostic int firstopen; 16*49149Sbostic u_int opendev; /* last device opened */ 17*49149Sbostic extern u_int bootdev; 18*49149Sbostic 19*49149Sbostic struct dirstuff { 20*49149Sbostic int loc; 21*49149Sbostic struct iob *io; 22*49149Sbostic }; 23*49149Sbostic 24*49149Sbostic #ifndef SMALL 25*49149Sbostic static ino_t dlook __P((char *, struct iob *, char *)); 26*49149Sbostic static int find __P((char *, struct iob *)); 27*49149Sbostic static int getdev __P((char *, int)); 28*49149Sbostic static int getunit __P((char *)); 29*49149Sbostic static struct direct *readdir __P((struct dirstuff *)); 30*49149Sbostic static int openi __P((int, struct iob *)); 31*49149Sbostic #endif 32*49149Sbostic 33*49149Sbostic open(str, how) 34*49149Sbostic char *str; 35*49149Sbostic int how; 36*49149Sbostic { 37*49149Sbostic static int firstopen = 1; 38*49149Sbostic register struct iob *file; 39*49149Sbostic register char *t; 40*49149Sbostic register int cnt; 41*49149Sbostic int fdesc, args[8], *argp; 42*49149Sbostic 43*49149Sbostic if (firstopen) { 44*49149Sbostic for (cnt = 0; cnt < SOPEN_MAX; cnt++) 45*49149Sbostic iob[cnt].i_flgs = 0; 46*49149Sbostic firstopen = 0; 47*49149Sbostic } 48*49149Sbostic 49*49149Sbostic for (fdesc = 0;; fdesc++) { 50*49149Sbostic if (fdesc == SOPEN_MAX) 51*49149Sbostic _stop("No more file slots"); 52*49149Sbostic if (iob[fdesc].i_flgs == 0) { 53*49149Sbostic file = &iob[fdesc]; 54*49149Sbostic file->i_flgs |= F_ALLOC; 55*49149Sbostic file->i_adapt = file->i_ctlr = file->i_unit = 56*49149Sbostic file->i_part = 0; 57*49149Sbostic break; 58*49149Sbostic } 59*49149Sbostic } 60*49149Sbostic 61*49149Sbostic for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0); 62*49149Sbostic #ifndef SMALL 63*49149Sbostic for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t) 64*49149Sbostic if (isupper(*t)) 65*49149Sbostic *t = tolower(*t); 66*49149Sbostic switch(*t) { 67*49149Sbostic case '(': /* type(adapt, ctlr, drive, partition)file */ 68*49149Sbostic if ((file->i_dev = getdev(str, t - str)) == -1) 69*49149Sbostic goto bad; 70*49149Sbostic for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) { 71*49149Sbostic for (++t; isspace(*t); ++t); 72*49149Sbostic if (*t == ')') 73*49149Sbostic break; 74*49149Sbostic if (!isdigit(*t)) 75*49149Sbostic goto badspec; 76*49149Sbostic *argp++ = atoi(t); 77*49149Sbostic for (++t; isdigit(*t); ++t); 78*49149Sbostic if (*t != ',' && *t != ')' || cnt == 4) 79*49149Sbostic goto badspec; 80*49149Sbostic } 81*49149Sbostic for (++t; isspace(*t); ++t); 82*49149Sbostic argp -= 4; 83*49149Sbostic file->i_adapt = *argp++; 84*49149Sbostic file->i_ctlr = *argp++; 85*49149Sbostic file->i_unit = *argp++; 86*49149Sbostic file->i_part = *argp; 87*49149Sbostic break; 88*49149Sbostic case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */ 89*49149Sbostic for (t = str; *t != ':' && !isdigit(*t); ++t); 90*49149Sbostic if ((file->i_dev = getdev(str, t - str)) == -1) 91*49149Sbostic goto bad; 92*49149Sbostic if ((file->i_unit = getunit(t)) == -1) 93*49149Sbostic goto bad; 94*49149Sbostic for (; isdigit(*t); ++t); 95*49149Sbostic if (*t >= 'a' && *t <= 'h') 96*49149Sbostic file->i_part = *t++ - 'a'; 97*49149Sbostic if (*t != ':') { 98*49149Sbostic errno = EOFFSET; 99*49149Sbostic goto badspec; 100*49149Sbostic } 101*49149Sbostic for (++t; isspace(*t); ++t); 102*49149Sbostic break; 103*49149Sbostic case '/': 104*49149Sbostic default: /* default bootstrap unit and device */ 105*49149Sbostic #else 106*49149Sbostic { 107*49149Sbostic #endif /* SMALL */ 108*49149Sbostic file->i_dev = B_TYPE(bootdev); 109*49149Sbostic file->i_adapt = B_ADAPTOR(bootdev); 110*49149Sbostic file->i_ctlr = B_CONTROLLER(bootdev); 111*49149Sbostic file->i_unit = B_UNIT(bootdev); 112*49149Sbostic file->i_part = B_PARTITION(bootdev); 113*49149Sbostic t = str; 114*49149Sbostic } 115*49149Sbostic 116*49149Sbostic opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr, 117*49149Sbostic file->i_unit, file->i_part); 118*49149Sbostic 119*49149Sbostic if (errno = devopen(file)) 120*49149Sbostic goto bad; 121*49149Sbostic 122*49149Sbostic if (*t == '\0') { 123*49149Sbostic file->i_flgs |= how + 1; 124*49149Sbostic file->i_cc = 0; 125*49149Sbostic file->i_offset = 0; 126*49149Sbostic return (fdesc+3); 127*49149Sbostic } 128*49149Sbostic #ifndef SMALL 129*49149Sbostic else if (how != 0) { 130*49149Sbostic printf("Can't write files yet.. Sorry\n"); 131*49149Sbostic errno = EIO; 132*49149Sbostic goto bad; 133*49149Sbostic } 134*49149Sbostic #endif 135*49149Sbostic file->i_ma = (char *)(&file->i_fs); 136*49149Sbostic file->i_cc = SBSIZE; 137*49149Sbostic file->i_bn = SBOFF / DEV_BSIZE + file->i_boff; 138*49149Sbostic file->i_offset = 0; 139*49149Sbostic if (devread(file) < 0) { 140*49149Sbostic errno = file->i_error; 141*49149Sbostic printf("super block read error\n"); 142*49149Sbostic goto bad; 143*49149Sbostic } 144*49149Sbostic if ((cnt = find(t, file)) == 0) { 145*49149Sbostic errno = ESRCH; 146*49149Sbostic goto bad; 147*49149Sbostic } 148*49149Sbostic if (openi(cnt, file) < 0) { 149*49149Sbostic errno = file->i_error; 150*49149Sbostic goto bad; 151*49149Sbostic } 152*49149Sbostic file->i_offset = 0; 153*49149Sbostic file->i_cc = 0; 154*49149Sbostic file->i_flgs |= F_FILE | (how+1); 155*49149Sbostic return (fdesc+3); 156*49149Sbostic 157*49149Sbostic #ifndef SMALL 158*49149Sbostic badspec: 159*49149Sbostic printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n"); 160*49149Sbostic #endif 161*49149Sbostic bad: 162*49149Sbostic file->i_flgs = 0; 163*49149Sbostic return (-1); 164*49149Sbostic } 165*49149Sbostic 166*49149Sbostic #ifndef SMALL 167*49149Sbostic static 168*49149Sbostic getdev(str, len) 169*49149Sbostic register char *str; 170*49149Sbostic int len; 171*49149Sbostic { 172*49149Sbostic register struct devsw *dp; 173*49149Sbostic register int i; 174*49149Sbostic char savedch = str[len]; 175*49149Sbostic 176*49149Sbostic str[len] = '\0'; 177*49149Sbostic for (dp = devsw, i = 0; i < ndevs; dp++, i++) 178*49149Sbostic if (dp->dv_name && strcmp(str, dp->dv_name) == 0) { 179*49149Sbostic str[len] = savedch; 180*49149Sbostic return (i); 181*49149Sbostic } 182*49149Sbostic printf("Unknown device\nKnown devices are:\n"); 183*49149Sbostic for (dp = devsw, i = 0; i < ndevs; dp++, i++) 184*49149Sbostic if (dp->dv_name) 185*49149Sbostic printf(" %s", dp->dv_name); 186*49149Sbostic printf("\n"); 187*49149Sbostic errno = ENXIO; 188*49149Sbostic return (-1); 189*49149Sbostic } 190*49149Sbostic 191*49149Sbostic static 192*49149Sbostic getunit(cp) 193*49149Sbostic register char *cp; 194*49149Sbostic { 195*49149Sbostic int unit; 196*49149Sbostic 197*49149Sbostic unit = atoi(cp); 198*49149Sbostic if ((u_int)unit > 255) { 199*49149Sbostic printf("minor device number out of range (0-255)\n"); 200*49149Sbostic errno = EUNIT; 201*49149Sbostic return (-1); 202*49149Sbostic } 203*49149Sbostic return (unit); 204*49149Sbostic } 205*49149Sbostic #endif /* SMALL */ 206*49149Sbostic 207*49149Sbostic static 208*49149Sbostic find(path, file) 209*49149Sbostic register char *path; 210*49149Sbostic struct iob *file; 211*49149Sbostic { 212*49149Sbostic register char *q; 213*49149Sbostic char *dir, c; 214*49149Sbostic int n; 215*49149Sbostic 216*49149Sbostic if (path == NULL || *path == '\0') { 217*49149Sbostic printf("null path\n"); 218*49149Sbostic return (0); 219*49149Sbostic } 220*49149Sbostic 221*49149Sbostic if (openi((ino_t) ROOTINO, file) < 0) { 222*49149Sbostic printf("can't read root inode\n"); 223*49149Sbostic return (0); 224*49149Sbostic } 225*49149Sbostic dir = path; 226*49149Sbostic while (*path) { 227*49149Sbostic while (*path == '/') 228*49149Sbostic path++; 229*49149Sbostic q = path; 230*49149Sbostic while(*q != '/' && *q != '\0') 231*49149Sbostic q++; 232*49149Sbostic c = *q; 233*49149Sbostic *q = '\0'; 234*49149Sbostic if (q == path) path = "." ; /* "/" means "/." */ 235*49149Sbostic 236*49149Sbostic if ((n = dlook(path, file, dir)) != 0) { 237*49149Sbostic if (c == '\0') 238*49149Sbostic break; 239*49149Sbostic if (openi(n, file) < 0) 240*49149Sbostic return (0); 241*49149Sbostic *q = c; 242*49149Sbostic path = q; 243*49149Sbostic continue; 244*49149Sbostic } else { 245*49149Sbostic printf("%s: not found\n", path); 246*49149Sbostic return (0); 247*49149Sbostic } 248*49149Sbostic } 249*49149Sbostic return (n); 250*49149Sbostic } 251*49149Sbostic 252*49149Sbostic static ino_t 253*49149Sbostic dlook(s, io, dir) 254*49149Sbostic char *s; 255*49149Sbostic register struct iob *io; 256*49149Sbostic char *dir; 257*49149Sbostic { 258*49149Sbostic register struct direct *dp; 259*49149Sbostic register struct dinode *ip; 260*49149Sbostic struct dirstuff dirp; 261*49149Sbostic int len; 262*49149Sbostic 263*49149Sbostic if (s == NULL || *s == '\0') 264*49149Sbostic return (0); 265*49149Sbostic ip = &io->i_ino; 266*49149Sbostic if ((ip->di_mode&IFMT) != IFDIR) { 267*49149Sbostic printf("%s: not a directory\n", dir); 268*49149Sbostic return (0); 269*49149Sbostic } 270*49149Sbostic if (ip->di_size == 0) { 271*49149Sbostic printf("%s: zero length directory\n", dir); 272*49149Sbostic return (0); 273*49149Sbostic } 274*49149Sbostic len = strlen(s); 275*49149Sbostic dirp.loc = 0; 276*49149Sbostic dirp.io = io; 277*49149Sbostic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 278*49149Sbostic if(dp->d_ino == 0) 279*49149Sbostic continue; 280*49149Sbostic if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 281*49149Sbostic return (dp->d_ino); 282*49149Sbostic } 283*49149Sbostic return (0); 284*49149Sbostic } 285*49149Sbostic 286*49149Sbostic static struct direct * 287*49149Sbostic readdir(dirp) 288*49149Sbostic register struct dirstuff *dirp; 289*49149Sbostic { 290*49149Sbostic register struct direct *dp; 291*49149Sbostic register struct iob *io; 292*49149Sbostic daddr_t lbn, d; 293*49149Sbostic int off; 294*49149Sbostic 295*49149Sbostic io = dirp->io; 296*49149Sbostic for(;;) { 297*49149Sbostic if (dirp->loc >= io->i_ino.di_size) 298*49149Sbostic return (NULL); 299*49149Sbostic off = blkoff(&io->i_fs, dirp->loc); 300*49149Sbostic if (off == 0) { 301*49149Sbostic lbn = lblkno(&io->i_fs, dirp->loc); 302*49149Sbostic d = bmap(io, lbn); 303*49149Sbostic if(d == 0) 304*49149Sbostic return (NULL); 305*49149Sbostic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 306*49149Sbostic io->i_ma = io->i_buf; 307*49149Sbostic io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn); 308*49149Sbostic if (devread(io) < 0) { 309*49149Sbostic errno = io->i_error; 310*49149Sbostic printf("bn %D: directory read error\n", 311*49149Sbostic io->i_bn); 312*49149Sbostic return (NULL); 313*49149Sbostic } 314*49149Sbostic } 315*49149Sbostic dp = (struct direct *)(io->i_buf + off); 316*49149Sbostic dirp->loc += dp->d_reclen; 317*49149Sbostic if (dp->d_ino == 0) 318*49149Sbostic continue; 319*49149Sbostic return (dp); 320*49149Sbostic } 321*49149Sbostic } 322*49149Sbostic 323*49149Sbostic static 324*49149Sbostic openi(n, io) 325*49149Sbostic int n; 326*49149Sbostic register struct iob *io; 327*49149Sbostic { 328*49149Sbostic register struct dinode *dp; 329*49149Sbostic int cc; 330*49149Sbostic 331*49149Sbostic io->i_offset = 0; 332*49149Sbostic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 333*49149Sbostic io->i_cc = io->i_fs.fs_bsize; 334*49149Sbostic io->i_ma = io->i_buf; 335*49149Sbostic cc = devread(io); 336*49149Sbostic dp = (struct dinode *)io->i_buf; 337*49149Sbostic io->i_ino = dp[itoo(&io->i_fs, n)]; 338*49149Sbostic return (cc); 339*49149Sbostic } 340*49149Sbostic 341