aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeoff Voelker1998-06-17 04:22:58 +0000
committerGeoff Voelker1998-06-17 04:22:58 +0000
commit9d3355d17865eb292084d09f6ddf487affa32dd9 (patch)
tree8f5a0a3af2ec1819ce0397462467e1618831dc4e
parent0c8b57ade8c9cb8cc9caafb09182bab185983a47 (diff)
downloademacs-9d3355d17865eb292084d09f6ddf487affa32dd9.tar.gz
emacs-9d3355d17865eb292084d09f6ddf487affa32dd9.zip
(is_unc_volume, open_unc_volume, read_unc_volume,
close_unc_volume, unc_volume_file_attributes): New functions. (wnet_enum_handle): New variable. (opendir, readdir, closedir, sys_access, stat): Handle UNC volumes.
-rw-r--r--src/w32.c148
1 files changed, 143 insertions, 5 deletions
diff --git a/src/w32.c b/src/w32.c
index f35ebc6523b..ca4b50ecb2d 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -533,6 +533,19 @@ w32_get_long_filename (char * name, char * buf, int size)
533 return TRUE; 533 return TRUE;
534} 534}
535 535
536int
537is_unc_volume (const char *filename)
538{
539 const char *ptr = filename;
540
541 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
542 return 0;
543
544 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
545 return 0;
546
547 return 1;
548}
536 549
537/* Routines that are no-ops on NT but are defined to get Emacs to compile. */ 550/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
538 551
@@ -1194,6 +1207,13 @@ static int dir_is_fat;
1194static char dir_pathname[MAXPATHLEN+1]; 1207static char dir_pathname[MAXPATHLEN+1];
1195static WIN32_FIND_DATA dir_find_data; 1208static WIN32_FIND_DATA dir_find_data;
1196 1209
1210/* Support shares on a network resource as subdirectories of a read-only
1211 root directory. */
1212static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
1213HANDLE open_unc_volume (char *);
1214char *read_unc_volume (HANDLE, char *, int);
1215void close_unc_volume (HANDLE);
1216
1197DIR * 1217DIR *
1198opendir (char *filename) 1218opendir (char *filename)
1199{ 1219{
@@ -1202,10 +1222,20 @@ opendir (char *filename)
1202 /* Opening is done by FindFirstFile. However, a read is inherent to 1222 /* Opening is done by FindFirstFile. However, a read is inherent to
1203 this operation, so we defer the open until read time. */ 1223 this operation, so we defer the open until read time. */
1204 1224
1205 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1206 return NULL;
1207 if (dir_find_handle != INVALID_HANDLE_VALUE) 1225 if (dir_find_handle != INVALID_HANDLE_VALUE)
1208 return NULL; 1226 return NULL;
1227 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1228 return NULL;
1229
1230 if (is_unc_volume (filename))
1231 {
1232 wnet_enum_handle = open_unc_volume (filename);
1233 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
1234 return NULL;
1235 }
1236
1237 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1238 return NULL;
1209 1239
1210 dirp->dd_fd = 0; 1240 dirp->dd_fd = 0;
1211 dirp->dd_loc = 0; 1241 dirp->dd_loc = 0;
@@ -1227,14 +1257,26 @@ closedir (DIR *dirp)
1227 FindClose (dir_find_handle); 1257 FindClose (dir_find_handle);
1228 dir_find_handle = INVALID_HANDLE_VALUE; 1258 dir_find_handle = INVALID_HANDLE_VALUE;
1229 } 1259 }
1260 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1261 {
1262 close_unc_volume (wnet_enum_handle);
1263 wnet_enum_handle = INVALID_HANDLE_VALUE;
1264 }
1230 xfree ((char *) dirp); 1265 xfree ((char *) dirp);
1231} 1266}
1232 1267
1233struct direct * 1268struct direct *
1234readdir (DIR *dirp) 1269readdir (DIR *dirp)
1235{ 1270{
1271 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1272 {
1273 if (!read_unc_volume (wnet_enum_handle,
1274 dir_find_data.cFileName,
1275 MAX_PATH))
1276 return NULL;
1277 }
1236 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ 1278 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1237 if (dir_find_handle == INVALID_HANDLE_VALUE) 1279 else if (dir_find_handle == INVALID_HANDLE_VALUE)
1238 { 1280 {
1239 char filename[MAXNAMLEN + 3]; 1281 char filename[MAXNAMLEN + 3];
1240 int ln; 1282 int ln;
@@ -1280,6 +1322,80 @@ readdir (DIR *dirp)
1280 return &dir_static; 1322 return &dir_static;
1281} 1323}
1282 1324
1325HANDLE
1326open_unc_volume (char *path)
1327{
1328 NETRESOURCE nr;
1329 HANDLE henum;
1330 int result;
1331
1332 nr.dwScope = RESOURCE_GLOBALNET;
1333 nr.dwType = RESOURCETYPE_DISK;
1334 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
1335 nr.dwUsage = RESOURCEUSAGE_CONTAINER;
1336 nr.lpLocalName = NULL;
1337 nr.lpRemoteName = map_w32_filename (path, NULL);
1338 nr.lpComment = NULL;
1339 nr.lpProvider = NULL;
1340
1341 result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
1342 RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
1343
1344 if (result == NO_ERROR)
1345 return henum;
1346 else
1347 return INVALID_HANDLE_VALUE;
1348}
1349
1350char *
1351read_unc_volume (HANDLE henum, char *readbuf, int size)
1352{
1353 int count;
1354 int result;
1355 int bufsize = 512;
1356 char *buffer;
1357 char *ptr;
1358
1359 count = 1;
1360 buffer = alloca (bufsize);
1361 result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
1362 if (result != NO_ERROR)
1363 return NULL;
1364
1365 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1366 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
1367 ptr += 2;
1368 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
1369 ptr++;
1370
1371 strncpy (readbuf, ptr, size);
1372 return readbuf;
1373}
1374
1375void
1376close_unc_volume (HANDLE henum)
1377{
1378 if (henum != INVALID_HANDLE_VALUE)
1379 WNetCloseEnum (henum);
1380}
1381
1382DWORD
1383unc_volume_file_attributes (char *path)
1384{
1385 HANDLE henum;
1386 DWORD attrs;
1387
1388 henum = open_unc_volume (path);
1389 if (henum == INVALID_HANDLE_VALUE)
1390 return -1;
1391
1392 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
1393
1394 close_unc_volume (henum);
1395
1396 return attrs;
1397}
1398
1283 1399
1284/* Shadow some MSVC runtime functions to map requests for long filenames 1400/* Shadow some MSVC runtime functions to map requests for long filenames
1285 to reasonable short names if necessary. This was originally added to 1401 to reasonable short names if necessary. This was originally added to
@@ -1293,7 +1409,15 @@ sys_access (const char * path, int mode)
1293 1409
1294 /* MSVC implementation doesn't recognize D_OK. */ 1410 /* MSVC implementation doesn't recognize D_OK. */
1295 path = map_w32_filename (path, NULL); 1411 path = map_w32_filename (path, NULL);
1296 if ((attributes = GetFileAttributes (path)) == -1) 1412 if (is_unc_volume (path))
1413 {
1414 attributes = unc_volume_file_attributes (path);
1415 if (attributes == -1) {
1416 errno = EACCES;
1417 return -1;
1418 }
1419 }
1420 else if ((attributes = GetFileAttributes (path)) == -1)
1297 { 1421 {
1298 /* Should try mapping GetLastError to errno; for now just indicate 1422 /* Should try mapping GetLastError to errno; for now just indicate
1299 that path doesn't exist. */ 1423 that path doesn't exist. */
@@ -1759,7 +1883,21 @@ stat (const char * path, struct stat * buf)
1759 && (IS_DIRECTORY_SEP (*path) || *path == 0)); 1883 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1760 name = strcpy (alloca (len + 2), name); 1884 name = strcpy (alloca (len + 2), name);
1761 1885
1762 if (rootdir) 1886 if (is_unc_volume (name))
1887 {
1888 DWORD attrs = unc_volume_file_attributes (name);
1889
1890 if (attrs == -1)
1891 return -1;
1892
1893 memset (&wfd, 0, sizeof (wfd));
1894 wfd.dwFileAttributes = attrs;
1895 wfd.ftCreationTime = utc_base_ft;
1896 wfd.ftLastAccessTime = utc_base_ft;
1897 wfd.ftLastWriteTime = utc_base_ft;
1898 strcpy (wfd.cFileName, name);
1899 }
1900 else if (rootdir)
1763 { 1901 {
1764 if (!IS_DIRECTORY_SEP (name[len-1])) 1902 if (!IS_DIRECTORY_SEP (name[len-1]))
1765 strcat (name, "\\"); 1903 strcat (name, "\\");