fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / find_session.cc
1 /*
2     Copyright (C) 2012 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <unistd.h>
21
22 #include <cstring>
23 #include <climits>
24 #include <cerrno>
25
26 #include "pbd/gstdio_compat.h"
27
28 #include <glibmm/miscutils.h>
29
30 #include "pbd/compose.h"
31 #include "pbd/pathexpand.h"
32 #include "pbd/error.h"
33
34 #include "ardour/filename_extensions.h"
35 #include "ardour/utils.h"
36 #include "ardour/session_utils.h"
37
38 #include "pbd/i18n.h"
39
40 using namespace std;
41 using namespace PBD;
42
43 namespace ARDOUR {
44
45 int
46 find_session (string str, string& path, string& snapshot, bool& isnew)
47 {
48         GStatBuf statbuf;
49
50         isnew = false;
51
52         str = canonical_path (str);
53
54         /* check to see if it exists, and what it is */
55
56         if (g_stat (str.c_str(), &statbuf)) {
57                 if (errno == ENOENT) {
58                         isnew = true;
59                 } else {
60                         error << string_compose (_("cannot check session path %1 (%2)"), str, strerror (errno))
61                               << endmsg;
62                         return -1;
63                 }
64         }
65
66         if (!isnew) {
67
68                 /* it exists, so it must either be the name
69                    of the directory, or the name of the statefile
70                    within it.
71                 */
72
73                 if (S_ISDIR (statbuf.st_mode)) {
74
75                         string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
76
77                         if (slash == string::npos) {
78
79                                 /* a subdirectory of cwd, so statefile should be ... */
80
81                                 string tmp = Glib::build_filename (str, str+statefile_suffix);
82
83                                 /* is it there ? */
84
85                                 if (g_stat (tmp.c_str(), &statbuf)) {
86                                         error << string_compose (_("cannot check statefile %1 (%2)"), tmp, strerror (errno))
87                                               << endmsg;
88                                         return -1;
89                                 }
90
91                                 path = str;
92                                 snapshot = str;
93
94                         } else {
95
96                                 /* some directory someplace in the filesystem.
97                                    the snapshot name is the directory name
98                                    itself.
99                                 */
100
101                                 path = str;
102                                 snapshot = str.substr (slash+1);
103
104                         }
105
106                 } else if (S_ISREG (statbuf.st_mode)) {
107
108                         string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
109                         string::size_type suffix;
110
111                         /* remove the suffix */
112
113                         if (slash != string::npos) {
114                                 snapshot = str.substr (slash+1);
115                         } else {
116                                 snapshot = str;
117                         }
118
119                         suffix = snapshot.find (statefile_suffix);
120
121                         const string::size_type start_pos_of_extension = snapshot.size () - strlen (statefile_suffix);
122                         // we should check the start of extension position
123                         // because files '*.ardour.bak' are possible
124                         if (suffix != start_pos_of_extension) {
125                                 error << string_compose (_("%1 is not a snapshot file"), str) << endmsg;
126                                 return -1;
127                         }
128
129                         /* remove suffix */
130
131                         snapshot = snapshot.substr (0, suffix);
132
133                         if (slash == string::npos) {
134
135                                 /* we must be in the directory where the
136                                    statefile lives. get it using cwd().
137                                 */
138
139                                 char cwd[PATH_MAX+1];
140
141                                 if (getcwd (cwd, sizeof (cwd)) == 0) {
142                                         error << string_compose (_("cannot determine current working directory (%1)"), strerror (errno))
143                                               << endmsg;
144                                         return -1;
145                                 }
146
147                                 path = cwd;
148
149                         } else {
150
151                                 /* full path to the statefile */
152
153                                 path = str.substr (0, slash);
154                         }
155
156                 } else {
157
158                         /* what type of file is it? */
159                         error << string_compose (_("unknown file type for session %1"), str) << endmsg;
160                         return -1;
161                 }
162
163         } else {
164
165                 /* its the name of a new directory. get the name
166                    as "dirname" does.
167                 */
168
169                 string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
170
171                 if (slash == string::npos) {
172
173                         /* no slash, just use the name, but clean it up */
174
175                         path = legalize_for_path (str);
176                         snapshot = path;
177
178                 } else {
179
180                         path = str;
181                         snapshot = str.substr (slash+1);
182                 }
183         }
184
185         return 0;
186 }
187
188 }  // namespace ARDOUR