149149Sbostic /*-
2*63721Sbostic * Copyright (c) 1982, 1988, 1993
3*63721Sbostic * The Regents of the University of California. All rights reserved.
449149Sbostic *
549149Sbostic * %sccs.include.proprietary.c%
649149Sbostic *
7*63721Sbostic * @(#)open.c 8.1 (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
2763719Smckusick /*
2863719Smckusick * XXX avoid stdio... its a long story.
2963719Smckusick */
3063719Smckusick #define isupper(c) ((c) >= 'A' && (c) <= 'Z')
3163719Smckusick #define tolower(c) ((c) - 'A' + 'a')
3263719Smckusick #define isspace(c) ((c) == ' ' || (c) == '\t')
3363719Smckusick #define isdigit(c) ((c) >= '0' && (c) <= '9')
3463719Smckusick
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
open(str,how)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
getdev(str,len)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
getunit(cp)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 }
21563719Smckusick
21663719Smckusick /*
21763719Smckusick * XXX more stdio-avoidance.
21863719Smckusick */
atoi(cp)21963719Smckusick atoi(cp)
22063719Smckusick char *cp;
22163719Smckusick {
22263719Smckusick int val = 0;
22363719Smckusick
22463719Smckusick while (*cp >= '0' && *cp <= '9')
22563719Smckusick val = val * 10 + (*cp++ - '0');
22663719Smckusick return (val);
22763719Smckusick }
22849149Sbostic #endif /* SMALL */
22949149Sbostic
23049149Sbostic static
find(path,file)23149149Sbostic find(path, file)
23249149Sbostic register char *path;
23349149Sbostic struct iob *file;
23449149Sbostic {
23549149Sbostic register char *q;
23649149Sbostic char *dir, c;
23749149Sbostic int n;
23849149Sbostic
23949149Sbostic if (path == NULL || *path == '\0') {
24049149Sbostic printf("null path\n");
24149149Sbostic return (0);
24249149Sbostic }
24349149Sbostic
24449149Sbostic if (openi((ino_t) ROOTINO, file) < 0) {
24549149Sbostic printf("can't read root inode\n");
24649149Sbostic return (0);
24749149Sbostic }
24849149Sbostic dir = path;
24949149Sbostic while (*path) {
25049149Sbostic while (*path == '/')
25149149Sbostic path++;
25249149Sbostic q = path;
25349149Sbostic while(*q != '/' && *q != '\0')
25449149Sbostic q++;
25549149Sbostic c = *q;
25649149Sbostic *q = '\0';
25749149Sbostic if (q == path) path = "." ; /* "/" means "/." */
25849149Sbostic
25949149Sbostic if ((n = dlook(path, file, dir)) != 0) {
26049149Sbostic if (c == '\0')
26149149Sbostic break;
26249149Sbostic if (openi(n, file) < 0)
26349149Sbostic return (0);
26449149Sbostic *q = c;
26549149Sbostic path = q;
26649149Sbostic continue;
26749149Sbostic } else {
26849149Sbostic printf("%s: not found\n", path);
26949149Sbostic return (0);
27049149Sbostic }
27149149Sbostic }
27249149Sbostic return (n);
27349149Sbostic }
27449149Sbostic
27549149Sbostic static ino_t
dlook(s,io,dir)27649149Sbostic dlook(s, io, dir)
27749149Sbostic char *s;
27849149Sbostic register struct iob *io;
27949149Sbostic char *dir;
28049149Sbostic {
28149149Sbostic register struct direct *dp;
28249149Sbostic register struct dinode *ip;
28349149Sbostic struct dirstuff dirp;
28449149Sbostic int len;
28549149Sbostic
28649149Sbostic if (s == NULL || *s == '\0')
28749149Sbostic return (0);
28849149Sbostic ip = &io->i_ino;
28949149Sbostic if ((ip->di_mode&IFMT) != IFDIR) {
29049149Sbostic printf("%s: not a directory\n", dir);
29149149Sbostic return (0);
29249149Sbostic }
29349149Sbostic if (ip->di_size == 0) {
29449149Sbostic printf("%s: zero length directory\n", dir);
29549149Sbostic return (0);
29649149Sbostic }
29749149Sbostic len = strlen(s);
29849149Sbostic dirp.loc = 0;
29949149Sbostic dirp.io = io;
30055894Shibler dirp.name = dir;
30149149Sbostic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
30249149Sbostic if(dp->d_ino == 0)
30349149Sbostic continue;
30449149Sbostic if (dp->d_namlen == len && !strcmp(s, dp->d_name))
30549149Sbostic return (dp->d_ino);
30649149Sbostic }
30749149Sbostic return (0);
30849149Sbostic }
30949149Sbostic
31049149Sbostic static struct direct *
readdir(dirp)31149149Sbostic readdir(dirp)
31249149Sbostic register struct dirstuff *dirp;
31349149Sbostic {
31449149Sbostic register struct direct *dp;
31549149Sbostic register struct iob *io;
31649149Sbostic daddr_t lbn, d;
31749149Sbostic int off;
31849149Sbostic
31949149Sbostic io = dirp->io;
32049149Sbostic for(;;) {
32149149Sbostic if (dirp->loc >= io->i_ino.di_size)
32249149Sbostic return (NULL);
32349149Sbostic off = blkoff(&io->i_fs, dirp->loc);
32449149Sbostic if (off == 0) {
32549149Sbostic lbn = lblkno(&io->i_fs, dirp->loc);
32649149Sbostic d = bmap(io, lbn);
32749149Sbostic if(d == 0)
32849149Sbostic return (NULL);
32949149Sbostic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
33049149Sbostic io->i_ma = io->i_buf;
33149149Sbostic io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
33249149Sbostic if (devread(io) < 0) {
33349149Sbostic errno = io->i_error;
33455894Shibler printf("%s: directory read error, bn %ld\n",
33555894Shibler dirp->name, io->i_bn);
33649149Sbostic return (NULL);
33749149Sbostic }
33849149Sbostic }
33949149Sbostic dp = (struct direct *)(io->i_buf + off);
34049149Sbostic dirp->loc += dp->d_reclen;
34155894Shibler if (dp->d_ino == 0) {
34255894Shibler if (dp->d_reclen == 0) {
34355894Shibler printf("%s: bad directory entry, offset %ld\n",
34455894Shibler dirp->name, dirp->loc);
34555894Shibler return (NULL);
34655894Shibler }
34749149Sbostic continue;
34855894Shibler }
34949149Sbostic return (dp);
35049149Sbostic }
35149149Sbostic }
35249149Sbostic
35349149Sbostic static
openi(n,io)35449149Sbostic openi(n, io)
35549149Sbostic int n;
35649149Sbostic register struct iob *io;
35749149Sbostic {
35849149Sbostic register struct dinode *dp;
35949149Sbostic int cc;
36049149Sbostic
36149149Sbostic io->i_offset = 0;
36249149Sbostic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
36349149Sbostic io->i_cc = io->i_fs.fs_bsize;
36449149Sbostic io->i_ma = io->i_buf;
36549149Sbostic cc = devread(io);
36649149Sbostic dp = (struct dinode *)io->i_buf;
36749149Sbostic io->i_ino = dp[itoo(&io->i_fs, n)];
36849149Sbostic return (cc);
36949149Sbostic }
370