libexplain  1.4.D001
libexplain/buffer/eperm/unlink.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2010, 2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU Lesser General Public License as
00007  * published by the Free Software Foundation; either version 3 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser 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/limits.h> /* for PATH_MAX on Solaris */
00020 #include <libexplain/ac/sys/param.h> /* for PATH_MAX except Solaris */
00021 #include <libexplain/ac/sys/stat.h>
00022 #include <libexplain/ac/unistd.h>
00023 
00024 #include <libexplain/buffer/dac.h>
00025 #include <libexplain/buffer/eperm.h>
00026 #include <libexplain/buffer/uid.h>
00027 #include <libexplain/dirname.h>
00028 
00029 
00030 void
00031 explain_buffer_eperm_unlink(explain_string_buffer_t *sb, const char *pathname,
00032     const char *pathname_caption, const char *syscall_name)
00033 {
00034     struct stat     pathname_st;
00035     struct stat     dir_st;
00036     char            dir[PATH_MAX];
00037 
00038     explain_dirname(dir, pathname, sizeof(dir));
00039     if
00040     (
00041         stat(dir, &dir_st) >= 0
00042     &&
00043         (dir_st.st_mode & S_ISVTX)
00044     &&
00045         geteuid() != dir_st.st_uid
00046     &&
00047         stat(pathname, &pathname_st) >= 0
00048     &&
00049         geteuid() != pathname_st.st_uid
00050     )
00051     {
00052         explain_string_buffer_t proc_uid_sb;
00053         explain_string_buffer_t pathname_uid_sb;
00054         explain_string_buffer_t dir_uid_sb;
00055         explain_string_buffer_t dir_quoted_sb;
00056         char            proc_uid[50];
00057         char            pathname_uid[50];
00058         char            dir_uid[50];
00059         char            dir_quoted[PATH_MAX];
00060 
00061         explain_string_buffer_init(&dir_quoted_sb, dir_quoted,
00062             sizeof(dir_quoted));
00063         explain_string_buffer_puts_quoted(&dir_quoted_sb, dir);
00064 
00065         explain_string_buffer_init(&proc_uid_sb, proc_uid,
00066             sizeof(proc_uid));
00067         explain_buffer_uid(&proc_uid_sb, geteuid());
00068 
00069         explain_string_buffer_init(&pathname_uid_sb, pathname_uid,
00070             sizeof(pathname_uid));
00071         explain_buffer_uid(&pathname_uid_sb, pathname_st.st_uid);
00072 
00073         explain_string_buffer_init(&dir_uid_sb, dir_uid,
00074             sizeof(dir_uid));
00075         explain_buffer_uid(&dir_uid_sb, dir_st.st_uid);
00076 
00077         explain_string_buffer_printf_gettext
00078         (
00079             sb,
00080             /*
00081              * xgettext:  This error message is used to explain an EPERM error
00082              * reported by the unlink(2) system call, in the case where the
00083              * directory containing pathname has the sticky bit (S_ISVTX) set
00084              * and the process's effective UID is neither the UID of the file to
00085              * be deleted nor that of the directory containing it.
00086              *
00087              * %1$s => The path for the directory containing the file ot be
00088              *         unlinked, already quoted.
00089              * %2$s => The process's effective UID, and user name (already
00090              *         quoted) if available
00091              * %3$s => The file to be deleted's effective UID, and user name
00092              *         (already quoted) if available
00093              * %4$s => The directory's effective UID, and user name (already
00094              *         quoted) if available
00095              */
00096             i18n("the directory containing pathname (%s) has the "
00097                 "sticky bit (S_ISVTX) set and the process's effective "
00098                 "UID (%s) is neither the UID of the file to be deleted "
00099                 "(%s) nor that of the directory containing it (%s)"),
00100             dir_quoted,
00101             proc_uid,
00102             pathname_uid,
00103             dir_uid
00104         );
00105     }
00106     else
00107     {
00108         explain_string_buffer_printf_gettext
00109         (
00110             sb,
00111             /*
00112              * xgettext:  This error message is used to explain an EPERM
00113              * error reported by the unlink(2) system call, in the case
00114              * where the file system does not allow unlinking of files;
00115              * or, the directory containing pathname has the sticky
00116              * bit (S_ISVTX) set and the process's effective UID is
00117              * neither the UID of the file to be deleted nor that of the
00118              * directory containing it.
00119              *
00120              * $1$s => the name of the offending system call argument
00121              * $2$s => the name of the offended system call
00122              */
00123             i18n("the %s does not refer to a file system object to which %s "
00124                 "may be applied; or, the directory containing pathname has "
00125                 "the sticky bit (S_ISVTX) set and the process's effective UID "
00126                 "is neither the UID of the file to be deleted nor that of the "
00127                 "directory containing it"),
00128             pathname_caption,
00129             syscall_name
00130         );
00131     }
00132     explain_buffer_dac_fowner(sb);
00133 }
00134 
00135 
00136 /* vim: set ts=8 sw=4 et : */