libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-2010, 2013 Peter Miller 00004 * Written by Peter Miller <pmiller@opensource.org.au> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 3 of the License, or (at 00009 * your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <libexplain/ac/errno.h> 00021 #include <libexplain/ac/sys/stat.h> 00022 00023 #include <libexplain/buffer/dac.h> 00024 #include <libexplain/buffer/eacces.h> 00025 #include <libexplain/buffer/efault.h> 00026 #include <libexplain/buffer/eio.h> 00027 #include <libexplain/buffer/eloop.h> 00028 #include <libexplain/buffer/enametoolong.h> 00029 #include <libexplain/buffer/enoent.h> 00030 #include <libexplain/buffer/enomem.h> 00031 #include <libexplain/buffer/enotdir.h> 00032 #include <libexplain/buffer/eperm.h> 00033 #include <libexplain/buffer/erofs.h> 00034 #include <libexplain/buffer/errno/generic.h> 00035 #include <libexplain/buffer/errno/path_resolution.h> 00036 #include <libexplain/buffer/errno/unlink.h> 00037 #include <libexplain/buffer/mount_point.h> 00038 #include <libexplain/buffer/note/still_exists.h> 00039 #include <libexplain/buffer/path_to_pid.h> 00040 #include <libexplain/buffer/pointer.h> 00041 #include <libexplain/explanation.h> 00042 #include <libexplain/option.h> 00043 #include <libexplain/pathname_is_a_directory.h> 00044 #include <libexplain/string_buffer.h> 00045 00046 00047 static void 00048 explain_buffer_errno_unlink_system_call(explain_string_buffer_t *sb, 00049 int errnum, const char *pathname) 00050 { 00051 explain_string_buffer_printf(sb, "unlink(pathname = "); 00052 if (errnum == EFAULT) 00053 explain_buffer_pointer(sb, pathname); 00054 else 00055 explain_string_buffer_puts_quoted(sb, pathname); 00056 explain_string_buffer_putc(sb, ')'); 00057 } 00058 00059 00060 void 00061 explain_buffer_errno_unlink_explanation(explain_string_buffer_t *sb, 00062 int errnum, const char *syscall_name, const char *pathname) 00063 { 00064 explain_final_t final_component; 00065 00066 explain_final_init(&final_component); 00067 final_component.want_to_unlink = 1; 00068 00069 switch (errnum) 00070 { 00071 case EACCES: 00072 explain_buffer_eacces(sb, pathname, "pathname", &final_component); 00073 break; 00074 00075 case EBUSY: 00076 explain_string_buffer_puts 00077 ( 00078 sb, 00079 /* 00080 * xgettext: This error message is used to explain an 00081 * unlink EBUSY error, in the case where the pathname is 00082 * being used by the system or another process and the 00083 * implementation considers this an error. (This does not 00084 * happen on Linux.) 00085 */ 00086 i18n("the pathname is being used by the system or another " 00087 "process and the implementation considers this an error") 00088 ); 00089 explain_buffer_path_to_pid(sb, pathname); 00090 break; 00091 00092 case EFAULT: 00093 explain_buffer_efault(sb, "pathname"); 00094 break; 00095 00096 case EIO: 00097 explain_buffer_eio_path(sb, pathname); 00098 break; 00099 00100 case EISDIR: 00101 explain_string_buffer_puts 00102 ( 00103 sb, 00104 /* 00105 * xgettext: This message is used when explaining an EISDIR error 00106 * reported by the unlink(2) system call, in the case where the 00107 * named file is a directory. 00108 */ 00109 i18n("the named file is a directory; directories may not be " 00110 "unlinked, use rmdir(2) or remove(3) instead") 00111 ); 00112 break; 00113 00114 case ELOOP: 00115 case EMLINK: /* BSD */ 00116 explain_buffer_eloop(sb, pathname, "pathname", &final_component); 00117 break; 00118 00119 case ENAMETOOLONG: 00120 explain_buffer_enametoolong 00121 ( 00122 sb, 00123 pathname, 00124 "pathname", 00125 &final_component 00126 ); 00127 break; 00128 00129 case ENOENT: 00130 explain_buffer_enoent(sb, pathname, "pathname", &final_component); 00131 break; 00132 00133 case ENOMEM: 00134 explain_buffer_enomem_kernel(sb); 00135 break; 00136 00137 case ENOTDIR: 00138 explain_buffer_enotdir(sb, pathname, "pathname", &final_component); 00139 break; 00140 00141 case EPERM: 00142 #ifndef __linux__ 00143 /* 00144 * This code branch is for systems OTHER THAN Linux, 00145 * because Linux says "EISDIR" in this case. 00146 */ 00147 if (explain_pathname_is_a_directory(pathname)) 00148 { 00149 explain_string_buffer_puts 00150 ( 00151 sb, 00152 /* 00153 * xgettext: This message is uased to explain an EPERM error 00154 * reported by the unlink system call, in the case where the 00155 * system does not allow unlinking of directories, or unlinking 00156 * of directories requires privileges that the process does not 00157 * have. This case does not happen on Linux. 00158 */ 00159 i18n("the system does not allow unlinking of directories, or " 00160 "unlinking of directories requires privileges that the process " 00161 "does not have") 00162 ); 00163 break; 00164 } 00165 #endif 00166 if 00167 ( 00168 explain_buffer_errno_path_resolution 00169 ( 00170 sb, 00171 errnum, 00172 pathname, 00173 "pathname", 00174 &final_component 00175 ) 00176 ) 00177 { 00178 explain_buffer_eperm_unlink(sb, pathname, "pathname", syscall_name); 00179 break; 00180 } 00181 goto generic; 00182 00183 case EROFS: 00184 explain_buffer_erofs(sb, pathname, "pathname"); 00185 break; 00186 00187 default: 00188 generic: 00189 explain_buffer_errno_generic(sb, errnum, syscall_name); 00190 break; 00191 } 00192 00193 explain_buffer_note_if_still_exists(sb, pathname, "pathname"); 00194 } 00195 00196 00197 void 00198 explain_buffer_errno_unlink(explain_string_buffer_t *sb, int errnum, 00199 const char *pathname) 00200 { 00201 explain_explanation_t exp; 00202 00203 explain_explanation_init(&exp, errnum); 00204 explain_buffer_errno_unlink_system_call 00205 ( 00206 &exp.system_call_sb, 00207 errnum, 00208 pathname 00209 ); 00210 explain_buffer_errno_unlink_explanation 00211 ( 00212 &exp.explanation_sb, 00213 errnum, 00214 "unlink", 00215 pathname 00216 ); 00217 explain_explanation_assemble(&exp, sb); 00218 } 00219 00220 00221 /* vim: set ts=8 sw=4 et : */