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*56509Sbostic * @(#)open.c 7.5 (Berkeley) 10/11/92 849149Sbostic */ 949149Sbostic 1049149Sbostic #include <sys/param.h> 1149149Sbostic #include <sys/reboot.h> 12*56509Sbostic 1353697Ssklower #include <ufs/ufs/dir.h> 14*56509Sbostic #include <stand/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 2749149Sbostic static ino_t dlook __P((char *, struct iob *, char *)); 2849149Sbostic static int find __P((char *, struct iob *)); 2949149Sbostic static int getdev __P((char *, int)); 3049149Sbostic static int getunit __P((char *)); 3149149Sbostic static struct direct *readdir __P((struct dirstuff *)); 3249149Sbostic static int openi __P((int, struct iob *)); 3349149Sbostic #endif 3449149Sbostic 3549149Sbostic open(str, how) 3649149Sbostic char *str; 3749149Sbostic int how; 3849149Sbostic { 3949149Sbostic static int firstopen = 1; 4049149Sbostic register struct iob *file; 4149149Sbostic register char *t; 4249149Sbostic register int cnt; 4349149Sbostic int fdesc, args[8], *argp; 4449149Sbostic 4549149Sbostic if (firstopen) { 4649149Sbostic for (cnt = 0; cnt < SOPEN_MAX; cnt++) 4749149Sbostic iob[cnt].i_flgs = 0; 4849149Sbostic firstopen = 0; 4949149Sbostic } 5049149Sbostic 5149149Sbostic for (fdesc = 0;; fdesc++) { 5249149Sbostic if (fdesc == SOPEN_MAX) 5349149Sbostic _stop("No more file slots"); 5449149Sbostic if (iob[fdesc].i_flgs == 0) { 5549149Sbostic file = &iob[fdesc]; 5649149Sbostic file->i_flgs |= F_ALLOC; 5749149Sbostic file->i_adapt = file->i_ctlr = file->i_unit = 5849149Sbostic file->i_part = 0; 5949149Sbostic break; 6049149Sbostic } 6149149Sbostic } 6249149Sbostic 6349149Sbostic for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0); 6449149Sbostic #ifndef SMALL 6549149Sbostic for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t) 6649149Sbostic if (isupper(*t)) 6749149Sbostic *t = tolower(*t); 6849149Sbostic switch(*t) { 6949149Sbostic case '(': /* type(adapt, ctlr, drive, partition)file */ 7049149Sbostic if ((file->i_dev = getdev(str, t - str)) == -1) 7149149Sbostic goto bad; 7249149Sbostic for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) { 7349149Sbostic for (++t; isspace(*t); ++t); 7449149Sbostic if (*t == ')') 7549149Sbostic break; 7649149Sbostic if (!isdigit(*t)) 7749149Sbostic goto badspec; 7849149Sbostic *argp++ = atoi(t); 7949149Sbostic for (++t; isdigit(*t); ++t); 8049149Sbostic if (*t != ',' && *t != ')' || cnt == 4) 8149149Sbostic goto badspec; 8249149Sbostic } 8349149Sbostic for (++t; isspace(*t); ++t); 8449149Sbostic argp -= 4; 8549149Sbostic file->i_adapt = *argp++; 8649149Sbostic file->i_ctlr = *argp++; 8749149Sbostic file->i_unit = *argp++; 8849149Sbostic file->i_part = *argp; 8949149Sbostic break; 9049149Sbostic case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */ 9149149Sbostic for (t = str; *t != ':' && !isdigit(*t); ++t); 9249149Sbostic if ((file->i_dev = getdev(str, t - str)) == -1) 9349149Sbostic goto bad; 9449149Sbostic if ((file->i_unit = getunit(t)) == -1) 9549149Sbostic goto bad; 9649149Sbostic for (; isdigit(*t); ++t); 9749149Sbostic if (*t >= 'a' && *t <= 'h') 9849149Sbostic file->i_part = *t++ - 'a'; 9949149Sbostic if (*t != ':') { 10049149Sbostic errno = EOFFSET; 10149149Sbostic goto badspec; 10249149Sbostic } 10349149Sbostic for (++t; isspace(*t); ++t); 10449149Sbostic break; 10549149Sbostic case '/': 10649149Sbostic default: /* default bootstrap unit and device */ 10749149Sbostic #else 10849149Sbostic { 10949149Sbostic #endif /* SMALL */ 11049149Sbostic file->i_dev = B_TYPE(bootdev); 11149149Sbostic file->i_adapt = B_ADAPTOR(bootdev); 11249149Sbostic file->i_ctlr = B_CONTROLLER(bootdev); 11349149Sbostic file->i_unit = B_UNIT(bootdev); 11449149Sbostic file->i_part = B_PARTITION(bootdev); 11549149Sbostic t = str; 11649149Sbostic } 11749149Sbostic 11849149Sbostic opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr, 11949149Sbostic file->i_unit, file->i_part); 12049149Sbostic 12149149Sbostic if (errno = devopen(file)) 12249149Sbostic goto bad; 12349149Sbostic 12449149Sbostic if (*t == '\0') { 12549149Sbostic file->i_flgs |= how + 1; 12649149Sbostic file->i_cc = 0; 12749149Sbostic file->i_offset = 0; 12849149Sbostic return (fdesc+3); 12949149Sbostic } 13049149Sbostic #ifndef SMALL 13149149Sbostic else if (how != 0) { 13249149Sbostic printf("Can't write files yet.. Sorry\n"); 13349149Sbostic errno = EIO; 13449149Sbostic goto bad; 13549149Sbostic } 13649149Sbostic #endif 13749149Sbostic file->i_ma = (char *)(&file->i_fs); 13849149Sbostic file->i_cc = SBSIZE; 13949149Sbostic file->i_bn = SBOFF / DEV_BSIZE + file->i_boff; 14049149Sbostic file->i_offset = 0; 14149149Sbostic if (devread(file) < 0) { 14249149Sbostic errno = file->i_error; 14349149Sbostic printf("super block read error\n"); 14449149Sbostic goto bad; 14549149Sbostic } 14649149Sbostic if ((cnt = find(t, file)) == 0) { 14749149Sbostic errno = ESRCH; 14849149Sbostic goto bad; 14949149Sbostic } 15049149Sbostic if (openi(cnt, file) < 0) { 15149149Sbostic errno = file->i_error; 15249149Sbostic goto bad; 15349149Sbostic } 15449149Sbostic file->i_offset = 0; 15549149Sbostic file->i_cc = 0; 15649149Sbostic file->i_flgs |= F_FILE | (how+1); 15749149Sbostic return (fdesc+3); 15849149Sbostic 15949149Sbostic #ifndef SMALL 16049149Sbostic badspec: 16149149Sbostic printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n"); 16249149Sbostic #endif 16349149Sbostic bad: 16449149Sbostic file->i_flgs = 0; 16549149Sbostic return (-1); 16649149Sbostic } 16749149Sbostic 16849149Sbostic #ifndef SMALL 16949149Sbostic static 17049149Sbostic getdev(str, len) 17149149Sbostic register char *str; 17249149Sbostic int len; 17349149Sbostic { 17449149Sbostic register struct devsw *dp; 17549149Sbostic register int i; 17649149Sbostic char savedch = str[len]; 17749149Sbostic 17849149Sbostic str[len] = '\0'; 17949149Sbostic for (dp = devsw, i = 0; i < ndevs; dp++, i++) 18049149Sbostic if (dp->dv_name && strcmp(str, dp->dv_name) == 0) { 18149149Sbostic str[len] = savedch; 18249149Sbostic return (i); 18349149Sbostic } 18449149Sbostic printf("Unknown device\nKnown devices are:\n"); 18549149Sbostic for (dp = devsw, i = 0; i < ndevs; dp++, i++) 18649149Sbostic if (dp->dv_name) 18749149Sbostic printf(" %s", dp->dv_name); 18849149Sbostic printf("\n"); 18949149Sbostic errno = ENXIO; 19049149Sbostic return (-1); 19149149Sbostic } 19249149Sbostic 19349149Sbostic static 19449149Sbostic getunit(cp) 19549149Sbostic register char *cp; 19649149Sbostic { 19749149Sbostic int unit; 19849149Sbostic 19949149Sbostic unit = atoi(cp); 20049149Sbostic if ((u_int)unit > 255) { 20149149Sbostic printf("minor device number out of range (0-255)\n"); 20249149Sbostic errno = EUNIT; 20349149Sbostic return (-1); 20449149Sbostic } 20549149Sbostic return (unit); 20649149Sbostic } 20749149Sbostic #endif /* SMALL */ 20849149Sbostic 20949149Sbostic static 21049149Sbostic find(path, file) 21149149Sbostic register char *path; 21249149Sbostic struct iob *file; 21349149Sbostic { 21449149Sbostic register char *q; 21549149Sbostic char *dir, c; 21649149Sbostic int n; 21749149Sbostic 21849149Sbostic if (path == NULL || *path == '\0') { 21949149Sbostic printf("null path\n"); 22049149Sbostic return (0); 22149149Sbostic } 22249149Sbostic 22349149Sbostic if (openi((ino_t) ROOTINO, file) < 0) { 22449149Sbostic printf("can't read root inode\n"); 22549149Sbostic return (0); 22649149Sbostic } 22749149Sbostic dir = path; 22849149Sbostic while (*path) { 22949149Sbostic while (*path == '/') 23049149Sbostic path++; 23149149Sbostic q = path; 23249149Sbostic while(*q != '/' && *q != '\0') 23349149Sbostic q++; 23449149Sbostic c = *q; 23549149Sbostic *q = '\0'; 23649149Sbostic if (q == path) path = "." ; /* "/" means "/." */ 23749149Sbostic 23849149Sbostic if ((n = dlook(path, file, dir)) != 0) { 23949149Sbostic if (c == '\0') 24049149Sbostic break; 24149149Sbostic if (openi(n, file) < 0) 24249149Sbostic return (0); 24349149Sbostic *q = c; 24449149Sbostic path = q; 24549149Sbostic continue; 24649149Sbostic } else { 24749149Sbostic printf("%s: not found\n", path); 24849149Sbostic return (0); 24949149Sbostic } 25049149Sbostic } 25149149Sbostic return (n); 25249149Sbostic } 25349149Sbostic 25449149Sbostic static ino_t 25549149Sbostic dlook(s, io, dir) 25649149Sbostic char *s; 25749149Sbostic register struct iob *io; 25849149Sbostic char *dir; 25949149Sbostic { 26049149Sbostic register struct direct *dp; 26149149Sbostic register struct dinode *ip; 26249149Sbostic struct dirstuff dirp; 26349149Sbostic int len; 26449149Sbostic 26549149Sbostic if (s == NULL || *s == '\0') 26649149Sbostic return (0); 26749149Sbostic ip = &io->i_ino; 26849149Sbostic if ((ip->di_mode&IFMT) != IFDIR) { 26949149Sbostic printf("%s: not a directory\n", dir); 27049149Sbostic return (0); 27149149Sbostic } 27249149Sbostic if (ip->di_size == 0) { 27349149Sbostic printf("%s: zero length directory\n", dir); 27449149Sbostic return (0); 27549149Sbostic } 27649149Sbostic len = strlen(s); 27749149Sbostic dirp.loc = 0; 27849149Sbostic dirp.io = io; 27955894Shibler dirp.name = dir; 28049149Sbostic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 28149149Sbostic if(dp->d_ino == 0) 28249149Sbostic continue; 28349149Sbostic if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 28449149Sbostic return (dp->d_ino); 28549149Sbostic } 28649149Sbostic return (0); 28749149Sbostic } 28849149Sbostic 28949149Sbostic static struct direct * 29049149Sbostic readdir(dirp) 29149149Sbostic register struct dirstuff *dirp; 29249149Sbostic { 29349149Sbostic register struct direct *dp; 29449149Sbostic register struct iob *io; 29549149Sbostic daddr_t lbn, d; 29649149Sbostic int off; 29749149Sbostic 29849149Sbostic io = dirp->io; 29949149Sbostic for(;;) { 30049149Sbostic if (dirp->loc >= io->i_ino.di_size) 30149149Sbostic return (NULL); 30249149Sbostic off = blkoff(&io->i_fs, dirp->loc); 30349149Sbostic if (off == 0) { 30449149Sbostic lbn = lblkno(&io->i_fs, dirp->loc); 30549149Sbostic d = bmap(io, lbn); 30649149Sbostic if(d == 0) 30749149Sbostic return (NULL); 30849149Sbostic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 30949149Sbostic io->i_ma = io->i_buf; 31049149Sbostic io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn); 31149149Sbostic if (devread(io) < 0) { 31249149Sbostic errno = io->i_error; 31355894Shibler printf("%s: directory read error, bn %ld\n", 31455894Shibler dirp->name, io->i_bn); 31549149Sbostic return (NULL); 31649149Sbostic } 31749149Sbostic } 31849149Sbostic dp = (struct direct *)(io->i_buf + off); 31949149Sbostic dirp->loc += dp->d_reclen; 32055894Shibler if (dp->d_ino == 0) { 32155894Shibler if (dp->d_reclen == 0) { 32255894Shibler printf("%s: bad directory entry, offset %ld\n", 32355894Shibler dirp->name, dirp->loc); 32455894Shibler return (NULL); 32555894Shibler } 32649149Sbostic continue; 32755894Shibler } 32849149Sbostic return (dp); 32949149Sbostic } 33049149Sbostic } 33149149Sbostic 33249149Sbostic static 33349149Sbostic openi(n, io) 33449149Sbostic int n; 33549149Sbostic register struct iob *io; 33649149Sbostic { 33749149Sbostic register struct dinode *dp; 33849149Sbostic int cc; 33949149Sbostic 34049149Sbostic io->i_offset = 0; 34149149Sbostic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 34249149Sbostic io->i_cc = io->i_fs.fs_bsize; 34349149Sbostic io->i_ma = io->i_buf; 34449149Sbostic cc = devread(io); 34549149Sbostic dp = (struct dinode *)io->i_buf; 34649149Sbostic io->i_ino = dp[itoo(&io->i_fs, n)]; 34749149Sbostic return (cc); 34849149Sbostic } 349