| ︙ | | | ︙ | |
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#endif
#ifndef LABEL_SECURITY_INFORMATION
# define LABEL_SECURITY_INFORMATION (0x00000010L)
#endif
#ifndef FSCTL_GET_REPARSE_POINT
# define FSCTL_GET_REPARSE_POINT (((0x00000009) << 16) | ((0x00000000) << 14) | ((42) << 2) | (0))
#endif
static HANDLE dllhandle = NULL;
static DWORD (WINAPI *getFinalPathNameByHandleW) (HANDLE, LPWSTR, DWORD, DWORD) = NULL;
static BOOLEAN (APIENTRY *createSymbolicLinkW) (LPCWSTR, LPCWSTR, DWORD) = NULL;
/* a couple defines to make the borrowed struct below compile */
|
|
|
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#endif
#ifndef LABEL_SECURITY_INFORMATION
# define LABEL_SECURITY_INFORMATION (0x00000010L)
#endif
#ifndef FSCTL_GET_REPARSE_POINT
# define FSCTL_GET_REPARSE_POINT (((0x00000009) << 16) | ((0x00000000) << 14) | ((42) << 2) | (0))
#endif
static HANDLE dllhandle = NULL;
static DWORD (WINAPI *getFinalPathNameByHandleW) (HANDLE, LPWSTR, DWORD, DWORD) = NULL;
static BOOLEAN (APIENTRY *createSymbolicLinkW) (LPCWSTR, LPCWSTR, DWORD) = NULL;
/* a couple defines to make the borrowed struct below compile */
|
| ︙ | | | ︙ | |
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
int rc = GetFileAttributesExW(zFilename, GetFileExInfoStandard, &attr);
if( rc ){
ssize_t tlen = 0; /* assume it is not a symbolic link */
/* if it is a reparse point it *might* be a symbolic link */
/* so defer to win32_readlink to actually check */
if( attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ){
char *tname = fossil_filename_to_utf8(zFilename);
char tlink[LINK_BUFFER_SIZE];
tlen = win32_readlink(tname, tlink, sizeof(tlink));
fossil_filename_free(tname);
}
ULARGE_INTEGER ull;
/* if a link was retrieved, it is a symlink, otherwise a dir or file */
if( tlen == 0 ){
buf->st_mode = ((attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
|
|
|
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
int rc = GetFileAttributesExW(zFilename, GetFileExInfoStandard, &attr);
if( rc ){
ssize_t tlen = 0; /* assume it is not a symbolic link */
/* if it is a reparse point it *might* be a symbolic link */
/* so defer to win32_readlink to actually check */
if( attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ){
char *tname = fossil_path_to_utf8(zFilename);
char tlink[LINK_BUFFER_SIZE];
tlen = win32_readlink(tname, tlink, sizeof(tlink));
fossil_path_free(tname);
}
ULARGE_INTEGER ull;
/* if a link was retrieved, it is a symlink, otherwise a dir or file */
if( tlen == 0 ){
buf->st_mode = ((attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
| ︙ | | | ︙ | |
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
USHORT
offset = data->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(wchar_t),
length = data->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t);
char *temp;
data->SymbolicLinkReparseBuffer.PathBuffer[offset + length] = 0;
/* convert the filename to utf8, copy it, and discard the converted copy */
temp = fossil_filename_to_utf8(data->SymbolicLinkReparseBuffer.PathBuffer + offset);
rv = strlen(temp);
if( rv >= bufsiz )
rv = bufsiz;
memcpy(buf, temp, rv);
fossil_filename_free(temp);
}
fossil_free(data);
/* all done, close the reparse point */
CloseHandle(file);
}
|
|
|
|
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
USHORT
offset = data->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(wchar_t),
length = data->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t);
char *temp;
data->SymbolicLinkReparseBuffer.PathBuffer[offset + length] = 0;
/* convert the filename to utf8, copy it, and discard the converted copy */
temp = fossil_path_to_utf8(data->SymbolicLinkReparseBuffer.PathBuffer + offset);
rv = strlen(temp);
if( rv >= bufsiz )
rv = bufsiz;
memcpy(buf, temp, rv);
fossil_path_free(temp);
}
fossil_free(data);
/* all done, close the reparse point */
CloseHandle(file);
}
|
| ︙ | | | ︙ | |
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
|
int win32_symlink(const char *oldpath, const char *newpath){
fossilStat stat;
int created = 0;
DWORD flags = 0;
wchar_t *zMbcs, *zMbcsOld;
/* does oldpath exist? is it a dir or a file? */
zMbcsOld = fossil_utf8_to_filename(oldpath);
if( win32_stat(zMbcsOld, &stat) == 0 ){
if( stat.st_mode == S_IFDIR ){
flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
}
}
/* remove newpath before creating the symlink */
zMbcs = fossil_utf8_to_filename(newpath);
win32_unlink_rmdir(zMbcs);
if( isVistaOrLater() ){
created = createSymbolicLinkW(zMbcs, zMbcsOld, flags);
}
fossil_filename_free(zMbcs);
fossil_filename_free(zMbcsOld);
/* if the symlink was not created, create a plain text file */
if( !created ){
Blob content;
blob_set(&content, oldpath);
blob_write_to_file(&content, newpath);
blob_reset(&content);
|
|
|
|
|
|
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
|
int win32_symlink(const char *oldpath, const char *newpath){
fossilStat stat;
int created = 0;
DWORD flags = 0;
wchar_t *zMbcs, *zMbcsOld;
/* does oldpath exist? is it a dir or a file? */
zMbcsOld = fossil_utf8_to_path(oldpath, 0);
if( win32_stat(zMbcsOld, &stat) == 0 ){
if( stat.st_mode == S_IFDIR ){
flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
}
}
/* remove newpath before creating the symlink */
zMbcs = fossil_utf8_to_path(newpath, 0);
win32_unlink_rmdir(zMbcs);
if( isVistaOrLater() ){
created = createSymbolicLinkW(zMbcs, zMbcsOld, flags);
}
fossil_path_free(zMbcs);
fossil_path_free(zMbcsOld);
/* if the symlink was not created, create a plain text file */
if( !created ){
Blob content;
blob_set(&content, oldpath);
blob_write_to_file(&content, newpath);
blob_reset(&content);
|
| ︙ | | | ︙ | |
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
** 4. the symbolic link type is different than the target type
*/
int win32_check_symlink_type_changed(const char* zName){
int changed = 0;
wchar_t* zMbcs;
fossilStat lstat_buf, stat_buf;
WIN32_FILE_ATTRIBUTE_DATA lstat_attr;
zMbcs = fossil_utf8_to_filename(zName);
if( win32_stat(zMbcs, &stat_buf) != 0 ){
stat_buf.st_mode = S_IFREG;
}
changed =
(win32_lstat(zMbcs, &lstat_buf) == 0) &&
(lstat_buf.st_mode == S_IFLNK) &&
GetFileAttributesExW(zMbcs, GetFileExInfoStandard, &lstat_attr) &&
((stat_buf.st_mode == S_IFDIR) != ((lstat_attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY));
fossil_filename_free(zMbcs);
return changed;
}
/*
** Check if symlinks are potentially supported on the current OS for the given file.
** Theoretically this code should work on any NT based version of windows
** but I have no way of testing that. The initial check for
|
|
|
|
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
** 4. the symbolic link type is different than the target type
*/
int win32_check_symlink_type_changed(const char* zName){
int changed = 0;
wchar_t* zMbcs;
fossilStat lstat_buf, stat_buf;
WIN32_FILE_ATTRIBUTE_DATA lstat_attr;
zMbcs = fossil_utf8_to_path(zName, 0);
if( win32_stat(zMbcs, &stat_buf) != 0 ){
stat_buf.st_mode = S_IFREG;
}
changed =
(win32_lstat(zMbcs, &lstat_buf) == 0) &&
(lstat_buf.st_mode == S_IFLNK) &&
GetFileAttributesExW(zMbcs, GetFileExInfoStandard, &lstat_attr) &&
((stat_buf.st_mode == S_IFDIR) != ((lstat_attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY));
fossil_path_free(zMbcs);
return changed;
}
/*
** Check if symlinks are potentially supported on the current OS for the given file.
** Theoretically this code should work on any NT based version of windows
** but I have no way of testing that. The initial check for
|
| ︙ | | | ︙ | |
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
|
if( status != ERROR_SUCCESS ){
return 0;
}
/* assume no support for symlinks */
success = 0;
pFilename = fossil_utf8_to_filename(zFilename);
/* given the filename we're interested in, symlinks are supported if */
/* 1. we can get the full name of the path from the given path */
fullLength = GetFullPathNameW(pFilename, sizeof(fullName), fullName, NULL);
if( (fullLength > 0) && (fullLength < sizeof(fullName)) ){
/* 2. we can get the volume path name from the full name */
if( GetVolumePathNameW(fullName, volName, sizeof(volName)) ){
/* 3. we can get volume information from the volume path name */
if( GetVolumeInformationW(volName, NULL, 0, NULL, NULL, &fsFlags, NULL, 0) ){
/* 4. the given volume support reparse points */
if( fsFlags & FILE_SUPPORTS_REPARSE_POINTS ){
/* all four conditions were true, so we support symlinks; success! */
success = 1;
}
}
}
}
fossil_filename_free(pFilename);
return success;
}
/*
** Wrapper around the access() system call. This code was copied from Tcl
** 8.6 and then modified.
|
|
|
|
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
|
if( status != ERROR_SUCCESS ){
return 0;
}
/* assume no support for symlinks */
success = 0;
pFilename = fossil_utf8_to_path(zFilename, 0);
/* given the filename we're interested in, symlinks are supported if */
/* 1. we can get the full name of the path from the given path */
fullLength = GetFullPathNameW(pFilename, sizeof(fullName), fullName, NULL);
if( (fullLength > 0) && (fullLength < sizeof(fullName)) ){
/* 2. we can get the volume path name from the full name */
if( GetVolumePathNameW(fullName, volName, sizeof(volName)) ){
/* 3. we can get volume information from the volume path name */
if( GetVolumeInformationW(volName, NULL, 0, NULL, NULL, &fsFlags, NULL, 0) ){
/* 4. the given volume support reparse points */
if( fsFlags & FILE_SUPPORTS_REPARSE_POINTS ){
/* all four conditions were true, so we support symlinks; success! */
success = 1;
}
}
}
}
fossil_path_free(pFilename);
return success;
}
/*
** Wrapper around the access() system call. This code was copied from Tcl
** 8.6 and then modified.
|
| ︙ | | | ︙ | |
652
653
654
655
656
657
658
659
660
661
662
663
664
665
|
void win32_getcwd(char *zBuf, int nBuf){
int i;
char *zUtf8;
wchar_t *zWide = fossil_malloc( sizeof(wchar_t)*nBuf );
if( GetCurrentDirectoryW(nBuf, zWide)==0 ){
fossil_fatal("cannot find current working directory.");
}
zUtf8 = fossil_filename_to_utf8(zWide);
fossil_free(zWide);
for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/';
strncpy(zBuf, zUtf8, nBuf);
fossil_filename_free(zUtf8);
}
#endif /* _WIN32 -- This code is for win32 only */
|
|
|
|
652
653
654
655
656
657
658
659
660
661
662
663
664
665
|
void win32_getcwd(char *zBuf, int nBuf){
int i;
char *zUtf8;
wchar_t *zWide = fossil_malloc( sizeof(wchar_t)*nBuf );
if( GetCurrentDirectoryW(nBuf, zWide)==0 ){
fossil_fatal("cannot find current working directory.");
}
zUtf8 = fossil_path_to_utf8(zWide);
fossil_free(zWide);
for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/';
strncpy(zBuf, zUtf8, nBuf);
fossil_path_free(zUtf8);
}
#endif /* _WIN32 -- This code is for win32 only */
|