[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
FYI: openat evolution: new functions: fchmodat, fchownat
From: |
Jim Meyering |
Subject: |
FYI: openat evolution: new functions: fchmodat, fchownat |
Date: |
Wed, 11 Jan 2006 16:30:23 +0100 |
I need fchmodat and fchownat for the upcoming fts.c changes,
so I've just checked in these changes:
2006-01-11 Jim Meyering <address@hidden>
* openat.c (fchownat): New function.
* openat.h (fchmodat, fchownat): Declare.
(chmodat, lchmodat): Define convenience functions.
(chownat, lchownat): Likewise.
* fchmodat.c (fchmodat): New file and function.
2006-01-11 Jim Meyering <address@hidden>
* openat.m4 (gl_FUNC_OPENAT): Require and compile fchmodat.c.
Check for the lchmod function.
Index: m4/openat.m4
===================================================================
RCS file: /fetish/cu/m4/openat.m4,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -p -u -r1.8 -r1.9
--- m4/openat.m4 30 Nov 2005 13:05:03 -0000 1.8
+++ m4/openat.m4 11 Jan 2006 15:25:30 -0000 1.9
@@ -1,7 +1,7 @@
-#serial 7
-# See if we need to use our replacement for Solaris' openat function.
+#serial 8
+# See if we need to use our replacement for Solaris' openat et al functions.
-dnl Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+dnl Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
@@ -12,12 +12,15 @@ AC_DEFUN([gl_FUNC_OPENAT],
[
AC_LIBSOURCES([openat.c, openat.h, openat-priv.h, openat-die.c])
AC_LIBSOURCES([mkdirat.c])
+ AC_LIBSOURCES([fchmodat.c])
- # No system provides a mkdirat function; compile it unconditionally.
+ # No system provides these functions; compile them unconditionally.
AC_LIBOBJ([mkdirat])
+ AC_LIBOBJ([fchmodat])
AC_LIBOBJ([openat-die])
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ AC_CHECK_FUNCS_ONCE([lchmod])
AC_CHECK_FUNCS_ONCE([fdopendir])
AC_REPLACE_FUNCS(openat)
case $ac_cv_func_openat in
Index: lib/openat.c
===================================================================
RCS file: /fetish/cu/lib/openat.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -p -u -r1.23 -r1.24
--- lib/openat.c 22 Dec 2005 14:34:20 -0000 1.23
+++ lib/openat.c 11 Jan 2006 13:32:03 -0000 1.24
@@ -1,5 +1,5 @@
/* provide a replacement openat function
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,16 +23,16 @@
#include "openat.h"
+#include <stdarg.h>
+#include <stddef.h>
+#include <errno.h>
+
#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
#include "fcntl--.h"
#include "openat-priv.h"
#include "save-cwd.h"
#include "unistd--.h"
-#include <stdarg.h>
-#include <stddef.h>
-#include <errno.h>
-
/* Replacement for Solaris' openat function.
<http://www.google.com/search?q=openat+site:docs.sun.com>
Simulate it by doing save_cwd/fchdir/open/restore_cwd.
@@ -286,3 +286,57 @@ unlinkat (int fd, char const *file, int
errno = saved_errno;
return err;
}
+
+/* Replacement for Solaris' function by the same name.
+ Invoke chown or lchown on file, FILE, using OWNER and GROUP, in the
+ directory open on descriptor FD. If FLAG is AT_SYMLINK_NOFOLLOW, then
+ use lchown, otherwise, use chown. If possible, do it without changing
+ the working directory. Otherwise, resort to using save_cwd/fchdir,
+ then mkdir/restore_cwd. If either the save_cwd or the restore_cwd
+ fails, then give a diagnostic and exit nonzero. */
+int
+fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag)
+{
+ struct saved_cwd saved_cwd;
+ int saved_errno;
+ int err;
+
+ if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
+ return (flag == AT_SYMLINK_NOFOLLOW
+ ? lchown (file, owner, group)
+ : chown (file, owner, group));
+
+ {
+ char *proc_file;
+ BUILD_PROC_NAME (proc_file, fd, file);
+ err = (flag == AT_SYMLINK_NOFOLLOW
+ ? lchown (proc_file, owner, group)
+ : chown (proc_file, owner, group));
+ /* If the syscall succeeds, or if it fails with an unexpected
+ errno value, then return right away. Otherwise, fall through
+ and resort to using save_cwd/restore_cwd. */
+ if (0 <= err || ! EXPECTED_ERRNO (errno))
+ return err;
+ }
+
+ if (save_cwd (&saved_cwd) != 0)
+ openat_save_fail (errno);
+
+ err = fchdir (fd);
+ saved_errno = errno;
+
+ if (! err)
+ {
+ err = (flag == AT_SYMLINK_NOFOLLOW
+ ? lchown (file, owner, group)
+ : chown (file, owner, group));
+ saved_errno = errno;
+
+ if (restore_cwd (&saved_cwd) != 0)
+ openat_restore_fail (errno);
+ }
+
+ free_cwd (&saved_cwd);
+ errno = saved_errno;
+ return err;
+}
Index: lib/openat.h
===================================================================
RCS file: /fetish/cu/lib/openat.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -p -u -r1.15 -r1.16
--- lib/openat.h 17 Dec 2005 06:55:01 -0000 1.15
+++ lib/openat.h 11 Jan 2006 13:32:47 -0000 1.16
@@ -1,5 +1,5 @@
/* provide a replacement openat function
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -72,3 +72,32 @@ int unlinkat (int fd, char const *file,
int mkdirat (int fd, char const *file, mode_t mode);
void openat_restore_fail (int) ATTRIBUTE_NORETURN;
void openat_save_fail (int) ATTRIBUTE_NORETURN;
+int fchmodat (int fd, char const *file, mode_t mode, int flag);
+int fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag);
+
+/* Using these function names makes application code
+ slightly more readable than it would be with
+ fchownat (..., 0) or fchownat (..., AT_SYMLINK_NOFOLLOW). */
+static inline int
+chownat (int fd, char const *file, uid_t owner, gid_t group)
+{
+ return fchownat (fd, file, owner, group, 0);
+}
+
+static inline int
+lchownat (int fd, char const *file, uid_t owner, gid_t group)
+{
+ return fchownat (fd, file, owner, group, AT_SYMLINK_NOFOLLOW);
+}
+
+static inline int
+chmodat (int fd, char const *file, mode_t mode)
+{
+ return fchmodat (fd, file, mode, 0);
+}
+
+static inline int
+lchmodat (int fd, char const *file, mode_t mode)
+{
+ return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW);
+}
Index: lib/fchmodat.c
===================================================================
RCS file: lib/fchmodat.c
diff -N lib/fchmodat.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lib/fchmodat.c 11 Jan 2006 13:30:31 -0000 1.1
@@ -0,0 +1,104 @@
+/* Change the protections of file relative to an open directory.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* written by Jim Meyering */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "openat.h"
+
+#include <errno.h>
+
+#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+#include "save-cwd.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+#include "openat-priv.h"
+
+/* Some systems don't have ENOSYS. */
+#ifndef ENOSYS
+# ifdef ENOTSUP
+# define ENOSYS ENOTSUP
+# else
+/* Some systems don't have ENOTSUP either. */
+# define ENOSYS EINVAL
+# endif
+#endif
+
+#ifndef HAVE_LCHMOD
+# undef lchmod
+# define lchmod(f,m) (errno = ENOSYS, -1)
+#endif
+
+/* Solaris 10 has no function like this.
+ Invoke chmod or lchmod on file, FILE, using mode MODE, in the directory
+ open on descriptor FD. If possible, do it without changing the
+ working directory. Otherwise, resort to using save_cwd/fchdir,
+ then mkdir/restore_cwd. If either the save_cwd or the restore_cwd
+ fails, then give a diagnostic and exit nonzero.
+ Note that an attempt to use a FLAG value of AT_SYMLINK_NOFOLLOW
+ on a system without lchmod support causes this function to fail. */
+int
+fchmodat (int fd, char const *file, mode_t mode, int flag)
+{
+ struct saved_cwd saved_cwd;
+ int saved_errno;
+ int err;
+
+ if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
+ return (flag == AT_SYMLINK_NOFOLLOW
+ ? lchmod (file, mode)
+ : chmod (file, mode));
+
+ {
+ char *proc_file;
+ BUILD_PROC_NAME (proc_file, fd, file);
+ err = (flag == AT_SYMLINK_NOFOLLOW
+ ? lchmod (proc_file, mode)
+ : chmod (proc_file, mode));
+ /* If the syscall succeeds, or if it fails with an unexpected
+ errno value, then return right away. Otherwise, fall through
+ and resort to using save_cwd/restore_cwd. */
+ if (0 <= err || ! EXPECTED_ERRNO (errno))
+ return err;
+ }
+
+ if (save_cwd (&saved_cwd) != 0)
+ openat_save_fail (errno);
+
+ err = fchdir (fd);
+ saved_errno = errno;
+
+ if (! err)
+ {
+ err = (flag == AT_SYMLINK_NOFOLLOW
+ ? lchmod (file, mode)
+ : chmod (file, mode));
+ saved_errno = errno;
+
+ if (restore_cwd (&saved_cwd) != 0)
+ openat_restore_fail (errno);
+ }
+
+ free_cwd (&saved_cwd);
+ errno = saved_errno;
+ return err;
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- FYI: openat evolution: new functions: fchmodat, fchownat,
Jim Meyering <=