Exemple #1
0
static void
setfile(const char *name, struct stat *fs)
{
	static struct timespec tspec[2];

	fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;

	tspec[0] = fs->st_atim;
	tspec[1] = fs->st_mtim;
	if (utimensat(AT_FDCWD, name, tspec, 0))
		cwarn("utimensat: %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);
}
static int process_utimes(const char *path, struct timespec *at,
			  struct timespec *mt, struct timespec *ct,
			  void *user)
{
	int ret = 0;
	struct btrfs_receive *r = user;
	char full_path[PATH_MAX];
	struct timespec tv[2];

	ret = path_cat_out(full_path, r->full_subvol_path, path);
	if (ret < 0) {
		error("utimes: path invalid: %s", path);
		goto out;
	}

	if (g_verbose >= 2)
		fprintf(stderr, "utimes %s\n", path);

	tv[0] = *at;
	tv[1] = *mt;
	ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
	if (ret < 0) {
		ret = -errno;
		error("utimes %s failed: %s",
				path, strerror(-ret));
		goto out;
	}

out:
	return ret;
}
Exemple #3
0
int serv_touch(char *arg)
{
	char corr[40];

	if (!arg || !arg[0])
		return serv_list(NULL);

	if (!strstr(arg, ".conf")) {
		snprintf(corr, sizeof(corr), "%s.conf", arg);
		arg = corr;
	}

	pushd(FINIT_RCSD);
	if (!fexist(arg)) {
		popd();
		if (!strstr(arg, "finit.conf"))
			errx(1, "Service %s is not enabled", arg);
		arg = FINIT_CONF;
	}

	/* libite:touch() follows symlinks */
	if (utimensat(AT_FDCWD, arg, NULL, AT_SYMLINK_NOFOLLOW))
		err(1, "Failed marking %s for reload", arg);

	return 0;
}
void sys_stat_check_functions()
{
    (void)chmod((const char *)1234, (mode_t)0);
    (void)fchmod(0, (mode_t)0);
#if HAVE_XXXAT
    (void)fchmodat(0, (const char *)1234, (mode_t)0, 0);
#endif
    (void)fstat(0, (struct stat *)1234);
#if HAVE_XXXAT
    (void)fstatat(0, (const char *)1234, (struct stat *)1234, 0);
#endif
    (void)futimens(0, (const struct timespec *)1234);
    (void)lstat((const char *)1234, (struct stat *)1234);
    (void)mkdir((const char *)1234, (mode_t)0);
#if HAVE_XXXAT
    (void)mkdirat(0, (const char *)1234, (mode_t)0);
#endif
    (void)mkfifo((const char *)1234, (mode_t)0);
    (void)mkfifoat(0, (const char *)1234, (mode_t)0);
    (void)mknod((const char *)1234, (mode_t)0, (dev_t)0);
    (void)mknodat(0, (const char *)1234, (mode_t)0, (dev_t)0);
    (void)stat((const char *)1234, (struct stat *)1234);
    (void)umask((mode_t)0);
    (void)utimensat(0, (const char *)1234, (const struct timespec *)1234, 0);
}
Exemple #5
0
void DCOPY_copy_timestamps(
    bayer_flist flist,
    uint64_t idx,
    const char* dest_path)
{
    /* get atime seconds and nsecs */
    uint64_t atime      = bayer_flist_file_get_atime(flist, idx);
    uint64_t atime_nsec = bayer_flist_file_get_atime_nsec(flist, idx);

    /* get mtime seconds and nsecs */
    uint64_t mtime      = bayer_flist_file_get_mtime(flist, idx);
    uint64_t mtime_nsec = bayer_flist_file_get_mtime_nsec(flist, idx);

    /* fill in time structures */
    struct timespec times[2];
    times[0].tv_sec  = (time_t) atime;
    times[0].tv_nsec = (long)   atime_nsec;
    times[1].tv_sec  = (time_t) mtime;
    times[1].tv_nsec = (long)   mtime_nsec;

    /* set times with nanosecond precision using utimensat,
     * assume path is relative to current working directory,
     * if it's not absolute, and set times on link (not target file)
     * if dest_path refers to a link */
    if(utimensat(AT_FDCWD, dest_path, times, AT_SYMLINK_NOFOLLOW) != 0) {
        BAYER_LOG(BAYER_LOG_ERR, "Failed to change timestamps on %s utime() errno=%d %s",
                  dest_path, errno, strerror(errno)
                 );
    }

#if 0
    /* TODO: see stat-time.h and get_stat_atime/mtime/ctime to read sub-second times,
     * and use utimensat to set sub-second times */
    /* as last step, change timestamps */
    if(! S_ISLNK(statbuf->st_mode)) {
        struct utimbuf times;
        times.actime  = statbuf->st_atime;
        times.modtime = statbuf->st_mtime;
        if(utime(dest_path, &times) != 0) {
            BAYER_LOG(BAYER_LOG_ERR, "Failed to change timestamps on %s utime() errno=%d %s",
                      dest_path, errno, strerror(errno)
                     );
        }
    }
    else {
        struct timeval tv[2];
        tv[0].tv_sec  = statbuf->st_atime;
        tv[0].tv_usec = 0;
        tv[1].tv_sec  = statbuf->st_mtime;
        tv[1].tv_usec = 0;
        if(lutimes(dest_path, tv) != 0) {
            BAYER_LOG(BAYER_LOG_ERR, "Failed to change timestamps on %s utime() errno=%d %s",
                      dest_path, errno, strerror(errno)
                     );
        }
    }
#endif

    return;
}
Exemple #6
0
static int apply_timestamp(const char *path, struct timespec *ts) {
        struct timespec twice[2] = {
                *ts,
                *ts
        };
        struct stat st;

        assert(path);
        assert(ts);

        if (stat(path, &st) >= 0) {
                /* Is the timestamp file already newer than the OS? If
                 * so, there's nothing to do. We ignore the nanosecond
                 * component of the timestamp, since some file systems
                 * do not support any better accuracy than 1s and we
                 * have no way to identify the accuracy
                 * available. Most notably ext4 on small disks (where
                 * 128 byte inodes are used) does not support better
                 * accuracy than 1s. */
                if (st.st_mtim.tv_sec > ts->tv_sec)
                        return 0;

                /* It is older? Then let's update it */
                if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) {

                        if (errno == EROFS)
                                return log_debug("Can't update timestamp file %s, file system is read-only.", path);

                        return log_error_errno(errno, "Failed to update timestamp on %s: %m", path);
                }

        } else if (errno == ENOENT) {
                _cleanup_close_ int fd = -1;
                int r;

                /* The timestamp file doesn't exist yet? Then let's create it. */

                r = mac_selinux_create_file_prepare(path, S_IFREG);
                if (r < 0)
                        return log_error_errno(r, "Failed to set SELinux context for %s: %m", path);

                fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
                mac_selinux_create_file_clear();

                if (fd < 0) {
                        if (errno == EROFS)
                                return log_debug("Can't create timestamp file %s, file system is read-only.", path);

                        return log_error_errno(errno, "Failed to create timestamp file %s: %m", path);
                }

                (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false);

                if (futimens(fd, twice) < 0)
                        return log_error_errno(errno, "Failed to update timestamp on %s: %m", path);
        } else
                log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path);

        return 0;
}
Exemple #7
0
/*
 * Check if @path is on read-only filesystem independently on file permissions.
 */
int mnt_is_readonly(const char *path)
{
	if (access(path, W_OK) == 0)
		return 0;
	if (errno == EROFS)
		return 1;
	if (errno != EACCES)
		return 0;

#ifdef HAVE_FUTIMENS
	/*
	 * access(2) returns EACCES on read-only FS:
	 *
	 * - for set-uid application if one component of the path is not
	 *   accessible for the current rUID. (Note that euidaccess(2) does not
	 *   check for EROFS at all).
	 *
	 * - for read-write filesystem with read-only VFS node (aka -o remount,ro,bind)
	 */
	{
		struct timespec times[2];

		times[0].tv_nsec = UTIME_NOW;	/* atime */
		times[1].tv_nsec = UTIME_OMIT;	/* mtime */

		if (utimensat(AT_FDCWD, path, times, 0) == -1)
			return errno == EROFS;
	}
#endif
	return 0;
}
Exemple #8
0
void
psync_utimes(const char *fn, const struct pfl_timespec *pts, int flags)
{
#ifdef HAVE_FUTIMENS
	struct timespec ts[2];

	ts[0].tv_sec = pts[0].tv_sec;
	ts[0].tv_nsec = pts[0].tv_nsec;

	ts[1].tv_sec = pts[1].tv_sec;
	ts[1].tv_nsec = pts[1].tv_nsec;

	if (utimensat(AT_FDCWD, fn, ts, flags) == -1)
		psynclog_warn("utimes %s", fn);
#else
	struct timeval tv[2];

	(void)flags;

	tv[0].tv_sec = pts[0].tv_sec;
	tv[0].tv_usec = pts[0].tv_nsec / 1000;

	tv[1].tv_sec = pts[1].tv_sec;
	tv[1].tv_usec = pts[1].tv_nsec / 1000;

	if (lutimes(fn, tv) == -1)
		psynclog_warn("utimes %s", fn);
#endif
}
/* SELinux uses PCRE pre-compiled regexps for binary caches, which can
 * fail if the version of PCRE on the host differs from the version
 * which generated the cache (in the target root).
 *
 * Note also this function is probably already broken in Fedora
 * 23+ from https://bugzilla.redhat.com/show_bug.cgi?id=1265406
 */
static gboolean
workaround_selinux_cross_labeling_recurse (int            dfd,
        const char    *path,
        GCancellable  *cancellable,
        GError       **error)
{
    gboolean ret = FALSE;
    g_auto(GLnxDirFdIterator) dfd_iter = { 0, };

    if (!glnx_dirfd_iterator_init_at (dfd, path, TRUE, &dfd_iter, error))
        goto out;

    while (TRUE)
    {
        struct dirent *dent = NULL;
        const char *name;

        if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
            goto out;

        if (!dent)
            break;

        name = dent->d_name;

        if (dent->d_type == DT_DIR)
        {
            if (!workaround_selinux_cross_labeling_recurse (dfd_iter.fd, name, cancellable, error))
                goto out;
        }
        else if (g_str_has_suffix (name, ".bin"))
        {
            struct stat stbuf;
            const char *lastdot;
            gs_free char *nonbin_name = NULL;

            if (TEMP_FAILURE_RETRY (fstatat (dfd_iter.fd, name, &stbuf, AT_SYMLINK_NOFOLLOW)) != 0)
            {
                glnx_set_error_from_errno (error);
                goto out;
            }

            lastdot = strrchr (name, '.');
            g_assert (lastdot);

            nonbin_name = g_strndup (name, lastdot - name);

            g_print ("Setting mtime of '%s' to newer than '%s'\n", nonbin_name, name);
            if (TEMP_FAILURE_RETRY (utimensat (dfd_iter.fd, nonbin_name, NULL, 0)) == -1)
            {
                glnx_set_error_from_errno (error);
                goto out;
            }
        }
    }

    ret = TRUE;
out:
    return ret;
}
Exemple #10
0
static void
touch(const char *file)
{
	int fd;
	struct stat st;
	int r;

	if ((r = stat(file, &st)) < 0) {
		if (errno != ENOENT)
			eprintf("stat %s:", file);
		if (cflag)
			return;
	} else if (!r) {
		if (!aflag)
			times[0] = st.st_atim;
		if (!mflag)
			times[1] = st.st_mtim;
		if (utimensat(AT_FDCWD, file, times, 0) < 0)
			eprintf("utimensat %s:", file);
		return;
	}

	if ((fd = open(file, O_CREAT | O_EXCL, 0644)) < 0)
		eprintf("open %s:", file);
	close(fd);

	touch(file);
}
static int process_utimes(const char *path, struct timespec *at,
			  struct timespec *mt, struct timespec *ct,
			  void *user)
{
	int ret = 0;
	struct btrfs_receive *r = user;
	char *full_path = path_cat(r->full_subvol_path, path);
	struct timespec tv[2];

	if (g_verbose >= 2)
		fprintf(stderr, "utimes %s\n", path);

	tv[0] = *at;
	tv[1] = *mt;
	ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
	if (ret < 0) {
		ret = -errno;
		fprintf(stderr, "ERROR: utimes %s failed. %s\n",
				path, strerror(-ret));
		goto out;
	}

out:
	free(full_path);
	return ret;
}
Exemple #12
0
void
set_ftime(char *fnm, time_t mtime, time_t atime, int frc)
{
	struct timespec tv[2];

	tv[0].tv_sec = atime;
	tv[0].tv_nsec = 0L;
	tv[1].tv_sec = mtime;
	tv[1].tv_nsec = 0L;
	if (!frc) {
		/*
		 * if we are not forcing, only set those times the user wants
		 * set.
		 */
		if (!patime)
			tv[0].tv_nsec = UTIME_OMIT;
		if (!pmtime)
			tv[1].tv_nsec = UTIME_OMIT;
	}

	/*
	 * set the times
	 */
	if (utimensat(AT_FDCWD, fnm, tv, AT_SYMLINK_NOFOLLOW) < 0)
		syswarn(1, errno, "Access/modification time set failed on: %s",
		    fnm);
}
Exemple #13
0
/**
 * mbox_path_probe - Is this an mbox mailbox? - Implements MxOps::path_probe()
 */
enum MailboxType mbox_path_probe(const char *path, const struct stat *st)
{
  if (!path || !st)
    return MUTT_UNKNOWN;

  if (S_ISDIR(st->st_mode))
    return MUTT_UNKNOWN;

  if (st->st_size == 0)
    return MUTT_MBOX;

  FILE *fp = fopen(path, "r");
  if (!fp)
    return MUTT_UNKNOWN;

  int ch;
  while ((ch = fgetc(fp)) != EOF)
  {
    /* Some mailbox creation tools erroneously append a blank line to
     * a file before appending a mail message.  This allows neomutt to
     * detect magic for and thus open those files. */
    if ((ch != '\n') && (ch != '\r'))
    {
      ungetc(ch, fp);
      break;
    }
  }

  enum MailboxType magic = MUTT_UNKNOWN;
  char tmp[256];
  if (fgets(tmp, sizeof(tmp), fp))
  {
    if (mutt_str_startswith(tmp, "From ", CASE_MATCH))
      magic = MUTT_MBOX;
    else if (mutt_str_strcmp(tmp, MMDF_SEP) == 0)
      magic = MUTT_MMDF;
  }
  mutt_file_fclose(&fp);

  if (!C_CheckMboxSize)
  {
    /* need to restore the times here, the file was not really accessed,
     * only the type was accessed.  This is important, because detection
     * of "new mail" depends on those times set correctly.  */
#ifdef HAVE_UTIMENSAT
    struct timespec ts[2];
    mutt_file_get_stat_timespec(&ts[0], &st, MUTT_STAT_ATIME);
    mutt_file_get_stat_timespec(&ts[1], &st, MUTT_STAT_MTIME);
    utimensat(0, path, ts, 0);
#else
    struct utimbuf times;
    times.actime = st->st_atime;
    times.modtime = st->st_mtime;
    utime(path, &times);
#endif
  }

  return magic;
}
Exemple #14
0
int stream_utimens(const char *path, const struct timespec tv[2])
{
    int rc;
    drop_privilege();
    rc = (utimensat(-1, fixpath(path), tv, 0)) ? -errno : 0;
    regain_privilege();
    return rc;
}
Exemple #15
0
int
main(void)
{
	static const char fname[] = "utimensat\nfilename";

	assert(utimensat(AT_FDCWD, fname, NULL, 0) == -1);
	if (ENOENT != errno)
		error_msg_and_skip("utimensat");

	#define PREFIX "utimensat(AT_FDCWD, \"utimensat\\nfilename\", "
	printf(PREFIX "NULL, 0) = -1 ENOENT (%m)\n");

	struct timeval tv;
	struct timespec ts[2];

	if (gettimeofday(&tv, NULL))
		perror_msg_and_skip("gettimeofday");

	ts[0].tv_sec = tv.tv_sec;
	ts[0].tv_nsec = tv.tv_usec;
	ts[1].tv_sec = tv.tv_sec - 1;
	ts[1].tv_nsec = tv.tv_usec + 1;

	printf(PREFIX "[");
	print_ts(&ts[0]);
	printf(", ");
	print_ts(&ts[1]);
	printf("], AT_SYMLINK_NOFOLLOW) = -1 ENOENT ");

	assert(utimensat(AT_FDCWD, fname, ts, AT_SYMLINK_NOFOLLOW) == -1);
	if (ENOENT != errno)
		error_msg_and_skip("utimensat");
	printf("(%m)\n");

	ts[0].tv_nsec = UTIME_NOW;
	ts[1].tv_nsec = UTIME_OMIT;
	assert(utimensat(AT_FDCWD, fname, ts, AT_SYMLINK_NOFOLLOW) == -1);
	if (ENOENT != errno)
		error_msg_and_skip("utimensat");
	printf(PREFIX "[UTIME_NOW, UTIME_OMIT], AT_SYMLINK_NOFOLLOW)"
	       " = -1 ENOENT (%m)\n");

	puts("+++ exited with 0 +++");
	return 0;
}
Exemple #16
0
static int xmp_utimens(const char *path, const struct timespec ts[2])
{
        int res;
        /* don't use utime/utimes since they follow symlinks */
        res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
        if (res == -1)
                return -errno;
        return 0;
}
Exemple #17
0
int lutimes(const char *filename, const struct timeval tv[2])
{
	struct timespec times[2];
	times[0].tv_sec  = tv[0].tv_sec;
	times[0].tv_nsec = tv[0].tv_usec * 1000;
	times[1].tv_sec  = tv[1].tv_sec;
	times[1].tv_nsec = tv[1].tv_usec * 1000;
	return utimensat(AT_FDCWD, filename, times, AT_SYMLINK_NOFOLLOW);
}
Exemple #18
0
ATF_TC_BODY(utimensat_fderr1, tc)
{
	int dfd;

	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
	ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1);
	ATF_REQUIRE(utimensat(dfd, FILEERR, tptr, 0) == -1);
	ATF_REQUIRE(close(dfd) == 0);
}
static int apply_timestamp(const char *path, struct timespec *ts) {
        struct timespec twice[2];
        struct stat st;

        assert(path);
        assert(ts);

        if (stat(path, &st) >= 0) {
                /* Is the timestamp file already newer than the OS? If so, there's nothing to do. */
                if (st.st_mtim.tv_sec > ts->tv_sec ||
                    (st.st_mtim.tv_sec == ts->tv_sec && st.st_mtim.tv_nsec >= ts->tv_nsec))
                        return 0;

                /* It is older? Then let's update it */
                twice[0] = *ts;
                twice[1] = *ts;

                if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) {

                        if (errno == EROFS)
                                return log_debug("Can't update timestamp file %s, file system is read-only.", path);

                        return log_error_errno(errno, "Failed to update timestamp on %s: %m", path);
                }

        } else if (errno == ENOENT) {
                _cleanup_close_ int fd = -1;
                int r;

                /* The timestamp file doesn't exist yet? Then let's create it. */

                r = mac_selinux_create_file_prepare(path, S_IFREG);
                if (r < 0)
                        return log_error_errno(r, "Failed to set SELinux context for %s: %m", path);

                fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
                mac_selinux_create_file_clear();

                if (fd < 0) {
                        if (errno == EROFS)
                                return log_debug("Can't create timestamp file %s, file system is read-only.", path);

                        return log_error_errno(errno, "Failed to create timestamp file %s: %m", path);
                }

                (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false);

                twice[0] = *ts;
                twice[1] = *ts;

                if (futimens(fd, twice) < 0)
                        return log_error_errno(errno, "Failed to update timestamp on %s: %m", path);
        } else
                log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path);

        return 0;
}
static int handle_setattr(struct fuse* fuse, struct fuse_handler* handler,
        const struct fuse_in_header *hdr, const struct fuse_setattr_in *req)
{
    struct node* node;
    char path[PATH_MAX];
    struct timespec times[2];

    pthread_mutex_lock(&fuse->lock);
    node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path));
    TRACE("[%d] SETATTR fh=%llx valid=%x @ %llx (%s)\n", handler->token,
            req->fh, req->valid, hdr->nodeid, node ? node->name : "?");
    pthread_mutex_unlock(&fuse->lock);

    if (!node) {
        return -ENOENT;
    }

    /* XXX: incomplete implementation on purpose.
     * chmod/chown should NEVER be implemented.*/

    if ((req->valid & FATTR_SIZE) && truncate(path, req->size) < 0) {
        return -errno;
    }

    /* Handle changing atime and mtime.  If FATTR_ATIME_and FATTR_ATIME_NOW
     * are both set, then set it to the current time.  Else, set it to the
     * time specified in the request.  Same goes for mtime.  Use utimensat(2)
     * as it allows ATIME and MTIME to be changed independently, and has
     * nanosecond resolution which fuse also has.
     */
    if (req->valid & (FATTR_ATIME | FATTR_MTIME)) {
        times[0].tv_nsec = UTIME_OMIT;
        times[1].tv_nsec = UTIME_OMIT;
        if (req->valid & FATTR_ATIME) {
            if (req->valid & FATTR_ATIME_NOW) {
              times[0].tv_nsec = UTIME_NOW;
            } else {
              times[0].tv_sec = req->atime;
              times[0].tv_nsec = req->atimensec;
            }
        }
        if (req->valid & FATTR_MTIME) {
            if (req->valid & FATTR_MTIME_NOW) {
              times[1].tv_nsec = UTIME_NOW;
            } else {
              times[1].tv_sec = req->mtime;
              times[1].tv_nsec = req->mtimensec;
            }
        }
        TRACE("[%d] Calling utimensat on %s with atime %ld, mtime=%ld\n",
                handler->token, path, times[0].tv_sec, times[1].tv_sec);
        if (utimensat(-1, path, times, 0) < 0) {
            return -errno;
        }
    }
    return fuse_reply_attr(fuse, hdr->unique, hdr->nodeid, path);
}
Exemple #21
0
ATF_TC_BODY(utimensat_fderr3, tc)
{
	int fd;

	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
	ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
	ATF_REQUIRE(close(fd) == 0);

	ATF_REQUIRE(utimensat(-1, FILE, tptr, 0) == -1);
}
Exemple #22
0
static int pifs_utimens(const char *path, const struct timespec times[2])
{
  DIR *dir = opendir(options.mdd);
  if (!dir) {
    return -errno;
  }
  int ret = utimensat(dirfd(dir), basename((char *) path), times, 0);
  closedir(dir);
  return ret == -1 ? -errno : ret;
}
Exemple #23
0
/*
 * TODO: To simplify things, we're mandating absolute paths.  We should
 * probably properly handle relative paths for this later and remove this
 * restriction.  Given this, the first argument to utimensat() is ignored.
 */
static int bru_utimens(const char *path, const struct timespec *times)
{
	SET_CALLER_UID();
	REDIR_PATH(path, new_path);

	int ret = utimensat(0, new_path, times, AT_SYMLINK_NOFOLLOW);

	SET_RET_ERRNO();
	return ret;
}
Exemple #24
0
static int xmp_utimens(const char *path, const struct timespec ts[2])
{
	fprintf(f, "utimes path: %s\n", path);
	int res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
	if (res == -1){
		fprintf(f, "operation failed\n");
		return -errno;
	}
	fprintf(f, "operation succeeded\n");
	return 0;
}
Exemple #25
0
static int copyat(int olddirfd, const char* oldpath, int newdirfd, const char* newpath) {
    int err;
    int oldfd = openat(olddirfd, oldpath, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NOATIME);
    if (oldfd == -1 && errno == EPERM) {
        oldfd = openat(olddirfd, oldpath, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
    }
    if (oldfd == -1 && errno == ELOOP) {
        char oldtarget[PATH_MAX];
        ssize_t oldlen = readlinkat(olddirfd, oldpath, oldtarget, sizeof(oldtarget));
        if (oldlen == -1) {
            return -1;
        }
        oldtarget[oldlen] = '\0';
        return symlinkat(oldtarget, newdirfd, newpath);
    }
    if (oldfd == -1) {
        return -1;
    }
    struct stat oldstat;
    if (fstat(oldfd, &oldstat) == -1) {
        err = errno;
        close(oldfd);
        errno = err;
        return -1;
    }
    int newfd = openat(newdirfd, newpath, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC | O_NOATIME, oldstat.st_mode);
    if (newfd == -1 && errno == EPERM) {
        newfd = openat(newdirfd, newpath, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, oldstat.st_mode);
    }
    if (newfd == -1) {
        err = errno;
        close(oldfd);
        errno = err;
        return -1;
    }
    if (fchown(newfd, oldstat.st_uid, oldstat.st_gid) == -1) {
        // ignore error
    }
    if (copyfile_sparse(oldfd, newfd) == -1) {
        err = errno;
        close(newfd);
        close(oldfd);
        errno = err;
        return -1;
    }
    close(newfd);
    close(oldfd);
    struct timespec times[2];
    times[0] = oldstat.st_atim;
    times[1] = oldstat.st_mtim;
    utimensat(newdirfd, newpath, times, 0); // ignore error
    return 0;
}
Exemple #26
0
int utimes(const char* path, const struct timeval tv[2]) {
  struct timespec ts[2];
  struct timespec* ts_ptr = NULL;
  if (tv != NULL) {
    if (!timespec_from_timeval(&ts[0], &tv[0]) || !timespec_from_timeval(&ts[1], &tv[1])) {
      errno = EINVAL;
      return -1;
    }
    ts_ptr = ts;
  }
  return utimensat(AT_FDCWD, path, ts_ptr, 0);
}
Exemple #27
0
int
setfile(struct stat *fs, int fd)
{
	struct timespec ts[2];
	int rval;

	rval = 0;
	fs->st_mode &= S_ISTXT | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;

	ts[0] = fs->st_atim;
	ts[1] = fs->st_mtim;
	if (fd >= 0 ? futimens(fd, ts) :
	    utimensat(AT_FDCWD, to.p_path, ts, AT_SYMLINK_NOFOLLOW)) {
		warn("update times: %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 >= 0 ? 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_ISTXT | S_ISUID | S_ISGID);
	}
	if (fd >= 0 ? fchmod(fd, fs->st_mode) :
	    fchmodat(AT_FDCWD, to.p_path, fs->st_mode, AT_SYMLINK_NOFOLLOW)) {
		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 >= 0 ? fchflags(fd, fs->st_flags) :
	    chflagsat(AT_FDCWD, to.p_path, fs->st_flags, AT_SYMLINK_NOFOLLOW))
		if (errno != EOPNOTSUPP || fs->st_flags != 0) {
			warn("chflags: %s", to.p_path);
			rval = 1;
		}
	return (rval);
}
Exemple #28
0
int main (void)
{
#if defined(HAVE_SIGNALFD) && defined(HAVE_EVENTFD) \
    && defined(HAVE_EVENTFD_READ) && defined(HAVE_PPOLL)
  {
    sigset_t mask;
    int fd, fd2;
    eventfd_t ev;
    struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 };
    struct pollfd pfd[2];

    sigemptyset (&mask);
    sigaddset (&mask, SIGUSR1);
    fd = signalfd (-1, &mask, 0);
    sigaddset (&mask, SIGUSR2);
    fd = signalfd (fd, &mask, 0);
    fd2 = eventfd (5, 0);
    eventfd_read (fd2, &ev);
    pfd[0].fd = fd;
    pfd[0].events = POLLIN|POLLOUT;
    pfd[1].fd = fd2;
    pfd[1].events = POLLIN|POLLOUT;
    ppoll (pfd, 2, &ts, &mask);
  }
#endif

#if defined(HAVE_UTIMENSAT)
  unlink("/tmp/valgrind-utimensat-test");
  close (creat ("/tmp/valgrind-utimensat-test", S_IRUSR | S_IWUSR));
  {
    struct timespec ts2[2] = { [0].tv_sec = 10000000, [1].tv_sec = 20000000 };
    utimensat (AT_FDCWD, "/tmp/valgrind-utimensat-test", ts2, 0);
  }
  unlink("/tmp/valgrind-utimensat-test");
#endif

#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_EPOLL_PWAIT)
  {
    int fd3;
    struct epoll_event evs[10];
    sigset_t mask;

    sigemptyset (&mask);
    sigaddset (&mask, SIGUSR1);
    sigaddset (&mask, SIGUSR2);
    fd3 = epoll_create (10);
    epoll_pwait (fd3, evs, 10, 0, &mask);
  }
#endif

  return 0;
}
Exemple #29
0
ATF_TC_BODY(utimensat_fdlink, tc)
{
	int dfd;
	struct stat st;

	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
	ATF_REQUIRE(symlink(FILE, LINK) == 0); /* NB: FILE does not exists */

	ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1);

	ATF_REQUIRE(utimensat(dfd, BASELINK, tptr, 0) == -1);
	ATF_REQUIRE(errno = ENOENT);

	ATF_REQUIRE(utimensat(dfd, BASELINK, tptr, AT_SYMLINK_NOFOLLOW) == 0);

	ATF_REQUIRE(close(dfd) == 0);

	ATF_REQUIRE(lstat(LINK, &st) == 0);
	ATF_REQUIRE(st.st_atimespec.tv_sec == tptr[0].tv_sec);
	ATF_REQUIRE(st.st_atimespec.tv_nsec == tptr[0].tv_nsec);
	ATF_REQUIRE(st.st_mtimespec.tv_sec == tptr[1].tv_sec);
	ATF_REQUIRE(st.st_mtimespec.tv_nsec == tptr[1].tv_nsec);
}
Exemple #30
0
int
utimesys(int code,
    uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4)
{
	switch (code) {
	case 0:
		return (futimens((int)arg1, (timespec_t *)arg2));
	case 1:
		return (utimensat((int)arg1, (char *)arg2,
		    (timespec_t *)arg3, (int)arg4));
	default:
		return (set_errno(EINVAL));
	}
}