2009-09-03 Eric Blake <ebb9@byu.net>
+ openat: make template easier to use
+ * lib/at-func.c (CALL_FUNC): Allow AT_FUNC_USE_F1_COND and
+ AT_FUNC_F2 to be undefined.
+ (VALIDATE_FLAG): New macro; use it to reject bad flags.
+ (AT_FUNC_USE_F1_COND): Change sense to just flag bit.
+ * lib/fchmodat.c (AT_FUNC_USE_F1_COND): Adjust.
+ * lib/fchownat.c (AT_FUNC_USE_F1_COND): Likewise.
+ * lib/openat.c (AT_FUNC_USE_F1_COND) [fstatat, unlinkat]:
+ Likewise.
+ * lib/mkdirat.c (AT_FUNC_F2, AT_FUNC_USE_F1_COND): Delete.
+ * lib/selinux-at.c (AT_FUNC_F2, AT_FUNC_USE_F1_COND)
+ [getfileconat, lgetfileconat, setfileconat, lsetfileconat]:
+ Likewise.
+
openat: declare in POSIX headers
* NEWS: Mention this.
* modules/openat (configure.ac): Declare witnesses.
/* Define an at-style functions like fstatat, unlinkat, fchownat, etc.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
/* written by Jim Meyering */
-#define CALL_FUNC(F) \
- (AT_FUNC_USE_F1_COND \
+#ifdef AT_FUNC_USE_F1_COND
+# define CALL_FUNC(F) \
+ (flag == AT_FUNC_USE_F1_COND \
? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
: AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
+# define VALIDATE_FLAG(F) \
+ if (flag & ~AT_FUNC_USE_F1_COND) \
+ { \
+ errno = EINVAL; \
+ return -1; \
+ }
+#else
+# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS))
+# define VALIDATE_FLAG(F) /* empty */
+#endif
-/* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to
- determine which) to operate on FILE, which is in the directory
- open on descriptor FD. If possible, do it without changing the
+/* Call AT_FUNC_F1 to operate on FILE, which is in the directory
+ open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value,
+ AT_FUNC_POST_FILE_PARAM_DECLS must inlude a parameter named flag;
+ call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than
+ AT_FUNC_USE_F1_COND. If possible, do it without changing the
working directory. Otherwise, resort to using save_cwd/fchdir,
then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd
fails, then give a diagnostic and exit nonzero. */
int saved_errno;
int err;
+ VALIDATE_FLAG (flag);
+
if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
return CALL_FUNC (file);
#define AT_FUNC_NAME fchmodat
#define AT_FUNC_F1 lchmod
#define AT_FUNC_F2 chmod
-#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW
+#define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
#define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag
#define AT_FUNC_POST_FILE_ARGS , mode
#include "at-func.c"
#define AT_FUNC_NAME fchownat
#define AT_FUNC_F1 lchown
#define AT_FUNC_F2 chown
-#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW
+#define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
#define AT_FUNC_POST_FILE_PARAM_DECLS , uid_t owner, gid_t group, int flag
#define AT_FUNC_POST_FILE_ARGS , owner, group
#include "at-func.c"
#define AT_FUNC_NAME mkdirat
#define AT_FUNC_F1 mkdir
-#define AT_FUNC_F2 mkdir
-#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode
#define AT_FUNC_POST_FILE_ARGS , mode
#include "at-func.c"
#define AT_FUNC_NAME fstatat
#define AT_FUNC_F1 lstat
#define AT_FUNC_F2 stat
-#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW
+#define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag
#define AT_FUNC_POST_FILE_ARGS , st
#include "at-func.c"
#define AT_FUNC_NAME unlinkat
#define AT_FUNC_F1 rmdir
#define AT_FUNC_F2 unlink
-#define AT_FUNC_USE_F1_COND flag == AT_REMOVEDIR
+#define AT_FUNC_USE_F1_COND AT_REMOVEDIR
#define AT_FUNC_POST_FILE_PARAM_DECLS , int flag
#define AT_FUNC_POST_FILE_ARGS /* empty */
#include "at-func.c"
#define AT_FUNC_NAME getfileconat
#define AT_FUNC_F1 getfilecon
-#define AT_FUNC_F2 getfilecon
-#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
-#undef AT_FUNC_F2
-#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME lgetfileconat
#define AT_FUNC_F1 lgetfilecon
-#define AT_FUNC_F2 lgetfilecon
-#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
-#undef AT_FUNC_F2
-#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME setfileconat
#define AT_FUNC_F1 setfilecon
-#define AT_FUNC_F2 setfilecon
-#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
-#undef AT_FUNC_F2
-#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME lsetfileconat
#define AT_FUNC_F1 lsetfilecon
-#define AT_FUNC_F2 lsetfilecon
-#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
-#undef AT_FUNC_F2
-#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS