static void dosetattr(const char *filename, int fd, struct jattr *jattr) { if (fd >= 0) { if (jattr->uid != (uid_t)-1 && jattr->gid != (gid_t)-1) fchown(fd, jattr->uid, jattr->gid); else if (jattr->uid != (uid_t)-1) fchown(fd, jattr->uid, -1); else if (jattr->gid != (gid_t)-1) fchown(fd, -1, jattr->gid); if (jattr->modes != (mode_t)-1) fchmod(fd, jattr->modes); if (jattr->fflags != -1) fchflags(fd, jattr->fflags); if (jattr->size != -1) ftruncate(fd, jattr->size); } else { if (jattr->uid != (uid_t)-1 && jattr->gid != (gid_t)-1) lchown(filename, jattr->uid, jattr->gid); else if (jattr->uid != (uid_t)-1) lchown(filename, jattr->uid, -1); else if (jattr->gid != (gid_t)-1) lchown(filename, -1, jattr->gid); if (jattr->modes != (mode_t)-1) lchmod(filename, jattr->modes); if (jattr->fflags != -1) chflags(filename, jattr->fflags); if (jattr->size != -1) truncate(filename, jattr->size); } }
/* * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives * Method: internalCopyAttributesW * Signature: ([C[CZ)Z */ JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalCopyAttributesW (JNIEnv *env, jclass clazz, jcharArray source, jcharArray destination, jboolean copyLastModified) { struct stat info; struct utimbuf ut; int code; char *sourceFile= (char*) getUTF8ByteArray(env, source); char *destinationFile= (char*) getUTF8ByteArray(env, destination); code= stat(sourceFile, &info); if (code != 0) goto fail; code= chmod(destinationFile, info.st_mode); if (code != 0) goto fail; chflags(destinationFile, info.st_flags); // ignore return code if (copyLastModified) { ut.actime= info.st_atime; ut.modtime= info.st_mtime; code= utime(destinationFile, &ut); } fail: free(sourceFile); free(destinationFile); return code == 0; }
static void setfile(const char *name, struct stat *fs) { static struct timeval tv[2]; fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim); TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim); if (utimes(name, tv)) cwarn("utimes: %s", name); /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (chown(name, fs->st_uid, fs->st_gid)) { if (errno != EPERM) cwarn("chown: %s", name); fs->st_mode &= ~(S_ISUID|S_ISGID); } if (chmod(name, fs->st_mode) && errno != EOPNOTSUPP) cwarn("chmod: %s", name); if (chflags(name, fs->st_flags) && errno != EOPNOTSUPP) cwarn("chflags: %s", name); }
/* * Set the mode, owner, and times for all new or changed directories */ void setdirmodes(int flags) { FILE *mf; struct modeinfo node; struct entry *ep; char *cp; const char *tmpdir; vprintf(stdout, "Set directory mode, owner, and times.\n"); if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0') tmpdir = _PATH_TMP; if (command == 'r' || command == 'R') sprintf(modefile, "%s/rstmode%ld", tmpdir, (long)dumpdate); if (modefile[0] == '#') { panic("modefile not defined\n"); fprintf(stderr, "directory mode, owner, and times not set\n"); return; } mf = fopen(modefile, "r"); if (mf == NULL) { fprintf(stderr, "fopen: %s\n", strerror(errno)); fprintf(stderr, "cannot open mode file %s\n", modefile); fprintf(stderr, "directory mode, owner, and times not set\n"); return; } clearerr(mf); for (;;) { fread((char *)&node, 1, sizeof(struct modeinfo), mf); if (feof(mf)) break; ep = lookupino(node.ino); if (command == 'i' || command == 'x') { if (ep == NULL) continue; if ((flags & FORCE) == 0 && ep->e_flags & EXISTED) { ep->e_flags &= ~NEW; continue; } if (node.ino == ROOTINO && reply("set owner/mode for '.'") == FAIL) continue; } if (ep == NULL) { panic("cannot find directory inode %d\n", node.ino); } else { cp = myname(ep); if (!Nflag) { chown(cp, node.uid, node.gid); chmod(cp, node.mode); utimes(cp, node.timep); chflags(cp, node.flags); } ep->e_flags &= ~NEW; } } if (ferror(mf)) panic("error setting directory modes\n"); fclose(mf); }
/* * Set the mode, owner, and times for all new or changed directories */ void setdirmodes(int flags) { FILE *mf; struct modeinfo node; struct entry *ep; char *cp; Vprintf(stdout, "Set directory mode, owner, and times.\n"); if (command == 'r' || command == 'R') (void)snprintf(modefile, sizeof(modefile), "%s/rstmode%d", tmpdir, dumpdate); if (modefile[0] == '#') { panic("modefile not defined\n"); fputs("directory mode, owner, and times not set\n", stderr); return; } mf = fopen(modefile, "r"); if (mf == NULL) { warn("fopen"); fprintf(stderr, "cannot open mode file %s\n", modefile); fprintf(stderr, "directory mode, owner, and times not set\n"); return; } clearerr(mf); for (;;) { (void)fread((char *)&node, 1, sizeof(struct modeinfo), mf); if (feof(mf)) break; ep = lookupino(node.ino); if (command == 'i' || command == 'x') { if (ep == NULL) continue; if ((flags & FORCE) == 0 && ep->e_flags & EXISTED) { ep->e_flags &= ~NEW; continue; } if (node.ino == ROOTINO && reply("set owner/mode for '.'") == FAIL) continue; } if (ep == NULL) { panic("cannot find directory inode %d\n", node.ino); } else { if (!Nflag) { cp = myname(ep); (void)chown(cp, node.uid, node.gid); (void)chmod(cp, node.mode); (void)chflags(cp, node.flags); (void)utimes(cp, node.ctimep); (void)utimes(cp, node.mtimep); } ep->e_flags &= ~NEW; } } if (ferror(mf)) panic("error setting directory modes\n"); (void)fclose(mf); }
/* * Function: setfile * * Purpose: * Set the owner/group/permissions for the "to" file to the information * in the stat structure. If fd is zero, also call set_utimes() to set * the mod/access times. If fd is non-zero, the caller must do a utimes * itself after close(fd). */ int setfile(struct stat *fs, int fd) { int rval; #if HAVE_MEMBER_STRUCT_STAT_ST_FLAGS_SYS_STAT_H int islink; #endif rval = 0; #if HAVE_MEMBER_STRUCT_STAT_ST_FLAGS_SYS_STAT_H islink = S_ISLNK(fs->st_mode); #endif fs->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (fd ? fchown(fd, fs->st_uid, fs->st_gid) : lchown(to.p_path, fs->st_uid, fs->st_gid)) { if (errno != EPERM) { warn("chown: %s", to.p_path); rval = 1; } fs->st_mode &= ~(S_ISUID | S_ISGID); } if (fd ? fchmod(fd, fs->st_mode) : lchmod(to.p_path, fs->st_mode)) { warn("chmod: %s", to.p_path); rval = 1; } #if HAVE_MEMBER_STRUCT_STAT_ST_FLAGS_SYS_STAT_H if (!islink && !Nflag) { unsigned long fflags = fs->st_flags; /* * XXX * NFS doesn't support chflags; ignore errors unless * there's reason to believe we're losing bits. * (Note, this still won't be right if the server * supports flags and we were trying to *remove* flags * on a file that we copied, i.e., that we didn't create.) */ errno = 0; if ((fd ? fchflags(fd, fflags) : chflags(to.p_path, fflags)) == -1) if (errno != EOPNOTSUPP || fs->st_flags != 0) { warn("chflags: %s", to.p_path); rval = 1; } } #endif /* HAVE_MEMBER_STRUCT_STAT_ST_FLAGS_SYS_STAT_H */ /* if fd is non-zero, caller must call set_utimes() after close() */ if (fd == 0 && set_utimes(to.p_path, fs)) rval = 1; return (rval); }
static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flags) { #ifdef HAVE_CHFLAGS return chflags(path, flags); #else errno = ENOSYS; return -1; #endif }
// Clone User, Owner and Mode, and "User Defined" flags if supported void clone(struct stat *source, char *dpath) { err_wrap(chmod(dpath, source->st_mode), "while changing mode" ); err_wrap(chown(dpath, source->st_uid, source->st_gid), "while changing ownership"); // Does this os/fs support "user-defined" flags // via stat->st_flags #if defined(__APPLE__) || defined(FreeBSD) err_wrap(chflags(dpath, source->st_flags), "while changing user-defined flags"); #endif }
/* * set_chflags() * Set 4.4BSD file flags */ void set_chflags(char *fnm, u_int32_t flags) { #if 0 if (chflags(fnm, flags) < 0 && errno != EOPNOTSUPP) syswarn(1, errno, "Cannot set file flags on %s", fnm); #endif return; }
/** * set the stat() data of a file **/ int setfile(const char *path, struct stat *fs) { DBG_IN(); struct utimbuf ut; int rval; rval = 0; fs->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; ut.actime = fs->st_atime; ut.modtime = fs->st_mtime; if (utime(path, &ut)) { usyslog(LOG_WARNING, "utimes: %s", path); rval = 1; } /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (chown(path, fs->st_uid, fs->st_gid)) { if (errno != EPERM) { usyslog(LOG_WARNING, "chown: %s", path); rval = 1; } fs->st_mode &= ~(S_ISTXT | S_ISUID | S_ISGID); } if (chmod(path, fs->st_mode)) { usyslog(LOG_WARNING, "chown: %s", path); rval = 1; } #ifdef HAVE_CHFLAGS /* * XXX * NFS doesn't support chflags; ignore errors unless there's reason * to believe we're losing bits. (Note, this still won't be right * if the server supports flags and we were trying to *remove* flags * on a file that we copied, i.e., that we didn't create.) */ errno = 0; if (chflags(path, fs->st_flags)) { if (errno != EOPNOTSUPP || fs->st_flags != 0) { usyslog(LOG_WARNING, "chflags: %s", path); rval = 1; } return (rval); } #endif return 0; }
int32_t xar_flags_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { #ifdef HAVE_CHFLAGS char *tmp; u_int flags = 0; if( xar_prop_get(f, XAR_FLAG_FORK, NULL) ) return 0; #ifdef UF_NODUMP if( x_getprop(f, "UserNoDump", (char **)&tmp) == 0 ) flags |= UF_NODUMP; #endif #ifdef UF_IMMUTABLE if( x_getprop(f, "UserImmutable", (char **)&tmp) == 0 ) flags |= UF_IMMUTABLE; #endif #ifdef UF_APPEND if( x_getprop(f, "UserAppend", (char **)&tmp) == 0 ) flags |= UF_APPEND; #endif #ifdef UF_OPAQUE if( x_getprop(f, "UserOpaque", (char **)&tmp) == 0 ) flags |= UF_OPAQUE; #endif #ifdef SF_ARCHIVED if( x_getprop(f, "SystemArchived", (char **)&tmp) == 0 ) flags |= SF_ARCHIVED; #endif #ifdef SF_IMMUTABLE if( x_getprop(f, "SystemImmutable", (char **)&tmp) == 0 ) flags |= SF_IMMUTABLE; #endif #ifdef SF_APPEND if( x_getprop(f, "SystemAppend", (char **)&tmp) == 0 ) flags |= SF_APPEND; #endif if( !flags ) return 0; if( chflags(file, flags) != 0 ) { char e[1024]; memset(e, 0, sizeof(e)); snprintf(e, sizeof(e)-1, "chflags: %s", strerror(errno)); xar_err_new(x); xar_err_set_file(x, f); xar_err_set_string(x, e); xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); return -1; } #endif return 0; }
int fsetflags (const char * name, unsigned long flags) { #if HAVE_CHFLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS) unsigned long bsd_flags = 0; #ifdef UF_IMMUTABLE if (flags & EXT2_IMMUTABLE_FL) bsd_flags |= UF_IMMUTABLE; #endif #ifdef UF_APPEND if (flags & EXT2_APPEND_FL) bsd_flags |= UF_APPEND; #endif #ifdef UF_NODUMP if (flags & EXT2_NODUMP_FL) bsd_flags |= UF_NODUMP; #endif return chflags (name, bsd_flags); #else /* !HAVE_CHFLAGS || (APPLE_DARWIN && HAVE_EXT2_IOCTLS) */ #if HAVE_EXT2_IOCTLS int fd, r, f, save_errno = 0; struct stat buf; if (!lstat(name, &buf) && !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { goto notsupp; } #if !APPLE_DARWIN fd = open (name, OPEN_FLAGS); if (fd == -1) return -1; f = (int) flags; r = ioctl (fd, EXT2_IOC_SETFLAGS, &f); if (r == -1) save_errno = errno; close (fd); if (save_errno) errno = save_errno; #else /* APPLE_DARWIN */ f = (int) flags; return syscall(SYS_fsctl, name, EXT2_IOC_SETFLAGS, &f, 0); #endif /* !APPLE_DARWIN */ return r; notsupp: #endif /* HAVE_EXT2_IOCTLS */ #endif errno = EOPNOTSUPP; return -1; }
rm_file(char **argv) #endif { struct stat sb; int df, rval; char *f; df = dflag; /* * Remove a file. POSIX 1003.2 states that, by default, attempting * to remove a directory is an error, so must always stat the file. */ while ((f = *argv++) != NULL) { /* Assume if can't stat the file, can't unlink it. */ if (lstat(f, &sb)) { if (!fflag || errno != ENOENT) { warn("%s", f); eval = 1; } continue; } if (S_ISDIR(sb.st_mode) && !df) { warnx("%s: is a directory", f); eval = 1; continue; } if (!fflag && !check(f, f, &sb)) continue; rval = 0; #ifndef __GNO__ if (!uid && (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE))) rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE)); #endif if (!rval) { if (S_ISDIR(sb.st_mode)) rval = rmdir(f); else { if (Pflag) rm_overwrite(f, &sb); rval = unlink(f); } } if (rval && (!fflag || errno != ENOENT)) { warn("%s", f); eval = 1; } } }
int setfile(struct stat *fs, int fd) { static struct timeval tv[2]; int rval; rval = 0; fs->st_mode &= S_ISTXT | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); if (utimes(to.p_path, tv)) { warn("utimes: %s", to.p_path); rval = 1; } /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (fd ? fchown(fd, fs->st_uid, fs->st_gid) : chown(to.p_path, fs->st_uid, fs->st_gid)) { if (errno != EPERM) { warn("chown: %s", to.p_path); rval = 1; } fs->st_mode &= ~(S_ISTXT | S_ISUID | S_ISGID); } if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) { warn("chmod: %s", to.p_path); rval = 1; } /* * XXX * NFS doesn't support chflags; ignore errors unless there's reason * to believe we're losing bits. (Note, this still won't be right * if the server supports flags and we were trying to *remove* flags * on a file that we copied, i.e., that we didn't create.) */ errno = 0; if (fd ? fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) if (errno != EOPNOTSUPP || fs->st_flags != 0) { warn("chflags: %s", to.p_path); rval = 1; } return (rval); }
int fsetflags (const char * name, unsigned long flags) { struct stat buf; #if HAVE_CHFLAGS unsigned long bsd_flags = 0; #ifdef UF_IMMUTABLE if (flags & EXT2_IMMUTABLE_FL) bsd_flags |= UF_IMMUTABLE; #endif #ifdef UF_APPEND if (flags & EXT2_APPEND_FL) bsd_flags |= UF_APPEND; #endif #ifdef UF_NODUMP if (flags & EXT2_NODUMP_FL) bsd_flags |= UF_NODUMP; #endif return chflags (name, bsd_flags); #else #if HAVE_EXT2_IOCTLS int fd = 0, r, f, save_errno = 0; if (!stat(name, &buf) && !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { close(fd); goto notsupp; } fd = open (name, OPEN_FLAGS); if (fd == -1) return -1; f = (int) flags; r = ioctl (fd, EXT2_IOC_SETFLAGS, &f); if (r == -1) save_errno = errno; close (fd); if (save_errno) errno = save_errno; return r; #endif /* HAVE_EXT2_IOCTLS */ #endif notsupp: errno = EOPNOTSUPP; return -1; }
int setfile(struct stat *fs, int fd) { static struct timeval tv[2]; struct stat ts; int rval, gotstat, islink, fdval; rval = 0; fdval = fd != -1; islink = !fdval && S_ISLNK(fs->st_mode); fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim); TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim); if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) { warn("%sutimes: %s", islink ? "l" : "", to.p_path); rval = 1; } if (fdval ? fstat(fd, &ts) : (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts))) gotstat = 0; else { gotstat = 1; ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; } if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) : chown(to.p_path, fs->st_uid, fs->st_gid))) { if (errno != EPERM) { warn("chown: %s", to.p_path); rval = 1; } fs->st_mode &= ~(S_ISUID | S_ISGID); } if (!gotstat || fs->st_mode != ts.st_mode) if (fdval ? fchmod(fd, fs->st_mode) : (islink ? lchmod(to.p_path, fs->st_mode) : chmod(to.p_path, fs->st_mode))) { warn("chmod: %s", to.p_path); rval = 1; } if (!gotstat || fs->st_flags != ts.st_flags) if (fdval ? fchflags(fd, fs->st_flags) : (islink ? lchflags(to.p_path, fs->st_flags) : chflags(to.p_path, fs->st_flags))) { warn("chflags: %s", to.p_path); rval = 1; } return (rval); }
nsresult nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir) { NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!"); nsresult rv; rv = EnsureDirectoryExists(aDir); if (NS_FAILED(rv)) return rv; rv = EnsureDirectoryExists(aLocalDir); if (NS_FAILED(rv)) return rv; #ifdef XP_MACOSX bool same; if (NS_SUCCEEDED(aDir->Equals(aLocalDir, &same)) && !same) { // Ensure that the cache directory is not indexed by Spotlight // (bug 718910). At least on OS X, the cache directory (under // ~/Library/Caches/) is always the "local" user profile // directory. This is confusing, since *both* user profile // directories are "local" (they both exist under the user's // home directory). But this usage dates back at least as far // as the patch for bug 291033, where "local" seems to mean // "suitable for temporary storage". Don't hide the cache // directory if by some chance it and the "non-local" profile // directory are the same -- there are bad side effects from // hiding a profile directory under /Library/Application Support/ // (see bug 801883). nsAutoCString cacheDir; if (NS_SUCCEEDED(aLocalDir->GetNativePath(cacheDir))) { if (chflags(cacheDir.get(), UF_HIDDEN)) { NS_WARNING("Failed to set Cache directory to HIDDEN."); } } } #endif mProfileDir = aDir; mProfileLocalDir = aLocalDir; return NS_OK; }
static void login_protect(const char *table, char *pattern, int mask, uid_t uid, gid_t gid) { glob_t gl; char *path; unsigned int i; if (glob(pattern, GLOB_NOSORT, NULL, &gl) != 0) return; for (i = 0; i < gl.gl_pathc; i++) { path = gl.gl_pathv[i]; /* clear flags of the device */ if (chflags(path, 0) && errno != ENOENT && errno != EOPNOTSUPP) syslog(LOG_ERR, "%s: chflags(%s): %m", table, path); if (chmod(path, mask) && errno != ENOENT) syslog(LOG_ERR, "%s: chmod(%s): %m", table, path); if (chown(path, uid, gid) && errno != ENOENT) syslog(LOG_ERR, "%s: chown(%s): %m", table, path); } globfree(&gl); }
ATF_TC_BODY(stat_chflags, tc) { struct stat sa, sb; int fd; (void)memset(&sa, 0, sizeof(struct stat)); (void)memset(&sb, 0, sizeof(struct stat)); fd = open(path, O_RDONLY | O_CREAT); ATF_REQUIRE(fd != -1); ATF_REQUIRE(stat(path, &sa) == 0); ATF_REQUIRE(chflags(path, UF_NODUMP) == 0); ATF_REQUIRE(stat(path, &sb) == 0); if (sa.st_flags == sb.st_flags) atf_tc_fail("stat(2) did not detect chflags(2)"); ATF_REQUIRE(close(fd) == 0); ATF_REQUIRE(unlink(path) == 0); }
int fsetflags (const char * name, unsigned long flags) { #if HAVE_CHFLAGS unsigned long bsd_flags = 0; #ifdef UF_IMMUTABLE if (flags & EXT2_IMMUTABLE_FL) bsd_flags |= UF_IMMUTABLE; #endif #ifdef UF_APPEND if (flags & EXT2_APPEND_FL) bsd_flags |= UF_APPEND; #endif #ifdef UF_NODUMP if (flags & EXT2_NODUMP_FL) bsd_flags |= UF_NODUMP; #endif return chflags (name, bsd_flags); #else #if HAVE_EXT2_IOCTLS int fd, r, f; fd = open (name, OPEN_FLAGS); if (fd == -1) return -1; f = (int) flags; r = ioctl (fd, EXT2_IOC_SETFLAGS, &f); close (fd); return r; #else /* ! HAVE_EXT2_IOCTLS */ // extern int errno; errno = EOPNOTSUPP; return -1; #endif /* ! HAVE_EXT2_IOCTLS */ #endif }
int extractfile(char *name) { int flags; uid_t uid; gid_t gid; mode_t mode; int extsize; struct timeval mtimep[2], ctimep[2]; struct entry *ep; char *buf; curfile.name = name; curfile.action = USING; mtimep[0].tv_sec = curfile.atime_sec; mtimep[0].tv_usec = curfile.atime_nsec / 1000; mtimep[1].tv_sec = curfile.mtime_sec; mtimep[1].tv_usec = curfile.mtime_nsec / 1000; ctimep[0].tv_sec = curfile.atime_sec; ctimep[0].tv_usec = curfile.atime_nsec / 1000; ctimep[1].tv_sec = curfile.birthtime_sec; ctimep[1].tv_usec = curfile.birthtime_nsec / 1000; extsize = curfile.extsize; uid = getuid(); if (uid == 0) uid = curfile.uid; gid = curfile.gid; mode = curfile.mode; flags = curfile.file_flags; switch (mode & IFMT) { default: fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); skipfile(); return (FAIL); case IFSOCK: vprintf(stdout, "skipped socket %s\n", name); skipfile(); return (GOOD); case IFDIR: if (mflag) { ep = lookupname(name); if (ep == NULL || ep->e_flags & EXTRACT) panic("unextracted directory %s\n", name); skipfile(); return (GOOD); } vprintf(stdout, "extract file %s\n", name); return (genliteraldir(name, curfile.ino)); case IFLNK: lnkbuf[0] = '\0'; pathlen = 0; buf = setupextattr(extsize); getfile(xtrlnkfile, xtrattr, xtrlnkskip); if (pathlen == 0) { vprintf(stdout, "%s: zero length symbolic link (ignored)\n", name); return (GOOD); } if (linkit(lnkbuf, name, SYMLINK) == GOOD) { if (extsize > 0) set_extattr_link(name, buf, extsize); (void) lchown(name, uid, gid); (void) lchmod(name, mode); (void) lutimes(name, ctimep); (void) lutimes(name, mtimep); (void) lchflags(name, flags); return (GOOD); } return (FAIL); case IFIFO: vprintf(stdout, "extract fifo %s\n", name); if (Nflag) { skipfile(); return (GOOD); } if (uflag) (void) unlink(name); if (mkfifo(name, 0600) < 0) { fprintf(stderr, "%s: cannot create fifo: %s\n", name, strerror(errno)); skipfile(); return (FAIL); } if (extsize == 0) { skipfile(); } else { buf = setupextattr(extsize); getfile(xtrnull, xtrattr, xtrnull); set_extattr_file(name, buf, extsize); } (void) chown(name, uid, gid); (void) chmod(name, mode); (void) utimes(name, ctimep); (void) utimes(name, mtimep); (void) chflags(name, flags); return (GOOD); case IFCHR: case IFBLK: vprintf(stdout, "extract special file %s\n", name); if (Nflag) { skipfile(); return (GOOD); } if (uflag) (void) unlink(name); if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600, (int)curfile.rdev) < 0) { fprintf(stderr, "%s: cannot create special file: %s\n", name, strerror(errno)); skipfile(); return (FAIL); } if (extsize == 0) { skipfile(); } else { buf = setupextattr(extsize); getfile(xtrnull, xtrattr, xtrnull); set_extattr_file(name, buf, extsize); } (void) chown(name, uid, gid); (void) chmod(name, mode); (void) utimes(name, ctimep); (void) utimes(name, mtimep); (void) chflags(name, flags); return (GOOD); case IFREG: vprintf(stdout, "extract file %s\n", name); if (Nflag) { skipfile(); return (GOOD); } if (uflag) (void) unlink(name); if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { fprintf(stderr, "%s: cannot create file: %s\n", name, strerror(errno)); skipfile(); return (FAIL); } buf = setupextattr(extsize); getfile(xtrfile, xtrattr, xtrskip); if (extsize > 0) set_extattr_fd(ofile, name, buf, extsize); (void) fchown(ofile, uid, gid); (void) fchmod(ofile, mode); (void) futimes(ofile, ctimep); (void) futimes(ofile, mtimep); (void) fchflags(ofile, flags); (void) close(ofile); return (GOOD); } /* NOTREACHED */ }
int attribs_set(struct asfd *asfd, const char *path, struct stat *statp, uint64_t winattr, struct conf *conf) { struct utimbuf ut; ut.actime=statp->st_atime; ut.modtime=statp->st_mtime; #ifdef HAVE_WIN32 win32_chmod(path, statp->st_mode, winattr); set_file_times(asfd, path, &ut, statp, conf); return 0; #endif /* ***FIXME**** optimize -- don't do if already correct */ /* * For link, change owner of link using lchown, but don't * try to do a chmod as that will update the file behind it. */ /* Watch out, a metadata restore will have cmd set to CMD_METADATA or CMD_ENC_META, but that is OK at the moment because we are not doing meta stuff on links. */ if(S_ISLNK(statp->st_mode)) { // Change owner of link, not of real file. if(lchown(path, statp->st_uid, statp->st_gid)<0) { berrno be; berrno_init(&be); logw(asfd, conf, "Unable to set file owner %s: ERR=%s", path, berrno_bstrerror(&be, errno)); return -1; } } else { if(chown(path, statp->st_uid, statp->st_gid)<0) { berrno be; berrno_init(&be); logw(asfd, conf, "Unable to set file owner %s: ERR=%s", path, berrno_bstrerror(&be, errno)); return -1; } if(chmod(path, statp->st_mode) < 0) { berrno be; berrno_init(&be); logw(asfd, conf, "Unable to set file modes %s: ERR=%s", path, berrno_bstrerror(&be, errno)); return -1; } if(set_file_times(asfd, path, &ut, statp, conf)) return -1; #ifdef HAVE_CHFLAGS /* * FreeBSD user flags * * Note, this should really be done before the utime() above, * but if the immutable bit is set, it will make the utimes() * fail. */ if(chflags(path, statp->st_flags)<0) { berrno be; berrno_init(&be); logw(conf, "Unable to set file flags %s: ERR=%s", path, berrno_bstrerror(&be, errno)); return -1; } #endif } return 0; }
static unsigned int call_syscall(struct syscall_desc *scall, char *argv[]) { struct stat64 sb; struct utimbuf ut; long long flags; unsigned int i; char *endp; int rval; int more; union { char *str; long long num; } args[MAX_ARGS]; more = 0; /* * Verify correctness of the arguments. */ for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { if (scall->sd_args[i] == TYPE_NONE) { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) break; fprintf(stderr, "too many arguments [%s]\n", argv[i]); exit(1); } else { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { if (scall->sd_args[i] & TYPE_OPTIONAL) { args[i].str = NULL; break; } fprintf(stderr, "too few arguments\n"); exit(1); } if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) { if (strcmp(argv[i], "NULL") == 0) args[i].str = NULL; else if (strcmp(argv[i], "DEADCODE") == 0) args[i].str = (void *)0xdeadc0de; else args[i].str = argv[i]; } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_NUMBER) { args[i].num = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_DESCRIPTOR) { if (strcmp(argv[i], "AT_FDCWD") == 0) { args[i].num = AT_FDCWD; } else if (strcmp(argv[i], "BADFD") == 0) { /* In case AT_FDCWD is -1 on some systems... */ if (AT_FDCWD == -1) args[i].num = -2; else args[i].num = -1; } else { int pos; pos = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } args[i].num = descriptor_get(pos); } } } } /* * Call the given syscall. */ #define NUM(n) (args[(n)].num) #define STR(n) (args[(n)].str) switch (scall->sd_action) { case ACTION_OPEN: flags = str2flags(open_flags, STR(1)); if (flags & O_CREAT) { if (i == 2) { fprintf(stderr, "too few arguments\n"); exit(1); } rval = open(STR(0), flags, (mode_t)NUM(2)); } else { if (i == 3) { fprintf(stderr, "too many arguments\n"); exit(1); } rval = open(STR(0), flags); } if (rval >= 0) { more = argv[i] && !strcmp(argv[i], ":"); descriptor_add(rval); } break; case ACTION_CREATE: rval = open(STR(0), O_CREAT | O_EXCL, NUM(1)); if (rval >= 0) { more = argv[i] && !strcmp(argv[i], ":"); descriptor_add(rval); } break; case ACTION_UNLINK: rval = unlink(STR(0)); break; case ACTION_MKDIR: rval = mkdir(STR(0), NUM(1)); break; case ACTION_RMDIR: rval = rmdir(STR(0)); break; case ACTION_LINK: rval = link(STR(0), STR(1)); break; case ACTION_SYMLINK: rval = symlink(STR(0), STR(1)); break; case ACTION_RENAME: rval = rename(STR(0), STR(1)); break; case ACTION_MKFIFO: rval = mkfifo(STR(0), NUM(1)); break; case ACTION_CHMOD: rval = chmod(STR(0), NUM(1)); break; #ifdef HAS_LCHMOD case ACTION_LCHMOD: rval = lchmod(STR(0), NUM(1)); break; #endif case ACTION_CHOWN: rval = chown(STR(0), NUM(1), NUM(2)); break; case ACTION_LCHOWN: rval = lchown(STR(0), NUM(1), NUM(2)); break; #ifdef HAS_CHFLAGS case ACTION_CHFLAGS: rval = chflags(STR(0), str2flags(chflags_flags, STR(1))); break; #endif #ifdef HAS_LCHFLAGS case ACTION_LCHFLAGS: rval = lchflags(STR(0), str2flags(chflags_flags, STR(1))); break; #endif case ACTION_TRUNCATE: rval = truncate64(STR(0), NUM(1)); break; case ACTION_FTRUNCATE: rval = ftruncate64(NUM(0), NUM(1)); break; case ACTION_STAT: rval = stat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_LSTAT: rval = lstat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_UTIME : switch (i) { case 1 : rval = utime(STR(0), (struct utimbuf*)NULL); break; case 3: ut.actime = NUM(1); ut.modtime = NUM(2); rval = utime(STR(0), &ut); break; default : fprintf(stderr,"utime() requires 1 or 3 arguments\n"); exit(1); } break; case ACTION_BIND: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } case ACTION_MKNOD: case ACTION_MKNODAT: { mode_t ntype; dev_t dev; int fa; switch (scall->sd_action) { case ACTION_MKNOD: fa = 0; break; case ACTION_MKNODAT: fa = 1; break; default: abort(); } dev = makedev(NUM(fa + 3), NUM(fa + 4)); if (strcmp(STR(fa + 1), "c") == 0) /* character device */ ntype = S_IFCHR; else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ ntype = S_IFBLK; else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */ ntype = S_IFIFO; else if (strcmp(STR(fa + 1), "d") == 0) /* directory */ ntype = S_IFDIR; else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */ ntype = S_IFREG; else { fprintf(stderr, "wrong argument 1\n"); exit(1); } switch (scall->sd_action) { case ACTION_MKNOD: rval = mknod(STR(0), ntype | NUM(2), dev); break; case ACTION_MKNODAT: rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev); break; default: abort(); } break; } #ifdef HAS_ACL case ACTION_GETFACL : rval = do_getfacl(STR(0), STR(1)); if (rval == 0) return (i); break; case ACTION_SETFACL : rval = do_setfacl(STR(0), STR(1), STR(2)); break; #endif default: fprintf(stderr, "unsupported syscall\n"); exit(1); } #undef STR #undef NUM if (rval < 0) { const char *serrno; serrno = err2str(errno); fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); printf("%s\n", serrno); exit(1); } /* Do not output a "0" when more syscalls to come */ if (!more) printf("0\n"); return (i); }
/* * This function adds a journal inode to a filesystem, using either * POSIX routines if the filesystem is mounted, or using direct I/O * functions if it is not. */ errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags) { errcode_t retval; ext2_ino_t journal_ino; struct stat st; char jfile[1024]; int mount_flags; int fd = -1; if (flags & EXT2_MKJOURNAL_NO_MNT_CHECK) mount_flags = 0; else if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags, jfile, sizeof(jfile)-10))) return retval; if (mount_flags & EXT2_MF_MOUNTED) { #if HAVE_EXT2_IOCTLS int f = 0; #endif strcat(jfile, "/.journal"); /* * If .../.journal already exists, make sure any * immutable or append-only flags are cleared. */ #if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) (void) chflags (jfile, 0); #else #if HAVE_EXT2_IOCTLS fd = open(jfile, O_RDONLY); if (fd >= 0) { retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); close(fd); if (retval) return retval; } #endif #endif /* Create the journal file */ if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) return errno; /* Note that we can't do lazy journal initialization for mounted * filesystems, since the zero writing is also allocating the * journal blocks. We could use fallocate, but not all kernels * support that, and creating a journal on a mounted ext2 * filesystems is extremely rare these days... Ignore it. */ flags &= ~EXT2_MKJOURNAL_LAZYINIT; if ((retval = write_journal_file(fs, jfile, num_blocks, flags))) goto errout; /* Get inode number of the journal file */ if (fstat(fd, &st) < 0) { retval = errno; goto errout; } #if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); #else #if HAVE_EXT2_IOCTLS if (ioctl(fd, EXT2_IOC_GETFLAGS, &f) < 0) { retval = errno; goto errout; } f |= EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL; retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); #endif #endif if (retval) { retval = errno; goto errout; } if (close(fd) < 0) { retval = errno; fd = -1; goto errout; } journal_ino = st.st_ino; } else { if ((mount_flags & EXT2_MF_BUSY) && !(fs->flags & EXT2_FLAG_EXCLUSIVE)) { retval = EBUSY; goto errout; } journal_ino = EXT2_JOURNAL_INO; if ((retval = write_journal_inode(fs, journal_ino, num_blocks, flags))) return retval; } fs->super->s_journal_inum = journal_ino; fs->super->s_journal_dev = 0; memset(fs->super->s_journal_uuid, 0, sizeof(fs->super->s_journal_uuid)); fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; ext2fs_mark_super_dirty(fs); return 0; errout: if (fd >= 0) close(fd); return retval; }
int setfile(struct stat *fs, int fd) { static struct timeval tv[2]; struct stat ts; int rval, gotstat, islink, fdval; rval = 0; fdval = fd != -1; islink = !fdval && S_ISLNK(fs->st_mode); fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) { warn("%sutimes: %s", islink ? "l" : "", to.p_path); rval = 1; } if (fdval ? fstat(fd, &ts) : (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts))) gotstat = 0; else { gotstat = 1; ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO; } /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) : chown(to.p_path, fs->st_uid, fs->st_gid))) { if (errno != EPERM) { warn("chown: %s", to.p_path); rval = 1; } fs->st_mode &= ~(S_ISUID | S_ISGID); } if (!gotstat || fs->st_mode != ts.st_mode) if (fdval ? fchmod(fd, fs->st_mode) : (islink ? lchmod(to.p_path, fs->st_mode) : chmod(to.p_path, fs->st_mode))) { warn("chmod: %s", to.p_path); rval = 1; } if (!gotstat || fs->st_flags != ts.st_flags) if (fdval ? fchflags(fd, fs->st_flags) : (islink ? lchflags(to.p_path, fs->st_flags) : chflags(to.p_path, fs->st_flags))) { warn("chflags: %s", to.p_path); rval = 1; } return (rval); }
/* * This function adds a journal inode to a filesystem, using either * POSIX routines if the filesystem is mounted, or using direct I/O * functions if it is not. */ errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) { errcode_t retval; ext2_ino_t journal_ino; struct stat st; char jfile[1024]; int mount_flags, f; int fd = -1; if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags, jfile, sizeof(jfile)-10))) return retval; if (mount_flags & EXT2_MF_MOUNTED) { strcat(jfile, "/.journal"); /* * If .../.journal already exists, make sure any * immutable or append-only flags are cleared. */ #if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) (void) chflags (jfile, 0); #else #if HAVE_EXT2_IOCTLS fd = open(jfile, O_RDONLY); if (fd >= 0) { f = 0; ioctl(fd, EXT2_IOC_SETFLAGS, &f); close(fd); } #endif #endif /* Create the journal file */ if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) return errno; if ((retval = write_journal_file(fs, jfile, size, flags))) goto errout; /* Get inode number of the journal file */ if (fstat(fd, &st) < 0) { retval = errno; goto errout; } #if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); #else #if HAVE_EXT2_IOCTLS if (ioctl(fd, EXT2_IOC_GETFLAGS, &f) < 0) { retval = errno; goto errout; } f |= EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL; retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); #endif #endif if (retval) { retval = errno; goto errout; } if (close(fd) < 0) { retval = errno; fd = -1; goto errout; } journal_ino = st.st_ino; } else { if ((mount_flags & EXT2_MF_BUSY) && !(fs->flags & EXT2_FLAG_EXCLUSIVE)) { retval = EBUSY; goto errout; } journal_ino = EXT2_JOURNAL_INO; if ((retval = write_journal_inode(fs, journal_ino, size, flags))) return retval; } fs->super->s_journal_inum = journal_ino; fs->super->s_journal_dev = 0; memset(fs->super->s_journal_uuid, 0, sizeof(fs->super->s_journal_uuid)); fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; ext2fs_mark_super_dirty(fs); return 0; errout: if (fd > 0) close(fd); return retval; }
/** * Set file modes, permissions and times * * fname is the original filename * ofile is the output filename (may be in a different directory) * * Returns: true on success * false on failure */ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) { struct utimbuf ut; mode_t old_mask; bool ok = true; boffset_t fsize; if (uid_set) { my_uid = getuid(); my_gid = getgid(); uid_set = true; } #if defined(HAVE_WIN32) if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX && set_win32_attributes(jcr, attr, ofd)) { if (is_bopen(ofd)) { bclose(ofd); } pm_strcpy(attr->ofname, "*none*"); return true; } if (attr->data_stream == STREAM_WIN32_DATA || attr->data_stream == STREAM_WIN32_GZIP_DATA || attr->data_stream == STREAM_WIN32_COMPRESSED_DATA) { if (is_bopen(ofd)) { bclose(ofd); } pm_strcpy(attr->ofname, "*none*"); return true; } /** * If Windows stuff failed, e.g. attempt to restore Unix file * to Windows, simply fall through and we will do it the * universal way. */ #endif old_mask = umask(0); if (is_bopen(ofd)) { char ec1[50], ec2[50]; fsize = blseek(ofd, 0, SEEK_END); bclose(ofd); /* first close file */ if (attr->type == FT_REG && fsize > 0 && attr->statp.st_size > 0 && fsize != (boffset_t)attr->statp.st_size) { Jmsg3(jcr, M_ERROR, 0, _("File size of restored file %s not correct. Original %s, restored %s.\n"), attr->ofname, edit_uint64(attr->statp.st_size, ec1), edit_uint64(fsize, ec2)); } } /** * We do not restore sockets, so skip trying to restore their * attributes. */ if (attr->type == FT_SPEC && S_ISSOCK(attr->statp.st_mode)) { goto bail_out; } ut.actime = attr->statp.st_atime; ut.modtime = attr->statp.st_mtime; /* ***FIXME**** optimize -- don't do if already correct */ /** * For link, change owner of link using lchown, but don't * try to do a chmod as that will update the file behind it. */ if (attr->type == FT_LNK) { /** Change owner of link, not of real file */ if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), attr->ofname, be.bstrerror()); ok = false; } } else { if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), attr->ofname, be.bstrerror()); ok = false; } if (chmod(attr->ofname, attr->statp.st_mode) < 0 && my_uid == 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"), attr->ofname, be.bstrerror()); ok = false; } /** * Reset file times. */ if (utime(attr->ofname, &ut) < 0 && my_uid == 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), attr->ofname, be.bstrerror()); ok = false; } #ifdef HAVE_CHFLAGS /** * FreeBSD user flags * * Note, this should really be done before the utime() above, * but if the immutable bit is set, it will make the utimes() * fail. */ if (chflags(attr->ofname, attr->statp.st_flags) < 0 && my_uid == 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file flags %s: ERR=%s\n"), attr->ofname, be.bstrerror()); ok = false; } #endif } bail_out: pm_strcpy(attr->ofname, "*none*"); umask(old_mask); return ok; }
int main(int argc, char *argv[]) { FTS *ftsp; FTSENT *p; void *set; long val; int oct; mode_t omode; int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval; uid_t uid; gid_t gid; u_int32_t fclear, fset; char *ep, *mode, *cp, *flags; #ifdef lint set = NULL; oct = omode = 0; #endif setlocale(LC_ALL, ""); ischown = __progname[2] == 'o'; ischgrp = __progname[2] == 'g'; ischmod = __progname[2] == 'm'; ischflags = __progname[2] == 'f'; uid = (uid_t)-1; gid = (gid_t)-1; Hflag = Lflag = Rflag = fflag = hflag = 0; while ((ch = getopt(argc, argv, "HLPRXfghorstuwx")) != -1) switch (ch) { case 'H': Hflag = 1; Lflag = 0; break; case 'L': Lflag = 1; Hflag = 0; break; case 'P': Hflag = Lflag = 0; break; case 'R': Rflag = 1; break; case 'f': /* XXX: undocumented. */ fflag = 1; break; case 'h': /* * In System V (and probably POSIX.2) the -h option * causes chmod to change the mode of the symbolic * link. 4.4BSD's symbolic links don't have modes, * so it's an undocumented noop. Do syntax checking, * though. */ hflag = 1; break; /* * XXX * "-[rwx]" are valid mode commands. If they are the entire * argument, getopt has moved past them, so decrement optind. * Regardless, we're done argument processing. */ case 'g': case 'o': case 'r': case 's': case 't': case 'u': case 'w': case 'X': case 'x': if (!ischmod) usage(); if (argv[optind - 1][0] == '-' && argv[optind - 1][1] == ch && argv[optind - 1][2] == '\0') --optind; goto done; default: usage(); } done: argv += optind; argc -= optind; if (argc < 2) usage(); fts_options = FTS_PHYSICAL; if (Rflag) { if (hflag) errx(1, "the -R and -h options may not be specified together."); if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { fts_options &= ~FTS_PHYSICAL; fts_options |= FTS_LOGICAL; } } if (ischflags) { flags = *argv; if (*flags >= '0' && *flags <= '7') { errno = 0; val = strtoul(flags, &ep, 8); if (val > UINT_MAX) errno = ERANGE; if (errno) err(1, "invalid flags: %s", flags); if (*ep) errx(1, "invalid flags: %s", flags); fset = val; oct = 1; } else { if (strtofflags(&flags, &fset, &fclear)) errx(1, "invalid flag: %s", flags); fclear = ~fclear; oct = 0; } } else if (ischmod) { mode = *argv; if (*mode >= '0' && *mode <= '7') { errno = 0; val = strtol(mode, &ep, 8); if (val > INT_MAX || val < 0) errno = ERANGE; if (errno) err(1, "invalid file mode: %s", mode); if (*ep) errx(1, "invalid file mode: %s", mode); omode = val; oct = 1; } else { if ((set = setmode(mode)) == NULL) errx(1, "invalid file mode: %s", mode); oct = 0; } } else if (ischown) { /* Both UID and GID are given. */ if ((cp = strchr(*argv, ':')) != NULL) { *cp++ = '\0'; gid = a_gid(cp); } #ifdef SUPPORT_DOT /* UID and GID are separated by a dot and UID exists. */ else if ((cp = strchr(*argv, '.')) != NULL && (uid = a_uid(*argv, 1)) == (uid_t)-1) { *cp++ = '\0'; gid = a_gid(cp); } #endif if (uid == (uid_t)-1) uid = a_uid(*argv, 0); } else gid = a_gid(*argv); if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) err(1, NULL); for (rval = 0; (p = fts_read(ftsp)) != NULL;) { switch (p->fts_info) { case FTS_D: if (!Rflag) fts_set(ftsp, p, FTS_SKIP); if (ischmod) break; else continue; case FTS_DNR: /* Warn, chmod, continue. */ warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; break; case FTS_DP: /* Already changed at FTS_D. */ if (ischmod) continue; else break; case FTS_ERR: /* Warn, continue. */ case FTS_NS: warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; continue; case FTS_SL: /* Ignore. */ case FTS_SLNONE: /* * The only symlinks that end up here are ones that * don't point to anything and ones that we found * doing a physical walk. */ if (ischflags || ischmod || !hflag) continue; break; default: break; } if (ischflags) { if (oct) { if (!chflags(p->fts_accpath, fset)) continue; } else { p->fts_statp->st_flags |= fset; p->fts_statp->st_flags &= fclear; if (!chflags(p->fts_accpath, p->fts_statp->st_flags)) continue; } warn("%s", p->fts_path); rval = 1; } else if (ischmod && chmod(p->fts_accpath, oct ? omode : getmode(set, p->fts_statp->st_mode)) && !fflag) { warn("%s", p->fts_path); rval = 1; } else if (!ischmod && !ischflags && (hflag ? lchown(p->fts_accpath, uid, gid) : chown(p->fts_accpath, uid, gid)) && !fflag) { warn("%s", p->fts_path); rval = 1; } } if (errno) err(1, "fts_read"); exit(rval); }
static unsigned int call_syscall(struct syscall_desc *scall, char *argv[]) { struct stat64 sb; long long flags; unsigned int i; char *endp; int rval; union { char *str; long long num; } args[MAX_ARGS]; /* * Verify correctness of the arguments. */ for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { if (scall->sd_args[i] == TYPE_NONE) { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) break; fprintf(stderr, "too many arguments [%s]\n", argv[i]); exit(1); } else { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { if (scall->sd_args[i] & TYPE_OPTIONAL) break; fprintf(stderr, "too few arguments\n"); exit(1); } if (scall->sd_args[i] & TYPE_STRING) { if (strcmp(argv[i], "NULL") == 0) args[i].str = NULL; else if (strcmp(argv[i], "DEADCODE") == 0) args[i].str = (void *)0xdeadc0de; else args[i].str = argv[i]; } else if (scall->sd_args[i] & TYPE_NUMBER) { args[i].num = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } } } } /* * Call the given syscall. */ #define NUM(n) (args[(n)].num) #define STR(n) (args[(n)].str) switch (scall->sd_action) { case ACTION_OPEN: flags = str2flags(open_flags, STR(1)); if (flags & O_CREAT) { if (i == 2) { fprintf(stderr, "too few arguments\n"); exit(1); } rval = open(STR(0), flags, (mode_t)NUM(2)); } else { if (i == 3) { fprintf(stderr, "too many arguments\n"); exit(1); } rval = open(STR(0), flags); } break; case ACTION_CREATE: rval = open(STR(0), O_CREAT | O_EXCL, NUM(1)); if (rval >= 0) close(rval); break; case ACTION_UNLINK: rval = unlink(STR(0)); break; case ACTION_MKDIR: rval = mkdir(STR(0), NUM(1)); break; case ACTION_RMDIR: rval = rmdir(STR(0)); break; case ACTION_LINK: rval = link(STR(0), STR(1)); break; case ACTION_SYMLINK: rval = symlink(STR(0), STR(1)); break; case ACTION_RENAME: rval = rename(STR(0), STR(1)); break; case ACTION_MKFIFO: rval = mkfifo(STR(0), NUM(1)); break; case ACTION_CHMOD: rval = chmod(STR(0), NUM(1)); break; #ifdef HAS_LCHMOD case ACTION_LCHMOD: rval = lchmod(STR(0), NUM(1)); break; #endif case ACTION_CHOWN: rval = chown(STR(0), NUM(1), NUM(2)); break; case ACTION_LCHOWN: rval = lchown(STR(0), NUM(1), NUM(2)); break; #ifdef HAS_CHFLAGS case ACTION_CHFLAGS: rval = chflags(STR(0), str2flags(chflags_flags, STR(1))); break; #endif #ifdef HAS_LCHFLAGS case ACTION_LCHFLAGS: rval = lchflags(STR(0), str2flags(chflags_flags, STR(1))); break; #endif case ACTION_TRUNCATE: rval = truncate64(STR(0), NUM(1)); break; case ACTION_STAT: rval = stat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_LSTAT: rval = lstat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_READDIR: rval = readdir_loop(STR(0)); break; default: fprintf(stderr, "unsupported syscall\n"); exit(1); } #undef STR #undef NUM if (rval < 0) { const char *serrno; serrno = err2str(errno); fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); printf("%s\n", serrno); exit(1); } printf("0\n"); return (i); }
static int do_extract(struct archive *a, struct archive_entry *ae, const char *location, int nfiles, struct pkg *pkg, struct pkg *local) { int retcode = EPKG_OK; int ret = 0, cur_file = 0; char path[MAXPATHLEN], pathname[MAXPATHLEN], rpath[MAXPATHLEN]; struct stat st; const struct stat *aest; bool renamed = false; const struct pkg_file *rf; struct pkg_config_file *rcf; struct sbuf *newconf; bool automerge = pkg_object_bool(pkg_config_get("AUTOMERGE")); unsigned long set, clear; #ifndef HAVE_ARC4RANDOM srand(time(NULL)); #endif if (nfiles == 0) return (EPKG_OK); pkg_emit_extract_begin(pkg); pkg_emit_progress_start(NULL); newconf = sbuf_new_auto(); do { ret = ARCHIVE_OK; sbuf_clear(newconf); rf = NULL; rcf = NULL; pkg_absolutepath(archive_entry_pathname(ae), path, sizeof(path)); snprintf(pathname, sizeof(pathname), "%s%s%s", location ? location : "", *path == '/' ? "" : "/", path ); strlcpy(rpath, pathname, sizeof(rpath)); aest = archive_entry_stat(ae); archive_entry_fflags(ae, &set, &clear); if (lstat(rpath, &st) != -1) { /* * We have an existing file on the path, so handle it */ if (!S_ISDIR(aest->st_mode)) { pkg_debug(2, "Old version found, renaming"); pkg_add_file_random_suffix(rpath, sizeof(rpath), 12); renamed = true; } if (!S_ISDIR(st.st_mode) && S_ISDIR(aest->st_mode)) { if (S_ISLNK(st.st_mode)) { if (stat(rpath, &st) == -1) { pkg_emit_error("Dead symlink %s", rpath); } else { pkg_debug(2, "Directory is a symlink, use it"); pkg_emit_progress_tick(cur_file++, nfiles); continue; } } } } archive_entry_set_pathname(ae, rpath); /* load in memory the content of config files */ if (pkg_is_config_file(pkg, path, &rf, &rcf)) { pkg_debug(1, "Populating config_file %s", pathname); size_t len = archive_entry_size(ae); rcf->content = malloc(len); archive_read_data(a, rcf->content, len); if (renamed && (!automerge || local == NULL)) strlcat(pathname, ".pkgnew", sizeof(pathname)); } /* * check if the file is already provided by previous package */ if (!automerge) attempt_to_merge(renamed, rcf, local, pathname, path, newconf); if (sbuf_len(newconf) == 0 && (rcf == NULL || rcf->content == NULL)) { pkg_debug(1, "Extracting: %s", archive_entry_pathname(ae)); int install_as_user = (getenv("INSTALL_AS_USER") != NULL); int extract_flags = EXTRACT_ARCHIVE_FLAGS; if (install_as_user) { /* when installing as user don't try to set file ownership */ extract_flags &= ~ARCHIVE_EXTRACT_OWNER; } ret = archive_read_extract(a, ae, extract_flags); } else { if (sbuf_len(newconf) == 0) { sbuf_cat(newconf, rcf->content); sbuf_finish(newconf); } pkg_debug(2, "Writing conf in %s", pathname); unlink(rpath); FILE *f = fopen(rpath, "w+"); fprintf(f, "%s", sbuf_data(newconf)); fclose(f); } if (ret != ARCHIVE_OK) { /* * show error except when the failure is during * extracting a directory and that the directory already * exists. * this allow to install packages linux_base from * package for example */ if (archive_entry_filetype(ae) != AE_IFDIR || !is_dir(pathname)) { pkg_emit_error("archive_read_extract(): %s", archive_error_string(a)); retcode = EPKG_FATAL; goto cleanup; } } /* Reapply modes to the directories to work around a problem on FreeBSD 9 */ if (archive_entry_filetype(ae) == AE_IFDIR) chmod(pathname, aest->st_mode); pkg_emit_progress_tick(cur_file++, nfiles); /* Rename old file */ if (renamed) { pkg_debug(1, "Renaming %s -> %s", rpath, pathname); #ifdef HAVE_CHFLAGS bool old = false; if (set & NOCHANGESFLAGS) chflags(rpath, 0); if (lstat(pathname, &st) != -1) { old = true; if (st.st_flags & NOCHANGESFLAGS) chflags(pathname, 0); } #endif if (rename(rpath, pathname) == -1) { #ifdef HAVE_CHFLAGS /* restore flags */ if (old) chflags(pathname, st.st_flags); #endif pkg_emit_error("cannot rename %s to %s: %s", rpath, pathname, strerror(errno)); retcode = EPKG_FATAL; goto cleanup; } #ifdef HAVE_CHFLAGS /* Restore flags */ chflags(pathname, set); #endif } if (string_end_with(pathname, ".pkgnew")) pkg_emit_notice("New configuration file: %s", pathname); renamed = false; } while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK); if (ret != ARCHIVE_EOF) { pkg_emit_error("archive_read_next_header(): %s", archive_error_string(a)); retcode = EPKG_FATAL; } cleanup: pkg_emit_progress_tick(nfiles, nfiles); pkg_emit_extract_finished(pkg); if (renamed && retcode == EPKG_FATAL) { #ifdef HAVE_CHFLAGS if (set & NOCHANGESFLAGS) chflags(rpath, set & ~NOCHANGESFLAGS); #endif unlink(rpath); } return (retcode); }