static bool preallocate_file_sparse (tr_sys_file_t fd, uint64_t length, tr_error ** error) { tr_error * my_error = NULL; if (length == 0) return true; if (tr_sys_file_preallocate (fd, length, TR_SYS_FILE_PREALLOC_SPARSE, &my_error)) return true; dbgmsg ("Preallocating (sparse, normal) failed (%d): %s", my_error->code, my_error->message); if (!TR_ERROR_IS_ENOSPC (my_error->code)) { const char zero = '\0'; tr_error_clear (&my_error); /* fallback: the old-style seek-and-write */ if (tr_sys_file_write_at (fd, &zero, 1, length - 1, NULL, &my_error) && tr_sys_file_truncate (fd, length, &my_error)) return true; dbgmsg ("Preallocating (sparse, fallback) failed (%d): %s", my_error->code, my_error->message); } tr_error_propagate (error, &my_error); return false; }
static int test_error_set (void) { tr_error * err = NULL; tr_error_prefix (&err, "error: "); check (err == NULL); tr_error_set (&err, 1, "error: %s (%d)", "oops", 2); check (err != NULL); check_int_eq (1, err->code); check_streq ("error: oops (2)", err->message); tr_error_clear (&err); check (err == NULL); tr_error_set_literal (&err, 2, "oops"); check (err != NULL); check_int_eq (2, err->code); check_streq ("oops", err->message); tr_error_prefix (&err, "error: "); check (err != NULL); check_int_eq (2, err->code); check_streq ("error: oops", err->message); tr_error_free (err); return 0; }
static int test_path_xname (const struct xname_test_data * data, size_t data_size, char * (* func) (const char *, tr_error **)) { for (size_t i = 0; i < data_size; ++i) { tr_error * err = NULL; char * name = func (data[i].input, &err); if (data[i].output != NULL) { check (name != NULL); check (err == NULL); check_streq (data[i].output, name); tr_free (name); } else { check (name == NULL); check (err != NULL); tr_error_clear (&err); } } return 0; }
static void create_temp_path (char * path_template, void (* callback) (const char * path, void * param, tr_error ** error), void * callback_param, tr_error ** error) { char * path; size_t path_size; int attempt; tr_error * my_error = NULL; assert (path_template != NULL); assert (callback != NULL); path = tr_strdup (path_template); path_size = strlen (path); assert (path_size > 0); for (attempt = 0; attempt < 100; ++attempt) { size_t i = path_size; while (i > 0 && path_template[i - 1] == 'X') { const int c = tr_rand_int (26 + 26 + 10); path[i - 1] = c < 26 ? c + 'A' : (c < 26 + 26 ? (c - 26) + 'a' : (c - 26 - 26) + '0'); --i; } assert (path_size >= i + 6); tr_error_clear (&my_error); (*callback) (path, callback_param, &my_error); if (my_error == NULL) break; } if (my_error != NULL) tr_error_propagate(error, &my_error); else memcpy (path_template, path, path_size); tr_free (path); }
bool gtr_file_trash_or_remove (const char * filename, tr_error ** error) { GFile * file; gboolean trashed = FALSE; bool result = true; g_return_val_if_fail (filename && *filename, false); file = g_file_new_for_path (filename); if (gtr_pref_flag_get (TR_KEY_trash_can_enabled)) { GError * err = NULL; trashed = g_file_trash (file, NULL, &err); if (err) { g_message ("Unable to trash file \"%s\": %s", filename, err->message); tr_error_set_literal (error, err->code, err->message); g_clear_error (&err); } } if (!trashed) { GError * err = NULL; g_file_delete (file, NULL, &err); if (err) { g_message ("Unable to delete file \"%s\": %s", filename, err->message); tr_error_clear (error); tr_error_set_literal (error, err->code, err->message); g_clear_error (&err); result = false; } } g_object_unref (G_OBJECT (file)); return result; }
static bool preallocate_file_full (tr_sys_file_t fd, uint64_t length, tr_error ** error) { tr_error * my_error = NULL; if (length == 0) return true; if (tr_sys_file_preallocate (fd, length, 0, &my_error)) return true; dbgmsg ("Preallocating (full, normal) failed (%d): %s", my_error->code, my_error->message); if (!TR_ERROR_IS_ENOSPC (my_error->code)) { uint8_t buf[4096]; bool success = true; memset (buf, 0, sizeof (buf)); tr_error_clear (&my_error); /* fallback: the old-fashioned way */ while (success && length > 0) { const uint64_t thisPass = MIN (length, sizeof (buf)); uint64_t bytes_written; success = tr_sys_file_write (fd, buf, thisPass, &bytes_written, &my_error); length -= bytes_written; } if (success) return true; dbgmsg ("Preallocating (full, fallback) failed (%d): %s", my_error->code, my_error->message); } tr_error_propagate (error, &my_error); return false; }
static int test_get_info (void) { char * const test_dir = create_test_dir (__FUNCTION__); tr_sys_path_info info; tr_sys_file_t fd; tr_error * err = NULL; char * path1, * path2; time_t t; path1 = tr_buildPath (test_dir, "a", NULL); path2 = tr_buildPath (test_dir, "b", NULL); /* Can't get info of non-existent file/directory */ check (!tr_sys_path_get_info (path1, 0, &info, &err)); check (err != NULL); tr_error_clear (&err); t = time (NULL); libtest_create_file_with_string_contents (path1, "test"); /* Good file info */ clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); /* Good file info (by handle) */ fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL); clear_path_info (&info); check (tr_sys_file_get_info (fd, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_file_close (fd, NULL); tr_sys_path_remove (path1, NULL); /* Good directory info */ t = time (NULL); tr_sys_dir_create (path1, 0, 0777, NULL); clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type); check (info.size != (uint64_t) -1); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_path_remove (path1, NULL); if (create_symlink (path1, path2, false)) { /* Can't get info of non-existent file/directory */ check (!tr_sys_path_get_info (path1, 0, &info, &err)); check (err != NULL); tr_error_clear (&err); t = time (NULL); libtest_create_file_with_string_contents (path2, "test"); /* Good file info */ clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); /* Good file info (by handle) */ fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL); clear_path_info (&info); check (tr_sys_file_get_info (fd, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_file_close (fd, NULL); tr_sys_path_remove (path2, NULL); /* Good directory info */ t = time (NULL); tr_sys_dir_create (path2, 0, 0777, NULL); clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type); check (info.size != (uint64_t) -1); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_path_remove (path2, NULL); tr_sys_path_remove (path1, NULL); } else { fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } tr_free (path2); tr_free (path1); tr_free (test_dir); return 0; }