Mercurial > hg > octave-kai > gnulib-hg
view lib/at-func.c @ 11943:6e808da2cce5
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.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Thu, 03 Sep 2009 11:38:53 -0600 |
parents | bbbbbf4cd1c5 |
children | 55cb5282dd84 |
line wrap: on
line source
/* Define an at-style functions like fstatat, unlinkat, fchownat, etc. 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 the Free Software Foundation; either version 3 of the License, 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, see <http://www.gnu.org/licenses/>. */ /* written by Jim Meyering */ #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 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 AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) { struct saved_cwd saved_cwd; int saved_errno; int err; VALIDATE_FLAG (flag); if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) return CALL_FUNC (file); { char buf[OPENAT_BUFFER_SIZE]; char *proc_file = openat_proc_name (buf, fd, file); if (proc_file) { int proc_result = CALL_FUNC (proc_file); int proc_errno = errno; if (proc_file != buf) free (proc_file); /* 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 <= proc_result) return proc_result; if (! EXPECTED_ERRNO (proc_errno)) { errno = proc_errno; return proc_result; } } } if (save_cwd (&saved_cwd) != 0) openat_save_fail (errno); if (fchdir (fd) != 0) { saved_errno = errno; free_cwd (&saved_cwd); errno = saved_errno; return -1; } err = CALL_FUNC (file); saved_errno = (err < 0 ? errno : 0); if (restore_cwd (&saved_cwd) != 0) openat_restore_fail (errno); free_cwd (&saved_cwd); if (saved_errno) errno = saved_errno; return err; } #undef CALL_FUNC