Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Jul 2015 12:57:20 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r285954 - head/sys/compat/cloudabi
Message-ID:  <201507281257.t6SCvKRS006457@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ed
Date: Tue Jul 28 12:57:19 2015
New Revision: 285954
URL: https://svnweb.freebsd.org/changeset/base/285954

Log:
  Implement file attribute modification system calls for CloudABI.
  
  CloudABI uses a system call interface to modify file attributes that is
  more similar to KPI's/FUSE, namely where a stat structure is passed back
  to the kernel, together with a bitmask of attributes that should be
  changed. This would allow us to update any set of attributes atomically.
  
  That said, I'd rather not go as far as to actually implement it that
  way, as it would require us to duplicate more code than strictly needed.
  Let's just stick to the combinations that are actually used by
  cloudlibc.
  
  Obtained from:	https://github.com/NuxiNL/freebsd

Modified:
  head/sys/compat/cloudabi/cloudabi_file.c

Modified: head/sys/compat/cloudabi/cloudabi_file.c
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_file.c	Tue Jul 28 12:52:22 2015	(r285953)
+++ head/sys/compat/cloudabi/cloudabi_file.c	Tue Jul 28 12:57:19 2015	(r285954)
@@ -292,13 +292,64 @@ cloudabi_sys_file_stat_fget(struct threa
 	return (copyout(&csb, uap->buf, sizeof(csb)));
 }
 
+/* Converts timestamps to arguments to futimens() and utimensat(). */
+static void
+convert_utimens_arguments(const cloudabi_filestat_t *fs,
+    cloudabi_fsflags_t flags, struct timespec *ts)
+{
+
+	if ((flags & CLOUDABI_FILESTAT_ATIM_NOW) != 0) {
+		ts[0].tv_nsec = UTIME_NOW;
+	} else if ((flags & CLOUDABI_FILESTAT_ATIM) != 0) {
+		ts[0].tv_sec = fs->st_atim / 1000000000;
+		ts[0].tv_nsec = fs->st_atim % 1000000000;
+	} else {
+		ts[0].tv_nsec = UTIME_OMIT;
+	}
+
+	if ((flags & CLOUDABI_FILESTAT_MTIM_NOW) != 0) {
+		ts[1].tv_nsec = UTIME_NOW;
+	} else if ((flags & CLOUDABI_FILESTAT_MTIM) != 0) {
+		ts[1].tv_sec = fs->st_mtim / 1000000000;
+		ts[1].tv_nsec = fs->st_mtim % 1000000000;
+	} else {
+		ts[1].tv_nsec = UTIME_OMIT;
+	}
+}
+
 int
 cloudabi_sys_file_stat_fput(struct thread *td,
     struct cloudabi_sys_file_stat_fput_args *uap)
 {
+	cloudabi_filestat_t fs;
+	struct timespec ts[2];
+	int error;
+
+	error = copyin(uap->buf, &fs, sizeof(fs));
+	if (error != 0)
+		return (error);
 
-	/* Not implemented. */
-	return (ENOSYS);
+	/*
+	 * Only support truncation and timestamp modification separately
+	 * for now, to prevent unnecessary code duplication.
+	 */
+	if ((uap->flags & CLOUDABI_FILESTAT_SIZE) != 0) {
+		/* Call into kern_ftruncate() for file truncation. */
+		if ((uap->flags & ~CLOUDABI_FILESTAT_SIZE) != 0)
+			return (EINVAL);
+		return (kern_ftruncate(td, uap->fd, fs.st_size));
+	} else if ((uap->flags & (CLOUDABI_FILESTAT_ATIM |
+	    CLOUDABI_FILESTAT_ATIM_NOW | CLOUDABI_FILESTAT_MTIM |
+	    CLOUDABI_FILESTAT_MTIM_NOW)) != 0) {
+		/* Call into kern_futimens() for timestamp modification. */
+		if ((uap->flags & ~(CLOUDABI_FILESTAT_ATIM |
+		    CLOUDABI_FILESTAT_ATIM_NOW | CLOUDABI_FILESTAT_MTIM |
+		    CLOUDABI_FILESTAT_MTIM_NOW)) != 0)
+			return (EINVAL);
+		convert_utimens_arguments(&fs, uap->flags, ts);
+		return (kern_futimens(td, uap->fd, ts, UIO_SYSSPACE));
+	}
+	return (EINVAL);
 }
 
 int
@@ -347,9 +398,33 @@ int
 cloudabi_sys_file_stat_put(struct thread *td,
     struct cloudabi_sys_file_stat_put_args *uap)
 {
+	cloudabi_filestat_t fs;
+	struct timespec ts[2];
+	char *path;
+	int error;
+
+	/*
+	 * Only support timestamp modification for now, as there is no
+	 * truncateat().
+	 */
+	if ((uap->flags & ~(CLOUDABI_FILESTAT_ATIM |
+	    CLOUDABI_FILESTAT_ATIM_NOW | CLOUDABI_FILESTAT_MTIM |
+	    CLOUDABI_FILESTAT_MTIM_NOW)) != 0)
+		return (EINVAL);
 
-	/* Not implemented. */
-	return (ENOSYS);
+	error = copyin(uap->buf, &fs, sizeof(fs));
+	if (error != 0)
+		return (error);
+	error = copyin_path(uap->path, uap->pathlen, &path);
+	if (error != 0)
+		return (error);
+
+	convert_utimens_arguments(&fs, uap->flags, ts);
+	error = kern_utimensat(td, uap->fd, path, UIO_SYSSPACE, ts,
+	    UIO_SYSSPACE, (uap->fd & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ?
+	    0 : AT_SYMLINK_NOFOLLOW);
+	cloudabi_freestr(path);
+	return (error);
 }
 
 int



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507281257.t6SCvKRS006457>