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