aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32.c
diff options
context:
space:
mode:
authorEli Zaretskii2013-11-02 15:03:32 +0200
committerEli Zaretskii2013-11-02 15:03:32 +0200
commit1fd201bb1d720d0c5ab727a3972363778eef834f (patch)
tree508abf22dbb91d24309869bc42a93e814f9fbcd6 /src/w32.c
parent5c4a19a90f803ed46629c2bdc1ac3d3563caa738 (diff)
downloademacs-1fd201bb1d720d0c5ab727a3972363778eef834f.tar.gz
emacs-1fd201bb1d720d0c5ab727a3972363778eef834f.zip
Adapted dostounix_filename. w32-short/long-filename work with wide APIs.
Diffstat (limited to 'src/w32.c')
-rw-r--r--src/w32.c202
1 files changed, 73 insertions, 129 deletions
diff --git a/src/w32.c b/src/w32.c
index 09d78141e14..396a8cdd08b 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1336,7 +1336,7 @@ filename_to_ansi (const char *fn_in, char *fn_out)
1336 return -1; 1336 return -1;
1337} 1337}
1338 1338
1339static int 1339int
1340filename_from_ansi (const char *fn_in, char *fn_out) 1340filename_from_ansi (const char *fn_in, char *fn_out)
1341{ 1341{
1342 wchar_t fn_utf16[MAXPATHLEN]; 1342 wchar_t fn_utf16[MAXPATHLEN];
@@ -1799,31 +1799,20 @@ max_filename_mbslen (void)
1799 return cp_info.MaxCharSize; 1799 return cp_info.MaxCharSize;
1800} 1800}
1801 1801
1802/* Normalize filename by converting all path separators to 1802/* Normalize filename by converting in-place all of its path
1803 the specified separator. Also conditionally convert upper 1803 separators to the separator specified by PATH_SEP. */
1804 case path name components to lower case. */
1805 1804
1806static void 1805static void
1807normalize_filename (register char *fp, char path_sep, int multibyte) 1806normalize_filename (register char *fp, char path_sep)
1808{ 1807{
1809 char sep; 1808 char *p2;
1810 char *elem, *p2;
1811 int dbcs_p = max_filename_mbslen () > 1;
1812
1813 /* Multibyte file names are in the Emacs internal representation, so
1814 we can traverse them by bytes with no problems. */
1815 if (multibyte)
1816 dbcs_p = 0;
1817 1809
1818 /* Always lower-case drive letters a-z, even if the filesystem 1810 /* Always lower-case drive letters a-z, even if the filesystem
1819 preserves case in filenames. 1811 preserves case in filenames.
1820 This is so filenames can be compared by string comparison 1812 This is so filenames can be compared by string comparison
1821 functions that are case-sensitive. Even case-preserving filesystems 1813 functions that are case-sensitive. Even case-preserving filesystems
1822 do not distinguish case in drive letters. */ 1814 do not distinguish case in drive letters. */
1823 if (dbcs_p) 1815 p2 = fp + 1;
1824 p2 = CharNextExA (file_name_codepage, fp, 0);
1825 else
1826 p2 = fp + 1;
1827 1816
1828 if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z') 1817 if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z')
1829 { 1818 {
@@ -1831,68 +1820,26 @@ normalize_filename (register char *fp, char path_sep, int multibyte)
1831 fp += 2; 1820 fp += 2;
1832 } 1821 }
1833 1822
1834 if (multibyte || NILP (Vw32_downcase_file_names)) 1823 while (*fp)
1835 { 1824 {
1836 while (*fp) 1825 if (*fp == '/' || *fp == '\\')
1837 { 1826 *fp = path_sep;
1838 if (*fp == '/' || *fp == '\\') 1827 fp++;
1839 *fp = path_sep;
1840 if (!dbcs_p)
1841 fp++;
1842 else
1843 fp = CharNextExA (file_name_codepage, fp, 0);
1844 }
1845 return;
1846 } 1828 }
1847
1848 sep = path_sep; /* convert to this path separator */
1849 elem = fp; /* start of current path element */
1850
1851 do {
1852 if (*fp >= 'a' && *fp <= 'z')
1853 elem = 0; /* don't convert this element */
1854
1855 if (*fp == 0 || *fp == ':')
1856 {
1857 sep = *fp; /* restore current separator (or 0) */
1858 *fp = '/'; /* after conversion of this element */
1859 }
1860
1861 if (*fp == '/' || *fp == '\\')
1862 {
1863 if (elem && elem != fp)
1864 {
1865 *fp = 0; /* temporary end of string */
1866 _mbslwr (elem); /* while we convert to lower case */
1867 }
1868 *fp = sep; /* convert (or restore) path separator */
1869 elem = fp + 1; /* next element starts after separator */
1870 sep = path_sep;
1871 }
1872 if (*fp)
1873 {
1874 if (!dbcs_p)
1875 fp++;
1876 else
1877 fp = CharNextExA (file_name_codepage, fp, 0);
1878 }
1879 } while (*fp);
1880} 1829}
1881 1830
1882/* Destructively turn backslashes into slashes. MULTIBYTE non-zero 1831/* Destructively turn backslashes into slashes. */
1883 means the file name is a multibyte string in Emacs's internal
1884 representation. */
1885void 1832void
1886dostounix_filename (register char *p, int multibyte) 1833dostounix_filename (register char *p)
1887{ 1834{
1888 normalize_filename (p, '/', multibyte); 1835 normalize_filename (p, '/');
1889} 1836}
1890 1837
1891/* Destructively turn slashes into backslashes. */ 1838/* Destructively turn slashes into backslashes. */
1892void 1839void
1893unixtodos_filename (register char *p) 1840unixtodos_filename (register char *p)
1894{ 1841{
1895 normalize_filename (p, '\\', 0); 1842 normalize_filename (p, '\\');
1896} 1843}
1897 1844
1898/* Remove all CR's that are followed by a LF. 1845/* Remove all CR's that are followed by a LF.
@@ -1943,17 +1890,13 @@ parse_root (char * name, char ** pPath)
1943 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) 1890 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1944 { 1891 {
1945 int slashes = 2; 1892 int slashes = 2;
1946 int dbcs_p = max_filename_mbslen () > 1;
1947 1893
1948 name += 2; 1894 name += 2;
1949 do 1895 do
1950 { 1896 {
1951 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 1897 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1952 break; 1898 break;
1953 if (dbcs_p) 1899 name++;
1954 name = CharNextExA (file_name_codepage, name, 0);
1955 else
1956 name++;
1957 } 1900 }
1958 while ( *name ); 1901 while ( *name );
1959 if (IS_DIRECTORY_SEP (name[0])) 1902 if (IS_DIRECTORY_SEP (name[0]))
@@ -1970,23 +1913,44 @@ parse_root (char * name, char ** pPath)
1970static int 1913static int
1971get_long_basename (char * name, char * buf, int size) 1914get_long_basename (char * name, char * buf, int size)
1972{ 1915{
1973 WIN32_FIND_DATA find_data;
1974 HANDLE dir_handle; 1916 HANDLE dir_handle;
1917 char fname_utf8[MAX_UTF8_PATH];
1975 int len = 0; 1918 int len = 0;
1919 int cstatus;
1976 1920
1977 /* must be valid filename, no wild cards or other invalid characters */ 1921 /* Must be valid filename, no wild cards or other invalid characters. */
1978 if (_mbspbrk (name, "*?|<>\"")) 1922 if (strpbrk (name, "*?|<>\""))
1979 return 0; 1923 return 0;
1980 1924
1981 dir_handle = FindFirstFile (name, &find_data); 1925 if (w32_unicode_filenames)
1982 if (dir_handle != INVALID_HANDLE_VALUE)
1983 { 1926 {
1984 if ((len = strlen (find_data.cFileName)) < size) 1927 wchar_t fname_utf16[MAX_PATH];
1985 memcpy (buf, find_data.cFileName, len + 1); 1928 WIN32_FIND_DATAW find_data_wide;
1986 else 1929
1987 len = 0; 1930 filename_to_utf16 (name, fname_utf16);
1988 FindClose (dir_handle); 1931 dir_handle = FindFirstFileW (fname_utf16, &find_data_wide);
1932 if (dir_handle != INVALID_HANDLE_VALUE)
1933 cstatus = filename_from_utf16 (find_data_wide.cFileName, fname_utf8);
1934 }
1935 else
1936 {
1937 char fname_ansi[MAX_PATH];
1938 WIN32_FIND_DATAA find_data_ansi;
1939
1940 filename_to_ansi (name, fname_ansi);
1941 dir_handle = FindFirstFileA (fname_ansi, &find_data_ansi);
1942 if (dir_handle != INVALID_HANDLE_VALUE)
1943 cstatus = filename_from_ansi (find_data_ansi.cFileName, fname_utf8);
1989 } 1944 }
1945
1946 if (cstatus == 0 && (len = strlen (fname_utf8)) < size)
1947 memcpy (buf, fname_utf8, len + 1);
1948 else
1949 len = 0;
1950
1951 if (dir_handle != INVALID_HANDLE_VALUE)
1952 FindClose (dir_handle);
1953
1990 return len; 1954 return len;
1991} 1955}
1992 1956
@@ -1997,11 +1961,11 @@ w32_get_long_filename (char * name, char * buf, int size)
1997 char * o = buf; 1961 char * o = buf;
1998 char * p; 1962 char * p;
1999 char * q; 1963 char * q;
2000 char full[ MAX_PATH ]; 1964 char full[ MAX_UTF8_PATH ];
2001 int len; 1965 int len;
2002 1966
2003 len = strlen (name); 1967 len = strlen (name);
2004 if (len >= MAX_PATH) 1968 if (len >= MAX_UTF8_PATH)
2005 return FALSE; 1969 return FALSE;
2006 1970
2007 /* Use local copy for destructive modification. */ 1971 /* Use local copy for destructive modification. */
@@ -2018,7 +1982,7 @@ w32_get_long_filename (char * name, char * buf, int size)
2018 while (p != NULL && *p) 1982 while (p != NULL && *p)
2019 { 1983 {
2020 q = p; 1984 q = p;
2021 p = _mbschr (q, '\\'); 1985 p = strchr (q, '\\');
2022 if (p) *p = '\0'; 1986 if (p) *p = '\0';
2023 len = get_long_basename (full, o, size); 1987 len = get_long_basename (full, o, size);
2024 if (len > 0) 1988 if (len > 0)
@@ -2042,6 +2006,29 @@ w32_get_long_filename (char * name, char * buf, int size)
2042 return TRUE; 2006 return TRUE;
2043} 2007}
2044 2008
2009unsigned int
2010w32_get_short_filename (char * name, char * buf, int size)
2011{
2012 if (w32_unicode_filenames)
2013 {
2014 wchar_t name_utf16[MAX_PATH], short_name[MAX_PATH];
2015 unsigned int retval;
2016
2017 filename_to_utf16 (name, name_utf16);
2018 retval = GetShortPathNameW (name_utf16, short_name, size);
2019 if (retval && retval < size)
2020 filename_from_utf16 (short_name, buf);
2021 return retval;
2022 }
2023 else
2024 {
2025 char name_ansi[MAX_PATH];
2026
2027 filename_to_ansi (name, name_ansi);
2028 return GetShortPathNameA (name_ansi, buf, size);
2029 }
2030}
2031
2045static int 2032static int
2046is_unc_volume (const char *filename) 2033is_unc_volume (const char *filename)
2047{ 2034{
@@ -2506,7 +2493,7 @@ emacs_root_dir (void)
2506 emacs_abort (); 2493 emacs_abort ();
2507 strcpy (root_dir, p); 2494 strcpy (root_dir, p);
2508 root_dir[parse_root (root_dir, NULL)] = '\0'; 2495 root_dir[parse_root (root_dir, NULL)] = '\0';
2509 dostounix_filename (root_dir, 0); 2496 dostounix_filename (root_dir);
2510 return root_dir; 2497 return root_dir;
2511} 2498}
2512 2499
@@ -3937,49 +3924,6 @@ convert_from_time_t (time_t time, FILETIME * pft)
3937 pft->dwLowDateTime = tmp.LowPart; 3924 pft->dwLowDateTime = tmp.LowPart;
3938} 3925}
3939 3926
3940#if 0
3941/* No reason to keep this; faking inode values either by hashing or even
3942 using the file index from GetInformationByHandle, is not perfect and
3943 so by default Emacs doesn't use the inode values on Windows.
3944 Instead, we now determine file-truename correctly (except for
3945 possible drive aliasing etc). */
3946
3947/* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
3948static unsigned
3949hashval (const unsigned char * str)
3950{
3951 unsigned h = 0;
3952 while (*str)
3953 {
3954 h = (h << 4) + *str++;
3955 h ^= (h >> 28);
3956 }
3957 return h;
3958}
3959
3960/* Return the hash value of the canonical pathname, excluding the
3961 drive/UNC header, to get a hopefully unique inode number. */
3962static DWORD
3963generate_inode_val (const char * name)
3964{
3965 char fullname[ MAX_PATH ];
3966 char * p;
3967 unsigned hash;
3968
3969 /* Get the truly canonical filename, if it exists. (Note: this
3970 doesn't resolve aliasing due to subst commands, or recognize hard
3971 links. */
3972 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
3973 emacs_abort ();
3974
3975 parse_root (fullname, &p);
3976 /* Normal W32 filesystems are still case insensitive. */
3977 _strlwr (p);
3978 return hashval (p);
3979}
3980
3981#endif
3982
3983static PSECURITY_DESCRIPTOR 3927static PSECURITY_DESCRIPTOR
3984get_file_security_desc_by_handle (HANDLE h) 3928get_file_security_desc_by_handle (HANDLE h)
3985{ 3929{