diff options
author | Ron Yorston <rmy@pobox.com> | 2019-03-11 12:42:25 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2019-03-11 15:15:39 +0000 |
commit | db255bbadf9c6b219b29d06d4958fbd7967eb8b4 (patch) | |
tree | faa51ac07e6c9c10674d76c33c758b0eeccadc2d /shell | |
parent | b04bbc0109046ee69806a472fd7e44313c646687 (diff) | |
download | busybox-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.c | 43 |
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. */ | ||
2862 | static int | ||
2863 | unc_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 * | |||
2860 | updatepwd(const char *dir) | 2888 | updatepwd(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, "/\\"); |