1/*	Id: path.c$	/
2/*	$NetBSD: path.c,v 1.1.1.1 2016/02/09 20:29:12 plunky Exp $/
3
4/*-
5 * Copyright (c) 2011 Joerg Sonnenberger <joerg@NetBSD.org>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in
16 *    the documentation and/or other materials provided with the
17 *    distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <assert.h>
34#include <stdlib.h>
35#include <stdio.h>
36#include <string.h>
37#ifdef HAVE_UNISTD_H
38#include <unistd.h>
39#endif
40
41#include "driver.h"
42
43static void
44expand_sysroot(void)
45{
46	struct string *s;
47	struct strlist *lists[] = { &crtdirs, &sysincdirs, &incdirs,
48	    &user_sysincdirs, &libdirs, &progdirs, NULL };
49	const char *sysroots[] = { sysroot, isysroot, isysroot, isysroot,
50	    sysroot, sysroot, NULL };
51	size_t i, sysroot_len, value_len;
52	char *path;
53
54	assert(sizeof(lists) / sizeof(lists[0]) ==
55	       sizeof(sysroots) / sizeof(sysroots[0]));
56
57	for (i = 0; lists[i] != NULL; ++i) {
58		STRLIST_FOREACH(s, lists[i]) {
59			if (s->value[0] != '=')
60				continue;
61			sysroot_len = strlen(sysroots[i]);
62			/* Skipped '=' compensates additional space for '\0' */
63			value_len = strlen(s->value);
64			path = xmalloc(sysroot_len + value_len);
65			memcpy(path, sysroots[i], sysroot_len);
66			memcpy(path + sysroot_len, s->value + 1, value_len);
67			free(s->value);
68			s->value = path;
69		}
70	}
71}
72
73static char *
74find_file(const char *file, struct strlist *path, int mode)
75{
76	struct string *s;
77	char *f;
78	size_t lf, lp;
79	int need_sep;
80
81	lf = strlen(file);
82	STRLIST_FOREACH(s, path) {
83		lp = strlen(s->value);
84		need_sep = (lp && s->value[lp - 1] != '/') ? 1 : 0;
85		f = xmalloc(lp + lf + need_sep + 1);
86		memcpy(f, s->value, lp);
87		if (need_sep)
88			f[lp] = '/';
89		memcpy(f + lp + need_sep, file, lf + 1);
90		if (access(f, mode) == 0)
91			return f;
92		free(f);
93	}
94	return xstrdup(file);
95}
96
97static char *
98output_name(const char *file, const char *new_suffix, int counter, int last)
99{
100	const char *old_suffix;
101	char *name;
102	size_t lf, ls, len;
103	int counter_len;
104
105	if (last && final_output)
106		return xstrdup(final_output);
107
108	old_suffix = strrchr(file, '.');
109	if (old_suffix != NULL && strchr(old_suffix, '/') != NULL)
110		old_suffix = NULL;
111	if (old_suffix == NULL)
112		old_suffix = file + strlen(file);
113
114	ls = strlen(new_suffix);
115	if (save_temps || last) {
116		lf = old_suffix - file;
117		name = xmalloc(lf + ls + 1);
118		memcpy(name, file, lf);
119		memcpy(name + lf, new_suffix, ls + 1);
120		return name;
121	}
122	if (temp_directory == NULL) {
123		const char *template;
124		char *path;
125		size_t template_len;
126		int need_sep;
127
128		template = getenv("TMPDIR");
129		if (template == NULL)
130			template = "/tmp";
131		template_len = strlen(template);
132		if (template_len && template[template_len - 1] == '/')
133			need_sep = 0;
134		else
135			need_sep = 1;
136		path = xmalloc(template_len + need_sep + 6 + 1);
137		memcpy(path, template, template_len);
138		if (need_sep)
139			path[template_len] = '/';
140		memcpy(path + template_len + need_sep, "pcc-XXXXXX", 11);
141		if (mkdtemp(path) == NULL)
142			error("mkdtemp failed: %s", strerror(errno));
143		temp_directory = path;
144	}
145	lf = strlen(temp_directory);
146	counter_len = snprintf(NULL, 0, "%d", counter);
147	if (counter_len < 1)
148		error("snprintf failure");
149	len = lf + 1 + (size_t)counter_len + ls + 1;
150	name = xmalloc(len);
151	snprintf(name, len, "%s/%d%s", temp_directory, counter, new_suffix);
152	strlist_add(&temp_outputs, name);
153	return name;
154}
155