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 : 396 : path_trim_slash_slashdot(char *path)
44 : : {
45 : : char *end;
46 : :
47 [ + + ]: 396 : if (str_is_unset(path))
48 : 17 : return 0;
49 : :
50 [ + + ]: 422 : for (end = path + strlen(path) - 1; end - path >= 1; end--) {
51 [ + + + + : 414 : if (*end == '/' || (*(end - 1) == '/' && *end == '.'))
+ + ]
52 : 43 : *end = '\0';
53 : : else
54 : : break;
55 : : }
56 : :
57 : 379 : 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 : 520 : path_skip_slash_dotslash(const char *path)
69 : : {
70 [ + + + + : 1089 : while (path[0] == '/' || (path[0] == '.' && path[1] == '/'))
+ + ]
71 : 569 : path++;
72 : :
73 : 520 : 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 : 439 : path_basename(const char *path)
85 : : {
86 : : const char *last_slash;
87 : :
88 : 439 : last_slash = strrchr(path, '/');
89 [ + + ]: 439 : if (last_slash == NULL)
90 : 423 : 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 : 57 : path_make_temp_template(const char *suffix)
104 : : {
105 : : const char *tmpdir;
106 : :
107 : 57 : tmpdir = getenv("TMPDIR");
108 [ + - ]: 57 : if (!tmpdir)
109 : 57 : tmpdir = P_tmpdir;
110 : :
111 : 57 : 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 *ret = dst;
135 : 6 : ssize_t size = (ssize_t)n;
136 : :
137 [ + + ]: 6 : if (size == 0)
138 : 1 : return ret;
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 ret;
170 : : }
|