aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mingw.h1
-rw-r--r--libbb/lineedit.c11
-rw-r--r--shell/ash.c97
-rw-r--r--win32/mingw.c12
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);
528char *get_system_drive(void); 528char *get_system_drive(void);
529int chdir_system_drive(void); 529int chdir_system_drive(void);
530char *xabsolute_path(char *path); 530char *xabsolute_path(char *path);
531char *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
2846static int 2847static int
2847cdopt(void) 2848cdopt(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
3178static void
3179print_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
3163static int FAST_FUNC 3196static int FAST_FUNC
3164pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 3197pwdcmd(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
1704char *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}