static void setupdevs() { int dirno = 0; char **srch_dirs; hashtab = malloc(NDEVS * sizeof (struct devhash)); if (hashtab == NULL) { (void) fprintf(stderr, gettext("No memory for device table\n")); return; } srch_dirs = get_pri_dirs(); while (srch_dirs[dirno] != NULL) { if (srch_dir(srch_dirs[dirno]) < 0) return; dirno++; } dirno = 0; while (srch_dirs[dirno] != NULL) { if (strcmp("/dev", srch_dirs[dirno]) == 0) /* * Don't search /dev twice. */ return; dirno++; } }
static int srch_dir(const entry_t path, /* current path */ int match_mask, /* flags mask */ int depth, /* current depth (/dev = 0) */ const entry_t skip_dirs[], /* directories not needing searching */ struct stat64 *fsb) /* the file being searched for */ { DIR *dirp; struct dirent64 *direntp; struct stat64 tsb; char file_name[MAX_DEV_PATH]; entry_t file; char *last_comp; int found = 0; int dirno = 0; size_t path_len; file.name = file_name; file.flags = path.flags & match_mask; if (file.flags == 0) file.flags = match_mask; /* * do we need to search this directory? (always search /dev at depth 0) */ if ((skip_dirs != NULL) && (depth != 0)) while (skip_dirs[dirno].name != NULL) if (strcmp(skip_dirs[dirno++].name, path.name) == 0) return (0); /* * open directory */ if ((dirp = opendir(path.name)) == NULL) { return (0); } /* * skip two first entries ('.' and '..') */ if (((direntp = readdir64(dirp)) == NULL) || ((direntp = readdir64(dirp)) == NULL)) { (void) closedir(dirp); return (0); } path_len = strlen(path.name); (void) strcpy(file_name, path.name); last_comp = file_name + path_len; *last_comp++ = '/'; /* * read thru the directory */ while ((!found) && ((direntp = readdir64(dirp)) != NULL)) { /* * if the file name (path + "/" + d_name + NULL) would be too * long, skip it */ if ((path_len + strlen(direntp->d_name) + 2) > MAX_DEV_PATH) continue; else (void) strcpy(last_comp, direntp->d_name); if (stat64(file_name, &tsb) < 0) continue; /* * if a file is a directory and we are not too deep, recurse */ if ((tsb.st_mode & S_IFMT) == S_IFDIR) if (depth < MAX_SRCH_DEPTH) found = srch_dir(file, match_mask, depth+1, skip_dirs, fsb); else continue; /* * else if it is not a directory, is it a character special * file? */ else if ((tsb.st_mode & S_IFMT) == S_IFCHR) { int flag = 0; if (tsb.st_dev == fsb->st_dev) flag |= MATCH_FS; if (tsb.st_rdev == fsb->st_rdev) flag |= MATCH_MM; if (tsb.st_ino == fsb->st_ino) flag |= MATCH_INO; if ((flag & file.flags) == file.flags) { (void) strcpy(rbuf, file.name); found = 1; } else if ((flag & (MATCH_MM | MATCH_FS)) == (MATCH_MM | MATCH_FS)) { /* * no (inodes do not match), but save the name * for later */ (void) strcpy(dev_rbuf, file.name); dev_flag = 1; } } } (void) closedir(dirp); return (found); }
static char * _ttyname_common(struct stat64 *fsp, char *buffer, uint_t match_mask) { struct stat64 tfsb; const entry_t *srch_dirs; /* priority directories */ spcl_t *spclp; int i; int found = 0; int dirno = 0; int is_pts = 0; char *retval = NULL; char *pt = NULL; /* * We can't use lmutex_lock() here because we call malloc()/free() * and _libc_gettext(). Use the brute-force fork_lock_enter(). */ (void) fork_lock_enter(NULL); /* * match special cases */ for (spclp = special_case, i = 0; i < NUMSPECIAL; spclp++, i++) { if ((spclp->spcl_inum | spclp->spcl_fsdev | spclp->spcl_rdev) == 0) { if (stat64(spclp->spcl_name, &tfsb) != 0) continue; spclp->spcl_rdev = tfsb.st_rdev; spclp->spcl_fsdev = tfsb.st_dev; spclp->spcl_inum = tfsb.st_ino; } if (match_mask == MATCH_MM) { if (spclp->spcl_rdev == fsp->st_rdev) { retval = strcpy(rbuf, spclp->spcl_name); goto out; } } else if (spclp->spcl_fsdev == fsp->st_dev && spclp->spcl_rdev == fsp->st_rdev && spclp->spcl_inum == fsp->st_ino) { retval = strcpy(rbuf, spclp->spcl_name); goto out; } } /* * additional special case: ptm clone device * ptm devs have no entries in /dev * if major number matches, just short circuit any further lookup * NOTE: the minor number of /dev/ptmx is the ptm major number */ spclp = &ptmspecial; if ((spclp->spcl_inum | spclp->spcl_fsdev | spclp->spcl_rdev) == 0) { if (stat64(spclp->spcl_name, &tfsb) == 0) { spclp->spcl_rdev = tfsb.st_rdev; spclp->spcl_fsdev = tfsb.st_dev; spclp->spcl_inum = tfsb.st_ino; } } if ((spclp->spcl_rdev != 0) && (minor(spclp->spcl_rdev) == major(fsp->st_rdev))) goto out; /* * additional special case: pty dev * one of the known default pairs of /dev/ptyXX or /dev/ttyXX */ if ((retval = ispty(fsp, match_mask)) != NULL) goto out; /* * search the priority directories */ srch_dirs = get_pri_dirs(); dev_flag = 0; while ((!found) && (srch_dirs[dirno].name != NULL)) { /* * if /dev is one of the priority directories, only * search its top level(set depth = MAX_SEARCH_DEPTH) */ /* * Is /dev/pts then just do a quick check. We don't have * to stat the entire /dev/pts dir. */ if (strcmp(PTS, srch_dirs[dirno].name) == NULL) { if ((pt = ispts(fsp, match_mask)) != NULL) { is_pts = 1; found = 1; } } else { found = srch_dir(srch_dirs[dirno], match_mask, ((strcmp(srch_dirs[dirno].name, dev_dir.name) == 0) ? MAX_SRCH_DEPTH : 1), 0, fsp); } dirno++; } /* * search the /dev/ directory, skipping priority directories */ if (!found) found = srch_dir(dev_dir, match_mask, 0, srch_dirs, fsp); /* * return */ if (found) { if (is_pts) retval = pt; else retval = rbuf; } else if (dev_flag) retval = dev_rbuf; else retval = NULL; out: retval = (retval ? strcpy(buffer, retval) : NULL); fork_lock_exit(); return (retval); }
inoptr kn_open(char *namep, inoptr *parent) { staticfast inoptr wd; /* the directory we are currently searching. */ staticfast inoptr ninode; inoptr temp; staticfast char *name; name = namep; #ifdef DEBUG kprintf("kn_open(\"%s\")\n", name); #endif if(*name == '/') wd = udata.u_root; else wd = udata.u_cwd; i_ref(ninode = wd); i_ref(ninode); for(;;) { if(ninode) magic(ninode); /* cheap way to spot rename inside yourself */ if (udata.u_rename == ninode) udata.u_rename = NULLINODE; /* See if we are at a mount point */ if(ninode) ninode = srch_mt(ninode); while(*name == '/') /* Skip(possibly repeated) slashes */ ++name; if(!*name) /* No more components of path? */ break; if(!ninode){ udata.u_error = ENOENT; goto nodir; } i_deref(wd); wd = ninode; if(getmode(wd) != F_DIR){ udata.u_error = ENOTDIR; goto nodir; } if(!(getperm(wd) & OTH_EX)){ udata.u_error = EPERM; goto nodir; } /* See if we are going up through a mount point */ if((wd == udata.u_root || (wd->c_num == ROOTINODE && wd->c_dev != root_dev)) && name[0] == '.' && name[1] == '.' && (name[2] == '/' || name[2] == '\0')){ if (wd == udata.u_root) { ninode = wd; name += 2; continue; } temp = fs_tab_get(wd->c_dev)->m_fs->s_mntpt; ++temp->c_refs; i_deref(wd); wd = temp; } ninode = srch_dir(wd, name); while(*name != '/' && *name) ++name; } if(parent) *parent = wd; else i_deref(wd); if(!(parent || ninode)) udata.u_error = ENOENT; return ninode; nodir: if(parent) *parent = NULLINODE; i_deref(wd); return NULLINODE; }