Fix Unix->Windows path conversion

Francois Gouget fgouget at codeweavers.com
Fri Oct 7 10:14:11 CDT 2005


Currently winepath uses the GetFullPathName() to convert Unix paths to 
Windows paths but that's not garanteed to work. In particular if 'y:' 
points to your home directory, cwd()==$HOME and you call 
GetFullPathName("../otheruser/foo.txt") then you get 
"y:\otheruser\foo.txt" which is wrong.

Alexandre told me that's by design and GetFullPathName() will just get 
things wrong for relative paths. That's why we now have 
wine_get_dos_file_name(). So I modified winepath to use the new 
function. I also fixed the description of the --long and --short 
operations to reflect what they really do.

Changelog:

  * programs/winepath/winepath.c

    Francois Gouget <fgouget at codeweavers.com>
    Add a --windows option for converting a Unix path to a long Windows 
path.
    Fix the description of --long and --short. They are only garanteed 
to work on Windows paths though they will often successfully convert 
Unix paths to Windows paths too.

-- 
Francois Gouget
fgouget at codeweavers.com

-------------- next part --------------
Index: programs/winepath/winepath.c
===================================================================
RCS file: /var/cvs/wine/programs/winepath/winepath.c,v
retrieving revision 1.8
diff -u -p -r1.8 winepath.c
--- programs/winepath/winepath.c	25 Jan 2005 16:41:50 -0000	1.8
+++ programs/winepath/winepath.c	7 Oct 2005 14:55:01 -0000
@@ -1,8 +1,9 @@
 /*
- * Translate between Wine and Unix paths
+ * Translate between Windows and Unix paths formats
  *
  * Copyright 2002 Mike Wetherell
  * Copyright 2005 Dmitry Timoshkov
+ * Copyright 2005 Francois Gouget
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,15 +31,14 @@
 #define VERSION "0.1 (" PACKAGE_STRING ")"
 
 enum {
-    SHORTFORMAT = 1,
-    LONGFORMAT  = 2,
-    UNIXFORMAT  = 4
+    SHORTFORMAT   = 1,
+    LONGFORMAT    = 2,
+    UNIXFORMAT    = 4,
+    WINDOWSFORMAT = 8
 };
 
 static const char progname[] = "winepath";
 
-/* Wine specific functions */
-typedef LPSTR (*wine_get_unix_file_name_t) ( LPCWSTR dos );
 /*
  * handle an option
  */
@@ -47,15 +47,16 @@ static int option(int shortopt, const WC
     static const char helpmsg[] =
     "Convert PATH(s) to Unix or Windows long or short paths.\n"
     "\n"
-    "  -u, --unix    output Unix format\n"
-    "  -l, --long    output Windows long format\n"
-    "  -s, --short   output Windows short format \n"
+    "  -u, --unix    converts a Windows path to a Unix path\n"
+    "  -w, --windows converts a Unix path to a long Windows path\n"
+    "  -l, --long    converts a short Windows path to the long format\n"
+    "  -s, --short   converts a long Windows path to the short format\n"
     "  -h, --help    output this help message and exit\n"
     "  -v, --version output version information and exit\n"
     "\n"
-    "The input paths can be in any format. If more than one option is given\n"
-    "then the input paths are output in all formats specified, in the order\n"
-    "Unix, long, short. If no option is given the default is Unix format.\n";
+    "If more than one option is given then the input paths are output in\n"
+    "all formats specified, in the order long, short, Unix, Windows.\n"
+    "If no option is given the default is Unix format.\n";
 
     switch (shortopt) {
         case 'h':
@@ -71,6 +72,8 @@ static int option(int shortopt, const WC
             return SHORTFORMAT;
         case 'u':
             return UNIXFORMAT;
+        case 'w':
+            return WINDOWSFORMAT;
     }
 
     fprintf(stderr, "%s: invalid option ", progname);
@@ -90,10 +93,11 @@ static int parse_options(const WCHAR *ar
     static const WCHAR longW[] = { 'l','o','n','g',0 };
     static const WCHAR shortW[] = { 's','h','o','r','t',0 };
     static const WCHAR unixW[] = { 'u','n','i','x',0 };
+    static const WCHAR windowsW[] = { 'w','i','n','d','o','w','s',0 };
     static const WCHAR helpW[] = { 'h','e','l','p',0 };
     static const WCHAR versionW[] = { 'v','e','r','s','i','o','n',0 };
     static const WCHAR nullW[] = { 0 };
-    static const WCHAR *longopts[] = { longW, shortW, unixW, helpW, versionW, nullW };
+    static const WCHAR *longopts[] = { longW, shortW, unixW, windowsW, helpW, versionW, nullW };
     int outputformats = 0;
     int done = 0;
     int i, j;
@@ -136,7 +140,8 @@ static int parse_options(const WCHAR *ar
  */
 int wmain(int argc, const WCHAR *argv[])
 {
-    wine_get_unix_file_name_t wine_get_unix_file_name_ptr = NULL;
+    LPSTR (*wine_get_unix_file_name_ptr)(LPCWSTR) = NULL;
+    LPWSTR (*wine_get_dos_file_name_ptr)(LPCSTR) = NULL;
     WCHAR dos_pathW[MAX_PATH];
     char path[MAX_PATH];
     int outputformats;
@@ -147,7 +152,7 @@ int wmain(int argc, const WCHAR *argv[])
         outputformats = UNIXFORMAT;
 
     if (outputformats & UNIXFORMAT) {
-        wine_get_unix_file_name_ptr = (wine_get_unix_file_name_t)
+        wine_get_unix_file_name_ptr = (void*)
             GetProcAddress(GetModuleHandle("KERNEL32"),
                            "wine_get_unix_file_name");
         if (wine_get_unix_file_name_ptr == NULL) {
@@ -157,6 +162,17 @@ int wmain(int argc, const WCHAR *argv[])
         }
     }
 
+    if (outputformats & WINDOWSFORMAT) {
+        wine_get_dos_file_name_ptr = (void*)
+            GetProcAddress(GetModuleHandle("KERNEL32"),
+                           "wine_get_dos_file_name");
+        if (wine_get_dos_file_name_ptr == NULL) {
+            fprintf(stderr, "%s: cannot get the address of "
+                            "'wine_get_dos_file_name'\n", progname);
+            exit(3);
+        }
+    }
+
     for (i = 1; argv[i]; i++)
     {
         *path='\0';
@@ -180,6 +196,24 @@ int wmain(int argc, const WCHAR *argv[])
             }
             else printf( "\n" );
         }
+        if (outputformats & WINDOWSFORMAT) {
+            WCHAR* windows_name;
+            char* unix_name;
+            DWORD size;
+
+            size=WideCharToMultiByte(CP_UNIXCP, 0, argv[i], -1, NULL, 0, NULL, NULL);
+            unix_name=HeapAlloc(GetProcessHeap(), 0, size);
+            WideCharToMultiByte(CP_UNIXCP, 0, argv[i], -1, unix_name, size, NULL, NULL);
+
+            if ((windows_name = wine_get_dos_file_name_ptr(unix_name)))
+            {
+                WideCharToMultiByte(CP_UNIXCP, 0, windows_name, -1, path, MAX_PATH, NULL, NULL);
+                printf("%s\n", path);
+                HeapFree( GetProcessHeap(), 0, windows_name );
+            }
+            else printf( "\n" );
+            HeapFree( GetProcessHeap(), 0, unix_name );
+        }
     }
 
     exit(0);


More information about the wine-patches mailing list