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