[Glibc-bsd-commits] r2559 - trunk/glibc-ports/kfreebsd
Aurelien Jarno
aurel32 at alioth.debian.org
Mon Jun 1 23:18:37 UTC 2009
Author: aurel32
Date: 2009-06-01 23:18:37 +0000 (Mon, 01 Jun 2009)
New Revision: 2559
Added:
trunk/glibc-ports/kfreebsd/faccessat.c
trunk/glibc-ports/kfreebsd/fchmodat.c
trunk/glibc-ports/kfreebsd/fchownat.c
trunk/glibc-ports/kfreebsd/fexecve.c
trunk/glibc-ports/kfreebsd/futimesat.c
trunk/glibc-ports/kfreebsd/fxstatat.c
trunk/glibc-ports/kfreebsd/fxstatat64.c
trunk/glibc-ports/kfreebsd/linkat.c
trunk/glibc-ports/kfreebsd/mkdirat.c
trunk/glibc-ports/kfreebsd/readlinkat.c
trunk/glibc-ports/kfreebsd/renameat.c
trunk/glibc-ports/kfreebsd/symlinkat.c
trunk/glibc-ports/kfreebsd/unlinkat.c
trunk/glibc-ports/kfreebsd/xmknodat.c
Modified:
trunk/glibc-ports/kfreebsd/Makefile
trunk/glibc-ports/kfreebsd/kernel-features.h
trunk/glibc-ports/kfreebsd/openat.c
trunk/glibc-ports/kfreebsd/openat64.c
trunk/glibc-ports/kfreebsd/syscalls.list
Log:
Add *at() syscalls support, part of POSIX.1-2008.
Modified: trunk/glibc-ports/kfreebsd/Makefile
===================================================================
--- trunk/glibc-ports/kfreebsd/Makefile 2009-06-01 12:44:51 UTC (rev 2558)
+++ trunk/glibc-ports/kfreebsd/Makefile 2009-06-01 23:18:37 UTC (rev 2559)
@@ -31,13 +31,17 @@
ifeq ($(subdir),io)
# For <unistd.h>.
-sysdep_routines += sys_getcwd sys_lseek sys_freebsd6_lseek
+sysdep_routines += sys_fchownat sys_fexecve sys_getcwd sys_linkat sys_lseek sys_freebsd6_lseek sys_readlinkat sys_symlinkat sys_unlinkat
# For <fcntl.h>.
-sysdep_routines += sys_open open_2
+sysdep_routines += sys_open sys_openat open_2
# For <sys/stat.h>.
-sysdep_routines += sys_fstat sys_lstat sys_mknod sys_nfstat sys_nlstat sys_nstat sys_stat
+sysdep_routines += sys_fchmodat sys_fstat sys_fstatat sys_lstat sys_mkdirat sys_mkfifoat sys_mknod sys_mknodat sys_nfstat sys_nlstat sys_nstat sys_stat
# For <sys/statfs.h>.
sysdep_routines += fstatfs64 statfs64 sys_fstatfs sys_statfs
+# For <stdio.h>
+sysdep_routines += sys_renameat
+# For <sys/times.h>.
+sysdep_routines += sys_futimesat
# Other.
sysdep_routines += lchmod
endif
@@ -51,7 +55,7 @@
# For <sched.h>.
sysdep_routines += clone start_thread
# For <unistd.h>.
-sysdep_routines += sys_ftruncate sys_freebsd6_ftruncate sys_truncate sys_freebsd6_truncate
+sysdep_routines += sys_faccessat sys_ftruncate sys_freebsd6_ftruncate sys_truncate sys_freebsd6_truncate
# For <sys/acl.h>.
sysdep_routines += acl_aclcheck_fd acl_aclcheck_file acl_delete_fd acl_delete_file acl_get_fd acl_get_file acl_set_fd acl_set_file
# For <sys/extattr.h>.
Added: trunk/glibc-ports/kfreebsd/faccessat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/faccessat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/faccessat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,164 @@
+/* Test for access to file, relative to open directory. Linux version.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+#include <sysdep.h>
+
+extern int __syscall_faccessat (int fd, const char *path, mode_t mode,
+ int flag);
+libc_hidden_proto (__syscall_faccessat)
+
+int
+faccessat (fd, file, mode, flag)
+ int fd;
+ const char *file;
+ int mode;
+ int flag;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (faccessat, 4, fd, file, mode, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (flag & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if ((!(flag & AT_EACCESS) || !__libc_enable_secure)
+ && !(flag & AT_SYMLINK_NOFOLLOW))
+ {
+ /* If we are not set-uid or set-gid, access does the same. */
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf =
+ (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ return __access (file, mode);
+ }
+#endif
+
+ struct stat64 stats;
+ if (fstatat64 (fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW))
+ return -1;
+
+ mode &= (X_OK | W_OK | R_OK); /* Clear any bogus bits. */
+#if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH
+# error Oops, portability assumptions incorrect.
+#endif
+
+ if (mode == F_OK)
+ return 0; /* The file exists. */
+
+ uid_t uid = (flag & AT_EACCESS) ? __geteuid () : __getuid ();
+
+ /* The super-user can read and write any file, and execute any file
+ that anyone can execute. */
+ if (uid == 0 && ((mode & X_OK) == 0
+ || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
+ return 0;
+
+ int granted = (uid == stats.st_uid
+ ? (unsigned int) (stats.st_mode & (mode << 6)) >> 6
+ : (stats.st_gid == ((flag & AT_EACCESS)
+ ? __getegid () : __getgid ())
+ || __group_member (stats.st_gid))
+ ? (unsigned int) (stats.st_mode & (mode << 3)) >> 3
+ : (stats.st_mode & mode));
+
+ if (granted == mode)
+ return 0;
+
+ __set_errno (EACCES);
+ return -1;
+}
Added: trunk/glibc-ports/kfreebsd/fchmodat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/fchmodat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/fchmodat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,130 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_fchmodat (int fd, const char *path,
+ mode_t mode, int flag);
+libc_hidden_proto (__syscall_fchmodat)
+
+/* This is specific to kFreeBSD. */
+extern int __lchmod (__const char *__file, __mode_t __mode);
+
+int
+fchmodat (fd, file, mode, flag)
+ int fd;
+ const char *file;
+ mode_t mode;
+ int flag;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (fchmodat, 4, fd, file, mode, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (flag & ~AT_SYMLINK_NOFOLLOW)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ return __lchmod(file, mode);
+ else
+ return __chmod(file, mode);
+#endif
+}
Added: trunk/glibc-ports/kfreebsd/fchownat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/fchownat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/fchownat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,129 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_fchownat (int fd, const char *path, uid_t uid,
+ gid_t gid, int flag);
+libc_hidden_proto (__syscall_fchownat)
+
+/* Change the owner and group of FILE. */
+int
+fchownat (fd, file, owner, group, flag)
+ int fd;
+ const char *file;
+ uid_t owner;
+ gid_t group;
+ int flag;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (fchownat, 5, fd, file, owner, group, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (flag & ~AT_SYMLINK_NOFOLLOW)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ return __lchown(file, owner, group);
+ else
+ return __chown(file, owner, group);
+#endif
+}
Added: trunk/glibc-ports/kfreebsd/fexecve.c
===================================================================
--- trunk/glibc-ports/kfreebsd/fexecve.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/fexecve.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,103 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_fexecve (int fd, char *const argv[], char *const envp[]);
+libc_hidden_proto (__syscall_fexecve);
+
+/* Execute the file FD refers to, overlaying the running program image.
+ ARGV and ENVP are passed to the new program, as for `execve'. */
+int
+fexecve (fd, argv, envp)
+ int fd;
+ char *const argv[];
+ char *const envp[];
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (fexecve, 3, fd, argv, envp);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (fd < 0 || argv == NULL || envp == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len);
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type == KF_TYPE_VNODE &&
+ kf->kf_vnode_type == KF_VTYPE_VREG)
+ return __execve (kf->kf_path, argv, envp);
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ __set_errno (EINVAL);
+ return -1;
+#endif
+}
Added: trunk/glibc-ports/kfreebsd/futimesat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/futimesat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/futimesat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,119 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_futimesat (int fd, const char *path,
+ struct timeval *times);
+libc_hidden_proto (__syscall_futimesat)
+
+/* Change the access time of FILE relative to FD to TVP[0] and
+ the modification time of FILE to TVP[1]. */
+int
+futimesat (fd, file, tvp)
+ int fd;
+ const char *file;
+ const struct timeval tvp[2];
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (futimesat, 3, fd, file, tvp);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ return __utimes(file, tvp);
+#endif
+}
Added: trunk/glibc-ports/kfreebsd/fxstatat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/fxstatat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/fxstatat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,150 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+#include <bp-checks.h>
+
+#include "stat16conv.c"
+
+extern int __syscall_fstatat (int fd, const char *path,
+ struct stat16 *buf, int flag);
+libc_hidden_proto (__syscall_fstatat)
+
+/* Get information about the file NAME relative to FD in ST. */
+int
+__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result;
+
+ if (__builtin_expect (vers == _STAT_VER, 1))
+ {
+ struct stat16 buf16;
+ result =
+ INLINE_SYSCALL (fstatat, 4, fd, CHECK_STRING (file),
+ __ptrvalue (&buf16), flag);
+ if (result == 0)
+ stat16_to_stat (&buf16, st);
+ }
+ else if (__builtin_expect (vers == _STAT_VER_stat, 1))
+ {
+ result =
+ INLINE_SYSCALL (fstatat, 4, fd, CHECK_STRING (file),
+ CHECK_1 ((struct stat16 *) st), flag);
+ }
+ else
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (flag & ~AT_SYMLINK_NOFOLLOW)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ return __lxstat (vers, file, st);
+ else
+ return __xstat (vers, file, st);
+#endif
+}
+
+libc_hidden_def (__fxstatat)
Added: trunk/glibc-ports/kfreebsd/fxstatat64.c
===================================================================
--- trunk/glibc-ports/kfreebsd/fxstatat64.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/fxstatat64.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,144 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+#include <bp-checks.h>
+
+#include "stat16conv.c"
+
+extern int __syscall_fstatat (int fd, const char *path,
+ struct stat16 *buf, int flag);
+libc_hidden_proto (__syscall_fstatat)
+
+/* Get information about the file NAME relative to FD in ST. */
+int
+__fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result;
+
+ if (__builtin_expect (vers == _STAT_VER, 1))
+ {
+ struct stat16 buf16;
+ result =
+ INLINE_SYSCALL (fstatat, 4, fd, CHECK_STRING (file),
+ __ptrvalue (&buf16), flag);
+ if (result == 0)
+ stat16_to_stat64 (&buf16, st);
+ }
+ else
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (flag & ~AT_SYMLINK_NOFOLLOW)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ return __lxstat64 (vers, file, st);
+ else
+ return __xstat64 (vers, file, st);
+#endif
+}
+
+libc_hidden_def (__fxstatat64)
Modified: trunk/glibc-ports/kfreebsd/kernel-features.h
===================================================================
--- trunk/glibc-ports/kfreebsd/kernel-features.h 2009-06-01 12:44:51 UTC (rev 2558)
+++ trunk/glibc-ports/kfreebsd/kernel-features.h 2009-06-01 23:18:37 UTC (rev 2559)
@@ -73,3 +73,8 @@
# define __ASSUME_TRUNCATE_SYSCALL 1
#endif
+/* The `*at' syscalls were introduced in kFreeBSD 8.0. */
+#if __KFREEBSD_KERNEL_VERSION >= 0x80000
+# define __ASSUME_ATFCTS 1
+#endif
+
Added: trunk/glibc-ports/kfreebsd/linkat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/linkat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/linkat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,171 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <stdio.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_linkat (int fd1, const char *path1, int fd2,
+ const char *path2, int flags);
+libc_hidden_proto (__syscall_linkat)
+
+/* Make a link to FROM named TO but relative paths in TO and FROM are
+ interpreted relative to FROMFD and TOFD respectively. */
+int
+linkat (fromfd, from, tofd, to, flags)
+ int fromfd;
+ const char *from;
+ int tofd;
+ const char *to;
+ int flags;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (linkat, 5, fromfd, from, tofd, to, flags);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ /* Without kernel support we cannot handle AT_SYMLINK_FOLLOW. */
+ if (flags != 0)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if ((fromfd != AT_FDCWD && from[0] != '/')
+ || (tofd != AT_FDCWD && to[0] != '/'))
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if ((fromfd < 0) || (tofd < 0))
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len);
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ if (fromfd != AT_FDCWD && from[0] != '/')
+ {
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf =
+ (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fromfd)
+ {
+ char *buf;
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ buf = alloca (strlen (kf->kf_path) + strlen (from) + 2);
+ strcpy(buf, kf->kf_path);
+ strcat (buf, "/");
+ strcat (buf, from);
+ from = buf;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ if (tofd != AT_FDCWD && to[0] != '/')
+ {
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf =
+ (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == tofd)
+ {
+ char *buf;
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ buf = alloca (strlen (kf->kf_path) + strlen (to) + 2);
+ strcpy(buf, kf->kf_path);
+ strcat (buf, "/");
+ strcat (buf, to);
+ to = buf;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+ }
+
+ return __link (from, to);
+#endif
+}
Added: trunk/glibc-ports/kfreebsd/mkdirat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/mkdirat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/mkdirat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,118 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write file the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Bosfilen, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_mkdirat (int fd, const char *path, mode_t mode);
+libc_hidden_proto (__syscall_mkdirat)
+
+/* Create a new direcfilery with permission bits MODE. But interpret
+ relative PATH names relative file the direcfilery associated with FD. */
+int
+mkdirat (fd, file, mode)
+ int fd;
+ const char *file;
+ mode_t mode;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (mkdirat, 3, fd, file, mode);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ return __mkdir (file, mode);
+#endif
+}
Modified: trunk/glibc-ports/kfreebsd/openat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/openat.c 2009-06-01 12:44:51 UTC (rev 2558)
+++ trunk/glibc-ports/kfreebsd/openat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,12 +21,26 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
-#include <string.h>
+#include <unistd.h>
+#include <sysdep.h>
#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
#include <kernel-features.h>
#include <sysdep-cancel.h>
#include <not-cancel.h>
+extern int __syscall_openat (int fd, const char *path, int flag, mode_t mode);
+libc_hidden_proto (__syscall_openat)
+
+# ifndef __ASSUME_ATFCTS
+int __have_atfcts = 0;
+#endif
+
+/* Open FILE with access OFLAG. Interpret relative paths relative to
+ the directory associated with FD. If OFLAG includes O_CREAT, a
+ third argument is the file protection. */
int
__openat_nocancel (fd, file, oflag, mode)
int fd;
@@ -34,23 +48,84 @@
int oflag;
mode_t mode;
{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (openat, 4, fd, file, oflag, mode);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
if (fd != AT_FDCWD && file[0] != '/')
{
- /* Check FD is associated with a directory. */
- struct stat64 st;
- if (__fxstat64 (_STAT_VER, fd, &st) != 0)
- /* errno is already set correctly. */
- return -1;
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
- if (!S_ISDIR (st.st_mode))
- __set_errno (ENOTDIR);
- else
- __set_errno (ENOSYS);
- return -1;
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
}
return INLINE_SYSCALL (open, 3, file, oflag, mode);
+#endif
}
+strong_alias (__openat_nocancel, __openat64_nocancel)
/* Open FILE with access OFLAG. Interpret relative paths relative to
the directory associated with FD. If OFLAG includes O_CREAT, a
@@ -61,7 +136,9 @@
const char *file;
int oflag;
{
- mode_t mode = 0;
+ int mode = 0;
+ int result;
+
if (oflag & O_CREAT)
{
va_list arg;
@@ -70,29 +147,138 @@
va_end (arg);
}
- if (SINGLE_THREAD_P)
- return __openat_nocancel (fd, file, oflag, mode);
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ if (SINGLE_THREAD_P)
+ {
+ result = INLINE_SYSCALL (openat, 4, fd, file, oflag, mode);
+ }
+ else
+ {
+ int oldtype = LIBC_CANCEL_ASYNC ();
+ result = INLINE_SYSCALL (openat, 4, fd, file, oflag, mode);
+ LIBC_CANCEL_RESET (oldtype);
+ }
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+# endif
+ }
- int oldtype = LIBC_CANCEL_ASYNC ();
+#ifndef __ASSUME_ATFCTS
+ if (__have_atfcts < 0)
+ {
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
- int res = __openat_nocancel (fd, file, oflag, mode);
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
- LIBC_CANCEL_RESET (oldtype);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
- return res;
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf =
+ (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+ if (SINGLE_THREAD_P)
+ {
+ result = INLINE_SYSCALL (open, 3, file, oflag, mode);
+ }
+ else
+ {
+ int oldtype = LIBC_CANCEL_ASYNC ();
+ result = INLINE_SYSCALL (open, 3, file, oflag, mode);
+ LIBC_CANCEL_RESET (oldtype);
+ }
+
+ }
+#endif
+
+ if (result >= 0 && (oflag & O_TRUNC))
+ {
+ /* Set the modification time. The kernel ought to do this. */
+ int saved_errno = errno;
+ struct timeval tv[2];
+
+ if (__gettimeofday (&tv[1], NULL) >= 0)
+ {
+ struct stat statbuf;
+
+ if (__fxstat (_STAT_VER, result, &statbuf) >= 0)
+ {
+ tv[0].tv_sec = statbuf.st_atime;
+ tv[0].tv_usec = 0;
+
+#ifdef NOT_IN_libc
+ futimes (fd, tv);
+#else
+ __futimes (fd, tv);
+#endif
+ }
+ }
+ __set_errno (saved_errno);
+ }
+
+ return result;
}
+
libc_hidden_def (__openat)
weak_alias (__openat, openat)
-/* openat64 is just the same as openat for us. */
+/* 'openat64' is the same as 'openat', because __off64_t == __off_t. */
strong_alias (__openat, __openat64)
-strong_alias (__openat_nocancel, __openat64_nocancel)
-libc_hidden_weak (__openat64)
+libc_hidden_def (__openat64)
weak_alias (__openat64, openat64)
-stub_warning (openat)
-stub_warning (openat64)
-
int
__openat_2 (fd, file, oflag)
int fd;
@@ -106,5 +292,3 @@
}
strong_alias (__openat_2, __openat64_2)
-stub_warning (__openat_2)
-stub_warning (__openat64_2)
Modified: trunk/glibc-ports/kfreebsd/openat64.c
===================================================================
--- trunk/glibc-ports/kfreebsd/openat64.c 2009-06-01 12:44:51 UTC (rev 2558)
+++ trunk/glibc-ports/kfreebsd/openat64.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -1,2 +1,2 @@
-/* 'openat64' is the same as 'open', because __off64_t == __off_t and
+/* 'openat64' is the same as 'openat', because __off64_t == __off_t and
O_LARGEFILE == 0. */
Added: trunk/glibc-ports/kfreebsd/readlinkat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/readlinkat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/readlinkat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,122 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_readlinkat (int fd, const char *path, char *buf,
+ size_t bufsize);
+libc_hidden_proto (__syscall_readlinkat)
+
+/* Read the contents of the symbolic link PATH relative to FD into no
+ more than LEN bytes of BUF. */
+ssize_t
+readlinkat (fd, path, buf, len)
+ int fd;
+ const char *path;
+ char *buf;
+ size_t len;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (readlinkat, 4, fd, path, buf, len);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (fd != AT_FDCWD && path[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (path));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, path);
+ path = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ return __readlink (path, buf, len);
+#endif
+}
+
+libc_hidden_def (readlinkat)
Added: trunk/glibc-ports/kfreebsd/renameat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/renameat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/renameat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,161 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <stdio.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_renameat (int oldfd, const char *old, int newfd,
+ const char *new);
+libc_hidden_proto (__syscall_renameat)
+
+/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */
+int renameat (oldfd, old, newfd, new)
+ int oldfd;
+ const char *old;
+ int newfd;
+ const char *new;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (renameat, 4, oldfd, old, newfd, new);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if ((oldfd != AT_FDCWD && old[0] != '/')
+ || (newfd != AT_FDCWD && new[0] != '/'))
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if ((oldfd < 0) || (newfd < 0))
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len);
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ if (oldfd != AT_FDCWD && old[0] != '/')
+ {
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf =
+ (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == oldfd)
+ {
+ char *buf;
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ buf = alloca (strlen (kf->kf_path) + strlen (old) + 2);
+ strcpy(buf, kf->kf_path);
+ strcat (buf, "/");
+ strcat (buf, old);
+ old = buf;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ if (newfd != AT_FDCWD && new[0] != '/')
+ {
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf =
+ (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == newfd)
+ {
+ char *buf;
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ buf = alloca (strlen (kf->kf_path) + strlen (new) + 2);
+ strcpy(buf, kf->kf_path);
+ strcat (buf, "/");
+ strcat (buf, new);
+ new = buf;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+ }
+
+ return rename (old, new);
+#endif
+}
Added: trunk/glibc-ports/kfreebsd/symlinkat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/symlinkat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/symlinkat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,118 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_symlinkat (const char *path1, int fd,
+ const char *path2);
+libc_hidden_proto (__syscall_symlinkat)
+
+/* Make a symbolic link to FROM named TO relative to TOFD. */
+int
+symlinkat (from, tofd, to)
+ const char *from;
+ int tofd;
+ const char *to;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (symlinkat, 3, from, tofd, to);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (tofd != AT_FDCWD && to[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (tofd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (to));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == tofd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, to);
+ to = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ return __symlink (from, to);
+#endif
+}
Modified: trunk/glibc-ports/kfreebsd/syscalls.list
===================================================================
--- trunk/glibc-ports/kfreebsd/syscalls.list 2009-06-01 12:44:51 UTC (rev 2558)
+++ trunk/glibc-ports/kfreebsd/syscalls.list 2009-06-01 23:18:37 UTC (rev 2559)
@@ -55,7 +55,7 @@
kldunload - kldunload i:i kldunload
kldunloadf - kldunloadf i:ii kldunloadf
ktrace - ktrace i:siii ktrace
-lchmod - lchmod i:si lchmod
+lchmod - lchmod i:si __lchmod lchmod
lchown - lchown i:sii __lchown lchown
sys_lio_listio - lio_listio i:ibnP __syscall_lio_listio
sys_lseek - lseek i:iii __syscall_lseek
@@ -161,4 +161,18 @@
sys_umtx - _umtx_op i:piipp __syscall__umtx_op
sys_cpuset_getaffinity - cpuset_getaffinity i:iiiip __syscall_cpuset_getaffinity
sys_cpuset_setaffinity - cpuset_setaffinity i:iiiip __syscall_cpuset_setaffinity
-
+sys_faccessat - faccessat i:isii __syscall_faccessat
+sys_fchmodat - fchmodat i:isii __syscall_fchmodat
+sys_fchownat - fchownat i:isiii __syscall_fchownat
+sys_fexecve - fexecve i:ipp __syscall_fexecve
+sys_fstatat - fstatat i:ispi __syscall_fstatat
+sys_futimesat - futimesat i:isp __syscall_futimesat
+sys_linkat - linkat i:isisi __syscall_linkat
+sys_mkdirat - mkdirat i:isi __syscall_mkdirat
+sys_mkfifoat - mkfifoat i:isi __syscall_mkfifoat
+sys_mknodat - mknodat i:isii __syscall_mknodat
+sys_openat - openat i:isii __syscall_openat
+sys_readlinkat - readlinkat i:issi __syscall_readlinkat
+sys_renameat - renameat i:isis __syscall_renameat
+sys_symlinkat - symlinkat i:sis __syscall_symlinkat
+sys_unlinkat - unlinkat i:isi __syscall_unlinkat
Added: trunk/glibc-ports/kfreebsd/unlinkat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/unlinkat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/unlinkat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,125 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_unlinkat (int fd, const char *file, int flag);
+libc_hidden_proto (__syscall_unlinkat)
+
+/* Remove the link named NAME. */
+int
+unlinkat (fd, file, flag)
+ int fd;
+ const char *file;
+ int flag;
+{
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result = INLINE_SYSCALL (unlinkat, 3, fd, file, flag);
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (flag & ~AT_REMOVEDIR)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+ if (flag & AT_REMOVEDIR)
+ return __rmdir (file);
+ else
+ return __unlink (file);
+#endif
+}
Added: trunk/glibc-ports/kfreebsd/xmknodat.c
===================================================================
--- trunk/glibc-ports/kfreebsd/xmknodat.c (rev 0)
+++ trunk/glibc-ports/kfreebsd/xmknodat.c 2009-06-01 23:18:37 UTC (rev 2559)
@@ -0,0 +1,137 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdep.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <kernel-features.h>
+
+extern int __syscall_mknodat (int fd, const char *path,
+ mode_t mode, dev_t dev);
+libc_hidden_proto (__syscall_mknodat)
+
+extern int __syscall_mkfifoat (int fd, const char *path,
+ mode_t mode);
+libc_hidden_proto (__syscall_mkfifoat)
+
+/* Create a device file named PATH relative to FD, with permission and
+ special bits MODE and device number DEV (which can be constructed
+ from major and minor device numbers with the `makedev' macro above). */
+int
+__xmknodat (int vers, int fd, const char *file, mode_t mode, dev_t * dev)
+{
+ if (vers != _MKNOD_VER)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+# ifndef __ASSUME_ATFCTS
+ if (__have_atfcts >= 0)
+# endif
+ {
+ int result;
+
+ /* The FreeBSD mknod() system call cannot be used to create FIFOs; we
+ must use the mkfifo() system call for this purpose. */
+ if (S_ISFIFO (mode))
+ result = INLINE_SYSCALL (mkfifoat, 4, fd, file, mode);
+ else
+ result = INLINE_SYSCALL (mknodat, 4, fd, file, mode, *dev);
+
+# ifndef __ASSUME_ATFCTS
+ if (result == -1 && errno == ENOSYS)
+ __have_atfcts = -1;
+ else
+# endif
+ return result;
+ }
+
+#ifndef __ASSUME_ATFCTS
+ if (fd != AT_FDCWD && file[0] != '/')
+ {
+ int mib[4];
+ size_t kf_len = 0;
+ char *kf_buf, *kf_bufp;
+
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = __getpid ();
+
+ if (sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_buf = alloca (kf_len + strlen (file));
+ if (sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
+ {
+ __set_errno (ENOSYS);
+ return -1;
+ }
+
+ kf_bufp = kf_buf;
+ while (kf_bufp < kf_buf + kf_len)
+ {
+ struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;
+
+ if (kf->kf_fd == fd)
+ {
+ if (kf->kf_type != KF_TYPE_VNODE ||
+ kf->kf_vnode_type != KF_VTYPE_VDIR)
+ {
+ __set_errno (ENOTDIR);
+ return -1;
+ }
+
+ strcat (kf->kf_path, "/");
+ strcat (kf->kf_path, file);
+ file = kf->kf_path;
+ break;
+ }
+ kf_bufp += kf->kf_structsize;
+ }
+
+ if (kf_bufp >= kf_buf + kf_len)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ }
+
+ return __xmknod (vers, file, mode, dev);
+#endif
+}
+
+libc_hidden_def (__xmknodat)
More information about the Glibc-bsd-commits
mailing list