libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-2011, 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/limits.h> /* for PATH_MAX on Solaris */ 00022 #include <libexplain/ac/string.h> 00023 #include <libexplain/ac/sys/param.h> /* for PATH_MAX except Solaris */ 00024 #include <libexplain/ac/sys/stat.h> 00025 #include <libexplain/ac/unistd.h> 00026 00027 #include <libexplain/buffer/eacces.h> 00028 #include <libexplain/buffer/eexist.h> 00029 #include <libexplain/buffer/efault.h> 00030 #include <libexplain/buffer/eio.h> 00031 #include <libexplain/buffer/eloop.h> 00032 #include <libexplain/buffer/enametoolong.h> 00033 #include <libexplain/buffer/enoent.h> 00034 #include <libexplain/buffer/enomem.h> 00035 #include <libexplain/buffer/enospc.h> 00036 #include <libexplain/buffer/enotdir.h> 00037 #include <libexplain/buffer/erofs.h> 00038 #include <libexplain/buffer/errno/generic.h> 00039 #include <libexplain/buffer/errno/path_resolution.h> 00040 #include <libexplain/buffer/errno/symlink.h> 00041 #include <libexplain/buffer/file_type.h> 00042 #include <libexplain/buffer/mount_point.h> 00043 #include <libexplain/buffer/pathname.h> 00044 #include <libexplain/explanation.h> 00045 #include <libexplain/is_efault.h> 00046 #include <libexplain/string_buffer.h> 00047 00048 00049 static void 00050 explain_buffer_errno_symlink_system_call(explain_string_buffer_t *sb, 00051 int errnum, const char *oldpath, const char *newpath) 00052 { 00053 (void)errnum; 00054 explain_string_buffer_printf(sb, "symlink(oldpath = "); 00055 explain_buffer_pathname(sb, oldpath); 00056 explain_string_buffer_puts(sb, ", newpath = "); 00057 explain_buffer_pathname(sb, newpath); 00058 explain_string_buffer_putc(sb, ')'); 00059 } 00060 00061 00062 static void 00063 explain_buffer_errno_symlink_explanation(explain_string_buffer_t *sb, 00064 int errnum, const char *oldpath, const char *newpath) 00065 { 00066 explain_final_t final_component; 00067 00068 explain_final_init(&final_component); 00069 final_component.must_exist = 0; 00070 final_component.must_not_exist = 1; 00071 final_component.want_to_create = 1; 00072 final_component.st_mode = S_IFLNK; 00073 00074 switch (errnum) 00075 { 00076 case EACCES: 00077 explain_buffer_eacces(sb, newpath, "newpath", &final_component); 00078 break; 00079 00080 case EEXIST: 00081 explain_buffer_eexist(sb, newpath); 00082 break; 00083 00084 case EFAULT: 00085 if (explain_is_efault_path(oldpath)) 00086 { 00087 explain_buffer_efault(sb, "oldpath"); 00088 break; 00089 } 00090 if (explain_is_efault_path(newpath)) 00091 { 00092 explain_buffer_efault(sb, "newpath"); 00093 break; 00094 } 00095 explain_buffer_efault(sb, "oldpath or newpath"); 00096 break; 00097 00098 case EIO: 00099 explain_buffer_eio_path_dirname(sb, newpath); 00100 break; 00101 00102 case ELOOP: 00103 case EMLINK: /* BSD */ 00104 explain_buffer_eloop(sb, newpath, "newpath", &final_component); 00105 break; 00106 00107 case ENAMETOOLONG: 00108 { 00109 size_t oldpath_len; 00110 long path_max; 00111 00112 oldpath_len = strlen(oldpath); 00113 path_max = pathconf(newpath, _PC_PATH_MAX); 00114 if (path_max <= 0) 00115 path_max = PATH_MAX; 00116 if (oldpath_len > (size_t)path_max) 00117 { 00118 /* FIXME: i18n */ 00119 explain_string_buffer_puts(sb, "oldpath is too long"); 00120 explain_string_buffer_printf 00121 ( 00122 sb, 00123 " (%ld > %ld)", 00124 (long)oldpath_len, 00125 path_max 00126 ); 00127 } 00128 else 00129 { 00130 explain_buffer_enametoolong 00131 ( 00132 sb, 00133 newpath, 00134 "newpath", 00135 &final_component 00136 ); 00137 } 00138 } 00139 break; 00140 00141 case ENOENT: 00142 if (!*oldpath) 00143 { 00144 explain_string_buffer_puts 00145 ( 00146 sb, 00147 /* FIXME: i18n */ 00148 "oldpath is the empty string; if you meant the current " 00149 "directory, use \".\" instead" 00150 ); 00151 break; 00152 } 00153 explain_buffer_enoent(sb, newpath, "newpath", &final_component); 00154 break; 00155 00156 case ENOMEM: 00157 explain_buffer_enomem_kernel(sb); 00158 break; 00159 00160 case ENOSPC: 00161 explain_buffer_enospc(sb, newpath, "newpath"); 00162 break; 00163 00164 case ENOTDIR: 00165 explain_buffer_enotdir(sb, newpath, "newpath", &final_component); 00166 break; 00167 00168 case EPERM: 00169 /* FIXME: i18n */ 00170 explain_string_buffer_puts 00171 ( 00172 sb, 00173 "the file system containing newpath" 00174 ); 00175 explain_buffer_mount_point_dirname(sb, newpath); 00176 explain_string_buffer_puts 00177 ( 00178 sb, 00179 " does not support the creation of symbolic links" 00180 ); 00181 break; 00182 00183 case EROFS: 00184 explain_buffer_erofs(sb, newpath, "newpath"); 00185 break; 00186 00187 default: 00188 explain_buffer_errno_generic(sb, errnum, "symlink"); 00189 break; 00190 } 00191 } 00192 00193 00194 void 00195 explain_buffer_errno_symlink(explain_string_buffer_t *sb, int errnum, 00196 const char *oldpath, const char *newpath) 00197 { 00198 explain_explanation_t exp; 00199 00200 explain_explanation_init(&exp, errnum); 00201 explain_buffer_errno_symlink_system_call 00202 ( 00203 &exp.system_call_sb, 00204 errnum, 00205 oldpath, 00206 newpath 00207 ); 00208 explain_buffer_errno_symlink_explanation 00209 ( 00210 &exp.explanation_sb, 00211 errnum, 00212 oldpath, 00213 newpath 00214 ); 00215 explain_explanation_assemble(&exp, sb); 00216 } 00217 00218 00219 /* vim: set ts=8 sw=4 et : */