summaryrefslogtreecommitdiff
path: root/src/LibraryFiles.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/LibraryFiles.vala')
-rw-r--r--src/LibraryFiles.vala104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/LibraryFiles.vala b/src/LibraryFiles.vala
new file mode 100644
index 0000000..4cffe94
--- /dev/null
+++ b/src/LibraryFiles.vala
@@ -0,0 +1,104 @@
+/* Copyright 2009-2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+namespace LibraryFiles {
+
+// This method uses global::generate_unique_file_at in order to "claim" a file in the filesystem.
+// Thus, when the method returns success a file may exist already, and should be overwritten.
+//
+// This function is thread safe.
+public File? generate_unique_file(string basename, MediaMetadata? metadata, time_t ts, out bool collision)
+ throws Error {
+ // use exposure timestamp over the supplied one (which probably comes from the file's
+ // modified time, or is simply time()), unless it's zero, in which case use current time
+
+ time_t timestamp = ts;
+ if (metadata != null) {
+ MetadataDateTime? date_time = metadata.get_creation_date_time();
+ if (date_time != null)
+ timestamp = date_time.get_timestamp();
+ else if (timestamp == 0)
+ timestamp = time_t();
+ }
+
+ // build a directory tree inside the library
+ File dir = AppDirs.get_baked_import_dir(timestamp);
+ try {
+ dir.make_directory_with_parents(null);
+ } catch (Error err) {
+ if (!(err is IOError.EXISTS))
+ throw err;
+
+ // silently ignore not creating a directory that already exists
+ }
+
+ // Optionally convert to lower-case.
+ string newbasename = basename;
+ if (Config.Facade.get_instance().get_use_lowercase_filenames())
+ newbasename = newbasename.down();
+
+ return global::generate_unique_file(dir, newbasename, out collision);
+}
+
+// This function is thread-safe.
+private File duplicate(File src, FileProgressCallback? progress_callback, bool blacklist) throws Error {
+ time_t timestamp = 0;
+ try {
+ timestamp = query_file_modified(src);
+ } catch (Error err) {
+ critical("Unable to access file modification for %s: %s", src.get_path(), err.message);
+ }
+
+ MediaMetadata? metadata = null;
+ if (VideoReader.is_supported_video_file(src)) {
+ VideoReader reader = new VideoReader(src);
+ try {
+ metadata = reader.read_metadata();
+ } catch (Error err) {
+ // ignored, leave metadata as null
+ }
+ } else {
+ PhotoFileReader reader = PhotoFileFormat.get_by_file_extension(src).create_reader(
+ src.get_path());
+ try {
+ metadata = reader.read_metadata();
+ } catch (Error err) {
+ // ignored, leave metadata as null
+ }
+ }
+
+ bool collision;
+ File? dest = generate_unique_file(src.get_basename(), metadata, timestamp, out collision);
+ if (dest == null)
+ throw new FileError.FAILED("Unable to generate unique pathname for destination");
+
+ if (blacklist)
+ LibraryMonitor.blacklist_file(dest, "LibraryFiles.duplicate");
+
+ try {
+ src.copy(dest, FileCopyFlags.ALL_METADATA | FileCopyFlags.OVERWRITE, null, progress_callback);
+ if (blacklist)
+ LibraryMonitor.unblacklist_file(dest);
+ } catch (Error err) {
+ message("There was a problem copying %s: %s", src.get_path(), err.message);
+ if (blacklist && (md5_file(src) != md5_file(dest)))
+ LibraryMonitor.unblacklist_file(dest);
+ }
+
+ // Make file writable by getting current Unix mode and or it with 600 (user read/write)
+ try {
+ FileInfo info = dest.query_info(FileAttribute.UNIX_MODE, FileQueryInfoFlags.NONE);
+ uint32 mode = info.get_attribute_uint32(FileAttribute.UNIX_MODE) | 0600;
+ if (!dest.set_attribute_uint32(FileAttribute.UNIX_MODE, mode, FileQueryInfoFlags.NONE)) {
+ warning("Could not make file writable");
+ }
+ } catch (Error err) {
+ warning("Could not make file writable: %s", err.message);
+ }
+
+ return dest;
+}
+}