Mercurial > emacs
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 { |