Merge branch 'master' into cairocanvas
[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 #include <sys/stat.h>
22
23 #include <cstring>
24 #include <climits>
25 #include <cerrno>
26
27 #include <glibmm/miscutils.h>
28
29 #include "pbd/compose.h"
30 #include "pbd/error.h"
31
32 #include "ardour/filename_extensions.h"
33 #include "ardour/utils.h"
34 #include "ardour/session_utils.h"
35
36 #include "i18n.h"
37
38 using namespace std;
39 using namespace PBD;
40
41 namespace ARDOUR {
42
43 int
44 find_session (string str, string& path, string& snapshot, bool& isnew)
45 {
46         struct stat statbuf;
47         char buf[PATH_MAX+1];
48
49         isnew = false;
50
51         if (!realpath (str.c_str(), buf) && (errno != ENOENT && errno != ENOTDIR)) {
52                 error << string_compose (_("Could not resolve path: %1 (%2)"), buf, strerror(errno)) << endmsg;
53                 return -1;
54         }
55
56         str = buf;
57
58         /* check to see if it exists, and what it is */
59
60         if (stat (str.c_str(), &statbuf)) {
61                 if (errno == ENOENT) {
62                         isnew = true;
63                 } else {
64                         error << string_compose (_("cannot check session path %1 (%2)"), str, strerror (errno))
65                               << endmsg;
66                         return -1;
67                 }
68         }
69
70         if (!isnew) {
71
72                 /* it exists, so it must either be the name
73                    of the directory, or the name of the statefile
74                    within it.
75                 */
76
77                 if (S_ISDIR (statbuf.st_mode)) {
78
79                         string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
80
81                         if (slash == string::npos) {
82
83                                 /* a subdirectory of cwd, so statefile should be ... */
84
85                                 string tmp = Glib::build_filename (str, str+statefile_suffix);
86
87                                 /* is it there ? */
88
89                                 if (stat (tmp.c_str(), &statbuf)) {
90                                         error << string_compose (_("cannot check statefile %1 (%2)"), tmp, strerror (errno))
91                                               << endmsg;
92                                         return -1;
93                                 }
94
95                                 path = str;
96                                 snapshot = str;
97
98                         } else {
99
100                                 /* some directory someplace in the filesystem.
101                                    the snapshot name is the directory name
102                                    itself.
103                                 */
104
105                                 path = str;
106                                 snapshot = str.substr (slash+1);
107
108                         }
109
110                 } else if (S_ISREG (statbuf.st_mode)) {
111
112                         string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
113                         string::size_type suffix;
114
115                         /* remove the suffix */
116
117                         if (slash != string::npos) {
118                                 snapshot = str.substr (slash+1);
119                         } else {
120                                 snapshot = str;
121                         }
122
123                         suffix = snapshot.find (statefile_suffix);
124
125                         if (suffix == string::npos) {
126                                 error << string_compose (_("%1 is not a snapshot file"), str) << endmsg;
127                                 return -1;
128                         }
129
130                         /* remove suffix */
131
132                         snapshot = snapshot.substr (0, suffix);
133
134                         if (slash == string::npos) {
135
136                                 /* we must be in the directory where the
137                                    statefile lives. get it using cwd().
138                                 */
139
140                                 char cwd[PATH_MAX+1];
141
142                                 if (getcwd (cwd, sizeof (cwd)) == 0) {
143                                         error << string_compose (_("cannot determine current working directory (%1)"), strerror (errno))
144                                               << endmsg;
145                                         return -1;
146                                 }
147
148                                 path = cwd;
149
150                         } else {
151
152                                 /* full path to the statefile */
153
154                                 path = str.substr (0, slash);
155                         }
156
157                 } else {
158
159                         /* what type of file is it? */
160                         error << string_compose (_("unknown file type for session %1"), str) << endmsg;
161                         return -1;
162                 }
163
164         } else {
165
166                 /* its the name of a new directory. get the name
167                    as "dirname" does.
168                 */
169
170                 string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
171
172                 if (slash == string::npos) {
173
174                         /* no slash, just use the name, but clean it up */
175
176                         path = legalize_for_path (str);
177                         snapshot = path;
178
179                 } else {
180
181                         path = str;
182                         snapshot = str.substr (slash+1);
183                 }
184         }
185
186         return 0;
187 }
188
189 }  // namespace ARDOUR