[PATCH] Fixes to the ia32 ABI (and amd64/Linux)

John Baldwin jhb at FreeBSD.org
Mon Feb 7 15:25:57 PST 2005


Can people test the patch below, it includes various and sundry fixes to the 
FreeBSD 32 compat ABI (i.e. FreeBSD/i386 binaries on FreeBSD/amd64 and 
FreeBSD/ia64) and the amd64 Linux/i386 ABI as well.  I don't expect it to 
make anything start working that was broken before, but there shouldn't be 
any regressions:

--- //depot/projects/smpng/sys/amd64/linux32/linux32_machdep.c	2004/10/05 
19:15:26
+++ //depot/user/jhb/proc/amd64/linux32/linux32_machdep.c	2005/02/04 16:32:42
@@ -34,6 +34,7 @@
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
+#include <sys/imgact.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mman.h>
@@ -49,6 +50,8 @@
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_map.h>
 
 #include <amd64/linux32/linux.h>
@@ -89,72 +92,120 @@
 	return (lsa);
 }
 
-int
-linux_execve(struct thread *td, struct linux_execve_args *args)
+/*
+ * Custom version of exec_copyin_args() so that we can translate
+ * the pointers.
+ */
+static int
+linux_exec_copyin_args(struct image_args *args, char *fname,
+    enum uio_seg segflg, char **argv, char **envv)
 {
-	struct execve_args ap;
-	caddr_t sg;
+	char *argp, *envp;
+	u_int32_t *p32, arg;
+	size_t length;
 	int error;
-	u_int32_t *p32, arg;
-	char **p, *p64;
-	int count;
+
+	bzero(args, sizeof(*args));
+	if (argv == NULL)
+		return (EFAULT);
 
-	sg = stackgap_init();
-	CHECKALTEXIST(td, &sg, args->path);
+	/*
+	 * Allocate temporary demand zeroed space for argument and
+	 *	environment strings
+	 */
+	args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX);
+	if (args->buf == NULL)
+		return (ENOMEM);
+	args->begin_argv = args->buf;
+	args->endp = args->begin_argv;
+	args->stringspace = ARG_MAX;
 
-#ifdef DEBUG
-	if (ldebug(execve))
-		printf(ARGS(execve, "%s"), args->path);
-#endif
+	args->fname = args->buf + ARG_MAX;
 
-	ap.fname = args->path;
+	/*
+	 * Copy the file name.
+	 */
+	error = (segflg == UIO_SYSSPACE) ?
+	    copystr(fname, args->fname, PATH_MAX, &length) :
+	    copyinstr(fname, args->fname, PATH_MAX, &length);
+	if (error != 0)
+		return (error);
 
-	if (args->argp != NULL) {
-		count = 0;
-		p32 = (u_int32_t *)args->argp;
-		do {
-			error = copyin(p32++, &arg, sizeof(arg));
-			if (error)
-				return error;
-			count++;
-		} while (arg != 0);
-		p = stackgap_alloc(&sg, count * sizeof(char *));
-		ap.argv = p;
-		p32 = (u_int32_t *)args->argp;
-		do {
-			error = copyin(p32++, &arg, sizeof(arg));
-			if (error)
-				return error;
-			p64 = PTRIN(arg);
-			error = copyout(&p64, p++, sizeof(p64));
-			if (error)
-				return error;
-		} while (arg != 0);
+	/*
+	 * extract arguments first
+	 */
+	p32 = (u_int32_t *)argv;
+	for (;;) {
+		error = copyin(p32++, &arg, sizeof(arg));
+		if (error)
+			return (error);
+		if (arg == 0)
+			break;
+		argp = PTRIN(arg);
+		error = copyinstr(argp, args->endp, args->stringspace, &length);
+		if (error) {
+			if (error == ENAMETOOLONG)
+				return (E2BIG);
+			else
+				return (error);
+		}
+		args->stringspace -= length;
+		args->endp += length;
+		args->argc++;
 	}
-	if (args->envp != NULL) {
-		count = 0;
-		p32 = (u_int32_t *)args->envp;
-		do {
+			
+	args->begin_envv = args->endp;
+
+	/*
+	 * extract environment strings
+	 */
+	if (envv) {
+		p32 = (u_int32_t *)envv;
+		for (;;) {
 			error = copyin(p32++, &arg, sizeof(arg));
 			if (error)
-				return error;
-			count++;
-		} while (arg != 0);
-		p = stackgap_alloc(&sg, count * sizeof(char *));
-		ap.envv = p;
-		p32 = (u_int32_t *)args->envp;
-		do {
-			error = copyin(p32++, &arg, sizeof(arg));
-			if (error)
-				return error;
-			p64 = PTRIN(arg);
-			error = copyout(&p64, p++, sizeof(p64));
-			if (error)
-				return error;
-		} while (arg != 0);
+				return (error);
+			if (arg == 0)
+				break;
+			envp = PTRIN(arg);
+			error = copyinstr(envp, args->endp, args->stringspace,
+			    &length);
+			if (error) {
+				if (error == ENAMETOOLONG)
+					return (E2BIG);
+				else
+					return (error);
+			}
+			args->stringspace -= length;
+			args->endp += length;
+			args->envc++;
+		}
 	}
 
-	return (execve(td, &ap));
+	return (0);
+}
+
+int
+linux_execve(struct thread *td, struct linux_execve_args *args)
+{
+	struct image_args eargs;
+	char *path;
+	int error;
+
+	LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+	if (ldebug(execve))
+		printf(ARGS(execve, "%s"), path);
+#endif
+
+	error = linux_exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp,
+	    args->envp);
+	free(path, M_TEMP);
+	if (error == 0)
+		error = kern_execve(td, &eargs, NULL);
+	exec_free_args(&eargs);
+	return (error);
 }
 
 struct iovec32 {
@@ -903,36 +954,20 @@
 int
 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *uap)
 {
-	struct timespec ats;
+	struct timespec rqt, rmt;
 	struct l_timespec ats32;
-	struct nanosleep_args bsd_args;
 	int error;
-	caddr_t sg;
-	caddr_t sarqts, sarmts;
 
-	sg = stackgap_init();
 	error = copyin(uap->rqtp, &ats32, sizeof(ats32));
 	if (error != 0)
 		return (error);
-	ats.tv_sec = ats32.tv_sec;
-	ats.tv_nsec = ats32.tv_nsec;
-	sarqts = stackgap_alloc(&sg, sizeof(ats));
-	error = copyout(&ats, sarqts, sizeof(ats));
-	if (error != 0)
-		return (error);
-	sarmts = stackgap_alloc(&sg, sizeof(ats));
-	bsd_args.rqtp = (void *)sarqts;
-	bsd_args.rmtp = (void *)sarmts;
-	error = nanosleep(td, &bsd_args);
+	rqt.tv_sec = ats32.tv_sec;
+	rqt.tv_nsec = ats32.tv_nsec;
+	error = kern_nanosleep(td, &rqt, &rmt);
 	if (uap->rmtp != NULL) {
-		error = copyin(sarmts, &ats, sizeof(ats));
-		if (error != 0)
-			return (error);
-		ats32.tv_sec = ats.tv_sec;
-		ats32.tv_nsec = ats.tv_nsec;
+		ats32.tv_sec = rmt.tv_sec;
+		ats32.tv_nsec = rmt.tv_nsec;
 		error = copyout(&ats32, uap->rmtp, sizeof(ats32));
-		if (error != 0)
-			return (error);
 	}
 	return (error);
 }
--- //depot/projects/smpng/sys/amd64/linux32/linux32_sysvec.c	2005/01/31 
22:15:49
+++ //depot/user/jhb/proc/amd64/linux32/linux32_sysvec.c	2005/02/04 16:32:42
@@ -744,7 +744,8 @@
 exec_linux_imgact_try(struct image_params *imgp)
 {
     const char *head = (const char *)imgp->image_header;
-    int error = -1;
+    char *rpath;
+    int error = -1, len;
 
     /*
      * The interpreter for shell scripts run from a linux binary needs
@@ -758,12 +759,10 @@
 	     * path is found, use our stringspace to store it.
 	     */
 	    if ((error = exec_shell_imgact(imgp)) == 0) {
-		    char *rpath = NULL;
-
-		    linux_emul_find(FIRST_THREAD_IN_PROC(imgp->proc), NULL,
-			imgp->interpreter_name, &rpath, 0);
-		    if (rpath != imgp->interpreter_name) {
-			    int len = strlen(rpath) + 1;
+		    linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
+			imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0);
+		    if (rpath != NULL) {
+			    len = strlen(rpath) + 1;
 
 			    if (len <= MAXSHELLCMDLEN) {
 				    memcpy(imgp->interpreter_name, rpath, len);
--- //depot/projects/smpng/sys/compat/freebsd32/freebsd32_misc.c	2005/01/31 
22:15:49
+++ //depot/user/jhb/proc/compat/freebsd32/freebsd32_misc.c	2005/02/04 
16:32:42
@@ -222,65 +222,111 @@
 	return (error);
 }
 
-int
-freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
+/*
+ * Custom version of exec_copyin_args() so that we can translate
+ * the pointers.
+ */
+static int
+freebsd32_exec_copyin_args(struct image_args *args, char *fname,
+    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
 {
+	char *argp, *envp;
+	u_int32_t *p32, arg;
+	size_t length;
 	int error;
-	caddr_t sg;
-	struct execve_args ap;
-	u_int32_t *p32, arg;
-	char **p, *p64;
-	int count;
+
+	bzero(args, sizeof(*args));
+	if (argv == NULL)
+		return (EFAULT);
+
+	/*
+	 * Allocate temporary demand zeroed space for argument and
+	 *	environment strings
+	 */
+	args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX);
+	if (args->buf == NULL)
+		return (ENOMEM);
+	args->begin_argv = args->buf;
+	args->endp = args->begin_argv;
+	args->stringspace = ARG_MAX;
+
+	args->fname = args->buf + ARG_MAX;
 
-	sg = stackgap_init();
-	ap.fname = uap->fname;
+	/*
+	 * Copy the file name.
+	 */
+	error = (segflg == UIO_SYSSPACE) ?
+	    copystr(fname, args->fname, PATH_MAX, &length) :
+	    copyinstr(fname, args->fname, PATH_MAX, &length);
+	if (error != 0)
+		return (error);
 
-	if (uap->argv) {
-		count = 0;
-		p32 = uap->argv;
-		do {
-			error = copyin(p32++, &arg, sizeof(arg));
-			if (error)
-				return error;
-			count++;
-		} while (arg != 0);
-		p = stackgap_alloc(&sg, count * sizeof(char *));
-		ap.argv = p;
-		p32 = uap->argv;
-		do {
-			error = copyin(p32++, &arg, sizeof(arg));
-			if (error)
-				return error;
-			p64 = PTRIN(arg);
-			error = copyout(&p64, p++, sizeof(p64));
-			if (error)
-				return error;
-		} while (arg != 0);
+	/*
+	 * extract arguments first
+	 */
+	p32 = argv;
+	for (;;) {
+		error = copyin(p32++, &arg, sizeof(arg));
+		if (error)
+			return (error);
+		if (arg == 0)
+			break;
+		argp = PTRIN(arg);
+		error = copyinstr(argp, args->endp, args->stringspace, &length);
+		if (error) {
+			if (error == ENAMETOOLONG)
+				return (E2BIG);
+			else
+				return (error);
+		}
+		args->stringspace -= length;
+		args->endp += length;
+		args->argc++;
 	}
-	if (uap->envv) {
-		count = 0;
-		p32 = uap->envv;
-		do {
+			
+	args->begin_envv = args->endp;
+
+	/*
+	 * extract environment strings
+	 */
+	if (envv) {
+		p32 = envv;
+		for (;;) {
 			error = copyin(p32++, &arg, sizeof(arg));
 			if (error)
-				return error;
-			count++;
-		} while (arg != 0);
-		p = stackgap_alloc(&sg, count * sizeof(char *));
-		ap.envv = p;
-		p32 = uap->envv;
-		do {
-			error = copyin(p32++, &arg, sizeof(arg));
-			if (error)
-				return error;
-			p64 = PTRIN(arg);
-			error = copyout(&p64, p++, sizeof(p64));
-			if (error)
-				return error;
-		} while (arg != 0);
+				return (error);
+			if (arg == 0)
+				break;
+			envp = PTRIN(arg);
+			error = copyinstr(envp, args->endp, args->stringspace,
+			    &length);
+			if (error) {
+				if (error == ENAMETOOLONG)
+					return (E2BIG);
+				else
+					return (error);
+			}
+			args->stringspace -= length;
+			args->endp += length;
+			args->envc++;
+		}
 	}
 
-	return execve(td, &ap);
+	return (0);
+}
+
+int
+freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
+{
+	struct image_args eargs;
+	int error;
+
+	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
+	    uap->argv, uap->envv);
+	if (error == 0)
+		error = kern_execve(td, &eargs, NULL);
+	exec_free_args(&eargs);
+	return (error);
 }
 
 #ifdef __ia64__
@@ -437,99 +483,63 @@
 int
 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
 {
+	struct itimerval itv, oitv, *itvp;	
+	struct itimerval32 i32;
 	int error;
-	caddr_t sg;
-	struct itimerval32 *p32, *op32, s32;
-	struct itimerval *p = NULL, *op = NULL, s;
 
-	p32 = uap->itv;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, sizeof(struct itimerval));
-		uap->itv = (struct itimerval32 *)p;
-		error = copyin(p32, &s32, sizeof(s32));
+	if (uap->itv != NULL) {
+		error = copyin(uap->itv, &i32, sizeof(i32));
 		if (error)
 			return (error);
-		TV_CP(s32, s, it_interval);
-		TV_CP(s32, s, it_value);
-		error = copyout(&s, p, sizeof(s));
-		if (error)
-			return (error);
-	}
-	op32 = uap->oitv;
-	if (op32) {
-		sg = stackgap_init();
-		op = stackgap_alloc(&sg, sizeof(struct itimerval));
-		uap->oitv = (struct itimerval32 *)op;
-	}
-	error = setitimer(td, (struct setitimer_args *) uap);
-	if (error)
+		TV_CP(i32, itv, it_interval);
+		TV_CP(i32, itv, it_value);
+		itvp = &itv;
+	} else
+		itvp = NULL;
+	error = kern_setitimer(td, uap->which, itvp, &oitv);
+	if (error || uap->oitv == NULL)
 		return (error);
-	if (op32) {
-		error = copyin(op, &s, sizeof(s));
-		if (error)
-			return (error);
-		TV_CP(s, s32, it_interval);
-		TV_CP(s, s32, it_value);
-		error = copyout(&s32, op32, sizeof(s32));
-	}
-	return (error);
+	TV_CP(oitv, i32, it_interval);
+	TV_CP(oitv, i32, it_value);
+	return (copyout(&i32, uap->oitv, sizeof(i32)));
 }
 
 int
 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
 {
+	struct itimerval itv;
+	struct itimerval32 i32;
 	int error;
-	caddr_t sg;
-	struct itimerval32 *p32, s32;
-	struct itimerval *p = NULL, s;
 
-	p32 = uap->itv;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, sizeof(struct itimerval));
-		uap->itv = (struct itimerval32 *)p;
-	}
-	error = getitimer(td, (struct getitimer_args *) uap);
-	if (error)
+	error = kern_getitimer(td, uap->which, &itv);
+	if (error || uap->itv == NULL)
 		return (error);
-	if (p32) {
-		error = copyin(p, &s, sizeof(s));
-		if (error)
-			return (error);
-		TV_CP(s, s32, it_interval);
-		TV_CP(s, s32, it_value);
-		error = copyout(&s32, p32, sizeof(s32));
-	}
-	return (error);
+	TV_CP(itv, i32, it_interval);
+	TV_CP(itv, i32, it_value);
+	return (copyout(&i32, uap->itv, sizeof(i32)));
 }
 
 int
 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
 {
+	struct timeval32 tv32;
+	struct timeval tv, *tvp;
 	int error;
-	caddr_t sg;
-	struct timeval32 *p32, s32;
-	struct timeval *p = NULL, s;
 
-	p32 = uap->tv;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, sizeof(struct timeval));
-		uap->tv = (struct timeval32 *)p;
-		error = copyin(p32, &s32, sizeof(s32));
+	if (uap->tv != NULL) {
+		error = copyin(uap->tv, &tv32, sizeof(tv32));
 		if (error)
 			return (error);
-		CP(s32, s, tv_sec);
-		CP(s32, s, tv_usec);
-		error = copyout(&s, p, sizeof(s));
-		if (error)
-			return (error);
-	}
+		CP(tv32, tv, tv_sec);
+		CP(tv32, tv, tv_usec);
+		tvp = &tv;
+	} else
+		tvp = NULL;
 	/*
 	 * XXX big-endian needs to convert the fd_sets too.
+	 * XXX Do pointers need PTRIN()?
 	 */
-	return (select(td, (struct select_args *) uap));
+	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
 }
 
 struct kevent32 {
@@ -799,28 +809,22 @@
 int
 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
 {
+	struct timeval32 s32[2];
+	struct timeval s[2], *sp;
 	int error;
-	caddr_t sg;
-	struct timeval32 *p32, s32[2];
-	struct timeval *p = NULL, s[2];
 
-	p32 = uap->tptr;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
-		uap->tptr = (struct timeval32 *)p;
-		error = copyin(p32, s32, sizeof(s32));
+	if (uap->tptr != NULL) {
+		error = copyin(uap->tptr, s32, sizeof(s32));
 		if (error)
 			return (error);
 		CP(s32[0], s[0], tv_sec);
 		CP(s32[0], s[0], tv_usec);
 		CP(s32[1], s[1], tv_sec);
 		CP(s32[1], s[1], tv_usec);
-		error = copyout(s, p, sizeof(s));
-		if (error)
-			return (error);
-	}
-	return (utimes(td, (struct utimes_args *) uap));
+		sp = s;
+	} else
+		sp = NULL;
+	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
 }
 
 int
@@ -851,7 +855,7 @@
 		op = stackgap_alloc(&sg, sizeof(struct timeval));
 		uap->olddelta = (struct timeval32 *)op;
 	}
-	error = utimes(td, (struct utimes_args *) uap);
+	error = adjtime(td, (struct adjtime_args *) uap);
 	if (error)
 		return error;
 	if (op32) {
@@ -869,28 +873,15 @@
 int
 freebsd4_freebsd32_statfs(struct thread *td, struct 
freebsd4_freebsd32_statfs_args *uap)
 {
+	struct statfs32 s32;
+	struct statfs s;
 	int error;
-	caddr_t sg;
-	struct statfs32 *p32, s32;
-	struct statfs *p = NULL, s;
 
-	p32 = uap->buf;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, sizeof(struct statfs));
-		uap->buf = (struct statfs32 *)p;
-	}
-	error = statfs(td, (struct statfs_args *) uap);
+	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
 	if (error)
 		return (error);
-	if (p32) {
-		error = copyin(p, &s, sizeof(s));
-		if (error)
-			return (error);
-		copy_statfs(&s, &s32);
-		error = copyout(&s32, p32, sizeof(s32));
-	}
-	return (error);
+	copy_statfs(&s, &s32);
+	return (copyout(&s32, uap->buf, sizeof(s32)));
 }
 #endif
 
@@ -898,28 +889,15 @@
 int
 freebsd4_freebsd32_fstatfs(struct thread *td, struct 
freebsd4_freebsd32_fstatfs_args *uap)
 {
+	struct statfs32 s32;
+	struct statfs s;
 	int error;
-	caddr_t sg;
-	struct statfs32 *p32, s32;
-	struct statfs *p = NULL, s;
 
-	p32 = uap->buf;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, sizeof(struct statfs));
-		uap->buf = (struct statfs32 *)p;
-	}
-	error = fstatfs(td, (struct fstatfs_args *) uap);
+	error = kern_fstatfs(td, uap->fd, &s);
 	if (error)
 		return (error);
-	if (p32) {
-		error = copyin(p, &s, sizeof(s));
-		if (error)
-			return (error);
-		copy_statfs(&s, &s32);
-		error = copyout(&s32, p32, sizeof(s32));
-	}
-	return (error);
+	copy_statfs(&s, &s32);
+	return (copyout(&s32, uap->buf, sizeof(s32)));
 }
 #endif
 
@@ -927,28 +905,18 @@
 int
 freebsd4_freebsd32_fhstatfs(struct thread *td, struct 
freebsd4_freebsd32_fhstatfs_args *uap)
 {
+	struct statfs32 s32;
+	struct statfs s;
+	fhandle_t fh;
 	int error;
-	caddr_t sg;
-	struct statfs32 *p32, s32;
-	struct statfs *p = NULL, s;
 
-	p32 = uap->buf;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, sizeof(struct statfs));
-		uap->buf = (struct statfs32 *)p;
-	}
-	error = fhstatfs(td, (struct fhstatfs_args *) uap);
+	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
+		return (error);
+	error = kern_fhstatfs(td, fh, &s);
 	if (error)
 		return (error);
-	if (p32) {
-		error = copyin(p, &s, sizeof(s));
-		if (error)
-			return (error);
-		copy_statfs(&s, &s32);
-		error = copyout(&s32, p32, sizeof(s32));
-	}
-	return (error);
+	copy_statfs(&s, &s32);
+	return (copyout(&s32, uap->buf, sizeof(s32)));
 }
 #endif
 
@@ -1124,20 +1092,8 @@
 	struct stat sb;
 	struct stat32 sb32;
 	int error;
-	struct nameidata nd;
 
-#ifdef LOOKUP_SHARED
-	NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ,
-	    UIO_USERSPACE, uap->path, td);
-#else
-	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
-	    uap->path, td);
-#endif
-	if ((error = namei(&nd)) != 0)
-		return (error);
-	error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	vput(nd.ni_vp);
+	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
 	if (error)
 		return (error);
 	copy_stat(&sb, &sb32);
@@ -1148,17 +1104,11 @@
 int
 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
 {
-	struct file *fp;
 	struct stat ub;
 	struct stat32 ub32;
 	int error;
 
-	if ((error = fget(td, uap->fd, &fp)) != 0)
-		return (error);
-	mtx_lock(&Giant);
-	error = fo_stat(fp, &ub, td->td_ucred, td);
-	mtx_unlock(&Giant);
-	fdrop(fp, td);
+	error = kern_fstat(td, uap->fd, &ub);
 	if (error)
 		return (error);
 	copy_stat(&ub, &ub32);
@@ -1169,20 +1119,11 @@
 int
 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
 {
-	int error;
-	struct vnode *vp;
 	struct stat sb;
 	struct stat32 sb32;
-	struct nameidata nd;
+	int error;
 
-	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
-	    uap->path, td);
-	if ((error = namei(&nd)) != 0)
-		return (error);
-	vp = nd.ni_vp;
-	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	vput(vp);
+	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
 	if (error)
 		return (error);
 	copy_stat(&sb, &sb32);

-- 
John Baldwin <jhb at FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org


More information about the freebsd-amd64 mailing list