comparison src/w32.c @ 22505:d4f3552a85f2

(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.
author Geoff Voelker <voelker@cs.washington.edu>
date Wed, 17 Jun 1998 04:22:58 +0000
parents d2edb98d0fa5
children a8c034594292
comparison
equal deleted inserted replaced
22504:115ca3d4f9c4 22505:d4f3552a85f2
531 while (p != NULL && *p); 531 while (p != NULL && *p);
532 532
533 return TRUE; 533 return TRUE;
534 } 534 }
535 535
536 int
537 is_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
539 int 552 int
540 sigsetmask (int signal_mask) 553 sigsetmask (int signal_mask)
1192 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE; 1205 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1193 static int dir_is_fat; 1206 static int dir_is_fat;
1194 static char dir_pathname[MAXPATHLEN+1]; 1207 static char dir_pathname[MAXPATHLEN+1];
1195 static WIN32_FIND_DATA dir_find_data; 1208 static WIN32_FIND_DATA dir_find_data;
1196 1209
1210 /* Support shares on a network resource as subdirectories of a read-only
1211 root directory. */
1212 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
1213 HANDLE open_unc_volume (char *);
1214 char *read_unc_volume (HANDLE, char *, int);
1215 void close_unc_volume (HANDLE);
1216
1197 DIR * 1217 DIR *
1198 opendir (char *filename) 1218 opendir (char *filename)
1199 { 1219 {
1200 DIR *dirp; 1220 DIR *dirp;
1201 1221
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
1225 if (dir_find_handle != INVALID_HANDLE_VALUE)
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
1205 if (!(dirp = (DIR *) malloc (sizeof (DIR)))) 1237 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1206 return NULL;
1207 if (dir_find_handle != INVALID_HANDLE_VALUE)
1208 return NULL; 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;
1212 dirp->dd_size = 0; 1242 dirp->dd_size = 0;
1225 if (dir_find_handle != INVALID_HANDLE_VALUE) 1255 if (dir_find_handle != INVALID_HANDLE_VALUE)
1226 { 1256 {
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
1233 struct direct * 1268 struct direct *
1234 readdir (DIR *dirp) 1269 readdir (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;
1241 1283
1242 strcpy (filename, dir_pathname); 1284 strcpy (filename, dir_pathname);
1278 } 1320 }
1279 1321
1280 return &dir_static; 1322 return &dir_static;
1281 } 1323 }
1282 1324
1325 HANDLE
1326 open_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
1350 char *
1351 read_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
1375 void
1376 close_unc_volume (HANDLE henum)
1377 {
1378 if (henum != INVALID_HANDLE_VALUE)
1379 WNetCloseEnum (henum);
1380 }
1381
1382 DWORD
1383 unc_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
1286 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support 1402 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1287 long file names. */ 1403 long file names. */
1291 { 1407 {
1292 DWORD attributes; 1408 DWORD attributes;
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. */
1300 errno = EACCES; 1424 errno = EACCES;
1301 return -1; 1425 return -1;
1757 len = strlen (name); 1881 len = strlen (name);
1758 rootdir = (path >= name + len - 1 1882 rootdir = (path >= name + len - 1
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, "\\");
1766 if (GetDriveType (name) < 2) 1904 if (GetDriveType (name) < 2)
1767 { 1905 {