+/*
+ Copyright (C) 2012 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
#include <unistd.h>
-#include <sys/stat.h>
#include <cstring>
#include <climits>
#include <cerrno>
+#include "pbd/gstdio_compat.h"
+
#include <glibmm/miscutils.h>
+#include <glibmm/fileutils.h>
+#include "pbd/basename.h"
#include "pbd/compose.h"
+#include "pbd/file_archive.h"
+#include "pbd/pathexpand.h"
#include "pbd/error.h"
#include "ardour/filename_extensions.h"
#include "ardour/utils.h"
+#include "ardour/session_utils.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace std;
using namespace PBD;
int
find_session (string str, string& path, string& snapshot, bool& isnew)
{
- struct stat statbuf;
- char buf[PATH_MAX+1];
+ GStatBuf statbuf;
isnew = false;
- if (!realpath (str.c_str(), buf) && (errno != ENOENT && errno != ENOTDIR)) {
- error << string_compose (_("Could not resolve path: %1 (%2)"), buf, strerror(errno)) << endmsg;
- return -1;
- }
-
- str = buf;
+ str = canonical_path (str);
/* check to see if it exists, and what it is */
- if (stat (str.c_str(), &statbuf)) {
+ if (g_stat (str.c_str(), &statbuf)) {
if (errno == ENOENT) {
isnew = true;
} else {
/* is it there ? */
- if (stat (tmp.c_str(), &statbuf)) {
+ if (g_stat (tmp.c_str(), &statbuf)) {
error << string_compose (_("cannot check statefile %1 (%2)"), tmp, strerror (errno))
<< endmsg;
return -1;
suffix = snapshot.find (statefile_suffix);
- if (suffix == string::npos) {
+ const string::size_type start_pos_of_extension = snapshot.size () - strlen (statefile_suffix);
+ // we should check the start of extension position
+ // because files '*.ardour.bak' are possible
+ if (suffix != start_pos_of_extension) {
error << string_compose (_("%1 is not a snapshot file"), str) << endmsg;
return -1;
}
return 0;
}
+/* check if zip is a session-archive,
+ * return > 0 if file is not an archive
+ * return < 0 if unzip failed
+ * return 0 on success. path and snapshot are set.
+ */
+int
+inflate_session (const std::string& zipfile, const std::string& target_dir, string& path, string& snapshot)
+{
+ if (zipfile.find (session_archive_suffix) == string::npos) {
+ return 1;
+ }
+
+ try {
+ PBD::FileArchive ar (zipfile);
+ std::vector<std::string> files = ar.contents ();
+
+ if (files.size () == 0) {
+ error << _("Archive is empty") << endmsg;
+ return 2;
+ }
+
+ /* session archives are expected to be named after the archive */
+ std::string bn = Glib::path_get_dirname (files.front());
+ if (bn.empty ()) {
+ error << _("Archive does not contain a session folder") << endmsg;
+ return 3;
+ }
+
+ size_t sep = bn.find_first_of ('/');
+
+ if (sep != string::npos) {
+ bn = bn.substr (0, sep);
+ }
+
+ if (bn.empty ()) {
+ error << _("Archive does not contain a valid session structure") << endmsg;
+ return 4;
+ }
+
+ string sn = Glib::build_filename (bn, bn + statefile_suffix);
+
+ if (std::find (files.begin(), files.end(), sn) == files.end()) {
+ error << _("Archive does not contain a session file") << endmsg;
+ return 5;
+ }
+
+ /* check if target folder exists */
+ string dest = Glib::build_filename (target_dir, bn);
+ if (Glib::file_test (dest, Glib::FILE_TEST_EXISTS)) {
+ error << string_compose (_("Destination '%1' already exists."), dest) << endmsg;
+ return -1;
+ }
+
+ if (0 == ar.inflate (target_dir)) {
+ info << string_compose (_("Extracted session-archive to '%1'."), dest) << endmsg;
+ path = dest;
+ snapshot = bn;
+ return 0;
+ }
+
+ } catch (...) {
+ error << _("Error reading file-archive") << endmsg;
+ return 6;
+ }
+
+ error << _("Error extracting file-archive") << endmsg;
+ return -2;
+}
+
+string inflate_error (int e) {
+ switch (e) {
+ case 0:
+ return _("No Error");
+ case 1:
+ return string_compose (_("File extension is not %1"), session_archive_suffix);
+ case 2:
+ return _("Archive is empty");
+ case 3:
+ return _("Archive does not contain a session folder");
+ case 4:
+ return _("Archive does not contain a valid session structure");
+ case 5:
+ return _("Archive does not contain a session file");
+ case 6:
+ return _("Error reading file-archive");
+ case -1:
+ return _("Destination folder already exists.");
+ case -2:
+ return _("Error extracting file-archive");
+ default:
+ assert (0);
+ break;
+ }
+ return _("Unknown Error");
+}
+
} // namespace ARDOUR