* mount.cc (GETVOLINFO_VALID_MASK): Drop FILE_SEQUENTIAL_WRITE_ONCE
from mask. Expand the comment a bit. (WIN_FAT_FLAGS): New define. (FS_IS_WINDOWS_FAT): New macro. (fs_info::update): Handle remote FS faking to be FAT. Subsume under CIFS. Check for NWFS and has_buggy_basic_info only for remote filesystems. Add check for has_dos_filenames_only. * mount.h (class fs_info): Add has_dos_filenames_only status flag. Implement accessors. * path.cc (symlink_info::check): Rearrange variable definitions to clear them up. Add a restart label to allow a clean restart within the method. Add a check for broken filesystems only allowing DOS pathnames in case we encounter a STATUS_OBJECT_NAME_NOT_FOUND status. If all checks point to one of that, restart method with tweaked incoming path. Add lengthy comments to explain what we do.
This commit is contained in:
		| @@ -1,3 +1,21 @@ | |||||||
|  | 2010-04-22  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* mount.cc (GETVOLINFO_VALID_MASK): Drop FILE_SEQUENTIAL_WRITE_ONCE | ||||||
|  | 	from mask.  Expand the comment a bit. | ||||||
|  | 	(WIN_FAT_FLAGS): New define. | ||||||
|  | 	(FS_IS_WINDOWS_FAT): New macro. | ||||||
|  | 	(fs_info::update): Handle remote FS faking to be FAT.  Subsume under | ||||||
|  | 	CIFS.  Check for NWFS and has_buggy_basic_info only for remote | ||||||
|  | 	filesystems.  Add check for has_dos_filenames_only. | ||||||
|  | 	* mount.h (class fs_info): Add has_dos_filenames_only status flag. | ||||||
|  | 	Implement accessors. | ||||||
|  | 	* path.cc (symlink_info::check): Rearrange variable definitions to | ||||||
|  | 	clear them up.  Add a restart label to allow a clean restart within | ||||||
|  | 	the method.  Add a check for broken filesystems only allowing DOS | ||||||
|  | 	pathnames in case we encounter a STATUS_OBJECT_NAME_NOT_FOUND status. | ||||||
|  | 	If all checks point to one of that, restart method with tweaked | ||||||
|  | 	incoming path.  Add lengthy comments to explain what we do. | ||||||
|  |  | ||||||
| 2010-04-22  Corinna Vinschen  <corinna@vinschen.de> | 2010-04-22  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* path.cc (symlink_info::check): Fix a comment. | 	* path.cc (symlink_info::check): Fix a comment. | ||||||
|   | |||||||
| @@ -208,9 +208,12 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) | |||||||
| /* Should be reevaluated for each new OS.  Right now this mask is valid up | /* Should be reevaluated for each new OS.  Right now this mask is valid up | ||||||
|    to Vista.  The important point here is to test only flags indicating |    to Vista.  The important point here is to test only flags indicating | ||||||
|    capabilities and to ignore flags indicating a specific state of this |    capabilities and to ignore flags indicating a specific state of this | ||||||
|    volume.  At present these flags to ignore are FILE_VOLUME_IS_COMPRESSED |    volume.  At present these flags to ignore are FILE_VOLUME_IS_COMPRESSED, | ||||||
|    and FILE_READ_ONLY_VOLUME. */ |    FILE_READ_ONLY_VOLUME, and FILE_SEQUENTIAL_WRITE_ONCE.  The additional | ||||||
| #define GETVOLINFO_VALID_MASK (0x003701ffUL) |    filesystem flags supported since Windows 7 are also ignored for now. | ||||||
|  |    They add information, but only on W7 and later, and only for filesystems | ||||||
|  |    also supporting these flags, right now only NTFS. */ | ||||||
|  | #define GETVOLINFO_VALID_MASK (0x002701ffUL) | ||||||
| #define TEST_GVI(f,m) (((f) & GETVOLINFO_VALID_MASK) == (m)) | #define TEST_GVI(f,m) (((f) & GETVOLINFO_VALID_MASK) == (m)) | ||||||
|  |  | ||||||
| /* FIXME: This flag twist is getting awkward.  There should really be some | /* FIXME: This flag twist is getting awkward.  There should really be some | ||||||
| @@ -244,6 +247,11 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) | |||||||
| 				| FILE_FILE_COMPRESSION) | 				| FILE_FILE_COMPRESSION) | ||||||
| #define FS_IS_WINDOWS_NTFS TEST_GVI(flags () & MINIMAL_WIN_NTFS_FLAGS, \ | #define FS_IS_WINDOWS_NTFS TEST_GVI(flags () & MINIMAL_WIN_NTFS_FLAGS, \ | ||||||
| 				    MINIMAL_WIN_NTFS_FLAGS) | 				    MINIMAL_WIN_NTFS_FLAGS) | ||||||
|  | /* These are the exact flags of a real Windows FAT/FAT32 filesystem. | ||||||
|  |    Anything else is a filesystem faking to be FAT. */ | ||||||
|  | #define WIN_FAT_FLAGS (FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK) | ||||||
|  | #define FS_IS_WINDOWS_FAT  TEST_GVI(flags (), WIN_FAT_FLAGS) | ||||||
|  |  | ||||||
|       /* This always fails on NT4. */ |       /* This always fails on NT4. */ | ||||||
|       status = NtQueryVolumeInformationFile (vol, &io, &ffoi, sizeof ffoi, |       status = NtQueryVolumeInformationFile (vol, &io, &ffoi, sizeof ffoi, | ||||||
| 					     FileFsObjectIdInformation); | 					     FileFsObjectIdInformation); | ||||||
| @@ -266,6 +274,11 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) | |||||||
| 	  && !is_netapp (FS_IS_NETAPP_DATAONTAP)) | 	  && !is_netapp (FS_IS_NETAPP_DATAONTAP)) | ||||||
| 	/* Any other remote FS faking to be NTFS. */ | 	/* Any other remote FS faking to be NTFS. */ | ||||||
| 	is_cifs (!FS_IS_WINDOWS_NTFS); | 	is_cifs (!FS_IS_WINDOWS_NTFS); | ||||||
|  |       /* Then check the remote filesystems faking to be FAT.  Right now all | ||||||
|  | 	 of them are subsumed under the "CIFS" filesystem type. */ | ||||||
|  |       if (!got_fs () | ||||||
|  | 	  && is_fat (RtlEqualUnicodePathPrefix (&fsname, &ro_u_fat, TRUE))) | ||||||
|  | 	is_cifs (!FS_IS_WINDOWS_FAT); | ||||||
|       /* Then check remote filesystems honest about their name. */ |       /* Then check remote filesystems honest about their name. */ | ||||||
|       if (!got_fs () |       if (!got_fs () | ||||||
| 	  /* Microsoft NFS needs distinct access methods for metadata. */ | 	  /* Microsoft NFS needs distinct access methods for metadata. */ | ||||||
| @@ -274,6 +287,8 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) | |||||||
| 	     drawbacks, like not supporting DOS attributes other than R/O | 	     drawbacks, like not supporting DOS attributes other than R/O | ||||||
| 	     and stuff like that. */ | 	     and stuff like that. */ | ||||||
| 	  && !is_mvfs (RtlEqualUnicodePathPrefix (&fsname, &ro_u_mvfs, FALSE)) | 	  && !is_mvfs (RtlEqualUnicodePathPrefix (&fsname, &ro_u_mvfs, FALSE)) | ||||||
|  | 	  /* NWFS == Novell Netware FS.  Broken info class, see below. */ | ||||||
|  | 	  && !is_nwfs (RtlEqualUnicodeString (&fsname, &ro_u_nwfs, FALSE)) | ||||||
| 	  /* Known remote file system which can't handle calls to | 	  /* Known remote file system which can't handle calls to | ||||||
| 	     NtQueryDirectoryFile(FileIdBothDirectoryInformation) */ | 	     NtQueryDirectoryFile(FileIdBothDirectoryInformation) */ | ||||||
| 	  && !is_unixfs (RtlEqualUnicodeString (&fsname, &ro_u_unixfs, FALSE))) | 	  && !is_unixfs (RtlEqualUnicodeString (&fsname, &ro_u_unixfs, FALSE))) | ||||||
| @@ -283,18 +298,31 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) | |||||||
| 	  is_sunwnfs (RtlEqualUnicodeString (&fsname, &ro_u_sunwnfs, FALSE)); | 	  is_sunwnfs (RtlEqualUnicodeString (&fsname, &ro_u_sunwnfs, FALSE)); | ||||||
| 	  has_buggy_open (is_sunwnfs ()); | 	  has_buggy_open (is_sunwnfs ()); | ||||||
| 	} | 	} | ||||||
|       /* Not only UNIXFS is known to choke on FileIdBothDirectoryInformation. |  | ||||||
| 	 Some other CIFS servers have problems with this call as well. |  | ||||||
| 	 Know example: EMC NS-702.  We just don't use that info class on |  | ||||||
| 	 any remote CIFS.  */ |  | ||||||
|       if (got_fs ()) |       if (got_fs ()) | ||||||
| 	has_buggy_fileid_dirinfo (is_cifs () || is_unixfs ()); | 	{ | ||||||
|  | 	  /* UNIXFS is known to choke on FileIdBothDirectoryInformation. | ||||||
|  | 	     Some other CIFS servers have problems with this call as well. | ||||||
|  | 	     Know example: EMC NS-702.  We just don't use that info class on | ||||||
|  | 	     any remote CIFS.  */ | ||||||
|  | 	  has_buggy_fileid_dirinfo (is_cifs () || is_unixfs ()); | ||||||
|  | 	  /* NWFS is known to have a broken FileBasicInformation info class. | ||||||
|  | 	     It can't be used to fetch information, only to set information.  | ||||||
|  | 	     Therefore, for NWFS we have to fallback to the | ||||||
|  | 	     FileNetworkOpenInformation info class.  Unfortunately we can't | ||||||
|  | 	     use FileNetworkOpenInformation all the time since that fails on | ||||||
|  | 	     other filesystems like NFS. */ | ||||||
|  | 	  has_buggy_basic_info (is_nwfs ()); | ||||||
|  | 	  /* Netapp ans NWFS are too dumb to allow non-DOS filesystems | ||||||
|  | 	     containing trailing dots and spaces when accessed from Windows | ||||||
|  | 	     clients.  We subsume CIFS into this class of filesystems right | ||||||
|  | 	     away since at least some of them are not capable either. */ | ||||||
|  | 	  has_dos_filenames_only (is_netapp () || is_nwfs () || is_cifs ()); | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
|   if (!got_fs () |   if (!got_fs () | ||||||
|       && !is_ntfs (RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE)) |       && !is_ntfs (RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE)) | ||||||
|       && !is_fat (RtlEqualUnicodePathPrefix (&fsname, &ro_u_fat, TRUE)) |       && !is_fat (RtlEqualUnicodePathPrefix (&fsname, &ro_u_fat, TRUE)) | ||||||
|       && !is_csc_cache (RtlEqualUnicodeString (&fsname, &ro_u_csc, FALSE)) |       && !is_csc_cache (RtlEqualUnicodeString (&fsname, &ro_u_csc, FALSE)) | ||||||
|       && !is_nwfs (RtlEqualUnicodeString (&fsname, &ro_u_nwfs, FALSE)) |  | ||||||
|       && is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM)) |       && is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM)) | ||||||
|     is_udf (RtlEqualUnicodeString (&fsname, &ro_u_udf, FALSE)); |     is_udf (RtlEqualUnicodeString (&fsname, &ro_u_udf, FALSE)); | ||||||
|   if (!got_fs ()) |   if (!got_fs ()) | ||||||
| @@ -308,12 +336,6 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) | |||||||
|   has_acls (flags () & FS_PERSISTENT_ACLS); |   has_acls (flags () & FS_PERSISTENT_ACLS); | ||||||
|   /* Netapp inode numbers are fly-by-night. */ |   /* Netapp inode numbers are fly-by-night. */ | ||||||
|   hasgood_inode ((has_acls () && !is_netapp ()) || is_nfs ()); |   hasgood_inode ((has_acls () && !is_netapp ()) || is_nfs ()); | ||||||
|   /* NWFS is known to have a broken FileBasicInformation info class.  It |  | ||||||
|      can't be used to fetch information, only to set information.  Therefore, |  | ||||||
|      for NWFS we have to fallback to the FileNetworkOpenInformation info |  | ||||||
|      class.  Unfortunately we can't use FileNetworkOpenInformation all the |  | ||||||
|      time since that fails on other filesystems like NFS. */ |  | ||||||
|   has_buggy_basic_info (is_nwfs ()); |  | ||||||
|   /* Case sensitivity is supported if FILE_CASE_SENSITIVE_SEARCH is set, |   /* Case sensitivity is supported if FILE_CASE_SENSITIVE_SEARCH is set, | ||||||
|      except on Samba which handles Windows clients case insensitive. |      except on Samba which handles Windows clients case insensitive. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -51,6 +51,7 @@ class fs_info | |||||||
|     unsigned has_buggy_open		: 1; |     unsigned has_buggy_open		: 1; | ||||||
|     unsigned has_buggy_fileid_dirinfo	: 1; |     unsigned has_buggy_fileid_dirinfo	: 1; | ||||||
|     unsigned has_buggy_basic_info	: 1; |     unsigned has_buggy_basic_info	: 1; | ||||||
|  |     unsigned has_dos_filenames_only	: 1; | ||||||
|   } status; |   } status; | ||||||
|   ULONG sernum;			/* Volume Serial Number */ |   ULONG sernum;			/* Volume Serial Number */ | ||||||
|   char fsn[80];			/* Windows filesystem name */ |   char fsn[80];			/* Windows filesystem name */ | ||||||
| @@ -75,6 +76,7 @@ class fs_info | |||||||
|   IMPLEMENT_STATUS_FLAG (bool, has_buggy_open) |   IMPLEMENT_STATUS_FLAG (bool, has_buggy_open) | ||||||
|   IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo) |   IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo) | ||||||
|   IMPLEMENT_STATUS_FLAG (bool, has_buggy_basic_info) |   IMPLEMENT_STATUS_FLAG (bool, has_buggy_basic_info) | ||||||
|  |   IMPLEMENT_STATUS_FLAG (bool, has_dos_filenames_only) | ||||||
|   IMPLEMENT_FS_FLAG (is_fat, fat) |   IMPLEMENT_FS_FLAG (is_fat, fat) | ||||||
|   IMPLEMENT_FS_FLAG (is_ntfs, ntfs) |   IMPLEMENT_FS_FLAG (is_ntfs, ntfs) | ||||||
|   IMPLEMENT_FS_FLAG (is_samba, samba) |   IMPLEMENT_FS_FLAG (is_samba, samba) | ||||||
|   | |||||||
| @@ -2170,29 +2170,39 @@ int | |||||||
| symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, | symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, | ||||||
| 		     fs_info &fs) | 		     fs_info &fs) | ||||||
| { | { | ||||||
|   HANDLE h = NULL; |   int res; | ||||||
|   int res = 0; |   HANDLE h; | ||||||
|  |   NTSTATUS status; | ||||||
|  |   UNICODE_STRING upath; | ||||||
|  |   OBJECT_ATTRIBUTES attr; | ||||||
|  |   IO_STATUS_BLOCK io; | ||||||
|  |   FILE_BASIC_INFORMATION fbi; | ||||||
|   suffix_scan suffix; |   suffix_scan suffix; | ||||||
|   contents[0] = '\0'; |  | ||||||
|  |  | ||||||
|  |   ULONG ci_flag = cygwin_shared->obcaseinsensitive || (pflags & PATH_NOPOSIX) | ||||||
|  | 		  ? OBJ_CASE_INSENSITIVE : 0; | ||||||
|  |   /* TODO: Temporarily do all char->UNICODE conversion here.  This should | ||||||
|  |      already be slightly faster than using Ascii functions. */ | ||||||
|  |   tmp_pathbuf tp; | ||||||
|  |   tp.u_get (&upath); | ||||||
|  |   InitializeObjectAttributes (&attr, &upath, ci_flag, NULL, NULL); | ||||||
|  |  | ||||||
|  |   /* This label is used in case we encounter a FS which only handles | ||||||
|  |      DOS paths.  See below. */ | ||||||
|  | restart: | ||||||
|  |  | ||||||
|  |   h = NULL; | ||||||
|  |   res = 0; | ||||||
|  |   contents[0] = '\0'; | ||||||
|   issymlink = true; |   issymlink = true; | ||||||
|   isdevice = false; |   isdevice = false; | ||||||
|   ext_here = suffix.has (path, suffixes); |  | ||||||
|   extn = ext_here - path; |  | ||||||
|   major = 0; |   major = 0; | ||||||
|   minor = 0; |   minor = 0; | ||||||
|   mode = 0; |   mode = 0; | ||||||
|   pflags &= ~(PATH_SYMLINK | PATH_LNK | PATH_REP); |   pflags &= ~(PATH_SYMLINK | PATH_LNK | PATH_REP); | ||||||
|   ULONG ci_flag = cygwin_shared->obcaseinsensitive || (pflags & PATH_NOPOSIX) |  | ||||||
| 		  ? OBJ_CASE_INSENSITIVE : 0; |  | ||||||
|  |  | ||||||
|   /* TODO: Temporarily do all char->UNICODE conversion here.  This should |   ext_here = suffix.has (path, suffixes); | ||||||
|      already be slightly faster than using Ascii functions. */ |   extn = ext_here - path; | ||||||
|   tmp_pathbuf tp; |  | ||||||
|   UNICODE_STRING upath; |  | ||||||
|   OBJECT_ATTRIBUTES attr; |  | ||||||
|   tp.u_get (&upath); |  | ||||||
|   InitializeObjectAttributes (&attr, &upath, ci_flag, NULL, NULL); |  | ||||||
|  |  | ||||||
|   PVOID eabuf = &nfs_aol_ffei; |   PVOID eabuf = &nfs_aol_ffei; | ||||||
|   ULONG easize = sizeof nfs_aol_ffei; |   ULONG easize = sizeof nfs_aol_ffei; | ||||||
| @@ -2200,9 +2210,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, | |||||||
|   bool had_ext = !!*ext_here; |   bool had_ext = !!*ext_here; | ||||||
|   while (suffix.next ()) |   while (suffix.next ()) | ||||||
|     { |     { | ||||||
|       FILE_BASIC_INFORMATION fbi; |  | ||||||
|       NTSTATUS status; |  | ||||||
|       IO_STATUS_BLOCK io; |  | ||||||
|       bool no_ea = false; |       bool no_ea = false; | ||||||
|       bool fs_update_called = false; |       bool fs_update_called = false; | ||||||
|  |  | ||||||
| @@ -2251,28 +2258,66 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, | |||||||
| 			       | FILE_OPEN_FOR_BACKUP_INTENT); | 			       | FILE_OPEN_FOR_BACKUP_INTENT); | ||||||
| 	  debug_printf ("%p = NtOpenFile (no-EA, %S)", status, &upath); | 	  debug_printf ("%p = NtOpenFile (no-EA, %S)", status, &upath); | ||||||
| 	} | 	} | ||||||
|       if (status == STATUS_OBJECT_NAME_NOT_FOUND && ci_flag == 0 |       if (status == STATUS_OBJECT_NAME_NOT_FOUND) | ||||||
| 	  && wincap.has_broken_udf ()) | 	{ | ||||||
|         { | 	  if (ci_flag == 0 && wincap.has_broken_udf ()) | ||||||
| 	  /* On NT 5.x UDF is broken (at least) in terms of case sensitivity. |  | ||||||
| 	     When trying to open a file case sensitive, the file appears to be |  | ||||||
| 	     non-existant.  Another bug is described in fs_info::update. */ |  | ||||||
| 	  attr.Attributes = OBJ_CASE_INSENSITIVE; |  | ||||||
| 	  status = NtOpenFile (&h, READ_CONTROL | FILE_READ_ATTRIBUTES, |  | ||||||
| 			       &attr, &io, FILE_SHARE_VALID_FLAGS, |  | ||||||
| 			       FILE_OPEN_REPARSE_POINT |  | ||||||
| 			       | FILE_OPEN_FOR_BACKUP_INTENT); |  | ||||||
| 	  debug_printf ("%p = NtOpenFile (broken-UDF, %S)", status, &upath); |  | ||||||
| 	  attr.Attributes = 0; |  | ||||||
| 	  if (NT_SUCCESS (status)) |  | ||||||
| 	    { | 	    { | ||||||
| 	      fs.update (&upath, h); | 	      /* On NT 5.x UDF is broken (at least) in terms of case | ||||||
| 	      if (fs.is_udf ()) | 		 sensitivity.  When trying to open a file case sensitive, | ||||||
| 		fs_update_called = true; | 		 the file appears to be non-existant.  Another bug is | ||||||
| 	      else | 		 described in fs_info::update. */ | ||||||
| 	      	{ | 	      attr.Attributes = OBJ_CASE_INSENSITIVE; | ||||||
| 		  NtClose (h); | 	      status = NtOpenFile (&h, READ_CONTROL | FILE_READ_ATTRIBUTES, | ||||||
| 		  status = STATUS_OBJECT_NAME_NOT_FOUND; | 				   &attr, &io, FILE_SHARE_VALID_FLAGS, | ||||||
|  | 				   FILE_OPEN_REPARSE_POINT | ||||||
|  | 				   | FILE_OPEN_FOR_BACKUP_INTENT); | ||||||
|  | 	      debug_printf ("%p = NtOpenFile (broken-UDF, %S)", status, &upath); | ||||||
|  | 	      attr.Attributes = 0; | ||||||
|  | 	      if (NT_SUCCESS (status)) | ||||||
|  | 		{ | ||||||
|  | 		  fs.update (&upath, h); | ||||||
|  | 		  if (fs.is_udf ()) | ||||||
|  | 		    fs_update_called = true; | ||||||
|  | 		  else | ||||||
|  | 		    { | ||||||
|  | 		      NtClose (h); | ||||||
|  | 		      status = STATUS_OBJECT_NAME_NOT_FOUND; | ||||||
|  | 		    } | ||||||
|  | 		} | ||||||
|  | 	    } | ||||||
|  | 	  /* There are filesystems out in the wild (Netapp, NWFS, and others) | ||||||
|  | 	     which are uncapable of generating pathnames outside the Win32 | ||||||
|  | 	     rules.  That means, filenames on these FSes must not have a | ||||||
|  | 	     leading space or trailing dots and spaces.  This code snippet | ||||||
|  | 	     manages them.  I really hope it's streamlined enough not to | ||||||
|  | 	     slow down normal operation.  This extra check only kicks in if | ||||||
|  | 	     we encountered a STATUS_OBJECT_NAME_NOT_FOUND *and* we didn't | ||||||
|  | 	     already attach a suffix *and* the above special case for UDF | ||||||
|  | 	     on XP didn't succeeed. */ | ||||||
|  | 	  if (!*ext_here && !fs_update_called) | ||||||
|  | 	    { | ||||||
|  | 	      /* Check for leading space or trailing dot or space in | ||||||
|  | 	         last component. */ | ||||||
|  | 	      char *pend = ext_here; | ||||||
|  | 	      while (pend[-1] == '.' || pend[-1] == ' ') | ||||||
|  | 		--pend; | ||||||
|  | 	      char *pbeg = pend; | ||||||
|  | 	      while (pbeg[-1] != '\\') | ||||||
|  | 	      	--pbeg; | ||||||
|  | 	      /* If so, call fs.update to check if the filesystem is one of | ||||||
|  | 		 the broken ones. */ | ||||||
|  | 	      if ((*pbeg == ' ' || *pend != '\0') | ||||||
|  | 		  && fs.update (&upath, NULL) | ||||||
|  | 		  && fs.has_dos_filenames_only ()) | ||||||
|  | 		{ | ||||||
|  | 		  /* If so, strip leading spaces and trailing dots and spaces | ||||||
|  | 		     from filename and... */ | ||||||
|  | 		  if (pbeg) | ||||||
|  | 		    while (*pbeg == ' ') | ||||||
|  | 		      memmove (pbeg, pbeg + 1, --pend - pbeg); | ||||||
|  | 		  *pend = '\0'; | ||||||
|  | 		  /* ...try again. */ | ||||||
|  | 		  goto restart; | ||||||
| 		} | 		} | ||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user