PERFORCE change 120837 for review

Roman Divacky rdivacky at FreeBSD.org
Sun Jun 3 12:57:50 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=120837

Change 120837 by rdivacky at rdivacky_witten on 2007/06/03 12:57:02

	Implement linux_fchownat().

Affected files ...

.. //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_dummy.c#4 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_proto.h#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_syscall.h#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_sysent.c#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/syscalls.master#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/compat/linux/linux_file.c#5 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_dummy.c#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_proto.h#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_syscall.h#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_sysent.c#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/syscalls.master#3 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/kern/vfs_syscalls.c#11 edit
.. //depot/projects/soc2007/rdivacky/linux_at/sys/sys/syscallsubr.h#4 edit

Differences ...

==== //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_dummy.c#4 (text+ko) ====

@@ -98,7 +98,6 @@
 DUMMY(migrate_pages);
 DUMMY(mkdirat);
 DUMMY(mknodat);
-DUMMY(fchownat);
 DUMMY(futimesat);
 DUMMY(unlinkat);
 DUMMY(renameat);

==== //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_proto.h#3 (text+ko) ====

@@ -886,7 +886,11 @@
 	register_t dummy;
 };
 struct linux_fchownat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)];
+	char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_futimesat_args {
 	register_t dummy;

==== //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_syscall.h#3 (text+ko) ====


==== //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/linux32_sysent.c#3 (text+ko) ====

@@ -318,7 +318,7 @@
 	{ AS(linux_openat_args), (sy_call_t *)linux_openat, AUE_OPEN_RWTC, NULL, 0, 0 },	/* 295 = linux_openat */
 	{ 0, (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 },	/* 296 = linux_mkdirat */
 	{ 0, (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 },	/* 297 = linux_mknodat */
-	{ 0, (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
+	{ AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
 	{ 0, (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 },	/* 299 = linux_futimesat */
 	{ AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 },	/* 300 = linux_fstatat64 */
 	{ 0, (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 },	/* 301 = linux_unlinkat */

==== //depot/projects/soc2007/rdivacky/linux_at/sys/amd64/linux32/syscalls.master#3 (text+ko) ====

@@ -467,7 +467,8 @@
 					l_int flags, l_int mode); }
 296	AUE_NULL	STD	{ int linux_mkdirat(void); }
 297	AUE_NULL	STD	{ int linux_mknodat(void); }
-298	AUE_NULL	STD	{ int linux_fchownat(void); }
+298     AUE_NULL        STD     { int linux_fchownat(l_int dfd, char *filename, \
+					l_uid16_t uid, l_gid16_t gid, l_int flag); }
 299	AUE_NULL	STD	{ int linux_futimesat(void); }
 300	AUE_NULL	STD	{ int linux_fstatat64(l_int dfd, char *pathname, \
 					struct l_stat64 *statbuf, l_int flag); }

==== //depot/projects/soc2007/rdivacky/linux_at/sys/compat/linux/linux_file.c#5 (text+ko) ====

@@ -1287,6 +1287,35 @@
 }
 
 int
+linux_fchownat(struct thread *td, struct linux_fchownat_args *args)
+{
+	char *path;
+	int error, dfd;
+
+	if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
+		return (EINVAL);	
+
+	LCONVPATHEXIST(td, args->filename, &path);
+
+#ifdef DEBUG
+	if (ldebug(fchownat))
+		printf(ARGS(fchownat, "%s, %d, %d"), path, args->uid, args->gid);
+#endif
+	
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	if (args->flag & LINUX_AT_SYMLINK_NOFOLLOW)
+		error = kern_lchownat(td, path, UIO_SYSSPACE, args->uid, args->gid, dfd);
+	else
+		error = kern_chownat(td, path, UIO_SYSSPACE, args->uid, args->gid, dfd);
+	LFREEPATH(path);
+	return (error);
+}
+
+int
 linux_lchown(struct thread *td, struct linux_lchown_args *args)
 {
 	char *path;

==== //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_dummy.c#3 (text+ko) ====

@@ -89,7 +89,6 @@
 DUMMY(migrate_pages);
 DUMMY(mkdirat);
 DUMMY(mknodat);
-DUMMY(fchownat);
 DUMMY(futimesat);
 DUMMY(unlinkat);
 DUMMY(renameat);

==== //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_proto.h#3 (text+ko) ====

@@ -905,7 +905,11 @@
 	register_t dummy;
 };
 struct linux_fchownat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)];
+	char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_futimesat_args {
 	register_t dummy;

==== //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_syscall.h#3 (text+ko) ====


==== //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/linux_sysent.c#3 (text+ko) ====

@@ -317,7 +317,7 @@
 	{ AS(linux_openat_args), (sy_call_t *)linux_openat, AUE_OPEN_RWTC, NULL, 0, 0 },	/* 295 = linux_openat */
 	{ 0, (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 },	/* 296 = linux_mkdirat */
 	{ 0, (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 },	/* 297 = linux_mknodat */
-	{ 0, (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
+	{ AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
 	{ 0, (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 },	/* 299 = linux_futimesat */
 	{ AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 },	/* 300 = linux_fstatat64 */
 	{ 0, (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 },	/* 301 = linux_unlinkat */

==== //depot/projects/soc2007/rdivacky/linux_at/sys/i386/linux/syscalls.master#3 (text+ko) ====

@@ -477,7 +477,8 @@
 					l_int flags, l_int mode); }
 296	AUE_NULL	STD	{ int linux_mkdirat(void); }
 297	AUE_NULL	STD	{ int linux_mknodat(void); }
-298	AUE_NULL	STD	{ int linux_fchownat(void); }
+298	AUE_NULL	STD	{ int linux_fchownat(l_int dfd, char *filename, \
+					l_uid16_t uid, l_gid16_t gid, l_int flag); }
 299	AUE_NULL	STD	{ int linux_futimesat(void); }
 300	AUE_NULL	STD	{ int linux_fstatat64(l_int dfd, char *pathname, \
 					struct l_stat64 *statbuf, l_int flag); }

==== //depot/projects/soc2007/rdivacky/linux_at/sys/kern/vfs_syscalls.c#11 (text+ko) ====

@@ -95,6 +95,10 @@
     struct nameidata *nd);
 static int kern_common_lstat(struct thread *td, struct stat *sbp,
     struct nameidata *nd);
+static int kern_common_chown(struct thread *td, int uid, int gid,
+    struct nameidata *nd);
+static int kern_common_lchown(struct thread *td, int uid, int gid,
+    struct nameidata *nd);
 
 /*
  * The module initialization routine for POSIX asynchronous I/O will
@@ -2814,18 +2818,55 @@
 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
     int gid)
 {
+	struct nameidata nd;
+
+	AUDIT_ARG(owner, uid, gid);
+	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
+
+	return kern_common_chown(td, uid, gid, &nd);
+}
+
+int
+kern_chownat(struct thread *td, char *path, enum uio_seg pathseg, int uid,
+    int gid, int dirfd)
+{
 	int error;
 	struct nameidata nd;
+	struct vnode *dir_vn;
+
+	if (dirfd == AT_FDCWD)
+		dir_vn = NULL;
+	else {
+		error = fgetvp(td, dirfd, &dir_vn);
+		if (error)
+			return (error);
+		if (dir_vn->v_type != VDIR) {
+			vrele(dir_vn);
+			return (ENOTDIR);
+		}
+	}
+
+	NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
+
+	error = kern_common_chown(td, uid, gid, &nd);
+	if (dirfd != AT_FDCWD)
+		vrele(dir_vn);
+	return (error);
+
+}
+
+static int
+kern_common_chown(struct thread *td, int uid, int gid, struct nameidata *nd)
+{
+	int error;
 	int vfslocked;
 
-	AUDIT_ARG(owner, uid, gid);
-	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
-	if ((error = namei(&nd)) != 0)
+	if ((error = namei(nd)) != 0)
 		return (error);
-	vfslocked = NDHASGIANT(&nd);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	error = setfown(td, nd.ni_vp, uid, gid);
-	vrele(nd.ni_vp);
+	vfslocked = NDHASGIANT(nd);
+	NDFREE(nd, NDF_ONLY_PNBUF);
+	error = setfown(td, nd->ni_vp, uid, gid);
+	vrele(nd->ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
 	return (error);
 }
@@ -2857,18 +2898,55 @@
 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
     int gid)
 {
+	struct nameidata nd;
+
+	AUDIT_ARG(owner, uid, gid);
+	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
+
+	return kern_common_lchown(td, uid, gid, &nd);
+}
+
+int
+kern_lchownat(struct thread *td, char *path, enum uio_seg pathseg, int uid,
+    int gid, int dirfd)
+{
 	int error;
 	struct nameidata nd;
+	struct vnode *dir_vn;
+
+	if (dirfd == AT_FDCWD)
+		dir_vn = NULL;
+	else {
+		error = fgetvp(td, dirfd, &dir_vn);
+		if (error)
+			return (error);
+		if (dir_vn->v_type != VDIR) {
+			vrele(dir_vn);
+			return (ENOTDIR);
+		}
+	}
+
+	NDINIT_AT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
+
+	error = kern_common_chown(td, uid, gid, &nd);
+	if (dirfd != AT_FDCWD)
+		vrele(dir_vn);
+	return (error);
+
+}
+
+static int
+kern_common_lchown(struct thread *td, int uid, int gid, struct nameidata *nd)
+{
+	int error;
 	int vfslocked;
 
-	AUDIT_ARG(owner, uid, gid);
-	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
-	if ((error = namei(&nd)) != 0)
+	if ((error = namei(nd)) != 0)
 		return (error);
-	vfslocked = NDHASGIANT(&nd);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	error = setfown(td, nd.ni_vp, uid, gid);
-	vrele(nd.ni_vp);
+	vfslocked = NDHASGIANT(nd);
+	NDFREE(nd, NDF_ONLY_PNBUF);
+	error = setfown(td, nd->ni_vp, uid, gid);
+	vrele(nd->ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
 	return (error);
 }

==== //depot/projects/soc2007/rdivacky/linux_at/sys/sys/syscallsubr.h#4 (text+ko) ====

@@ -67,6 +67,8 @@
 	    int mode);
 int	kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
 	    int gid);
+int	kern_chownat(struct thread *td, char *path, enum uio_seg pathseg, int uid,
+	    int gid, int dirfd);
 int	kern_clock_getres(struct thread *td, clockid_t clock_id,
 	    struct timespec *ts);
 int	kern_clock_gettime(struct thread *td, clockid_t clock_id,
@@ -103,6 +105,8 @@
 int	kern_kldunload(struct thread *td, int fileid, int flags);
 int	kern_lchown(struct thread *td, char *path, enum uio_seg pathseg,
 	    int uid, int gid);
+int	kern_lchownat(struct thread *td, char *path, enum uio_seg pathseg,
+	    int uid, int gid, int dirfd);
 int	kern_link(struct thread *td, char *path, char *link,
 	    enum uio_seg segflg);
 int	kern_lstat(struct thread *td, char *path, enum uio_seg pathseg,


More information about the p4-projects mailing list