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