Mercurial > hg > xemacs-beta
diff src/nt.c @ 2526:902d5bd9b75c
[xemacs-hg @ 2005-01-28 02:36:11 by ben]
Support symlinks under Windows
nt.c, fileio.c: Fix sync comments.
config.h.in, dired-msw.c, emacs.c, event-msw.c, fileio.c, glyphs.c, lisp.h, nt.c, process-nt.c, realpath.c, sound.c, symsinit.h, sysdep.c, sysfile.h, syswindows.h, win32.c: Add support for treating shortcuts under Windows as symbolic links.
Enabled with mswindows-shortcuts-are-links (t by default). Rewrite
lots of places to use PATHNAME_CONVERT_OUT, which is moved to
sysfile.h. Add PATHNAME_RESOLVE_LINKS, which only does things
under Windows.
Add profiling section for expand_file_name calls.
nt.c, sysdep.c: Unicode-ize.
realpath.c: Renamed from readlink_and_correct_case. Fix some problems with
Windows implementation due to incorrect understanding of workings
of the function.
sound.c, ntplay.c, sound.h: Rename play_sound_file to nt_play_sound_file and pass
internally-formatted data to it to avoid converting out and back
again.
text.h: is_c -> is_ascii.
author | ben |
---|---|
date | Fri, 28 Jan 2005 02:36:28 +0000 |
parents | ab71ad6ff3dd |
children | 5eb04c84c7ae |
line wrap: on
line diff
--- a/src/nt.c Fri Jan 28 02:05:05 2005 +0000 +++ b/src/nt.c Fri Jan 28 02:36:28 2005 +0000 @@ -30,7 +30,7 @@ incomplete synching, so beware.) Synched (completely!) with Emacs 20.6 by Ben Wing, 6-23-00. Largely rewritten by Ben Wing for XEmacs Mule support. - Synched (completely!) with Emacs 21.1.103 by Ben Wing, 6-13-01. + Synched (completely!) with Emacs 21.0.103 by Ben Wing, 6-13-01. */ /* This file Mule-ized by Ben Wing, 6-23-00. */ @@ -295,7 +295,7 @@ if (qxestrpbrk (name, "*?|<>\"")) return 0; - C_STRING_TO_TSTR (name, nameext); + PATHNAME_CONVERT_OUT (name, nameext); dir_handle = qxeFindFirstFile (nameext, &find_data); if (dir_handle != INVALID_HANDLE_VALUE) { @@ -663,7 +663,7 @@ Ibyte drive[3] = { root_dir[0], ':' }; Extbyte *driveext; - C_STRING_TO_TSTR (drive, driveext); + PATHNAME_CONVERT_OUT (drive, driveext); if (qxeWNetGetConnection (driveext, remote_name, sizeof (remote_name) / XETCHAR_SIZE) == NO_ERROR) @@ -682,7 +682,7 @@ Extbyte type[256 * MAX_XETCHAR_SIZE]; Extbyte *rootdirext; - C_STRING_TO_TSTR (root_dir, rootdirext); + PATHNAME_CONVERT_OUT (root_dir, rootdirext); /* Info is not cached, or is stale. */ if (!qxeGetVolumeInformation (rootdirext, @@ -869,16 +869,16 @@ { DECLARE_EISTRING (filename); Ichar lastch; + Extbyte *fileext; eicpy_rawz (filename, dir_pathname); lastch = eigetch_char (filename, eicharlen (filename) - 1); if (!IS_DIRECTORY_SEP (lastch)) eicat_ch (filename, '\\'); eicat_ch (filename, '*'); - eito_external (filename, Qmswindows_tstr); + PATHNAME_CONVERT_OUT (eidata (filename), fileext); - dir_find_handle = qxeFindFirstFile (eiextdata (filename), - &dir_find_data); + dir_find_handle = qxeFindFirstFile (fileext, &dir_find_data); if (dir_find_handle == INVALID_HANDLE_VALUE) return NULL; @@ -902,6 +902,33 @@ DECLARE_EISTRING (found); Bytecount namlen; + if (mswindows_shortcuts_are_symlinks) + { + int len = qxestrlen (val); + if (len > 4 && !qxestrcasecmp_ascii (val + len - 4, ".LNK")) + { + /* If we've found a valid link, then chop off the .LNK ending */ + DECLARE_EISTRING (linkname); + Ichar lastch; + Ibyte *resolved; + + /* First check if link is valid */ + PATHNAME_RESOLVE_LINKS (dir_pathname, resolved); + eicpy_rawz (linkname, resolved); + lastch = eigetch_char (linkname, eicharlen (linkname) - 1); + if (!IS_DIRECTORY_SEP (lastch)) + eicat_ch (linkname, '\\'); + eicat_rawz (linkname, val); + resolved = mswindows_read_link (eidata (linkname)); + if (resolved) + { + xfree (resolved, Ibyte *); + len -= 4; + val[len] = '\0'; + } + } + } + eicpy_rawz (found, val); if (need_to_free) xfree (val, Ibyte *); @@ -930,7 +957,7 @@ nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER; nr.dwUsage = RESOURCEUSAGE_CONTAINER; nr.lpLocalName = NULL; - C_STRING_TO_TSTR (path, nr.lpRemoteName); + PATHNAME_CONVERT_OUT (path, nr.lpRemoteName); nr.lpComment = NULL; nr.lpProvider = NULL; @@ -1023,7 +1050,7 @@ { Extbyte *pathext; - C_STRING_TO_TSTR (path, pathext); + PATHNAME_CONVERT_OUT (path, pathext); if ((attributes = qxeGetFileAttributes (pathext)) == -1) { /* Should try mapping GetLastError to errno; for now just indicate @@ -1066,7 +1093,7 @@ return -1; } - C_STRING_TO_TSTR (old, oldext); + PATHNAME_CONVERT_OUT (old, oldext); fileh = qxeCreateFile (oldext, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (fileh != INVALID_HANDLE_VALUE) @@ -1175,8 +1202,8 @@ seems to make the second rename work properly. */ qxesprintf (p, "_.%s.%u", o, i); i++; - C_STRING_TO_EXTERNAL (oldname, oldext, Qfile_name); - C_STRING_TO_EXTERNAL (temp, tempext, Qfile_name); + PATHNAME_CONVERT_OUT (oldname, oldext); + PATHNAME_CONVERT_OUT (temp, tempext); result = rename (oldext, tempext); } /* This loop must surely terminate! */ @@ -1198,15 +1225,28 @@ { Extbyte *newext, *tempext; - C_STRING_TO_EXTERNAL (newname, newext, Qfile_name); - C_STRING_TO_EXTERNAL (temp, tempext, Qfile_name); - result = rename (tempext, newext); - - if (result < 0 - && (errno == EEXIST || errno == EACCES) - && _chmod (newext, 0666) == 0 - && _unlink (newext) == 0) - result = rename (tempext, newext); + PATHNAME_CONVERT_OUT (newname, newext); + PATHNAME_CONVERT_OUT (temp, tempext); + if (XEUNICODE_P) + { + result = _wrename ((const wchar_t *) tempext, + (const wchar_t *) newext); + if (result < 0 + && (errno == EEXIST || errno == EACCES) + && _wchmod ((const wchar_t *) newext, 0666) == 0 + && _wunlink ((const wchar_t *) newext) == 0) + result = _wrename ((const wchar_t *) tempext, + (const wchar_t *) newext); + } + else + { + result = rename (tempext, newext); + if (result < 0 + && (errno == EEXIST || errno == EACCES) + && _chmod (newext, 0666) == 0 + && _unlink (newext) == 0) + result = rename (tempext, newext); + } } return result; @@ -1217,10 +1257,18 @@ { Extbyte *pathout; - C_STRING_TO_EXTERNAL (path, pathout, Qfile_name); + PATHNAME_CONVERT_OUT (path, pathout); /* On Unix, unlink works without write permission. */ - _chmod (pathout, 0666); - return _unlink (pathout); + if (XEUNICODE_P) + { + _wchmod ((const wchar_t *) pathout, 0666); + return _wunlink ((const wchar_t *) pathout); + } + else + { + _chmod (pathout, 0666); + return _unlink (pathout); + } } static FILETIME utc_base_ft; @@ -1510,6 +1558,8 @@ { if (!IS_DIRECTORY_SEP (name[len-1])) qxestrcat (name, (Ibyte *) "\\"); + /* File has already been resolved and we don't want to do it again + in case of lstat() */ C_STRING_TO_TSTR (name, nameext); if (qxeGetDriveType (nameext) < 2) { @@ -1574,13 +1624,15 @@ else { if (!NILP (Vmswindows_get_true_file_attributes)) + /* File has already been resolved and we don't want to do it again + in case of lstat() */ C_STRING_TO_TSTR (name, nameext); if (!NILP (Vmswindows_get_true_file_attributes) /* No access rights required to get info. */ && (fh = qxeCreateFile (nameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { - /* This is more accurate in terms of gettting the correct number + /* This is more accurate in terms of getting the correct number of links, but is quite slow (it is noticable when Emacs is making a list of file name completions). */ BY_HANDLE_FILE_INFORMATION info; @@ -1623,6 +1675,22 @@ buf->st_nlink = 1; fake_inode = 0; } + + if (mswindows_shortcuts_are_symlinks && + buf->st_mode == _S_IFREG) + { + len = qxestrlen (name); + if (len > 4 && !qxestrcasecmp_ascii (name + len - 4, ".LNK")) + { + /* check if link is valid */ + Ibyte *resolved = mswindows_read_link (name); + if (resolved) + { + xfree (resolved, Ibyte *); + buf->st_mode = S_IFLNK; + } + } + } } SetErrorMode (errm); @@ -1698,7 +1766,7 @@ times = &deftime; } - LISP_STRING_TO_TSTR (path, filename); + LISP_PATHNAME_CONVERT_OUT (path, filename); /* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */ #if 0 /* Need write access to set times. */ @@ -1768,7 +1836,7 @@ DWORD size, upper_size; Extbyte *fileext; - C_STRING_TO_TSTR (filename, fileext); + PATHNAME_CONVERT_OUT (filename, fileext); file = qxeCreateFile (fileext, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); @@ -1804,7 +1872,7 @@ void *file_base; Extbyte *fileext; - C_STRING_TO_TSTR (filename, fileext); + PATHNAME_CONVERT_OUT (filename, fileext); file = qxeCreateFile (fileext, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); @@ -2007,7 +2075,7 @@ /* first expand it. */ filename = Fexpand_file_name (filename, Qnil); - LISP_STRING_TO_TSTR (filename, fileext); + LISP_PATHNAME_CONVERT_OUT (filename, fileext); /* luckily, this returns the short version of each element in the path. */ if (qxeGetShortPathName (fileext, shortname, sizeof (shortname) / XETCHAR_SIZE) == 0) @@ -2121,7 +2189,7 @@ { Extbyte *driveext; - C_STRING_TO_TSTR (drive, driveext); + PATHNAME_CONVERT_OUT (drive, driveext); /* Record if this drive letter refers to a fixed drive. */ fixed_drives[DRIVE_INDEX (*drive)] =