static char* gl_dirnext(glob_t* gp, void* handle) { struct dirent* dp; while (dp = (struct dirent*)(*gp->gl_readdir)(handle)) #ifdef D_FILENO if (D_FILENO(dp)) #endif { #ifdef D_TYPE if (D_TYPE(dp) != DT_UNKNOWN && D_TYPE(dp) != DT_DIR && D_TYPE(dp) != DT_LNK) gp->gl_status |= GLOB_NOTDIR; #endif return dp->d_name; } return 0; }
char* getpreroot(char* path, const char* cmd) { register int c; register FILE* fp; register char* p; char buf[PATH_MAX]; if (!path) path = buf; if (cmd) { sfsprintf(buf, sizeof(buf), "set x `%s= %s - </dev/null 2>&1`\nwhile :\ndo\nshift\ncase $# in\n[012]) break ;;\nesac\ncase \"$1 $2\" in\n\"+ %s\") echo $3; exit ;;\nesac\ndone\necho\n", PR_SILENT, cmd, PR_COMMAND); if (!(fp = popen(buf, "rug"))) return(0); for (p = path; (c = getc(fp)) != EOF && c != '\n'; *p++ = c); *p = 0; pclose(fp); if (path == p) return(0); return(path == buf ? strdup(path) : path); } else { char* d; DIR* dirp = 0; int namlen; int euid; int ruid; struct dirent* entry; struct stat* cur; struct stat* par; struct stat* tmp; struct stat curst; struct stat parst; struct stat tstst; char dots[PATH_MAX]; cur = &curst; par = &parst; if ((ruid = getuid()) != (euid = geteuid())) setuid(ruid); if (stat(PR_REAL, cur) || stat("/", par) || cur->st_dev == par->st_dev && cur->st_ino == par->st_ino) ERROR(ENOTDIR); /* * like getcwd() but starting at the preroot */ d = dots; *d++ = '/'; p = path + PATH_MAX - 1; *p = 0; for (;;) { tmp = cur; cur = par; par = tmp; if ((d - dots) > (PATH_MAX - 4)) ERROR(ERANGE); *d++ = '.'; *d++ = '.'; *d = 0; if (!(dirp = opendir(dots))) ERROR(errno); #if !_dir_ok || _mem_dd_fd_DIR if (fstat(dirp->dd_fd, par)) ERROR(errno); #else if (stat(dots, par)) ERROR(errno); #endif *d++ = '/'; if (par->st_dev == cur->st_dev) { if (par->st_ino == cur->st_ino) { closedir(dirp); *--p = '/'; if (ruid != euid) setuid(euid); if (path == buf) return(strdup(p)); if (path != p) { d = path; while (*d++ = *p++); } return(path); } #ifdef D_FILENO while (entry = readdir(dirp)) if (D_FILENO(entry) == cur->st_ino) { namlen = D_NAMLEN(entry); goto found; } #endif /* * this fallthrough handles logical naming */ rewinddir(dirp); } do { if (!(entry = readdir(dirp))) ERROR(ENOENT); namlen = D_NAMLEN(entry); if ((d - dots) > (PATH_MAX - 1 - namlen)) ERROR(ERANGE); memcpy(d, entry->d_name, namlen + 1); if (stat(dots, &tstst)) ERROR(errno); } while (tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev); found: if (*p) *--p = '/'; if ((p -= namlen) <= (path + 1)) ERROR(ERANGE); memcpy(p, entry->d_name, namlen); closedir(dirp); dirp = 0; } error: if (dirp) closedir(dirp); if (ruid != euid) setuid(euid); } return(0); }
ssize_t msgsend(int fd, register Msg_call_t* msg, unsigned long call, long ret, int err, void* data) { register struct stat* sp; register struct dirent* dp; register struct dirent* de; register struct statvfs* vp; int i; char* b; char* e; if (call & MSG_ACK) { if ((fd = csbind(&cs, "udp", msg->ack.addr, msg->ack.port, 0L)) < 0) return -1; ret = ret == -1 ? ~msg->stamp : msg->stamp; err = 0; data = 0; } b = msg->data + MSG_SIZE_SIZE; e = msg->data + sizeof(msg->data); msgputu(&b, e, call); msgputu(&b, e, ret); if (ret == -1) msgputu(&b, e, err); else if (data) switch (MSG_CALL(call)) { case MSG_getdents: dp = (struct dirent*)data; de = (struct dirent*)((char*)dp + ret); while (dp < de) { i = D_NAMLEN(dp); msgputz(&b, e, dp->d_name, i + 1); msgputu(&b, e, D_FILENO(dp)); #if _mem_d_reclen_dirent i = dp->d_reclen; #else i = D_RECSIZ(dp, i); #endif dp = (struct dirent*)((char*)dp + i); } msgputu(&b, e, 0); break; case MSG_stat: sp = (struct stat*)data; msgputu(&b, e, sp->st_dev); msgputu(&b, e, sp->st_ino); msgputu(&b, e, sp->st_mode); msgputu(&b, e, sp->st_nlink); msgputu(&b, e, sp->st_uid); msgputu(&b, e, sp->st_gid); msgputu(&b, e, sp->st_size); msgputu(&b, e, sp->st_atime); msgputu(&b, e, sp->st_mtime); msgputu(&b, e, sp->st_ctime); #if _mem_st_blksize_stat msgputu(&b, e, sp->st_blksize); #else msgputu(&b, e, 1024); #endif #if _mem_st_blocks_stat msgputu(&b, e, sp->st_blocks); #else msgputu(&b, e, sp->st_size ? ((sp->st_size - 1) / 1024 + 1) : 0); #endif break; case MSG_statfs: vp = (struct statvfs*)data; msgputu(&b, e, vp->f_bsize); msgputu(&b, e, vp->f_frsize); msgputu(&b, e, vp->f_blocks); msgputu(&b, e, vp->f_bfree); msgputu(&b, e, vp->f_bavail); msgputu(&b, e, vp->f_files); msgputu(&b, e, vp->f_ffree); msgputu(&b, e, vp->f_favail); #if _mem_f_fsid_statvfs msgputu(&b, e, vp->f_fsid); #else msgputu(&b, e, 0); #endif #if _mem_f_basetype_statvfs msgputz(&b, e, vp->f_basetype, strlen(vp->f_basetype) + 1); #else msgputz(&b, e, "ufs", 4); #endif msgputu(&b, e, vp->f_flag); msgputu(&b, e, vp->f_namemax); #if _mem_f_fstr_statvfs msgputz(&b, e, vp->f_fstr, strlen(vp->f_fstr) + 1); #endif break; default: msgputz(&b, e, data, ret); break; } ret = b - msg->data; msgsetsize(msg->data, ret); if (cswrite(&cs, fd, msg->data, ret) != ret) ret = -1; if (call & MSG_ACK) close(fd); return ret; }