1 /* provide a replacement openat function
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* written by Jim Meyering */
32 #include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
36 #define _(msgid) gettext (msgid)
38 /* Replacement for Solaris' openat function.
39 <http://www.google.com/search?q=openat+site:docs.sun.com>
40 Simulate it by doing save_cwd/fchdir/open/restore_cwd.
41 If either the save_cwd or the restore_cwd fails (relatively unlikely,
42 and usually indicative of a problem that deserves close attention),
43 then give a diagnostic and exit nonzero.
44 Otherwise, upon failure, set errno and return -1, as openat does.
45 Upon successful completion, return a file descriptor. */
47 rpl_openat (int fd, char const *file, int flags, ...)
49 struct saved_cwd saved_cwd;
57 va_start (arg, flags);
59 /* Assume that mode_t is passed compatibly with mode_t's type
60 after argument promotion. */
61 mode = va_arg (arg, mode_t);
66 if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
67 return open (file, flags, mode);
69 if (save_cwd (&saved_cwd) != 0)
70 openat_save_fail (errno);
75 free_cwd (&saved_cwd);
80 new_fd = open (file, flags, mode);
83 if (restore_cwd (&saved_cwd) != 0)
84 openat_restore_fail (errno);
86 free_cwd (&saved_cwd);
92 /* Replacement for Solaris' function by the same name.
93 <http://www.google.com/search?q=fdopendir+site:docs.sun.com>
94 Simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd.
95 If either the save_cwd or the restore_cwd fails (relatively unlikely,
96 and usually indicative of a problem that deserves close attention),
97 then give a diagnostic and exit nonzero.
98 Otherwise, this function works just like Solaris' fdopendir.
101 Unlike the other fd-related functions here, this one
102 effectively consumes its FD parameter. The caller should not
103 close or otherwise manipulate FD after calling this function. */
107 struct saved_cwd saved_cwd;
112 return opendir (".");
114 if (save_cwd (&saved_cwd) != 0)
115 openat_save_fail (errno);
117 if (fchdir (fd) != 0)
120 free_cwd (&saved_cwd);
129 if (restore_cwd (&saved_cwd) != 0)
130 openat_restore_fail (errno);
132 free_cwd (&saved_cwd);
139 /* Replacement for Solaris' function by the same name.
140 <http://www.google.com/search?q=fstatat+site:docs.sun.com>
141 Simulate it by doing save_cwd/fchdir/(stat|lstat)/restore_cwd.
142 If either the save_cwd or the restore_cwd fails (relatively unlikely,
143 and usually indicative of a problem that deserves close attention),
144 then give a diagnostic and exit nonzero.
145 Otherwise, this function works just like Solaris' fstatat. */
147 fstatat (int fd, char const *file, struct stat *st, int flag)
149 struct saved_cwd saved_cwd;
154 return (flag == AT_SYMLINK_NOFOLLOW
158 if (save_cwd (&saved_cwd) != 0)
159 openat_save_fail (errno);
161 if (fchdir (fd) != 0)
164 free_cwd (&saved_cwd);
169 err = (flag == AT_SYMLINK_NOFOLLOW
174 if (restore_cwd (&saved_cwd) != 0)
175 openat_restore_fail (errno);
177 free_cwd (&saved_cwd);
183 /* Replacement for Solaris' function by the same name.
184 <http://www.google.com/search?q=unlinkat+site:docs.sun.com>
185 Simulate it by doing save_cwd/fchdir/(unlink|rmdir)/restore_cwd.
186 If either the save_cwd or the restore_cwd fails (relatively unlikely,
187 and usually indicative of a problem that deserves close attention),
188 then give a diagnostic and exit nonzero.
189 Otherwise, this function works just like Solaris' unlinkat. */
191 unlinkat (int fd, char const *file, int flag)
193 struct saved_cwd saved_cwd;
198 return (flag == AT_REMOVEDIR ? rmdir (file) : unlink (file));
200 if (save_cwd (&saved_cwd) != 0)
201 openat_save_fail (errno);
203 if (fchdir (fd) != 0)
206 free_cwd (&saved_cwd);
211 err = (flag == AT_REMOVEDIR ? rmdir (file) : unlink (file));
214 if (restore_cwd (&saved_cwd) != 0)
215 openat_restore_fail (errno);
217 free_cwd (&saved_cwd);