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