1
This file is cd.def, from which is created cd.c. It implements the
2
builtins "cd" and "pwd" in Bash.
4
Copyright (C) 1987-2013 Free Software Foundation, Inc.
6
This file is part of GNU Bash, the Bourne Again SHell.
8
Bash is free software: you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation, either version 3 of the License, or
11
(at your option) any later version.
13
Bash is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with Bash. If not, see <http://www.gnu.org/licenses/>.
24
#if defined (HAVE_UNISTD_H)
26
# include <sys/types.h>
31
#include "../bashtypes.h"
33
#include "posixstat.h"
34
#if defined (HAVE_SYS_PARAM_H)
35
#include <sys/param.h>
41
#include "../bashansi.h"
42
#include "../bashintl.h"
45
#include <tilde/tilde.h>
51
#include "bashgetopt.h"
57
extern int posixly_correct;
58
extern int array_needs_making;
59
extern const char * const bash_getcwd_errstr;
61
static int bindpwd __P((int));
62
static int setpwd __P((char *));
63
static char *resetpwd __P((char *));
64
static int change_to_directory __P((char *, int, int));
66
static int cdxattr __P((char *, char **));
67
static void resetxattr __P((void));
69
/* Change this to 1 to get cd spelling correction by default. */
74
static int eflag; /* file scope so bindpwd() can see it */
75
static int xattrflag; /* O_XATTR support for openat */
76
static int xattrfd = -1;
80
$SHORT_DOC cd [-L|[-P [-e]] [-@]] [dir]
81
Change the shell working directory.
83
Change the current directory to DIR. The default DIR is the value of the
86
The variable CDPATH defines the search path for the directory containing
87
DIR. Alternative directory names in CDPATH are separated by a colon (:).
88
A null directory name is the same as the current directory. If DIR begins
89
with a slash (/), then CDPATH is not used.
91
If the directory is not found, and the shell option `cdable_vars' is set,
92
the word is assumed to be a variable name. If that variable has a value,
93
its value is used for DIR.
96
-L force symbolic links to be followed: resolve symbolic links in
97
DIR after processing instances of `..'
98
-P use the physical directory structure without following symbolic
99
links: resolve symbolic links in DIR before processing instances
101
-e if the -P option is supplied, and the current working directory
102
cannot be determined successfully, exit with a non-zero status
103
#if defined (O_XATTR)
104
-@ on systems that support it, present a file with extended attributes
105
as a directory containing the file attributes
108
The default is to follow symbolic links, as if `-L' were specified.
109
`..' is processed by removing the immediately previous pathname component
110
back to a slash or the beginning of DIR.
113
Returns 0 if the directory is changed, and if $PWD is set successfully when
114
-P is used; non-zero otherwise.
117
/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
125
old_anm = array_needs_making;
126
tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
127
if (tvar && readonly_p (tvar))
128
return EXECUTION_FAILURE;
129
if (tvar && old_anm == 0 && array_needs_making && exported_p (tvar))
131
update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
132
array_needs_making = 0;
134
return EXECUTION_SUCCESS;
138
bindpwd (no_symlinks)
141
char *dirname, *pwdvar;
145
r = sh_chkwrite (EXECUTION_SUCCESS);
147
#define tcwd the_current_working_directory
148
dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
149
: get_working_directory ("cd");
152
old_anm = array_needs_making;
153
pwdvar = get_string_value ("PWD");
155
tvar = bind_variable ("OLDPWD", pwdvar, 0);
156
if (tvar && readonly_p (tvar))
157
r = EXECUTION_FAILURE;
159
if (old_anm == 0 && array_needs_making && exported_p (tvar))
161
update_export_env_inplace ("OLDPWD=", 7, pwdvar);
162
array_needs_making = 0;
165
if (setpwd (dirname) == EXECUTION_FAILURE)
166
r = EXECUTION_FAILURE;
167
if (dirname == 0 && eflag)
168
r = EXECUTION_FAILURE;
170
if (dirname && dirname != the_current_working_directory)
176
/* Call get_working_directory to reset the value of
177
the_current_working_directory () */
184
FREE (the_current_working_directory);
185
the_current_working_directory = (char *)NULL;
186
tdir = get_working_directory (caller);
192
char *dir; /* don't assume we can always free DIR */
193
char **ndirp; /* return new constructed directory name */
195
#if defined (O_XATTR)
197
char buf[11+40+40]; /* construct new `fake' path for pwd */
199
apfd = openat (AT_FDCWD, dir, O_RDONLY|O_NONBLOCK);
202
fd = openat (apfd, ".", O_XATTR);
204
close (apfd); /* ignore close error for now */
208
r = fchdir (fd); /* assume fchdir exists everywhere with O_XATTR */
214
/* NFSv4 and ZFS extended attribute directories do not have names which are
215
visible in the standard Unix directory tree structure. To ensure we have
216
a valid name for $PWD, we synthesize one under /proc, but to keep that
217
path valid, we need to keep the file descriptor open as long as we are in
218
this directory. This imposes a certain structure on /proc. */
221
sprintf (buf, "/proc/%d/fd/%d", getpid(), fd);
222
*ndirp = savestring (buf);
235
/* Clean up the O_XATTR baggage. Currently only closes xattrfd */
239
#if defined (O_XATTR)
246
xattrfd = -1; /* not strictly necessary */
250
#define LCD_DOVARS 0x001
251
#define LCD_DOSPELL 0x002
252
#define LCD_PRINTPATH 0x004
253
#define LCD_FREEDIRNAME 0x008
255
/* This builtin is ultimately the way that all user-visible commands should
256
change the current working directory. It is called by cd_to_string (),
257
so the programming interface is simple, and it handles errors and
258
restrictions properly. */
263
char *dirname, *cdpath, *path, *temp;
264
int path_index, no_symlinks, opt, lflag;
266
#if defined (RESTRICTED_SHELL)
269
sh_restricted ((char *)NULL);
270
return (EXECUTION_FAILURE);
272
#endif /* RESTRICTED_SHELL */
275
no_symlinks = no_symbolic_links;
277
reset_internal_getopt ();
278
#if defined (O_XATTR)
279
while ((opt = internal_getopt (list, "eLP@")) != -1)
281
while ((opt = internal_getopt (list, "eLP")) != -1)
295
#if defined (O_XATTR)
307
lflag = (cdable_vars ? LCD_DOVARS : 0) |
308
((interactive && cdspelling) ? LCD_DOSPELL : 0);
309
if (eflag && no_symlinks == 0)
314
/* `cd' without arguments is equivalent to `cd $HOME' */
315
dirname = get_string_value ("HOME");
319
builtin_error (_("HOME not set"));
320
return (EXECUTION_FAILURE);
324
#if defined (CD_COMPLAINS)
327
builtin_error (_("too many arguments"));
328
return (EXECUTION_FAILURE);
331
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
333
/* This is `cd -', equivalent to `cd $OLDPWD' */
334
dirname = get_string_value ("OLDPWD");
338
builtin_error (_("OLDPWD not set"));
339
return (EXECUTION_FAILURE);
342
lflag = interactive ? LCD_PRINTPATH : 0;
344
lflag = LCD_PRINTPATH; /* According to SUSv3 */
347
else if (absolute_pathname (list->word->word))
348
dirname = list->word->word;
349
else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
351
dirname = list->word->word;
353
/* Find directory in $CDPATH. */
355
while (path = extract_colon_unit (cdpath, &path_index))
357
/* OPT is 1 if the path element is non-empty */
358
opt = path[0] != '\0';
359
temp = sh_makepath (path, dirname, MP_DOTILDE);
362
if (change_to_directory (temp, no_symlinks, xattrflag))
364
/* POSIX.2 says that if a nonempty directory from CDPATH
365
is used to find the directory to change to, the new
366
directory name is echoed to stdout, whether or not
367
the shell is interactive. */
368
if (opt && (path = no_symlinks ? temp : the_current_working_directory))
369
printf ("%s\n", path);
373
/* Posix.2 says that after using CDPATH, the resultant
374
value of $PWD will not contain `.' or `..'. */
375
return (bindpwd (posixly_correct || no_symlinks));
377
return (bindpwd (no_symlinks));
385
/* changed for bash-4.2 Posix cd description steps 5-6 */
386
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
387
try the current directory, so we just punt now with an error
388
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
389
is so we don't mistakenly treat a CDPATH value of "" as not
390
specifying the current directory. */
391
if (posixly_correct && cdpath[0])
393
builtin_error ("%s: %s", dirname, strerror (ENOENT));
394
return (EXECUTION_FAILURE);
399
dirname = list->word->word;
401
/* When we get here, DIRNAME is the directory to change to. If we
402
chdir successfully, just return. */
403
if (change_to_directory (dirname, no_symlinks, xattrflag))
405
if (lflag & LCD_PRINTPATH)
406
printf ("%s\n", dirname);
407
return (bindpwd (no_symlinks));
410
/* If the user requests it, then perhaps this is the name of
411
a shell variable, whose value contains the directory to
413
if (lflag & LCD_DOVARS)
415
temp = get_string_value (dirname);
416
if (temp && change_to_directory (temp, no_symlinks, xattrflag))
418
printf ("%s\n", temp);
419
return (bindpwd (no_symlinks));
423
/* If the user requests it, try to find a directory name similar in
424
spelling to the one requested, in case the user made a simple
425
typo. This is similar to the UNIX 8th and 9th Edition shells. */
426
if (lflag & LCD_DOSPELL)
428
temp = dirspell (dirname);
429
if (temp && change_to_directory (temp, no_symlinks, xattrflag))
431
printf ("%s\n", temp);
433
return (bindpwd (no_symlinks));
439
builtin_error ("%s: %s", dirname, strerror (errno));
440
return (EXECUTION_FAILURE);
444
$FUNCTION pwd_builtin
446
Print the name of the current working directory.
449
-L print the value of $PWD if it names the current working
451
-P print the physical directory, without any symbolic links
453
By default, `pwd' behaves as if `-L' were specified.
456
Returns 0 unless an invalid option is given or the current directory
460
/* Non-zero means that pwd always prints the physical directory, without
462
static int verbatim_pwd;
464
/* Print the name of the current working directory. */
472
verbatim_pwd = no_symbolic_links;
474
reset_internal_getopt ();
475
while ((opt = internal_getopt (list, "LP")) != -1)
480
verbatim_pwd = pflag = 1;
492
#define tcwd the_current_working_directory
494
directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
495
: get_working_directory ("pwd");
497
/* Try again using getcwd() if canonicalization fails (for instance, if
498
the file system has changed state underneath bash). */
499
if ((tcwd && directory == 0) ||
500
(posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
502
if (directory && directory != tcwd)
504
directory = resetpwd ("pwd");
511
opt = EXECUTION_SUCCESS;
512
printf ("%s\n", directory);
513
/* This is dumb but posix-mandated. */
514
if (posixly_correct && pflag)
515
opt = setpwd (directory);
516
if (directory != the_current_working_directory)
518
return (sh_chkwrite (opt));
521
return (EXECUTION_FAILURE);
524
/* Do the work of changing to the directory NEWDIR. Handle symbolic
525
link following, etc. This function *must* return with
526
the_current_working_directory either set to NULL (in which case
527
getcwd() will eventually be called), or set to a string corresponding
528
to the working directory. Return 1 on success, 0 on failure. */
531
change_to_directory (newdir, nolinks, xattr)
535
char *t, *tdir, *ndir;
536
int err, canon_failed, r, ndlen, dlen;
540
if (the_current_working_directory == 0)
542
t = get_working_directory ("chdir");
546
t = make_absolute (newdir, the_current_working_directory);
548
/* TDIR is either the canonicalized absolute pathname of NEWDIR
549
(nolinks == 0) or the absolute physical pathname of NEWDIR
551
tdir = nolinks ? sh_physpath (t, 0)
552
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
554
ndlen = strlen (newdir);
557
/* Use the canonicalized version of NEWDIR, or, if canonicalization
558
failed, use the non-canonical form. */
569
/* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
570
returns NULL (because it checks the path, it will return NULL if the
571
resolved path doesn't exist), fail immediately. */
572
if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
574
#if defined ENAMETOOLONG
575
if (errno != ENOENT && errno != ENAMETOOLONG)
584
#if defined (O_XATTR)
587
r = cdxattr (nolinks ? newdir : tdir, &ndir);
599
return (0); /* no xattr */
605
r = chdir (nolinks ? newdir : tdir);
610
/* If the chdir succeeds, update the_current_working_directory. */
613
/* If canonicalization failed, but the chdir succeeded, reset the
614
shell's idea of the_current_working_directory. */
619
set_working_directory (tdir);
624
set_working_directory (tdir);
630
/* We failed to change to the appropriate directory name. If we tried
631
what the user passed (nolinks != 0), punt now. */
640
/* We're not in physical mode (nolinks == 0), but we failed to change to
641
the canonicalized directory name (TDIR). Try what the user passed
642
verbatim. If we succeed, reinitialize the_current_working_directory. */
643
if (chdir (newdir) == 0)
647
set_working_directory (tdir);