/* */
This source file includes following definitions.
- setupvariables
- getobjdir
- gtagsexist
- setupdbpath
- get_dbpath
- get_root
- get_root_with_slash
- get_cwd
1 /*
2 * Copyright (c) 1997, 1998, 1999, 2000, 2002, 2008, 2011
3 * Tama Communications Corporation
4 *
5 * This file is part of GNU GLOBAL.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #ifdef STDC_HEADERS
27 #include <stdlib.h>
28 #endif
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #else
32 #include <strings.h>
33 #endif
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include "gparam.h"
39 #include "die.h"
40 #include "getdbpath.h"
41 #include "gtagsop.h"
42 #include "makepath.h"
43 #include "path.h"
44 #include "strlimcpy.h"
45 #include "test.h"
46
47 /**
48 * define the position of the root slash.
49 */
50 #if defined(_WIN32) || defined(__DJGPP__)
51 #define ROOT 2
52 #else
53 #define ROOT 0
54 #endif
55
56 static const char *makeobjdirprefix; /**< obj partition */
57 static const char *makeobjdir; /**< obj directory */
58 char const *gtags_dbpath_error; /**< error message */
59
60 /**
61 * setupvariables: load variables regard to @NAME{BSD} @NAME{OBJ} directory.
62 */
63 static void
64 setupvariables(int verbose)
65 {
66 const char *p;
67
68 if ((p = getenv("MAKEOBJDIRPREFIX")) != NULL) {
69 makeobjdirprefix = p;
70 if (verbose)
71 fprintf(stderr, "MAKEOBJDIRPREFIX is set to '%s'.\n", p);
72 } else {
73 makeobjdirprefix = "/usr/obj";
74 }
75 if ((p = getenv("MAKEOBJDIR")) != NULL) {
76 makeobjdir = p;
77 if (verbose)
78 fprintf(stderr, "MAKEOBJDIR is set to '%s'.\n", p);
79 } else {
80 makeobjdir = "obj";
81 }
82 }
83 /**
84 * getobjdir: get objdir if it exists.
85 *
86 * @param[in] candidate candidate root directory
87 * @param[in] verbose verbose mode 1: on, 0: off
88 * @return objdir(@VAR{NULL}: not found)
89 */
90 char *
91 getobjdir(const char *candidate, int verbose)
92 {
93 static char path[MAXPATHLEN];
94
95 /*
96 * setup makeobjdir and makeobjdirprefix (only first time).
97 */
98 if (makeobjdir == NULL)
99 setupvariables(0);
100 snprintf(path, sizeof(path), "%s/%s", candidate, makeobjdir);
101 if (test("d", path)) {
102 if (!test("drw", path))
103 die("Found objdir '%s', but you don't have read/write permission for it.", path);
104 if (verbose)
105 fprintf(stderr, "Using objdir '%s'.\n", path);
106 return path;
107 }
108 #if !defined(_WIN32) && !defined(__DJGPP__)
109 if (test("d", makeobjdirprefix)) {
110 snprintf(path, sizeof(path), "%s%s", makeobjdirprefix, candidate);
111 if (test("d", path)) {
112 if (!test("drw", path))
113 die("Found objdir '%s', but you don't have read/write permission for it.", path);
114 if (verbose)
115 fprintf(stderr, "Using objdir '%s'.\n", path);
116 return path;
117 }
118 if (makedirectories(makeobjdirprefix, candidate + 1, verbose) < 0)
119 die("Found the base for objdir '%s', but you cannot create new directory in it.", path);
120 if (verbose)
121 fprintf(stderr, "Using objdir '%s'.\n", path);
122 return path;
123 }
124 #endif
125 return NULL;
126 }
127 /**
128 * gtagsexist: test whether GTAGS's existence.
129 *
130 * @param[in] candidate candidate root directory
131 * @param[out] dbpath directory which @FILE{GTAGS} exist
132 * @param[in] size size of @a dbpath buffer
133 * @param[in] verbose verbose mode 1: on, 0: off
134 * @return 0: not found, 1: found
135 *
136 * Gtagsexist locate @FILE{GTAGS} file in @FILE{\$candidate/}, @FILE{\$candidate/obj/} and
137 * @FILE{/usr/obj/\$candidate/} in this order by default. <br>
138 * This behavior is same with @NAME{BSD} @XREF{make,1}'s one.
139 */
140 int
141 gtagsexist(const char *candidate, char *dbpath, int size, int verbose)
142 {
143 char path[MAXPATHLEN];
144 const char *candidate_without_slash;
145
146 /*
147 * setup makeobjdir and makeobjdirprefix (only first time).
148 */
149 if (makeobjdir == NULL)
150 setupvariables(verbose);
151
152 if (strcmp(candidate, "/") == 0)
153 candidate_without_slash = "";
154 else
155 candidate_without_slash = candidate;
156 snprintf(path, sizeof(path), "%s/%s", candidate_without_slash, dbname(GTAGS));
157 if (verbose)
158 fprintf(stderr, "checking %s\n", path);
159 if (test("fr", path)) {
160 if (verbose)
161 fprintf(stderr, "GTAGS found at '%s'.\n", path);
162 snprintf(dbpath, size, "%s", candidate);
163 return 1;
164 }
165 snprintf(path, sizeof(path),
166 "%s/%s/%s", candidate_without_slash, makeobjdir, dbname(GTAGS));
167 if (verbose)
168 fprintf(stderr, "checking %s\n", path);
169 if (test("fr", path)) {
170 if (verbose)
171 fprintf(stderr, "GTAGS found at '%s'.\n", path);
172 snprintf(dbpath, size, "%s/%s", candidate_without_slash, makeobjdir);
173 return 1;
174 }
175 #if !defined(_WIN32) && !defined(__DJGPP__)
176 snprintf(path, sizeof(path),
177 "%s%s/%s", makeobjdirprefix, candidate_without_slash, dbname(GTAGS));
178 if (verbose)
179 fprintf(stderr, "checking %s\n", path);
180 if (test("fr", path)) {
181 if (verbose)
182 fprintf(stderr, "GTAGS found at '%s'.\n", path);
183 snprintf(dbpath, size, "%s%s", makeobjdirprefix, candidate_without_slash);
184 return 1;
185 }
186 #endif
187 return 0;
188 }
189 static char dbpath[MAXPATHLEN];
190 static char root[MAXPATHLEN];
191 static char root_with_slash[MAXPATHLEN];
192 static char cwd[MAXPATHLEN];
193 /**
194 * setupdbpath: setup dbpath directory
195 *
196 * @param[in] verbose verbose mode 1: on, 0: off
197 *
198 * @par Globals used (output):
199 * #cwd: current directory <br>
200 * #root: root of source tree <br>
201 * #dbpath: directory which @FILE{GTAGS} exist <br>
202 * #gtags_dbpath_error: set if status (return value) \< 0
203 *
204 * @return 0: normal, 0\<: error
205 */
206 int
207 setupdbpath(int verbose)
208 {
209 struct stat sb;
210 char *p;
211 static char msg[1024];
212
213 if (!getcwd(cwd, MAXPATHLEN)) {
214 gtags_dbpath_error = "cannot get current directory.";
215 return -1;
216 }
217 canonpath(cwd);
218
219 if ((p = getenv("GTAGSROOT")) != NULL) {
220 if (verbose)
221 fprintf(stderr, "GTAGSROOT is set to '%s'.\n", p);
222 if (!isabspath(p)) {
223 gtags_dbpath_error = "GTAGSROOT must be an absolute path.";
224 return -1;
225 }
226 if (stat(p, &sb) || !S_ISDIR(sb.st_mode)) {
227 snprintf(msg, sizeof(msg), "directory '%s' not found.", p);
228 gtags_dbpath_error = msg;
229 return -1;
230 }
231 if (realpath(p, root) == NULL) {
232 snprintf(msg, sizeof(msg), "cannot get real path of '%s'.", p);
233 gtags_dbpath_error = msg;
234 return -1;
235 }
236 /*
237 * GTAGSDBPATH is meaningful only when GTAGSROOT exist.
238 */
239 if ((p = getenv("GTAGSDBPATH")) != NULL) {
240 if (verbose)
241 fprintf(stderr, "GTAGSDBPATH is set to '%s'.\n", p);
242 if (!isabspath(p)) {
243 gtags_dbpath_error = "GTAGSDBPATH must be an absolute path.";
244 return -1;
245 }
246 if (stat(p, &sb) || !S_ISDIR(sb.st_mode)) {
247 snprintf(msg, sizeof(msg), "directory '%s' not found.", p);
248 gtags_dbpath_error = msg;
249 return -1;
250 }
251 strlimcpy(dbpath, getenv("GTAGSDBPATH"), MAXPATHLEN);
252 } else {
253 if (!gtagsexist(root, dbpath, MAXPATHLEN, verbose)) {
254 gtags_dbpath_error = "GTAGS not found.";
255 return -3;
256 }
257 }
258 } else {
259 if (verbose && getenv("GTAGSDBPATH"))
260 fprintf(stderr, "warning: GTAGSDBPATH is ignored because GTAGSROOT is not set.\n");
261 /*
262 * start from current directory to '/' directory.
263 */
264 strlimcpy(root, cwd, MAXPATHLEN);
265 p = root + strlen(root);
266 while (!gtagsexist(root, dbpath, MAXPATHLEN, verbose)) {
267 if (!strcmp(root+ROOT, "/")) { /* reached the system's root directory */
268 *(root+ROOT) = '\0';
269 break;
270 }
271 while (*--p != '/' && p > (root+ROOT))
272 ;
273 if (p == (root+ROOT))
274 p++;
275 *p = 0;
276 }
277 if (*(root+ROOT) == 0) {
278 gtags_dbpath_error = "GTAGS not found.";
279 return -3;
280 }
281 /*
282 * If file 'GTAGSROOT' found without environment variable
283 * GTAGSDBPATH, use the value of it as GTAGSROOT.
284 */
285 do {
286 FILE *fp;
287 STRBUF *sb;
288 const char *s, *path;
289
290 path = makepath(root, "GTAGSROOT", NULL);
291 if (!test("fr", path)) {
292 break;
293 }
294 fp = fopen(path, "r");
295 if (fp == NULL) {
296 if (verbose)
297 fprintf(stderr, "'%s' ignored because it cannot be opened.\n", path);
298 break;
299 }
300 sb = strbuf_open(0);
301 s = strbuf_fgets(sb, fp, STRBUF_NOCRLF);
302 if (!test("d", s)) {
303 if (verbose)
304 fprintf(stderr, "'%s' ignored because it doesn't include existent directory name.\n", path);
305 } else {
306 char buf[MAXPATHLEN];
307
308 if (verbose)
309 fprintf(stderr, "GTAGSROOT found at '%s'.\n", path);
310 if (!isabspath(s))
311 s = realpath(makepath(root, s, NULL), buf);
312 strlimcpy(root, s, MAXPATHLEN);
313 }
314 fclose(fp);
315 strbuf_close(sb);
316 break;
317 } while (0);
318 }
319 if (!strcmp(root+ROOT, "/"))
320 strlimcpy(root_with_slash, root, sizeof(root_with_slash));
321 else
322 snprintf(root_with_slash, sizeof(root_with_slash), "%s/", root);
323 return 0;
324 }
325 /**
326 * @name return saved values.
327 */
328 /** @{ */
329 const char *
330 get_dbpath(void)
331 {
332 return (const char *)dbpath;
333 }
334 const char *
335 get_root(void)
336 {
337 return (const char *)root;
338 }
339 const char *
340 get_root_with_slash(void)
341 {
342 return (const char *)root_with_slash;
343 }
344 const char *
345 get_cwd(void)
346 {
347 return (const char *)cwd;
348 }
349 /** @} */
/* */