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