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