@@ -79,107 +79,122 @@ int my_delete(const char *name, myf MyFlags)
7979 a file to unique name.
8080
8181 Symbolic link are deleted without renaming. Directories are not deleted.
82- */
82+ */
83+
8384static int my_win_unlink (const char * name )
8485{
8586 HANDLE handle = INVALID_HANDLE_VALUE ;
8687 DWORD attributes ;
8788 uint last_error ;
8889 char unique_filename [MAX_PATH + 35 ];
8990 unsigned long long tsc ; /* time stamp counter, for unique filename*/
90-
91+ int retries ;
9192 DBUG_ENTER ("my_win_unlink" );
92- attributes = GetFileAttributes (name );
93- if (attributes == INVALID_FILE_ATTRIBUTES )
94- {
95- last_error = GetLastError ();
96- DBUG_PRINT ("error" ,("GetFileAttributes(%s) failed with %u\n" , name , last_error ));
97- goto error ;
98- }
9993
100- if (attributes & FILE_ATTRIBUTE_DIRECTORY )
101- {
102- DBUG_PRINT ("error" ,("can't remove %s - it is a directory\n" , name ));
103- errno = EINVAL ;
104- DBUG_RETURN (-1 );
105- }
106-
107- if (attributes & FILE_ATTRIBUTE_REPARSE_POINT )
94+ DBUG_INJECT_FILE_SHARING_VIOLATION (name );
95+
96+ for (retries = FILE_SHARING_VIOLATION_RETRIES ; ; retries -- )
10897 {
109- /* Symbolic link. Delete link, the not target */
110- if (! DeleteFile ( name ) )
98+ attributes = GetFileAttributes ( name );
99+ if (attributes == INVALID_FILE_ATTRIBUTES )
111100 {
112- last_error = GetLastError ();
113- DBUG_PRINT ("error" ,("DeleteFile(%s) failed with %u\n" , name ,last_error ));
114- goto error ;
101+ last_error = GetLastError ();
102+ DBUG_PRINT ("error" ,
103+ ("GetFileAttributes(%s) failed with %u\n" , name , last_error ));
104+ goto error ;
115105 }
116- DBUG_RETURN (0 );
117- }
118106
119- /*
120- Try Windows 10 method, delete with "posix semantics" (file is not visible, and creating
121- a file with the same name won't fail, even if it the fiile was open)
122- */
123- struct
124- {
125- DWORD _Flags ;
126- } disp = {0x3 };
127- /* 0x3 = FILE_DISPOSITION_FLAG_DELETE | FILE_DISPOSITION_FLAG_POSIX_SEMANTICS */
107+ if (attributes & FILE_ATTRIBUTE_DIRECTORY )
108+ {
109+ DBUG_PRINT ("error" , ("can't remove %s - it is a directory\n" , name ));
110+ errno = EINVAL ;
111+ DBUG_RETURN (-1 );
112+ }
128113
129- handle = CreateFile (name , DELETE , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
130- NULL , OPEN_EXISTING , 0 , NULL );
131- if (handle != INVALID_HANDLE_VALUE )
132- {
133- BOOL ok = SetFileInformationByHandle (handle ,
134- (FILE_INFO_BY_HANDLE_CLASS ) 21 , & disp , sizeof (disp ));
135- CloseHandle (handle );
136- if (ok )
114+ if (attributes & FILE_ATTRIBUTE_REPARSE_POINT )
115+ {
116+ /* Symbolic link. Delete link, the not target */
117+ if (!DeleteFile (name ))
118+ {
119+ last_error = GetLastError ();
120+ DBUG_PRINT ("error" ,
121+ ("DeleteFile(%s) failed with %u\n" , name , last_error ));
122+ goto error ;
123+ }
137124 DBUG_RETURN (0 );
138- }
125+ }
139126
140- handle = CreateFile (name , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_DELETE_ON_CLOSE , NULL );
141- if (handle != INVALID_HANDLE_VALUE )
142- {
143127 /*
144- We opened file without sharing flags (exclusive), no one else has this file
145- opened, thus it is save to close handle to remove it. No renaming is
146- necessary.
128+ Try Windows 10 method, delete with "posix semantics" ( file is not
129+ visible, and creating a file with the same name won't fail, even if it
130+ the file was open)
147131 */
148- CloseHandle (handle );
149- DBUG_RETURN (0 );
150- }
132+ handle = CreateFile (name , DELETE ,
133+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
134+ NULL , OPEN_EXISTING , 0 , NULL );
135+ if (handle != INVALID_HANDLE_VALUE )
136+ {
137+ /* 0x3 = FILE_DISPOSITION_FLAG_DELETE | FILE_DISPOSITION_FLAG_POSIX_SEMANTICS */
138+ struct {DWORD _Flags ;} disp = {0x3 };
139+ BOOL ok = SetFileInformationByHandle (
140+ handle , (FILE_INFO_BY_HANDLE_CLASS ) 21 , & disp , sizeof (disp ));
141+ CloseHandle (handle );
142+ if (ok )
143+ DBUG_RETURN (0 );
144+ }
151145
152- /*
153- Can't open file exclusively, hence the file must be already opened by
154- someone else. Open it for delete (with all FILE_SHARE flags set),
155- rename to unique name, close.
156- */
157- handle = CreateFile (name , DELETE , FILE_SHARE_READ |FILE_SHARE_WRITE |FILE_SHARE_DELETE ,
158- NULL , OPEN_EXISTING , FILE_FLAG_DELETE_ON_CLOSE , NULL );
159- if (handle == INVALID_HANDLE_VALUE )
160- {
161- last_error = GetLastError ();
162- DBUG_PRINT ("error" ,
163- ("CreateFile(%s) with FILE_FLAG_DELETE_ON_CLOSE failed with %u\n" ,
164- name ,last_error ));
165- goto error ;
166- }
146+ handle = CreateFile (name , DELETE , 0 , NULL , OPEN_EXISTING ,
147+ FILE_FLAG_DELETE_ON_CLOSE , NULL );
148+ if (handle != INVALID_HANDLE_VALUE )
149+ {
150+ /*
151+ We opened file without sharing flags (exclusive), no one else has this
152+ file opened, thus it is safe to close handle to remove it. No renaming
153+ is necessary.
154+ */
155+ CloseHandle (handle );
156+ DBUG_RETURN (0 );
157+ }
167158
168- tsc = __rdtsc ();
169- my_snprintf (unique_filename ,sizeof (unique_filename ),"%s.%llx.deleted" ,
170- name , tsc );
171- if (!MoveFile (name , unique_filename ))
172- {
173- DBUG_PRINT ("warning" , ("moving %s to unique filename failed, error %lu\n" ,
174- name ,GetLastError ()));
175- }
159+ /*
160+ Can't open file exclusively, hence the file must be already opened by
161+ someone else. Open it for delete (with all FILE_SHARE flags set),
162+ rename to unique name, close.
163+ */
164+ handle = CreateFile (name , DELETE ,
165+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
166+ NULL , OPEN_EXISTING , FILE_FLAG_DELETE_ON_CLOSE , NULL );
167+ if (handle == INVALID_HANDLE_VALUE )
168+ {
169+ last_error = GetLastError ();
170+ DBUG_PRINT (
171+ "error" ,
172+ ("CreateFile(%s) with FILE_FLAG_DELETE_ON_CLOSE failed with %u\n" ,
173+ name , last_error ));
174+ goto error ;
175+ }
176+
177+ tsc = __rdtsc ();
178+ my_snprintf (unique_filename , sizeof (unique_filename ), "%s.%llx.deleted" ,
179+ name , tsc );
180+ if (!MoveFile (name , unique_filename ))
181+ {
182+ DBUG_PRINT ("warning" ,
183+ ("moving %s to unique filename failed, error %lu\n" , name ,
184+ GetLastError ()));
185+ }
186+ CloseHandle (handle );
187+ DBUG_RETURN (0 );
176188
177- CloseHandle (handle );
178- DBUG_RETURN (0 );
179-
180189error :
181- my_osmaperr (last_error );
182- DBUG_RETURN (-1 );
190+ if (last_error != ERROR_SHARING_VIOLATION || retries == 0 )
191+ {
192+ my_osmaperr (last_error );
193+ DBUG_RETURN (-1 );
194+ }
195+ DBUG_CLEAR_FILE_SHARING_VIOLATION ();
196+ Sleep (FILE_SHARING_VIOLATION_DELAY_MS );
197+ }
183198}
184199#endif
185200
0 commit comments