Mercurial > emacs
comparison src/w32.c @ 22363:d00f146c3e9d
#include sys/file.h
(sys_access): Provide our own implementation which recognizes D_OK.
(is_exec): New function.
(stat): Use it.
(init_environment): Set TMPDIR to an existing directory.
Abort if none of the usual places is available.
(sys_rename): On Windows 95, choose a temp name that
includes the original file's base name and use an explicit loop
rather than calling mktemp. Only attempt to unlink the newname if
the rename fails, rather than second-guessing whether the old and
new names refer to the same file.
author | Karl Heuer <kwzh@gnu.org> |
---|---|
date | Fri, 05 Jun 1998 16:08:32 +0000 |
parents | 83928cc3329e |
children | 921311b43bf4 |
comparison
equal
deleted
inserted
replaced
22362:e845baca3407 | 22363:d00f146c3e9d |
---|---|
28 #include <io.h> | 28 #include <io.h> |
29 #include <errno.h> | 29 #include <errno.h> |
30 #include <fcntl.h> | 30 #include <fcntl.h> |
31 #include <ctype.h> | 31 #include <ctype.h> |
32 #include <signal.h> | 32 #include <signal.h> |
33 #include <sys/file.h> | |
33 #include <sys/time.h> | 34 #include <sys/time.h> |
34 #include <sys/utime.h> | 35 #include <sys/utime.h> |
35 | 36 |
36 /* must include CRT headers *before* config.h */ | 37 /* must include CRT headers *before* config.h */ |
37 #include "config.h" | 38 #include "config.h" |
625 extern Lisp_Object Vsystem_configuration; | 626 extern Lisp_Object Vsystem_configuration; |
626 | 627 |
627 void | 628 void |
628 init_environment () | 629 init_environment () |
629 { | 630 { |
631 int len; | |
632 static const char * const tempdirs[] = { | |
633 "$TMPDIR", "$TEMP", "$TMP", "c:/" | |
634 }; | |
635 int i; | |
636 const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]); | |
637 | |
638 /* Make sure they have a usable $TMPDIR. Many Emacs functions use | |
639 temporary files and assume "/tmp" if $TMPDIR is unset, which | |
640 will break on DOS/Windows. Refuse to work if we cannot find | |
641 a directory, not even "c:/", usable for that purpose. */ | |
642 for (i = 0; i < imax ; i++) | |
643 { | |
644 const char *tmp = tempdirs[i]; | |
645 | |
646 if (*tmp == '$') | |
647 tmp = getenv (tmp + 1); | |
648 /* Note that `access' can lie to us if the directory resides on a | |
649 read-only filesystem, like CD-ROM or a write-protected floppy. | |
650 The only way to be really sure is to actually create a file and | |
651 see if it succeeds. But I think that's too much to ask. */ | |
652 if (tmp && access (tmp, D_OK) == 0) | |
653 { | |
654 char * var = alloca (strlen (tmp) + 8); | |
655 sprintf (var, "TMPDIR=%s", tmp); | |
656 putenv (var); | |
657 break; | |
658 } | |
659 } | |
660 if (i >= imax) | |
661 cmd_error_internal | |
662 (Fcons (Qerror, | |
663 Fcons (build_string ("no usable temporary directories found!!"), | |
664 Qnil)), | |
665 "While setting TMPDIR: "); | |
666 | |
630 /* Check for environment variables and use registry if they don't exist */ | 667 /* Check for environment variables and use registry if they don't exist */ |
631 { | 668 { |
632 int i; | 669 int i; |
633 LPBYTE lpval; | 670 LPBYTE lpval; |
634 DWORD dwType; | 671 DWORD dwType; |
1133 *pPath = shortname + (path - save_name); | 1170 *pPath = shortname + (path - save_name); |
1134 | 1171 |
1135 return shortname; | 1172 return shortname; |
1136 } | 1173 } |
1137 | 1174 |
1175 static int | |
1176 is_exec (const char * name) | |
1177 { | |
1178 char * p = strrchr (name, '.'); | |
1179 return | |
1180 (p != NULL | |
1181 && (stricmp (p, ".exe") == 0 || | |
1182 stricmp (p, ".com") == 0 || | |
1183 stricmp (p, ".bat") == 0 || | |
1184 stricmp (p, ".cmd") == 0)); | |
1185 } | |
1186 | |
1138 /* Emulate the Unix directory procedures opendir, closedir, | 1187 /* Emulate the Unix directory procedures opendir, closedir, |
1139 and readdir. We can't use the procedures supplied in sysdep.c, | 1188 and readdir. We can't use the procedures supplied in sysdep.c, |
1140 so we provide them here. */ | 1189 so we provide them here. */ |
1141 | 1190 |
1142 struct direct dir_static; /* simulated directory contents */ | 1191 struct direct dir_static; /* simulated directory contents */ |
1238 long file names. */ | 1287 long file names. */ |
1239 | 1288 |
1240 int | 1289 int |
1241 sys_access (const char * path, int mode) | 1290 sys_access (const char * path, int mode) |
1242 { | 1291 { |
1243 return _access (map_w32_filename (path, NULL), mode); | 1292 DWORD attributes; |
1293 | |
1294 /* MSVC implementation doesn't recognize D_OK. */ | |
1295 path = map_w32_filename (path, NULL); | |
1296 if ((attributes = GetFileAttributes (path)) == -1) | |
1297 { | |
1298 /* Should try mapping GetLastError to errno; for now just indicate | |
1299 that path doesn't exist. */ | |
1300 errno = EACCES; | |
1301 return -1; | |
1302 } | |
1303 if ((mode & X_OK) != 0 && !is_exec (path)) | |
1304 { | |
1305 errno = EACCES; | |
1306 return -1; | |
1307 } | |
1308 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0) | |
1309 { | |
1310 errno = EACCES; | |
1311 return -1; | |
1312 } | |
1313 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) | |
1314 { | |
1315 errno = EACCES; | |
1316 return -1; | |
1317 } | |
1318 return 0; | |
1244 } | 1319 } |
1245 | 1320 |
1246 int | 1321 int |
1247 sys_chdir (const char * path) | 1322 sys_chdir (const char * path) |
1248 { | 1323 { |
1442 } | 1517 } |
1443 | 1518 |
1444 int | 1519 int |
1445 sys_rename (const char * oldname, const char * newname) | 1520 sys_rename (const char * oldname, const char * newname) |
1446 { | 1521 { |
1522 int result; | |
1447 char temp[MAX_PATH]; | 1523 char temp[MAX_PATH]; |
1448 DWORD attr; | |
1449 int result; | |
1450 | 1524 |
1451 /* MoveFile on Windows 95 doesn't correctly change the short file name | 1525 /* MoveFile on Windows 95 doesn't correctly change the short file name |
1452 alias in a number of circumstances (it is not easy to predict when | 1526 alias in a number of circumstances (it is not easy to predict when |
1453 just by looking at oldname and newname, unfortunately). In these | 1527 just by looking at oldname and newname, unfortunately). In these |
1454 cases, renaming through a temporary name avoids the problem. | 1528 cases, renaming through a temporary name avoids the problem. |
1463 | 1537 |
1464 strcpy (temp, map_w32_filename (oldname, NULL)); | 1538 strcpy (temp, map_w32_filename (oldname, NULL)); |
1465 | 1539 |
1466 if (os_subtype == OS_WIN95) | 1540 if (os_subtype == OS_WIN95) |
1467 { | 1541 { |
1542 char * o; | |
1468 char * p; | 1543 char * p; |
1544 int i = 0; | |
1545 | |
1546 oldname = map_w32_filename (oldname, NULL); | |
1547 if (o = strrchr (oldname, '\\')) | |
1548 o++; | |
1549 else | |
1550 o = (char *) oldname; | |
1469 | 1551 |
1470 if (p = strrchr (temp, '\\')) | 1552 if (p = strrchr (temp, '\\')) |
1471 p++; | 1553 p++; |
1472 else | 1554 else |
1473 p = temp; | 1555 p = temp; |
1474 /* Force temp name to require a manufactured 8.3 alias - this | 1556 |
1475 seems to make the second rename work properly. */ | 1557 do |
1476 strcpy (p, "_rename_temp.XXXXXX"); | 1558 { |
1477 sys_mktemp (temp); | 1559 /* Force temp name to require a manufactured 8.3 alias - this |
1478 if (rename (map_w32_filename (oldname, NULL), temp) < 0) | 1560 seems to make the second rename work properly. */ |
1561 sprintf (p, ".%s.%u", o, i); | |
1562 i++; | |
1563 } | |
1564 /* This loop must surely terminate! */ | |
1565 while (rename (oldname, temp) < 0 && errno == EEXIST); | |
1566 if (errno != EEXIST) | |
1479 return -1; | 1567 return -1; |
1480 } | 1568 } |
1481 | 1569 |
1482 /* Emulate Unix behaviour - newname is deleted if it already exists | 1570 /* Emulate Unix behaviour - newname is deleted if it already exists |
1483 (at least if it is a file; don't do this for directories). | 1571 (at least if it is a file; don't do this for directories). |
1484 However, don't do this if we are just changing the case of the file | 1572 |
1485 name - we will end up deleting the file we are trying to rename! */ | 1573 Since we mustn't do this if we are just changing the case of the |
1574 file name (we would end up deleting the file we are trying to | |
1575 rename!), we let rename detect if the destination file already | |
1576 exists - that way we avoid the possible pitfalls of trying to | |
1577 determine ourselves whether two names really refer to the same | |
1578 file, which is not always possible in the general case. (Consider | |
1579 all the permutations of shared or subst'd drives, etc.) */ | |
1580 | |
1486 newname = map_w32_filename (newname, NULL); | 1581 newname = map_w32_filename (newname, NULL); |
1487 | |
1488 /* Suggested by Pekka Pirila <pekka.pirila@vtt.fi>: stricmp does not | |
1489 handle accented characters correctly, so comparing filenames will | |
1490 accidentally delete these files. Instead, do the rename first; | |
1491 newname will not be deleted if successful or if errno == EACCES. | |
1492 In this case, delete the file explicitly. */ | |
1493 result = rename (temp, newname); | 1582 result = rename (temp, newname); |
1494 if (result < 0 && errno == EACCES | 1583 |
1495 && (attr = GetFileAttributes (newname)) != -1 | 1584 if (result < 0 |
1496 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) | 1585 && errno == EEXIST |
1497 { | 1586 && _chmod (newname, 0666) == 0 |
1498 _chmod (newname, 0666); | 1587 && _unlink (newname) == 0) |
1499 _unlink (newname); | 1588 result = rename (temp, newname); |
1500 } | |
1501 | 1589 |
1502 return result; | 1590 return result; |
1503 } | 1591 } |
1504 | 1592 |
1505 int | 1593 int |
1811 else | 1899 else |
1812 permission = _S_IREAD | _S_IWRITE; | 1900 permission = _S_IREAD | _S_IWRITE; |
1813 | 1901 |
1814 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | 1902 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
1815 permission |= _S_IEXEC; | 1903 permission |= _S_IEXEC; |
1816 else | 1904 else if (is_exec (name)) |
1817 { | 1905 permission |= _S_IEXEC; |
1818 char * p = strrchr (name, '.'); | |
1819 if (p != NULL | |
1820 && (stricmp (p, ".exe") == 0 || | |
1821 stricmp (p, ".com") == 0 || | |
1822 stricmp (p, ".bat") == 0 || | |
1823 stricmp (p, ".cmd") == 0)) | |
1824 permission |= _S_IEXEC; | |
1825 } | |
1826 | 1906 |
1827 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); | 1907 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); |
1828 | 1908 |
1829 return 0; | 1909 return 0; |
1830 } | 1910 } |