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