Exemple #1
0
/* properties_on_apply */
static void _properties_on_apply(gpointer data)
{
	Properties * properties = data;
	char * p;
	struct group * gr;
	gid_t gid = properties->gid;
	size_t i;
	mode_t mode = 0;

#if GTK_CHECK_VERSION(2, 24, 0)
	p = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(
				properties->group));
#else
	p = gtk_combo_box_get_active_text(GTK_COMBO_BOX(properties->group));
#endif
	if((gr = getgrnam(p)) == NULL)
		_properties_error(properties, p, 1);
	else
		gid = gr->gr_gid;
	for(i = 0; i < 9; i++)
		mode |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
					properties->mode[i])) << i;
	if(lchown(properties->filename, properties->uid, gid) != 0
			|| lchmod(properties->filename, mode) != 0)
		_properties_error(properties, properties->filename, 1);
}
Exemple #2
0
Fichier : null.c Projet : glk/puffs
/*
 * set attributes to what is specified.  XXX: no rollback in case of failure
 */
static int
processvattr(const char *path, const struct vattr *va, int regular)
{
	struct timeval tv[2];

	/* XXX: -1 == PUFFS_VNOVAL, but shouldn't trust that */
	if (va->va_uid != (unsigned)-1 || va->va_gid != (unsigned)-1)
		if (lchown(path, va->va_uid, va->va_gid) == -1)
			return errno;

	if (va->va_mode != (u_short)PUFFS_VNOVAL)
		if (lchmod(path, va->va_mode) == -1)
			return errno;

	/* sloppy */
	if (va->va_atime.tv_sec != (time_t)PUFFS_VNOVAL
	    || va->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) {
		TIMESPEC_TO_TIMEVAL(&tv[0], &va->va_atime);
		TIMESPEC_TO_TIMEVAL(&tv[1], &va->va_mtime);

		if (lutimes(path, tv) == -1)
			return errno;
	}

	if (regular && va->va_size != (u_quad_t)PUFFS_VNOVAL)
		if (truncate(path, (off_t)va->va_size) == -1)
			return errno;

	return 0;
}
Exemple #3
0
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);
    }
}
Exemple #4
0
int do_chmod(const char *path, mode_t mode)
{
	int code;
	if (dry_run) return 0;
	RETURN_ERROR_IF_RO_OR_LO;
#ifdef HAVE_LCHMOD
	code = lchmod(path, mode & CHMOD_BITS);
#else
	if (S_ISLNK(mode)) {
# if defined HAVE_SETATTRLIST
		struct attrlist attrList;
		uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */

		memset(&attrList, 0, sizeof attrList);
		attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
		attrList.commonattr = ATTR_CMN_ACCESSMASK;
		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
# else
		code = 1;
# endif
	} else
		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
#endif /* !HAVE_LCHMOD */
	if (code != 0 && (preserve_perms || preserve_executability))
		return code;
	return 0;
}
Exemple #5
0
/*
 * 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);
}
Exemple #6
0
void setup() {
  create_file("file", "abcdef", 0777);
  symlink("file", "file-link");
  // some platforms use 777, some use 755 by default for symlinks
  // make sure we're using 777 for the test
  lchmod("file-link", 0777);
  mkdir("folder", 0777);
}
Exemple #7
0
void
set_pmode(char *fnm, mode_t mode)
{
	mode &= ABITS;
	if (lchmod(fnm, mode) < 0)
		syswarn(1, errno, "Could not set permissions on %s", fnm);
	return;
}
Exemple #8
0
void
set_pmode(char *fnm, mode_t mode)
{
	mode &= A_BITS;
	if (lchmod(fnm, mode)) {
		(void)fflush(listf);
		syswarn(1, errno, "Cannot set permissions on %s", fnm);
	}
	return;
}
Exemple #9
0
static int _single_p(Copy * copy, char const * dst, struct stat const * st)
{
	struct timeval tv[2];

	if(lchown(dst, st->st_uid, st->st_gid) != 0)
	{
		_copy_filename_error(copy, dst, 0);
		if(lchmod(dst, st->st_mode & ~(S_ISUID | S_ISGID)) != 0)
			_copy_filename_error(copy, dst, 0);
	}
	else if(lchmod(dst, st->st_mode) != 0)
		_copy_filename_error(copy, dst, 0);
	tv[0].tv_sec = st->st_atime;
	tv[0].tv_usec = 0;
	tv[1].tv_sec = st->st_mtime;
	tv[1].tv_usec = 0;
	if(lutimes(dst, tv) != 0)
		_copy_filename_error(copy, dst, 0);
	return 0;
}
Exemple #10
0
int do_chmod(const char *path, mode_t mode)
{
	int code;
	if (dry_run) return 0;
	RETURN_ERROR_IF_RO_OR_LO;
	if (S_ISLNK(mode)) {
#ifdef HAVE_LCHMOD
		code = lchmod(path, mode & CHMOD_BITS);
#else
		code = 1;
#endif
	} else
		code = chmod(path, mode & CHMOD_BITS);
	if (code != 0 && preserve_perms)
	    return code;
	return 0;
}
Exemple #11
0
/* Work around trailing slash bugs in lchown.  */
int
rpl_lchown (const char *file, uid_t uid, gid_t gid)
{
  bool stat_valid = false;
  int result;

# if CHOWN_CHANGE_TIME_BUG
  struct stat st;

  if (gid != (gid_t) -1 || uid != (uid_t) -1)
    {
      if (lstat (file, &st))
        return -1;
      stat_valid = true;
      if (!S_ISLNK (st.st_mode))
        return chown (file, uid, gid);
    }
# endif

# if CHOWN_TRAILING_SLASH_BUG
  if (!stat_valid)
    {
      size_t len = strlen (file);
      if (len && file[len - 1] == '/')
        return chown (file, uid, gid);
    }
# endif

  result = lchown (file, uid, gid);

# if CHOWN_CHANGE_TIME_BUG && HAVE_LCHMOD
  if (result == 0 && stat_valid
      && (uid == st.st_uid || uid == (uid_t) -1)
      && (gid == st.st_gid || gid == (gid_t) -1))
    {
      /* No change in ownership, but at least one argument was not -1,
         so we are required to update ctime.  Since lchown succeeded,
         we assume that lchmod will do likewise.  But if the system
         lacks lchmod and lutimes, we are out of luck.  Oh well.  */
      result = lchmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
                                           | S_ISUID | S_ISGID | S_ISVTX));
    }
# endif

  return result;
}
Exemple #12
0
/*
 * Restore the owner and permissions (mode) of a Directory.
 *  See attribs.c for the equivalent for files.
 */
static void set_own_mod(ATTR *attr, char *path, uid_t owner, gid_t group, mode_t mode)
{
   if (lchown(path, owner, group) != 0 && attr->uid == 0
#ifdef AFS
        && errno != EPERM
#endif
   ) {
      berrno be;
      Jmsg2(attr->jcr, M_WARNING, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
           path, be.bstrerror());
   }
   if (lchmod(path, mode) != 0 && attr->uid == 0) {
      berrno be;
      Jmsg2(attr->jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
           path, be.bstrerror());
   }
}
Exemple #13
0
int do_chmod(const char *path, mode_t mode, uint32 fileflags)
{
	int code;
	if (dry_run) return 0;
	RETURN_ERROR_IF_RO_OR_LO;
#ifdef HAVE_LCHMOD
	code = lchmod(path, mode & CHMOD_BITS);
#else
	if (S_ISLNK(mode)) {
# if defined HAVE_SETATTRLIST
		struct attrlist attrList;
		uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */

		memset(&attrList, 0, sizeof attrList);
		attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
		attrList.commonattr = ATTR_CMN_ACCESSMASK;
		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
# else
		code = 1;
# endif
	} else
		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
#endif /* !HAVE_LCHMOD */
#ifdef SUPPORT_FORCE_CHANGE
	if (code < 0 && force_change && errno == EPERM && !S_ISLNK(mode)) {
		if (fileflags == NO_FFLAGS) {
			STRUCT_STAT st;
			if (x_lstat(path, &st, NULL) == 0)
				fileflags = st.st_flags;
		}
		if (fileflags != NO_FFLAGS
		 && make_mutable(path, mode, fileflags, force_change) > 0) {
			code = chmod(path, mode & CHMOD_BITS);
			undo_make_mutable(path, fileflags);
			if (code == 0)
				return 0;
		}
		errno = EPERM;
	}
#else
	fileflags = 0; /* avoid compiler warning */
#endif
	if (code != 0 && (preserve_perms || preserve_executability))
		return code;
	return 0;
}
Exemple #14
0
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);
}
Exemple #15
0
/* No support for micro-second file time resolution. Use utime(). */
int copydate(char *pszToFile, char *pszFromFile) { /* Copy the file dates */
  /* Note: "struct _stat" and "struct _utimbuf" don't compile under Linux */
  struct stat stFrom = {0};
  struct utimbuf utbTo = {0};
  int err;
  err = lstat(pszFromFile, &stFrom);
  /* Copy file permissions too */
  err = lchmod(pszToFile, stFrom.st_mode);
  /* And copy file times */
  utbTo.actime = stFrom.st_atime;
  utbTo.modtime = stFrom.st_mtime;
  err = lutime(pszToFile, &utbTo);
  DEBUG_CODE({
    struct tm *pTime;
    char buf[40];
    pTime = LocalFileTime(&(utbTo.modtime)); /* Time of last data modification */
    sprintf(buf, "%4d-%02d-%02d %02d:%02d:%02d",
	    pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
	    pTime->tm_hour, pTime->tm_min, pTime->tm_sec);
    DEBUG_PRINTF(("utime(\"%s\", %s) = %d %s\n", pszToFile, buf, err,
      		  err?strerror(errno):""));
  });
Exemple #16
0
int
extractfile(char *name)
{
	int flags;
	uid_t uid;
	gid_t gid;
	mode_t mode;
	struct timeval timep[2];
	struct entry *ep;

	curfile.name = name;
	curfile.action = USING;
	timep[0].tv_sec = curfile.dip->di_atime;
	timep[0].tv_usec = curfile.dip->di_atimensec / 1000;
	timep[1].tv_sec = curfile.dip->di_mtime;
	timep[1].tv_usec = curfile.dip->di_mtimensec / 1000;
	uid = curfile.dip->di_uid;
	gid = curfile.dip->di_gid;
	mode = curfile.dip->di_mode;
	flags = curfile.dip->di_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;
		getfile(xtrlnkfile, xtrlnkskip);
		if (pathlen == 0) {
			vprintf(stdout,
			    "%s: zero length symbolic link (ignored)\n", name);
			return (GOOD);
		}
		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
			lchown(name, uid, gid);
			lchmod(name, mode);
			lutimes(name, timep);
			return (GOOD);
		}
		return (FAIL);

	case IFIFO:
		vprintf(stdout, "extract fifo %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag && !Nflag)
			unlink(name);
		if (mkfifo(name, mode) < 0) {
			fprintf(stderr, "%s: cannot create fifo: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		chown(name, uid, gid);
		chmod(name, mode);
		utimes(name, timep);
		chflags(name, flags);
		skipfile();
		return (GOOD);

	case IFCHR:
	case IFBLK:
		vprintf(stdout, "extract special file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			unlink(name);
		if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
			fprintf(stderr, "%s: cannot create special file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		chown(name, uid, gid);
		chmod(name, mode);
		utimes(name, timep);
		chflags(name, flags);
		skipfile();
		return (GOOD);

	case IFREG:
		vprintf(stdout, "extract file %s\n", name);
		if (Nflag) {
			skipfile();
			return (GOOD);
		}
		if (uflag)
			unlink(name);
		if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
		    0666)) < 0) {
			fprintf(stderr, "%s: cannot create file: %s\n",
			    name, strerror(errno));
			skipfile();
			return (FAIL);
		}
		fchown(ofile, uid, gid);
		fchmod(ofile, mode);
		getfile(xtrfile, xtrskip);
		close(ofile);
		utimes(name, timep);
		chflags(name, flags);
		return (GOOD);
	}
	/* NOTREACHED */
}
Exemple #17
0
static bool
lchmod_fails(void)
{
    ATF_REQUIRE(mkdir("test", 0755) != -1);
    return lchmod("test", 0700) == -1 && chmod("test", 0700) != -1;
}
Exemple #18
0
/*
 * 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 = 0;
#ifdef BSD
	int 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);
	}
#ifndef BSD
    if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) {
#else
    if (fd ? fchmod(fd, fs->st_mode) : lchmod(to.p_path, fs->st_mode)) {
#endif
        warn("chmod: %s", to.p_path);
        rval = 1;
    }

#ifdef BSD
	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
	/* 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);
}

void
cp_usage(void)
{
	(void)fprintf(stderr,
	    "usage: cp [-R [-H | -L | -P]] [-f | -i] [-alNpv] src target\n"
	    "       cp [-R [-H | -L | -P]] [-f | -i] [-alNpv] src1 ... srcN directory\n");
	exit(1);
	/* NOTREACHED */
}
Exemple #19
0
int
main(int argc, char *argv[])
{
	FTS *ftsp;
	FTSENT *p;
	mode_t *set;
	int Hflag, Lflag, Rflag, ch, error, fflag, fts_options, hflag, rval;
	int vflag;
	char *mode;
	mode_t newmode;

	set = NULL;
	Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
	while ((ch = getopt(argc, argv, "HLPRXfghorstuvwx")) != -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':
			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 didn't have modes,
			 * so it was an undocumented noop.  In FreeBSD 3.0,
			 * lchmod(2) is introduced and this option does real
			 * work.
			 */
			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 (argv[optind - 1][0] == '-' &&
			    argv[optind - 1][1] == ch &&
			    argv[optind - 1][2] == '\0')
				--optind;
			goto done;
		case 'v':
			vflag++;
			break;
		case '?':
		default:
			usage();
		}
done:	argv += optind;
	argc -= optind;

	if (argc < 2)
		usage();

	if (Rflag) {
		fts_options = FTS_PHYSICAL;
		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;
		}
	} else
		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;

	mode = *argv;
	if ((set = setmode(mode)) == NULL)
		errx(1, "invalid file mode: %s", mode);

	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
		err(1, "fts_open");
	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
		switch (p->fts_info) {
		case FTS_D:			/* Change it at FTS_DP. */
			if (!Rflag)
				fts_set(ftsp, p, FTS_SKIP);
			continue;
		case FTS_DNR:			/* Warn, chmod, continue. */
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			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 (!hflag)
				continue;
			/* FALLTHROUGH */
		default:
			break;
		}
		newmode = getmode(set, p->fts_statp->st_mode);
		/*
		 * With NFSv4 ACLs, it is possible that applying a mode
		 * identical to the one computed from an ACL will change
		 * that ACL.
		 */
		if (may_have_nfs4acl(p, hflag) == 0 &&
		    (newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
				continue;
		if (hflag)
			error = lchmod(p->fts_accpath, newmode);
		else
			error = chmod(p->fts_accpath, newmode);
		if (error) {
			if (!fflag) {
				warn("%s", p->fts_path);
				rval = 1;
			}
		} else {
			if (vflag) {
				(void)printf("%s", p->fts_path);

				if (vflag > 1) {
					char m1[12], m2[12];

					strmode(p->fts_statp->st_mode, m1);
					strmode((p->fts_statp->st_mode &
					    S_IFMT) | newmode, m2);
					(void)printf(": 0%o [%s] -> 0%o [%s]",
					    p->fts_statp->st_mode, m1,
					    (p->fts_statp->st_mode & S_IFMT) |
					    newmode, m2);
				}
				(void)printf("\n");
			}
		}
	}
	if (errno)
		err(1, "fts_read");
	exit(rval);
}
Exemple #20
0
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);
}
Exemple #21
0
int
dirchownmod (int fd, char const *dir, mode_t mkdir_mode,
             uid_t owner, gid_t group,
             mode_t mode, mode_t mode_bits)
{
  struct stat st;
  int result = (fd < 0 ? stat (dir, &st) : fstat (fd, &st));

  if (result == 0)
    {
      mode_t dir_mode = st.st_mode;

      /* Check whether DIR is a directory.  If FD is nonnegative, this
         check avoids changing the ownership and mode bits of the
         wrong file in many cases.  This doesn't fix all the race
         conditions, but it is better than nothing.  */
      if (! S_ISDIR (dir_mode))
        {
          errno = ENOTDIR;
          result = -1;
        }
      else
        {
          /* If at least one of the S_IXUGO bits are set, chown might
             clear the S_ISUID and S_SGID bits.  Keep track of any
             file mode bits whose values are indeterminate due to this
             issue.  */
          mode_t indeterminate = 0;

          /* On some systems, chown clears S_ISUID and S_ISGID, so do
             chown before chmod.  On older System V hosts, ordinary
             users can give their files away via chown; don't worry
             about that here, since users shouldn't do that.  */

          if ((owner != (uid_t) -1 && owner != st.st_uid)
              || (group != (gid_t) -1 && group != st.st_gid))
            {
              result = (0 <= fd
                        ? fchown (fd, owner, group)
                        : mkdir_mode != (mode_t) -1
                        ? lchown (dir, owner, group)
                        : chown (dir, owner, group));

              /* Either the user cares about an indeterminate bit and
                 it'll be set properly by chmod below, or the user
                 doesn't care and it's OK to use the bit's pre-chown
                 value.  So there's no need to re-stat DIR here.  */

              if (result == 0 && (dir_mode & S_IXUGO))
                indeterminate = dir_mode & (S_ISUID | S_ISGID);
            }

          /* If the file mode bits might not be right, use chmod to
             change them.  Don't change bits the user doesn't care
             about.  */
          if (result == 0 && (((dir_mode ^ mode) | indeterminate) & mode_bits))
            {
              mode_t chmod_mode =
                mode | (dir_mode & CHMOD_MODE_BITS & ~mode_bits);
              result = (HAVE_FCHMOD && 0 <= fd
                        ? fchmod (fd, chmod_mode)
                        : mkdir_mode != (mode_t) -1
                        ? lchmod (dir, chmod_mode)
                        : chmod (dir, chmod_mode));
            }
        }
    }

  if (0 <= fd)
    {
      if (result == 0)
        result = close (fd);
      else
        {
          int e = errno;
          close (fd);
          errno = e;
        }
    }

  return result;
}
Exemple #22
0
void test() {
  int err;
  int lastctime;
  struct stat s;
  
  //
  // chmod a file
  //
  // get the current ctime for the file
  memset(&s, 0, sizeof s);
  stat("file", &s);
  lastctime = s.st_ctime;
  sleep(1);

  // do the actual chmod
  err = chmod("file", 0200);
  assert(!err);

  memset(&s, 0, sizeof s);
  stat("file", &s);
#if USE_OLD_FS
  assert(s.st_mode == (0222 | S_IFREG));
#else
  assert(s.st_mode == (0200 | S_IFREG));
#endif
  assert(s.st_ctime != lastctime);

  //
  // fchmod a file
  //
  lastctime = s.st_ctime;
  sleep(1);

  err = fchmod(open("file", O_WRONLY), 0100);
  assert(!err);

  memset(&s, 0, sizeof s);
  stat("file", &s);
#if USE_OLD_FS
  assert(s.st_mode == (0000 | S_IFREG));
#else
  assert(s.st_mode == (0100 | S_IFREG));
#endif
  assert(s.st_ctime != lastctime);

  //
  // chmod a folder
  //
  // get the current ctime for the folder
  memset(&s, 0, sizeof s);
  stat("folder", &s);
  lastctime = s.st_ctime;
  sleep(1);

  // do the actual chmod
  err = chmod("folder", 0300);
  assert(!err);
  memset(&s, 0, sizeof s);
  stat("folder", &s);
#if USE_OLD_FS
  assert(s.st_mode == (0222 | S_IFDIR));
#else
  assert(s.st_mode == (0300 | S_IFDIR));
#endif
  assert(s.st_ctime != lastctime);

  //
  // chmod a symlink's target
  //
  err = chmod("file-link", 0400);
  assert(!err);

  // make sure the file it references changed
  stat("file-link", &s);
#if USE_OLD_FS
  assert(s.st_mode == (0555 | S_IFREG));
#else
  assert(s.st_mode == (0400 | S_IFREG));
#endif

  // but the link didn't
  lstat("file-link", &s);
  assert(s.st_mode == (0777 | S_IFLNK));

  //
  // chmod the actual symlink
  //
  err = lchmod("file-link", 0500);
  assert(!err);

  // make sure the file it references didn't change
  stat("file-link", &s);
#if USE_OLD_FS
  assert(s.st_mode == (0555 | S_IFREG));
#else
  assert(s.st_mode == (0400 | S_IFREG));
#endif

  // but the link did
  lstat("file-link", &s);
#if USE_OLD_FS
  assert(s.st_mode == (0555 | S_IFLNK));
#else
  assert(s.st_mode == (0500 | S_IFLNK));
#endif

  puts("success");
}
Exemple #23
0
int
main(int argc, char *argv[])
{
    int ch, i, stdinflag = 0;
    char cflag = 0, mflag = 0;
    char *outfile, *outpath = NULL;
    struct field *fldtab;
    size_t fldtab_sz, fld_cnt;
    size_t alloc_size;
    struct filelist filelist;
    int num_input_files;
    FILE *outfp = NULL;
    struct rlimit rl;
    struct stat st;

    setlocale(LC_ALL, "");

    /* bump RLIMIT_NOFILE to maximum our hard limit allows */
    if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
        err(2, "getrlimit");
    rl.rlim_cur = rl.rlim_max;
    if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
        err(2, "setrlimit");

    d_mask[REC_D = '\n'] = REC_D_F;
    d_mask['\t'] = d_mask[' '] = BLANK | FLD_D;

    /* fldtab[0] is the global options. */
    fldtab_sz = 3;
    fld_cnt = 0;
    alloc_size = fldtab_sz * sizeof(*fldtab);
    fldtab = malloc(alloc_size);
    if (fldtab == NULL)
        err(1, "Cannot allocate %zu bytes", alloc_size);
    memset(fldtab, 0, alloc_size);

#define SORT_OPTS "bcdD:fHik:lmno:rR:sSt:T:ux"

    /* Convert "+field" args to -f format */
    fixit(&argc, argv, SORT_OPTS);

    if (!(tmpdir = getenv("TMPDIR")))
        tmpdir = _PATH_TMP;

    while ((ch = getopt(argc, argv, SORT_OPTS)) != -1) {
        switch (ch) {
        case 'b':
            fldtab[0].flags |= BI | BT;
            break;
        case 'c':
            cflag = 1;
            break;
        case 'D': /* Debug flags */
            for (i = 0; optarg[i]; i++)
                debug_flags |= 1 << (optarg[i] & 31);
            break;
        case 'd':
        case 'f':
        case 'i':
        case 'n':
        case 'l':
            fldtab[0].flags |= optval(ch, 0);
            break;
        case 'H':
            /* -H was ; use merge sort for blocks of large files' */
            /* That is now the default. */
            break;
        case 'k':
            alloc_size = (fldtab_sz + 1) * sizeof(*fldtab);
            fldtab = realloc(fldtab, alloc_size);
            if (fldtab == NULL)
                err(1, "Cannot re-allocate %zu bytes", alloc_size);
            memset(&fldtab[fldtab_sz], 0, sizeof(fldtab[0]));
            fldtab_sz++;

            setfield(optarg, &fldtab[++fld_cnt], fldtab[0].flags);
            break;
        case 'm':
            mflag = 1;
            break;
        case 'o':
            outpath = optarg;
            break;
        case 'r':
            REVERSE = 1;
            break;
        case 's':
            /*
             * Nominally 'stable sort', keep lines with equal keys
             * in input file order. (Default for NetBSD)
             * (-s for GNU sort compatibility.)
             */
            posix_sort = 0;
            break;
        case 'S':
            /*
             * Reverse of -s!
             * This needs to enforce a POSIX sort where records
             * with equal keys are then sorted by the raw data.
             * Currently not implemented!
             * (using libc radixsort() v sradixsort() doesn't
             * have the desired effect.)
             */
            posix_sort = 1;
            break;
        case 't':
            if (SEP_FLAG)
                usage("multiple field delimiters");
            SEP_FLAG = 1;
            d_mask[' '] &= ~FLD_D;
            d_mask['\t'] &= ~FLD_D;
            d_mask[(u_char)*optarg] |= FLD_D;
            if (d_mask[(u_char)*optarg] & REC_D_F)
                errx(2, "record/field delimiter clash");
            break;
        case 'R':
            if (REC_D != '\n')
                usage("multiple record delimiters");
            REC_D = *optarg;
            if (REC_D == '\n')
                break;
            if (optarg[1] != '\0') {
                char *ep;
                int t = 0;
                if (optarg[0] == '\\')
                    optarg++, t = 8;
                REC_D = (int)strtol(optarg, &ep, t);
                if (*ep != '\0' || REC_D < 0 ||
                        REC_D >= (int)__arraycount(d_mask))
                    errx(2, "invalid record delimiter %s",
                         optarg);
            }
            d_mask['\n'] = d_mask[' '];
            d_mask[REC_D] = REC_D_F;
            break;
        case 'T':
            /* -T tmpdir */
            tmpdir = optarg;
            break;
        case 'u':
            UNIQUE = 1;
            break;
        case '?':
        default:
            usage(NULL);
        }
    }

    if (UNIQUE)
        /* Don't sort on raw record if keys match */
        posix_sort = 0;

    if (cflag && argc > optind+1)
        errx(2, "too many input files for -c option");
    if (argc - 2 > optind && !strcmp(argv[argc-2], "-o")) {
        outpath = argv[argc-1];
        argc -= 2;
    }
    if (mflag && argc - optind > (MAXFCT - (16+1))*16)
        errx(2, "too many input files for -m option");

    for (i = optind; i < argc; i++) {
        /* allow one occurrence of /dev/stdin */
        if (!strcmp(argv[i], "-") || !strcmp(argv[i], _PATH_STDIN)) {
            if (stdinflag)
                warnx("ignoring extra \"%s\" in file list",
                      argv[i]);
            else
                stdinflag = 1;

            /* change to /dev/stdin if '-' */
            if (argv[i][0] == '-') {
                static char path_stdin[] = _PATH_STDIN;
                argv[i] = path_stdin;
            }

        } else if ((ch = access(argv[i], R_OK)))
            err(2, "%s", argv[i]);
    }

    if (fldtab[1].icol.num == 0) {
        /* No sort key specified */
        if (fldtab[0].flags & (I|D|F|N|L)) {
            /* Modified - generate a key that covers the line */
            fldtab[0].flags &= ~(BI|BT);
            setfield("1", &fldtab[++fld_cnt], fldtab->flags);
            fldreset(fldtab);
        } else {
            /* Unmodified, just compare the line */
            SINGL_FLD = 1;
            fldtab[0].icol.num = 1;
        }
    } else {
        fldreset(fldtab);
    }

    settables();

    if (optind == argc) {
        static const char * const names[] = { _PATH_STDIN, NULL };
        filelist.names = names;
        num_input_files = 1;
    } else {
        filelist.names = (const char * const *) &argv[optind];
        num_input_files = argc - optind;
    }

    if (cflag) {
        order(&filelist, fldtab);
        /* NOT REACHED */
    }

    if (!outpath) {
        toutpath[0] = '\0';	/* path not used in this case */
        outfile = outpath = toutpath;
        outfp = stdout;
    } else if (lstat(outpath, &st) == 0
               && !S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
        /* output file exists and isn't character or block device */
        struct sigaction act;
        static const int sigtable[] = {SIGHUP, SIGINT, SIGPIPE,
                                       SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, 0
                                      };
        int outfd;
        errno = 0;
        if (access(outpath, W_OK))
            err(2, "%s", outpath);
        (void)snprintf(toutpath, sizeof(toutpath), "%sXXXXXX",
                       outpath);
        if ((outfd = mkstemp(toutpath)) == -1)
            err(2, "Cannot create temporary file `%s'", toutpath);
        (void)atexit(cleanup);
        act.sa_handler = onsignal;
        (void) sigemptyset(&act.sa_mask);
        act.sa_flags = SA_RESTART | SA_RESETHAND;
        for (i = 0; sigtable[i]; ++i)	/* always unlink toutpath */
            sigaction(sigtable[i], &act, 0);
        outfile = toutpath;
        if ((outfp = fdopen(outfd, "w")) == NULL)
            err(2, "Cannot open temporary file `%s'", toutpath);
    } else {
        outfile = outpath;

        if ((outfp = fopen(outfile, "w")) == NULL)
            err(2, "output file %s", outfile);
    }

    if (mflag)
        fmerge(&filelist, num_input_files, outfp, fldtab);
    else
        fsort(&filelist, num_input_files, outfp, fldtab);

    if (outfile != outpath) {
        if (access(outfile, F_OK))
            err(2, "%s", outfile);

        /*
         * Copy file permissions bits of the original file.
         * st is initialized above, when we create the
         * temporary spool file.
         */
        if (lchmod(outfile, st.st_mode & ALLPERMS) != 0) {
            err(2, "cannot chmod %s: output left in %s",
                outpath, outfile);
        }

        (void)unlink(outpath);
        if (link(outfile, outpath))
            err(2, "cannot link %s: output left in %s",
                outpath, outfile);
        (void)unlink(outfile);
        toutpath[0] = 0;
    }
    exit(0);
}
Exemple #24
0
static void
miss(NODE *p, char *tail)
{
	int create;
	char *tp;
	const char *type;
	u_int32_t flags;

	for (; p; p = p->next) {
		if (p->flags & F_OPT && !(p->flags & F_VISIT))
			continue;
		if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
			continue;
		strcpy(tail, p->name);
		if (!(p->flags & F_VISIT))
			printf("missing: %s", path);
		switch (p->type) {
		case F_BLOCK:
		case F_CHAR:
			type = "device";
			break;
		case F_DIR:
			type = "directory";
			break;
		case F_LINK:
			type = "symlink";
			break;
		default:
			putchar('\n');
			continue;
		}

		create = 0;
		if (!(p->flags & F_VISIT) && uflag) {
			if (mtree_Wflag || p->type == F_LINK)
				goto createit;
			if (!(p->flags & (F_UID | F_UNAME)))
			    printf(
				" (%s not created: user not specified)", type);
			else if (!(p->flags & (F_GID | F_GNAME)))
			    printf(
				" (%s not created: group not specified)", type);
			else if (!(p->flags & F_MODE))
			    printf(
				" (%s not created: mode not specified)", type);
			else
 createit:
			switch (p->type) {
			case F_BLOCK:
			case F_CHAR:
				if (mtree_Wflag)
					continue;
				if (!(p->flags & F_DEV))
					printf(
				    " (%s not created: device not specified)",
					    type);
				else if (mknod(path,
				    p->st_mode | nodetoino(p->type),
				    p->st_rdev) == -1)
					printf(" (%s not created: %s)\n",
					    type, strerror(errno));
				else
					create = 1;
				break;
			case F_LINK:
				if (!(p->flags & F_SLINK))
					printf(
				    " (%s not created: link not specified)\n",
					    type);
				else if (symlink(p->slink, path))
					printf(
					    " (%s not created: %s)\n",
					    type, strerror(errno));
				else
					create = 1;
				break;
			case F_DIR:
				if (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO))
					printf(" (not created: %s)",
					    strerror(errno));
				else
					create = 1;
				break;
			default:
				mtree_err("can't create create %s",
				    nodetype(p->type));
			}
		}
		if (create)
			printf(" (created)");
		if (p->type == F_DIR) {
			if (!(p->flags & F_VISIT))
				putchar('\n');
			for (tp = tail; *tp; ++tp)
				continue;
			*tp = '/';
			miss(p->child, tp + 1);
			*tp = '\0';
		} else
			putchar('\n');

		if (!create || mtree_Wflag)
			continue;
		if ((p->flags & (F_UID | F_UNAME)) &&
		    (p->flags & (F_GID | F_GNAME)) &&
		    (lchown(path, p->st_uid, p->st_gid))) {
			printf("%s: user/group/mode not modified: %s\n",
			    path, strerror(errno));
			printf("%s: warning: file mode %snot set\n", path,
			    (p->flags & F_FLAGS) ? "and file flags " : "");
			continue;
		}
		if (p->flags & F_MODE) {
			if (lchmod(path, p->st_mode))
				printf("%s: permissions not set: %s\n",
				    path, strerror(errno));
		}
#if HAVE_STRUCT_STAT_ST_FLAGS
		if ((p->flags & F_FLAGS) && p->st_flags) {
			if (iflag)
				flags = p->st_flags;
			else
				flags = p->st_flags & ~SP_FLGS;
			if (lchflags(path, flags))
				printf("%s: file flags not set: %s\n",
				    path, strerror(errno));
		}
#endif	/* HAVE_STRUCT_STAT_ST_FLAGS */
	}
}
Exemple #25
0
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);
}
Exemple #26
0
void
set_file_attributes (char const *to, enum file_attributes attr,
		     char const *from, const struct stat *st, mode_t mode,
		     struct timespec *new_time)
{
  if (attr & FA_TIMES)
    {
      struct timespec times[2];
      if (new_time)
	times[0] = times[1] = *new_time;
      else
        {
	  times[0] = get_stat_atime (st);
	  times[1] = get_stat_mtime (st);
	}
      if (lutimens (to, times) != 0)
	pfatal ("Failed to set the timestamps of %s %s",
		S_ISLNK (mode) ? "symbolic link" : "file",
		quotearg (to));
    }
  if (attr & FA_IDS)
    {
      static uid_t euid = -1;
      static gid_t egid = -1;
      uid_t uid;
      uid_t gid;

      if (euid == -1)
        {
	  euid = geteuid ();
	  egid = getegid ();
	}
      uid = (euid == st->st_uid) ? -1 : st->st_uid;
      gid = (egid == st->st_gid) ? -1 : st->st_gid;

      /* May fail if we are not privileged to set the file owner, or we are
         not in group instat.st_gid.  Ignore those errors.  */
      if ((uid != -1 || gid != -1)
	  && lchown (to, uid, gid) != 0
	  && (errno != EPERM
	      || (uid != -1
		  && lchown (to, (uid = -1), gid) != 0
		  && errno != EPERM)))
	pfatal ("Failed to set the %s of %s %s",
		(uid == -1) ? "owner" : "owning group",
		S_ISLNK (mode) ? "symbolic link" : "file",
		quotearg (to));
    }
  if (attr & FA_XATTRS)
    if (copy_attr (from, to) != 0
	&& errno != ENOSYS && errno != ENOTSUP && errno != EPERM)
      fatal_exit (0);
  if (attr & FA_MODE)
    {
#if 0 && defined HAVE_LCHMOD
      /* The "diff --git" format does not store the file permissions of
	 symlinks, so don't try to set symlink file permissions even on
	 systems where we could.  */
      if (lchmod (to, mode))
#else
      if (! S_ISLNK (mode) && chmod (to, mode) != 0)
#endif
	pfatal ("Failed to set the permissions of %s %s",
		S_ISLNK (mode) ? "symbolic link" : "file",
		quotearg (to));
    }
}
Exemple #27
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);
}
Exemple #28
0
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	long long flags;
	unsigned int i;
	char *endp;
	int name, rval;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];
#ifdef HAS_FREEBSD_ACL
	int entry_id = ACL_FIRST_ENTRY;
	acl_t acl, newacl;
	acl_entry_t entry, newentry;
#endif

	/*
	 * 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_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), (int)flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_OPENAT:
		flags = str2flags(open_flags, STR(2));
		if (flags & O_CREAT) {
			if (i == 3) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags,
			    (mode_t)NUM(3));
		} else {
			if (i == 4) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
		if (rval >= 0)
			close(rval);
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_UNLINKAT:
		rval = unlinkat(NUM(0), STR(1),
		    (int)str2flags(unlinkat_flags, STR(2)));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKDIRAT:
		rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_LINKAT:
		rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
		    (int)str2flags(linkat_flags, STR(4)));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_SYMLINKAT:
		rval = symlinkat(STR(0), NUM(1), STR(2));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_RENAMEAT:
		rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKFIFOAT:
		rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
		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;
	    }
	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;
	    }
#ifdef HAS_BINDAT
	case ACTION_BINDAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), 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 = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CONNECT:
	    {
		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 = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_CONNECTAT
	case ACTION_CONNECTAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), 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 = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CHMOD:
		rval = chmod(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_FCHMOD:
		rval = fchmod(NUM(0), (mode_t)NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), (mode_t)NUM(1));
		break;
#endif
	case ACTION_FCHMODAT:
		rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
		    str2flags(fchmodat_flags, STR(3)));
		break;
	case ACTION_CHOWN:
		rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWN:
		rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWNAT:
		rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
		    (int)str2flags(fchownat_flags, STR(4)));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_FCHFLAGS
	case ACTION_FCHFLAGS:
		rval = fchflags(NUM(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_CHFLAGSAT
	case ACTION_CHFLAGSAT:
		rval = chflagsat(NUM(0), STR(1),
		    (unsigned long)str2flags(chflags_flags, STR(2)),
		    (int)str2flags(chflagsat_flags, STR(3)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0),
		    (unsigned long)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_FSTAT:
		rval = fstat64(NUM(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_FSTATAT:
		rval = fstatat(NUM(0), STR(1), &sb,
		    (int)str2flags(fstatat_flags, STR(2)));
		if (rval == 0) {
			show_stats(&sb, STR(3));
			return (i);
		}
		break;
	case ACTION_PATHCONF:
	case ACTION_FPATHCONF:
	case ACTION_LPATHCONF:
	    {
		long lrval;

		name = str2name(pathconf_names, STR(1));
		if (name == -1) {
			fprintf(stderr, "unknown name %s", STR(1));
			exit(1);
		}
		errno = 0;
		switch (scall->sd_action) {
		case ACTION_PATHCONF:
			lrval = pathconf(STR(0), name);
			break;
		case ACTION_FPATHCONF:
			lrval = fpathconf(NUM(0), name);
			break;
		case ACTION_LPATHCONF:
			lrval = lpathconf(STR(0), name);
			break;
		default:
			abort();
		}
		if (lrval == -1 && errno == 0) {
			printf("unlimited\n");
			return (i);
		} else if (lrval >= 0) {
			printf("%ld\n", lrval);
			return (i);
		}
		rval = -1;
		break;
	    }
#ifdef HAS_FREEBSD_ACL
	case ACTION_PREPENDACL:
		rval = -1;

		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			break;

		newacl = acl_from_text(STR(1));
		if (acl == NULL)
			break;

		while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
			entry_id = ACL_NEXT_ENTRY;

			if (acl_create_entry_np(&acl, &entry, 0))
				break;

			if (acl_copy_entry(entry, newentry))
				break;
		}

		rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
		break;
	case ACTION_READACL:
		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			rval = -1;
		else
			rval = 0;
		break;
#endif
	case ACTION_WRITE:
		rval = write(NUM(0), STR(1), strlen(STR(1)));
		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);
}
Exemple #29
0
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 */
}
static void
convert_spamd_db(int dbformat)
{
    char*       tsfn = NULL;
    int         r, fd = -1;
    u_int32_t   count = 0;
    DB          *db1, *db2;
    BTREEINFO   btreeinfo;
    HASHINFO    hashinfo_odb, hashinfo_ndb;
    DBT         dbk, dbd;
    time_t      t_start, t_end;

    if (verbose)
        /* print details for input database */
        printf ("in : %-20s uid: %-4d gid: %-4d mode %04o format: %-5s "
           "size: %-10u (%.3f MiB)\n", PATH_SPAMD_DB, (int)statbuf_in.st_uid,
           (int)statbuf_in.st_gid, statbuf_in.st_mode & 0777,
           dbformat == DBHASH ? "hash" : "btree", (u_int)statbuf_in.st_size,
           (double)statbuf_in.st_size / (1024 * 1024));

    if (dbformat == DBBTREE){
        replace = 0; /* no replace if source db is in btree format */
        /* try to open the db as a BTREE */
        memset(&btreeinfo, 0, sizeof(btreeinfo));
        db1 = dbopen(PATH_SPAMD_DB, O_EXLOCK|O_RDWR, 0600, DB_BTREE, &btreeinfo);
    }
    else {
        /* DB is already in hash format */
        memset(&hashinfo_odb, 0, sizeof(hashinfo_odb));
        db1 = dbopen(PATH_SPAMD_DB, O_EXLOCK|O_RDWR, 0600, DB_HASH, &hashinfo_odb);
    }

    if (db1 == NULL) {
    if (errno == EACCES) {
        syslog_r(LOG_ERR, &sdata,
        "can't open %s in RW mode for UID %d (%m)", PATH_SPAMD_DB, geteuid() );
        err(1, "can't open %s in RW mode for UID %d", PATH_SPAMD_DB, geteuid() );
    }
    else
        syslog_r(LOG_ERR, &sdata,
        "corrupt db in %s, remove and restart (%m)", PATH_SPAMD_DB);
        err(1, "corrupt db in %s, remove and restart", PATH_SPAMD_DB );
    exit(1);
    }

    if ((fd = mkstemp(sfn)) == -1) {
        syslog_r(LOG_ERR, &sdata,
            "can't process %s: mkstemp failed. UID: %d (%m)", PATH_SPAMD_DB, geteuid());
        err(1, "can't process %s: mkstemp failed. UID: %d", PATH_SPAMD_DB, geteuid());
    }

    memset(&hashinfo_ndb, 0, sizeof(hashinfo_ndb));
    db2 = dbopen(sfn, O_EXLOCK|O_RDWR|O_CREAT, 0600, DB_HASH, &hashinfo_ndb);
    if (db2 == NULL) {
        unlink(sfn);
        syslog_r(LOG_ERR, &sdata,
            "can't convert %s: can't dbopen %s (%m)", PATH_SPAMD_DB, sfn);
        db1->close(db1);
        exit(1);
    }

    if (verbose) {
        if (dbformat == DBBTREE)
            printf("convert %s from btree to hash format\n", PATH_SPAMD_DB);
        else
            printf("start reorganization of %s...\n", PATH_SPAMD_DB);
    }

    time(&t_start);
    memset(&dbk, 0, sizeof(dbk));
    memset(&dbd, 0, sizeof(dbd));
    for (r = db1->seq(db1, &dbk, &dbd, R_FIRST); !r;
        r = db1->seq(db1, &dbk, &dbd, R_NEXT)) {
        if (db2->put(db2, &dbk, &dbd, 0)) {
            db2->sync(db2, 0);
            db2->close(db2);
            db1->close(db1);
            unlink(sfn);
            syslog_r(LOG_ERR, &sdata,
                "can't convert %s - remove and restart", PATH_SPAMD_DB);
            exit(1);
        }
        count++;
        if (verbose){
            if ((count % 100) == 0) {
                printf("\rprogress %7u records", count);
                fflush(stdout);
            }
        }
    }
    db2->sync(db2, 0);
    db2->close(db2);
    db1->sync(db1, 0);
    db1->close(db1);

    time(&t_end);
    syslog_r(LOG_INFO, &sdata, "progress %u records: in %.f second(s)",
        count, difftime(t_end, t_start) );

    if (verbose)
        printf("\rprogress %7u records: -> finish in %.f second(s)\n", count,
            difftime(t_end, t_start) );

    if (replace) {
        rename(sfn, PATH_SPAMD_DB);
        tsfn = PATH_SPAMD_DB;
    }
    else {
        rename(sfn, PATH_REORG_DB);
        tsfn = PATH_REORG_DB;
    }

    close(fd);

    /* change owner to _spamd */
    if (pw && (chown(tsfn, pw->pw_uid, pw->pw_gid) == -1)) {
        syslog_r(LOG_ERR, &sdata, "chown %s failed (%m)", tsfn);
        exit(1);
    }
    /* restore file access mode */
    if (lchmod(tsfn, statbuf_in.st_mode) == -1) {
        syslog_r(LOG_ERR, &sdata, "chmod %s failed (%m)", tsfn);
        printf ("chmod %s faild (%s)\n", tsfn, strerror(errno));
        exit(1);
    }

    r = lstat(tsfn, &statbuf_out);
    if (r != -1) {
        if (replace)
            syslog_r(LOG_INFO, &sdata, "replace %s with reorganized db. "
                "old size %u (%.3f MiB), new size: %u (%.3f MiB)",
                PATH_SPAMD_DB, (u_int)statbuf_in.st_size,
                (double)statbuf_in.st_size / (1024 * 1024),
                (u_int)statbuf_out.st_size,
                (double)statbuf_out.st_size / (1024 * 1024));
        else
            syslog_r(LOG_INFO, &sdata, "%s db finished, "
                "size %s : %u (%.3f MiB), new size %s: %u (%.3f MiB)",
                dbformat == DBHASH ? "reorganize" : "convert",
                PATH_SPAMD_DB, (u_int)statbuf_in.st_size,
                (double)statbuf_in.st_size / (1024 * 1024),
                tsfn, (u_int)statbuf_out.st_size,
                (double)statbuf_out.st_size / (1024 * 1024));

        if (verbose) {
            /* print details for output database */
            printf ("out: %-20s uid: %-4d gid: %-4d mode %04o format: %-5s "
                "size: %-10u (%.3f MiB)\n", tsfn, (int)statbuf_out.st_uid,
                (int)statbuf_out.st_gid, statbuf_out.st_mode & 0777,
                "hash", (u_int)statbuf_out.st_size,
                (double)statbuf_out.st_size / (1024 * 1024) );
        }
    }
}