diff options
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | libbb/lineedit.c | 11 | ||||
-rw-r--r-- | shell/ash.c | 97 | ||||
-rw-r--r-- | win32/mingw.c | 12 |
4 files changed, 92 insertions, 29 deletions
diff --git a/include/mingw.h b/include/mingw.h index d77a9beb9..8b295814c 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -528,3 +528,4 @@ int root_len(const char *path); | |||
528 | char *get_system_drive(void); | 528 | char *get_system_drive(void); |
529 | int chdir_system_drive(void); | 529 | int chdir_system_drive(void); |
530 | char *xabsolute_path(char *path); | 530 | char *xabsolute_path(char *path); |
531 | char *get_drive_cwd(const char *path, char *buffer, int size); | ||
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 3725dba0d..0d5ce9082 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -843,6 +843,17 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
843 | path1[0] = (char*)"."; | 843 | path1[0] = (char*)"."; |
844 | 844 | ||
845 | pfind = strrchr(command, '/'); | 845 | pfind = strrchr(command, '/'); |
846 | #if ENABLE_PLATFORM_MINGW32 | ||
847 | if (!pfind && has_dos_drive_prefix(command) && command[2] != '\0') { | ||
848 | char buffer[PATH_MAX]; | ||
849 | |||
850 | /* path is of form c:path with no '/' */ | ||
851 | if (get_drive_cwd(command, buffer, PATH_MAX)) { | ||
852 | pfind = command + 2; | ||
853 | path1[0] = xstrdup(buffer); | ||
854 | } | ||
855 | } else | ||
856 | #endif | ||
846 | if (!pfind) { | 857 | if (!pfind) { |
847 | if (type == FIND_EXE_ONLY) | 858 | if (type == FIND_EXE_ONLY) |
848 | npaths = path_parse(&paths); | 859 | npaths = path_parse(&paths); |
diff --git a/shell/ash.c b/shell/ash.c index 40965bafa..5f64bebe3 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -2842,6 +2842,7 @@ setprompt_if(smallint do_set, int whichprompt) | |||
2842 | 2842 | ||
2843 | #define CD_PHYSICAL 1 | 2843 | #define CD_PHYSICAL 1 |
2844 | #define CD_PRINT 2 | 2844 | #define CD_PRINT 2 |
2845 | #define CD_PRINT_ALL 4 | ||
2845 | 2846 | ||
2846 | static int | 2847 | static int |
2847 | cdopt(void) | 2848 | cdopt(void) |
@@ -2850,7 +2851,14 @@ cdopt(void) | |||
2850 | int i, j; | 2851 | int i, j; |
2851 | 2852 | ||
2852 | j = 'L'; | 2853 | j = 'L'; |
2854 | #if ENABLE_PLATFORM_MINGW32 | ||
2855 | while ((i = nextopt("LPa")) != '\0') { | ||
2856 | if (i == 'a') | ||
2857 | flags |= CD_PRINT_ALL; | ||
2858 | else | ||
2859 | #else | ||
2853 | while ((i = nextopt("LP")) != '\0') { | 2860 | while ((i = nextopt("LP")) != '\0') { |
2861 | #endif | ||
2854 | if (i != j) { | 2862 | if (i != j) { |
2855 | flags ^= CD_PHYSICAL; | 2863 | flags ^= CD_PHYSICAL; |
2856 | j = i; | 2864 | j = i; |
@@ -2882,56 +2890,62 @@ updatepwd(const char *dir) | |||
2882 | int len = 0; | 2890 | int len = 0; |
2883 | /* | 2891 | /* |
2884 | * There are five cases that make some kind of sense | 2892 | * There are five cases that make some kind of sense |
2885 | * absdrive + abspath: c:/path | ||
2886 | * absdrive + !abspath: c:path | ||
2887 | * !absdrive + abspath: /path | ||
2888 | * !absdrive + uncpath: //host/share | ||
2889 | * !absdrive + !abspath: path | ||
2890 | * | 2893 | * |
2891 | * Damn DOS! | 2894 | * Absolute paths: |
2892 | * c:path behaviour is "undefined" | 2895 | * c:/path |
2893 | * To properly handle this case, I have to keep track of cwd | 2896 | * //host/share |
2894 | * of every drive, which is too painful to do. | 2897 | * |
2895 | * So when c:path is given, I assume it's c:${curdir}path | 2898 | * Relative to current drive: |
2896 | * with ${curdir} comes from the current drive | 2899 | * /path |
2900 | * | ||
2901 | * Relative to current working directory of current drive | ||
2902 | * path | ||
2903 | * | ||
2904 | * Relative to current working directory of other drive | ||
2905 | * c:path | ||
2897 | */ | 2906 | */ |
2898 | int absdrive = *dir && dir[1] == ':'; | 2907 | int absdrive = has_dos_drive_prefix(dir); |
2899 | int abspath = absdrive ? is_path_sep(dir[2]) : is_path_sep(*dir); | 2908 | int curr_relpath = !absdrive && !is_path_sep(*dir); |
2909 | int other_relpath = absdrive && !is_path_sep(dir[2]); | ||
2910 | int relpath = curr_relpath || other_relpath; | ||
2900 | 2911 | ||
2901 | cdcomppath = sstrdup(dir); | 2912 | cdcomppath = sstrdup(dir); |
2902 | STARTSTACKSTR(new); | 2913 | STARTSTACKSTR(new); |
2903 | if (!absdrive && curdir == nullstr) | 2914 | |
2904 | return 0; | 2915 | /* prefix new path with current directory, if required */ |
2905 | if (!abspath || (is_root(dir) && unc_root_len(curdir))) { | 2916 | if (other_relpath) { |
2917 | /* c:path */ | ||
2918 | char buffer[PATH_MAX]; | ||
2919 | |||
2920 | if (get_drive_cwd(dir, buffer, PATH_MAX) == NULL) | ||
2921 | return 0; | ||
2922 | new = stack_putstr(buffer, new); | ||
2923 | } | ||
2924 | else if (curr_relpath || (is_root(dir) && unc_root_len(curdir))) { | ||
2925 | /* relative path on current drive or explicit root of UNC curdir */ | ||
2906 | if (curdir == nullstr) | 2926 | if (curdir == nullstr) |
2907 | return 0; | 2927 | return 0; |
2908 | new = stack_putstr(curdir, new); | 2928 | new = stack_putstr(curdir, new); |
2909 | } | 2929 | } |
2930 | |||
2910 | new = makestrspace(strlen(dir) + 2, new); | 2931 | new = makestrspace(strlen(dir) + 2, new); |
2911 | 2932 | ||
2912 | if ( (len=unc_root_len(dir)) || ((len=unc_root_len(curdir)) && | 2933 | if ( (len=unc_root_len(dir)) || ((len=unc_root_len(curdir)) && |
2913 | (is_root(dir) || (!absdrive && !abspath))) ) { | 2934 | (is_root(dir) || curr_relpath)) ) { |
2914 | if (is_root(dir)) | 2935 | /* //host/share or path relative to //host/share */ |
2915 | new = (char *)stackblock() + len; | ||
2916 | lim = (char *)stackblock() + len; | 2936 | lim = (char *)stackblock() + len; |
2917 | } | 2937 | } |
2918 | else { | 2938 | else { |
2919 | char *drive = stackblock(); | ||
2920 | if (absdrive) { | 2939 | if (absdrive) { |
2921 | *drive = *dir; | 2940 | if (!relpath) |
2941 | new = stack_nputstr(dir, 2, new); | ||
2922 | cdcomppath += 2; | 2942 | cdcomppath += 2; |
2923 | dir += 2; | 2943 | dir += 2; |
2924 | } else { | ||
2925 | *drive = *curdir; | ||
2926 | } | 2944 | } |
2927 | drive[1] = ':'; /* in case of absolute drive+path */ | 2945 | lim = (char *)stackblock() + 3; |
2928 | |||
2929 | if (abspath) | ||
2930 | new = drive + 2; | ||
2931 | lim = drive + 3; | ||
2932 | } | 2946 | } |
2933 | 2947 | ||
2934 | if (!abspath) { | 2948 | if (relpath) { |
2935 | if (!is_path_sep(new[-1])) | 2949 | if (!is_path_sep(new[-1])) |
2936 | USTPUTC('/', new); | 2950 | USTPUTC('/', new); |
2937 | } else { | 2951 | } else { |
@@ -3160,6 +3174,25 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
3160 | return 0; | 3174 | return 0; |
3161 | } | 3175 | } |
3162 | 3176 | ||
3177 | #if ENABLE_PLATFORM_MINGW32 | ||
3178 | static void | ||
3179 | print_all_cwd(void) | ||
3180 | { | ||
3181 | FILE *mnt; | ||
3182 | struct mntent *entry; | ||
3183 | char buffer[PATH_MAX]; | ||
3184 | |||
3185 | mnt = setmntent(bb_path_mtab_file, "r"); | ||
3186 | if (mnt) { | ||
3187 | while ((entry=getmntent(mnt)) != NULL) { | ||
3188 | if (get_drive_cwd(entry->mnt_fsname, buffer, PATH_MAX) != NULL) | ||
3189 | out1fmt("%s\n", buffer); | ||
3190 | } | ||
3191 | endmntent(mnt); | ||
3192 | } | ||
3193 | } | ||
3194 | #endif | ||
3195 | |||
3163 | static int FAST_FUNC | 3196 | static int FAST_FUNC |
3164 | pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | 3197 | pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
3165 | { | 3198 | { |
@@ -3167,6 +3200,12 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
3167 | const char *dir = curdir; | 3200 | const char *dir = curdir; |
3168 | 3201 | ||
3169 | flags = cdopt(); | 3202 | flags = cdopt(); |
3203 | #if ENABLE_PLATFORM_MINGW32 | ||
3204 | if (flags & CD_PRINT_ALL) { | ||
3205 | print_all_cwd(); | ||
3206 | return 0; | ||
3207 | } | ||
3208 | #endif | ||
3170 | if (flags) { | 3209 | if (flags) { |
3171 | if (physdir == nullstr) | 3210 | if (physdir == nullstr) |
3172 | setpwd(dir, 0); | 3211 | setpwd(dir, 0); |
diff --git a/win32/mingw.c b/win32/mingw.c index 1d5644f92..ec7d6c456 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1700,3 +1700,15 @@ char *xabsolute_path(char *path) | |||
1700 | } | 1700 | } |
1701 | bb_perror_msg_and_die("can't open '%s'", path); | 1701 | bb_perror_msg_and_die("can't open '%s'", path); |
1702 | } | 1702 | } |
1703 | |||
1704 | char *get_drive_cwd(const char *path, char *buffer, int size) | ||
1705 | { | ||
1706 | char drive[3] = { *path, ':', '\0' }; | ||
1707 | DWORD ret; | ||
1708 | |||
1709 | ret = GetFullPathName(drive, size, buffer, NULL); | ||
1710 | if (ret == 0 || ret > size) | ||
1711 | return NULL; | ||
1712 | bs_to_slash(buffer); | ||
1713 | return buffer; | ||
1714 | } | ||