Branch data Line data Source code
1 : : /* 2 : : * libdpkg - Debian packaging suite library routines 3 : : * path.c - path handling functions 4 : : * 5 : : * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk> 6 : : * Copyright © 2008-2012 Guillem Jover <guillem@debian.org> 7 : : * 8 : : * This is free software; you can redistribute it and/or modify 9 : : * it under the terms of the GNU General Public License as published by 10 : : * the Free Software Foundation; either version 2 of the License, or 11 : : * (at your option) any later version. 12 : : * 13 : : * This is distributed in the hope that it will be useful, 14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 : : * GNU General Public License for more details. 17 : : * 18 : : * You should have received a copy of the GNU General Public License 19 : : * along with this program. If not, see <https://www.gnu.org/licenses/>. 20 : : */ 21 : : 22 : : #include <config.h> 23 : : #include <compat.h> 24 : : 25 : : #include <stdlib.h> 26 : : #include <string.h> 27 : : #include <stdio.h> 28 : : 29 : : #include <dpkg/dpkg.h> 30 : : #include <dpkg/string.h> 31 : : #include <dpkg/path.h> 32 : : 33 : : /** 34 : : * Trim ‘/’ and ‘/.’ from the end of a pathname. 35 : : * 36 : : * The given string will get NUL-terminatd. 37 : : * 38 : : * @param path The pathname to trim. 39 : : * 40 : : * @return The size of the trimmed pathname. 41 : : */ 42 : : size_t 43 : 368 : path_trim_slash_slashdot(char *path) 44 : : { 45 : : char *end; 46 : : 47 [ + + ]: 368 : if (str_is_unset(path)) 48 : 1 : return 0; 49 : : 50 [ + + ]: 410 : for (end = path + strlen(path) - 1; end - path >= 1; end--) { 51 [ + + + + : 402 : if (*end == '/' || (*(end - 1) == '/' && *end == '.')) + + ] 52 : 43 : *end = '\0'; 53 : : else 54 : : break; 55 : : } 56 : : 57 : 367 : return end - path + 1; 58 : : } 59 : : 60 : : /** 61 : : * Skip ‘/’ and ‘./’ from the beginning of a pathname. 62 : : * 63 : : * @param path The pathname to skip. 64 : : * 65 : : * @return The new beginning of the pathname. 66 : : */ 67 : : const char * 68 : 496 : path_skip_slash_dotslash(const char *path) 69 : : { 70 [ + + + + : 1041 : while (path[0] == '/' || (path[0] == '.' && path[1] == '/')) + + ] 71 : 545 : path++; 72 : : 73 : 496 : return path; 74 : : } 75 : : 76 : : /** 77 : : * Return the last component of a pathname. 78 : : * 79 : : * @param path The pathname to get the base name from. 80 : : * 81 : : * @return A pointer to the last component inside pathname. 82 : : */ 83 : : const char * 84 : 393 : path_basename(const char *path) 85 : : { 86 : : const char *last_slash; 87 : : 88 : 393 : last_slash = strrchr(path, '/'); 89 [ + + ]: 393 : if (last_slash == NULL) 90 : 377 : return path; 91 : : else 92 : 16 : return last_slash + 1; 93 : : } 94 : : 95 : : /** 96 : : * Create a template for a temporary pathname. 97 : : * 98 : : * @param suffix The suffix to use for the template string. 99 : : * 100 : : * @return An allocated string with the created template. 101 : : */ 102 : : char * 103 : 41 : path_make_temp_template(const char *suffix) 104 : : { 105 : : const char *tmpdir; 106 : : 107 : 41 : tmpdir = getenv("TMPDIR"); 108 [ + - ]: 41 : if (!tmpdir) 109 : 41 : tmpdir = P_tmpdir; 110 : : 111 : 41 : return str_fmt("%s/%s.XXXXXX", tmpdir, suffix); 112 : : } 113 : : 114 : : /** 115 : : * Escape characters in a pathname for safe locale printing. 116 : : * 117 : : * We need to quote paths so that they do not cause problems when printing 118 : : * them, for example with snprintf(3) which does not work if the format 119 : : * string contains %s and an argument has invalid characters for the 120 : : * current locale, it will then return -1. 121 : : * 122 : : * To simplify things, we just escape all 8 bit characters, instead of 123 : : * just invalid characters. 124 : : * 125 : : * @param dst The escaped destination string. 126 : : * @param src The source string to escape. 127 : : * @param n The size of the destination buffer. 128 : : * 129 : : * @return The destination string. 130 : : */ 131 : : char * 132 : 6 : path_quote_filename(char *dst, const char *src, size_t n) 133 : : { 134 : 6 : char *r = dst; 135 : 6 : ssize_t size = (ssize_t)n; 136 : : 137 [ + + ]: 6 : if (size == 0) 138 : 1 : return r; 139 : : 140 [ + + ]: 98 : while (*src) { 141 [ + + ]: 96 : if (*src == '\\') { 142 : 2 : size -= 2; 143 [ + + ]: 2 : if (size <= 0) 144 : 1 : break; 145 : : 146 : 1 : *dst++ = '\\'; 147 : 1 : *dst++ = '\\'; 148 : 1 : src++; 149 [ + + ]: 94 : } else if (((*src) & 0x80) == '\0') { 150 : 90 : size--; 151 [ + + ]: 90 : if (size <= 0) 152 : 1 : break; 153 : : 154 : 89 : *dst++ = *src++; 155 : : } else { 156 : 4 : size -= 4; 157 [ + + ]: 4 : if (size <= 0) 158 : 1 : break; 159 : : 160 : 3 : sprintf(dst, "\\%03o", 161 : 3 : *(const unsigned char *)src); 162 : 3 : dst += 4; 163 : 3 : src++; 164 : : } 165 : : } 166 : : 167 : 5 : *dst = '\0'; 168 : : 169 : 5 : return r; 170 : : }