149149Sbostic /*- 249149Sbostic * Copyright (c) 1982, 1988 The Regents of the University of California. 349149Sbostic * All rights reserved. 449149Sbostic * 549149Sbostic * %sccs.include.proprietary.c% 649149Sbostic * 7*63719Smckusick * @(#)open.c 7.7 (Berkeley) 07/07/93 849149Sbostic */ 949149Sbostic 1049149Sbostic #include <sys/param.h> 1149149Sbostic #include <sys/reboot.h> 1256509Sbostic 1353697Ssklower #include <ufs/ufs/dir.h> 1460328Smckusick #include <stand.att/saio.h> 1549149Sbostic 1649149Sbostic int firstopen; 1749149Sbostic u_int opendev; /* last device opened */ 1849149Sbostic extern u_int bootdev; 1949149Sbostic 2049149Sbostic struct dirstuff { 2149149Sbostic int loc; 2249149Sbostic struct iob *io; 2355894Shibler char *name; 2449149Sbostic }; 2549149Sbostic 2649149Sbostic #ifndef SMALL 27*63719Smckusick /* 28*63719Smckusick * XXX avoid stdio... its a long story. 29*63719Smckusick */ 30*63719Smckusick #define isupper(c) ((c) >= 'A' && (c) <= 'Z') 31*63719Smckusick #define tolower(c) ((c) - 'A' + 'a') 32*63719Smckusick #define isspace(c) ((c) == ' ' || (c) == '\t') 33*63719Smckusick #define isdigit(c) ((c) >= '0' && (c) <= '9') 34*63719Smckusick 3549149Sbostic static ino_t dlook __P((char *, struct iob *, char *)); 3649149Sbostic static int find __P((char *, struct iob *)); 3749149Sbostic static int getdev __P((char *, int)); 3849149Sbostic static int getunit __P((char *)); 3949149Sbostic static struct direct *readdir __P((struct dirstuff *)); 4049149Sbostic static int openi __P((int, struct iob *)); 4149149Sbostic #endif 4249149Sbostic 4349149Sbostic open(str, how) 4449149Sbostic char *str; 4549149Sbostic int how; 4649149Sbostic { 4749149Sbostic static int firstopen = 1; 4849149Sbostic register struct iob *file; 4949149Sbostic register char *t; 5049149Sbostic register int cnt; 5149149Sbostic int fdesc, args[8], *argp; 5249149Sbostic 5349149Sbostic if (firstopen) { 5449149Sbostic for (cnt = 0; cnt < SOPEN_MAX; cnt++) 5549149Sbostic iob[cnt].i_flgs = 0; 5649149Sbostic firstopen = 0; 5749149Sbostic } 5849149Sbostic 5949149Sbostic for (fdesc = 0;; fdesc++) { 6049149Sbostic if (fdesc == SOPEN_MAX) 6149149Sbostic _stop("No more file slots"); 6249149Sbostic if (iob[fdesc].i_flgs == 0) { 6349149Sbostic file = &iob[fdesc]; 6449149Sbostic file->i_flgs |= F_ALLOC; 6549149Sbostic file->i_adapt = file->i_ctlr = file->i_unit = 6649149Sbostic file->i_part = 0; 6749149Sbostic break; 6849149Sbostic } 6949149Sbostic } 7049149Sbostic 7149149Sbostic for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0); 7249149Sbostic #ifndef SMALL 7349149Sbostic for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t) 7449149Sbostic if (isupper(*t)) 7549149Sbostic *t = tolower(*t); 7649149Sbostic switch(*t) { 7749149Sbostic case '(': /* type(adapt, ctlr, drive, partition)file */ 7849149Sbostic if ((file->i_dev = getdev(str, t - str)) == -1) 7949149Sbostic goto bad; 8049149Sbostic for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) { 8149149Sbostic for (++t; isspace(*t); ++t); 8249149Sbostic if (*t == ')') 8349149Sbostic break; 8449149Sbostic if (!isdigit(*t)) 8549149Sbostic goto badspec; 8649149Sbostic *argp++ = atoi(t); 8749149Sbostic for (++t; isdigit(*t); ++t); 8849149Sbostic if (*t != ',' && *t != ')' || cnt == 4) 8949149Sbostic goto badspec; 9049149Sbostic } 9149149Sbostic for (++t; isspace(*t); ++t); 9249149Sbostic argp -= 4; 9349149Sbostic file->i_adapt = *argp++; 9449149Sbostic file->i_ctlr = *argp++; 9549149Sbostic file->i_unit = *argp++; 9649149Sbostic file->i_part = *argp; 9749149Sbostic break; 9849149Sbostic case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */ 9949149Sbostic for (t = str; *t != ':' && !isdigit(*t); ++t); 10049149Sbostic if ((file->i_dev = getdev(str, t - str)) == -1) 10149149Sbostic goto bad; 10249149Sbostic if ((file->i_unit = getunit(t)) == -1) 10349149Sbostic goto bad; 10449149Sbostic for (; isdigit(*t); ++t); 10549149Sbostic if (*t >= 'a' && *t <= 'h') 10649149Sbostic file->i_part = *t++ - 'a'; 10749149Sbostic if (*t != ':') { 10849149Sbostic errno = EOFFSET; 10949149Sbostic goto badspec; 11049149Sbostic } 11149149Sbostic for (++t; isspace(*t); ++t); 11249149Sbostic break; 11349149Sbostic case '/': 11449149Sbostic default: /* default bootstrap unit and device */ 11549149Sbostic #else 11649149Sbostic { 11749149Sbostic #endif /* SMALL */ 11849149Sbostic file->i_dev = B_TYPE(bootdev); 11949149Sbostic file->i_adapt = B_ADAPTOR(bootdev); 12049149Sbostic file->i_ctlr = B_CONTROLLER(bootdev); 12149149Sbostic file->i_unit = B_UNIT(bootdev); 12249149Sbostic file->i_part = B_PARTITION(bootdev); 12349149Sbostic t = str; 12449149Sbostic } 12549149Sbostic 12649149Sbostic opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr, 12749149Sbostic file->i_unit, file->i_part); 12849149Sbostic 12949149Sbostic if (errno = devopen(file)) 13049149Sbostic goto bad; 13149149Sbostic 13249149Sbostic if (*t == '\0') { 13349149Sbostic file->i_flgs |= how + 1; 13449149Sbostic file->i_cc = 0; 13549149Sbostic file->i_offset = 0; 13649149Sbostic return (fdesc+3); 13749149Sbostic } 13849149Sbostic #ifndef SMALL 13949149Sbostic else if (how != 0) { 14049149Sbostic printf("Can't write files yet.. Sorry\n"); 14149149Sbostic errno = EIO; 14249149Sbostic goto bad; 14349149Sbostic } 14449149Sbostic #endif 14549149Sbostic file->i_ma = (char *)(&file->i_fs); 14649149Sbostic file->i_cc = SBSIZE; 14749149Sbostic file->i_bn = SBOFF / DEV_BSIZE + file->i_boff; 14849149Sbostic file->i_offset = 0; 14949149Sbostic if (devread(file) < 0) { 15049149Sbostic errno = file->i_error; 15149149Sbostic printf("super block read error\n"); 15249149Sbostic goto bad; 15349149Sbostic } 15449149Sbostic if ((cnt = find(t, file)) == 0) { 15549149Sbostic errno = ESRCH; 15649149Sbostic goto bad; 15749149Sbostic } 15849149Sbostic if (openi(cnt, file) < 0) { 15949149Sbostic errno = file->i_error; 16049149Sbostic goto bad; 16149149Sbostic } 16249149Sbostic file->i_offset = 0; 16349149Sbostic file->i_cc = 0; 16449149Sbostic file->i_flgs |= F_FILE | (how+1); 16549149Sbostic return (fdesc+3); 16649149Sbostic 16749149Sbostic #ifndef SMALL 16849149Sbostic badspec: 16949149Sbostic printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n"); 17049149Sbostic #endif 17149149Sbostic bad: 17249149Sbostic file->i_flgs = 0; 17349149Sbostic return (-1); 17449149Sbostic } 17549149Sbostic 17649149Sbostic #ifndef SMALL 17749149Sbostic static 17849149Sbostic getdev(str, len) 17949149Sbostic register char *str; 18049149Sbostic int len; 18149149Sbostic { 18249149Sbostic register struct devsw *dp; 18349149Sbostic register int i; 18449149Sbostic char savedch = str[len]; 18549149Sbostic 18649149Sbostic str[len] = '\0'; 18749149Sbostic for (dp = devsw, i = 0; i < ndevs; dp++, i++) 18849149Sbostic if (dp->dv_name && strcmp(str, dp->dv_name) == 0) { 18949149Sbostic str[len] = savedch; 19049149Sbostic return (i); 19149149Sbostic } 19249149Sbostic printf("Unknown device\nKnown devices are:\n"); 19349149Sbostic for (dp = devsw, i = 0; i < ndevs; dp++, i++) 19449149Sbostic if (dp->dv_name) 19549149Sbostic printf(" %s", dp->dv_name); 19649149Sbostic printf("\n"); 19749149Sbostic errno = ENXIO; 19849149Sbostic return (-1); 19949149Sbostic } 20049149Sbostic 20149149Sbostic static 20249149Sbostic getunit(cp) 20349149Sbostic register char *cp; 20449149Sbostic { 20549149Sbostic int unit; 20649149Sbostic 20749149Sbostic unit = atoi(cp); 20849149Sbostic if ((u_int)unit > 255) { 20949149Sbostic printf("minor device number out of range (0-255)\n"); 21049149Sbostic errno = EUNIT; 21149149Sbostic return (-1); 21249149Sbostic } 21349149Sbostic return (unit); 21449149Sbostic } 215*63719Smckusick 216*63719Smckusick /* 217*63719Smckusick * XXX more stdio-avoidance. 218*63719Smckusick */ 219*63719Smckusick static 220*63719Smckusick atoi(cp) 221*63719Smckusick char *cp; 222*63719Smckusick { 223*63719Smckusick int val = 0; 224*63719Smckusick 225*63719Smckusick while (*cp >= '0' && *cp <= '9') 226*63719Smckusick val = val * 10 + (*cp++ - '0'); 227*63719Smckusick return (val); 228*63719Smckusick } 22949149Sbostic #endif /* SMALL */ 23049149Sbostic 23149149Sbostic static 23249149Sbostic find(path, file) 23349149Sbostic register char *path; 23449149Sbostic struct iob *file; 23549149Sbostic { 23649149Sbostic register char *q; 23749149Sbostic char *dir, c; 23849149Sbostic int n; 23949149Sbostic 24049149Sbostic if (path == NULL || *path == '\0') { 24149149Sbostic printf("null path\n"); 24249149Sbostic return (0); 24349149Sbostic } 24449149Sbostic 24549149Sbostic if (openi((ino_t) ROOTINO, file) < 0) { 24649149Sbostic printf("can't read root inode\n"); 24749149Sbostic return (0); 24849149Sbostic } 24949149Sbostic dir = path; 25049149Sbostic while (*path) { 25149149Sbostic while (*path == '/') 25249149Sbostic path++; 25349149Sbostic q = path; 25449149Sbostic while(*q != '/' && *q != '\0') 25549149Sbostic q++; 25649149Sbostic c = *q; 25749149Sbostic *q = '\0'; 25849149Sbostic if (q == path) path = "." ; /* "/" means "/." */ 25949149Sbostic 26049149Sbostic if ((n = dlook(path, file, dir)) != 0) { 26149149Sbostic if (c == '\0') 26249149Sbostic break; 26349149Sbostic if (openi(n, file) < 0) 26449149Sbostic return (0); 26549149Sbostic *q = c; 26649149Sbostic path = q; 26749149Sbostic continue; 26849149Sbostic } else { 26949149Sbostic printf("%s: not found\n", path); 27049149Sbostic return (0); 27149149Sbostic } 27249149Sbostic } 27349149Sbostic return (n); 27449149Sbostic } 27549149Sbostic 27649149Sbostic static ino_t 27749149Sbostic dlook(s, io, dir) 27849149Sbostic char *s; 27949149Sbostic register struct iob *io; 28049149Sbostic char *dir; 28149149Sbostic { 28249149Sbostic register struct direct *dp; 28349149Sbostic register struct dinode *ip; 28449149Sbostic struct dirstuff dirp; 28549149Sbostic int len; 28649149Sbostic 28749149Sbostic if (s == NULL || *s == '\0') 28849149Sbostic return (0); 28949149Sbostic ip = &io->i_ino; 29049149Sbostic if ((ip->di_mode&IFMT) != IFDIR) { 29149149Sbostic printf("%s: not a directory\n", dir); 29249149Sbostic return (0); 29349149Sbostic } 29449149Sbostic if (ip->di_size == 0) { 29549149Sbostic printf("%s: zero length directory\n", dir); 29649149Sbostic return (0); 29749149Sbostic } 29849149Sbostic len = strlen(s); 29949149Sbostic dirp.loc = 0; 30049149Sbostic dirp.io = io; 30155894Shibler dirp.name = dir; 30249149Sbostic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 30349149Sbostic if(dp->d_ino == 0) 30449149Sbostic continue; 30549149Sbostic if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 30649149Sbostic return (dp->d_ino); 30749149Sbostic } 30849149Sbostic return (0); 30949149Sbostic } 31049149Sbostic 31149149Sbostic static struct direct * 31249149Sbostic readdir(dirp) 31349149Sbostic register struct dirstuff *dirp; 31449149Sbostic { 31549149Sbostic register struct direct *dp; 31649149Sbostic register struct iob *io; 31749149Sbostic daddr_t lbn, d; 31849149Sbostic int off; 31949149Sbostic 32049149Sbostic io = dirp->io; 32149149Sbostic for(;;) { 32249149Sbostic if (dirp->loc >= io->i_ino.di_size) 32349149Sbostic return (NULL); 32449149Sbostic off = blkoff(&io->i_fs, dirp->loc); 32549149Sbostic if (off == 0) { 32649149Sbostic lbn = lblkno(&io->i_fs, dirp->loc); 32749149Sbostic d = bmap(io, lbn); 32849149Sbostic if(d == 0) 32949149Sbostic return (NULL); 33049149Sbostic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 33149149Sbostic io->i_ma = io->i_buf; 33249149Sbostic io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn); 33349149Sbostic if (devread(io) < 0) { 33449149Sbostic errno = io->i_error; 33555894Shibler printf("%s: directory read error, bn %ld\n", 33655894Shibler dirp->name, io->i_bn); 33749149Sbostic return (NULL); 33849149Sbostic } 33949149Sbostic } 34049149Sbostic dp = (struct direct *)(io->i_buf + off); 34149149Sbostic dirp->loc += dp->d_reclen; 34255894Shibler if (dp->d_ino == 0) { 34355894Shibler if (dp->d_reclen == 0) { 34455894Shibler printf("%s: bad directory entry, offset %ld\n", 34555894Shibler dirp->name, dirp->loc); 34655894Shibler return (NULL); 34755894Shibler } 34849149Sbostic continue; 34955894Shibler } 35049149Sbostic return (dp); 35149149Sbostic } 35249149Sbostic } 35349149Sbostic 35449149Sbostic static 35549149Sbostic openi(n, io) 35649149Sbostic int n; 35749149Sbostic register struct iob *io; 35849149Sbostic { 35949149Sbostic register struct dinode *dp; 36049149Sbostic int cc; 36149149Sbostic 36249149Sbostic io->i_offset = 0; 36349149Sbostic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 36449149Sbostic io->i_cc = io->i_fs.fs_bsize; 36549149Sbostic io->i_ma = io->i_buf; 36649149Sbostic cc = devread(io); 36749149Sbostic dp = (struct dinode *)io->i_buf; 36849149Sbostic io->i_ino = dp[itoo(&io->i_fs, n)]; 36949149Sbostic return (cc); 37049149Sbostic } 371