1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * AT&T Bell Laboratories 25 * return the real absolute pathname of the preroot dir for cmd 26 * if cmd==0 then current preroot path returned 27 */ 28 29 #include <ast.h> 30 #include <preroot.h> 31 32 #if FS_PREROOT 33 34 #include <ast_dir.h> 35 #include <ls.h> 36 #include <error.h> 37 #include <stdio.h> 38 39 #ifndef ERANGE 40 #define ERANGE E2BIG 41 #endif 42 43 #define ERROR(e) {errno=e;goto error;} 44 45 char* 46 getpreroot(char* path, const char* cmd) 47 { 48 register int c; 49 register FILE* fp; 50 register char* p; 51 char buf[PATH_MAX]; 52 53 if (!path) path = buf; 54 if (cmd) 55 { 56 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); 57 if (!(fp = popen(buf, "rug"))) return(0); 58 for (p = path; (c = getc(fp)) != EOF && c != '\n'; *p++ = c); 59 *p = 0; 60 pclose(fp); 61 if (path == p) return(0); 62 return(path == buf ? strdup(path) : path); 63 } 64 else 65 { 66 char* d; 67 DIR* dirp = 0; 68 int namlen; 69 int euid; 70 int ruid; 71 struct dirent* entry; 72 struct stat* cur; 73 struct stat* par; 74 struct stat* tmp; 75 struct stat curst; 76 struct stat parst; 77 struct stat tstst; 78 char dots[PATH_MAX]; 79 80 cur = &curst; 81 par = &parst; 82 if ((ruid = getuid()) != (euid = geteuid())) setuid(ruid); 83 if (stat(PR_REAL, cur) || stat("/", par) || cur->st_dev == par->st_dev && cur->st_ino == par->st_ino) ERROR(ENOTDIR); 84 85 /* 86 * like getcwd() but starting at the preroot 87 */ 88 89 d = dots; 90 *d++ = '/'; 91 p = path + PATH_MAX - 1; 92 *p = 0; 93 for (;;) 94 { 95 tmp = cur; 96 cur = par; 97 par = tmp; 98 if ((d - dots) > (PATH_MAX - 4)) ERROR(ERANGE); 99 *d++ = '.'; 100 *d++ = '.'; 101 *d = 0; 102 if (!(dirp = opendir(dots))) ERROR(errno); 103 #if !_dir_ok || _mem_dd_fd_DIR 104 if (fstat(dirp->dd_fd, par)) ERROR(errno); 105 #else 106 if (stat(dots, par)) ERROR(errno); 107 #endif 108 *d++ = '/'; 109 if (par->st_dev == cur->st_dev) 110 { 111 if (par->st_ino == cur->st_ino) 112 { 113 closedir(dirp); 114 *--p = '/'; 115 if (ruid != euid) setuid(euid); 116 if (path == buf) return(strdup(p)); 117 if (path != p) 118 { 119 d = path; 120 while (*d++ = *p++); 121 } 122 return(path); 123 } 124 #ifdef D_FILENO 125 while (entry = readdir(dirp)) 126 if (D_FILENO(entry) == cur->st_ino) 127 { 128 namlen = D_NAMLEN(entry); 129 goto found; 130 } 131 #endif 132 133 /* 134 * this fallthrough handles logical naming 135 */ 136 137 rewinddir(dirp); 138 } 139 do 140 { 141 if (!(entry = readdir(dirp))) ERROR(ENOENT); 142 namlen = D_NAMLEN(entry); 143 if ((d - dots) > (PATH_MAX - 1 - namlen)) ERROR(ERANGE); 144 memcpy(d, entry->d_name, namlen + 1); 145 if (stat(dots, &tstst)) ERROR(errno); 146 } while (tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev); 147 found: 148 if (*p) *--p = '/'; 149 if ((p -= namlen) <= (path + 1)) ERROR(ERANGE); 150 memcpy(p, entry->d_name, namlen); 151 closedir(dirp); 152 dirp = 0; 153 } 154 error: 155 if (dirp) closedir(dirp); 156 if (ruid != euid) setuid(euid); 157 } 158 return(0); 159 } 160 161 #else 162 163 NoN(getpreroot) 164 165 #endif 166