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.7 (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 static 220 atoi(cp) 221 char *cp; 222 { 223 int val = 0; 224 225 while (*cp >= '0' && *cp <= '9') 226 val = val * 10 + (*cp++ - '0'); 227 return (val); 228 } 229 #endif /* SMALL */ 230 231 static 232 find(path, file) 233 register char *path; 234 struct iob *file; 235 { 236 register char *q; 237 char *dir, c; 238 int n; 239 240 if (path == NULL || *path == '\0') { 241 printf("null path\n"); 242 return (0); 243 } 244 245 if (openi((ino_t) ROOTINO, file) < 0) { 246 printf("can't read root inode\n"); 247 return (0); 248 } 249 dir = path; 250 while (*path) { 251 while (*path == '/') 252 path++; 253 q = path; 254 while(*q != '/' && *q != '\0') 255 q++; 256 c = *q; 257 *q = '\0'; 258 if (q == path) path = "." ; /* "/" means "/." */ 259 260 if ((n = dlook(path, file, dir)) != 0) { 261 if (c == '\0') 262 break; 263 if (openi(n, file) < 0) 264 return (0); 265 *q = c; 266 path = q; 267 continue; 268 } else { 269 printf("%s: not found\n", path); 270 return (0); 271 } 272 } 273 return (n); 274 } 275 276 static ino_t 277 dlook(s, io, dir) 278 char *s; 279 register struct iob *io; 280 char *dir; 281 { 282 register struct direct *dp; 283 register struct dinode *ip; 284 struct dirstuff dirp; 285 int len; 286 287 if (s == NULL || *s == '\0') 288 return (0); 289 ip = &io->i_ino; 290 if ((ip->di_mode&IFMT) != IFDIR) { 291 printf("%s: not a directory\n", dir); 292 return (0); 293 } 294 if (ip->di_size == 0) { 295 printf("%s: zero length directory\n", dir); 296 return (0); 297 } 298 len = strlen(s); 299 dirp.loc = 0; 300 dirp.io = io; 301 dirp.name = dir; 302 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 303 if(dp->d_ino == 0) 304 continue; 305 if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 306 return (dp->d_ino); 307 } 308 return (0); 309 } 310 311 static struct direct * 312 readdir(dirp) 313 register struct dirstuff *dirp; 314 { 315 register struct direct *dp; 316 register struct iob *io; 317 daddr_t lbn, d; 318 int off; 319 320 io = dirp->io; 321 for(;;) { 322 if (dirp->loc >= io->i_ino.di_size) 323 return (NULL); 324 off = blkoff(&io->i_fs, dirp->loc); 325 if (off == 0) { 326 lbn = lblkno(&io->i_fs, dirp->loc); 327 d = bmap(io, lbn); 328 if(d == 0) 329 return (NULL); 330 io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 331 io->i_ma = io->i_buf; 332 io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn); 333 if (devread(io) < 0) { 334 errno = io->i_error; 335 printf("%s: directory read error, bn %ld\n", 336 dirp->name, io->i_bn); 337 return (NULL); 338 } 339 } 340 dp = (struct direct *)(io->i_buf + off); 341 dirp->loc += dp->d_reclen; 342 if (dp->d_ino == 0) { 343 if (dp->d_reclen == 0) { 344 printf("%s: bad directory entry, offset %ld\n", 345 dirp->name, dirp->loc); 346 return (NULL); 347 } 348 continue; 349 } 350 return (dp); 351 } 352 } 353 354 static 355 openi(n, io) 356 int n; 357 register struct iob *io; 358 { 359 register struct dinode *dp; 360 int cc; 361 362 io->i_offset = 0; 363 io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 364 io->i_cc = io->i_fs.fs_bsize; 365 io->i_ma = io->i_buf; 366 cc = devread(io); 367 dp = (struct dinode *)io->i_buf; 368 io->i_ino = dp[itoo(&io->i_fs, n)]; 369 return (cc); 370 } 371