comparison src/fileio.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 3d8143fc88e1
children 6c7605dfcf07
comparison
equal deleted inserted replaced
2525:52f00344a629 2526:902d5bd9b75c
21 21
22 /* Synched up with: Mule 2.0, FSF 19.30. */ 22 /* Synched up with: Mule 2.0, FSF 19.30. */
23 /* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> 23 /* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org>
24 (Note: Sync messages from Marc Paquette may indicate 24 (Note: Sync messages from Marc Paquette may indicate
25 incomplete synching, so beware.) */ 25 incomplete synching, so beware.) */
26 /* Some functions synched with FSF 21.0.103. */
26 /* Mule-ized completely except for the #if 0-code including decrypt-string 27 /* Mule-ized completely except for the #if 0-code including decrypt-string
27 and encrypt-string. --ben 7-2-00 */ 28 and encrypt-string. --ben 7-2-00 */
28 /* #if 0-code Mule-ized, 2-22-03. --ben */ 29 /* #if 0-code Mule-ized, 2-22-03. --ben */
29 30
30 31
36 #include "events.h" 37 #include "events.h"
37 #include "file-coding.h" 38 #include "file-coding.h"
38 #include "frame.h" 39 #include "frame.h"
39 #include "insdel.h" 40 #include "insdel.h"
40 #include "lstream.h" 41 #include "lstream.h"
42 #include "profile.h"
41 #include "process.h" 43 #include "process.h"
42 #include "redisplay.h" 44 #include "redisplay.h"
43 #include "sysdep.h" 45 #include "sysdep.h"
44 #include "window-impl.h" 46 #include "window-impl.h"
45 47
126 Lisp_Object Qauto_saving; 128 Lisp_Object Qauto_saving;
127 129
128 Lisp_Object Qcar_less_than_car; 130 Lisp_Object Qcar_less_than_car;
129 131
130 Lisp_Object Qcompute_buffer_file_truename; 132 Lisp_Object Qcompute_buffer_file_truename;
133
134 Lisp_Object QSin_expand_file_name;
131 135
132 EXFUN (Frunning_temacs_p, 0); 136 EXFUN (Frunning_temacs_p, 0);
133 137
134 /* DATA can be anything acceptable to signal_error (). 138 /* DATA can be anything acceptable to signal_error ().
135 */ 139 */
323 CHECK_STRING (result); 327 CHECK_STRING (result);
324 return result; 328 return result;
325 } 329 }
326 330
327 331
332
333 Ibyte *
334 find_end_of_directory_component (const Ibyte *path, Bytecount len)
335 {
336 const Ibyte *p = path + len;
337
338 while (p != path && !IS_DIRECTORY_SEP (p[-1])
339 #ifdef WIN32_FILENAMES
340 /* only recognise drive specifier at the beginning */
341 && !(p[-1] == ':'
342 /* handle the "/:d:foo" and "/:foo" cases correctly */
343 && ((p == path + 2 && !IS_DIRECTORY_SEP (*path))
344 || (p == path + 4 && IS_DIRECTORY_SEP (*path))))
345 #endif
346 ) p--;
347
348 return (Ibyte *) p;
349 }
350
328 DEFUN ("file-name-directory", Ffile_name_directory, 1, 1, 0, /* 351 DEFUN ("file-name-directory", Ffile_name_directory, 1, 1, 0, /*
329 Return the directory component in file name FILENAME. 352 Return the directory component in file name FILENAME.
330 Return nil if FILENAME does not include a directory. 353 Return nil if FILENAME does not include a directory.
331 Otherwise return a directory spec. 354 Otherwise return a directory spec.
332 Given a Unix syntax file name, returns a string ending in slash. 355 Given a Unix syntax file name, returns a string ending in slash.
350 #ifdef FILE_SYSTEM_CASE 373 #ifdef FILE_SYSTEM_CASE
351 filename = FILE_SYSTEM_CASE (filename); 374 filename = FILE_SYSTEM_CASE (filename);
352 #endif 375 #endif
353 beg = XSTRING_DATA (filename); 376 beg = XSTRING_DATA (filename);
354 /* XEmacs: no need to alloca-copy here */ 377 /* XEmacs: no need to alloca-copy here */
355 p = beg + XSTRING_LENGTH (filename); 378 p = find_end_of_directory_component (beg, XSTRING_LENGTH (filename));
356
357 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
358 #ifdef WIN32_FILENAMES
359 /* only recognise drive specifier at the beginning */
360 && !(p[-1] == ':'
361 /* handle the "/:d:foo" and "/:foo" cases correctly */
362 && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
363 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
364 #endif
365 ) p--;
366 379
367 if (p == beg) 380 if (p == beg)
368 return Qnil; 381 return Qnil;
369 #ifdef WIN32_NATIVE 382 #ifdef WIN32_NATIVE
370 /* Expansion of "c:" to drive and default directory. */ 383 /* Expansion of "c:" to drive and default directory. */
520 handler = Ffind_file_name_handler (filename, Qfile_name_as_directory); 533 handler = Ffind_file_name_handler (filename, Qfile_name_as_directory);
521 if (!NILP (handler)) 534 if (!NILP (handler))
522 return call2_check_string (handler, Qfile_name_as_directory, filename); 535 return call2_check_string (handler, Qfile_name_as_directory, filename);
523 536
524 buf = alloca_ibytes (XSTRING_LENGTH (filename) + 10); 537 buf = alloca_ibytes (XSTRING_LENGTH (filename) + 10);
525 return build_intstring (file_name_as_directory (buf, XSTRING_DATA (filename))); 538 file_name_as_directory (buf, XSTRING_DATA (filename));
539 if (qxestrcmp (buf, XSTRING_DATA (filename)))
540 return build_intstring (buf);
541 else
542 return filename;
526 } 543 }
527 544
528 /* 545 /*
529 * Convert from directory name to filename. 546 * Convert from directory name to filename.
530 * On UNIX, it's simple: just make sure there isn't a terminating / 547 * On UNIX, it's simple: just make sure there isn't a terminating /
733 struct passwd *pw; 750 struct passwd *pw;
734 #endif 751 #endif
735 int length; 752 int length;
736 Lisp_Object handler = Qnil; 753 Lisp_Object handler = Qnil;
737 struct gcpro gcpro1, gcpro2, gcpro3; 754 struct gcpro gcpro1, gcpro2, gcpro3;
755 PROFILE_DECLARE ();
756
757 PROFILE_RECORD_ENTERING_SECTION (QSin_expand_file_name);
738 758
739 /* both of these get set below */ 759 /* both of these get set below */
740 GCPRO3 (name, default_directory, handler); 760 GCPRO3 (name, default_directory, handler);
741 761
742 CHECK_STRING (name); 762 CHECK_STRING (name);
743 763
744 /* If the file name has special constructs in it, 764 /* If the file name has special constructs in it,
745 call the corresponding file handler. */ 765 call the corresponding file handler. */
746 handler = Ffind_file_name_handler (name, Qexpand_file_name); 766 handler = Ffind_file_name_handler (name, Qexpand_file_name);
747 if (!NILP (handler)) 767 if (!NILP (handler))
748 RETURN_UNGCPRO (call3_check_string (handler, Qexpand_file_name, 768 RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
749 name, default_directory)); 769 call3_check_string
770 (handler, Qexpand_file_name,
771 name, default_directory));
750 772
751 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ 773 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
752 if (NILP (default_directory)) 774 if (NILP (default_directory))
753 default_directory = current_buffer->directory; 775 default_directory = current_buffer->directory;
754 if (! STRINGP (default_directory)) 776 if (! STRINGP (default_directory))
760 782
761 if (!NILP (default_directory)) 783 if (!NILP (default_directory))
762 { 784 {
763 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); 785 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
764 if (!NILP (handler)) 786 if (!NILP (handler))
765 RETURN_UNGCPRO (call3 (handler, Qexpand_file_name, 787 RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
766 name, default_directory)); 788 call3 (handler, Qexpand_file_name,
789 name, default_directory));
767 } 790 }
768 791
769 o = XSTRING_DATA (default_directory); 792 o = XSTRING_DATA (default_directory);
770 793
771 /* Make sure DEFAULT_DIRECTORY is properly expanded. 794 /* Make sure DEFAULT_DIRECTORY is properly expanded.
925 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive); 948 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive);
926 XSTRING_DATA (name)[1] = ':'; 949 XSTRING_DATA (name)[1] = ':';
927 } 950 }
928 } 951 }
929 xfree (newnm, Ibyte *); 952 xfree (newnm, Ibyte *);
930 RETURN_UNGCPRO (name); 953 RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, name);
931 } 954 }
932 #endif /* WIN32_FILENAMES */ 955 #endif /* WIN32_FILENAMES */
933 #ifndef WIN32_NATIVE 956 #ifndef WIN32_NATIVE
934 if (nm == XSTRING_DATA (name)) 957 if (nm == XSTRING_DATA (name))
935 RETURN_UNGCPRO (name); 958 RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, name);
936 RETURN_UNGCPRO (build_intstring (nm)); 959 RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
960 build_intstring (nm));
937 #endif /* not WIN32_NATIVE */ 961 #endif /* not WIN32_NATIVE */
938 } 962 }
939 } 963 }
940 964
941 /* At this point, nm might or might not be an absolute file name. We 965 /* At this point, nm might or might not be an absolute file name. We
1299 { 1323 {
1300 Ibyte *newtarget = mswindows_canonicalize_filename (target); 1324 Ibyte *newtarget = mswindows_canonicalize_filename (target);
1301 Lisp_Object result = build_intstring (newtarget); 1325 Lisp_Object result = build_intstring (newtarget);
1302 xfree (newtarget, Ibyte *); 1326 xfree (newtarget, Ibyte *);
1303 1327
1304 RETURN_UNGCPRO (result); 1328 RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, result);
1305 } 1329 }
1306 #else /* not WIN32_FILENAMES */ 1330 #else /* not WIN32_FILENAMES */
1307 RETURN_UNGCPRO (make_string (target, o - target)); 1331 RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
1332 make_string (target, o - target));
1308 #endif /* not WIN32_FILENAMES */ 1333 #endif /* not WIN32_FILENAMES */
1309 } 1334 }
1310 1335
1311 DEFUN ("file-truename", Ffile_truename, 1, 2, 0, /* 1336 DEFUN ("file-truename", Ffile_truename, 1, 2, 0, /*
1312 Return the canonical name of FILENAME. 1337 Return the canonical name of FILENAME.
1358 } 1383 }
1359 #endif 1384 #endif
1360 p = path; 1385 p = path;
1361 1386
1362 /* Try doing it all at once. */ 1387 /* Try doing it all at once. */
1363 if (!qxe_realpath (path, resolved_path)) 1388 if (!qxe_realpath (path, resolved_path, 0))
1364 { 1389 {
1365 /* Didn't resolve it -- have to do it one component at a time. */ 1390 /* Didn't resolve it -- have to do it one component at a time. */
1366 /* "realpath" is a typically useless, stupid un*x piece of crap. 1391 /* "realpath" is a typically useless, stupid un*x piece of crap.
1367 It claims to return a useful value in the "error" case, but since 1392 It claims to return a useful value in the "error" case, but since
1368 there is no indication provided of how far along the pathname 1393 there is no indication provided of how far along the pathname
1377 returns a null pointer and sets errno to indicate the 1402 returns a null pointer and sets errno to indicate the
1378 error, and the contents of the buffer pointed to by 1403 error, and the contents of the buffer pointed to by
1379 resolved_name are undefined." 1404 resolved_name are undefined."
1380 1405
1381 Since we depend on undocumented semantics of various system 1406 Since we depend on undocumented semantics of various system
1382 realpath()s, we just use our own version in realpath.c. */ 1407 realpath()s, we just use our own version in realpath.c.
1408
1409 Note also that our own version differs in its semantics from any
1410 standard version, since it accepts and returns internal-format
1411 text, not external-format. */
1383 for (;;) 1412 for (;;)
1384 { 1413 {
1385 Ibyte *pos; 1414 Ibyte *pos;
1386 1415
1387 #ifdef WIN32_FILENAMES 1416 #ifdef WIN32_FILENAMES
1400 break; 1429 break;
1401 } 1430 }
1402 if (p != pos) 1431 if (p != pos)
1403 p = 0; 1432 p = 0;
1404 1433
1405 if (qxe_realpath (path, resolved_path)) 1434 if (qxe_realpath (path, resolved_path, 0))
1406 { 1435 {
1407 if (p) 1436 if (p)
1408 *p = DIRECTORY_SEP; 1437 *p = DIRECTORY_SEP;
1409 else 1438 else
1410 break; 1439 break;
2336 call the corresponding file handler. */ 2365 call the corresponding file handler. */
2337 handler = Ffind_file_name_handler (abspath, Qfile_readable_p); 2366 handler = Ffind_file_name_handler (abspath, Qfile_readable_p);
2338 if (!NILP (handler)) 2367 if (!NILP (handler))
2339 RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath)); 2368 RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath));
2340 2369
2341 #if defined(WIN32_FILENAMES) 2370 #if defined (WIN32_FILENAMES)
2342 /* Under MS-DOS and Windows, open does not work for directories. */ 2371 /* Under MS-DOS and Windows, open does not work for directories. */
2343 UNGCPRO; 2372 UNGCPRO;
2344 if (qxe_access (XSTRING_DATA (abspath), 0) == 0) 2373 if (qxe_access (XSTRING_DATA (abspath), 0) == 0)
2345 return Qt; 2374 return Qt;
2346 else 2375 else
2441 return Qnil; 2470 return Qnil;
2442 } 2471 }
2443 val = make_string (buf, valsize); 2472 val = make_string (buf, valsize);
2444 xfree (buf, Ibyte *); 2473 xfree (buf, Ibyte *);
2445 return val; 2474 return val;
2446 #else /* not HAVE_READLINK */ 2475 #elif defined (WIN32_NATIVE)
2476 if (mswindows_shortcuts_are_symlinks)
2477 {
2478 /* We want to resolve the directory component and leave the rest
2479 alone. */
2480 Ibyte *path = XSTRING_DATA (filename);
2481 Ibyte *dirend =
2482 find_end_of_directory_component (path, XSTRING_LENGTH (filename));
2483 Ibyte *fname;
2484 DECLARE_EISTRING (dir);
2485
2486 if (dirend != path)
2487 {
2488 Ibyte *resdir;
2489 DECLARE_EISTRING (resname);
2490
2491 eicpy_raw (dir, path, dirend - path);
2492 PATHNAME_RESOLVE_LINKS (eidata (dir), resdir);
2493 eicpy_rawz (resname, resdir);
2494 eicat_rawz (resname, dirend);
2495 path = eidata (resname);
2496 }
2497
2498 fname = mswindows_read_link (path);
2499 if (!fname)
2500 return Qnil;
2501 {
2502 Lisp_Object val = build_intstring (fname);
2503 xfree (fname, Ibyte *);
2504 return val;
2505 }
2506 }
2447 return Qnil; 2507 return Qnil;
2448 #endif /* not HAVE_READLINK */ 2508 #else
2509 return Qnil;
2510 #endif
2449 } 2511 }
2450 2512
2451 DEFUN ("file-directory-p", Ffile_directory_p, 1, 1, 0, /* 2513 DEFUN ("file-directory-p", Ffile_directory_p, 1, 1, 0, /*
2452 Return t if file FILENAME is the name of a directory as a file. 2514 Return t if file FILENAME is the name of a directory as a file.
2453 A directory name spec may be given instead; then the value is t 2515 A directory name spec may be given instead; then the value is t
2497 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); 2559 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p);
2498 if (!NILP (handler)) 2560 if (!NILP (handler))
2499 return call2 (handler, Qfile_accessible_directory_p, 2561 return call2 (handler, Qfile_accessible_directory_p,
2500 filename); 2562 filename);
2501 2563
2502 #if !defined(WIN32_NATIVE) 2564 #if !defined (WIN32_NATIVE)
2503 if (NILP (Ffile_directory_p (filename))) 2565 if (NILP (Ffile_directory_p (filename)))
2504 return (Qnil); 2566 return (Qnil);
2505 else 2567 else
2506 return Ffile_executable_p (filename); 2568 return Ffile_executable_p (filename);
2507 #else 2569 #else
4298 } 4360 }
4299 4361
4300 void 4362 void
4301 vars_of_fileio (void) 4363 vars_of_fileio (void)
4302 { 4364 {
4365 QSin_expand_file_name =
4366 build_msg_string ("(in expand-file-name)");
4367 staticpro (&QSin_expand_file_name);
4368
4303 DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format /* 4369 DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format /*
4304 *Format in which to write auto-save files. 4370 *Format in which to write auto-save files.
4305 Should be a list of symbols naming formats that are defined in `format-alist'. 4371 Should be a list of symbols naming formats that are defined in `format-alist'.
4306 If it is t, which is the default, auto-save files are written in the 4372 If it is t, which is the default, auto-save files are written in the
4307 same format as a regular save would use. 4373 same format as a regular save would use.