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/assert.h> 00021 #include <libexplain/ac/ctype.h> 00022 #include <libexplain/ac/dirent.h> 00023 #include <libexplain/ac/errno.h> 00024 #include <libexplain/ac/fcntl.h> 00025 #include <libexplain/ac/limits.h> /* for PATH_MAX on Solaris */ 00026 #include <libexplain/ac/stdlib.h> 00027 #include <libexplain/ac/string.h> 00028 #include <libexplain/ac/sys/param.h> /* for PATH_MAX except Solaris */ 00029 #include <libexplain/ac/sys/stat.h> 00030 #include <libexplain/ac/unistd.h> 00031 00032 #include <libexplain/buffer/caption_name_type.h> 00033 #include <libexplain/buffer/dac.h> 00034 #include <libexplain/buffer/does_not_have_inode_modify_permission.h> 00035 #include <libexplain/buffer/eexist.h> 00036 #include <libexplain/buffer/errno/path_resolution.h> 00037 #include <libexplain/buffer/file_type.h> 00038 #include <libexplain/buffer/gettext.h> 00039 #include <libexplain/buffer/mount_point.h> 00040 #include <libexplain/buffer/uid.h> 00041 #include <libexplain/buffer/wrong_file_type.h> 00042 #include <libexplain/capability.h> 00043 #include <libexplain/fstrcmp.h> 00044 #include <libexplain/getppcwd.h> 00045 #include <libexplain/have_permission.h> 00046 #include <libexplain/name_max.h> 00047 #include <libexplain/option.h> 00048 #include <libexplain/symloopmax.h> 00049 00050 00051 static int 00052 all_slash(const char *s) 00053 { 00054 while (*s == '/') 00055 ++s; 00056 return !*s; 00057 } 00058 00059 00060 static void 00061 look_for_similar(explain_string_buffer_t *sb, const char *lookup_directory, 00062 const char *component) 00063 { 00064 DIR *dp; 00065 char best_name[NAME_MAX + 1]; 00066 double best_weight; 00067 char subject[NAME_MAX * 4 + 3]; 00068 explain_string_buffer_t subject_sb; 00069 struct stat st; 00070 00071 dp = opendir(lookup_directory); 00072 if (!dp) 00073 return; 00074 00075 best_name[0] = '\0'; 00076 best_weight = 0.6; 00077 for (;;) 00078 { 00079 struct dirent *dep; 00080 double weight; 00081 00082 dep = readdir(dp); 00083 if (!dep) 00084 break; 00085 if (0 == strcmp(dep->d_name, ".")) 00086 continue; 00087 if (0 == strcmp(dep->d_name, "..")) 00088 continue; 00089 weight = explain_fstrcasecmp(component, dep->d_name); 00090 if (best_weight < weight) 00091 { 00092 best_weight = weight; 00093 explain_strendcpy 00094 ( 00095 best_name, 00096 dep->d_name, 00097 best_name + sizeof(best_name) 00098 ); 00099 } 00100 } 00101 closedir(dp); 00102 00103 if (best_name[0] == '\0') 00104 return; 00105 00106 memset(&st, 0, sizeof(st)); 00107 { 00108 /* 00109 * see if we can say what kind of file it is 00110 */ 00111 char ipath[PATH_MAX + 1]; 00112 char *ipath_end; 00113 char *ip; 00114 00115 ipath_end = ipath + sizeof(ipath); 00116 ip = ipath; 00117 ip = explain_strendcpy(ip, lookup_directory, ipath_end); 00118 ip = explain_strendcpy(ip, "/", ipath_end); 00119 ip = explain_strendcpy(ip, best_name, ipath_end); 00120 lstat(ipath, &st); 00121 } 00122 00123 explain_string_buffer_init(&subject_sb, subject, sizeof(subject)); 00124 if (st.st_dev) 00125 explain_buffer_caption_name_type_st(&subject_sb, 0, best_name, &st); 00126 else 00127 explain_buffer_caption_name_type(&subject_sb, 0, best_name, -1); 00128 00129 explain_string_buffer_puts(sb->footnotes, "; "); 00130 explain_string_buffer_printf_gettext 00131 ( 00132 sb->footnotes, 00133 /* 00134 * xgettext: This message is issued when a file (or directory 00135 * component) could not be found, but a sufficiently similar 00136 * name has been found in the same directory. This often helps 00137 * with typographical errors. 00138 * 00139 * %1$s => the name (already quoted) and file type (already 00140 * translated) of the alternate file found. 00141 */ 00142 i18n("did you mean the %s instead?"), 00143 subject 00144 ); 00145 } 00146 00147 00148 static int 00149 command_interpreter_broken(explain_string_buffer_t *sb, const char *pathname) 00150 { 00151 char block[512]; 00152 int fd; 00153 ssize_t n; 00154 char *end; 00155 char *interpreter_pathname; 00156 explain_final_t final_component; 00157 char *bp; 00158 00159 fd = open(pathname, O_RDONLY); 00160 if (fd < 0) 00161 return -1; 00162 n = read(fd, block, sizeof(block) - 1); 00163 close(fd); 00164 if (n < 4) 00165 return -1; 00166 end = block + n; 00167 if (block[0] != '#') 00168 return -1; 00169 if (block[1] != '!') 00170 return -1; 00171 bp = block + 2; 00172 while (bp < end && (*bp == ' ' || *bp == '\t')) 00173 ++bp; 00174 if (bp >= end) 00175 return -1; 00176 interpreter_pathname = bp; 00177 ++bp; 00178 while (bp < end && !isspace(*bp)) 00179 ++bp; 00180 *bp = '\0'; 00181 00182 explain_final_init(&final_component); 00183 final_component.want_to_execute = 1; 00184 final_component.follow_interpreter = 0; /* avoid infinite loops */ 00185 return 00186 explain_buffer_errno_path_resolution 00187 ( 00188 sb, 00189 EACCES, 00190 interpreter_pathname, 00191 "#!", 00192 &final_component 00193 ); 00194 } 00195 00196 00197 static int 00198 hash_bang(explain_string_buffer_t *sb, const char *pathname) 00199 { 00200 int fd; 00201 ssize_t n; 00202 char *end; 00203 char *interpreter_pathname; 00204 char *bp; 00205 char block[512]; 00206 char qintname[PATH_MAX + 1]; 00207 explain_string_buffer_t qintname_sb; 00208 00209 fd = open(pathname, O_RDONLY); 00210 if (fd < 0) 00211 return -1; 00212 n = read(fd, block, sizeof(block) - 1); 00213 close(fd); 00214 if (n < 4) 00215 return -1; 00216 end = block + n; 00217 if (block[0] != '#') 00218 return -1; 00219 if (block[1] != '!') 00220 return -1; 00221 bp = block + 2; 00222 while (bp < end && (*bp == ' ' || *bp == '\t')) 00223 ++bp; 00224 if (bp >= end) 00225 return -1; 00226 interpreter_pathname = bp; 00227 ++bp; 00228 while (bp < end && !isspace(*bp)) 00229 ++bp; 00230 *bp = '\0'; 00231 00232 explain_string_buffer_init(&qintname_sb, qintname, sizeof(qintname)); 00233 explain_string_buffer_puts_quoted(&qintname_sb, interpreter_pathname); 00234 00235 explain_string_buffer_printf_gettext 00236 ( 00237 sb, 00238 /* 00239 * xgettext: This message is used to explain an EACCES error, 00240 * where nested #! interpreter files are attempted. 00241 * 00242 * %1$s => The quoted pathname of the first file that contains an 00243 * interpreter (#!) line, that points at yet another 00244 * interpreted file. 00245 */ 00246 i18n("too many levels of interpreters (%s)"), 00247 qintname 00248 ); 00249 return 0; 00250 } 00251 00252 00253 static void 00254 directory_does_not_exist(explain_string_buffer_t *sb, const char *caption, 00255 const char *dirname) 00256 { 00257 char subject[PATH_MAX + 50]; 00258 explain_string_buffer_t subject_sb; 00259 00260 explain_string_buffer_init(&subject_sb, subject, sizeof(subject)); 00261 explain_buffer_caption_name_type(&subject_sb, caption, dirname, S_IFDIR); 00262 explain_string_buffer_printf_gettext 00263 ( 00264 sb, 00265 /* 00266 * xgettext: This message is used when a path is being used as a 00267 * directory, when does not exist. 00268 * 00269 * %1$s => the name of the system call argument, the quoted path 00270 * and the expected file type ("directory", already translated). 00271 */ 00272 i18n("%s does not exist"), 00273 subject 00274 ); 00275 } 00276 00277 00278 static void 00279 not_a_directory(explain_string_buffer_t *sb, const char *caption, 00280 const char *dir, const struct stat *st) 00281 { 00282 char subject[PATH_MAX + 50]; 00283 explain_string_buffer_t subject_sb; 00284 00285 explain_string_buffer_init(&subject_sb, subject, sizeof(subject)); 00286 explain_buffer_caption_name_type(&subject_sb, caption, dir, -1); 00287 explain_buffer_wrong_file_type_st(sb, st, subject, S_IFDIR); 00288 } 00289 00290 00291 static void 00292 no_such_directory_entry(explain_string_buffer_t *sb, const char *comp, 00293 int comp_st_mode, const char *dir_caption, const char *dir, int dir_st_mode) 00294 { 00295 char part1[NAME_MAX * 4 + 100]; 00296 explain_string_buffer_t part1_sb; 00297 char part2[PATH_MAX * 4 + 100]; 00298 explain_string_buffer_t part2_sb; 00299 00300 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00301 explain_buffer_caption_name_type(&part1_sb, 0, comp, comp_st_mode); 00302 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00303 explain_buffer_caption_name_type 00304 ( 00305 &part2_sb, 00306 dir_caption, 00307 dir, 00308 dir_st_mode 00309 ); 00310 00311 explain_string_buffer_printf_gettext 00312 ( 00313 sb, 00314 /* 00315 * xgettext: This message is used when directory does not have a 00316 * directory entry for the named component. 00317 * 00318 * Different language grammars may need to rearrange the parts. 00319 * 00320 * %1$s => The name of the offending path component (will never have 00321 * slashes). It will be quoted. 00322 * %2$s => The name of the directory that contains the problematic 00323 * component; it may have zero, one or more slashes in it. Will 00324 * include the name of the function call argument, the name of 00325 * the directory, and the file type "directory". 00326 */ 00327 i18n("there is no %s in the %s"), 00328 part1, 00329 part2 00330 ); 00331 } 00332 00333 00334 static void 00335 not_possible_to_execute(explain_string_buffer_t *sb, const char *caption, 00336 const char *name, int st_mode) 00337 { 00338 char ftype[NAME_MAX * 4 + 50]; 00339 explain_string_buffer_t ftype_sb; 00340 00341 explain_string_buffer_init(&ftype_sb, ftype, sizeof(ftype)); 00342 explain_buffer_caption_name_type(&ftype_sb, caption, name, st_mode); 00343 00344 explain_string_buffer_printf_gettext 00345 ( 00346 sb, 00347 /* 00348 * xgettext: This message is issued when a user attempts to 00349 * execute something that is not a file, such as a block special 00350 * device. 00351 * 00352 * %1$s => the name of the system call argument, the name of the 00353 * final path component and the type of the file. 00354 */ 00355 i18n("it is not possible to execute the %s, " 00356 "only regular files can be executed"), 00357 ftype 00358 ); 00359 } 00360 00361 00362 static void 00363 does_not_have_search_permission(explain_string_buffer_t *sb, 00364 const char *comp, const struct stat *comp_st, const char *caption, 00365 const char *dir, const struct stat *dir_st, 00366 const explain_have_identity_t *hip) 00367 { 00368 char part1[NAME_MAX * 4 + 100]; 00369 explain_string_buffer_t part1_sb; 00370 char part2[PATH_MAX * 4 + 100]; 00371 explain_string_buffer_t part2_sb; 00372 00373 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00374 explain_buffer_caption_name_type_st(&part1_sb, 0, comp, comp_st); 00375 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00376 explain_buffer_caption_name_type_st 00377 ( 00378 &part2_sb, 00379 caption, 00380 dir, 00381 dir_st 00382 ); 00383 00384 explain_string_buffer_printf_gettext 00385 ( 00386 sb, 00387 /* 00388 * xgettext: This message is used when a process does not have 00389 * search permission to a directory it attempts to traverse. 00390 * Different language grammars may need to rearrange the parts. 00391 * 00392 * %1$s => The name of the component of the path, the subdirectory in 00393 * question (will never have slashes). It will in clude the 00394 * name of the file, and the file type "directory". 00395 * %2$s => The name of the directory that contains the subdirectory in 00396 * question; it may have zero, one or more slashes in it. Will 00397 * include the name of the function call argument, the name of 00398 * the directory, and the file type "directory". 00399 */ 00400 i18n("the process does not have search permission to the %s in " 00401 "the %s"), 00402 part1, 00403 part2 00404 ); 00405 explain_explain_search_permission(sb, comp_st, hip); 00406 } 00407 00408 00409 static void 00410 does_not_have_search_permission1(explain_string_buffer_t *sb, 00411 const char *caption, const char *dir, const struct stat *dir_st, 00412 const explain_have_identity_t *hip) 00413 { 00414 char dir_part[PATH_MAX + 100]; 00415 explain_string_buffer_t dir_part_sb; 00416 00417 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00418 explain_buffer_caption_name_type_st 00419 ( 00420 &dir_part_sb, 00421 caption, 00422 dir, 00423 dir_st 00424 ); 00425 00426 explain_string_buffer_printf_gettext 00427 ( 00428 sb, 00429 /* 00430 * xgettext: This message is used when a process does not have 00431 * search permission to a directory it attempts to traverse. 00432 * (Only used for problems with "." and "/".) 00433 * Different language grammars may need to rearrange the parts. 00434 * 00435 * %1$s => The pathname, the directory in question. It will 00436 * include the name of the function call argument, the 00437 * name of the directory, file type "directory". 00438 */ 00439 i18n("the process does not have search permission to the %s"), 00440 dir_part 00441 ); 00442 explain_explain_search_permission(sb, dir_st, hip); 00443 } 00444 00445 00446 static void 00447 does_not_have_execute_permission(explain_string_buffer_t *sb, 00448 const char *comp, const struct stat *comp_st, const char *caption, 00449 const char *dir, const struct stat *dir_st, 00450 const explain_have_identity_t *hip) 00451 { 00452 char final_part[NAME_MAX * 4 + 100]; 00453 explain_string_buffer_t final_part_sb; 00454 char dir_part[PATH_MAX * 4 + 100]; 00455 explain_string_buffer_t dir_part_sb; 00456 00457 explain_string_buffer_init 00458 ( 00459 &final_part_sb, 00460 final_part, 00461 sizeof(final_part) 00462 ); 00463 explain_buffer_caption_name_type_st(&final_part_sb, 0, comp, comp_st); 00464 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00465 explain_buffer_caption_name_type_st(&dir_part_sb, caption, dir, dir_st); 00466 00467 explain_string_buffer_printf_gettext 00468 ( 00469 sb, 00470 /* 00471 * xgettext: This message is used when a process does not have 00472 * execute permission to something it attempts to execute; for 00473 * example, one of the execve calls, or similar. 00474 * Different language grammars may need to rearrange the parts. 00475 * 00476 * %1$s => the name of the final component of the path, the 00477 * regular file in question (will never have slashes). 00478 * It will in clude the name of the file, and the file 00479 * type "regular file". 00480 * %2$s => the name of the directory that contains the regular 00481 * file to be executed; it may have zero, one or more 00482 * slashes in it. Will include the name of the function 00483 * call argument, the name of the directory, and the 00484 * file type "directory". 00485 */ 00486 i18n("the process does not have execute permission to the %s in " 00487 "the %s"), 00488 final_part, 00489 dir_part 00490 ); 00491 explain_explain_execute_permission(sb, comp_st, hip); 00492 } 00493 00494 00495 static void 00496 does_not_have_read_permission(explain_string_buffer_t *sb, const char *comp, 00497 const struct stat *comp_st, const char *caption, const char *dir, 00498 const struct stat *dir_st, const explain_have_identity_t *hip) 00499 { 00500 char final_part[NAME_MAX * 4 + 100]; 00501 explain_string_buffer_t final_part_sb; 00502 char dir_part[PATH_MAX * 4 + 100]; 00503 explain_string_buffer_t dir_part_sb; 00504 00505 explain_string_buffer_init 00506 ( 00507 &final_part_sb, 00508 final_part, 00509 sizeof(final_part) 00510 ); 00511 explain_buffer_caption_name_type_st(&final_part_sb, 0, comp, comp_st); 00512 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00513 explain_buffer_caption_name_type_st(&dir_part_sb, caption, dir, dir_st); 00514 00515 explain_string_buffer_printf_gettext 00516 ( 00517 sb, 00518 /* 00519 * xgettext: This message is used when a process does not have 00520 * read permission to something it attempts to 00521 * open for reading; for example, open() or fopen(). 00522 * Different language grammars may need to rearrange the parts. 00523 * 00524 * %1$s => the name of the final component of the path, the 00525 * regular file in question (will never have slashes). 00526 * It will include the name of the file, and the file 00527 * type "regular file". 00528 * %2$s => the name of the directory that contains the regular 00529 * file to be executed; it may have zero, one or more 00530 * slashes in it. Will include the name of the function 00531 * call argument, the name of the directory, and the 00532 * file type "directory". 00533 */ 00534 i18n("the process does not have read permission to the %s in the %s"), 00535 final_part, 00536 dir_part 00537 ); 00538 explain_explain_read_permission(sb, comp_st, hip); 00539 } 00540 00541 00542 static void 00543 does_not_have_write_permission(explain_string_buffer_t *sb, const char *comp, 00544 const struct stat *comp_st, const char *caption, const char *dir, 00545 const struct stat *dir_st, const explain_have_identity_t *hip) 00546 { 00547 char final_part[NAME_MAX * 4 + 100]; 00548 explain_string_buffer_t final_part_sb; 00549 char dir_part[PATH_MAX * 4 + 100]; 00550 explain_string_buffer_t dir_part_sb; 00551 00552 explain_string_buffer_init 00553 ( 00554 &final_part_sb, 00555 final_part, 00556 sizeof(final_part) 00557 ); 00558 explain_buffer_caption_name_type_st(&final_part_sb, 0, comp, comp_st); 00559 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00560 explain_buffer_caption_name_type_st(&dir_part_sb, caption, dir, dir_st); 00561 00562 explain_string_buffer_printf_gettext 00563 ( 00564 sb, 00565 /* 00566 * xgettext: This message is used when a process does not have 00567 * write permission to something it attempts to 00568 * open for writing; for example, open() or fopen(). 00569 * Different language grammars may need to rearrange the parts. 00570 * 00571 * %1$s => the name of the final component of the path, the 00572 * regular file in question (will never have slashes). 00573 * It will include the name of the file, and the file 00574 * type "regular file". 00575 * %2$s => the name of the directory that contains the regular 00576 * file to be executed; it may have zero, one or more 00577 * slashes in it. Will include the name of the function 00578 * call argument, the name of the directory, and the 00579 * file type "directory". 00580 */ 00581 i18n("the process does not have write permission to the %s in the %s"), 00582 final_part, 00583 dir_part 00584 ); 00585 explain_explain_write_permission(sb, comp_st, hip); 00586 } 00587 00588 00589 static void 00590 does_not_have_new_directory_entry_permission(explain_string_buffer_t *sb, 00591 const char *caption, const char *dir, const struct stat *dir_st, 00592 const char *comp, int comp_st_mode, const explain_have_identity_t *hip) 00593 { 00594 char dir_part[PATH_MAX * 4 + 100]; 00595 explain_string_buffer_t dir_part_sb; 00596 char final_part[NAME_MAX * 4 + 100]; 00597 explain_string_buffer_t final_part_sb; 00598 00599 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00600 explain_buffer_caption_name_type_st(&dir_part_sb, caption, dir, dir_st); 00601 explain_string_buffer_init 00602 ( 00603 &final_part_sb, 00604 final_part, 00605 sizeof(final_part) 00606 ); 00607 explain_buffer_caption_name_type(&final_part_sb, 0, comp, comp_st_mode); 00608 00609 explain_string_buffer_printf_gettext 00610 ( 00611 sb, 00612 /* 00613 * xgettext: This message is used when a process does not have write 00614 * permission to a directoryin order to create a new directory entry; 00615 * for example creat(), mkdir(), symlink(), etc. 00616 * Different language grammars may need to rearrange the parts. 00617 * 00618 * %1$s => The name of the directory that is to receive the new 00619 * directory entry; it may have zero, one or more slashes in it. 00620 * Will include the name of the function call argument, the name 00621 * of the directory, and the file type "directory". 00622 * %2$s => The name of the final component of the path, the 00623 * new directory entry in question (will never have slashes). 00624 * It will include the name of the new file, and the file type. 00625 */ 00626 i18n("the process does not have write permission to the %s, this is " 00627 "needed to create the directory entry for the %s"), 00628 dir_part, 00629 final_part 00630 ); 00631 explain_explain_write_permission(sb, dir_st, hip); 00632 } 00633 00634 00635 static void 00636 dangling_symbolic_link(explain_string_buffer_t *sb, const char *comp, 00637 int comp_st_mode, const char *caption, const char *dir, int dir_st_mode, 00638 const char *garbage) 00639 { 00640 char final_part[NAME_MAX * 2 + 100]; 00641 explain_string_buffer_t final_part_sb; 00642 char dir_part[PATH_MAX * 2 + 100]; 00643 explain_string_buffer_t dir_part_sb; 00644 char dangling_part[PATH_MAX * 2 + 100]; 00645 explain_string_buffer_t dangling_part_sb; 00646 00647 explain_string_buffer_init 00648 ( 00649 &final_part_sb, 00650 final_part, 00651 sizeof(final_part) 00652 ); 00653 explain_buffer_caption_name_type(&final_part_sb, 0, comp, comp_st_mode); 00654 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00655 explain_buffer_caption_name_type 00656 ( 00657 &dir_part_sb, 00658 caption, 00659 dir, 00660 dir_st_mode 00661 ); 00662 explain_string_buffer_init 00663 ( 00664 &dangling_part_sb, 00665 dangling_part, 00666 sizeof(dangling_part) 00667 ); 00668 explain_string_buffer_puts_quoted(&dangling_part_sb, garbage); 00669 00670 explain_string_buffer_printf_gettext 00671 ( 00672 sb, 00673 /* 00674 * xgettext: This message is used when there is a dangling 00675 * symbolic link. 00676 * 00677 * Different language grammars may need to rearrange the parts. 00678 * 00679 * %1$s => The name of the final component of the path, the name of 00680 * symbolic link in question, will include the file type 00681 * "symbolic link", but will never have slashes. 00682 * %2$s => The name of the directory that contains the symbolic link; 00683 * it may have zero, one or more slashes in it. Will include 00684 * the name of the function call argument, the name of the 00685 * directory, and the file type "directory". 00686 * %3$s => the non-existent thing the symbolic link point to 00687 */ 00688 i18n("the %s in the %s refers to %s that does not exist"), 00689 final_part, 00690 dir_part, 00691 dangling_part 00692 ); 00693 } 00694 00695 00696 static void 00697 name_too_long(explain_string_buffer_t *sb, const char *caption, 00698 const char *component, long comp_length, long name_max) 00699 { 00700 char part1[PATH_MAX * 2]; 00701 explain_string_buffer_t part1_sb; 00702 00703 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00704 explain_string_buffer_puts(&part1_sb, caption); 00705 explain_string_buffer_putc(&part1_sb, ' '); 00706 explain_string_buffer_puts_quoted(&part1_sb, component); 00707 00708 explain_string_buffer_printf_gettext 00709 ( 00710 sb, 00711 /* 00712 * xgettext: This message is used when a path name component is 00713 * longer than the system limit (NAME_MAX, not PATH_MAX). 00714 * 00715 * %1$s => the name of the function call argument and the quoted 00716 * text of the offending path component. 00717 */ 00718 i18n("%s component is longer than the system limit"), 00719 part1 00720 ); 00721 explain_string_buffer_printf(sb, " (%ld > %ld)", comp_length, name_max); 00722 } 00723 00724 00725 static void 00726 not_a_subdirectory(explain_string_buffer_t *sb, const char *comp, 00727 int comp_st_mode, const char *caption, const char *dir, int dir_st_mode) 00728 { 00729 char part1[NAME_MAX * 4 + 100]; 00730 explain_string_buffer_t part1_sb; 00731 char part2[PATH_MAX * 4 + 100]; 00732 explain_string_buffer_t part2_sb; 00733 00734 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00735 explain_buffer_caption_name_type(&part1_sb, 0, comp, comp_st_mode); 00736 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00737 explain_buffer_caption_name_type(&part2_sb, caption, dir, dir_st_mode); 00738 00739 explain_string_buffer_printf_gettext 00740 ( 00741 sb, 00742 /* 00743 * xgettext: This message is used when directory has a directory 00744 * entry for the named component, but a directory was expected 00745 * and something else was there instead. 00746 * 00747 * Different language grammars may need to rearrange the parts. 00748 * 00749 * %1$s => The name of the offending path component (will never have 00750 * slashes). It is already quoted. 00751 * %2$s => The name of the directory that contains the problematic 00752 * component; it may have zero, one or more slashes in it. Will 00753 * include the name of the function call argument, the name of 00754 * the directory, and the file type "directory". 00755 */ 00756 i18n("the %s in the %s is being used as a directory when it is not"), 00757 part1, 00758 part2 00759 ); 00760 } 00761 00762 00763 static void 00764 wrong_file_type(explain_string_buffer_t *sb, const char *caption, 00765 const char *dir, int dir_st_mode, const char *comp, int comp_st_mode, 00766 int wanted_st_mode) 00767 { 00768 char part1[PATH_MAX * 4 + 100]; 00769 explain_string_buffer_t part1_sb; 00770 char part2[NAME_MAX * 4 + 100]; 00771 explain_string_buffer_t part2_sb; 00772 char part3[100]; 00773 explain_string_buffer_t part3_sb; 00774 00775 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00776 explain_buffer_caption_name_type(&part2_sb, 0, comp, comp_st_mode); 00777 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00778 explain_buffer_caption_name_type(&part1_sb, caption, dir, dir_st_mode); 00779 explain_string_buffer_init(&part3_sb, part3, sizeof(part3)); 00780 explain_buffer_file_type(&part3_sb, wanted_st_mode); 00781 00782 explain_string_buffer_printf_gettext 00783 ( 00784 sb, 00785 /* 00786 * xgettext: This message is used when directory has a directory 00787 * entry for the named component, but a directory was expected 00788 * and something else was there instead. 00789 * 00790 * Different language grammars may need to rearrange the parts. 00791 * 00792 * %1$s => The name of the directory that contains the problematic 00793 * component; it may have zero, one or more slashes in 00794 * it. It will include the name of the function call 00795 * argument, the name of the directory, and the file 00796 * type "directory". 00797 * %2$s => The name of the offending path component and file 00798 * type (will never have slashes). It will be quoted. 00799 * %3$s => the desired file type 00800 */ 00801 i18n("in the %s there is a %s, but it should be a %s"), 00802 part1, 00803 part2, 00804 part3 00805 ); 00806 } 00807 00808 00809 static void 00810 need_dir_write_for_remove_dir_entry(explain_string_buffer_t *sb, 00811 const char *dir_caption, const char *dir_name, int dir_type, 00812 const char *comp_name, int comp_type) 00813 { 00814 explain_string_buffer_t dir_part_sb; 00815 explain_string_buffer_t comp_part_sb; 00816 char dir_part[PATH_MAX * 4 + 100]; 00817 char comp_part[PATH_MAX * 4 + 100]; 00818 00819 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00820 explain_buffer_caption_name_type 00821 ( 00822 &dir_part_sb, 00823 dir_caption, 00824 dir_name, 00825 dir_type 00826 ); 00827 explain_string_buffer_init(&comp_part_sb, comp_part, sizeof(comp_part)); 00828 explain_buffer_caption_name_type(&comp_part_sb, 0, comp_name, comp_type); 00829 00830 explain_string_buffer_printf_gettext 00831 ( 00832 sb, 00833 /* 00834 * xgettext: This message is used when the process has 00835 * insufficient permissions to a directory to remove a directory 00836 * entry from it. 00837 * 00838 * %1$s => The name of the offending system call argument, the 00839 * quoted name of the corresponding directory, and its 00840 * file type already translated. 00841 * %2$s => The quoted name of the directory component, and its 00842 * file type already translated. 00843 */ 00844 i18n("the process does not have write permission to the %s, this " 00845 "is needed to remove the directory entry for the %s"), 00846 dir_part, 00847 comp_part 00848 ); 00849 } 00850 00851 00852 static void 00853 explain_sticky_bit_vs_unlink(explain_string_buffer_t *sb, 00854 const explain_have_identity_t *hip, const struct stat *dir_st, 00855 const struct stat *file_st) 00856 { 00857 explain_string_buffer_t proc_part_sb; 00858 explain_string_buffer_t dir_part_sb; 00859 explain_string_buffer_t file_part_sb; 00860 explain_string_buffer_t ftype_sb; 00861 char proc_part[100]; 00862 char dir_part[100]; 00863 char file_part[100]; 00864 char ftype[100]; 00865 00866 explain_string_buffer_init(&proc_part_sb, proc_part, sizeof(proc_part)); 00867 explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part)); 00868 explain_string_buffer_init(&file_part_sb, file_part, sizeof(file_part)); 00869 explain_string_buffer_init(&ftype_sb, ftype, sizeof(ftype)); 00870 00871 explain_buffer_uid(&proc_part_sb, hip->uid); 00872 explain_buffer_uid(&dir_part_sb, dir_st->st_uid); 00873 explain_buffer_uid(&file_part_sb, file_st->st_uid); 00874 explain_buffer_file_type_st(&ftype_sb, file_st); 00875 00876 explain_string_buffer_puts(sb, ", "); 00877 explain_string_buffer_printf_gettext 00878 ( 00879 sb, 00880 /* 00881 * %1$s => the kind of UID, either "effective UID" or "real 00882 * UID", already translated 00883 * %2$s => the process's UID and the corresponding login name, 00884 * already quoted 00885 * %3$s => the file's UID and the corresponding login name, 00886 * already quoted 00887 * %4$s => the type of file to be removed (e.g. "regular file"), 00888 * already translated 00889 * %5$s => the directory's UID and the corresponding login name, 00890 * already quoted 00891 */ 00892 i18n("the directory has the sticky bit (S_ISVTX) set and the " 00893 "process's %s %s is neither the owner UID %s of the %s " 00894 "to be removed, nor the owner UID %s of the directory " 00895 "containing it"), 00896 explain_have_identity_kind_of_uid(hip), 00897 proc_part, 00898 file_part, 00899 ftype, 00900 dir_part 00901 ); 00902 explain_buffer_dac_fowner(sb); 00903 } 00904 00905 00906 static int 00907 current_directory_confusing(void) 00908 { 00909 char parent_dir[PATH_MAX + 1]; 00910 char child_dir[PATH_MAX + 1]; 00911 00912 /* 00913 * If this process' current directory differs from that of the 00914 * parent process' current directory, it means that the user may 00915 * well have a different idea of "the current directory" than this 00916 * process does. 00917 */ 00918 if (!explain_getppcwd(parent_dir, sizeof(parent_dir))) 00919 return 1; 00920 if (!getcwd(child_dir, sizeof(child_dir))) 00921 return 1; 00922 return (0 != strcmp(parent_dir, child_dir)); 00923 } 00924 00925 00926 static int 00927 is_ok_pathname_caption(const char *caption) 00928 { 00929 /* most of them */ 00930 if (0 == strcmp(caption, "pathname")) 00931 return 1; 00932 /* rename */ 00933 if (0 == strcmp(caption, "oldpath")) 00934 return 1; 00935 /* rename */ 00936 if (0 == strcmp(caption, "newpath")) 00937 return 1; 00938 00939 /* mount */ 00940 if (0 == strcmp(caption, "source")) 00941 return 1; 00942 /* mount */ 00943 if (0 == strcmp(caption, "target")) 00944 return 1; 00945 00946 /* heuristic */ 00947 return !strchr(caption, '/'); 00948 } 00949 00950 00951 int 00952 explain_buffer_errno_path_resolution(explain_string_buffer_t *sb, 00953 int expected_errno, const char *initial_pathname, const char *caption, 00954 const explain_final_t *final_component) 00955 { 00956 char pathname[PATH_MAX * 2 + 1]; 00957 explain_string_buffer_t pathname_buf; 00958 int number_of_symlinks_followed; 00959 const char *pp; 00960 char lookup_directory[PATH_MAX + 1]; 00961 explain_string_buffer_t lookup_directory_buf; 00962 char **symlinks_so_far; 00963 int symloop_max; 00964 long path_max; 00965 00966 /* 00967 * It's easy to pass pathname twice, rather than pathname and 00968 * "pathname", so we do a little checking. Add to this list if 00969 * something else turns up, but I don't expect any more. 00970 * 00971 * RESIST the temptation to add more, because it actually makes the 00972 * libexplain API inconsistent (at the expense of avoiding lame 00973 * POSIX argument name inconsistencies). 00974 */ 00975 assert(is_ok_pathname_caption(caption)); 00976 00977 if (expected_errno == EMLINK) 00978 expected_errno = ELOOP; 00979 symlinks_so_far = 0; 00980 number_of_symlinks_followed = 0; 00981 00982 /* 00983 * Empty pathname: 00984 * In the original Unix, the empty pathname referred to the current 00985 * directory. Nowadays POSIX decrees that an empty pathname must 00986 * not be resolved successfully. Linux returns ENOENT in this case. 00987 * 00988 * FIXME: is there a way pathconf can tell us which semanrics apply? 00989 * or maybe sysconf? 00990 */ 00991 if (!initial_pathname || !*initial_pathname) 00992 { 00993 #ifdef __sun__ 00994 initial_pathname = "."; 00995 #else 00996 explain_string_buffer_printf 00997 ( 00998 sb, 00999 /* 01000 * xgettext: this explanation is given for paths that are 01001 * the empty string. 01002 * 01003 * %1$s => the name of the relevant system call argument. 01004 */ 01005 i18n("POSIX decrees that an empty %s must not be resolved " 01006 "successfully"), 01007 caption 01008 ); 01009 return 0; 01010 #endif 01011 } 01012 01013 /* 01014 * Deal with some boundary conditions. 01015 * What we want is to always have at least one component. 01016 */ 01017 if (!initial_pathname || !*initial_pathname) 01018 initial_pathname = "."; 01019 else if (all_slash(initial_pathname)) 01020 initial_pathname = "/."; 01021 01022 path_max = final_component->path_max; 01023 if (path_max < 0) 01024 path_max = pathconf(initial_pathname, _PC_PATH_MAX); 01025 if (path_max <= 0) 01026 path_max = PATH_MAX; 01027 01028 if (expected_errno == ENAMETOOLONG) 01029 { 01030 size_t len; 01031 01032 len = strlen(initial_pathname); 01033 if (len > (size_t)path_max) 01034 { 01035 explain_string_buffer_printf_gettext 01036 ( 01037 sb, 01038 /* 01039 * xgettext: This message is used when a pathname 01040 * exceeds the maximum (system specific) path name 01041 * length (in bytes, not characters). 01042 * 01043 * %1$s => the name of the offending system call argument 01044 */ 01045 i18n("%s exceeds the system maximum path length"), 01046 caption 01047 ); 01048 explain_string_buffer_printf 01049 ( 01050 sb, 01051 " (%ld > %ld)", 01052 (long)len, 01053 path_max 01054 ); 01055 return 0; 01056 } 01057 } 01058 01059 explain_string_buffer_init(&pathname_buf, pathname, sizeof(pathname)); 01060 if (initial_pathname[0] != '/' && current_directory_confusing()) 01061 { 01062 if (getcwd(pathname, sizeof(pathname) - 1)) 01063 { 01064 pathname_buf.position = strlen(pathname); 01065 explain_string_buffer_putc(&pathname_buf, '/'); 01066 } 01067 } 01068 explain_string_buffer_puts(&pathname_buf, initial_pathname); 01069 01070 /* 01071 * Trailing slashes 01072 * If a pathname ends in a '/', that forces resolution of the 01073 * preceding component as in Step 2: it has to exist and resolve 01074 * to a directory. Otherwise a trailing '/' is ignored. (Or, 01075 * equivalently, a pathname with a trailing '/' is equivalent to the 01076 * pathname obtained by appending '.' to it.) 01077 */ 01078 if (pathname[pathname_buf.position - 1] == '/') 01079 explain_string_buffer_putc(&pathname_buf, '.'); 01080 01081 /* 01082 * Try to get the system's idea of the loop maximum. 01083 */ 01084 symloop_max = explain_symloopmax(); 01085 01086 symlinks_so_far = malloc(2 * symloop_max * sizeof(char *)); 01087 if 01088 ( 01089 !symlinks_so_far 01090 && 01091 (expected_errno == ELOOP || expected_errno == EMLINK) 01092 ) 01093 return -1; 01094 01095 pp = pathname; 01096 01097 /* 01098 * Set the current lookup directory to the starting lookup directory. 01099 */ 01100 explain_string_buffer_init 01101 ( 01102 &lookup_directory_buf, 01103 lookup_directory, 01104 sizeof(lookup_directory) 01105 ); 01106 explain_string_buffer_puts 01107 ( 01108 &lookup_directory_buf, 01109 (*pp == '/' ? "/" : ".") 01110 ); 01111 while (*pp == '/') 01112 ++pp; 01113 01114 /* 01115 * Walk along the path 01116 */ 01117 for (;;) 01118 { 01119 char component[PATH_MAX + 1]; /* deliberately not NAME_MAX */ 01120 explain_string_buffer_t component_buf; 01121 char intermediate_path[PATH_MAX + 1]; 01122 explain_string_buffer_t intermediate_path_buf; 01123 int final; 01124 int lookup_directory_writable; 01125 struct stat lookup_directory_st; 01126 struct stat intermediate_path_st; 01127 01128 /* 01129 * Check that the lookup directory will play ball. 01130 */ 01131 if (lstat(lookup_directory, &lookup_directory_st) != 0) 01132 { 01133 int lookup_directory_st_errnum = errno; 01134 if (lookup_directory_st_errnum != ENOENT) 01135 goto return_minus_1; 01136 directory_does_not_exist(sb, caption, lookup_directory); 01137 return_0: 01138 if (symlinks_so_far) 01139 { 01140 int j; 01141 01142 for (j = 0; j < number_of_symlinks_followed; ++j) 01143 free(symlinks_so_far[j]); 01144 free(symlinks_so_far); 01145 } 01146 return 0; 01147 } 01148 01149 /* 01150 * The lookup directory is never a symbolic link. 01151 * We take care to ensure it, see below. 01152 */ 01153 assert(!S_ISLNK(lookup_directory_st.st_mode)); 01154 01155 if (!S_ISDIR(lookup_directory_st.st_mode)) 01156 { 01157 /* 01158 * If the lookup_directory is found, but is not a directory, 01159 * an ENOTDIR error is returned ("Not a directory"). 01160 */ 01161 not_a_directory 01162 ( 01163 sb, 01164 caption, 01165 lookup_directory, 01166 &lookup_directory_st 01167 ); 01168 goto return_0; 01169 } 01170 01171 /* 01172 * If the process does not have search permission on the current 01173 * lookup directory, an EACCES error is returned ("Permission 01174 * denied"). 01175 */ 01176 if 01177 ( 01178 !explain_have_search_permission 01179 ( 01180 &lookup_directory_st, 01181 &final_component->id 01182 ) 01183 ) 01184 { 01185 does_not_have_search_permission1 01186 ( 01187 sb, 01188 caption, 01189 lookup_directory, 01190 &lookup_directory_st, 01191 &final_component->id 01192 ); 01193 goto return_0; 01194 } 01195 01196 lookup_directory_writable = 01197 explain_have_write_permission 01198 ( 01199 &lookup_directory_st, 01200 &final_component->id 01201 ); 01202 01203 /* 01204 * Extract the next path component. 01205 * A path component is a substring delimited by '/' characters. 01206 */ 01207 explain_string_buffer_init 01208 ( 01209 &component_buf, 01210 component, 01211 sizeof(component) 01212 ); 01213 for (;;) 01214 { 01215 unsigned char c = *pp++; 01216 switch (c) 01217 { 01218 default: 01219 explain_string_buffer_putc(&component_buf, c); 01220 continue; 01221 01222 case '\0': 01223 --pp; 01224 break; 01225 01226 case '/': 01227 break; 01228 } 01229 break; 01230 } 01231 while (*pp == '/') 01232 ++pp; 01233 final = !*pp; 01234 01235 /* 01236 * Check the length of the component 01237 */ 01238 if (expected_errno == ENAMETOOLONG) 01239 { 01240 long no_trunc; 01241 int silent_truncate; 01242 long name_max; 01243 01244 /* 01245 * Components can only be too long if the file system 01246 * they are on does not silently truncate over-long path 01247 * components. 01248 */ 01249 no_trunc = pathconf(lookup_directory, _PC_NO_TRUNC); 01250 silent_truncate = (no_trunc == 0); 01251 01252 name_max = pathconf(lookup_directory, _PC_NAME_MAX); 01253 if (name_max <= 0) 01254 name_max = NAME_MAX; 01255 if (!silent_truncate && component_buf.position > (size_t)name_max) 01256 { 01257 name_too_long 01258 ( 01259 sb, 01260 caption, 01261 component, 01262 (long)component_buf.position, 01263 name_max 01264 ); 01265 goto return_0; 01266 } 01267 if (component_buf.position > (size_t)name_max) 01268 { 01269 explain_string_buffer_truncate(&component_buf, name_max); 01270 } 01271 } 01272 else 01273 { 01274 /* 01275 * Silently truncate over-long path components. 01276 */ 01277 long name_max = pathconf(lookup_directory, _PC_NAME_MAX); 01278 if (name_max <= 0) 01279 name_max = NAME_MAX; 01280 if (component_buf.position > (size_t)name_max) 01281 { 01282 explain_string_buffer_truncate(&component_buf, name_max); 01283 } 01284 } 01285 01286 /* 01287 * Build the intermediate path by joining the lookup_directory 01288 * and the component. 01289 */ 01290 explain_string_buffer_init 01291 ( 01292 &intermediate_path_buf, 01293 intermediate_path, 01294 sizeof(intermediate_path) 01295 ); 01296 explain_string_buffer_puts(&intermediate_path_buf, lookup_directory); 01297 explain_string_buffer_path_join(&intermediate_path_buf, component); 01298 01299 if (lstat(intermediate_path, &intermediate_path_st) < 0) 01300 { 01301 int intermediate_path_st_errnum; 01302 01303 intermediate_path_st_errnum = errno; 01304 if (!final) 01305 { 01306 if (intermediate_path_st_errnum == ENOENT) 01307 { 01308 no_such_directory_entry 01309 ( 01310 sb, 01311 component, 01312 S_IFDIR, 01313 caption, 01314 lookup_directory, 01315 lookup_directory_st.st_mode 01316 ); 01317 01318 /* 01319 * If it was a typo, see if we can find something similar. 01320 */ 01321 look_for_similar(sb, lookup_directory, component); 01322 goto return_0; 01323 } 01324 01325 /* 01326 * intermediate path of non-final component returned 01327 * unexpected error to lstat (i.e. not ENOENT), bail out 01328 */ 01329 goto return_minus_1; 01330 } 01331 01332 /* 01333 * At this point, we know it is a final component. 01334 */ 01335 if (final_component->must_not_exist) 01336 { 01337 if (intermediate_path_st_errnum == ENOENT) 01338 { 01339 if (!lookup_directory_writable) 01340 { 01341 /* EACCES */ 01342 does_not_have_new_directory_entry_permission 01343 ( 01344 sb, 01345 caption, 01346 lookup_directory, 01347 &lookup_directory_st, 01348 component, 01349 final_component->st_mode, 01350 &final_component->id 01351 ); 01352 goto return_0; 01353 } 01354 01355 /* 01356 * yay, 01357 * but we were looking for an error 01358 * and didn't find it 01359 */ 01360 goto return_minus_1; 01361 } 01362 01363 /* 01364 * The final component is not meant to exist, but the 01365 * final component gave an unexpected error to lstat 01366 * (i.e. not ENOENT), bail out 01367 */ 01368 goto return_minus_1; 01369 } 01370 if (final_component->must_exist) 01371 { 01372 if (intermediate_path_st_errnum != ENOENT) 01373 { 01374 /* 01375 * The final component is meant to exist, but the 01376 * final component gave an unexpected error to 01377 * lstat (i.e. not success and not ENOENT), bail out 01378 */ 01379 goto return_minus_1; 01380 } 01381 01382 no_such_directory_entry 01383 ( 01384 sb, 01385 component, 01386 final_component->st_mode, 01387 caption, 01388 lookup_directory, 01389 lookup_directory_st.st_mode 01390 ); 01391 01392 /* 01393 * If it was a typo, see if we can find something similar. 01394 */ 01395 look_for_similar(sb, lookup_directory, component); 01396 01397 goto return_0; 01398 } 01399 01400 /* 01401 * Creating a new file requires write permission in the 01402 * containing directory. 01403 */ 01404 if 01405 ( 01406 (expected_errno == EACCES || expected_errno == EPERM) 01407 && 01408 intermediate_path_st_errnum == ENOENT 01409 && 01410 final_component->want_to_create 01411 && 01412 !lookup_directory_writable 01413 ) 01414 { 01415 does_not_have_new_directory_entry_permission 01416 ( 01417 sb, 01418 caption, 01419 lookup_directory, 01420 &lookup_directory_st, 01421 component, 01422 final_component->st_mode, 01423 &final_component->id 01424 ); 01425 01426 /* 01427 * What if they meant to overwrite an existing file? 01428 * That would not have needed write permission on the 01429 * containing directory. 01430 */ 01431 look_for_similar(sb, lookup_directory, component); 01432 goto return_0; 01433 } 01434 01435 /* 01436 * It's OK if the final component path doesn't exist, 01437 * but we were looking for an error and didn't find one. 01438 */ 01439 goto return_minus_1; 01440 } 01441 01442 /* 01443 * At this point, we know that the intermediate path exists. 01444 */ 01445 if 01446 ( 01447 S_ISLNK(intermediate_path_st.st_mode) 01448 && 01449 (!final || final_component->follow_symlink) 01450 ) 01451 { 01452 int n; 01453 char rlb[PATH_MAX + 1]; 01454 01455 /* 01456 * Have we read this symlink before? 01457 */ 01458 if (symlinks_so_far) 01459 { 01460 int j; 01461 01462 for (j = 0; j < number_of_symlinks_followed; ++j) 01463 { 01464 if (0 == strcmp(symlinks_so_far[j], intermediate_path)) 01465 { 01466 char qs[PATH_MAX * 2 + 1]; 01467 explain_string_buffer_t qs_sb; 01468 01469 explain_string_buffer_init(&qs_sb, qs, sizeof(qs)); 01470 explain_string_buffer_puts_quoted 01471 ( 01472 &qs_sb, 01473 intermediate_path 01474 ); 01475 explain_string_buffer_printf_gettext 01476 ( 01477 sb, 01478 /* 01479 * xgettext: This message is used when a 01480 * symbolic link loop has been detected, 01481 * usually as a result of an ELOOP error. 01482 * 01483 * %1$s => The name of the offending system 01484 * call argument 01485 * %2$s => The path of the first symlink in 01486 * the loop, already quoted. 01487 */ 01488 i18n("a symbolic link loop was encountered in %s, " 01489 "starting at %s"), 01490 caption, 01491 qs 01492 ); 01493 goto return_0; 01494 } 01495 } 01496 } 01497 01498 /* 01499 * Follow the symbolic link, that way we can give the actual 01500 * path in our error messages. 01501 */ 01502 n = readlink(intermediate_path, rlb, sizeof(rlb) - 1); 01503 if (n >= 0) 01504 { 01505 char new_pathname[PATH_MAX + 1]; 01506 explain_string_buffer_t new_pathname_buf; 01507 01508 if (symlinks_so_far) 01509 { 01510 size_t len; 01511 char *p; 01512 01513 len = strlen(intermediate_path) + 1; 01514 p = malloc(len); 01515 if (!p) 01516 { 01517 int j; 01518 01519 for (j = 0; j < number_of_symlinks_followed; ++j) 01520 free(symlinks_so_far[j]); 01521 free(symlinks_so_far); 01522 symlinks_so_far = 0; 01523 if (expected_errno == ELOOP || expected_errno == EMLINK) 01524 goto return_minus_1; 01525 } 01526 else 01527 { 01528 memcpy(p, intermediate_path, len); 01529 symlinks_so_far[number_of_symlinks_followed] = p; 01530 } 01531 } 01532 01533 if (n == 0) 01534 { 01535 rlb[0] = '.'; 01536 n = 1; 01537 } 01538 rlb[n] = '\0'; 01539 01540 explain_string_buffer_init 01541 ( 01542 &new_pathname_buf, 01543 new_pathname, 01544 sizeof(new_pathname) 01545 ); 01546 explain_string_buffer_puts(&new_pathname_buf, rlb); 01547 explain_string_buffer_path_join(&new_pathname_buf, pp); 01548 01549 explain_string_buffer_copy(&pathname_buf, &new_pathname_buf); 01550 01551 /* 01552 * Check for dangling symbolic links 01553 */ 01554 explain_string_buffer_init 01555 ( 01556 &intermediate_path_buf, 01557 intermediate_path, 01558 sizeof(intermediate_path) 01559 ); 01560 if (rlb[0] == '/') 01561 { 01562 explain_string_buffer_puts(&intermediate_path_buf, rlb); 01563 } 01564 else 01565 { 01566 explain_string_buffer_puts 01567 ( 01568 &intermediate_path_buf, 01569 lookup_directory 01570 ); 01571 explain_string_buffer_path_join 01572 ( 01573 &intermediate_path_buf, 01574 rlb 01575 ); 01576 } 01577 if 01578 ( 01579 lstat(intermediate_path, &intermediate_path_st) < 0 01580 && 01581 errno == ENOENT 01582 ) 01583 { 01584 dangling_symbolic_link 01585 ( 01586 sb, 01587 component, 01588 S_IFLNK, 01589 caption, 01590 lookup_directory, 01591 lookup_directory_st.st_mode, 01592 rlb 01593 ); 01594 goto return_0; 01595 } 01596 01597 if (rlb[0] == '/') 01598 { 01599 explain_string_buffer_rewind(&lookup_directory_buf); 01600 explain_string_buffer_putc(&lookup_directory_buf, '/'); 01601 } 01602 ++number_of_symlinks_followed; 01603 if (number_of_symlinks_followed >= symloop_max) 01604 { 01605 explain_string_buffer_printf_gettext 01606 ( 01607 sb, 01608 /* 01609 * xgettext: This message is used when too 01610 * may links (ELOOP or EMLINK) are seen when 01611 * resolving a path. 01612 * 01613 * It may ioptionally be followed by the limit, 01614 * in parentheses, so sentence structure that 01615 * works that way would be a plus. 01616 * 01617 * %1$s => The name of the offending system call 01618 * argument. 01619 */ 01620 i18n("too many symbolic links were encountered in %s"), 01621 caption 01622 ); 01623 if (explain_option_dialect_specific()) 01624 { 01625 explain_string_buffer_printf 01626 ( 01627 sb, 01628 " (%d)", 01629 number_of_symlinks_followed 01630 ); 01631 } 01632 goto return_0; 01633 } 01634 pp = pathname; 01635 while (*pp == '/') 01636 ++pp; 01637 continue; 01638 } 01639 } 01640 01641 if (!final) 01642 { 01643 /* 01644 * check that intermediate_path is, in fact, a directory 01645 */ 01646 if (!S_ISDIR(intermediate_path_st.st_mode)) 01647 { 01648 /* ENOTDIR */ 01649 not_a_subdirectory 01650 ( 01651 sb, 01652 component, 01653 intermediate_path_st.st_mode, 01654 caption, 01655 lookup_directory, 01656 lookup_directory_st.st_mode 01657 ); 01658 return 0; 01659 } 01660 01661 explain_string_buffer_copy 01662 ( 01663 &lookup_directory_buf, 01664 &intermediate_path_buf 01665 ); 01666 continue; 01667 } 01668 01669 /* 01670 * At this point, we know that intermediate_path is the final 01671 * path, and we know it *does* exist. 01672 */ 01673 if (final_component->must_not_exist) 01674 { 01675 explain_buffer_eexist5 01676 ( 01677 sb, 01678 component, 01679 intermediate_path_st.st_mode, 01680 lookup_directory, 01681 lookup_directory_st.st_mode 01682 ); 01683 goto return_0; 01684 } 01685 01686 if 01687 ( 01688 final_component->must_be_a_st_mode 01689 && 01690 (intermediate_path_st.st_mode & S_IFMT) != final_component->st_mode 01691 ) 01692 { 01693 wrong_file_type 01694 ( 01695 sb, 01696 caption, 01697 lookup_directory, 01698 lookup_directory_st.st_mode, 01699 component, 01700 intermediate_path_st.st_mode, 01701 final_component->st_mode 01702 ); 01703 goto return_0; 01704 } 01705 01706 if 01707 ( 01708 (expected_errno == EACCES || expected_errno == EPERM) 01709 && 01710 final_component->want_to_modify_inode 01711 && 01712 !explain_have_inode_permission 01713 ( 01714 &intermediate_path_st, 01715 &final_component->id 01716 ) 01717 ) 01718 { 01719 explain_buffer_does_not_have_inode_modify_permission 01720 ( 01721 sb, 01722 component, 01723 &intermediate_path_st, 01724 caption, 01725 lookup_directory, 01726 &lookup_directory_st, 01727 &final_component->id 01728 ); 01729 goto return_0; 01730 } 01731 01732 if 01733 ( 01734 (expected_errno == EACCES || expected_errno == EPERM) 01735 && 01736 final_component->want_to_unlink 01737 && 01738 !lookup_directory_writable 01739 ) 01740 { 01741 if ((lookup_directory_st.st_mode & S_ISVTX) == 0) 01742 { 01743 /* 01744 * No sticky bit set, therefore only need write permissions on 01745 * the lookup directory. 01746 */ 01747 need_dir_write_for_remove_dir_entry 01748 ( 01749 sb, 01750 caption, 01751 lookup_directory, 01752 lookup_directory_st.st_mode, 01753 component, 01754 intermediate_path_st.st_mode 01755 ); 01756 goto return_0; 01757 } 01758 else 01759 { 01760 int uid; 01761 01762 uid = final_component->id.uid; 01763 if 01764 ( 01765 uid != (int)intermediate_path_st.st_uid 01766 && 01767 uid != (int)lookup_directory_st.st_uid 01768 && 01769 !explain_capability_fowner() 01770 ) 01771 { 01772 need_dir_write_for_remove_dir_entry 01773 ( 01774 sb, 01775 caption, 01776 lookup_directory, 01777 lookup_directory_st.st_mode, 01778 component, 01779 intermediate_path_st.st_mode 01780 ); 01781 explain_sticky_bit_vs_unlink 01782 ( 01783 sb, 01784 &final_component->id, 01785 &lookup_directory_st, 01786 &intermediate_path_st 01787 ); 01788 goto return_0; 01789 } 01790 } 01791 } 01792 01793 if (expected_errno == EACCES) 01794 { 01795 if 01796 ( 01797 final_component->want_to_read 01798 && 01799 !explain_have_read_permission 01800 ( 01801 &intermediate_path_st, 01802 &final_component->id 01803 ) 01804 ) 01805 { 01806 does_not_have_read_permission 01807 ( 01808 sb, 01809 component, 01810 &intermediate_path_st, 01811 caption, 01812 lookup_directory, 01813 &lookup_directory_st, 01814 &final_component->id 01815 ); 01816 goto return_0; 01817 } 01818 01819 if 01820 ( 01821 final_component->want_to_write 01822 && 01823 !explain_have_write_permission 01824 ( 01825 &intermediate_path_st, 01826 &final_component->id 01827 ) 01828 ) 01829 { 01830 does_not_have_write_permission 01831 ( 01832 sb, 01833 component, 01834 &intermediate_path_st, 01835 caption, 01836 lookup_directory, 01837 &lookup_directory_st, 01838 &final_component->id 01839 ); 01840 goto return_0; 01841 } 01842 01843 if (final_component->want_to_execute) 01844 { 01845 if 01846 ( 01847 explain_have_execute_permission 01848 ( 01849 &intermediate_path_st, 01850 &final_component->id 01851 ) 01852 ) 01853 { 01854 if 01855 ( 01856 explain_mount_point_noexec(intermediate_path) 01857 && 01858 !explain_capability_dac_override() 01859 ) 01860 { 01861 explain_buffer_gettext 01862 ( 01863 sb, 01864 /* 01865 * xgettext: This message is used when the process 01866 * attempts to execute a regular file which would 01867 * otherwise be executable, except that it resides 01868 * on a file system that is mounted with the 01869 * "noexec" option. 01870 */ 01871 i18n("the executable is on a file system that is " 01872 "mounted with the \"noexec\" option") 01873 ); 01874 explain_buffer_mount_point(sb, intermediate_path); 01875 goto return_0; 01876 } 01877 01878 if 01879 ( 01880 (intermediate_path_st.st_mode & (S_ISUID | S_ISGID)) 01881 && 01882 explain_mount_point_nosuid(intermediate_path) 01883 && 01884 !explain_capability_dac_override() 01885 ) 01886 { 01887 explain_buffer_gettext 01888 ( 01889 sb, 01890 /* 01891 * xgettext: This message is used when the process 01892 * attempts to execute a regular file which would 01893 * otherwise be executable, except that it has the 01894 * set-UID (S_ISUID) or set-GID (S_ISGID) bit set, 01895 * and it resides on a file system that is mounted 01896 * with the "nosuid" option. 01897 */ 01898 i18n("the executable is on a file system that is " 01899 "mounted with the \"nosuid\" option") 01900 ); 01901 explain_buffer_mount_point(sb, intermediate_path); 01902 goto return_0; 01903 } 01904 01905 /* 01906 * If it is a #! script, check the command interpreter. 01907 * (But avoid command interpreter infinite loops.) 01908 */ 01909 if (final_component->follow_interpreter) 01910 { 01911 if (!command_interpreter_broken(sb, intermediate_path)) 01912 goto return_0; 01913 } 01914 else 01915 { 01916 if (!hash_bang(sb, intermediate_path)) 01917 goto return_0; 01918 } 01919 } 01920 else 01921 { 01922 if (!S_ISREG(intermediate_path_st.st_mode)) 01923 { 01924 not_possible_to_execute 01925 ( 01926 sb, 01927 caption, 01928 component, 01929 intermediate_path_st.st_mode 01930 ); 01931 goto return_0; 01932 } 01933 01934 does_not_have_execute_permission 01935 ( 01936 sb, 01937 component, 01938 &intermediate_path_st, 01939 caption, 01940 lookup_directory, 01941 &lookup_directory_st, 01942 &final_component->id 01943 ); 01944 goto return_0; 01945 } 01946 } 01947 01948 if 01949 ( 01950 final_component->want_to_search 01951 && 01952 !explain_have_search_permission 01953 ( 01954 &intermediate_path_st, 01955 &final_component->id 01956 ) 01957 ) 01958 { 01959 does_not_have_search_permission 01960 ( 01961 sb, 01962 component, 01963 &intermediate_path_st, 01964 caption, 01965 lookup_directory, 01966 &lookup_directory_st, 01967 &final_component->id 01968 ); 01969 goto return_0; 01970 } 01971 } 01972 01973 /* 01974 * No error, yay! Except that we were looking for an error, and 01975 * did not find one. 01976 */ 01977 return_minus_1: 01978 if (symlinks_so_far) 01979 { 01980 int k; 01981 01982 for (k = 0; k < number_of_symlinks_followed; ++k) 01983 free(symlinks_so_far[k]); 01984 free(symlinks_so_far); 01985 } 01986 return -1; 01987 } 01988 } 01989 01990 01991 void 01992 explain_final_init(explain_final_t *p) 01993 { 01994 p->want_to_read = 0; 01995 p->want_to_write = 0; 01996 p->want_to_search = 0; 01997 p->want_to_execute = 0; 01998 p->want_to_create = 0; 01999 p->want_to_modify_inode = 0; 02000 p->want_to_unlink = 0; 02001 p->must_exist = 1; 02002 p->must_not_exist = 0; 02003 p->must_be_a_st_mode = 0; 02004 p->follow_symlink = 1; 02005 p->follow_interpreter = 1; 02006 p->st_mode = S_IFREG; 02007 explain_have_identity_init(&p->id); 02008 p->path_max = -1; 02009 } 02010 02011 02012 /* vim: set ts=8 sw=4 et : */