comparison src/nt.c @ 290:c9fe270a4101 r21-0b43

Import from CVS: tag r21-0b43
author cvs
date Mon, 13 Aug 2007 10:36:47 +0200
parents e11d67e05968
children 70ad99077275
comparison
equal deleted inserted replaced
289:6e6992ccc4b6 290:c9fe270a4101
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ 22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */
23 23
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ 24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ 25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
26 26
27 #include <config.h>
28
29 #undef signal
30 #define getwd _getwd
31 #include "lisp.h"
32 #undef getwd
33
34 #include "systime.h"
35 #include "syssignal.h"
36 #include "sysproc.h"
37
38 #include <ctype.h>
39 #include <direct.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <io.h>
43 #include <pwd.h>
44 #include <signal.h>
27 #include <stddef.h> /* for offsetof */ 45 #include <stddef.h> /* for offsetof */
28 #include <string.h> 46 #include <string.h>
29 #include <stdlib.h> 47 #include <stdlib.h>
30 #include <stdio.h> 48 #include <stdio.h>
31 #include <io.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <ctype.h>
35 #include <signal.h>
36 #include <direct.h>
37
38 /* must include CRT headers *before* config.h */
39 /* ### I don't believe it - martin */
40 #include <config.h>
41 #include "systime.h"
42 #include "syssignal.h"
43 #include "sysproc.h"
44
45 #undef access
46 #undef chdir
47 #undef chmod
48 #undef creat
49 #undef ctime
50 #undef fopen
51 #undef link
52 #undef mkdir
53 #undef mktemp
54 #undef open
55 #undef rename
56 #undef rmdir
57 #undef unlink
58
59 #undef close
60 #undef dup
61 #undef dup2
62 #undef pipe
63 #undef read
64 #undef write
65 #undef closedir
66
67 #define getwd _getwd
68 #include "lisp.h"
69 #undef getwd
70
71 #include <pwd.h>
72 49
73 #include <windows.h> 50 #include <windows.h>
74 #include <mmsystem.h> 51 #include <mmsystem.h>
75 52
76 #include "nt.h" 53 #include "nt.h"
1213 } 1190 }
1214 1191
1215 return &dir_static; 1192 return &dir_static;
1216 } 1193 }
1217 1194
1218 /* Shadow some MSVC runtime functions to map requests for long filenames 1195 #if 0
1219 to reasonable short names if necessary. This was originally added to 1196 /* #### Have to check if all that sad story about '95 is true - kkm */
1220 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1221 long file names. */
1222
1223 int
1224 sys_access (const char * path, int mode)
1225 {
1226 return _access (map_win32_filename (path, NULL), mode);
1227 }
1228
1229 int
1230 sys_chdir (const char * path)
1231 {
1232 return _chdir (map_win32_filename (path, NULL));
1233 }
1234
1235 int
1236 sys_chmod (const char * path, mode_t mode)
1237 {
1238 return _chmod (map_win32_filename (path, NULL), mode);
1239 }
1240
1241 int
1242 sys_creat (const char * path, mode_t mode)
1243 {
1244 return _creat (map_win32_filename (path, NULL), mode);
1245 }
1246
1247 FILE *
1248 sys_fopen(const char * path, const char * mode)
1249 {
1250 int fd;
1251 int oflag;
1252 const char * mode_save = mode;
1253
1254 /* Force all file handles to be non-inheritable. This is necessary to
1255 ensure child processes don't unwittingly inherit handles that might
1256 prevent future file access. */
1257
1258 if (mode[0] == 'r')
1259 oflag = O_RDONLY;
1260 else if (mode[0] == 'w' || mode[0] == 'a')
1261 oflag = O_WRONLY | O_CREAT | O_TRUNC;
1262 else
1263 return NULL;
1264
1265 /* Only do simplistic option parsing. */
1266 while (*++mode)
1267 if (mode[0] == '+')
1268 {
1269 oflag &= ~(O_RDONLY | O_WRONLY);
1270 oflag |= O_RDWR;
1271 }
1272 else if (mode[0] == 'b')
1273 {
1274 oflag &= ~O_TEXT;
1275 oflag |= O_BINARY;
1276 }
1277 else if (mode[0] == 't')
1278 {
1279 oflag &= ~O_BINARY;
1280 oflag |= O_TEXT;
1281 }
1282 else break;
1283
1284 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
1285 if (fd < 0)
1286 return NULL;
1287
1288 return _fdopen (fd, mode_save);
1289 }
1290
1291 /* This only works on NTFS volumes, but is useful to have. */
1292 int
1293 sys_link (const char * old, const char * new)
1294 {
1295 HANDLE fileh;
1296 int result = -1;
1297 char oldname[MAX_PATH], newname[MAX_PATH];
1298
1299 if (old == NULL || new == NULL)
1300 {
1301 errno = ENOENT;
1302 return -1;
1303 }
1304
1305 strcpy (oldname, map_win32_filename (old, NULL));
1306 strcpy (newname, map_win32_filename (new, NULL));
1307
1308 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
1309 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1310 if (fileh != INVALID_HANDLE_VALUE)
1311 {
1312 int wlen;
1313
1314 /* Confusingly, the "alternate" stream name field does not apply
1315 when restoring a hard link, and instead contains the actual
1316 stream data for the link (ie. the name of the link to create).
1317 The WIN32_STREAM_ID structure before the cStreamName field is
1318 the stream header, which is then immediately followed by the
1319 stream data. */
1320
1321 struct {
1322 WIN32_STREAM_ID wid;
1323 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
1324 } data;
1325
1326 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
1327 data.wid.cStreamName, MAX_PATH);
1328 if (wlen > 0)
1329 {
1330 LPVOID context = NULL;
1331 DWORD wbytes = 0;
1332
1333 data.wid.dwStreamId = BACKUP_LINK;
1334 data.wid.dwStreamAttributes = 0;
1335 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
1336 data.wid.Size.HighPart = 0;
1337 data.wid.dwStreamNameSize = 0;
1338
1339 if (BackupWrite (fileh, (LPBYTE)&data,
1340 offsetof (WIN32_STREAM_ID, cStreamName)
1341 + data.wid.Size.LowPart,
1342 &wbytes, FALSE, FALSE, &context)
1343 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
1344 {
1345 /* succeeded */
1346 result = 0;
1347 }
1348 else
1349 {
1350 /* Should try mapping GetLastError to errno; for now just
1351 indicate a general error (eg. links not supported). */
1352 errno = EINVAL; // perhaps EMLINK?
1353 }
1354 }
1355
1356 CloseHandle (fileh);
1357 }
1358 else
1359 errno = ENOENT;
1360
1361 return result;
1362 }
1363
1364 int
1365 sys_mkdir (const char * path, int mode_unused)
1366 {
1367 return _mkdir (map_win32_filename (path, NULL));
1368 }
1369
1370 /* Because of long name mapping issues, we need to implement this
1371 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1372 a unique name, instead of setting the input template to an empty
1373 string.
1374
1375 Standard algorithm seems to be use pid or tid with a letter on the
1376 front (in place of the 6 X's) and cycle through the letters to find a
1377 unique name. We extend that to allow any reasonable character as the
1378 first of the 6 X's. */
1379 char *
1380 sys_mktemp (char * template)
1381 {
1382 char * p;
1383 int i;
1384 unsigned uid = GetCurrentThreadId ();
1385 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1386
1387 if (template == NULL)
1388 return NULL;
1389 p = template + strlen (template);
1390 i = 5;
1391 /* replace up to the last 5 X's with uid in decimal */
1392 while (--p >= template && p[0] == 'X' && --i >= 0)
1393 {
1394 p[0] = '0' + uid % 10;
1395 uid /= 10;
1396 }
1397
1398 if (i < 0 && p[0] == 'X')
1399 {
1400 i = 0;
1401 do
1402 {
1403 int save_errno = errno;
1404 p[0] = first_char[i];
1405 if (sys_access (template, 0) < 0)
1406 {
1407 errno = save_errno;
1408 return template;
1409 }
1410 }
1411 while (++i < sizeof (first_char));
1412 }
1413
1414 /* Template is badly formed or else we can't generate a unique name,
1415 so return empty string */
1416 template[0] = 0;
1417 return template;
1418 }
1419
1420 int
1421 sys_open (const char * path, int oflag, int mode)
1422 {
1423 int fd;
1424
1425 /* Force all file handles to be non-inheritable. */
1426 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
1427
1428 if (fd >= MAXDESC)
1429 {
1430 _close (fd);
1431 errno = EMFILE;
1432 return -1;
1433 }
1434
1435 if (fd >= 0)
1436 {
1437 fd_info[fd].cp = 0;
1438 }
1439 return (fd);
1440 }
1441
1442 int 1197 int
1443 sys_rename (const char * oldname, const char * newname) 1198 sys_rename (const char * oldname, const char * newname)
1444 { 1199 {
1445 char temp[MAX_PATH]; 1200 char temp[MAX_PATH];
1446 DWORD attr; 1201 DWORD attr;
1492 _unlink (newname); 1247 _unlink (newname);
1493 } 1248 }
1494 1249
1495 return rename (temp, newname); 1250 return rename (temp, newname);
1496 } 1251 }
1497 1252 #endif /* 0 */
1498 int
1499 sys_rmdir (const char * path)
1500 {
1501 return _rmdir (map_win32_filename (path, NULL));
1502 }
1503
1504 int
1505 sys_unlink (const char * path)
1506 {
1507 return _unlink (map_win32_filename (path, NULL));
1508 }
1509 1253
1510 static FILETIME utc_base_ft; 1254 static FILETIME utc_base_ft;
1511 static long double utc_base; 1255 static long double utc_base;
1512 static int init = 0; 1256 static int init = 0;
1513 1257
1810 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); 1554 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1811 1555
1812 return 0; 1556 return 0;
1813 } 1557 }
1814 1558
1815 /* Shadow main io functions: we need to handle pipes and sockets more
1816 intelligently, and implement non-blocking mode as well. */
1817
1818 int
1819 sys_close (int fd)
1820 {
1821 int rc;
1822
1823 if (fd < 0 || fd >= MAXDESC)
1824 {
1825 errno = EBADF;
1826 return -1;
1827 }
1828
1829 if (fd_info[fd].cp)
1830 {
1831 child_process * cp = fd_info[fd].cp;
1832
1833 fd_info[fd].cp = NULL;
1834
1835 if (CHILD_ACTIVE (cp))
1836 {
1837 /* if last descriptor to active child_process then cleanup */
1838 int i;
1839 for (i = 0; i < MAXDESC; i++)
1840 {
1841 if (i == fd)
1842 continue;
1843 if (fd_info[i].cp == cp)
1844 break;
1845 }
1846 if (i == MAXDESC)
1847 {
1848 delete_child (cp);
1849 }
1850 }
1851 }
1852
1853 /* Note that sockets do not need special treatment here (at least on
1854 NT and Win95 using the standard tcp/ip stacks) - it appears that
1855 closesocket is equivalent to CloseHandle, which is to be expected
1856 because socket handles are fully fledged kernel handles. */
1857 rc = _close (fd);
1858
1859 if (rc == 0)
1860 fd_info[fd].flags = 0;
1861
1862 return rc;
1863 }
1864
1865 int
1866 sys_dup (int fd)
1867 {
1868 int new_fd;
1869
1870 new_fd = _dup (fd);
1871 if (new_fd >= 0)
1872 {
1873 /* duplicate our internal info as well */
1874 fd_info[new_fd] = fd_info[fd];
1875 }
1876 return new_fd;
1877 }
1878
1879
1880 int
1881 sys_dup2 (int src, int dst)
1882 {
1883 int rc;
1884
1885 if (dst < 0 || dst >= MAXDESC)
1886 {
1887 errno = EBADF;
1888 return -1;
1889 }
1890
1891 /* make sure we close the destination first if it's a pipe or socket */
1892 if (src != dst && fd_info[dst].flags != 0)
1893 sys_close (dst);
1894
1895 rc = _dup2 (src, dst);
1896 if (rc == 0)
1897 {
1898 /* duplicate our internal info as well */
1899 fd_info[dst] = fd_info[src];
1900 }
1901 return rc;
1902 }
1903
1904 /* From callproc.c */ 1559 /* From callproc.c */
1905 extern Lisp_Object Vbinary_process_input; 1560 extern Lisp_Object Vbinary_process_input;
1906 extern Lisp_Object Vbinary_process_output; 1561 extern Lisp_Object Vbinary_process_output;
1907 1562
1908 /* Unix pipe() has only one arg */ 1563 /* Unix pipe() has only one arg */
1992 else 1647 else
1993 cp->status = STATUS_READ_FAILED; 1648 cp->status = STATUS_READ_FAILED;
1994 1649
1995 return cp->status; 1650 return cp->status;
1996 } 1651 }
1997
1998 int
1999 sys_read (int fd, char * buffer, size_t count)
2000 {
2001 int nchars;
2002 int to_read;
2003 DWORD waiting;
2004 char * orig_buffer = buffer;
2005
2006 if (fd < 0 || fd >= MAXDESC)
2007 {
2008 errno = EBADF;
2009 return -1;
2010 }
2011
2012 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2013 {
2014 child_process *cp = fd_info[fd].cp;
2015
2016 if ((fd_info[fd].flags & FILE_READ) == 0)
2017 {
2018 errno = EBADF;
2019 return -1;
2020 }
2021
2022 nchars = 0;
2023
2024 /* re-read CR carried over from last read */
2025 if (fd_info[fd].flags & FILE_LAST_CR)
2026 {
2027 if (fd_info[fd].flags & FILE_BINARY) abort ();
2028 *buffer++ = 0x0d;
2029 count--;
2030 nchars++;
2031 fd_info[fd].flags &= ~FILE_LAST_CR;
2032 }
2033
2034 /* presence of a child_process structure means we are operating in
2035 non-blocking mode - otherwise we just call _read directly.
2036 Note that the child_process structure might be missing because
2037 reap_subprocess has been called; in this case the pipe is
2038 already broken, so calling _read on it is okay. */
2039 if (cp)
2040 {
2041 int current_status = cp->status;
2042
2043 switch (current_status)
2044 {
2045 case STATUS_READ_FAILED:
2046 case STATUS_READ_ERROR:
2047 /* report normal EOF if nothing in buffer */
2048 if (nchars <= 0)
2049 fd_info[fd].flags |= FILE_AT_EOF;
2050 return nchars;
2051
2052 case STATUS_READ_READY:
2053 case STATUS_READ_IN_PROGRESS:
2054 errno = EWOULDBLOCK;
2055 return -1;
2056
2057 case STATUS_READ_SUCCEEDED:
2058 /* consume read-ahead char */
2059 *buffer++ = cp->chr;
2060 count--;
2061 nchars++;
2062 cp->status = STATUS_READ_ACKNOWLEDGED;
2063 ResetEvent (cp->char_avail);
2064
2065 case STATUS_READ_ACKNOWLEDGED:
2066 break;
2067
2068 default:
2069 errno = EBADF;
2070 return -1;
2071 }
2072
2073 if (fd_info[fd].flags & FILE_PIPE)
2074 {
2075 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2076 to_read = min (waiting, (DWORD) count);
2077
2078 if (to_read > 0)
2079 nchars += _read (fd, buffer, to_read);
2080 }
2081 }
2082 else
2083 {
2084 int nread = _read (fd, buffer, count);
2085 if (nread >= 0)
2086 nchars += nread;
2087 else if (nchars == 0)
2088 nchars = nread;
2089 }
2090
2091 if (nchars <= 0)
2092 fd_info[fd].flags |= FILE_AT_EOF;
2093 /* Perform text mode translation if required. */
2094 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
2095 {
2096 unsigned lf_count = 0;
2097 nchars = crlf_to_lf (nchars, orig_buffer, &lf_count);
2098 /* If buffer contains only CR, return that. To be absolutely
2099 sure we should attempt to read the next char, but in
2100 practice a CR to be followed by LF would not appear by
2101 itself in the buffer. */
2102 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
2103 {
2104 fd_info[fd].flags |= FILE_LAST_CR;
2105 nchars--;
2106 }
2107 }
2108 }
2109 else
2110 nchars = _read (fd, buffer, count);
2111
2112 return nchars;
2113 }
2114
2115 /* For now, don't bother with a non-blocking mode */
2116 int
2117 sys_write (int fd, const void * buffer, size_t count)
2118 {
2119 int nchars;
2120
2121 if (fd < 0 || fd >= MAXDESC)
2122 {
2123 errno = EBADF;
2124 return -1;
2125 }
2126
2127 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2128 {
2129 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2130 {
2131 errno = EBADF;
2132 return -1;
2133 }
2134
2135 /* Perform text mode translation if required. */
2136 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2137 {
2138 char * tmpbuf = alloca (count * 2);
2139 unsigned char * src = (void *)buffer;
2140 unsigned char * dst = tmpbuf;
2141 int nbytes = count;
2142
2143 while (1)
2144 {
2145 unsigned char *next;
2146 /* copy next line or remaining bytes */
2147 next = _memccpy (dst, src, '\n', nbytes);
2148 if (next)
2149 {
2150 /* copied one line ending with '\n' */
2151 int copied = next - dst;
2152 nbytes -= copied;
2153 src += copied;
2154 /* insert '\r' before '\n' */
2155 next[-1] = '\r';
2156 next[0] = '\n';
2157 dst = next + 1;
2158 count++;
2159 }
2160 else
2161 /* copied remaining partial line -> now finished */
2162 break;
2163 }
2164 buffer = tmpbuf;
2165 }
2166 }
2167
2168 nchars = _write (fd, buffer, count);
2169
2170 return nchars;
2171 }
2172
2173 1652
2174 void 1653 void
2175 term_ntproc (int unused) 1654 term_ntproc (int unused)
2176 { 1655 {
2177 } 1656 }