Mercurial > hg > xemacs-beta
annotate src/nt.c @ 4976:16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-04 Ben Wing <ben@xemacs.org>
* alloc.c (release_breathing_space):
* alloc.c (resize_string):
* alloc.c (sweep_lcrecords_1):
* alloc.c (SWEEP_FIXED_TYPE_BLOCK_1):
* alloc.c (ADDITIONAL_FREE_compiled_function):
* alloc.c (compact_string_chars):
* alloc.c (ADDITIONAL_FREE_string):
* alloc.c (sweep_strings):
* alloca.c (xemacs_c_alloca):
* alsaplay.c (alsa_play_sound_file):
* buffer.c (init_initial_directory):
* buffer.h:
* buffer.h (BUFFER_FREE):
* console-stream.c (stream_delete_console):
* console-tty.c (free_tty_console_struct):
* data.c (Fnumber_to_string):
* device-gtk.c (gtk_init_device):
* device-gtk.c (free_gtk_device_struct):
* device-gtk.c (gtk_delete_device):
* device-msw.c (mswindows_delete_device):
* device-msw.c (msprinter_delete_device):
* device-tty.c (free_tty_device_struct):
* device-tty.c (tty_delete_device):
* device-x.c (x_init_device):
* device-x.c (free_x_device_struct):
* device-x.c (x_delete_device):
* dialog-msw.c (handle_directory_dialog_box):
* dialog-x.c (dbox_descriptor_to_widget_value):
* dired-msw.c (Fmswindows_insert_directory):
* dired.c (free_user_cache):
* dired.c (user_name_completion_unwind):
* doc.c (unparesseuxify_doc_string):
* doc.c (Fsubstitute_command_keys):
* doprnt.c (emacs_doprnt_1):
* dumper.c (pdump_load_finish):
* dumper.c (pdump_file_free):
* dumper.c (pdump_file_unmap):
* dynarr.c:
* dynarr.c (Dynarr_free):
* editfns.c (uncache_home_directory):
* editfns.c (Fset_time_zone_rule):
* elhash.c:
* elhash.c (pdump_reorganize_hash_table):
* elhash.c (maphash_unwind):
* emacs.c (make_arg_list_1):
* emacs.c (free_argc_argv):
* emacs.c (sort_args):
* emacs.c (Frunning_temacs_p):
* emodules.c (attempt_module_delete):
* eval.c (free_pointer):
* event-Xt.c (unselect_filedesc):
* event-Xt.c (emacs_Xt_select_process):
* event-gtk.c (unselect_filedesc):
* event-gtk.c (dragndrop_data_received):
* event-msw.c (winsock_closer):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (mswindows_wnd_proc):
* event-stream.c (finalize_command_builder):
* event-stream.c (free_command_builder):
* extents.c (free_gap_array):
* extents.c (free_extent_list):
* extents.c (free_soe):
* extents.c (extent_fragment_delete):
* extents.c (extent_priority_sort_function):
* file-coding.c (make_coding_system_1):
* file-coding.c (coding_finalizer):
* file-coding.c (set_coding_stream_coding_system):
* file-coding.c (chain_finalize_coding_stream_1):
* file-coding.c (chain_finalize):
* file-coding.c (free_detection_state):
* file-coding.c (coding_category_symbol_to_id):
* fileio.c:
* fileio.c (Ffile_name_directory):
* fileio.c (if):
* fileio.c (Ffile_symlink_p):
* filelock.c (FREE_LOCK_INFO):
* filelock.c (current_lock_owner):
* font-mgr.c (Ffc_name_unparse):
* font-mgr.c (Ffc_pattern_duplicate):
* frame-gtk.c (gtk_delete_frame):
* frame-msw.c (mswindows_delete_frame):
* frame-msw.c (msprinter_delete_frame):
* frame-x.c (x_cde_destroy_callback):
* frame-x.c (Fcde_start_drag_internal):
* frame-x.c (x_cde_transfer_callback):
* frame-x.c (x_delete_frame):
* frame.c (update_frame_title):
* frame.c (Fset_frame_pointer):
* gc.c (register_for_finalization):
* gccache-gtk.c (free_gc_cache):
* gccache-gtk.c (gc_cache_lookup):
* gccache-x.c (free_gc_cache):
* gccache-x.c (gc_cache_lookup):
* glyphs-eimage.c:
* glyphs-eimage.c (jpeg_instantiate_unwind):
* glyphs-eimage.c (gif_instantiate_unwind):
* glyphs-eimage.c (png_instantiate_unwind):
* glyphs-eimage.c (png_instantiate):
* glyphs-eimage.c (tiff_instantiate_unwind):
* glyphs-gtk.c (convert_EImage_to_GDKImage):
* glyphs-gtk.c (gtk_finalize_image_instance):
* glyphs-gtk.c (gtk_init_image_instance_from_eimage):
* glyphs-gtk.c (gtk_xpm_instantiate):
* glyphs-msw.c (convert_EImage_to_DIBitmap):
* glyphs-msw.c (mswindows_init_image_instance_from_eimage):
* glyphs-msw.c (mswindows_initialize_image_instance_mask):
* glyphs-msw.c (xpm_to_eimage):
* glyphs-msw.c (mswindows_xpm_instantiate):
* glyphs-msw.c (xbm_create_bitmap_from_data):
* glyphs-msw.c (mswindows_finalize_image_instance):
* glyphs-x.c (convert_EImage_to_XImage):
* glyphs-x.c (x_finalize_image_instance):
* glyphs-x.c (x_init_image_instance_from_eimage):
* glyphs-x.c (x_xpm_instantiate):
* gui-x.c (free_popup_widget_value_tree):
* hash.c (free_hash_table):
* hash.c (grow_hash_table):
* hash.c (pregrow_hash_table_if_necessary):
* imgproc.c (build_EImage_quantable):
* insdel.c (uninit_buffer_text):
* intl-win32.c (convert_multibyte_to_internal_malloc):
* intl.c:
* intl.c (Fset_current_locale):
* keymap.c:
* keymap.c (where_is_recursive_mapper):
* keymap.c (where_is_internal):
* lisp.h:
* lisp.h (xfree):
* lstream.c (Lstream_close):
* lstream.c (resizing_buffer_closer):
* mule-coding.c:
* mule-coding.c (iso2022_finalize_detection_state):
* nt.c:
* nt.c (mswindows_get_long_filename):
* nt.c (nt_get_resource):
* nt.c (init_mswindows_environment):
* nt.c (get_cached_volume_information):
* nt.c (mswindows_opendir):
* nt.c (mswindows_closedir):
* nt.c (mswindows_readdir):
* nt.c (mswindows_stat):
* nt.c (mswindows_getdcwd):
* nt.c (Fmswindows_long_file_name):
* ntplay.c (nt_play_sound_file):
* ntplay.c (play_sound_data_1):
* number-gmp.c (gmp_free):
* number-gmp.c (init_number_gmp):
* number-mp.c (bignum_to_string):
* number-mp.c (BIGNUM_TO_TYPE):
* number.c (bignum_print):
* number.c (bignum_convfree):
* number.c (ratio_print):
* number.c (bigfloat_print):
* number.c (bigfloat_finalize):
* objects-gtk.c (gtk_finalize_color_instance):
* objects-gtk.c (gtk_finalize_font_instance):
* objects-msw.c (mswindows_finalize_color_instance):
* objects-msw.c (mswindows_finalize_font_instance):
* objects-tty.c (tty_finalize_color_instance):
* objects-tty.c (tty_finalize_font_instance):
* objects-tty.c (tty_font_list):
* objects-x.c (x_finalize_color_instance):
* objects-x.c (x_finalize_font_instance):
* process.c:
* process.c (finalize_process):
* realpath.c:
* redisplay.c (add_propagation_runes):
* regex.c:
* regex.c (xfree):
* regex.c (REGEX_FREE_STACK):
* regex.c (FREE_STACK_RETURN):
* regex.c (regex_compile):
* regex.c (regexec):
* regex.c (regfree):
* scrollbar-gtk.c (gtk_free_scrollbar_instance):
* scrollbar-gtk.c (gtk_release_scrollbar_instance):
* scrollbar-msw.c (mswindows_free_scrollbar_instance):
* scrollbar-msw.c (unshow_that_mofo):
* scrollbar-x.c (x_free_scrollbar_instance):
* scrollbar-x.c (x_release_scrollbar_instance):
* select-gtk.c (emacs_gtk_selection_handle):
* select-msw.c (mswindows_own_selection):
* select-x.c:
* select-x.c (x_handle_selection_request):
* select-x.c (unexpect_property_change):
* select-x.c (x_handle_property_notify):
* select-x.c (receive_incremental_selection):
* select-x.c (x_get_window_property_as_lisp_data):
* select-x.c (Fx_get_cutbuffer_internal):
* specifier.c (finalize_specifier):
* syntax.c (uninit_buffer_syntax_cache):
* sysdep.c (qxe_allocating_getcwd):
* sysdep.c (qxe_lstat):
* sysdep.c (copy_in_passwd):
* sysdep.c (qxe_ctime):
* sysdep.c (closedir):
* sysdep.c (DIRSIZ):
* termcap.c (tgetent):
* termcap.c (tprint):
* tests.c (Ftest_data_format_conversion):
* text.c (new_dfc_convert_copy_data):
* text.h (eifree):
* text.h (eito_alloca):
* text.h (eito_external):
* toolbar-msw.c (mswindows_output_toolbar):
* ui-gtk.c (CONVERT_RETVAL):
* ui-gtk.c (__allocate_object_storage):
* unicode.c (free_from_unicode_table):
* unicode.c (free_to_unicode_table):
* unicode.c (free_charset_unicode_tables):
* win32.c (mswindows_read_link_1):
Rename: xfree(VAL, TYPE)->xfree(VAL)
Command used:
gr 'xfree *\((.*),.*\);' 'xfree (\1);' *.[ch]
Followed by grepping for 'xfree.*,' and fixing anything left.
Rationale: Having to specify the TYPE argument is annoying and
error-prone. It was originally put in to work around warnings
due to strict aliasing but years and years ago I rewrote it
in a way that doesn't use the TYPE argument at all and no one
has complained since then. (And anyway, XEmacs is far from
ever being in compliance with strict aliasing and would require
far-reaching changes to get that way.)
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Thu, 04 Feb 2010 07:28:14 -0600 |
parents | 304aebb79cd3 |
children | 3c3c1d139863 |
rev | line source |
---|---|
771 | 1 /* Utility and Unix shadow routines under MS Windows (WIN32_NATIVE defined). |
428 | 2 Copyright (C) 1994, 1995 Free Software Foundation, Inc. |
2957 | 3 Copyright (C) 2000, 2001, 2002, 2004, 2005 Ben Wing. |
428 | 4 |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to the Free | |
19 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
20 02111-1307, USA. | |
21 | |
771 | 22 */ |
428 | 23 |
771 | 24 /* Authorship: |
428 | 25 |
771 | 26 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 |
27 Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> | |
28 Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> | |
29 (Note: Sync messages from Marc Paquette may indicate | |
30 incomplete synching, so beware.) | |
31 Synched (completely!) with Emacs 20.6 by Ben Wing, 6-23-00. | |
32 Largely rewritten by Ben Wing for XEmacs Mule support. | |
2526 | 33 Synched (completely!) with Emacs 21.0.103 by Ben Wing, 6-13-01. |
771 | 34 */ |
35 | |
36 /* This file Mule-ized by Ben Wing, 6-23-00. */ | |
428 | 37 |
38 #include <config.h> | |
39 #include "lisp.h" | |
40 | |
592 | 41 #include "buffer.h" |
872 | 42 #include "process.h" |
592 | 43 |
859 | 44 #include "sysdir.h" |
45 #include "sysfile.h" | |
428 | 46 #include "sysproc.h" |
442 | 47 #include "syspwd.h" |
859 | 48 #include "syssignal.h" |
49 #include "systime.h" | |
428 | 50 |
442 | 51 #include "syswindows.h" |
428 | 52 |
771 | 53 /* Control whether stat() attempts to determine file type and link count |
54 exactly, at the expense of slower operation. Since true hard links | |
55 are supported on NTFS volumes, this is only relevant on NT. */ | |
56 Lisp_Object Vmswindows_get_true_file_attributes; | |
428 | 57 |
771 | 58 /* Vmswindows_generate_fake_inodes; deleted */ |
59 | |
60 Fixnum mswindows_fake_unix_uid; | |
428 | 61 |
62 /* Emulate getpwuid, getpwnam and others. */ | |
63 | |
771 | 64 static struct passwd the_passwd = |
428 | 65 { |
771 | 66 "", |
67 "", | |
428 | 68 0, |
69 0, | |
70 0, | |
771 | 71 "", |
72 "", | |
73 "", | |
428 | 74 }; |
75 | |
76 uid_t | |
442 | 77 getuid (void) |
440 | 78 { |
771 | 79 return mswindows_fake_unix_uid; |
428 | 80 } |
81 | |
82 uid_t | |
442 | 83 geteuid (void) |
428 | 84 { |
771 | 85 /* Emacs 20.6 says: [[I could imagine arguing for checking to see |
86 whether the user is in the Administrators group and returning a | |
87 UID of 0 for that case, but I don't know how wise that would be | |
88 in the long run.]] */ | |
89 return mswindows_fake_unix_uid; | |
428 | 90 } |
91 | |
92 gid_t | |
442 | 93 getgid (void) |
428 | 94 { |
95 return the_passwd.pw_gid; | |
96 } | |
97 | |
98 gid_t | |
442 | 99 getegid (void) |
428 | 100 { |
101 return getgid (); | |
102 } | |
103 | |
104 struct passwd * | |
105 getpwuid (uid_t uid) | |
106 { | |
771 | 107 if (uid == mswindows_fake_unix_uid) |
440 | 108 { |
109 the_passwd.pw_gid = the_passwd.pw_uid = uid; | |
110 return &the_passwd; | |
111 } | |
112 else | |
113 return NULL; | |
428 | 114 } |
115 | |
116 struct passwd * | |
867 | 117 getpwnam (const Ibyte *name) |
428 | 118 { |
119 struct passwd *pw; | |
120 | |
121 pw = getpwuid (getuid ()); | |
122 if (!pw) | |
123 return pw; | |
124 | |
1204 | 125 if (qxestrcasecmp_i18n (name, (Ibyte *) pw->pw_name)) |
428 | 126 return NULL; |
127 | |
128 return pw; | |
129 } | |
130 | |
771 | 131 static void |
442 | 132 init_user_info (void) |
428 | 133 { |
440 | 134 /* This code is pretty much of ad hoc nature. There is no unix-like |
135 UIDs under Windows NT. There is no concept of root user, because | |
136 all security is ACL-based. Instead, let's use a simple variable, | |
137 nt-fake-unix-uid, which would allow the user to have a uid of | |
138 choice. --kkm, 02/03/2000 */ | |
139 #if 0 | |
428 | 140 /* Find the user's real name by opening the process token and |
141 looking up the name associated with the user-sid in that token. | |
142 | |
143 Use the relative portion of the identifier authority value from | |
144 the user-sid as the user id value (same for group id using the | |
145 primary group sid from the process token). */ | |
146 | |
771 | 147 TOKEN_USER sidinfo; |
148 Extbyte name[256], domain[256]; | |
149 Charcount length = sizeof (name) / XETCHAR_SIZE; | |
150 Charcount dlength = sizeof (domain) / XETCHAR_SIZE; | |
151 DWORD trash; | |
152 HANDLE token = NULL; | |
153 SID_NAME_USE user_type; | |
428 | 154 |
155 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token) | |
771 | 156 && GetTokenInformation (token, TokenUser, &sidinfo, sizeof (sidinfo), |
157 &trash) | |
158 && qxeLookupAccountSid (NULL, sidinfo.User.Sid, name, &length, | |
159 domain, &dlength, &user_type)) | |
428 | 160 { |
771 | 161 TSTR_TO_C_STRING_MALLOC (name, the_passwd.pw_name); |
428 | 162 /* Determine a reasonable uid value. */ |
771 | 163 if (qxestrcasecmp ("administrator", the_passwd.pw_name) == 0) |
428 | 164 { |
165 the_passwd.pw_uid = 0; | |
166 the_passwd.pw_gid = 0; | |
167 } | |
168 else | |
169 { | |
170 SID_IDENTIFIER_AUTHORITY * pSIA; | |
771 | 171 TOKEN_PRIMARY_GROUP group; |
428 | 172 |
771 | 173 pSIA = GetSidIdentifierAuthority (sidinfo.User.Sid); |
428 | 174 /* I believe the relative portion is the last 4 bytes (of 6) |
175 with msb first. */ | |
176 the_passwd.pw_uid = ((pSIA->Value[2] << 24) + | |
177 (pSIA->Value[3] << 16) + | |
178 (pSIA->Value[4] << 8) + | |
179 (pSIA->Value[5] << 0)); | |
180 /* restrict to conventional uid range for normal users */ | |
181 the_passwd.pw_uid = the_passwd.pw_uid % 60001; | |
182 | |
183 /* Get group id */ | |
184 if (GetTokenInformation (token, TokenPrimaryGroup, | |
771 | 185 &group, sizeof (group), &trash)) |
428 | 186 { |
187 SID_IDENTIFIER_AUTHORITY * pSIA; | |
188 | |
771 | 189 pSIA = GetSidIdentifierAuthority (group.PrimaryGroup); |
428 | 190 the_passwd.pw_gid = ((pSIA->Value[2] << 24) + |
191 (pSIA->Value[3] << 16) + | |
192 (pSIA->Value[4] << 8) + | |
193 (pSIA->Value[5] << 0)); | |
194 /* I don't know if this is necessary, but for safety... */ | |
195 the_passwd.pw_gid = the_passwd.pw_gid % 60001; | |
196 } | |
197 else | |
198 the_passwd.pw_gid = the_passwd.pw_uid; | |
199 } | |
200 } | |
201 /* If security calls are not supported (presumably because we | |
202 are running under Windows 95), fallback to this. */ | |
771 | 203 else if (qxeGetUserName (name, &length)) |
428 | 204 { |
771 | 205 TSTR_TO_C_STRING_MALLOC (name, the_passwd.pw_name); |
206 if (qxestrcasecmp ("administrator", the_passwd.pw_name) == 0) | |
428 | 207 the_passwd.pw_uid = 0; |
208 else | |
209 the_passwd.pw_uid = 123; | |
210 the_passwd.pw_gid = the_passwd.pw_uid; | |
211 } | |
212 else | |
213 { | |
771 | 214 the_passwd.pw_name = "unknown"; |
428 | 215 the_passwd.pw_uid = 123; |
216 the_passwd.pw_gid = 123; | |
217 } | |
218 | |
440 | 219 if (token) |
220 CloseHandle (token); | |
221 #else | |
222 /* Obtain only logon id here, uid part is moved to getuid */ | |
771 | 223 DWORD length = UNLEN + 1; |
224 Extbyte name[MAX_XETCHAR_SIZE * (UNLEN + 1)]; | |
225 if (qxeGetUserName (name, &length)) | |
226 TSTR_TO_C_STRING_MALLOC (name, the_passwd.pw_name); | |
440 | 227 else |
771 | 228 the_passwd.pw_name = "unknown"; |
440 | 229 #endif |
230 | |
771 | 231 #if 0 |
428 | 232 /* Ensure HOME and SHELL are defined. */ |
233 /* | |
234 * With XEmacs, setting $HOME is deprecated. | |
235 */ | |
771 | 236 if (egetenv ("HOME") == NULL) |
237 eputenv ("HOME=c:/"); | |
428 | 238 #endif |
239 | |
611 | 240 /* Set dir from environment variables. */ |
771 | 241 the_passwd.pw_dir = (char *) qxestrdup (get_home_directory ()); |
611 | 242 /* We used to set pw_shell here, but the order is wrong (SHELL gets |
853 | 243 initted in process.c, called later in the init process) and pw_shell |
611 | 244 is not used anywhere. */ |
428 | 245 } |
246 | |
771 | 247 /* Parse the root part of file name, if present. Return length and |
867 | 248 optionally store pointer to Ibyte after root. */ |
771 | 249 static Bytecount |
867 | 250 parse_root (Ibyte *name, Ibyte **pPath) |
428 | 251 { |
867 | 252 Ibyte *start = name; |
428 | 253 |
254 if (name == NULL) | |
255 return 0; | |
256 | |
257 /* find the root name of the volume if given */ | |
258 if (isalpha (name[0]) && name[1] == ':') | |
259 { | |
260 /* skip past drive specifier */ | |
261 name += 2; | |
262 if (IS_DIRECTORY_SEP (name[0])) | |
263 name++; | |
264 } | |
265 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) | |
266 { | |
267 int slashes = 2; | |
268 name += 2; | |
269 do | |
270 { | |
271 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) | |
272 break; | |
273 name++; | |
274 } | |
771 | 275 while (*name); |
428 | 276 if (IS_DIRECTORY_SEP (name[0])) |
277 name++; | |
278 } | |
279 | |
280 if (pPath) | |
281 *pPath = name; | |
282 | |
283 return name - start; | |
284 } | |
285 | |
286 /* Get long base name for name; name is assumed to be absolute. */ | |
867 | 287 static Ibyte * |
288 get_long_basename (Ibyte *name) | |
428 | 289 { |
771 | 290 WIN32_FIND_DATAW find_data; |
428 | 291 HANDLE dir_handle; |
771 | 292 Extbyte *nameext; |
428 | 293 |
771 | 294 /* must be valid filename, no wild cards or other invalid characters */ |
295 if (qxestrpbrk (name, "*?|<>\"")) | |
296 return 0; | |
428 | 297 |
2526 | 298 PATHNAME_CONVERT_OUT (name, nameext); |
771 | 299 dir_handle = qxeFindFirstFile (nameext, &find_data); |
428 | 300 if (dir_handle != INVALID_HANDLE_VALUE) |
301 { | |
867 | 302 Ibyte *fileint; |
771 | 303 |
304 TSTR_TO_C_STRING_MALLOC (find_data.cFileName, fileint); | |
428 | 305 FindClose (dir_handle); |
771 | 306 return fileint; |
428 | 307 } |
771 | 308 return 0; |
428 | 309 } |
310 | |
311 /* Get long name for file, if possible (assumed to be absolute). */ | |
867 | 312 Ibyte * |
313 mswindows_get_long_filename (Ibyte *name) | |
428 | 314 { |
867 | 315 Ibyte *full = mswindows_canonicalize_filename (name); |
316 Ibyte *p; | |
317 Ibyte *q; | |
771 | 318 DECLARE_EISTRING (o); |
319 Bytecount len; | |
428 | 320 |
321 /* Copy root part verbatim. */ | |
322 len = parse_root (full, &p); | |
771 | 323 eicpy_raw (o, full, len); |
428 | 324 |
771 | 325 while (p != NULL && *p) |
428 | 326 { |
867 | 327 Ibyte *component; |
771 | 328 |
428 | 329 q = p; |
771 | 330 p = qxestrchr (q, '\\'); |
428 | 331 if (p) *p = '\0'; |
771 | 332 component = get_long_basename (full); |
333 if (component) | |
428 | 334 { |
771 | 335 eicat_rawz (o, component); |
428 | 336 if (p != NULL) |
337 { | |
338 *p++ = '\\'; | |
771 | 339 eicat_ch (o, '\\'); |
428 | 340 } |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
341 xfree (component); |
428 | 342 } |
343 else | |
771 | 344 { |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
345 xfree (full); |
771 | 346 return 0; |
347 } | |
428 | 348 } |
349 | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
350 xfree (full); |
771 | 351 return eicpyout_malloc (o, 0); |
428 | 352 } |
353 | |
771 | 354 static int |
867 | 355 is_unc_volume (const Ibyte *filename) |
771 | 356 { |
867 | 357 const Ibyte *ptr = filename; |
428 | 358 |
771 | 359 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2]) |
360 return 0; | |
361 | |
362 if (qxestrpbrk (ptr + 2, "*?|<>\"\\/")) | |
363 return 0; | |
364 | |
365 return 1; | |
428 | 366 } |
367 | |
771 | 368 /* NOTE: Value returned is still in external format. Callers need to |
369 convert. */ | |
707 | 370 #define REG_ROOT "SOFTWARE\\XEmacs\\XEmacs" |
428 | 371 |
771 | 372 static LPBYTE |
867 | 373 nt_get_resource (Ibyte *key, LPDWORD lpdwtype) |
428 | 374 { |
375 LPBYTE lpvalue; | |
376 HKEY hrootkey = NULL; | |
377 DWORD cbData; | |
771 | 378 Extbyte *keyext; |
379 | |
380 C_STRING_TO_TSTR (key, keyext); | |
428 | 381 |
382 /* Check both the current user and the local machine to see if | |
383 we have any resources. */ | |
384 | |
771 | 385 if (qxeRegOpenKeyEx (HKEY_CURRENT_USER, XETEXT (REG_ROOT), 0, KEY_READ, |
386 &hrootkey) == ERROR_SUCCESS) | |
428 | 387 { |
388 lpvalue = NULL; | |
389 | |
771 | 390 if (qxeRegQueryValueEx (hrootkey, keyext, NULL, NULL, NULL, |
391 &cbData) == ERROR_SUCCESS | |
2367 | 392 && (lpvalue = xnew_array (BYTE, cbData)) != NULL |
771 | 393 && qxeRegQueryValueEx (hrootkey, keyext, NULL, lpdwtype, lpvalue, |
394 &cbData) == ERROR_SUCCESS) | |
395 return (lpvalue); | |
428 | 396 |
1726 | 397 if (lpvalue) |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
398 xfree (lpvalue); |
428 | 399 |
400 RegCloseKey (hrootkey); | |
401 } | |
402 | |
771 | 403 if (qxeRegOpenKeyEx (HKEY_LOCAL_MACHINE, XETEXT (REG_ROOT), 0, KEY_READ, |
404 &hrootkey) == ERROR_SUCCESS) | |
428 | 405 { |
406 lpvalue = NULL; | |
407 | |
771 | 408 if (qxeRegQueryValueEx (hrootkey, keyext, NULL, NULL, NULL, |
409 &cbData) == ERROR_SUCCESS && | |
2367 | 410 (lpvalue = xnew_array (BYTE, cbData)) != NULL && |
771 | 411 qxeRegQueryValueEx (hrootkey, keyext, NULL, lpdwtype, lpvalue, |
412 &cbData) == ERROR_SUCCESS) | |
413 return (lpvalue); | |
428 | 414 |
1726 | 415 if (lpvalue) |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
416 xfree (lpvalue); |
428 | 417 |
418 RegCloseKey (hrootkey); | |
419 } | |
420 | |
421 return (NULL); | |
422 } | |
423 | |
424 void | |
814 | 425 init_mswindows_environment (void) |
428 | 426 { |
427 /* Check for environment variables and use registry if they don't exist */ | |
771 | 428 /* Emacs 20.6 sets default values for these; not necessary here because |
429 we already supply them. (except SHELL, which is set in init_user_info().) | |
430 Emacs 20.6 messes with TMPDIR; not necessary here. */ | |
428 | 431 { |
432 int i; | |
433 LPBYTE lpval; | |
434 DWORD dwType; | |
435 | |
2367 | 436 static Ascbyte *env_vars[] = |
428 | 437 { |
438 "HOME", | |
439 "EMACSLOADPATH", | |
440 "EMACSDEBUGPATHS", | |
441 "SHELL", | |
442 "CMDPROXY", | |
443 "EMACSDATA", | |
444 "EMACSPATH", | |
445 "EMACSPACKAGEPATH", | |
3179 | 446 "EMACSEARLYPACKAGES", |
447 "EMACSLATEPACKAGES", | |
448 "EMACSLASTPACKAGES", | |
771 | 449 "EMACSLOCKMETHOD", |
428 | 450 "INFOPATH" |
451 }; | |
771 | 452 #if defined (HEAP_IN_DATA) && !defined (PDUMP) |
430 | 453 cache_system_info (); |
454 #endif | |
771 | 455 |
456 #if 0 /* FSF 21.1 */ | |
457 /* !!#### i think i already do the equivalent elsewhere. | |
458 delete when i'm sure i do. | |
459 (but maybe i should be playing with LANG when the user changes | |
460 the locale, so that subprocesses get it right.) */ | |
461 /* Get default locale info and use it for LANG. */ | |
462 if (GetLocaleInfo (LOCALE_USER_DEFAULT, | |
463 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP, | |
464 locale_name, sizeof (locale_name))) | |
465 { | |
466 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) | |
467 { | |
468 if (strcmp (env_vars[i].name, "LANG") == 0) | |
469 { | |
470 env_vars[i].def_value = locale_name; | |
471 break; | |
472 } | |
473 } | |
474 } | |
475 #endif /* 0 */ | |
476 | |
428 | 477 for (i = 0; i < countof (env_vars); i++) |
478 { | |
771 | 479 if (!egetenv (env_vars[i]) && |
1204 | 480 (lpval = nt_get_resource ((Ibyte *) env_vars[i], &dwType)) != NULL) |
428 | 481 { |
482 if (dwType == REG_EXPAND_SZ) | |
483 { | |
771 | 484 Extbyte *buf = NULL; |
867 | 485 Ibyte *envval; |
771 | 486 Charcount cch; |
428 | 487 |
771 | 488 cch = qxeExpandEnvironmentStrings ((Extbyte *) lpval, buf, 0); |
2367 | 489 buf = alloca_extbytes (cch * XETCHAR_SIZE); |
771 | 490 qxeExpandEnvironmentStrings ((Extbyte *) lpval, buf, cch); |
491 TSTR_TO_C_STRING (buf, envval); | |
1204 | 492 eputenv (env_vars[i], (CIbyte *) envval); |
428 | 493 } |
494 else if (dwType == REG_SZ) | |
495 { | |
867 | 496 Ibyte *envval; |
771 | 497 |
498 TSTR_TO_C_STRING (lpval, envval); | |
1204 | 499 eputenv (env_vars[i], (CIbyte *) envval); |
428 | 500 } |
501 | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
502 xfree (lpval); |
428 | 503 } |
504 } | |
505 } | |
506 | |
507 /* Another special case: on NT, the PATH variable is actually named | |
508 "Path" although cmd.exe (perhaps NT itself) arranges for | |
509 environment variable lookup and setting to be case insensitive. | |
510 However, Emacs assumes a fully case sensitive environment, so we | |
511 need to change "Path" to "PATH" to match the expectations of | |
771 | 512 various elisp packages. |
428 | 513 |
514 The same applies to COMSPEC. */ | |
515 { | |
2367 | 516 EXTERNAL_LIST_LOOP_2 (str, Vprocess_environment) |
771 | 517 { |
518 if (STRINGP (str)) | |
519 { | |
867 | 520 Ibyte *dat = XSTRING_DATA (str); |
2367 | 521 if (qxestrncasecmp_ascii (dat, "PATH=", 5) == 0) |
771 | 522 memcpy (dat, "PATH=", 5); |
2367 | 523 else if (qxestrncasecmp_ascii (dat, "COMSPEC=", 8) == 0) |
771 | 524 memcpy (dat, "COMSPEC=", 8); |
525 } | |
526 } | |
428 | 527 } |
528 | |
529 init_user_info (); | |
530 } | |
531 | |
771 | 532 /* Emacs 20.6 contains a routine get_emacs_configuration() here to set |
533 EMACS_CONFIGURATION. */ | |
428 | 534 #ifndef HAVE_X_WINDOWS |
535 /* X11R6 on NT provides the single parameter version of this command. */ | |
536 | |
537 #include <sys/timeb.h> | |
538 | |
539 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */ | |
540 void | |
541 gettimeofday (struct timeval *tv, struct timezone *tz) | |
542 { | |
543 struct _timeb tb; | |
544 _ftime (&tb); | |
545 | |
546 tv->tv_sec = tb.time; | |
547 tv->tv_usec = tb.millitm * 1000L; | |
548 if (tz) | |
549 { | |
550 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ | |
551 tz->tz_dsttime = tb.dstflag; /* type of dst correction */ | |
552 } | |
553 } | |
554 | |
555 #endif /* HAVE_X_WINDOWS */ | |
556 | |
771 | 557 |
428 | 558 /* ------------------------------------------------------------------------- */ |
771 | 559 /* IO support and wrapper functions for Win32 API. */ |
428 | 560 /* ------------------------------------------------------------------------- */ |
561 | |
771 | 562 typedef struct volume_info_data |
428 | 563 { |
771 | 564 struct volume_info_data *next; |
428 | 565 |
566 /* time when info was obtained */ | |
771 | 567 DWORD timestamp; |
428 | 568 |
569 /* actual volume info */ | |
867 | 570 Ibyte *root_dir; |
771 | 571 DWORD serialnum; |
572 DWORD maxcomp; | |
573 DWORD flags; | |
867 | 574 Ibyte *name; |
575 Ibyte *type; | |
428 | 576 } volume_info_data; |
577 | |
578 /* Global referenced by various functions. */ | |
579 static volume_info_data volume_info; | |
580 | |
581 /* Vector to indicate which drives are local and fixed (for which cached | |
582 data never expires). */ | |
583 static BOOL fixed_drives[26]; | |
584 | |
585 /* Consider cached volume information to be stale if older than 10s, | |
586 at least for non-local drives. Info for fixed drives is never stale. */ | |
587 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' ) | |
588 #define VOLINFO_STILL_VALID( root_dir, info ) \ | |
589 ( ( isalpha (root_dir[0]) && \ | |
590 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \ | |
591 || GetTickCount () - info->timestamp < 10000 ) | |
592 | |
593 /* Cache support functions. */ | |
594 | |
595 /* Simple linked list with linear search is sufficient. */ | |
596 static volume_info_data *volume_cache = NULL; | |
597 | |
598 static volume_info_data * | |
867 | 599 lookup_volume_info (Ibyte *root_dir) |
428 | 600 { |
771 | 601 volume_info_data *info; |
428 | 602 |
603 for (info = volume_cache; info; info = info->next) | |
771 | 604 if (qxestrcasecmp_i18n (info->root_dir, root_dir) == 0) |
428 | 605 break; |
606 return info; | |
607 } | |
608 | |
609 static void | |
867 | 610 add_volume_info (Ibyte *root_dir, volume_info_data *info) |
428 | 611 { |
771 | 612 info->root_dir = qxestrdup (root_dir); |
428 | 613 info->next = volume_cache; |
614 volume_cache = info; | |
615 } | |
616 | |
617 | |
618 /* Wrapper for GetVolumeInformation, which uses caching to avoid | |
619 performance penalty (~2ms on 486 for local drives, 7.5ms for local | |
620 cdrom drive, ~5-10ms or more for remote drives on LAN). */ | |
771 | 621 static volume_info_data * |
867 | 622 get_cached_volume_information (Ibyte *root_dir) |
428 | 623 { |
771 | 624 volume_info_data *info; |
867 | 625 Ibyte *default_root; |
428 | 626 |
627 /* NULL for root_dir means use root from current directory. */ | |
628 if (root_dir == NULL) | |
629 { | |
771 | 630 Charcount nchars = qxeGetCurrentDirectory (0, NULL); |
631 Extbyte *rootext; | |
632 | |
633 if (!nchars) | |
428 | 634 return NULL; |
771 | 635 rootext = alloca_extbytes (nchars * XETCHAR_SIZE); |
636 if (!qxeGetCurrentDirectory (nchars, rootext)) | |
637 return NULL; | |
638 TSTR_TO_C_STRING (rootext, default_root); | |
428 | 639 parse_root (default_root, &root_dir); |
640 *root_dir = 0; | |
641 root_dir = default_root; | |
642 } | |
643 | |
644 /* Local fixed drives can be cached permanently. Removable drives | |
645 cannot be cached permanently, since the volume name and serial | |
646 number (if nothing else) can change. Remote drives should be | |
647 treated as if they are removable, since there is no sure way to | |
648 tell whether they are or not. Also, the UNC association of drive | |
649 letters mapped to remote volumes can be changed at any time (even | |
650 by other processes) without notice. | |
651 | |
652 As a compromise, so we can benefit from caching info for remote | |
653 volumes, we use a simple expiry mechanism to invalidate cache | |
654 entries that are more than ten seconds old. */ | |
655 | |
656 #if 0 | |
657 /* No point doing this, because WNetGetConnection is even slower than | |
658 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW, | |
659 GetDriveType is about the only call of this type which does not | |
660 involve network access, and so is extremely quick). */ | |
661 | |
662 /* Map drive letter to UNC if remote. */ | |
771 | 663 if (isalpha (root_dir[0]) && !fixed [DRIVE_INDEX (root_dir[0])]) |
428 | 664 { |
771 | 665 Extbyte remote_name[256 * XETCHAR_SIZE]; |
867 | 666 Ibyte drive[3] = { root_dir[0], ':' }; |
771 | 667 Extbyte *driveext; |
428 | 668 |
2526 | 669 PATHNAME_CONVERT_OUT (drive, driveext); |
771 | 670 if (qxeWNetGetConnection (driveext, remote_name, |
671 sizeof (remote_name) / XETCHAR_SIZE) | |
428 | 672 == NO_ERROR) |
673 /* do something */ ; | |
674 } | |
675 #endif | |
676 | |
677 info = lookup_volume_info (root_dir); | |
678 | |
679 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info)) | |
771 | 680 { |
681 Extbyte name[256 * MAX_XETCHAR_SIZE]; | |
682 DWORD serialnum; | |
683 DWORD maxcomp; | |
684 DWORD flags; | |
685 Extbyte type[256 * MAX_XETCHAR_SIZE]; | |
1204 | 686 Extbyte *rootdirext; |
687 | |
2526 | 688 PATHNAME_CONVERT_OUT (root_dir, rootdirext); |
428 | 689 |
771 | 690 /* Info is not cached, or is stale. */ |
1204 | 691 if (!qxeGetVolumeInformation (rootdirext, |
771 | 692 name, sizeof (name) / XETCHAR_SIZE, |
693 &serialnum, | |
694 &maxcomp, | |
695 &flags, | |
696 type, sizeof (type) / XETCHAR_SIZE)) | |
697 return NULL; | |
428 | 698 |
771 | 699 /* Cache the volume information for future use, overwriting existing |
700 entry if present. */ | |
701 if (info == NULL) | |
702 { | |
2367 | 703 info = xnew (volume_info_data); |
771 | 704 add_volume_info (root_dir, info); |
705 } | |
706 else | |
707 { | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
708 xfree (info->name); |
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
709 xfree (info->type); |
771 | 710 } |
428 | 711 |
771 | 712 TSTR_TO_C_STRING_MALLOC (name, info->name); |
713 info->serialnum = serialnum; | |
714 info->maxcomp = maxcomp; | |
715 info->flags = flags; | |
716 TSTR_TO_C_STRING_MALLOC (type, info->type); | |
717 info->timestamp = GetTickCount (); | |
718 } | |
428 | 719 |
720 return info; | |
721 } | |
722 | |
723 /* Get information on the volume where name is held; set path pointer to | |
724 start of pathname in name (past UNC header\volume header if present). */ | |
771 | 725 static int |
867 | 726 get_volume_info (const Ibyte *name, const Ibyte **pPath) |
428 | 727 { |
771 | 728 /* We probably only need a couple of bytes, but let's be generous in |
729 case this function gets changed */ | |
2367 | 730 Ibyte *temp = alloca_ibytes (qxestrlen (name) + 10); |
867 | 731 Ibyte *rootname = NULL; /* default to current volume */ |
771 | 732 volume_info_data *info; |
428 | 733 |
734 if (name == NULL) | |
735 return FALSE; | |
736 | |
737 /* find the root name of the volume if given */ | |
738 if (isalpha (name[0]) && name[1] == ':') | |
739 { | |
740 rootname = temp; | |
741 temp[0] = *name++; | |
742 temp[1] = *name++; | |
743 temp[2] = '\\'; | |
744 temp[3] = 0; | |
745 } | |
746 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) | |
747 { | |
867 | 748 Ibyte *str = temp; |
428 | 749 int slashes = 4; |
750 rootname = temp; | |
751 do | |
752 { | |
753 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) | |
754 break; | |
755 *str++ = *name++; | |
756 } | |
771 | 757 while (*name); |
428 | 758 |
759 *str++ = '\\'; | |
760 *str = 0; | |
761 } | |
762 | |
763 if (pPath) | |
764 *pPath = name; | |
765 | |
771 | 766 info = get_cached_volume_information (rootname); |
428 | 767 if (info != NULL) |
768 { | |
769 /* Set global referenced by other functions. */ | |
770 volume_info = *info; | |
771 return TRUE; | |
772 } | |
773 return FALSE; | |
774 } | |
775 | |
771 | 776 /* XEmacs: Everything referring to map_win32_filename() aka map_w32_filename() |
777 removed; it was only for NT 3.1, which we hereby do not support. (NT 3.5 | |
778 predates Windows 95!) */ | |
428 | 779 |
1204 | 780 int |
781 mswindows_is_executable (const Ibyte *name) | |
771 | 782 { |
867 | 783 Ibyte *p = qxestrrchr (name, '.'); |
2367 | 784 return (p != NULL && (qxestrcasecmp_ascii (p, ".exe") == 0 || |
785 qxestrcasecmp_ascii (p, ".com") == 0 || | |
786 qxestrcasecmp_ascii (p, ".bat") == 0 || | |
787 qxestrcasecmp_ascii (p, ".cmd") == 0)); | |
428 | 788 } |
789 | |
790 /* Emulate the Unix directory procedures opendir, closedir, | |
791 and readdir. We can't use the procedures supplied in sysdep.c, | |
792 so we provide them here. */ | |
793 | |
794 struct direct dir_static; /* simulated directory contents */ | |
795 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE; | |
771 | 796 /* dir_is_fat deleted */ |
867 | 797 static Ibyte *dir_pathname; |
771 | 798 static WIN32_FIND_DATAW dir_find_data; |
799 | |
800 /* Support shares on a network resource as subdirectories of a read-only | |
801 root directory. */ | |
802 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE; | |
867 | 803 static HANDLE open_unc_volume (const Ibyte *); |
804 static Ibyte *read_unc_volume (HANDLE); | |
771 | 805 static int close_unc_volume (HANDLE); |
428 | 806 |
807 DIR * | |
867 | 808 mswindows_opendir (const Ibyte *filename) |
428 | 809 { |
810 DIR *dirp; | |
811 | |
812 /* Opening is done by FindFirstFile. However, a read is inherent to | |
813 this operation, so we defer the open until read time. */ | |
814 | |
771 | 815 if (dir_find_handle != INVALID_HANDLE_VALUE) |
428 | 816 return NULL; |
771 | 817 if (wnet_enum_handle != INVALID_HANDLE_VALUE) |
428 | 818 return NULL; |
819 | |
771 | 820 if (is_unc_volume (filename)) |
821 { | |
822 wnet_enum_handle = open_unc_volume (filename); | |
823 if (wnet_enum_handle == INVALID_HANDLE_VALUE) | |
824 return NULL; | |
825 } | |
428 | 826 |
771 | 827 if (!(dirp = xnew_and_zero (DIR))) |
828 return NULL; | |
829 | |
830 if (dir_pathname) | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
831 xfree (dir_pathname); |
771 | 832 dir_pathname = qxestrdup (filename); |
428 | 833 |
834 return dirp; | |
835 } | |
836 | |
442 | 837 int |
771 | 838 mswindows_closedir (DIR *dirp) |
428 | 839 { |
2957 | 840 int retval = -1; |
442 | 841 |
428 | 842 /* If we have a find-handle open, close it. */ |
843 if (dir_find_handle != INVALID_HANDLE_VALUE) | |
844 { | |
771 | 845 retval = FindClose (dir_find_handle) ? 0 : -1; |
428 | 846 dir_find_handle = INVALID_HANDLE_VALUE; |
847 } | |
771 | 848 else if (wnet_enum_handle != INVALID_HANDLE_VALUE) |
849 { | |
850 retval = close_unc_volume (wnet_enum_handle); | |
851 wnet_enum_handle = INVALID_HANDLE_VALUE; | |
852 } | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
853 xfree (dirp); |
771 | 854 |
855 return retval; | |
856 } | |
857 | |
858 struct direct * | |
2286 | 859 mswindows_readdir (DIR *UNUSED (dirp)) |
771 | 860 { |
867 | 861 Ibyte *val; |
771 | 862 int need_to_free = 0; |
863 | |
864 if (wnet_enum_handle != INVALID_HANDLE_VALUE) | |
865 { | |
866 if (!(val = read_unc_volume (wnet_enum_handle))) | |
867 return NULL; | |
868 need_to_free = 1; | |
869 } | |
870 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ | |
871 else if (dir_find_handle == INVALID_HANDLE_VALUE) | |
872 { | |
873 DECLARE_EISTRING (filename); | |
867 | 874 Ichar lastch; |
2526 | 875 Extbyte *fileext; |
771 | 876 |
877 eicpy_rawz (filename, dir_pathname); | |
878 lastch = eigetch_char (filename, eicharlen (filename) - 1); | |
879 if (!IS_DIRECTORY_SEP (lastch)) | |
880 eicat_ch (filename, '\\'); | |
881 eicat_ch (filename, '*'); | |
2526 | 882 PATHNAME_CONVERT_OUT (eidata (filename), fileext); |
771 | 883 |
2526 | 884 dir_find_handle = qxeFindFirstFile (fileext, &dir_find_data); |
771 | 885 |
886 if (dir_find_handle == INVALID_HANDLE_VALUE) | |
887 return NULL; | |
888 TSTR_TO_C_STRING (dir_find_data.cFileName, val); | |
889 } | |
890 else | |
891 { | |
892 if (!qxeFindNextFile (dir_find_handle, &dir_find_data)) | |
893 return NULL; | |
894 TSTR_TO_C_STRING (dir_find_data.cFileName, val); | |
895 } | |
896 | |
897 /* XEmacs never uses this value, so don't bother making it match | |
898 value returned by qxe_stat(). */ | |
899 dir_static.d_ino = 1; | |
900 | |
901 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 + | |
902 dir_static.d_namlen - dir_static.d_namlen % 4; | |
903 | |
904 { | |
905 DECLARE_EISTRING (found); | |
906 Bytecount namlen; | |
907 | |
2526 | 908 if (mswindows_shortcuts_are_symlinks) |
909 { | |
910 int len = qxestrlen (val); | |
911 if (len > 4 && !qxestrcasecmp_ascii (val + len - 4, ".LNK")) | |
912 { | |
913 /* If we've found a valid link, then chop off the .LNK ending */ | |
914 DECLARE_EISTRING (linkname); | |
915 Ichar lastch; | |
916 Ibyte *resolved; | |
917 | |
918 /* First check if link is valid */ | |
919 PATHNAME_RESOLVE_LINKS (dir_pathname, resolved); | |
920 eicpy_rawz (linkname, resolved); | |
921 lastch = eigetch_char (linkname, eicharlen (linkname) - 1); | |
922 if (!IS_DIRECTORY_SEP (lastch)) | |
923 eicat_ch (linkname, '\\'); | |
924 eicat_rawz (linkname, val); | |
925 resolved = mswindows_read_link (eidata (linkname)); | |
926 if (resolved) | |
927 { | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
928 xfree (resolved); |
2526 | 929 len -= 4; |
930 val[len] = '\0'; | |
931 } | |
932 } | |
933 } | |
934 | |
771 | 935 eicpy_rawz (found, val); |
936 if (need_to_free) | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
937 xfree (val); |
771 | 938 |
939 if (!NILP (Vmswindows_downcase_file_names)) | |
940 eilwr (found); | |
941 | |
942 namlen = min (eilen (found), sizeof (dir_static.d_name) - 1); | |
943 strncpy (dir_static.d_name, (char *) eidata (found), namlen); | |
944 dir_static.d_name[namlen] = '\0'; | |
945 dir_static.d_namlen = (unsigned short) namlen; | |
946 } | |
947 | |
948 return &dir_static; | |
949 } | |
950 | |
951 static HANDLE | |
867 | 952 open_unc_volume (const Ibyte *path) |
771 | 953 { |
954 NETRESOURCEW nr; | |
955 HANDLE henum; | |
956 int result; | |
957 | |
958 nr.dwScope = RESOURCE_GLOBALNET; | |
959 nr.dwType = RESOURCETYPE_DISK; | |
960 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER; | |
961 nr.dwUsage = RESOURCEUSAGE_CONTAINER; | |
962 nr.lpLocalName = NULL; | |
2526 | 963 PATHNAME_CONVERT_OUT (path, nr.lpRemoteName); |
771 | 964 nr.lpComment = NULL; |
965 nr.lpProvider = NULL; | |
966 | |
967 result = qxeWNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, | |
968 RESOURCEUSAGE_CONNECTABLE, &nr, &henum); | |
969 | |
970 if (result == NO_ERROR) | |
971 return henum; | |
972 else | |
973 return INVALID_HANDLE_VALUE; | |
974 } | |
975 | |
867 | 976 static Ibyte * |
2286 | 977 read_unc_volume (HANDLE UNUSED (henum)) |
771 | 978 { |
1204 | 979 DWORD count; |
771 | 980 int result; |
981 Extbyte buf[16384]; | |
867 | 982 Ibyte *ptr; |
1204 | 983 DWORD bufsize = sizeof (buf); |
771 | 984 |
985 count = 1; | |
986 /* #### we should just be querying the size and then allocating the | |
987 right amount, like for all similar API's. but the docs say this ?! | |
988 | |
989 An application cannot set the lpBuffer parameter to NULL and | |
990 retrieve the required buffer size from the lpBufferSize | |
991 parameter. Instead, the application should allocate a buffer of a | |
992 reasonable size -- 16 kilobytes (K) is typical -- and use the value | |
993 of lpBufferSize for error detection. | |
994 */ | |
995 | |
996 result = qxeWNetEnumResource (wnet_enum_handle, &count, buf, &bufsize); | |
997 if (result != NO_ERROR) | |
998 return NULL; | |
999 | |
1000 /* WNetEnumResource returns \\resource\share...skip forward to "share". */ | |
1001 TSTR_TO_C_STRING (((LPNETRESOURCEW) buf)->lpRemoteName, ptr); | |
867 | 1002 INC_IBYTEPTR (ptr); |
1003 INC_IBYTEPTR (ptr); | |
1004 while (*ptr && !IS_DIRECTORY_SEP (itext_ichar (ptr))) | |
1005 INC_IBYTEPTR (ptr); | |
1006 INC_IBYTEPTR (ptr); | |
771 | 1007 |
1008 return qxestrdup (ptr); | |
1009 } | |
1010 | |
1011 static int | |
1012 close_unc_volume (HANDLE henum) | |
1013 { | |
1014 if (henum != INVALID_HANDLE_VALUE) | |
1015 return WNetCloseEnum (henum) == NO_ERROR ? 0 : -1; | |
442 | 1016 else |
1017 return -1; | |
428 | 1018 } |
1019 | |
771 | 1020 static DWORD |
867 | 1021 unc_volume_file_attributes (const Ibyte *path) |
428 | 1022 { |
771 | 1023 HANDLE henum; |
1024 DWORD attrs; | |
1025 | |
1026 henum = open_unc_volume (path); | |
1027 if (henum == INVALID_HANDLE_VALUE) | |
1028 return -1; | |
1029 | |
1030 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY; | |
1031 | |
1032 close_unc_volume (henum); | |
428 | 1033 |
771 | 1034 return attrs; |
1035 } | |
1036 | |
1037 int | |
867 | 1038 mswindows_access (const Ibyte *path, int mode) |
771 | 1039 { |
1040 DWORD attributes; | |
428 | 1041 |
771 | 1042 /* MSVC implementation doesn't recognize D_OK. */ |
1043 if (is_unc_volume (path)) | |
1044 { | |
1045 attributes = unc_volume_file_attributes (path); | |
1046 if (attributes == -1) | |
1047 { | |
1048 errno = EACCES; | |
1049 return -1; | |
1050 } | |
428 | 1051 } |
1052 else | |
1053 { | |
771 | 1054 Extbyte *pathext; |
1055 | |
2526 | 1056 PATHNAME_CONVERT_OUT (path, pathext); |
771 | 1057 if ((attributes = qxeGetFileAttributes (pathext)) == -1) |
1058 { | |
1059 /* Should try mapping GetLastError to errno; for now just indicate | |
1060 that path doesn't exist. */ | |
1061 errno = EACCES; | |
1062 return -1; | |
1063 } | |
428 | 1064 } |
1204 | 1065 if ((mode & X_OK) != 0 && !mswindows_is_executable (path)) |
771 | 1066 { |
1067 errno = EACCES; | |
1068 return -1; | |
1069 } | |
1070 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0) | |
428 | 1071 { |
771 | 1072 errno = EACCES; |
1073 return -1; | |
428 | 1074 } |
771 | 1075 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) |
1076 { | |
1077 errno = EACCES; | |
1078 return -1; | |
1079 } | |
1080 return 0; | |
428 | 1081 } |
1082 | |
771 | 1083 /* This only works on NTFS volumes, but is useful to have. */ |
1084 /* #### NT 5.0 has a function CreateHardLink to do this directly, | |
1085 and it may do more things. */ | |
428 | 1086 int |
2957 | 1087 mswindows_link (const Ibyte *old, const Ibyte *new_) |
428 | 1088 { |
771 | 1089 HANDLE fileh; |
1090 int result = -1; | |
1204 | 1091 Extbyte *oldext; |
771 | 1092 |
2957 | 1093 if (old == NULL || new_ == NULL) |
771 | 1094 { |
1095 errno = ENOENT; | |
1096 return -1; | |
1097 } | |
1098 | |
2526 | 1099 PATHNAME_CONVERT_OUT (old, oldext); |
1204 | 1100 fileh = qxeCreateFile (oldext, 0, 0, NULL, OPEN_EXISTING, |
771 | 1101 FILE_FLAG_BACKUP_SEMANTICS, NULL); |
1102 if (fileh != INVALID_HANDLE_VALUE) | |
1103 { | |
1104 int wlen; | |
1105 WCHAR *newuni; | |
1106 | |
1107 /* Confusingly, the "alternate" stream name field does not apply | |
1108 when restoring a hard link, and instead contains the actual | |
1109 stream data for the link (ie. the name of the link to create). | |
1110 The WIN32_STREAM_ID structure before the cStreamName field is | |
1111 the stream header, which is then immediately followed by the | |
1112 stream data. */ | |
1113 | |
1114 struct | |
1115 { | |
1116 WIN32_STREAM_ID wid; | |
2421 | 1117 WCHAR wbuffer[_MAX_PATH]; /* extra space for link name */ |
771 | 1118 } data; |
1119 | |
2957 | 1120 TO_EXTERNAL_FORMAT (C_STRING, new_, |
771 | 1121 ALLOCA, (newuni, wlen), Qmswindows_unicode); |
2421 | 1122 if (wlen / sizeof (WCHAR) < _MAX_PATH) |
771 | 1123 { |
1124 LPVOID context = NULL; | |
1125 DWORD wbytes = 0; | |
428 | 1126 |
771 | 1127 wcscpy (data.wid.cStreamName, newuni); |
1128 data.wid.dwStreamId = BACKUP_LINK; | |
1129 data.wid.dwStreamAttributes = 0; | |
4638
5bbff3553494
mswindows_link had off-by-one error. <1vq2brxz.wl_Ron.Isaacson@morganstanley.com>
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4487
diff
changeset
|
1130 /* Include the trailing null. In bytes, not chars! */ |
5bbff3553494
mswindows_link had off-by-one error. <1vq2brxz.wl_Ron.Isaacson@morganstanley.com>
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4487
diff
changeset
|
1131 data.wid.Size.LowPart = wlen + sizeof (WCHAR); |
771 | 1132 data.wid.Size.HighPart = 0; |
1133 data.wid.dwStreamNameSize = 0; | |
1134 | |
1135 if (BackupWrite (fileh, (LPBYTE)&data, | |
1136 offsetof (WIN32_STREAM_ID, cStreamName) | |
1137 + data.wid.Size.LowPart, | |
1138 &wbytes, FALSE, FALSE, &context) | |
1139 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context)) | |
1140 { | |
1141 /* succeeded */ | |
1142 result = 0; | |
1143 } | |
1144 else | |
1145 { | |
1146 /* Should try mapping GetLastError to errno; for now just | |
1147 indicate a general error (eg. links not supported). */ | |
1242 | 1148 errno = EINVAL; /* perhaps EMLINK? */ |
771 | 1149 } |
1150 } | |
1151 | |
1152 CloseHandle (fileh); | |
1153 } | |
1154 else | |
1155 errno = ENOENT; | |
1156 | |
1157 return result; | |
1158 } | |
1159 | |
1160 /* sys_open() merged into sysdep.c sys_open() */ | |
1161 | |
1162 int | |
867 | 1163 mswindows_rename (const Ibyte *oldname, const Ibyte *newname) |
771 | 1164 { |
1165 int result; | |
867 | 1166 Ibyte *temp; |
771 | 1167 |
1168 /* MoveFile on Windows 95 doesn't correctly change the short file name | |
428 | 1169 alias in a number of circumstances (it is not easy to predict when |
1170 just by looking at oldname and newname, unfortunately). In these | |
1171 cases, renaming through a temporary name avoids the problem. | |
1172 | |
771 | 1173 A second problem on Windows 95 is that renaming through a temp name when |
428 | 1174 newname is uppercase fails (the final long name ends up in |
1175 lowercase, although the short alias might be uppercase) UNLESS the | |
1176 long temp name is not 8.3. | |
1177 | |
771 | 1178 So, on Windows 95 we always rename through a temp name, and we make sure |
428 | 1179 the temp name has a long extension to ensure correct renaming. */ |
1180 | |
771 | 1181 /* XEmacs: We sprintf() part of OLDNAME into part of OLDNAME + a number, |
1182 so the following calculation should certainly be enough. */ | |
428 | 1183 |
867 | 1184 temp = qxestrcpy (alloca_ibytes (2 * qxestrlen (oldname) + 100), oldname); |
771 | 1185 |
1186 if (mswindows_windows9x_p) | |
428 | 1187 { |
867 | 1188 Ibyte *o; |
1189 Ibyte *p; | |
771 | 1190 int i = 0; |
428 | 1191 |
771 | 1192 if (o = qxestrrchr (oldname, '\\')) |
1193 o++; | |
1194 else | |
867 | 1195 o = (Ibyte *) oldname; |
771 | 1196 |
1197 if (p = qxestrrchr (temp, '\\')) | |
428 | 1198 p++; |
1199 else | |
1200 p = temp; | |
771 | 1201 |
1202 do | |
1203 { | |
1204 Extbyte *oldext, *tempext; | |
1205 /* Force temp name to require a manufactured 8.3 alias - this | |
1206 seems to make the second rename work properly. */ | |
1207 qxesprintf (p, "_.%s.%u", o, i); | |
1208 i++; | |
2526 | 1209 PATHNAME_CONVERT_OUT (oldname, oldext); |
1210 PATHNAME_CONVERT_OUT (temp, tempext); | |
771 | 1211 result = rename (oldext, tempext); |
1212 } | |
1213 /* This loop must surely terminate! */ | |
1214 while (result < 0 && errno == EEXIST); | |
1215 if (result < 0) | |
428 | 1216 return -1; |
1217 } | |
1218 | |
771 | 1219 /* Emulate Unix behaviour - newname is deleted if it already exists |
428 | 1220 (at least if it is a file; don't do this for directories). |
771 | 1221 |
1222 Since we mustn't do this if we are just changing the case of the | |
1223 file name (we would end up deleting the file we are trying to | |
1224 rename!), we let rename detect if the destination file already | |
1225 exists - that way we avoid the possible pitfalls of trying to | |
1226 determine ourselves whether two names really refer to the same | |
1227 file, which is not always possible in the general case. (Consider | |
1228 all the permutations of shared or subst'd drives, etc.) */ | |
1229 { | |
1230 Extbyte *newext, *tempext; | |
1231 | |
2526 | 1232 PATHNAME_CONVERT_OUT (newname, newext); |
1233 PATHNAME_CONVERT_OUT (temp, tempext); | |
1234 if (XEUNICODE_P) | |
1235 { | |
1236 result = _wrename ((const wchar_t *) tempext, | |
1237 (const wchar_t *) newext); | |
1238 if (result < 0 | |
1239 && (errno == EEXIST || errno == EACCES) | |
1240 && _wchmod ((const wchar_t *) newext, 0666) == 0 | |
1241 && _wunlink ((const wchar_t *) newext) == 0) | |
1242 result = _wrename ((const wchar_t *) tempext, | |
1243 (const wchar_t *) newext); | |
1244 } | |
1245 else | |
1246 { | |
1247 result = rename (tempext, newext); | |
1248 if (result < 0 | |
1249 && (errno == EEXIST || errno == EACCES) | |
1250 && _chmod (newext, 0666) == 0 | |
1251 && _unlink (newext) == 0) | |
1252 result = rename (tempext, newext); | |
1253 } | |
771 | 1254 } |
1255 | |
1256 return result; | |
1257 } | |
428 | 1258 |
771 | 1259 int |
867 | 1260 mswindows_unlink (const Ibyte *path) |
771 | 1261 { |
1262 Extbyte *pathout; | |
1263 | |
2526 | 1264 PATHNAME_CONVERT_OUT (path, pathout); |
771 | 1265 /* On Unix, unlink works without write permission. */ |
2526 | 1266 if (XEUNICODE_P) |
1267 { | |
1268 _wchmod ((const wchar_t *) pathout, 0666); | |
1269 return _wunlink ((const wchar_t *) pathout); | |
1270 } | |
1271 else | |
1272 { | |
1273 _chmod (pathout, 0666); | |
1274 return _unlink (pathout); | |
1275 } | |
428 | 1276 } |
1277 | |
1278 static FILETIME utc_base_ft; | |
592 | 1279 static long double utc_base; |
440 | 1280 static int init = 0; |
771 | 1281 static LARGE_INTEGER utc_base_li; |
440 | 1282 |
771 | 1283 /* XEmacs: We seem to have a new definition of |
1284 mswindows_convert_time(), although I'm not sure why. --ben */ | |
428 | 1285 |
1286 time_t | |
771 | 1287 mswindows_convert_time (FILETIME uft) |
440 | 1288 { |
1289 time_t ret; | |
1290 #ifndef MAXLONGLONG | |
1291 SYSTEMTIME st; | |
1292 struct tm t; | |
1293 FILETIME ft; | |
1294 TIME_ZONE_INFORMATION tzi; | |
1295 DWORD tzid; | |
1296 #else | |
1297 LARGE_INTEGER lft; | |
1298 #endif | |
1299 | |
1300 if (!init) | |
1301 { | |
1302 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ | |
1303 SYSTEMTIME st; | |
1304 | |
1305 st.wYear = 1970; | |
1306 st.wMonth = 1; | |
1307 st.wDay = 1; | |
1308 st.wHour = 0; | |
1309 st.wMinute = 0; | |
1310 st.wSecond = 0; | |
1311 st.wMilliseconds = 0; | |
1312 | |
1313 SystemTimeToFileTime (&st, &utc_base_ft); | |
1314 | |
1315 utc_base_li.LowPart = utc_base_ft.dwLowDateTime; | |
1316 utc_base_li.HighPart = utc_base_ft.dwHighDateTime; | |
1317 | |
1318 init = 1; | |
1319 } | |
1320 | |
1321 #ifdef MAXLONGLONG | |
1322 | |
1323 /* On a compiler that supports long integers, do it the easy way */ | |
1324 lft.LowPart = uft.dwLowDateTime; | |
1325 lft.HighPart = uft.dwHighDateTime; | |
1326 ret = (time_t) ((lft.QuadPart - utc_base_li.QuadPart) / 10000000); | |
1327 | |
1328 #else | |
1329 | |
1330 /* Do it the hard way using mktime. */ | |
1331 FileTimeToLocalFileTime(&uft, &ft); | |
1332 FileTimeToSystemTime (&ft, &st); | |
1333 tzid = GetTimeZoneInformation (&tzi); | |
1334 t.tm_year = st.wYear - 1900; | |
1335 t.tm_mon = st.wMonth - 1; | |
1336 t.tm_mday = st.wDay; | |
1337 t.tm_hour = st.wHour; | |
1338 t.tm_min = st.wMinute; | |
1339 t.tm_sec = st.wSecond; | |
1340 t.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT); | |
1341 /* st.wMilliseconds not applicable */ | |
1342 ret = mktime(&t); | |
1343 if (ret == -1) | |
1344 { | |
1345 ret = 0; | |
1346 } | |
1347 | |
1348 #endif | |
1349 | |
1350 return ret; | |
1351 } | |
428 | 1352 |
771 | 1353 static void |
428 | 1354 convert_from_time_t (time_t time, FILETIME * pft) |
1355 { | |
1356 long double tmp; | |
1357 | |
1358 if (!init) | |
1359 { | |
1360 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ | |
1361 SYSTEMTIME st; | |
1362 | |
1363 st.wYear = 1970; | |
1364 st.wMonth = 1; | |
1365 st.wDay = 1; | |
1366 st.wHour = 0; | |
1367 st.wMinute = 0; | |
1368 st.wSecond = 0; | |
1369 st.wMilliseconds = 0; | |
1370 | |
1371 SystemTimeToFileTime (&st, &utc_base_ft); | |
1372 utc_base = (long double) utc_base_ft.dwHighDateTime | |
1373 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime; | |
1374 init = 1; | |
1375 } | |
1376 | |
1377 /* time in 100ns units since 1-Jan-1601 */ | |
1378 tmp = (long double) time * 1e7 + utc_base; | |
1379 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024)); | |
771 | 1380 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * |
1381 pft->dwHighDateTime); | |
428 | 1382 } |
1383 | |
1384 #if 0 | |
771 | 1385 /* A comment from Emacs 20.6: |
1386 | |
1387 No reason to keep this; faking inode values either by hashing or even | |
428 | 1388 using the file index from GetInformationByHandle, is not perfect and |
1389 so by default Emacs doesn't use the inode values on Windows. | |
1390 Instead, we now determine file-truename correctly (except for | |
1391 possible drive aliasing etc). */ | |
1392 | |
771 | 1393 /* XEmacs: Removed the fake-inodes code here, which was if 0'd out. |
1394 If you want it, look in w32.c in Emacs 20.6. */ | |
428 | 1395 #endif |
1396 | |
442 | 1397 /* #### aichner@ecf.teradyne.com reported that with the library |
1398 provided stat/fstat, (file-exist "d:\\tmp\\") =>> nil, | |
1399 (file-exist "d:\\tmp") =>> t, when d:\tmp exists. Whenever | |
1400 we opt to use non-encapsulated stat(), this should serve as | |
1401 a compatibility test. --kkm */ | |
440 | 1402 |
771 | 1403 /* Provide fstat and utime as well as stat for consistent handling of |
1404 file timestamps. */ | |
442 | 1405 int |
771 | 1406 mswindows_fstat (int desc, struct stat *buf) |
432 | 1407 { |
448 | 1408 HANDLE fh = (HANDLE) _get_osfhandle (desc); |
1409 BY_HANDLE_FILE_INFORMATION info; | |
1410 DWORD fake_inode; | |
1411 int permission; | |
1412 | |
1413 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE) | |
432 | 1414 { |
448 | 1415 case FILE_TYPE_DISK: |
1416 buf->st_mode = _S_IFREG; | |
1417 if (!GetFileInformationByHandle (fh, &info)) | |
1418 { | |
1419 errno = EACCES; | |
1420 return -1; | |
1421 } | |
1422 break; | |
1423 case FILE_TYPE_PIPE: | |
1424 buf->st_mode = _S_IFIFO; | |
1425 goto non_disk; | |
1426 case FILE_TYPE_CHAR: | |
1427 case FILE_TYPE_UNKNOWN: | |
1428 default: | |
1429 buf->st_mode = _S_IFCHR; | |
1430 non_disk: | |
1431 memset (&info, 0, sizeof (info)); | |
1432 info.dwFileAttributes = 0; | |
1433 info.ftCreationTime = utc_base_ft; | |
1434 info.ftLastAccessTime = utc_base_ft; | |
1435 info.ftLastWriteTime = utc_base_ft; | |
1436 } | |
1437 | |
1438 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1439 { | |
1440 buf->st_mode = _S_IFDIR; | |
1441 buf->st_nlink = 2; /* doesn't really matter */ | |
1442 fake_inode = 0; /* this doesn't either I think */ | |
432 | 1443 } |
1444 else | |
1445 { | |
462 | 1446 buf->st_nlink = (short) info.nNumberOfLinks; |
448 | 1447 /* Might as well use file index to fake inode values, but this |
1448 is not guaranteed to be unique unless we keep a handle open | |
1449 all the time (even then there are situations where it is | |
1450 not unique). Reputedly, there are at most 48 bits of info | |
1451 (on NTFS, presumably less on FAT). */ | |
1452 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh; | |
432 | 1453 } |
448 | 1454 |
1455 /* MSVC defines _ino_t to be short; other libc's might not. */ | |
1456 if (sizeof (buf->st_ino) == 2) | |
462 | 1457 buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16)); |
448 | 1458 else |
462 | 1459 buf->st_ino = (unsigned short) fake_inode; |
448 | 1460 |
1461 /* consider files to belong to current user */ | |
1462 buf->st_uid = 0; | |
1463 buf->st_gid = 0; | |
1464 | |
1465 buf->st_dev = info.dwVolumeSerialNumber; | |
1466 buf->st_rdev = info.dwVolumeSerialNumber; | |
1467 | |
1468 buf->st_size = info.nFileSizeLow; | |
1469 | |
1470 /* Convert timestamps to Unix format. */ | |
771 | 1471 buf->st_mtime = mswindows_convert_time (info.ftLastWriteTime); |
1472 buf->st_atime = mswindows_convert_time (info.ftLastAccessTime); | |
448 | 1473 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; |
771 | 1474 buf->st_ctime = mswindows_convert_time (info.ftCreationTime); |
448 | 1475 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; |
1476 | |
1477 /* determine rwx permissions */ | |
1478 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) | |
1479 permission = _S_IREAD; | |
1480 else | |
1481 permission = _S_IREAD | _S_IWRITE; | |
1482 | |
1483 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1484 permission |= _S_IEXEC; | |
771 | 1485 else |
1486 { | |
1487 #if 0 /* no way of knowing the filename */ | |
1204 | 1488 if (mswindows_is_executable (name)) |
771 | 1489 permission |= _S_IEXEC; |
1490 #endif | |
1491 } | |
448 | 1492 |
1493 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); | |
1494 | |
1495 return 0; | |
432 | 1496 } |
1497 | |
428 | 1498 /* MSVC stat function can't cope with UNC names and has other bugs, so |
1499 replace it with our own. This also allows us to calculate consistent | |
1500 inode values without hacks in the main Emacs code. */ | |
1501 int | |
867 | 1502 mswindows_stat (const Ibyte *path, struct stat *buf) |
428 | 1503 { |
867 | 1504 Ibyte *name, *r; |
771 | 1505 WIN32_FIND_DATAW wfd; |
428 | 1506 HANDLE fh; |
1507 DWORD fake_inode; | |
1508 int permission; | |
771 | 1509 Bytecount len; |
428 | 1510 int rootdir = FALSE; |
771 | 1511 Extbyte *nameext; |
819 | 1512 int errm; |
428 | 1513 |
1514 if (path == NULL || buf == NULL) | |
1515 { | |
1516 errno = EFAULT; | |
1517 return -1; | |
1518 } | |
1519 | |
867 | 1520 name = qxestrcpy (alloca_ibytes (qxestrlen (path) + 10), path); |
819 | 1521 errm = SetErrorMode (SEM_FAILCRITICALERRORS |
1522 | SEM_NOOPENFILEERRORBOX); | |
771 | 1523 |
1524 get_volume_info (name, &path); | |
1525 /* must be valid filename, no wild cards or other invalid characters */ | |
1526 if (qxestrpbrk (name, "*?|<>\"")) | |
428 | 1527 { |
1528 errno = ENOENT; | |
1529 return -1; | |
1530 } | |
1531 | |
771 | 1532 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */ |
1533 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name; | |
1534 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0') | |
1535 { | |
1536 r[1] = r[2] = '\0'; | |
1537 } | |
1538 | |
428 | 1539 /* Remove trailing directory separator, unless name is the root |
1540 directory of a drive or UNC volume in which case ensure there | |
1541 is a trailing separator. */ | |
771 | 1542 len = qxestrlen (name); |
428 | 1543 rootdir = (path >= name + len - 1 |
1544 && (IS_DIRECTORY_SEP (*path) || *path == 0)); | |
771 | 1545 |
1546 if (is_unc_volume (name)) | |
1547 { | |
1548 DWORD attrs = unc_volume_file_attributes (name); | |
1549 | |
1550 if (attrs == -1) | |
1551 return -1; | |
428 | 1552 |
771 | 1553 memset (&wfd, 0, sizeof (wfd)); |
1554 wfd.dwFileAttributes = attrs; | |
1555 wfd.ftCreationTime = utc_base_ft; | |
1556 wfd.ftLastAccessTime = utc_base_ft; | |
1557 wfd.ftLastWriteTime = utc_base_ft; | |
1558 /* XEmacs deleted: strcpy (wfd.cFileName, name); | |
1559 Not used later on. */ | |
1560 } | |
1561 else if (rootdir) | |
428 | 1562 { |
1563 if (!IS_DIRECTORY_SEP (name[len-1])) | |
867 | 1564 qxestrcat (name, (Ibyte *) "\\"); |
2526 | 1565 /* File has already been resolved and we don't want to do it again |
1566 in case of lstat() */ | |
771 | 1567 C_STRING_TO_TSTR (name, nameext); |
1568 if (qxeGetDriveType (nameext) < 2) | |
428 | 1569 { |
819 | 1570 SetErrorMode (errm); |
428 | 1571 errno = ENOENT; |
1572 return -1; | |
1573 } | |
1574 memset (&wfd, 0, sizeof (wfd)); | |
1575 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; | |
1576 wfd.ftCreationTime = utc_base_ft; | |
1577 wfd.ftLastAccessTime = utc_base_ft; | |
1578 wfd.ftLastWriteTime = utc_base_ft; | |
771 | 1579 /* XEmacs deleted: strcpy (wfd.cFileName, name); |
1580 Not used later on. */ | |
428 | 1581 } |
1582 else | |
1583 { | |
1584 if (IS_DIRECTORY_SEP (name[len-1])) | |
1585 name[len - 1] = 0; | |
1586 | |
1587 /* (This is hacky, but helps when doing file completions on | |
1588 network drives.) Optimize by using information available from | |
1589 active readdir if possible. */ | |
771 | 1590 if (dir_pathname) |
1591 { | |
1592 len = qxestrlen (dir_pathname); | |
1593 if (len && IS_DIRECTORY_SEP (dir_pathname[len-1])) | |
1594 len--; | |
1595 } | |
1596 if (dir_find_handle != INVALID_HANDLE_VALUE | |
1597 && dir_pathname | |
801 | 1598 && qxestrncasecmp_i18n (dir_pathname, name, len) == 0 |
771 | 1599 && IS_DIRECTORY_SEP (name[len]) |
1600 && qxestrcasecmp_i18n (name + len + 1, | |
867 | 1601 (Ibyte *) dir_static.d_name) == 0) |
428 | 1602 { |
1603 /* This was the last entry returned by readdir. */ | |
1604 wfd = dir_find_data; | |
1605 } | |
1606 else | |
1607 { | |
771 | 1608 C_STRING_TO_TSTR (name, nameext); |
1609 fh = qxeFindFirstFile (nameext, &wfd); | |
1610 if (fh == INVALID_HANDLE_VALUE) | |
1611 { | |
819 | 1612 SetErrorMode (errm); |
771 | 1613 errno = ENOENT; |
1614 return -1; | |
1615 } | |
1616 FindClose (fh); | |
1617 /* XEmacs: Don't need to convert wfd.cFileName because | |
1618 not used later on. */ | |
428 | 1619 } |
1620 } | |
1621 | |
1622 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1623 { | |
1624 buf->st_mode = _S_IFDIR; | |
1625 buf->st_nlink = 2; /* doesn't really matter */ | |
1626 fake_inode = 0; /* this doesn't either I think */ | |
1627 } | |
771 | 1628 else |
428 | 1629 { |
771 | 1630 if (!NILP (Vmswindows_get_true_file_attributes)) |
2526 | 1631 /* File has already been resolved and we don't want to do it again |
1632 in case of lstat() */ | |
771 | 1633 C_STRING_TO_TSTR (name, nameext); |
1634 if (!NILP (Vmswindows_get_true_file_attributes) | |
1635 /* No access rights required to get info. */ | |
1636 && (fh = qxeCreateFile (nameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) | |
1637 != INVALID_HANDLE_VALUE) | |
1638 { | |
2526 | 1639 /* This is more accurate in terms of getting the correct number |
771 | 1640 of links, but is quite slow (it is noticable when Emacs is |
1641 making a list of file name completions). */ | |
1642 BY_HANDLE_FILE_INFORMATION info; | |
428 | 1643 |
771 | 1644 if (GetFileInformationByHandle (fh, &info)) |
1645 { | |
1646 buf->st_nlink = (short) info.nNumberOfLinks; | |
1647 /* Might as well use file index to fake inode values, but this | |
1648 is not guaranteed to be unique unless we keep a handle open | |
1649 all the time (even then there are situations where it is | |
1650 not unique). Reputedly, there are at most 48 bits of info | |
1651 (on NTFS, presumably less on FAT). */ | |
1652 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh; | |
1653 } | |
1654 else | |
1655 { | |
1656 buf->st_nlink = 1; | |
1657 fake_inode = 0; | |
1658 } | |
428 | 1659 |
1660 switch (GetFileType (fh)) | |
1661 { | |
1662 case FILE_TYPE_DISK: | |
1663 buf->st_mode = _S_IFREG; | |
1664 break; | |
1665 case FILE_TYPE_PIPE: | |
1666 buf->st_mode = _S_IFIFO; | |
1667 break; | |
1668 case FILE_TYPE_CHAR: | |
1669 case FILE_TYPE_UNKNOWN: | |
1670 default: | |
1671 buf->st_mode = _S_IFCHR; | |
1672 } | |
1673 CloseHandle (fh); | |
1674 } | |
1675 else | |
1676 { | |
771 | 1677 /* Don't bother to make this information more accurate. */ |
1678 buf->st_mode = _S_IFREG; | |
1679 buf->st_nlink = 1; | |
1680 fake_inode = 0; | |
428 | 1681 } |
2526 | 1682 |
1683 if (mswindows_shortcuts_are_symlinks && | |
1684 buf->st_mode == _S_IFREG) | |
1685 { | |
1686 len = qxestrlen (name); | |
1687 if (len > 4 && !qxestrcasecmp_ascii (name + len - 4, ".LNK")) | |
1688 { | |
1689 /* check if link is valid */ | |
1690 Ibyte *resolved = mswindows_read_link (name); | |
1691 if (resolved) | |
1692 { | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1693 xfree (resolved); |
2526 | 1694 buf->st_mode = S_IFLNK; |
1695 } | |
1696 } | |
1697 } | |
428 | 1698 } |
1699 | |
819 | 1700 SetErrorMode (errm); |
1701 | |
428 | 1702 #if 0 |
771 | 1703 /* XEmacs: Removed the fake-inodes code here, which was if 0'd out. |
1704 If you want it, look in w32.c in Emacs 20.6. */ | |
428 | 1705 #endif |
1706 | |
771 | 1707 /* MSVC defines _ino_t to be short; other libc's might not. */ |
1708 if (sizeof (buf->st_ino) == 2) | |
1709 buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16)); | |
1710 else | |
1711 buf->st_ino = (unsigned short) fake_inode; | |
428 | 1712 |
1713 /* consider files to belong to current user */ | |
771 | 1714 buf->st_uid = the_passwd.pw_uid; |
1715 buf->st_gid = the_passwd.pw_gid; | |
428 | 1716 |
771 | 1717 /* volume_info is set by get_volume_info */ |
428 | 1718 buf->st_dev = volume_info.serialnum; |
1719 buf->st_rdev = volume_info.serialnum; | |
1720 | |
771 | 1721 |
428 | 1722 buf->st_size = wfd.nFileSizeLow; |
1723 | |
1724 /* Convert timestamps to Unix format. */ | |
771 | 1725 buf->st_mtime = mswindows_convert_time (wfd.ftLastWriteTime); |
1726 buf->st_atime = mswindows_convert_time (wfd.ftLastAccessTime); | |
428 | 1727 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; |
771 | 1728 buf->st_ctime = mswindows_convert_time (wfd.ftCreationTime); |
428 | 1729 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; |
1730 | |
1731 /* determine rwx permissions */ | |
1732 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) | |
1733 permission = _S_IREAD; | |
1734 else | |
1735 permission = _S_IREAD | _S_IWRITE; | |
1736 | |
1737 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
1738 permission |= _S_IEXEC; | |
1204 | 1739 else if (mswindows_is_executable (name)) |
771 | 1740 permission |= _S_IEXEC; |
428 | 1741 |
1742 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); | |
1743 | |
1744 return 0; | |
1745 } | |
1746 | |
1747 int | |
771 | 1748 mswindows_utime (Lisp_Object path, struct utimbuf *times) |
428 | 1749 { |
771 | 1750 /* #### Supposedly we're providing this because standard utime() |
1751 might not work; or at the very least to get consistent results | |
1752 since we replace other time-handling routines in stat. But out | |
1753 replacement doesn't seem to work, probably due to some subtle bug | |
1754 in this routine, which should be investigated eventually. So for | |
1755 the moment, we just use utime(), which conceivably might be | |
1756 slightly off in comparison with our own routines? Seems strange, | |
1757 and so far no problems seen. --ben */ | |
428 | 1758 |
771 | 1759 struct utimbuf deftime; |
1760 #if 0 | |
1761 HANDLE fh; | |
1762 #endif | |
1763 static FILETIME mtime; | |
1764 static FILETIME atime; | |
1765 Extbyte *filename; | |
428 | 1766 |
771 | 1767 if (times == NULL) |
428 | 1768 { |
771 | 1769 deftime.modtime = deftime.actime = time (NULL); |
1770 times = &deftime; | |
428 | 1771 } |
1772 | |
2526 | 1773 LISP_PATHNAME_CONVERT_OUT (path, filename); |
771 | 1774 /* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */ |
1775 #if 0 | |
1776 /* Need write access to set times. */ | |
1777 fh = qxeCreateFile (filename, GENERIC_WRITE, | |
1778 FILE_SHARE_READ | FILE_SHARE_WRITE, | |
1779 0, OPEN_EXISTING, 0, NULL); | |
1780 if (fh) | |
1781 { | |
1782 convert_from_time_t (times->actime, &atime); | |
1783 convert_from_time_t (times->modtime, &mtime); | |
1784 if (!SetFileTime (fh, NULL, &atime, &mtime)) | |
1785 { | |
1786 CloseHandle (fh); | |
1787 errno = EACCES; | |
1788 return -1; | |
1789 } | |
1790 CloseHandle (fh); | |
1791 } | |
1792 else | |
1793 { | |
1794 errno = EINVAL; | |
1795 return -1; | |
1796 } | |
1797 return 0; | |
1798 #else | |
1799 { | |
1800 struct _utimbuf newtimes; | |
1801 | |
1802 newtimes.actime = times->actime; | |
1803 newtimes.modtime = times->modtime; | |
1804 | |
1805 if (XEUNICODE_P) | |
1806 return _wutime ((const wchar_t *) filename, &newtimes); | |
1807 else | |
1808 return _utime (filename, &newtimes); | |
1809 } | |
1810 #endif | |
1811 } | |
1812 | |
867 | 1813 Ibyte * |
771 | 1814 mswindows_getdcwd (int drivelet) |
1815 { | |
1816 Extbyte *cwdext; | |
867 | 1817 Ibyte *cwd; |
4786 | 1818 /* Following comment and two-liner fix comes from |
1819 https://bugzilla.mozilla.org/show_bug.cgi?id=419326 which | |
1820 apparently fell prey to this feature of msvcrt8 as well. */ | |
1821 /* We need to worry about IPH, for details read bug 419326. | |
1822 * _getdrives - http://msdn2.microsoft.com/en-us/library/xdhk0xd2.aspx | |
1823 * uses a bitmask, bit 0 is 'a:' | |
1824 * _chdrive - http://msdn2.microsoft.com/en-us/library/0d1409hb.aspx | |
1825 * _getdcwd - http://msdn2.microsoft.com/en-us/library/7t2zk3s4.aspx | |
1826 * take an int, 1 is 'a:'. | |
1827 * | |
1828 * Because of this, we need to do some math. Subtract 1 to convert from | |
1829 * _chdrive/_getdcwd format to _getdrives drive numbering. | |
1830 * Shift left x bits to convert from integer indexing to bitfield indexing. | |
1831 * And of course, we need to find out if the drive is in the bitmask. | |
1832 * | |
1833 * If we're really unlucky, we can still lose, but only if the user | |
1834 * manages to eject the drive between our call to _getdrives() and | |
1835 * our *calls* to _wgetdcwd. | |
1836 */ | |
1837 if (!((1 << (drivelet - 1)) & _getdrives())) | |
1838 return NULL; | |
771 | 1839 if (XEUNICODE_P) |
1840 cwdext = (Extbyte *) _wgetdcwd (drivelet, NULL, 0); | |
1841 else | |
1842 cwdext = _getdcwd (drivelet, NULL, 0); | |
3648 | 1843 if (cwdext == NULL) return NULL; |
771 | 1844 TSTR_TO_C_STRING_MALLOC (cwdext, cwd); |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1845 xfree (cwdext); |
771 | 1846 return cwd; |
428 | 1847 } |
1848 | |
442 | 1849 |
1850 /*--------------------------------------------------------------------*/ | |
1851 /* Memory-mapped files */ | |
1852 /*--------------------------------------------------------------------*/ | |
1853 | |
428 | 1854 int |
867 | 1855 open_input_file (file_data *p_file, const Ibyte *filename) |
428 | 1856 { |
442 | 1857 /* Synched with FSF 20.6. We fixed some warnings. */ |
428 | 1858 HANDLE file; |
1859 HANDLE file_mapping; | |
771 | 1860 void *file_base; |
428 | 1861 DWORD size, upper_size; |
771 | 1862 Extbyte *fileext; |
428 | 1863 |
2526 | 1864 PATHNAME_CONVERT_OUT (filename, fileext); |
771 | 1865 |
1866 file = qxeCreateFile (fileext, GENERIC_READ, FILE_SHARE_READ, NULL, | |
1867 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |
428 | 1868 if (file == INVALID_HANDLE_VALUE) |
1869 return FALSE; | |
1870 | |
1871 size = GetFileSize (file, &upper_size); | |
771 | 1872 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READONLY, |
1873 0, size, NULL); | |
428 | 1874 if (!file_mapping) |
1875 return FALSE; | |
1876 | |
1877 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size); | |
1878 if (file_base == 0) | |
1879 return FALSE; | |
1880 | |
771 | 1881 p_file->name = filename; |
442 | 1882 p_file->size = size; |
1883 p_file->file = file; | |
1884 p_file->file_mapping = file_mapping; | |
771 | 1885 p_file->file_base = file_base; |
442 | 1886 |
1887 return TRUE; | |
1888 } | |
1889 | |
1890 int | |
867 | 1891 open_output_file (file_data *p_file, const Ibyte *filename, |
771 | 1892 unsigned long size) |
442 | 1893 { |
1894 /* Synched with FSF 20.6. We fixed some warnings. */ | |
1895 HANDLE file; | |
1896 HANDLE file_mapping; | |
771 | 1897 void *file_base; |
1898 Extbyte *fileext; | |
442 | 1899 |
2526 | 1900 PATHNAME_CONVERT_OUT (filename, fileext); |
771 | 1901 |
1902 file = qxeCreateFile (fileext, GENERIC_READ | GENERIC_WRITE, 0, NULL, | |
1903 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); | |
442 | 1904 if (file == INVALID_HANDLE_VALUE) |
1905 return FALSE; | |
1906 | |
771 | 1907 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READWRITE, |
1908 0, size, NULL); | |
442 | 1909 if (!file_mapping) |
1910 return FALSE; | |
1911 | |
1912 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size); | |
1913 if (file_base == NULL) | |
1914 return FALSE; | |
1915 | |
1916 p_file->name = filename; | |
428 | 1917 p_file->size = size; |
1918 p_file->file = file; | |
1919 p_file->file_mapping = file_mapping; | |
771 | 1920 p_file->file_base = file_base; |
428 | 1921 |
1922 return TRUE; | |
1923 } | |
1924 | |
442 | 1925 #if 1 /* !defined(MINGW) */ |
1926 /* Return pointer to section header for section containing the given | |
1927 relative virtual address. */ | |
1928 static IMAGE_SECTION_HEADER * | |
771 | 1929 rva_to_section (DWORD rva, IMAGE_NT_HEADERS *nt_header) |
442 | 1930 { |
1931 /* Synched with FSF 20.6. We added MINGW stuff. */ | |
1932 PIMAGE_SECTION_HEADER section; | |
1933 int i; | |
1934 | |
1935 section = IMAGE_FIRST_SECTION (nt_header); | |
1936 | |
1937 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) | |
1938 { | |
1939 /* Some linkers (eg. the NT SDK linker I believe) swapped the | |
1940 meaning of these two values - or rather, they ignored | |
1941 VirtualSize entirely and always set it to zero. This affects | |
1942 some very old exes (eg. gzip dated Dec 1993). Since | |
1943 mswindows_executable_type relies on this function to work reliably, | |
1944 we need to cope with this. */ | |
1945 DWORD real_size = max (section->SizeOfRawData, | |
1946 section->Misc.VirtualSize); | |
1947 if (rva >= section->VirtualAddress | |
1948 && rva < section->VirtualAddress + real_size) | |
1949 return section; | |
1950 section++; | |
1951 } | |
1952 return NULL; | |
1953 } | |
1954 #endif | |
1955 | |
1956 void | |
867 | 1957 mswindows_executable_type (const Ibyte *filename, int *is_dos_app, |
771 | 1958 int *is_cygnus_app) |
442 | 1959 { |
1960 /* Synched with FSF 20.6. We added MINGW stuff and casts. */ | |
1961 file_data executable; | |
867 | 1962 Ibyte *p; |
442 | 1963 |
1964 /* Default values in case we can't tell for sure. */ | |
1965 *is_dos_app = FALSE; | |
1966 *is_cygnus_app = FALSE; | |
1967 | |
1968 if (!open_input_file (&executable, filename)) | |
1969 return; | |
1970 | |
771 | 1971 p = qxestrrchr (filename, '.'); |
442 | 1972 |
1973 /* We can only identify DOS .com programs from the extension. */ | |
2367 | 1974 if (p && qxestrcasecmp_ascii (p, ".com") == 0) |
442 | 1975 *is_dos_app = TRUE; |
2367 | 1976 else if (p && (qxestrcasecmp_ascii (p, ".bat") == 0 || |
1977 qxestrcasecmp_ascii (p, ".cmd") == 0)) | |
442 | 1978 { |
1979 /* A DOS shell script - it appears that CreateProcess is happy to | |
1980 accept this (somewhat surprisingly); presumably it looks at | |
1981 COMSPEC to determine what executable to actually invoke. | |
1982 Therefore, we have to do the same here as well. */ | |
1983 /* Actually, I think it uses the program association for that | |
1984 extension, which is defined in the registry. */ | |
1985 p = egetenv ("COMSPEC"); | |
1986 if (p) | |
1987 mswindows_executable_type (p, is_dos_app, is_cygnus_app); | |
1988 } | |
1989 else | |
1990 { | |
1991 /* Look for DOS .exe signature - if found, we must also check that | |
1992 it isn't really a 16- or 32-bit Windows exe, since both formats | |
1993 start with a DOS program stub. Note that 16-bit Windows | |
1994 executables use the OS/2 1.x format. */ | |
1995 | |
1996 #if 0 /* defined( MINGW ) */ | |
771 | 1997 /* mingw doesn't have enough headers to detect cygwin |
442 | 1998 apps, just do what we can. */ |
771 | 1999 FILHDR *exe_header; |
442 | 2000 |
771 | 2001 exe_header = (FILHDR *) executable.file_base; |
442 | 2002 if (exe_header->e_magic != DOSMAGIC) |
2003 goto unwind; | |
2004 | |
771 | 2005 if ((char *) exe_header->e_lfanew > (char *) executable.size) |
442 | 2006 { |
2007 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
2008 *is_dos_app = TRUE; | |
2009 } | |
2010 else if (exe_header->nt_signature != NT_SIGNATURE) | |
2011 { | |
2012 *is_dos_app = TRUE; | |
2013 } | |
2014 #else | |
771 | 2015 IMAGE_DOS_HEADER *dos_header; |
2016 IMAGE_NT_HEADERS *nt_header; | |
442 | 2017 |
2018 dos_header = (PIMAGE_DOS_HEADER) executable.file_base; | |
2019 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
2020 goto unwind; | |
2021 | |
771 | 2022 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + |
2023 dos_header->e_lfanew); | |
442 | 2024 |
771 | 2025 if ((char *) nt_header > (char *) dos_header + executable.size) |
442 | 2026 { |
2027 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
2028 *is_dos_app = TRUE; | |
2029 } | |
2030 else if (nt_header->Signature != IMAGE_NT_SIGNATURE && | |
2031 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) | |
2032 { | |
2033 *is_dos_app = TRUE; | |
2034 } | |
2035 else if (nt_header->Signature == IMAGE_NT_SIGNATURE) | |
2036 { | |
2037 /* Look for cygwin.dll in DLL import list. */ | |
2038 IMAGE_DATA_DIRECTORY import_dir = | |
771 | 2039 nt_header->OptionalHeader. |
2040 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; | |
2041 IMAGE_IMPORT_DESCRIPTOR *imports; | |
2042 IMAGE_SECTION_HEADER *section; | |
442 | 2043 |
2044 section = rva_to_section (import_dir.VirtualAddress, nt_header); | |
771 | 2045 imports = |
2046 (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress, | |
2047 section, executable); | |
2048 | |
442 | 2049 for ( ; imports->Name; imports++) |
2050 { | |
771 | 2051 Extbyte *dllname_ext = |
2052 (Extbyte *) RVA_TO_PTR (imports->Name, section, executable); | |
867 | 2053 Ibyte *dllname; |
771 | 2054 |
2055 EXTERNAL_TO_C_STRING (dllname_ext, dllname, Qbinary); | |
442 | 2056 |
2057 /* The exact name of the cygwin dll has changed with | |
2058 various releases, but hopefully this will be reasonably | |
2059 future proof. */ | |
867 | 2060 if (qxestrncasecmp (dllname, (Ibyte *) "cygwin", 6) == 0) |
442 | 2061 { |
2062 *is_cygnus_app = TRUE; | |
2063 break; | |
2064 } | |
2065 } | |
2066 } | |
2067 #endif | |
2068 } | |
2069 | |
2070 unwind: | |
2071 close_file_data (&executable); | |
2072 } | |
2073 | |
428 | 2074 /* Close the system structures associated with the given file. */ |
2075 void | |
2076 close_file_data (file_data *p_file) | |
2077 { | |
611 | 2078 UnmapViewOfFile (p_file->file_base); |
2079 CloseHandle (p_file->file_mapping); | |
2080 CloseHandle (p_file->file); | |
428 | 2081 } |
2082 | |
771 | 2083 |
2084 /* Some miscellaneous functions that are Windows specific, but not GUI | |
2085 specific (ie. are applicable in terminal or batch mode as well). */ | |
2086 | |
4487
866b84b7c97e
Remove interactive specs from #'mswindows-{short,long}-file-name,
Aidan Kehoe <kehoea@parhasard.net>
parents:
3648
diff
changeset
|
2087 DEFUN ("mswindows-short-file-name", Fmswindows_short_file_name, 1, 1, 0, /* |
771 | 2088 Return the short file name version (8.3) of the full path of FILENAME. |
2089 If FILENAME does not exist, return nil. | |
2090 All path elements in FILENAME are converted to their short names. | |
2091 */ | |
2092 (filename)) | |
2093 { | |
4854 | 2094 Extbyte shortname[PATH_MAX_TCHAR]; |
771 | 2095 Extbyte *fileext; |
867 | 2096 Ibyte *shortint; |
771 | 2097 |
2098 CHECK_STRING (filename); | |
2099 | |
2100 /* first expand it. */ | |
2101 filename = Fexpand_file_name (filename, Qnil); | |
2102 | |
2526 | 2103 LISP_PATHNAME_CONVERT_OUT (filename, fileext); |
771 | 2104 /* luckily, this returns the short version of each element in the path. */ |
2105 if (qxeGetShortPathName (fileext, shortname, | |
2106 sizeof (shortname) / XETCHAR_SIZE) == 0) | |
2107 return Qnil; | |
2108 | |
2109 TSTR_TO_C_STRING (shortname, shortint); | |
2110 MSWINDOWS_NORMALIZE_FILENAME (shortint); | |
2111 | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4854
diff
changeset
|
2112 return build_istring (shortint); |
771 | 2113 } |
2114 | |
2115 | |
4487
866b84b7c97e
Remove interactive specs from #'mswindows-{short,long}-file-name,
Aidan Kehoe <kehoea@parhasard.net>
parents:
3648
diff
changeset
|
2116 DEFUN ("mswindows-long-file-name", Fmswindows_long_file_name, 1, 1, 0, /* |
771 | 2117 Return the long file name version of the full path of FILENAME. |
2118 If FILENAME does not exist, return nil. | |
2119 All path elements in FILENAME are converted to their long names. | |
2120 */ | |
2121 (filename)) | |
2122 { | |
867 | 2123 Ibyte *longname, *canon; |
771 | 2124 Lisp_Object ret; |
2125 | |
2126 CHECK_STRING (filename); | |
2127 | |
2128 /* first expand it. */ | |
2129 filename = Fexpand_file_name (filename, Qnil); | |
2130 | |
2131 if (!(longname = mswindows_get_long_filename (XSTRING_DATA (filename)))) | |
2132 return Qnil; | |
2133 | |
2134 canon = mswindows_canonicalize_filename (longname); | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4854
diff
changeset
|
2135 ret = build_istring (canon); |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
2136 xfree (canon); |
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
2137 xfree (longname); |
771 | 2138 return ret; |
2139 } | |
2140 | |
814 | 2141 |
2142 void | |
2143 init_nt (void) | |
2144 { | |
2145 /* Initial preparation for subprocess support: replace our standard | |
2146 handles with non-inheritable versions. | |
2147 | |
2148 #### Do we still need this? This is left over from the old process | |
2149 support. */ | |
2150 { | |
2151 HANDLE parent; | |
2152 HANDLE stdin_save = INVALID_HANDLE_VALUE; | |
2153 HANDLE stdout_save = INVALID_HANDLE_VALUE; | |
2154 HANDLE stderr_save = INVALID_HANDLE_VALUE; | |
2155 | |
2156 parent = GetCurrentProcess (); | |
2157 | |
2158 /* ignore errors when duplicating and closing; typically the | |
2159 handles will be invalid when running as a gui program. */ | |
2160 DuplicateHandle (parent, | |
2161 GetStdHandle (STD_INPUT_HANDLE), | |
2162 parent, | |
2163 &stdin_save, | |
2164 0, | |
2165 FALSE, | |
2166 DUPLICATE_SAME_ACCESS); | |
2167 | |
2168 DuplicateHandle (parent, | |
2169 GetStdHandle (STD_OUTPUT_HANDLE), | |
2170 parent, | |
2171 &stdout_save, | |
2172 0, | |
2173 FALSE, | |
2174 DUPLICATE_SAME_ACCESS); | |
2175 | |
2176 DuplicateHandle (parent, | |
2177 GetStdHandle (STD_ERROR_HANDLE), | |
2178 parent, | |
2179 &stderr_save, | |
2180 0, | |
2181 FALSE, | |
2182 DUPLICATE_SAME_ACCESS); | |
2183 | |
2184 retry_fclose (stdin); | |
2185 retry_fclose (stdout); | |
2186 retry_fclose (stderr); | |
2187 | |
2188 if (stdin_save != INVALID_HANDLE_VALUE) | |
2189 _open_osfhandle ((long) stdin_save, O_TEXT); | |
2190 else | |
2191 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY); | |
2192 _fdopen (0, "r"); | |
2193 | |
2194 if (stdout_save != INVALID_HANDLE_VALUE) | |
2195 _open_osfhandle ((long) stdout_save, O_TEXT); | |
2196 else | |
2197 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); | |
2198 _fdopen (1, "w"); | |
2199 | |
2200 if (stderr_save != INVALID_HANDLE_VALUE) | |
2201 _open_osfhandle ((long) stderr_save, O_TEXT); | |
2202 else | |
2203 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY); | |
2204 _fdopen (2, "w"); | |
2205 } | |
2206 | |
2207 /* determine which drives are fixed, for get_cached_volume_information */ | |
2208 { | |
2209 /* GetDriveType must have trailing backslash. */ | |
867 | 2210 Ibyte drive[] = "A:\\"; |
814 | 2211 |
2212 /* Loop over all possible drive letters */ | |
2213 while (*drive <= 'Z') | |
2214 { | |
2215 Extbyte *driveext; | |
2216 | |
2526 | 2217 PATHNAME_CONVERT_OUT (drive, driveext); |
814 | 2218 |
2219 /* Record if this drive letter refers to a fixed drive. */ | |
2220 fixed_drives[DRIVE_INDEX (*drive)] = | |
2221 (qxeGetDriveType (driveext) == DRIVE_FIXED); | |
2222 | |
2223 (*drive)++; | |
2224 } | |
2225 | |
2226 /* Reset the volume info cache. */ | |
2227 volume_cache = NULL; | |
2228 } | |
2229 } | |
2230 | |
771 | 2231 void |
2232 syms_of_nt (void) | |
2233 { | |
2234 DEFSUBR (Fmswindows_short_file_name); | |
2235 DEFSUBR (Fmswindows_long_file_name); | |
2236 } | |
2237 | |
440 | 2238 void |
2239 vars_of_nt (void) | |
2240 { | |
771 | 2241 DEFVAR_INT ("mswindows-fake-unix-uid", &mswindows_fake_unix_uid /* |
440 | 2242 *Set uid returned by `user-uid' and `user-real-uid'. |
771 | 2243 Under NT and 9x, there are no uids, and even no almighty user called root. |
2244 By setting this variable, you can have any uid of choice. Default is 0. | |
440 | 2245 Changes to this variable take effect immediately. |
2246 */ ); | |
771 | 2247 mswindows_fake_unix_uid = 0; |
2248 | |
2249 DEFVAR_LISP ("mswindows-get-true-file-attributes", &Vmswindows_get_true_file_attributes /* | |
2250 Non-nil means determine accurate link count in file-attributes. | |
2251 This option slows down file-attributes noticeably, so is disabled by | |
2252 default. Note that it is only useful for files on NTFS volumes, | |
2253 where hard links are supported. | |
2254 */ ); | |
2255 Vmswindows_get_true_file_attributes = Qnil; | |
440 | 2256 } |
2257 | |
428 | 2258 /* end of nt.c */ |