char *d_name = NULL;
csync_vio_handle_t *dh = NULL;
csync_vio_file_stat_t *dirent = NULL;
- csync_vio_file_stat_t *fs = NULL;
csync_file_stat_t *previous_fs = NULL;
int read_from_db = 0;
int rc = 0;
/* Only for the local replica we have to stat(), for the remote one we have all data already */
if (ctx->replica == LOCAL_REPLICA) {
- fs = csync_vio_file_stat_new();
- res = csync_vio_stat(ctx, filename, fs);
+ res = csync_vio_stat(ctx, filename, dirent);
} else {
- fs = dirent;
res = 0;
}
if( res == 0) {
- switch (fs->type) {
+ switch (dirent->type) {
case CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK:
flag = CSYNC_FTW_FLAG_SLINK;
break;
previous_fs = ctx->current_fs;
/* Call walker function for each file */
- rc = fn(ctx, filename, fs, flag);
+ rc = fn(ctx, filename, dirent, flag);
/* this function may update ctx->current and ctx->read_from_db */
- /* Only for the local replica we have to destroy stat(), for the remote one it is a pointer to dirent */
- if (ctx->replica == LOCAL_REPLICA) {
- csync_vio_file_stat_destroy(fs);
- }
-
if (rc < 0) {
if (CSYNC_STATUS_IS_OK(ctx->status_code)) {
ctx->status_code = CSYNC_STATUS_UPDATE_ERROR;
return rc;
}
+
+static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder)
+{
+ long long int t = filetime->dwHighDateTime;
+ t <<= 32;
+ t += (UINT32)filetime->dwLowDateTime;
+ t -= 116444736000000000LL;
+ if (t < 0)
+ {
+ if (remainder) *remainder = 9999999 - (-t - 1) % 10000000;
+ return -1 - ((-t - 1) / 10000000);
+ }
+ else
+ {
+ if (remainder) *remainder = t % 10000000;
+ return t / 10000000;
+ }
+}
+
csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
dhandle_t *handle = NULL;
csync_vio_file_stat_t *file_stat = NULL;
+ ULARGE_INTEGER FileIndex;
+ DWORD rem;
handle = (dhandle_t *) dhandle;
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;
- }
+ if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
+ && handle->ffd.dwReserved0 & IO_REPARSE_TAG_SYMLINK) {
+ file_stat->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
+ file_stat->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
+ } else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE
+ || handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE
+ || handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
+ file_stat->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
+ } else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
+ } else {
+ file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR;
+ }
+
+ file_stat->flags = CSYNC_VIO_FILE_FLAGS_NONE;
+ /* Check for the hidden flag */
+ if( handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
+ file_stat->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
+ }
+
+ file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
+ file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
- return file_stat;
+ file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
+ file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
+
+ file_stat->atime = FileTimeToUnixTime(&handle->ffd.ftLastAccessTime, &rem);
+ file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
+
+ file_stat->mtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
+ /* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Local File MTime: %llu", (unsigned long long) buf->mtime ); */
+ file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
+
+ file_stat->ctime = FileTimeToUnixTime(&handle->ffd.ftCreationTime, &rem);
+ file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;
+
+ return file_stat;
err:
SAFE_FREE(file_stat);
return NULL;
}
-static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder)
-{
- long long int t = filetime->dwHighDateTime;
- t <<= 32;
- t += (UINT32)filetime->dwLowDateTime;
- t -= 116444736000000000LL;
- if (t < 0)
- {
- if (remainder) *remainder = 9999999 - (-t - 1) % 10000000;
- return -1 - ((-t - 1) / 10000000);
- }
- else
- {
- if (remainder) *remainder = t % 10000000;
- return t / 10000000;
- }
-}
+
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
- HANDLE h, hFind;
- FILETIME ftCreate, ftAccess, ftWrite;
+ /* Almost nothing to do since csync_vio_local_readdir already filled up most of the information
+ But we still need to fetch the file ID.
+ Possible optimisation: only fetch the file id when we need it (for new files)
+ */
+
+ HANDLE h;
BY_HANDLE_FILE_INFORMATION fileInfo;
- WIN32_FIND_DATAW FindFileData;
ULARGE_INTEGER FileIndex;
mbchar_t *wuri = c_utf8_path_to_locale( uri );
return -1;
}
- buf->flags = CSYNC_VIO_FILE_FLAGS_NONE;
- do {
- // Check first if it is a symlink (code from c_islink)
- if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- hFind = FindFirstFileW(wuri, &FindFileData );
- if (hFind != INVALID_HANDLE_VALUE) {
- if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
- (FindFileData.dwReserved0 & IO_REPARSE_TAG_SYMLINK) ) {
- buf->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
- buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
- break;
- }
- }
- FindClose(hFind);
- }
- if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DEVICE
- || fileInfo.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE
- || fileInfo.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
- buf->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
- break;
- }
- if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- buf->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
- break;
- }
- // fallthrough:
- buf->type = CSYNC_VIO_FILE_TYPE_REGULAR;
- break;
- } while (0);
-
- /* Check for the hidden flag */
- if( fileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
- buf->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
- }
-
- buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
- buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
-
- buf->device = fileInfo.dwVolumeSerialNumber;
- buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DEVICE;
-
/* Get the Windows file id as an inode replacement. */
FileIndex.HighPart = fileInfo.nFileIndexHigh;
FileIndex.LowPart = fileInfo.nFileIndexLow;
/* printf("Index: %I64i\n", FileIndex.QuadPart); */
buf->inode = FileIndex.QuadPart;
- buf->size = (fileInfo.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + fileInfo.nFileSizeLow;
- buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
-
- /* Get the file time with a win32 call rather than through stat. See
- * http://www.codeproject.com/Articles/1144/Beating-the-Daylight-Savings-Time-bug-and-getting
- * for deeper explanation.
- */
- if( GetFileTime(h, &ftCreate, &ftAccess, &ftWrite) ) {
- DWORD rem;
- buf->atime = FileTimeToUnixTime(&ftAccess, &rem);
- buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
-
- buf->mtime = FileTimeToUnixTime(&ftWrite, &rem);
- /* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Local File MTime: %llu", (unsigned long long) buf->mtime ); */
- buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
-
- buf->ctime = FileTimeToUnixTime(&ftCreate, &rem);
- buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;
- }
-
c_free_locale_string(wuri);
CloseHandle(h);
-
return 0;
}
}
-/*
- * Test for general functions (stat, chmod, chown, ...)
- */
-
-static void check_csync_vio_stat_dir(void **state)
-{
- CSYNC *csync = *state;
- csync_vio_file_stat_t *fs;
- int rc;
-
- fs = csync_vio_file_stat_new();
- assert_non_null(fs);
-
- rc = csync_vio_stat(csync, CSYNC_TEST_DIR, fs);
- assert_int_equal(rc, 0);
-
- assert_string_equal(fs->name, "csync_test");
- assert_int_equal(fs->type, CSYNC_VIO_FILE_TYPE_DIRECTORY);
-
- csync_vio_file_stat_destroy(fs);
-}
-
-static void check_csync_vio_stat_file(void **state)
-{
- CSYNC *csync = *state;
- csync_vio_file_stat_t *fs;
- int rc;
-
- fs = csync_vio_file_stat_new();
- assert_non_null(fs);
-
- rc = csync_vio_stat(csync, CSYNC_TEST_FILE, fs);
- assert_int_equal(rc, 0);
-
- assert_string_equal(fs->name, "file.txt");
- assert_int_equal(fs->type, CSYNC_VIO_FILE_TYPE_REGULAR);
-
- csync_vio_file_stat_destroy(fs);
-}
-
int torture_run_tests(void)
{
const UnitTest tests[] = {
unit_test_setup_teardown(check_csync_vio_opendir_perm, setup, teardown),
unit_test(check_csync_vio_closedir_null),
unit_test_setup_teardown(check_csync_vio_readdir, setup_dir, teardown),
-
- unit_test_setup_teardown(check_csync_vio_stat_dir, setup_dir, teardown),
- unit_test_setup_teardown(check_csync_vio_stat_file, setup_file, teardown),
};
return run_tests(tests);