aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGeoff Voelker1998-04-23 23:41:12 +0000
committerGeoff Voelker1998-04-23 23:41:12 +0000
commit16bb7578f27c14e3668ad5e978d7f871b0f0ff5d (patch)
tree9d0ec3977105dc854c590089c73bcfe397fc425e /src
parent9b69357efcd5ed8bd1dd7b55f164fba326bef09a (diff)
downloademacs-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.c149
1 files changed, 144 insertions, 5 deletions
diff --git a/src/w32.c b/src/w32.c
index 6008afe0255..2cdccbe389a 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -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)
1501int 1502int
1502sys_unlink (const char * path) 1503sys_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
1507static FILETIME utc_base_ft; 1512static 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 */
1545void 1548void
1546convert_from_time_t (time_t time, FILETIME * pft) 1549convert_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. */
1818int
1819fstat (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
1916int
1917utime (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