diff options
| author | Ron Yorston <rmy@pobox.com> | 2020-06-30 15:44:20 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2020-06-30 15:52:54 +0100 |
| commit | 90b695c255eeeddb2bb90e5cacbd3253663bfa7f (patch) | |
| tree | 623627f54f8f131db7eb1029c556a60c0a0649dc /shell | |
| parent | 9114e110a59a77909132af6d97bccdf5056adfa4 (diff) | |
| download | busybox-w32-90b695c255eeeddb2bb90e5cacbd3253663bfa7f.tar.gz busybox-w32-90b695c255eeeddb2bb90e5cacbd3253663bfa7f.tar.bz2 busybox-w32-90b695c255eeeddb2bb90e5cacbd3253663bfa7f.zip | |
ash: improve handling of UNC paths
Be more strict about identifying UNC paths in unc_root_len().
In updatepwd() in ash:
- Skip duplicate leading slashes unless the directory is a UNC path.
- Rewrite detection and handling of the five possible types of path.
This improves cases like 'cd ///' and 'cd /xyz' when the current
directory is a UNC path.
See GitHub issue #192.
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 91 |
1 files changed, 54 insertions, 37 deletions
diff --git a/shell/ash.c b/shell/ash.c index 3c53b25ff..397995d9a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -2998,7 +2998,8 @@ updatepwd(const char *dir) | |||
| 2998 | char *p; | 2998 | char *p; |
| 2999 | char *cdcomppath; | 2999 | char *cdcomppath; |
| 3000 | const char *lim; | 3000 | const char *lim; |
| 3001 | int len = 0; | 3001 | int len; |
| 3002 | char buffer[PATH_MAX]; | ||
| 3002 | /* | 3003 | /* |
| 3003 | * There are five cases that make some kind of sense | 3004 | * There are five cases that make some kind of sense |
| 3004 | * | 3005 | * |
| @@ -3006,65 +3007,81 @@ updatepwd(const char *dir) | |||
| 3006 | * c:/path | 3007 | * c:/path |
| 3007 | * //host/share | 3008 | * //host/share |
| 3008 | * | 3009 | * |
| 3009 | * Relative to current drive: | 3010 | * Relative to current working directory of other drive: |
| 3011 | * c:path | ||
| 3012 | * | ||
| 3013 | * Relative to current root (drive/share): | ||
| 3010 | * /path | 3014 | * /path |
| 3011 | * | 3015 | * |
| 3012 | * Relative to current working directory of current drive | 3016 | * Relative to current working directory of current root (drive/share): |
| 3013 | * path | 3017 | * path |
| 3014 | * | ||
| 3015 | * Relative to current working directory of other drive | ||
| 3016 | * c:path | ||
| 3017 | */ | 3018 | */ |
| 3018 | int absdrive = has_dos_drive_prefix(dir); | 3019 | enum {ABS_DRIVE, ABS_SHARE, REL_OTHER, REL_ROOT, REL_CWD} target; |
| 3019 | int curr_relpath = !absdrive && !is_path_sep(*dir); | 3020 | |
| 3020 | int other_relpath = absdrive && !is_path_sep(dir[2]); | 3021 | /* skip multiple leading separators unless dir is a UNC path */ |
| 3021 | int relpath = curr_relpath || other_relpath; | 3022 | if (is_path_sep(*dir) && unc_root_len(dir) == 0) { |
| 3023 | while (is_path_sep(dir[1])) | ||
| 3024 | ++dir; | ||
| 3025 | } | ||
| 3026 | |||
| 3027 | len = strlen(dir); | ||
| 3028 | if (len >= 2 && has_dos_drive_prefix(dir)) | ||
| 3029 | target = len >= 3 && is_path_sep(dir[2]) ? ABS_DRIVE : REL_OTHER; | ||
| 3030 | else if (unc_root_len(dir) != 0) | ||
| 3031 | target = ABS_SHARE; | ||
| 3032 | else if (is_path_sep(*dir)) | ||
| 3033 | target = REL_ROOT; | ||
| 3034 | else | ||
| 3035 | target = REL_CWD; | ||
| 3022 | 3036 | ||
| 3023 | cdcomppath = sstrdup(dir); | 3037 | cdcomppath = sstrdup(dir); |
| 3024 | STARTSTACKSTR(new); | 3038 | STARTSTACKSTR(new); |
| 3025 | 3039 | ||
| 3026 | /* prefix new path with current directory, if required */ | 3040 | switch (target) { |
| 3027 | if (other_relpath) { | 3041 | case REL_OTHER: |
| 3028 | /* c:path */ | 3042 | /* c:path */ |
| 3029 | char buffer[PATH_MAX]; | ||
| 3030 | |||
| 3031 | if (get_drive_cwd(dir, buffer, PATH_MAX) == NULL) | 3043 | if (get_drive_cwd(dir, buffer, PATH_MAX) == NULL) |
| 3032 | return 0; | 3044 | return 0; |
| 3033 | new = stack_putstr(buffer, new); | 3045 | new = stack_putstr(buffer, new); |
| 3034 | } | 3046 | len = 2; |
| 3035 | else if (curr_relpath || (is_root(dir) && unc_root_len(curdir))) { | 3047 | cdcomppath += len; |
| 3036 | /* relative path on current drive or explicit root of UNC curdir */ | 3048 | dir += len; |
| 3037 | if (curdir == nullstr) | 3049 | break; |
| 3050 | case REL_CWD: | ||
| 3051 | case REL_ROOT: | ||
| 3052 | /* path or /path */ | ||
| 3053 | len = root_len(curdir); | ||
| 3054 | if (len == 0) | ||
| 3038 | return 0; | 3055 | return 0; |
| 3039 | new = stack_putstr(curdir, new); | 3056 | new = target == REL_CWD ? stack_putstr(curdir, new) : |
| 3057 | stnputs(curdir, len, new); | ||
| 3058 | break; | ||
| 3059 | default: | ||
| 3060 | /* //host/share or c:/path */ | ||
| 3061 | len = root_len(dir); | ||
| 3062 | if (len == 0) | ||
| 3063 | return 0; | ||
| 3064 | new = stnputs(dir, len, new); | ||
| 3065 | cdcomppath += len; | ||
| 3066 | dir += len; | ||
| 3067 | break; | ||
| 3040 | } | 3068 | } |
| 3041 | 3069 | ||
| 3042 | new = makestrspace(strlen(dir) + 2, new); | 3070 | new = makestrspace(strlen(dir) + 2, new); |
| 3071 | lim = (char *)stackblock() + len + 1; | ||
| 3043 | 3072 | ||
| 3044 | if ( (len=unc_root_len(dir)) || ((len=unc_root_len(curdir)) && | 3073 | if (!is_path_sep(*dir)) { |
| 3045 | (is_root(dir) || curr_relpath)) ) { | ||
| 3046 | /* //host/share or path relative to //host/share */ | ||
| 3047 | lim = (char *)stackblock() + len; | ||
| 3048 | } | ||
| 3049 | else { | ||
| 3050 | if (absdrive) { | ||
| 3051 | if (!relpath) | ||
| 3052 | new = stnputs(dir, 2, new); | ||
| 3053 | cdcomppath += 2; | ||
| 3054 | dir += 2; | ||
| 3055 | } | ||
| 3056 | lim = (char *)stackblock() + 3; | ||
| 3057 | } | ||
| 3058 | |||
| 3059 | if (relpath) { | ||
| 3060 | if (!is_path_sep(new[-1])) | 3074 | if (!is_path_sep(new[-1])) |
| 3061 | USTPUTC('/', new); | 3075 | USTPUTC('/', new); |
| 3076 | if (new > lim && is_path_sep(*lim)) | ||
| 3077 | lim++; | ||
| 3062 | } else { | 3078 | } else { |
| 3063 | USTPUTC('/', new); | 3079 | USTPUTC('/', new); |
| 3064 | cdcomppath ++; | 3080 | cdcomppath++; |
| 3065 | if (is_path_sep(dir[1]) && !is_path_sep(dir[2])) { | 3081 | if (is_path_sep(dir[1]) && !is_path_sep(dir[2])) { |
| 3066 | USTPUTC('/', new); | 3082 | USTPUTC('/', new); |
| 3067 | cdcomppath++; | 3083 | cdcomppath++; |
| 3084 | lim++; | ||
| 3068 | } | 3085 | } |
| 3069 | } | 3086 | } |
| 3070 | p = strtok(cdcomppath, "/\\"); | 3087 | p = strtok(cdcomppath, "/\\"); |
| @@ -3086,7 +3103,7 @@ updatepwd(const char *dir) | |||
| 3086 | new = stack_putstr(p, new); | 3103 | new = stack_putstr(p, new); |
| 3087 | USTPUTC('/', new); | 3104 | USTPUTC('/', new); |
| 3088 | } | 3105 | } |
| 3089 | p = strtok(0, "/\\"); | 3106 | p = strtok(NULL, "/\\"); |
| 3090 | } | 3107 | } |
| 3091 | if (new > lim) | 3108 | if (new > lim) |
| 3092 | STUNPUTC(new); | 3109 | STUNPUTC(new); |
