diff options
| author | Geoff Voelker | 1998-04-23 23:41:12 +0000 |
|---|---|---|
| committer | Geoff Voelker | 1998-04-23 23:41:12 +0000 |
| commit | 16bb7578f27c14e3668ad5e978d7f871b0f0ff5d (patch) | |
| tree | 9d0ec3977105dc854c590089c73bcfe397fc425e /src | |
| parent | 9b69357efcd5ed8bd1dd7b55f164fba326bef09a (diff) | |
| download | emacs-16bb7578f27c14e3668ad5e978d7f871b0f0ff5d.tar.gz emacs-16bb7578f27c14e3668ad5e978d7f871b0f0ff5d.zip | |
(fstat, utime): New functions; these are provided in
conjunction with stat to make handling of file timestamps
consistent.
(convert_from_time_t): Fix calculation of low-order bits.
(sys_unlink): Allow read-only files to be unlinked as on Unix.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32.c | 149 |
1 files changed, 144 insertions, 5 deletions
| @@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. | |||
| 31 | #include <ctype.h> | 31 | #include <ctype.h> |
| 32 | #include <signal.h> | 32 | #include <signal.h> |
| 33 | #include <sys/time.h> | 33 | #include <sys/time.h> |
| 34 | #include <sys/utime.h> | ||
| 34 | 35 | ||
| 35 | /* must include CRT headers *before* config.h */ | 36 | /* must include CRT headers *before* config.h */ |
| 36 | #include "config.h" | 37 | #include "config.h" |
| @@ -1501,7 +1502,11 @@ sys_rmdir (const char * path) | |||
| 1501 | int | 1502 | int |
| 1502 | sys_unlink (const char * path) | 1503 | sys_unlink (const char * path) |
| 1503 | { | 1504 | { |
| 1504 | return _unlink (map_w32_filename (path, NULL)); | 1505 | path = map_w32_filename (path, NULL); |
| 1506 | |||
| 1507 | /* On Unix, unlink works without write permission. */ | ||
| 1508 | _chmod (path, 0666); | ||
| 1509 | return _unlink (path); | ||
| 1505 | } | 1510 | } |
| 1506 | 1511 | ||
| 1507 | static FILETIME utc_base_ft; | 1512 | static FILETIME utc_base_ft; |
| @@ -1540,8 +1545,6 @@ convert_time (FILETIME ft) | |||
| 1540 | return (time_t) (ret * 1e-7); | 1545 | return (time_t) (ret * 1e-7); |
| 1541 | } | 1546 | } |
| 1542 | 1547 | ||
| 1543 | #if 0 | ||
| 1544 | /* in case we ever have need of this */ | ||
| 1545 | void | 1548 | void |
| 1546 | convert_from_time_t (time_t time, FILETIME * pft) | 1549 | convert_from_time_t (time_t time, FILETIME * pft) |
| 1547 | { | 1550 | { |
| @@ -1569,9 +1572,8 @@ convert_from_time_t (time_t time, FILETIME * pft) | |||
| 1569 | /* time in 100ns units since 1-Jan-1601 */ | 1572 | /* time in 100ns units since 1-Jan-1601 */ |
| 1570 | tmp = (long double) time * 1e7 + utc_base; | 1573 | tmp = (long double) time * 1e7 + utc_base; |
| 1571 | pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024)); | 1574 | pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024)); |
| 1572 | pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime); | 1575 | pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime); |
| 1573 | } | 1576 | } |
| 1574 | #endif | ||
| 1575 | 1577 | ||
| 1576 | #if 0 | 1578 | #if 0 |
| 1577 | /* No reason to keep this; faking inode values either by hashing or even | 1579 | /* No reason to keep this; faking inode values either by hashing or even |
| @@ -1811,6 +1813,143 @@ stat (const char * path, struct stat * buf) | |||
| 1811 | return 0; | 1813 | return 0; |
| 1812 | } | 1814 | } |
| 1813 | 1815 | ||
| 1816 | /* Provide fstat and utime as well as stat for consistent handling of | ||
| 1817 | file timestamps. */ | ||
| 1818 | int | ||
| 1819 | fstat (int desc, struct stat * buf) | ||
| 1820 | { | ||
| 1821 | HANDLE fh = (HANDLE) _get_osfhandle (desc); | ||
| 1822 | BY_HANDLE_FILE_INFORMATION info; | ||
| 1823 | DWORD fake_inode; | ||
| 1824 | int permission; | ||
| 1825 | |||
| 1826 | switch (GetFileType (fh) & ~FILE_TYPE_REMOTE) | ||
| 1827 | { | ||
| 1828 | case FILE_TYPE_DISK: | ||
| 1829 | buf->st_mode = _S_IFREG; | ||
| 1830 | if (!GetFileInformationByHandle (fh, &info)) | ||
| 1831 | { | ||
| 1832 | errno = EACCES; | ||
| 1833 | return -1; | ||
| 1834 | } | ||
| 1835 | break; | ||
| 1836 | case FILE_TYPE_PIPE: | ||
| 1837 | buf->st_mode = _S_IFIFO; | ||
| 1838 | goto non_disk; | ||
| 1839 | case FILE_TYPE_CHAR: | ||
| 1840 | case FILE_TYPE_UNKNOWN: | ||
| 1841 | default: | ||
| 1842 | buf->st_mode = _S_IFCHR; | ||
| 1843 | non_disk: | ||
| 1844 | memset (&info, 0, sizeof (info)); | ||
| 1845 | info.dwFileAttributes = 0; | ||
| 1846 | info.ftCreationTime = utc_base_ft; | ||
| 1847 | info.ftLastAccessTime = utc_base_ft; | ||
| 1848 | info.ftLastWriteTime = utc_base_ft; | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | ||
| 1852 | { | ||
| 1853 | buf->st_mode = _S_IFDIR; | ||
| 1854 | buf->st_nlink = 2; /* doesn't really matter */ | ||
| 1855 | fake_inode = 0; /* this doesn't either I think */ | ||
| 1856 | } | ||
| 1857 | else | ||
| 1858 | { | ||
| 1859 | buf->st_nlink = info.nNumberOfLinks; | ||
| 1860 | /* Might as well use file index to fake inode values, but this | ||
| 1861 | is not guaranteed to be unique unless we keep a handle open | ||
| 1862 | all the time (even then there are situations where it is | ||
| 1863 | not unique). Reputedly, there are at most 48 bits of info | ||
| 1864 | (on NTFS, presumably less on FAT). */ | ||
| 1865 | fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh; | ||
| 1866 | } | ||
| 1867 | |||
| 1868 | /* MSVC defines _ino_t to be short; other libc's might not. */ | ||
| 1869 | if (sizeof (buf->st_ino) == 2) | ||
| 1870 | buf->st_ino = fake_inode ^ (fake_inode >> 16); | ||
| 1871 | else | ||
| 1872 | buf->st_ino = fake_inode; | ||
| 1873 | |||
| 1874 | /* consider files to belong to current user */ | ||
| 1875 | buf->st_uid = 0; | ||
| 1876 | buf->st_gid = 0; | ||
| 1877 | |||
| 1878 | buf->st_dev = info.dwVolumeSerialNumber; | ||
| 1879 | buf->st_rdev = info.dwVolumeSerialNumber; | ||
| 1880 | |||
| 1881 | buf->st_size = info.nFileSizeLow; | ||
| 1882 | |||
| 1883 | /* Convert timestamps to Unix format. */ | ||
| 1884 | buf->st_mtime = convert_time (info.ftLastWriteTime); | ||
| 1885 | buf->st_atime = convert_time (info.ftLastAccessTime); | ||
| 1886 | if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; | ||
| 1887 | buf->st_ctime = convert_time (info.ftCreationTime); | ||
| 1888 | if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; | ||
| 1889 | |||
| 1890 | /* determine rwx permissions */ | ||
| 1891 | if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) | ||
| 1892 | permission = _S_IREAD; | ||
| 1893 | else | ||
| 1894 | permission = _S_IREAD | _S_IWRITE; | ||
| 1895 | |||
| 1896 | if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | ||
| 1897 | permission |= _S_IEXEC; | ||
| 1898 | else | ||
| 1899 | { | ||
| 1900 | #if 0 /* no way of knowing the filename */ | ||
| 1901 | char * p = strrchr (name, '.'); | ||
| 1902 | if (p != NULL && | ||
| 1903 | (stricmp (p, ".exe") == 0 || | ||
| 1904 | stricmp (p, ".com") == 0 || | ||
| 1905 | stricmp (p, ".bat") == 0 || | ||
| 1906 | stricmp (p, ".cmd") == 0)) | ||
| 1907 | permission |= _S_IEXEC; | ||
| 1908 | #endif | ||
| 1909 | } | ||
| 1910 | |||
| 1911 | buf->st_mode |= permission | (permission >> 3) | (permission >> 6); | ||
| 1912 | |||
| 1913 | return 0; | ||
| 1914 | } | ||
| 1915 | |||
| 1916 | int | ||
| 1917 | utime (const char *name, struct utimbuf *times) | ||
| 1918 | { | ||
| 1919 | struct utimbuf deftime; | ||
| 1920 | HANDLE fh; | ||
| 1921 | FILETIME mtime; | ||
| 1922 | FILETIME atime; | ||
| 1923 | |||
| 1924 | if (times == NULL) | ||
| 1925 | { | ||
| 1926 | deftime.modtime = deftime.actime = time (NULL); | ||
| 1927 | times = &deftime; | ||
| 1928 | } | ||
| 1929 | |||
| 1930 | /* Need write access to set times. */ | ||
| 1931 | fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
| 1932 | 0, OPEN_EXISTING, 0, NULL); | ||
| 1933 | if (fh) | ||
| 1934 | { | ||
| 1935 | convert_from_time_t (times->actime, &atime); | ||
| 1936 | convert_from_time_t (times->modtime, &mtime); | ||
| 1937 | if (!SetFileTime (fh, NULL, &atime, &mtime)) | ||
| 1938 | { | ||
| 1939 | CloseHandle (fh); | ||
| 1940 | errno = EACCES; | ||
| 1941 | return -1; | ||
| 1942 | } | ||
| 1943 | CloseHandle (fh); | ||
| 1944 | } | ||
| 1945 | else | ||
| 1946 | { | ||
| 1947 | errno = EINVAL; | ||
| 1948 | return -1; | ||
| 1949 | } | ||
| 1950 | return 0; | ||
| 1951 | } | ||
| 1952 | |||
| 1814 | #ifdef HAVE_SOCKETS | 1953 | #ifdef HAVE_SOCKETS |
| 1815 | 1954 | ||
| 1816 | /* Wrappers for winsock functions to map between our file descriptors | 1955 | /* Wrappers for winsock functions to map between our file descriptors |