aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-03-11 12:42:25 +0000
committerRon Yorston <rmy@pobox.com>2019-03-11 15:15:39 +0000
commitdb255bbadf9c6b219b29d06d4958fbd7967eb8b4 (patch)
treefaa51ac07e6c9c10674d76c33c758b0eeccadc2d /shell
parentb04bbc0109046ee69806a472fd7e44313c646687 (diff)
downloadbusybox-w32-db255bbadf9c6b219b29d06d4958fbd7967eb8b4.tar.gz
busybox-w32-db255bbadf9c6b219b29d06d4958fbd7967eb8b4.tar.bz2
busybox-w32-db255bbadf9c6b219b29d06d4958fbd7967eb8b4.zip
ash: improve handling of UNC paths
Rework the code in updatepwd() which processes UNC paths so that the root of a share is properly identified. This fixes problems when: - the current directory is a share and the user changes to '/'; - the current directory is the root of a share and the user tries to change to '..'.
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 10da3ebed..8ed0f19f3 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2852,6 +2852,34 @@ cdopt(void)
2852 return flags; 2852 return flags;
2853} 2853}
2854 2854
2855#if ENABLE_PLATFORM_MINGW32
2856#define is_path_sep(x) ((x) == '/' || (x) == '\\')
2857#define is_unc_path(x) (is_path_sep(x[0]) && is_path_sep(x[1]))
2858#define is_root(x) (is_path_sep(x[0]) && x[1] == '\0')
2859
2860/* Return the length of the root of a UNC path, i.e. the '//host/share'
2861 * component, or 0 if the path doesn't look like that. */
2862static int
2863unc_root_len(const char *dir)
2864{
2865 const char *s = dir + 2;
2866 int len;
2867
2868 if (!is_unc_path(dir))
2869 return 0;
2870 len = strcspn(s, "/\\");
2871 if (len == 0)
2872 return 0;
2873 s += len + 1;
2874 len = strcspn(s, "/\\");
2875 if (len == 0)
2876 return 0;
2877 s += len;
2878
2879 return s - dir;
2880}
2881#endif
2882
2855/* 2883/*
2856 * Update curdir (the name of the current directory) in response to a 2884 * Update curdir (the name of the current directory) in response to a
2857 * cd command. 2885 * cd command.
@@ -2860,8 +2888,6 @@ static const char *
2860updatepwd(const char *dir) 2888updatepwd(const char *dir)
2861{ 2889{
2862#if ENABLE_PLATFORM_MINGW32 2890#if ENABLE_PLATFORM_MINGW32
2863#define is_path_sep(x) ((x) == '/' || (x) == '\\')
2864#define is_unc_path(x) (is_path_sep(x[0]) && is_path_sep(x[1]))
2865 /* 2891 /*
2866 * Due to Windows drive notion, getting pwd is a completely 2892 * Due to Windows drive notion, getting pwd is a completely
2867 * different thing. Handle it in a separate routine 2893 * different thing. Handle it in a separate routine
@@ -2871,6 +2897,7 @@ updatepwd(const char *dir)
2871 char *p; 2897 char *p;
2872 char *cdcomppath; 2898 char *cdcomppath;
2873 const char *lim; 2899 const char *lim;
2900 int len = 0;
2874 /* 2901 /*
2875 * There are five cases that make some kind of sense 2902 * There are five cases that make some kind of sense
2876 * absdrive + abspath: c:/path 2903 * absdrive + abspath: c:/path
@@ -2893,15 +2920,18 @@ updatepwd(const char *dir)
2893 STARTSTACKSTR(new); 2920 STARTSTACKSTR(new);
2894 if (!absdrive && curdir == nullstr) 2921 if (!absdrive && curdir == nullstr)
2895 return 0; 2922 return 0;
2896 if (!abspath) { 2923 if (!abspath || (is_root(dir) && unc_root_len(curdir))) {
2897 if (curdir == nullstr) 2924 if (curdir == nullstr)
2898 return 0; 2925 return 0;
2899 new = stack_putstr(curdir, new); 2926 new = stack_putstr(curdir, new);
2900 } 2927 }
2901 new = makestrspace(strlen(dir) + 2, new); 2928 new = makestrspace(strlen(dir) + 2, new);
2902 2929
2903 if ( is_unc_path(dir) || (!absdrive && !abspath && is_unc_path(curdir)) ) { 2930 if ( (len=unc_root_len(dir)) || ((len=unc_root_len(curdir)) &&
2904 lim = (char *)stackblock() + 1; 2931 (is_root(dir) || (!absdrive && !abspath))) ) {
2932 if (is_root(dir))
2933 new = (char *)stackblock() + len;
2934 lim = (char *)stackblock() + len;
2905 } 2935 }
2906 else { 2936 else {
2907 char *drive = stackblock(); 2937 char *drive = stackblock();
@@ -2922,15 +2952,12 @@ updatepwd(const char *dir)
2922 if (!abspath) { 2952 if (!abspath) {
2923 if (!is_path_sep(new[-1])) 2953 if (!is_path_sep(new[-1]))
2924 USTPUTC('/', new); 2954 USTPUTC('/', new);
2925 if (new > lim && is_path_sep(*lim))
2926 lim++;
2927 } else { 2955 } else {
2928 USTPUTC('/', new); 2956 USTPUTC('/', new);
2929 cdcomppath ++; 2957 cdcomppath ++;
2930 if (is_path_sep(dir[1]) && !is_path_sep(dir[2])) { 2958 if (is_path_sep(dir[1]) && !is_path_sep(dir[2])) {
2931 USTPUTC('/', new); 2959 USTPUTC('/', new);
2932 cdcomppath++; 2960 cdcomppath++;
2933 lim++;
2934 } 2961 }
2935 } 2962 }
2936 p = strtok(cdcomppath, "/\\"); 2963 p = strtok(cdcomppath, "/\\");