(linenum→info "unix/slp.c:2238")

coreutils/6.9/lib/at-func.c

    1: /* Define an at-style functions like fstatat, unlinkat, fchownat, etc.
    2:    Copyright (C) 2006 Free Software Foundation, Inc.
    3: 
    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)
    7:    any later version.
    8: 
    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.
   13: 
   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.  */
   17: 
   18: /* written by Jim Meyering */
   19: 
   20: #define CALL_FUNC(F)                            \
   21:   (AT_FUNC_USE_F1_COND                          \
   22:     ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)     \
   23:     : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
   24: 
   25: /* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to
   26:    determine which) to operate on FILE, which is in the directory
   27:    open on descriptor FD.  If possible, do it without changing the
   28:    working directory.  Otherwise, resort to using save_cwd/fchdir,
   29:    then AT_FUNC_F?/restore_cwd.  If either the save_cwd or the restore_cwd
   30:    fails, then give a diagnostic and exit nonzero.  */
   31: int
   32: AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
   33: {
   34:   struct saved_cwd saved_cwd;
   35:   int saved_errno;
   36:   int err;
   37: 
   38:   if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
   39:     return CALL_FUNC (file);
   40: 
   41:   {
   42:     char buf[OPENAT_BUFFER_SIZE];
   43:     char *proc_file = openat_proc_name (buf, fd, file);
   44:     if (proc_file)
   45:       {
   46:         int proc_result = CALL_FUNC (proc_file);
   47:         int proc_errno = errno;
   48:         if (proc_file != buf)
   49:           free (proc_file);
   50:         /* If the syscall succeeds, or if it fails with an unexpected
   51:            errno value, then return right away.  Otherwise, fall through
   52:            and resort to using save_cwd/restore_cwd.  */
   53:         if (0 <= proc_result)
   54:           return proc_result;
   55:         if (! EXPECTED_ERRNO (proc_errno))
   56:           {
   57:             errno = proc_errno;
   58:             return proc_result;
   59:           }
   60:       }
   61:   }
   62: 
   63:   if (save_cwd (&saved_cwd) != 0)
   64:     openat_save_fail (errno);
   65: 
   66:   if (fchdir (fd) != 0)
   67:     {
   68:       saved_errno = errno;
   69:       free_cwd (&saved_cwd);
   70:       errno = saved_errno;
   71:       return -1;
   72:     }
   73: 
   74:   err = CALL_FUNC (file);
   75:   saved_errno = (err < 0 ? errno : 0);
   76: 
   77:   if (restore_cwd (&saved_cwd) != 0)
   78:     openat_restore_fail (errno);
   79: 
   80:   free_cwd (&saved_cwd);
   81: 
   82:   if (saved_errno)
   83:     errno = saved_errno;
   84:   return err;
   85: }
   86: #undef CALL_FUNC
Syntax (Markdown)