vio local: Use win32 native functions to traverse the file tree.

Native functions to replace the not native readdir and opendir functions.
This works with long filenames now.
This commit is contained in:
Klaas Freitag 2015-06-19 16:10:48 +02:00
parent 5caff8cc93
commit 2b391396c6

View file

@ -56,17 +56,48 @@ typedef struct dhandle_s {
csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
dhandle_t *handle = NULL;
mbchar_t *dirname = c_utf8_to_locale(name);
mbchar_t *dirname = NULL;
handle = c_malloc(sizeof(dhandle_t));
#ifdef _WIN32
// the file wildcard has to be attached
int len_name = strlen(name);
if( len_name ) {
char *h = NULL;
// alloc an enough large buffer to take the name + '/*' + the closing zero.
h = c_malloc(len_name+3);
strcpy( h, name);
strcat(h, "/*");
dirname = c_utf8_to_locale(h);
SAFE_FREE(h);
}
if( dirname ) {
handle->hFind = FindFirstFile(dirname, &(handle->ffd));
}
if (!dirname || handle->hFind == INVALID_HANDLE_VALUE) {
SAFE_FREE(handle);
return NULL;
}
// FIXME: Handle the case of no files in a dir.
// dwError = GetLastError();
// if (dwError != ERROR_NO_MORE_FILES) {
handle->firstFind = 1; // Set a flag that there first fileinfo is available.
// }
#else
dirname = c_utf8_to_locale(name);
handle->dh = _topendir( dirname );
if (handle->dh == NULL) {
c_free_locale_string(dirname);
SAFE_FREE(handle);
return NULL;
}
#endif
handle->path = c_strdup(name);
c_free_locale_string(dirname);
@ -83,7 +114,14 @@ int csync_vio_local_closedir(csync_vio_handle_t *dhandle) {
}
handle = (dhandle_t *) dhandle;
#ifdef _WIN32
// FindClose returns non-zero on success
if( FindClose(handle->hFind) != 0 ) {
rc = 0;
}
#else
rc = _tclosedir(handle->dh);
#endif
SAFE_FREE(handle->path);
SAFE_FREE(handle);
@ -100,6 +138,39 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
handle = (dhandle_t *) dhandle;
errno = 0;
file_stat = csync_vio_file_stat_new();
if (file_stat == NULL) {
goto err;
}
file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
#ifdef _WIN32
// the win32 functions get the first valid entry with the opendir
// thus we must not jump to next entry if it was the first find.
if( handle->firstFind ) {
handle->firstFind = 0;
} else {
if( FindNextFile(handle->hFind, &(handle->ffd)) == 0 ) {
// might be error, check!
int dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES) {
errno = EACCES; // FIXME: Is this a good errno?
goto err;
} else {
// Normal case that no more is in the dir.
return NULL;
}
}
}
file_stat->name = c_utf8_from_locale(handle->ffd.cFileName);
file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
} else {
file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR;
}
#else
dirent = _treaddir(handle->dh);
if (dirent == NULL) {
if (errno) {
@ -108,14 +179,7 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
return NULL;
}
}
file_stat = csync_vio_file_stat_new();
if (file_stat == NULL) {
goto err;
}
file_stat->name = c_utf8_from_locale(dirent->d_name);
file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
/* Check for availability of d_type, see manpage. */
#ifdef _DIRENT_HAVE_D_TYPE
@ -142,6 +206,8 @@ csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
}
#endif
#endif // non WIN32
return file_stat;
err: