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

coreutils/6.9/lib/acl.c

    1: /* acl.c - access control lists
    2: 
    3:    Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
    4: 
    5:    This program is free software; you can redistribute it and/or modify
    6:    it under the terms of the GNU General Public License as published by
    7:    the Free Software Foundation; either version 2, or (at your option)
    8:    any later version.
    9: 
   10:    This program is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13:    GNU General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU General Public License
   16:    along with this program; if not, write to the Free Software Foundation,
   17:    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   18: 
   19:    Written by Paul Eggert and Andreas Gruenbacher.  */
   20: 
   21: #include <config.h>
   22: 
   23: #include "acl.h"
   24: 
   25: #include "acl-internal.h"
   26: 
   27: /* If DESC is a valid file descriptor use fchmod to change the
   28:    file's mode to MODE on systems that have fchown. On systems
   29:    that don't have fchown and if DESC is invalid, use chown on
   30:    NAME instead.  */
   31: 
   32: int
   33: chmod_or_fchmod (const char *name, int desc, mode_t mode)
   34: {
   35:   if (HAVE_FCHMOD && desc != -1)
   36:     return fchmod (desc, mode);
   37:   else
   38:     return chmod (name, mode);
   39: }
   40: 
   41: /* Copy access control lists from one file to another. If SOURCE_DESC is
   42:    a valid file descriptor, use file descriptor operations, else use
   43:    filename based operations on SRC_NAME. Likewise for DEST_DESC and
   44:    DEST_NAME.
   45:    If access control lists are not available, fchmod the target file to
   46:    MODE.  Also sets the non-permission bits of the destination file
   47:    (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set.
   48:    System call return value semantics.  */
   49: 
   50: int
   51: copy_acl (const char *src_name, int source_desc, const char *dst_name,
   52:           int dest_desc, mode_t mode)
   53: {
   54:   int ret;
   55: 
   56: #if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
   57:   /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
   58: 
   59:   acl_t acl;
   60:   if (HAVE_ACL_GET_FD && source_desc != -1)
   61:     acl = acl_get_fd (source_desc);
   62:   else
   63:     acl = acl_get_file (src_name, ACL_TYPE_ACCESS);
   64:   if (acl == NULL)
   65:     {
   66:       if (ACL_NOT_WELL_SUPPORTED (errno))
   67:         return set_acl (dst_name, dest_desc, mode);
   68:       else
   69:         {
   70:           error (0, errno, "%s", quote (src_name));
   71:           return -1;
   72:         }
   73:     }
   74: 
   75:   if (HAVE_ACL_SET_FD && dest_desc != -1)
   76:     ret = acl_set_fd (dest_desc, acl);
   77:   else
   78:     ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl);
   79:   if (ret != 0)
   80:     {
   81:       int saved_errno = errno;
   82: 
   83:       if (ACL_NOT_WELL_SUPPORTED (errno))
   84:         {
   85:           int n = acl_entries (acl);
   86: 
   87:           acl_free (acl);
   88:           if (n == 3)
   89:             {
   90:               if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
   91:                 saved_errno = errno;
   92:               else
   93:                 return 0;
   94:             }
   95:           else
   96:             chmod_or_fchmod (dst_name, dest_desc, mode);
   97:         }
   98:       else
   99:         {
  100:           acl_free (acl);
  101:           chmod_or_fchmod (dst_name, dest_desc, mode);
  102:         }
  103:       error (0, saved_errno, _("preserving permissions for %s"),
  104:              quote (dst_name));
  105:       return -1;
  106:     }
  107:   else
  108:     acl_free (acl);
  109: 
  110:   if (mode & (S_ISUID | S_ISGID | S_ISVTX))
  111:     {
  112:       /* We did not call chmod so far, so the special bits have not yet
  113:          been set.  */
  114: 
  115:       if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
  116:         {
  117:           error (0, errno, _("preserving permissions for %s"),
  118:                  quote (dst_name));
  119:           return -1;
  120:         }
  121:     }
  122: 
  123:   if (S_ISDIR (mode))
  124:     {
  125:       acl = acl_get_file (src_name, ACL_TYPE_DEFAULT);
  126:       if (acl == NULL)
  127:         {
  128:           error (0, errno, "%s", quote (src_name));
  129:           return -1;
  130:         }
  131: 
  132:       if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl))
  133:         {
  134:           error (0, errno, _("preserving permissions for %s"),
  135:                  quote (dst_name));
  136:           acl_free (acl);
  137:           return -1;
  138:         }
  139:       else
  140:         acl_free (acl);
  141:     }
  142:   return 0;
  143: #else
  144:   ret = chmod_or_fchmod (dst_name, dest_desc, mode);
  145:   if (ret != 0)
  146:     error (0, errno, _("preserving permissions for %s"), quote (dst_name));
  147:   return ret;
  148: #endif
  149: }
  150: 
  151: /* Set the access control lists of a file. If DESC is a valid file
  152:    descriptor, use file descriptor operations where available, else use
  153:    filename based operations on NAME.  If access control lists are not
  154:    available, fchmod the target file to MODE.  Also sets the
  155:    non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX)
  156:    to those from MODE if any are set.  System call return value
  157:    semantics.  */
  158: 
  159: int
  160: set_acl (char const *name, int desc, mode_t mode)
  161: {
  162: #if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
  163:   /* POSIX 1003.1e draft 17 (abandoned) specific version.  */
  164: 
  165:   /* We must also have have_acl_from_text and acl_delete_def_file.
  166:      (acl_delete_def_file could be emulated with acl_init followed
  167:       by acl_set_file, but acl_set_file with an empty acl is
  168:       unspecified.)  */
  169: 
  170: # ifndef HAVE_ACL_FROM_TEXT
  171: #  error Must have acl_from_text (see POSIX 1003.1e draft 17).
  172: # endif
  173: # ifndef HAVE_ACL_DELETE_DEF_FILE
  174: #  error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
  175: # endif
  176: 
  177:   acl_t acl;
  178:   int ret;
  179: 
  180:   if (HAVE_ACL_FROM_MODE)
  181:     {
  182:       acl = acl_from_mode (mode);
  183:       if (!acl)
  184:         {
  185:           error (0, errno, "%s", quote (name));
  186:           return -1;
  187:         }
  188:     }
  189:   else
  190:     {
  191:       char acl_text[] = "u::---,g::---,o::---";
  192: 
  193:       if (mode & S_IRUSR) acl_text[ 3] = 'r';
  194:       if (mode & S_IWUSR) acl_text[ 4] = 'w';
  195:       if (mode & S_IXUSR) acl_text[ 5] = 'x';
  196:       if (mode & S_IRGRP) acl_text[10] = 'r';
  197:       if (mode & S_IWGRP) acl_text[11] = 'w';
  198:       if (mode & S_IXGRP) acl_text[12] = 'x';
  199:       if (mode & S_IROTH) acl_text[17] = 'r';
  200:       if (mode & S_IWOTH) acl_text[18] = 'w';
  201:       if (mode & S_IXOTH) acl_text[19] = 'x';
  202: 
  203:       acl = acl_from_text (acl_text);
  204:       if (!acl)
  205:         {
  206:           error (0, errno, "%s", quote (name));
  207:           return -1;
  208:         }
  209:     }
  210:   if (HAVE_ACL_SET_FD && desc != -1)
  211:     ret = acl_set_fd (desc, acl);
  212:   else
  213:     ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
  214:   if (ret != 0)
  215:     {
  216:       int saved_errno = errno;
  217:       acl_free (acl);
  218: 
  219:       if (ACL_NOT_WELL_SUPPORTED (errno))
  220:         {
  221:           if (chmod_or_fchmod (name, desc, mode) != 0)
  222:             saved_errno = errno;
  223:           else
  224:             return 0;
  225:         }
  226:       error (0, saved_errno, _("setting permissions for %s"), quote (name));
  227:       return -1;
  228:     }
  229:   else
  230:     acl_free (acl);
  231: 
  232:   if (S_ISDIR (mode) && acl_delete_def_file (name))
  233:     {
  234:       error (0, errno, _("setting permissions for %s"), quote (name));
  235:       return -1;
  236:     }
  237: 
  238:   if (mode & (S_ISUID | S_ISGID | S_ISVTX))
  239:     {
  240:       /* We did not call chmod so far, so the special bits have not yet
  241:          been set.  */
  242: 
  243:       if (chmod_or_fchmod (name, desc, mode))
  244:         {
  245:           error (0, errno, _("preserving permissions for %s"), quote (name));
  246:           return -1;
  247:         }
  248:     }
  249:   return 0;
  250: #else
  251:    int ret = chmod_or_fchmod (name, desc, mode);
  252:    if (ret)
  253:      error (0, errno, _("setting permissions for %s"), quote (name));
  254:    return ret;
  255: #endif
  256: }
Syntax (Markdown)