libexplain  1.4.D001
libexplain/buffer/errno/acl_set_file.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License as published by
00007  * the Free Software Foundation; either version 3 of the License, or (at
00008  * your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/acl/libacl.h>
00020 #include <libexplain/ac/errno.h>
00021 #include <libexplain/ac/sys/acl.h>
00022 #include <libexplain/ac/sys/stat.h>
00023 #include <libexplain/ac/unistd.h> /* pathconf */
00024 
00025 #include <libexplain/buffer/acl.h>
00026 #include <libexplain/buffer/acl_type.h>
00027 #include <libexplain/buffer/dac.h>
00028 #include <libexplain/buffer/does_not_have_inode_modify_permission.h>
00029 #include <libexplain/buffer/eacces.h>
00030 #include <libexplain/buffer/efault.h>
00031 #include <libexplain/buffer/enametoolong.h>
00032 #include <libexplain/buffer/enoent.h>
00033 #include <libexplain/buffer/enospc.h>
00034 #include <libexplain/buffer/enosys.h>
00035 #include <libexplain/buffer/enotdir.h>
00036 #include <libexplain/buffer/eperm.h>
00037 #include <libexplain/buffer/erofs.h>
00038 #include <libexplain/buffer/errno/acl_set_file.h>
00039 #include <libexplain/buffer/errno/generic.h>
00040 #include <libexplain/buffer/errno/path_resolution.h>
00041 #include <libexplain/buffer/is_the_null_pointer.h>
00042 #include <libexplain/buffer/pathname.h>
00043 #include <libexplain/explanation.h>
00044 
00045 
00046 static void
00047 explain_buffer_errno_acl_set_file_system_call(explain_string_buffer_t *sb,
00048     int errnum, const char *pathname, acl_type_t type, acl_t acl)
00049 {
00050     (void)errnum;
00051     explain_string_buffer_puts(sb, "acl_set_file(pathname = ");
00052     explain_buffer_pathname(sb, pathname);
00053     explain_string_buffer_puts(sb, ", type = ");
00054     explain_buffer_acl_type(sb, type);
00055     explain_string_buffer_puts(sb, ", acl = ");
00056     explain_buffer_acl(sb, acl);
00057     explain_string_buffer_putc(sb, ')');
00058 }
00059 
00060 
00061 static int
00062 is_a_directory(const char*pathname)
00063 {
00064     struct stat st;
00065     if (stat(pathname, &st) < 0)
00066         return 0;
00067     return !!S_ISDIR(st.st_mode);
00068 }
00069 
00070 
00071 void
00072 explain_buffer_errno_acl_set_file_explanation(explain_string_buffer_t *sb,
00073     int errnum, const char *syscall_name, const char *pathname, acl_type_t type,
00074     acl_t acl)
00075 {
00076     explain_final_t final_component;
00077 
00078     (void)type;
00079     explain_final_init(&final_component);
00080     final_component.want_to_modify_inode = 1;
00081 
00082     /*
00083      * http://www.opengroup.org/onlinepubs/009695399/functions/acl_set_file.html
00084      */
00085     switch (errnum)
00086     {
00087     case EFAULT:
00088         if (!pathname)
00089         {
00090             explain_buffer_is_the_null_pointer(sb, "pathname");
00091             break;
00092         }
00093         explain_buffer_efault(sb, "pathname");
00094         break;
00095 
00096     case EACCES:
00097         if (type == ACL_TYPE_DEFAULT && !is_a_directory(pathname))
00098         {
00099             /*
00100              * Note undocumented, discovered by reading the libacl source code
00101              */
00102             explain_string_buffer_puts
00103             (
00104                 sb,
00105                 /* FIXME: i18n */
00106                 "The type argument is ACL_TYPE_DEFAULT, but the file "
00107                 "referred to by pathname is not a directory"
00108             );
00109             break;
00110         }
00111 
00112         /*
00113          * Search permission is denied for a component of the
00114          * path prefix or the object exists and the process does
00115          * not have appropriate access rights.
00116          *
00117          * Argument type specifies a type of ACL that cannot be
00118          * associated with pathname.
00119          */
00120         explain_buffer_eacces(sb, pathname, "pathname", &final_component);
00121         break;
00122 
00123     case EINVAL:
00124         if (!acl)
00125         {
00126             explain_buffer_is_the_null_pointer(sb, "acl");
00127             break;
00128         }
00129         if (!pathname)
00130         {
00131             explain_buffer_is_the_null_pointer(sb, "pathname");
00132             break;
00133         }
00134         /*
00135          * The argument acl does not point to a valid ACL.
00136          */
00137         if (acl_valid(acl) < 0)
00138         {
00139             /* FIXME: i18n */
00140             explain_string_buffer_puts(sb, "acl does not point to a valid ACL");
00141             break;
00142         }
00143         if (type == ACL_TYPE_DEFAULT && !is_a_directory(pathname))
00144         {
00145             explain_string_buffer_puts
00146             (
00147                 sb,
00148                 /* FIXME: i18n */
00149                 "The type argument is ACL_TYPE_DEFAULT, but the file "
00150                 "referred to by pathname is not a directory"
00151             );
00152             break;
00153         }
00154 
00155         if
00156         (
00157             type != ACL_TYPE_ACCESS
00158         &&
00159             type != ACL_TYPE_DEFAULT
00160 #ifdef AC_TYPE_EXTENDED
00161         &&
00162             type != ACL_TYPE_EXTENDED
00163 #endif
00164 #ifdef AC_TYPE_NFSv4
00165         &&
00166             type != ACL_TYPE_NFSv4
00167 #endif
00168         )
00169         {
00170             explain_string_buffer_puts
00171             (
00172                 sb,
00173                 /* FIXME: i18n */
00174                 "the type parameter is not correctly specified"
00175             );
00176             break;
00177         }
00178 
00179         {
00180             long num = acl_entries(acl);
00181 #ifdef _PC_ACL_PATH_MAX
00182             long max = pathconf(pathname, _PC_ACL_PATH_MAX);
00183 #else
00184             long max = -1;
00185 #endif
00186             if (num > max)
00187             {
00188                 explain_string_buffer_puts
00189                 (
00190                     sb,
00191                     /* FIXME: i18n */
00192                     "The ACL has more entries than the file referred to "
00193                     "by pathname can obtain "
00194                 );
00195 #ifdef _PC_ACL_PATH_MAX
00196                 if (explain_option_dialect_specific())
00197                 {
00198                     explain_string_buffer_printf(" (%d > %d)", num, max);
00199                 }
00200 #endif
00201                 break;
00202             }
00203         }
00204         goto generic;
00205 
00206     case ENAMETOOLONG:
00207         /*
00208          * The length of the argument pathname is too long.
00209          */
00210         explain_buffer_enametoolong(sb, pathname, "pathname", &final_component);
00211         break;
00212 
00213     case ENOENT:
00214         /*
00215          * The named object does not exist or the argument pathname
00216          * points to an empty string.
00217          */
00218         explain_buffer_enoent(sb, pathname, "pathname", &final_component);
00219         break;
00220 
00221     case ENOSPC:
00222         /*
00223          * The directory or file system that would contain the
00224          * new ACL cannot be extended or the file system is out
00225          * of file allocation resources.
00226          */
00227         explain_buffer_enospc(sb, pathname, "pathnme");
00228         break;
00229 
00230     case ENOTDIR:
00231         /*
00232          * A component of the path prefix is not a directory.
00233          */
00234         explain_buffer_enotdir(sb, pathname, "pathname", &final_component);
00235         break;
00236 
00237     case ENOTSUP:
00238     case ENOSYS:
00239 #if defined(EOPNOTSUP) && ENOSYS != EOPNOTSUP
00240     case EOPNOTSUP:
00241 #endif
00242         /*
00243          * The file identified by pathname cannot be associated
00244          * with the ACL because the file system on which the file
00245          * is located does not support this.
00246          *  or ACLs are disabled.
00247          * or this host does not support ACLs.
00248          */
00249         explain_buffer_enosys_acl(sb, "pathname", syscall_name);
00250         break;
00251 
00252     case EPERM:
00253         /*
00254          * The process does not have appropriate privilege to
00255          * perform the operation to set the ACL.
00256          */
00257         if
00258         (
00259             /* returns zero if prints somthing */
00260             !explain_buffer_errno_path_resolution
00261             (
00262                 sb,
00263                 errnum,
00264                 pathname,
00265                 "pathname",
00266                 &final_component
00267             )
00268         )
00269             break;
00270 
00271         explain_buffer_eperm_vague(sb, syscall_name);
00272         explain_buffer_dac_sys_admin(sb);
00273         break;
00274 
00275     case EROFS:
00276         /*
00277          * This function requires modification of a file system
00278          * which is currently read-only.
00279          */
00280         explain_buffer_erofs(sb, pathname, "pathname");
00281         break;
00282 
00283     default:
00284         generic:
00285         explain_buffer_errno_generic(sb, errnum, syscall_name);
00286         break;
00287     }
00288 }
00289 
00290 
00291 void
00292 explain_buffer_errno_acl_set_file(explain_string_buffer_t *sb, int errnum,
00293     const char *pathname, acl_type_t type, acl_t acl)
00294 {
00295     explain_explanation_t exp;
00296 
00297     explain_explanation_init(&exp, errnum);
00298     explain_buffer_errno_acl_set_file_system_call(&exp.system_call_sb, errnum,
00299         pathname, type, acl);
00300     explain_buffer_errno_acl_set_file_explanation(&exp.explanation_sb, errnum,
00301         "acl_set_file", pathname, type, acl);
00302     explain_explanation_assemble(&exp, sb);
00303 }
00304 
00305 
00306 /* vim: set ts=8 sw=4 et : */