@@ -79,107 +79,122 @@ int my_delete(const char *name, myf MyFlags)
79
79
a file to unique name.
80
80
81
81
Symbolic link are deleted without renaming. Directories are not deleted.
82
- */
82
+ */
83
+
83
84
static int my_win_unlink (const char * name )
84
85
{
85
86
HANDLE handle = INVALID_HANDLE_VALUE ;
86
87
DWORD attributes ;
87
88
uint last_error ;
88
89
char unique_filename [MAX_PATH + 35 ];
89
90
unsigned long long tsc ; /* time stamp counter, for unique filename*/
90
-
91
+ int retries ;
91
92
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
- }
99
93
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 -- )
108
97
{
109
- /* Symbolic link. Delete link, the not target */
110
- if (! DeleteFile ( name ) )
98
+ attributes = GetFileAttributes ( name );
99
+ if (attributes == INVALID_FILE_ATTRIBUTES )
111
100
{
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 ;
115
105
}
116
- DBUG_RETURN (0 );
117
- }
118
106
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
+ }
128
113
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
+ }
137
124
DBUG_RETURN (0 );
138
- }
125
+ }
139
126
140
- handle = CreateFile (name , DELETE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_DELETE_ON_CLOSE , NULL );
141
- if (handle != INVALID_HANDLE_VALUE )
142
- {
143
127
/*
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)
147
131
*/
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
+ }
151
145
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
+ }
167
158
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 );
176
188
177
- CloseHandle (handle );
178
- DBUG_RETURN (0 );
179
-
180
189
error :
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
+ }
183
198
}
184
199
#endif
185
200
0 commit comments