Fossil SCM

When removing a directory on Windows, make sure it is a real directory (i.e. not a junction, symbolic link, etc).

mistachkin 2019-07-14 04:46 trunk
Commit 9bb25a28627be067847de63528aa23984590bed594abf7640b48fda5d276771d
1 file changed +48 -1
+48 -1
--- src/file.c
+++ src/file.c
@@ -701,10 +701,53 @@
701701
}
702702
free(zName);
703703
return rc;
704704
}
705705
706
+#if defined(_WIN32)
707
+/*
708
+** Returns non-zero if the specified name represents a real directory, i.e.
709
+** not a junction or symbolic link. This is important for some operations,
710
+** e.g. removing directories via _wrmdir(), because its detection of empty
711
+** directories will (apparently) not work right for junctions and symbolic
712
+** links, etc.
713
+*/
714
+int file_is_normal_dir(wchar_t *zName){
715
+ /*
716
+ ** Mask off attributes, applicable to directories, that are harmless for
717
+ ** our purposes. This may need to be updated if other attributes should
718
+ ** be ignored by this function.
719
+ */
720
+ DWORD dwAttributes = GetFileAttributesW(zName);
721
+ if( dwAttributes==INVALID_FILE_ATTRIBUTES ) return 0;
722
+ dwAttributes &= ~(
723
+ FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED |
724
+ FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_NORMAL |
725
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
726
+ );
727
+ return dwAttributes==FILE_ATTRIBUTE_DIRECTORY;
728
+}
729
+
730
+/*
731
+** COMMAND: test-is-normal-dir
732
+**
733
+** Usage: %fossil test-is-normal-dir NAME...
734
+**
735
+** Returns non-zero if the specified names represent real directories, i.e.
736
+** not junctions, symbolic links, etc.
737
+*/
738
+void test_is_normal_dir(void){
739
+ int i;
740
+ for(i=2; i<g.argc; i++){
741
+ wchar_t *zMbcs = fossil_utf8_to_path(g.argv[i], 1);
742
+ fossil_print("ATTRS \"%s\" -> %lx\n", g.argv[i], GetFileAttributesW(zMbcs));
743
+ fossil_print("ISDIR \"%s\" -> %d\n", g.argv[i], file_is_normal_dir(zMbcs));
744
+ fossil_path_free(zMbcs);
745
+ }
746
+}
747
+#endif
748
+
706749
/*
707750
** Removes the directory named in the argument, if it exists. The directory
708751
** must be empty and cannot be the current directory or the root directory.
709752
**
710753
** Returns zero upon success.
@@ -713,11 +756,15 @@
713756
int rc = file_isdir(zName, RepoFILE);
714757
if( rc==2 ) return 1; /* cannot remove normal file */
715758
if( rc==1 ){
716759
#if defined(_WIN32)
717760
wchar_t *zMbcs = fossil_utf8_to_path(zName, 1);
718
- rc = _wrmdir(zMbcs);
761
+ if( file_is_normal_dir(zMbcs) ){
762
+ rc = _wrmdir(zMbcs);
763
+ }else{
764
+ rc = ENOTDIR; /* junction, symbolic link, etc. */
765
+ }
719766
#else
720767
char *zMbcs = fossil_utf8_to_path(zName, 1);
721768
rc = rmdir(zName);
722769
#endif
723770
fossil_path_free(zMbcs);
724771
--- src/file.c
+++ src/file.c
@@ -701,10 +701,53 @@
701 }
702 free(zName);
703 return rc;
704 }
705
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
706 /*
707 ** Removes the directory named in the argument, if it exists. The directory
708 ** must be empty and cannot be the current directory or the root directory.
709 **
710 ** Returns zero upon success.
@@ -713,11 +756,15 @@
713 int rc = file_isdir(zName, RepoFILE);
714 if( rc==2 ) return 1; /* cannot remove normal file */
715 if( rc==1 ){
716 #if defined(_WIN32)
717 wchar_t *zMbcs = fossil_utf8_to_path(zName, 1);
718 rc = _wrmdir(zMbcs);
 
 
 
 
719 #else
720 char *zMbcs = fossil_utf8_to_path(zName, 1);
721 rc = rmdir(zName);
722 #endif
723 fossil_path_free(zMbcs);
724
--- src/file.c
+++ src/file.c
@@ -701,10 +701,53 @@
701 }
702 free(zName);
703 return rc;
704 }
705
706 #if defined(_WIN32)
707 /*
708 ** Returns non-zero if the specified name represents a real directory, i.e.
709 ** not a junction or symbolic link. This is important for some operations,
710 ** e.g. removing directories via _wrmdir(), because its detection of empty
711 ** directories will (apparently) not work right for junctions and symbolic
712 ** links, etc.
713 */
714 int file_is_normal_dir(wchar_t *zName){
715 /*
716 ** Mask off attributes, applicable to directories, that are harmless for
717 ** our purposes. This may need to be updated if other attributes should
718 ** be ignored by this function.
719 */
720 DWORD dwAttributes = GetFileAttributesW(zName);
721 if( dwAttributes==INVALID_FILE_ATTRIBUTES ) return 0;
722 dwAttributes &= ~(
723 FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED |
724 FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_NORMAL |
725 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
726 );
727 return dwAttributes==FILE_ATTRIBUTE_DIRECTORY;
728 }
729
730 /*
731 ** COMMAND: test-is-normal-dir
732 **
733 ** Usage: %fossil test-is-normal-dir NAME...
734 **
735 ** Returns non-zero if the specified names represent real directories, i.e.
736 ** not junctions, symbolic links, etc.
737 */
738 void test_is_normal_dir(void){
739 int i;
740 for(i=2; i<g.argc; i++){
741 wchar_t *zMbcs = fossil_utf8_to_path(g.argv[i], 1);
742 fossil_print("ATTRS \"%s\" -> %lx\n", g.argv[i], GetFileAttributesW(zMbcs));
743 fossil_print("ISDIR \"%s\" -> %d\n", g.argv[i], file_is_normal_dir(zMbcs));
744 fossil_path_free(zMbcs);
745 }
746 }
747 #endif
748
749 /*
750 ** Removes the directory named in the argument, if it exists. The directory
751 ** must be empty and cannot be the current directory or the root directory.
752 **
753 ** Returns zero upon success.
@@ -713,11 +756,15 @@
756 int rc = file_isdir(zName, RepoFILE);
757 if( rc==2 ) return 1; /* cannot remove normal file */
758 if( rc==1 ){
759 #if defined(_WIN32)
760 wchar_t *zMbcs = fossil_utf8_to_path(zName, 1);
761 if( file_is_normal_dir(zMbcs) ){
762 rc = _wrmdir(zMbcs);
763 }else{
764 rc = ENOTDIR; /* junction, symbolic link, etc. */
765 }
766 #else
767 char *zMbcs = fossil_utf8_to_path(zName, 1);
768 rc = rmdir(zName);
769 #endif
770 fossil_path_free(zMbcs);
771

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button