| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/pwd.c |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /* pwd - print current directory | - | ||||||||||||||||||||||||
| 2 | Copyright (C) 1994-2018 Free Software Foundation, Inc. | - | ||||||||||||||||||||||||
| 3 | - | |||||||||||||||||||||||||
| 4 | This program is free software: you can redistribute it and/or modify | - | ||||||||||||||||||||||||
| 5 | it under the terms of the GNU General Public License as published by | - | ||||||||||||||||||||||||
| 6 | the Free Software Foundation, either version 3 of the License, or | - | ||||||||||||||||||||||||
| 7 | (at your option) any later version. | - | ||||||||||||||||||||||||
| 8 | - | |||||||||||||||||||||||||
| 9 | This program is distributed in the hope that it will be useful, | - | ||||||||||||||||||||||||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | - | ||||||||||||||||||||||||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | - | ||||||||||||||||||||||||
| 12 | GNU General Public License for more details. | - | ||||||||||||||||||||||||
| 13 | - | |||||||||||||||||||||||||
| 14 | You should have received a copy of the GNU General Public License | - | ||||||||||||||||||||||||
| 15 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | - | ||||||||||||||||||||||||
| 16 | - | |||||||||||||||||||||||||
| 17 | #include <config.h> | - | ||||||||||||||||||||||||
| 18 | #include <getopt.h> | - | ||||||||||||||||||||||||
| 19 | #include <stdio.h> | - | ||||||||||||||||||||||||
| 20 | #include <sys/types.h> | - | ||||||||||||||||||||||||
| 21 | - | |||||||||||||||||||||||||
| 22 | #include "system.h" | - | ||||||||||||||||||||||||
| 23 | #include "die.h" | - | ||||||||||||||||||||||||
| 24 | #include "error.h" | - | ||||||||||||||||||||||||
| 25 | #include "quote.h" | - | ||||||||||||||||||||||||
| 26 | #include "root-dev-ino.h" | - | ||||||||||||||||||||||||
| 27 | #include "xgetcwd.h" | - | ||||||||||||||||||||||||
| 28 | - | |||||||||||||||||||||||||
| 29 | /* The official name of this program (e.g., no 'g' prefix). */ | - | ||||||||||||||||||||||||
| 30 | #define PROGRAM_NAME "pwd" | - | ||||||||||||||||||||||||
| 31 | - | |||||||||||||||||||||||||
| 32 | #define AUTHORS proper_name ("Jim Meyering") | - | ||||||||||||||||||||||||
| 33 | - | |||||||||||||||||||||||||
| 34 | struct file_name | - | ||||||||||||||||||||||||
| 35 | { | - | ||||||||||||||||||||||||
| 36 | char *buf; | - | ||||||||||||||||||||||||
| 37 | size_t n_alloc; | - | ||||||||||||||||||||||||
| 38 | char *start; | - | ||||||||||||||||||||||||
| 39 | }; | - | ||||||||||||||||||||||||
| 40 | - | |||||||||||||||||||||||||
| 41 | static struct option const longopts[] = | - | ||||||||||||||||||||||||
| 42 | { | - | ||||||||||||||||||||||||
| 43 | {"logical", no_argument, NULL, 'L'}, | - | ||||||||||||||||||||||||
| 44 | {"physical", no_argument, NULL, 'P'}, | - | ||||||||||||||||||||||||
| 45 | {GETOPT_HELP_OPTION_DECL}, | - | ||||||||||||||||||||||||
| 46 | {GETOPT_VERSION_OPTION_DECL}, | - | ||||||||||||||||||||||||
| 47 | {NULL, 0, NULL, 0} | - | ||||||||||||||||||||||||
| 48 | }; | - | ||||||||||||||||||||||||
| 49 | - | |||||||||||||||||||||||||
| 50 | void | - | ||||||||||||||||||||||||
| 51 | usage (int status) | - | ||||||||||||||||||||||||
| 52 | { | - | ||||||||||||||||||||||||
| 53 | if (status != EXIT_SUCCESS)
| 1-2 | ||||||||||||||||||||||||
| 54 | emit_try_help (); executed 1 time by 1 test: end of blockExecuted by:
| 1 | ||||||||||||||||||||||||
| 55 | else | - | ||||||||||||||||||||||||
| 56 | { | - | ||||||||||||||||||||||||
| 57 | printf (_("Usage: %s [OPTION]...\n"), program_name); | - | ||||||||||||||||||||||||
| 58 | fputs (_("\ | - | ||||||||||||||||||||||||
| 59 | Print the full filename of the current working directory.\n\ | - | ||||||||||||||||||||||||
| 60 | \n\ | - | ||||||||||||||||||||||||
| 61 | "), stdout); | - | ||||||||||||||||||||||||
| 62 | fputs (_("\ | - | ||||||||||||||||||||||||
| 63 | -L, --logical use PWD from environment, even if it contains symlinks\n\ | - | ||||||||||||||||||||||||
| 64 | -P, --physical avoid all symlinks\n\ | - | ||||||||||||||||||||||||
| 65 | "), stdout); | - | ||||||||||||||||||||||||
| 66 | fputs (HELP_OPTION_DESCRIPTION, stdout); | - | ||||||||||||||||||||||||
| 67 | fputs (VERSION_OPTION_DESCRIPTION, stdout); | - | ||||||||||||||||||||||||
| 68 | fputs (_("\n\ | - | ||||||||||||||||||||||||
| 69 | If no option is specified, -P is assumed.\n\ | - | ||||||||||||||||||||||||
| 70 | "), stdout); | - | ||||||||||||||||||||||||
| 71 | printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME); | - | ||||||||||||||||||||||||
| 72 | emit_ancillary_info (PROGRAM_NAME); | - | ||||||||||||||||||||||||
| 73 | } executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||||||||||||||
| 74 | exit (status); executed 3 times by 1 test: exit (status);Executed by:
| 3 | ||||||||||||||||||||||||
| 75 | } | - | ||||||||||||||||||||||||
| 76 | - | |||||||||||||||||||||||||
| 77 | static void | - | ||||||||||||||||||||||||
| 78 | file_name_free (struct file_name *p) | - | ||||||||||||||||||||||||
| 79 | { | - | ||||||||||||||||||||||||
| 80 | free (p->buf); | - | ||||||||||||||||||||||||
| 81 | free (p); | - | ||||||||||||||||||||||||
| 82 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 83 | - | |||||||||||||||||||||||||
| 84 | static struct file_name * | - | ||||||||||||||||||||||||
| 85 | file_name_init (void) | - | ||||||||||||||||||||||||
| 86 | { | - | ||||||||||||||||||||||||
| 87 | struct file_name *p = xmalloc (sizeof *p); | - | ||||||||||||||||||||||||
| 88 | - | |||||||||||||||||||||||||
| 89 | /* Start with a buffer larger than PATH_MAX, but beware of systems | - | ||||||||||||||||||||||||
| 90 | on which PATH_MAX is very large -- e.g., INT_MAX. */ | - | ||||||||||||||||||||||||
| 91 | p->n_alloc = MIN (2 * PATH_MAX, 32 * 1024);
| 0 | ||||||||||||||||||||||||
| 92 | - | |||||||||||||||||||||||||
| 93 | p->buf = xmalloc (p->n_alloc); | - | ||||||||||||||||||||||||
| 94 | p->start = p->buf + (p->n_alloc - 1); | - | ||||||||||||||||||||||||
| 95 | p->start[0] = '\0'; | - | ||||||||||||||||||||||||
| 96 | return p; never executed: return p; | 0 | ||||||||||||||||||||||||
| 97 | } | - | ||||||||||||||||||||||||
| 98 | - | |||||||||||||||||||||||||
| 99 | /* Prepend the name S of length S_LEN, to the growing file_name, P. */ | - | ||||||||||||||||||||||||
| 100 | static void | - | ||||||||||||||||||||||||
| 101 | file_name_prepend (struct file_name *p, char const *s, size_t s_len) | - | ||||||||||||||||||||||||
| 102 | { | - | ||||||||||||||||||||||||
| 103 | size_t n_free = p->start - p->buf; | - | ||||||||||||||||||||||||
| 104 | if (n_free < 1 + s_len)
| 0 | ||||||||||||||||||||||||
| 105 | { | - | ||||||||||||||||||||||||
| 106 | size_t half = p->n_alloc + 1 + s_len; | - | ||||||||||||||||||||||||
| 107 | /* Use xnmalloc+free rather than xnrealloc, since with the latter | - | ||||||||||||||||||||||||
| 108 | we'd end up copying the data twice: once via realloc, then again | - | ||||||||||||||||||||||||
| 109 | to align it with the end of the new buffer. With xnmalloc, we | - | ||||||||||||||||||||||||
| 110 | copy it only once. */ | - | ||||||||||||||||||||||||
| 111 | char *q = xnmalloc (2, half); | - | ||||||||||||||||||||||||
| 112 | size_t n_used = p->n_alloc - n_free; | - | ||||||||||||||||||||||||
| 113 | p->start = q + 2 * half - n_used; | - | ||||||||||||||||||||||||
| 114 | memcpy (p->start, p->buf + n_free, n_used); | - | ||||||||||||||||||||||||
| 115 | free (p->buf); | - | ||||||||||||||||||||||||
| 116 | p->buf = q; | - | ||||||||||||||||||||||||
| 117 | p->n_alloc = 2 * half; | - | ||||||||||||||||||||||||
| 118 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 119 | - | |||||||||||||||||||||||||
| 120 | p->start -= 1 + s_len; | - | ||||||||||||||||||||||||
| 121 | p->start[0] = '/'; | - | ||||||||||||||||||||||||
| 122 | memcpy (p->start + 1, s, s_len); | - | ||||||||||||||||||||||||
| 123 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 124 | - | |||||||||||||||||||||||||
| 125 | /* Return a string (malloc'd) consisting of N '/'-separated ".." components. */ | - | ||||||||||||||||||||||||
| 126 | static char * | - | ||||||||||||||||||||||||
| 127 | nth_parent (size_t n) | - | ||||||||||||||||||||||||
| 128 | { | - | ||||||||||||||||||||||||
| 129 | char *buf = xnmalloc (3, n); | - | ||||||||||||||||||||||||
| 130 | char *p = buf; | - | ||||||||||||||||||||||||
| 131 | - | |||||||||||||||||||||||||
| 132 | for (size_t i = 0; i < n; i++)
| 0 | ||||||||||||||||||||||||
| 133 | { | - | ||||||||||||||||||||||||
| 134 | memcpy (p, "../", 3); | - | ||||||||||||||||||||||||
| 135 | p += 3; | - | ||||||||||||||||||||||||
| 136 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 137 | p[-1] = '\0'; | - | ||||||||||||||||||||||||
| 138 | return buf; never executed: return buf; | 0 | ||||||||||||||||||||||||
| 139 | } | - | ||||||||||||||||||||||||
| 140 | - | |||||||||||||||||||||||||
| 141 | /* Determine the basename of the current directory, where DOT_SB is the | - | ||||||||||||||||||||||||
| 142 | result of lstat'ing "." and prepend that to the file name in *FILE_NAME. | - | ||||||||||||||||||||||||
| 143 | Find the directory entry in '..' that matches the dev/i-node of DOT_SB. | - | ||||||||||||||||||||||||
| 144 | Upon success, update *DOT_SB with stat information of '..', chdir to '..', | - | ||||||||||||||||||||||||
| 145 | and prepend "/basename" to FILE_NAME. | - | ||||||||||||||||||||||||
| 146 | Otherwise, exit with a diagnostic. | - | ||||||||||||||||||||||||
| 147 | PARENT_HEIGHT is the number of levels '..' is above the starting directory. | - | ||||||||||||||||||||||||
| 148 | The first time this function is called (from the initial directory), | - | ||||||||||||||||||||||||
| 149 | PARENT_HEIGHT is 1. This is solely for diagnostics. | - | ||||||||||||||||||||||||
| 150 | Exit nonzero upon error. */ | - | ||||||||||||||||||||||||
| 151 | - | |||||||||||||||||||||||||
| 152 | static void | - | ||||||||||||||||||||||||
| 153 | find_dir_entry (struct stat *dot_sb, struct file_name *file_name, | - | ||||||||||||||||||||||||
| 154 | size_t parent_height) | - | ||||||||||||||||||||||||
| 155 | { | - | ||||||||||||||||||||||||
| 156 | DIR *dirp; | - | ||||||||||||||||||||||||
| 157 | int fd; | - | ||||||||||||||||||||||||
| 158 | struct stat parent_sb; | - | ||||||||||||||||||||||||
| 159 | bool use_lstat; | - | ||||||||||||||||||||||||
| 160 | bool found; | - | ||||||||||||||||||||||||
| 161 | - | |||||||||||||||||||||||||
| 162 | dirp = opendir (".."); | - | ||||||||||||||||||||||||
| 163 | if (dirp == NULL)
| 0 | ||||||||||||||||||||||||
| 164 | die (EXIT_FAILURE, errno, _("cannot open directory %s"), never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"cannot open directory %s\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 ,...t (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "cannot open directory %s" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 165 | quote (nth_parent (parent_height))); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"cannot open directory %s\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 ,...t (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "cannot open directory %s" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 166 | - | |||||||||||||||||||||||||
| 167 | fd = dirfd (dirp); | - | ||||||||||||||||||||||||
| 168 | if ((0 <= fd ? fchdir (fd) : chdir ("..")) < 0)
| 0 | ||||||||||||||||||||||||
| 169 | die (EXIT_FAILURE, errno, _("failed to chdir to %s"), never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to chdir to %s\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , (*...rent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to chdir to %s" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 170 | quote (nth_parent (parent_height))); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to chdir to %s\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , (*...rent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to chdir to %s" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 171 | - | |||||||||||||||||||||||||
| 172 | if ((0 <= fd ? fstat (fd, &parent_sb) : stat (".", &parent_sb)) < 0)
| 0 | ||||||||||||||||||||||||
| 173 | die (EXIT_FAILURE, errno, _("failed to stat %s"), never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to stat %s\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , (*__er...h_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to stat %s" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 174 | quote (nth_parent (parent_height))); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to stat %s\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , (*__er...h_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to stat %s" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 175 | - | |||||||||||||||||||||||||
| 176 | /* If parent and child directory are on different devices, then we | - | ||||||||||||||||||||||||
| 177 | can't rely on d_ino for useful i-node numbers; use lstat instead. */ | - | ||||||||||||||||||||||||
| 178 | use_lstat = (parent_sb.st_dev != dot_sb->st_dev); | - | ||||||||||||||||||||||||
| 179 | - | |||||||||||||||||||||||||
| 180 | found = false; | - | ||||||||||||||||||||||||
| 181 | while (1) | - | ||||||||||||||||||||||||
| 182 | { | - | ||||||||||||||||||||||||
| 183 | struct dirent const *dp; | - | ||||||||||||||||||||||||
| 184 | struct stat ent_sb; | - | ||||||||||||||||||||||||
| 185 | ino_t ino; | - | ||||||||||||||||||||||||
| 186 | - | |||||||||||||||||||||||||
| 187 | errno = 0; | - | ||||||||||||||||||||||||
| 188 | if ((dp = readdir_ignoring_dot_and_dotdot (dirp)) == NULL)
| 0 | ||||||||||||||||||||||||
| 189 | { | - | ||||||||||||||||||||||||
| 190 | if (errno)
| 0 | ||||||||||||||||||||||||
| 191 | { | - | ||||||||||||||||||||||||
| 192 | /* Save/restore errno across closedir call. */ | - | ||||||||||||||||||||||||
| 193 | int e = errno; | - | ||||||||||||||||||||||||
| 194 | closedir (dirp); | - | ||||||||||||||||||||||||
| 195 | errno = e; | - | ||||||||||||||||||||||||
| 196 | - | |||||||||||||||||||||||||
| 197 | /* Arrange to give a diagnostic after exiting this loop. */ | - | ||||||||||||||||||||||||
| 198 | dirp = NULL; | - | ||||||||||||||||||||||||
| 199 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 200 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 201 | } | - | ||||||||||||||||||||||||
| 202 | - | |||||||||||||||||||||||||
| 203 | ino = D_INO (dp); | - | ||||||||||||||||||||||||
| 204 | - | |||||||||||||||||||||||||
| 205 | if (ino == NOT_AN_INODE_NUMBER || use_lstat)
| 0 | ||||||||||||||||||||||||
| 206 | { | - | ||||||||||||||||||||||||
| 207 | if (lstat (dp->d_name, &ent_sb) < 0)
| 0 | ||||||||||||||||||||||||
| 208 | { | - | ||||||||||||||||||||||||
| 209 | /* Skip any entry we can't stat. */ | - | ||||||||||||||||||||||||
| 210 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 211 | } | - | ||||||||||||||||||||||||
| 212 | ino = ent_sb.st_ino; | - | ||||||||||||||||||||||||
| 213 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 214 | - | |||||||||||||||||||||||||
| 215 | if (ino != dot_sb->st_ino)
| 0 | ||||||||||||||||||||||||
| 216 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 217 | - | |||||||||||||||||||||||||
| 218 | /* If we're not crossing a device boundary, then a simple i-node | - | ||||||||||||||||||||||||
| 219 | match is enough. */ | - | ||||||||||||||||||||||||
| 220 | if ( ! use_lstat || ent_sb.st_dev == dot_sb->st_dev)
| 0 | ||||||||||||||||||||||||
| 221 | { | - | ||||||||||||||||||||||||
| 222 | file_name_prepend (file_name, dp->d_name, _D_EXACT_NAMLEN (dp)); | - | ||||||||||||||||||||||||
| 223 | found = true; | - | ||||||||||||||||||||||||
| 224 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 225 | } | - | ||||||||||||||||||||||||
| 226 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 227 | - | |||||||||||||||||||||||||
| 228 | if (dirp == NULL || closedir (dirp) != 0)
| 0 | ||||||||||||||||||||||||
| 229 | { | - | ||||||||||||||||||||||||
| 230 | /* Note that this diagnostic serves for both readdir | - | ||||||||||||||||||||||||
| 231 | and closedir failures. */ | - | ||||||||||||||||||||||||
| 232 | die (EXIT_FAILURE, errno, _("reading directory %s"), | - | ||||||||||||||||||||||||
| 233 | quote (nth_parent (parent_height))); | - | ||||||||||||||||||||||||
| 234 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 235 | - | |||||||||||||||||||||||||
| 236 | if ( ! found)
| 0 | ||||||||||||||||||||||||
| 237 | die (EXIT_FAILURE, 0, never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"couldn't find directory entry in %s with matching i-node\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((...height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "couldn't find directory entry in %s with matching i-node" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 238 | _("couldn't find directory entry in %s with matching i-node"), never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"couldn't find directory entry in %s with matching i-node\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((...height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "couldn't find directory entry in %s with matching i-node" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 239 | quote (nth_parent (parent_height))); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"couldn't find directory entry in %s with matching i-node\", 5), quote (nth_parent (parent_height))), assume (false))" ")"); int _gl_dummy; })) ? ((...height))), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "couldn't find directory entry in %s with matching i-node" , 5) , quote (nth_parent (parent_height))), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 240 | - | |||||||||||||||||||||||||
| 241 | *dot_sb = parent_sb; | - | ||||||||||||||||||||||||
| 242 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 243 | - | |||||||||||||||||||||||||
| 244 | /* Construct the full, absolute name of the current working | - | ||||||||||||||||||||||||
| 245 | directory and store it in *FILE_NAME. | - | ||||||||||||||||||||||||
| 246 | The getcwd function performs nearly the same task, but is typically | - | ||||||||||||||||||||||||
| 247 | unable to handle names longer than PATH_MAX. This function has | - | ||||||||||||||||||||||||
| 248 | no such limitation. However, this function *can* fail due to | - | ||||||||||||||||||||||||
| 249 | permission problems or a lack of memory, while GNU/Linux's getcwd | - | ||||||||||||||||||||||||
| 250 | function works regardless of restricted permissions on parent | - | ||||||||||||||||||||||||
| 251 | directories. Upon failure, give a diagnostic and exit nonzero. | - | ||||||||||||||||||||||||
| 252 | - | |||||||||||||||||||||||||
| 253 | Note: although this function is similar to getcwd, it has a fundamental | - | ||||||||||||||||||||||||
| 254 | difference in that it gives a diagnostic and exits upon failure. | - | ||||||||||||||||||||||||
| 255 | I would have liked a function that did not exit, and that could be | - | ||||||||||||||||||||||||
| 256 | used as a getcwd replacement. Unfortunately, considering all of | - | ||||||||||||||||||||||||
| 257 | the information the caller would require in order to produce good | - | ||||||||||||||||||||||||
| 258 | diagnostics, it doesn't seem worth the added complexity. | - | ||||||||||||||||||||||||
| 259 | In any case, any getcwd replacement must *not* exceed the PATH_MAX | - | ||||||||||||||||||||||||
| 260 | limitation. Otherwise, functions like 'chdir' would fail with | - | ||||||||||||||||||||||||
| 261 | ENAMETOOLONG. | - | ||||||||||||||||||||||||
| 262 | - | |||||||||||||||||||||||||
| 263 | FIXME-maybe: if find_dir_entry fails due to permissions, try getcwd, | - | ||||||||||||||||||||||||
| 264 | in case the unreadable directory is close enough to the root that | - | ||||||||||||||||||||||||
| 265 | getcwd works from there. */ | - | ||||||||||||||||||||||||
| 266 | - | |||||||||||||||||||||||||
| 267 | static void | - | ||||||||||||||||||||||||
| 268 | robust_getcwd (struct file_name *file_name) | - | ||||||||||||||||||||||||
| 269 | { | - | ||||||||||||||||||||||||
| 270 | size_t height = 1; | - | ||||||||||||||||||||||||
| 271 | struct dev_ino dev_ino_buf; | - | ||||||||||||||||||||||||
| 272 | struct dev_ino *root_dev_ino = get_root_dev_ino (&dev_ino_buf); | - | ||||||||||||||||||||||||
| 273 | struct stat dot_sb; | - | ||||||||||||||||||||||||
| 274 | - | |||||||||||||||||||||||||
| 275 | if (root_dev_ino == NULL)
| 0 | ||||||||||||||||||||||||
| 276 | die (EXIT_FAILURE, errno, _("failed to get attributes of %s"), never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to get attributes of %s\", 5), quotearg_style (shell_escape_always_quoting_style, \"/\")), assume (false))" ")"); int _... ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to get attributes of %s" , 5) , quotearg_style (shell_escape_always_quoting_style, "/")), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 277 | quoteaf ("/")); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to get attributes of %s\", 5), quotearg_style (shell_escape_always_quoting_style, \"/\")), assume (false))" ")"); int _... ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to get attributes of %s" , 5) , quotearg_style (shell_escape_always_quoting_style, "/")), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||||||||
| 278 | - | |||||||||||||||||||||||||
| 279 | if (stat (".", &dot_sb) < 0)
| 0 | ||||||||||||||||||||||||
| 280 | die (EXIT_FAILURE, errno, _("failed to stat %s"), quoteaf (".")); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to stat %s\", 5), quotearg_style (shell_escape_always_quoting_style, \".\")), assume (false))" ")"); int _gl_dummy; }))... ".")), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to stat %s" , 5) , quotearg_style (shell_escape_always_quoting_style, ".")), (( 0 ) ? (void) 0 : __builtin_unreachable ())))); | 0 | ||||||||||||||||||||||||
| 281 | - | |||||||||||||||||||||||||
| 282 | while (1) | - | ||||||||||||||||||||||||
| 283 | { | - | ||||||||||||||||||||||||
| 284 | /* If we've reached the root, we're done. */ | - | ||||||||||||||||||||||||
| 285 | if (SAME_INODE (dot_sb, *root_dev_ino))
| 0 | ||||||||||||||||||||||||
| 286 | break; never executed: break; | 0 | ||||||||||||||||||||||||
| 287 | - | |||||||||||||||||||||||||
| 288 | find_dir_entry (&dot_sb, file_name, height++); | - | ||||||||||||||||||||||||
| 289 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 290 | - | |||||||||||||||||||||||||
| 291 | /* See if a leading slash is needed; file_name_prepend adds one. */ | - | ||||||||||||||||||||||||
| 292 | if (file_name->start[0] == '\0')
| 0 | ||||||||||||||||||||||||
| 293 | file_name_prepend (file_name, "", 0); never executed: file_name_prepend (file_name, "", 0); | 0 | ||||||||||||||||||||||||
| 294 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 295 | - | |||||||||||||||||||||||||
| 296 | - | |||||||||||||||||||||||||
| 297 | /* Return PWD from the environment if it is acceptable for 'pwd -L' | - | ||||||||||||||||||||||||
| 298 | output, otherwise NULL. */ | - | ||||||||||||||||||||||||
| 299 | static char * | - | ||||||||||||||||||||||||
| 300 | logical_getcwd (void) | - | ||||||||||||||||||||||||
| 301 | { | - | ||||||||||||||||||||||||
| 302 | struct stat st1; | - | ||||||||||||||||||||||||
| 303 | struct stat st2; | - | ||||||||||||||||||||||||
| 304 | char *wd = getenv ("PWD"); | - | ||||||||||||||||||||||||
| 305 | char *p; | - | ||||||||||||||||||||||||
| 306 | - | |||||||||||||||||||||||||
| 307 | /* Textual validation first. */ | - | ||||||||||||||||||||||||
| 308 | if (!wd || wd[0] != '/')
| 0-5 | ||||||||||||||||||||||||
| 309 | return NULL; executed 1 time by 1 test: return ((void *)0) ;Executed by:
| 1 | ||||||||||||||||||||||||
| 310 | p = wd; | - | ||||||||||||||||||||||||
| 311 | while ((p = strstr (p, "/.")))
| 2 | ||||||||||||||||||||||||
| 312 | { | - | ||||||||||||||||||||||||
| 313 | if (!p[2] || p[2] == '/'
| 0-1 | ||||||||||||||||||||||||
| 314 | || (p[2] == '.' && (!p[3] || p[3] == '/')))
| 0-1 | ||||||||||||||||||||||||
| 315 | return NULL; executed 2 times by 1 test: return ((void *)0) ;Executed by:
| 2 | ||||||||||||||||||||||||
| 316 | p++; | - | ||||||||||||||||||||||||
| 317 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 318 | - | |||||||||||||||||||||||||
| 319 | /* System call validation. */ | - | ||||||||||||||||||||||||
| 320 | if (stat (wd, &st1) == 0 && stat (".", &st2) == 0 && SAME_INODE (st1, st2))
| 0-2 | ||||||||||||||||||||||||
| 321 | return wd; executed 2 times by 1 test: return wd;Executed by:
| 2 | ||||||||||||||||||||||||
| 322 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||||||||||||||
| 323 | } | - | ||||||||||||||||||||||||
| 324 | - | |||||||||||||||||||||||||
| 325 | - | |||||||||||||||||||||||||
| 326 | int | - | ||||||||||||||||||||||||
| 327 | main (int argc, char **argv) | - | ||||||||||||||||||||||||
| 328 | { | - | ||||||||||||||||||||||||
| 329 | char *wd; | - | ||||||||||||||||||||||||
| 330 | /* POSIX requires a default of -L, but most scripts expect -P. | - | ||||||||||||||||||||||||
| 331 | Currently shells default to -L, while stand-alone | - | ||||||||||||||||||||||||
| 332 | pwd implementations default to -P. */ | - | ||||||||||||||||||||||||
| 333 | bool logical = (getenv ("POSIXLY_CORRECT") != NULL); | - | ||||||||||||||||||||||||
| 334 | - | |||||||||||||||||||||||||
| 335 | initialize_main (&argc, &argv); | - | ||||||||||||||||||||||||
| 336 | set_program_name (argv[0]); | - | ||||||||||||||||||||||||
| 337 | setlocale (LC_ALL, ""); | - | ||||||||||||||||||||||||
| 338 | bindtextdomain (PACKAGE, LOCALEDIR); | - | ||||||||||||||||||||||||
| 339 | textdomain (PACKAGE); | - | ||||||||||||||||||||||||
| 340 | - | |||||||||||||||||||||||||
| 341 | atexit (close_stdout); | - | ||||||||||||||||||||||||
| 342 | - | |||||||||||||||||||||||||
| 343 | while (1) | - | ||||||||||||||||||||||||
| 344 | { | - | ||||||||||||||||||||||||
| 345 | int c = getopt_long (argc, argv, "LP", longopts, NULL); | - | ||||||||||||||||||||||||
| 346 | if (c == -1)
| 17-26 | ||||||||||||||||||||||||
| 347 | break; executed 17 times by 1 test: break;Executed by:
| 17 | ||||||||||||||||||||||||
| 348 | switch (c) | - | ||||||||||||||||||||||||
| 349 | { | - | ||||||||||||||||||||||||
| 350 | case 'L': executed 5 times by 1 test: case 'L':Executed by:
| 5 | ||||||||||||||||||||||||
| 351 | logical = true; | - | ||||||||||||||||||||||||
| 352 | break; executed 5 times by 1 test: break;Executed by:
| 5 | ||||||||||||||||||||||||
| 353 | case 'P': executed 7 times by 1 test: case 'P':Executed by:
| 7 | ||||||||||||||||||||||||
| 354 | logical = false; | - | ||||||||||||||||||||||||
| 355 | break; executed 7 times by 1 test: break;Executed by:
| 7 | ||||||||||||||||||||||||
| 356 | - | |||||||||||||||||||||||||
| 357 | case_GETOPT_HELP_CHAR; never executed: break;executed 2 times by 1 test: case GETOPT_HELP_CHAR:Executed by:
| 0-2 | ||||||||||||||||||||||||
| 358 | - | |||||||||||||||||||||||||
| 359 | case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); executed 11 times by 1 test: exit ( 0 );Executed by:
never executed: break;executed 11 times by 1 test: case GETOPT_VERSION_CHAR:Executed by:
| 0-11 | ||||||||||||||||||||||||
| 360 | - | |||||||||||||||||||||||||
| 361 | default: executed 1 time by 1 test: default:Executed by:
| 1 | ||||||||||||||||||||||||
| 362 | usage (EXIT_FAILURE); | - | ||||||||||||||||||||||||
| 363 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 364 | } | - | ||||||||||||||||||||||||
| 365 | - | |||||||||||||||||||||||||
| 366 | if (optind < argc)
| 0-17 | ||||||||||||||||||||||||
| 367 | error (0, 0, _("ignoring non-option arguments")); never executed: error (0, 0, dcgettext (((void *)0), "ignoring non-option arguments" , 5) ); | 0 | ||||||||||||||||||||||||
| 368 | - | |||||||||||||||||||||||||
| 369 | if (logical)
| 5-12 | ||||||||||||||||||||||||
| 370 | { | - | ||||||||||||||||||||||||
| 371 | wd = logical_getcwd (); | - | ||||||||||||||||||||||||
| 372 | if (wd)
| 2-3 | ||||||||||||||||||||||||
| 373 | { | - | ||||||||||||||||||||||||
| 374 | puts (wd); | - | ||||||||||||||||||||||||
| 375 | return EXIT_SUCCESS; executed 2 times by 1 test: return 0 ;Executed by:
| 2 | ||||||||||||||||||||||||
| 376 | } | - | ||||||||||||||||||||||||
| 377 | } executed 3 times by 1 test: end of blockExecuted by:
| 3 | ||||||||||||||||||||||||
| 378 | - | |||||||||||||||||||||||||
| 379 | wd = xgetcwd (); | - | ||||||||||||||||||||||||
| 380 | if (wd != NULL)
| 0-15 | ||||||||||||||||||||||||
| 381 | { | - | ||||||||||||||||||||||||
| 382 | puts (wd); | - | ||||||||||||||||||||||||
| 383 | free (wd); | - | ||||||||||||||||||||||||
| 384 | } executed 15 times by 1 test: end of blockExecuted by:
| 15 | ||||||||||||||||||||||||
| 385 | else | - | ||||||||||||||||||||||||
| 386 | { | - | ||||||||||||||||||||||||
| 387 | struct file_name *file_name = file_name_init (); | - | ||||||||||||||||||||||||
| 388 | robust_getcwd (file_name); | - | ||||||||||||||||||||||||
| 389 | puts (file_name->start); | - | ||||||||||||||||||||||||
| 390 | file_name_free (file_name); | - | ||||||||||||||||||||||||
| 391 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 392 | - | |||||||||||||||||||||||||
| 393 | return EXIT_SUCCESS; executed 15 times by 1 test: return 0 ;Executed by:
| 15 | ||||||||||||||||||||||||
| 394 | } | - | ||||||||||||||||||||||||
| Source code | Switch to Preprocessed file |