int VAttachPartitions(void) { int errors = 0; int nmounts; struct vmount *vmountp; if ((nmounts = getmount(&vmountp)) <= 0) { Log("Problems in getting # of mount entries(getmount)\n"); exit(-1); } for (; nmounts; nmounts--, vmountp = (struct vmount *)((int)vmountp + vmountp->vmt_length)) { char *part = vmt2dataptr(vmountp, VMT_STUB); if (vmountp->vmt_flags & (MNT_READONLY | MNT_REMOVABLE | MNT_REMOTE)) continue; /* Ignore any "special" partitions */ #ifdef AFS_AIX42_ENV #ifndef AFS_NAMEI_ENV { struct superblock fs; /* The Log statements are non-sequiters in the SalvageLog and don't * even appear in the VolserLog, so restrict them to the FileLog. */ if (ReadSuper(&fs, vmt2dataptr(vmountp, VMT_OBJECT)) < 0) { if (programType == fileServer) Log("Can't read superblock for %s, ignoring it.\n", part); continue; } if (IsBigFilesFileSystem(&fs)) { if (programType == fileServer) Log("%s is a big files filesystem, ignoring it.\n", part); continue; } } #endif #endif /* Skip this Partition? */ if (VIsNeverAttach(part)) continue; /* If we're going to always attach this partition, do it later. */ if (VIsAlwaysAttach(part, NULL)) continue; if (VCheckPartition(part, vmt2dataptr(vmountp, VMT_OBJECT), 0) < 0) errors++; } /* Process the always-attach partitions, if any. */ VAttachPartitions2(); return errors; }
static #endif char* pathreal(const char* apath, register int type, struct stat* st) { char* path = (char*)apath; register char* sp; register char* cp; register char* ip; Table_t* safe; int oerrno = errno; int opaqued = 0; int len; int vir; int safesize; int safe_dir; long visits; char buf[PATH_MAX + 1]; static struct stat stbuf; static struct stat tsbuf; state.path.level = state.path.synthesize = state.path.nlinks = 0; if (!path) { errno = EFAULT; return 0; } initialize(); if (state.in_2d) { if (!st || (!state.level || *path == '/') && !LSTAT(path, st)) return path; if (state.level && streq(path, ".") && !CHDIR(state.pwd)) { state.level = 0; return path; } return 0; } #if FS if (mounted() && (sp = fsreal(state.path.monitor, MSG_stat, state.path.mount))) apath = (char*)(path = sp); #endif /* * handle null path, . and / separately */ if (safe = state.safe ? &state.vsafe : (Table_t*)0) { type |= P_ABSOLUTE; if (!(safesize = state.safe->servicesize)) safesize = strlen(state.safe->service); } else type &= ~P_SAFE; again: if (!*path) { errno = ENOENT; return 0; } cp = sp = path; state.path.synthesize = state.path.linksize = 0; if (!st) st = &stbuf; /* * check if virtual dir has been created by another process * only P_PATHONLY|P_TOP calls (usually create or modify link) and * references to "." are checked for performance */ if (state.level > 0 && state.pwd && ((type & (P_PATHONLY|P_TOP)) && *sp != '/' || *sp == '.' && sp[1] == 0)) { if (!CHDIR(state.pwd)) state.level = 0; else if (!(type & (P_PATHONLY|P_TOP))) { len = 0; state.path.level += (state.path.synthesize = state.level); sp = strcpy(state.path.name, state.pwd); goto skip; } } if (!state.pwd || sp[1] == 0 && (*sp == '.' || *sp == '/' && !safe)) { if (st != &stbuf && LSTAT(sp, st)) return 0; if (*sp == '/' || !state.pwd && (type & P_PATHONLY)) strncpy(state.path.name, sp, PATH_MAX); else if (!state.pwd) { /* * treat the current directory as if were empty */ errno = ENOENT; return 0; } else strncpy(state.path.name, state.pwd, PATH_MAX); errno = oerrno; return state.path.name; } /* * put absolute pathname into state.path */ safe_dir = 0; if (*path != '/') { strcpy(state.path.name, state.pwd); sp = state.path.name + state.pwdsize; *sp++ = '/'; if (safe && state.pwdsize >= safesize && !strncmp(state.pwd, state.safe->service, safesize) && (!state.pwd[safesize] || state.pwd[safesize] == '/')) safe_dir = safesize; } else sp = state.path.name; ip = state.path.name + elementsof(state.path.name); while (sp < ip && (*sp = *cp++)) sp++; if (type & P_DOTDOT) strcpy(sp, "/.."); sp = state.path.name; if (!(ip = pathcanon(sp + safe_dir, sizeof(state.path.name) - safe_dir, 0))) { errno = ENOENT; return 0; } if (type & (P_DOTDOT|P_NOSLASH)) { /* * remove trailing slashes */ while (*--ip == '/'); *++ip = 0; } else if ((type & P_SLASH) && *(ip - 1) != '/') *ip++ = '/'; if (*(ip - 1) == '/' && ip - sp > 1) { /* * trailing slash is equivalent to trailing slash-dot * this forces the common-sense interpretation */ #if DEBUG if (!(state.test & 010)) #endif *ip++ = '.'; *ip = 0; } len = ip - sp; /* * try to use relative path */ if (!(type & (P_LSTAT|P_READLINK))) { for (ip = state.pwd; *ip && *ip == *sp++; ip++); if (*ip != 0 || *sp && *sp != '/' || state.level < 0) sp = state.path.name; else { state.path.level += (state.path.synthesize = state.level); if (state.level && !(type & P_PATHONLY) && st == &stbuf) { sp = state.path.name; len -= state.pwdsize; } else if (type & P_ABSOLUTE) sp = state.path.name; else if (*sp == '/') sp++; } if (*sp == 0) sp = state.dot; } skip: if ((type & P_NOOPAQUE) && !LSTAT(sp, st) && checkopaque(sp, st)) { message((-1, "%s: remove opaque", sp)); UNLINK(sp); opaqued = 1; } if (safe && *sp == '/') { state.path.table = safe; cp = pathnext(sp, NiL, NiL); state.path.table = safe = 0; if (cp) { state.path.level = 0; path = strcpy(buf, sp); message((-5, "pathreal: == safe map %s", path)); type &= ~(P_DOTDOT|P_SAFE); goto again; } if (!*(sp + 1)) { strncpy(sp, state.safe->service, safesize); sp[safesize] = 0; } else if (strncmp(sp, state.safe->service, safesize) || sp[safesize] && sp[safesize] != '/') { if (*path != '/' && safe_dir) { errno = EPERM; return 0; } if (sp[1]) strcpy(buf, sp); else *buf = 0; len = sfsprintf(sp, sizeof(state.path.name), "%-*s%s", safesize, state.safe->service, buf); message((-5, "pathreal: == safe next %s", sp)); if (!pathnext(sp, NiL, NiL)) { errno = EPERM; return 0; } } else type &= ~P_SAFE; } if ((type & P_SAFE) && state.path.level) { errno = EPERM; return 0; } if (type & P_PATHONLY) { errno = oerrno; return sp; } visits = 0; vir = 1; while (LSTAT(sp, st)) { if (vir) { if (apath[0] == '.' && apath[1] == '.' && apath[2] == '.' && !apath[3]) { if (state.level > 0) { message((-1, "pathreal: %s => %s", apath, sp)); LSTAT(".", st); return sp; } errno = ENOENT; return 0; } vir = 0; } if (errno == ENOTDIR) { /* * check for version instance */ cp = ip = sp + strlen(sp); while (ip > sp && *--ip != '/'); if (ip < sp) return 0; while (ip > sp && *--ip == '/'); if (ip < sp) return 0; while (ip > sp && *--ip != '/'); if (*ip == '/') ip++; while (cp >= ip) { cp[4] = *cp; cp--; } memcpy(ip, state.opaque, 4); if (!LSTAT(sp, st)) break; errno = ENOTDIR; return 0; } if (errno != ENOENT || opaqued) return 0; #if FS /* * check user mount */ if (visits) { Mount_t* mp; const char* up; if ((mp = getmount(sp, &up)) && (mp->fs->flags & FS_NAME) && (sp = fsreal(mp, MSG_open, (char*)up)) && !LSTAT(sp, st)) break; } #endif /* * search down the viewpath */ if (type & P_SAFE) { errno = EPERM; return 0; } if (!pathnext(state.path.name, NiL, &visits)) return 0; sp = state.path.name; if (!(type & P_ABSOLUTE)) { /* * try to use relative path */ for (ip = state.pwd; *ip && *ip == *sp++; ip++); if (*ip == 0 && *sp == '/') sp++; else sp = state.path.name; } if (*sp == 0) sp = state.dot; } if (st->st_nlink > 1 && checkopaque(sp, st)) return 0; if ((type & P_TOP) && state.path.level) { int rfd; int wfd; if ((rfd = OPEN(sp, O_RDONLY, 0)) < 0) sp = 0; else { tsbuf = *st; wfd = open(apath, O_WRONLY|O_CREAT|O_TRUNC|O_cloexec, st->st_mode & S_IPERM); *st = tsbuf; if (wfd < 0) sp = 0; else { if (fs3d_copy(rfd, wfd, st)) sp = 0; CLOSE(wfd); } CLOSE(rfd); } if (!sp) { errno = EROFS; return 0; } if (st == &stbuf) st = 0; return pathreal(apath, P_PATHONLY, st); } IVIEW(st, state.path.level); if (state.path.synthesize) { if (state.path.level < state.level) { if (len) { ip = state.path.name + strlen(state.path.name) - len; len = *ip; *ip = 0; } if (!CHDIR(state.path.name)) state.level = state.path.level; message((-1, "chdir=%s level=%d", state.path.name, state.level)); *ip = len; } else if (S_ISDIR(st->st_mode)) { int mask; static int uid = -1; static int gid; umask(mask = umask(0)); st->st_mode = (st->st_mode | (S_IRWXU|S_IRWXG|S_IRWXO)) & ~(mask & (S_IRWXU|S_IRWXG|S_IRWXO)); if (uid == -1) { uid = geteuid(); gid = getegid(); } st->st_uid = uid; st->st_gid = gid; } } ip = sp; /* * symbolic links handled specially * get filename from pathname */ if (S_ISLNK(st->st_mode) && (len = checklink(sp, st, type)) > 1 && !(type & (P_LSTAT|P_READLINK)) && state.path.nlinks++ < MAXSYMLINKS) { path = strcpy(buf, state.path.name); message((-1, "pathreal: == again %s", path)); if (*path != '/') state.path.level = 0; type &= ~(P_DOTDOT|P_SAFE); goto again; } #if VCS && defined(VCS_REAL) VCS_REAL(state.path.name, st); #endif errno = oerrno; return sp; }
/* ensure that we don't have a "/" instead of a "/dev/rxd0a" type of device. * returns pointer to static storage; copy it out quickly! */ char * vol_DevName(dev_t adev, char *wpath) { static char pbuffer[128]; char pbuf[128], *ptr; #ifdef AFS_SUN5_ENV struct mnttab mnt; FILE *mntfile; #else #if defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX22_ENV) struct mntent *mntent; FILE *mfd; #else struct fstab *fsent; #endif #endif #ifdef AFS_AIX_ENV int nmounts; struct vmount *vmountp; #endif #ifdef AFS_AIX_ENV if ((nmounts = getmount(&vmountp)) <= 0) { return NULL; } for (; nmounts; nmounts--, vmountp = (struct vmount *)((int)vmountp + vmountp->vmt_length)) { char *part = vmt2dataptr(vmountp, VMT_STUB); #else #ifdef AFS_SUN5_ENV if (!(mntfile = fopen(MNTTAB, "r"))) { return NULL; } while (!getmntent(mntfile, &mnt)) { char *part = mnt.mnt_mountp; #else #if defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX22_ENV) #ifdef AFS_LINUX22_ENV if ((mfd = setmntent("/proc/mounts", "r")) == NULL) { if ((mfd = setmntent("/etc/mtab", "r")) == NULL) { return NULL; } } #else if ((mfd = setmntent(MOUNTED /*MNTTAB*/, "r")) == NULL) { return NULL; } #endif while ((mntent = getmntent(mfd))) { char *part = mntent->mnt_dir; #else setfsent(); while ((fsent = getfsent())) { char *part = fsent->fs_file; #endif #endif /* AFS_SGI_ENV */ #endif struct stat status; #ifdef AFS_AIX_ENV if (vmountp->vmt_flags & (MNT_READONLY | MNT_REMOVABLE | MNT_REMOTE)) continue; /* Ignore any "special" partitions */ #else #ifdef AFS_SUN5_ENV /* Ignore non ufs or non read/write partitions */ if ((strcmp(mnt.mnt_fstype, "ufs") != 0) || (strncmp(mnt.mnt_mntopts, "ro,ignore", 9) == 0)) continue; #else #if defined(AFS_LINUX22_ENV) if (strcmp(mntent->mnt_type, "ext2")) continue; #else #if defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV) if (!hasmntopt(mntent, MNTOPT_RW)) continue; #else if (strcmp(fsent->fs_type, "rw") != 0) continue; /* Ignore non read/write partitions */ #endif /* AFS_LINUX22_ENV */ #endif /* AFS_SGI_ENV */ #endif #endif /* Only keep track of "/vicepx" partitions since it can get hairy when NFS mounts are involved.. */ if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE)) { continue; /* Non /vicepx; ignore */ } if (stat(part, &status) == -1) { continue; } #if !defined(AFS_SGI_XFS_IOPS_ENV) && !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) if ((status.st_ino != ROOTINO) /*|| ((status.st_mode & S_IFMT) != S_IFBLK) */ ) { continue; } #endif if (status.st_dev == adev) { #ifdef AFS_AIX_ENV strcpy(pbuffer, vmt2dataptr(vmountp, VMT_OBJECT)); #else #ifdef AFS_SUN5_ENV strcpy(pbuffer, mnt.mnt_special); #else #if defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX22_ENV) strcpy(pbuffer, mntent->mnt_fsname); #else strcpy(pbuffer, fsent->fs_spec); #endif #endif /* AFS_SGI_ENV */ #endif if (wpath) { strcpy(pbuf, pbuffer); ptr = (char *)strrchr(pbuf, OS_DIRSEPC); if (ptr) { *ptr = '\0'; strcpy(wpath, pbuf); } else return NULL; } ptr = (char *)strrchr(pbuffer, OS_DIRSEPC); if (ptr) { strcpy(pbuffer, ptr + 1); return pbuffer; } else return NULL; } } #ifdef AFS_SUN5_ENV (void)fclose(mntfile); #else #if defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX22_ENV) endmntent(mfd); #else #ifndef AFS_AIX_ENV endfsent(); #endif #endif #endif /* AFS_SGI_ENV */ return NULL; } /* Search for the raw device name. Will put an "r" in front of each * directory and file entry of the pathname until we find a character * device. */ char * afs_rawname(char *devfile) { static char rawname[100]; struct stat statbuf; int code, i; i = strlen(devfile); while (i >= 0) { strcpy(rawname, devfile); if (devfile[i] == OS_DIRSEPC) { rawname[i + 1] = 'r'; rawname[i + 2] = 0; strcat(rawname, &devfile[i + 1]); } code = stat(rawname, &statbuf); if (!code && S_ISCHR(statbuf.st_mode)) return rawname; while ((--i >= 0) && (devfile[i] != OS_DIRSEPC)); } return NULL; }