NeoMutt  2024-04-25-85-g27bab4
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
path.h File Reference

Path manipulation functions. More...

#include <stdbool.h>
#include <stdio.h>
+ Include dependency graph for path.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool mutt_path_abbr_folder (struct Buffer *path, const char *folder)
 Create a folder abbreviation.
 
const char * mutt_path_basename (const char *path)
 Find the last component for a pathname.
 
bool mutt_path_canon (struct Buffer *path, const char *homedir, bool is_dir)
 Create the canonical version of a path.
 
char * mutt_path_dirname (const char *path)
 Return a path up to, but not including, the final '/'.
 
char * mutt_path_escape (const char *src)
 Escapes single quotes in a path for a command string.
 
const char * mutt_path_getcwd (struct Buffer *cwd)
 Get the current working directory.
 
size_t mutt_path_realpath (struct Buffer *path)
 Resolve path, unraveling symlinks.
 
bool mutt_path_tidy (struct Buffer *path, bool is_dir)
 Remove unnecessary parts of a path.
 
bool mutt_path_tidy_dotdot (char *buf)
 Remove dot-dot-slash from a path.
 
bool mutt_path_tidy_slash (char *buf, bool is_dir)
 Remove unnecessary slashes and dots.
 
bool mutt_path_tilde (struct Buffer *path, const char *homedir)
 Expand '~' in a path.
 
bool mutt_path_to_absolute (char *path, const char *reference)
 Convert relative filepath to an absolute path.
 

Detailed Description

Path manipulation functions.

Authors
  • Richard Russon
  • Dennis Schön

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file path.h.

Function Documentation

◆ mutt_path_abbr_folder()

bool mutt_path_abbr_folder ( struct Buffer path,
const char *  folder 
)

Create a folder abbreviation.

Parameters
pathPath to modify
folderBase path for '=' substitution
Return values
truePath was abbreviated

Abbreviate a path using '=' to represent the 'folder'. If the folder path is passed, it won't be abbreviated to just '='

Definition at line 392 of file path.c.

393{
394 if (buf_is_empty(path) || !folder)
395 return false;
396
397 size_t flen = mutt_str_len(folder);
398 if (flen < 2)
399 return false;
400
401 if (folder[flen - 1] == '/')
402 flen--;
403
404 if (!mutt_strn_equal(buf_string(path), folder, flen))
405 return false;
406
407 if (buf_at(path, flen + 1) == '\0') // Don't abbreviate to '=/'
408 return false;
409
410 size_t rlen = mutt_str_len(path->data + flen + 1);
411
412 path->data[0] = '=';
413 memmove(path->data + 1, path->data + flen + 1, rlen + 1);
414 buf_fix_dptr(path);
415
416 return true;
417}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:182
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:670
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:425
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
char * data
Pointer to data.
Definition: buffer.h:37
+ Here is the call graph for this function:

◆ mutt_path_basename()

const char * mutt_path_basename ( const char *  path)

Find the last component for a pathname.

Parameters
pathString to be examined
Return values
ptrPart of pathname after last '/' character
Note
Basename of / is /

Definition at line 282 of file path.c.

283{
284 if (!path)
285 return NULL;
286
287 const char *p = strrchr(path, '/');
288 if (p)
289 {
290 if (p[1] == '\0')
291 return path;
292
293 return p + 1;
294 }
295
296 return path;
297}
+ Here is the caller graph for this function:

◆ mutt_path_canon()

bool mutt_path_canon ( struct Buffer path,
const char *  homedir,
bool  is_dir 
)

Create the canonical version of a path.

Parameters
pathPath to modify
homedirHome directory for '~' substitution
is_dirIs the path a directory?
Return values
trueSuccess

Remove unnecessary dots and slashes from a path and expand '~'.

Definition at line 248 of file path.c.

249{
250 if (buf_is_empty(path))
251 return false;
252
253 if (buf_at(path, 0) == '~')
254 {
255 mutt_path_tilde(path, homedir);
256 }
257 else if (buf_at(path, 0) != '/')
258 {
259 char cwd[PATH_MAX] = { 0 };
260 if (!getcwd(cwd, sizeof(cwd)))
261 {
262 mutt_debug(LL_DEBUG1, "getcwd failed: %s (%d)\n", strerror(errno), errno); // LCOV_EXCL_LINE
263 return false; // LCOV_EXCL_LINE
264 }
265
266 size_t cwd_len = mutt_str_len(cwd);
267 cwd[cwd_len] = '/';
268 cwd[cwd_len + 1] = '\0';
269 buf_insert(path, 0, cwd);
270 }
271
272 return mutt_path_tidy(path, is_dir);
273}
size_t buf_insert(struct Buffer *buf, size_t offset, const char *s)
Add a string in the middle of a buffer.
Definition: buffer.c:256
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
bool mutt_path_tidy(struct Buffer *path, bool is_dir)
Remove unnecessary parts of a path.
Definition: path.c:169
bool mutt_path_tilde(struct Buffer *path, const char *homedir)
Expand '~' in a path.
Definition: path.c:194
#define PATH_MAX
Definition: mutt.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_path_dirname()

char * mutt_path_dirname ( const char *  path)

Return a path up to, but not including, the final '/'.

Parameters
pathPath
Return values
ptrThe directory containing p

Unlike the IEEE Std 1003.1-2001 specification of dirname(3), this implementation does not modify its parameter, so callers need not manually copy their paths into a modifiable buffer prior to calling this function.

Note
Dirname of / is /
The caller must free the returned string

Definition at line 312 of file path.c.

313{
314 if (!path)
315 return NULL;
316
317 char buf[PATH_MAX] = { 0 };
318 mutt_str_copy(buf, path, sizeof(buf));
319 return mutt_str_dup(dirname(buf));
320}
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:581
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_path_escape()

char * mutt_path_escape ( const char *  src)

Escapes single quotes in a path for a command string.

Parameters
srcthe path to escape
Return values
ptrThe escaped string
Note
Do not free the returned string

Definition at line 426 of file path.c.

427{
428 if (!src)
429 return NULL;
430
431 static char dest[STR_COMMAND];
432 char *destp = dest;
433 int destsize = 0;
434
435 while (*src && (destsize < sizeof(dest) - 1))
436 {
437 if (*src != '\'')
438 {
439 *destp++ = *src++;
440 destsize++;
441 }
442 else
443 {
444 /* convert ' into '\'' */
445 if ((destsize + 4) < sizeof(dest))
446 {
447 *destp++ = *src++;
448 *destp++ = '\\';
449 *destp++ = '\'';
450 *destp++ = '\'';
451 destsize += 4;
452 }
453 else
454 {
455 break; // LCOV_EXCL_LINE
456 }
457 }
458 }
459 *destp = '\0';
460
461 return dest;
462}
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
+ Here is the caller graph for this function:

◆ mutt_path_getcwd()

const char * mutt_path_getcwd ( struct Buffer cwd)

Get the current working directory.

Parameters
cwdBuffer for the result
Return values
ptrString of current working directory

Definition at line 469 of file path.c.

470{
471 if (!cwd)
472 return NULL;
473
474 buf_alloc(cwd, PATH_MAX);
475 char *rc = getcwd(cwd->data, cwd->dsize);
476 while (!rc && (errno == ERANGE))
477 {
478 buf_alloc(cwd, cwd->dsize + 256); // LCOV_EXCL_LINE
479 rc = getcwd(cwd->data, cwd->dsize); // LCOV_EXCL_LINE
480 }
481 if (rc)
482 buf_fix_dptr(cwd);
483 else
484 buf_reset(cwd); // LCOV_EXCL_LINE
485
486 return rc;
487}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
size_t dsize
Length of data.
Definition: buffer.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_path_realpath()

size_t mutt_path_realpath ( struct Buffer path)

Resolve path, unraveling symlinks.

Parameters
pathBuffer containing path
Return values
numString length of resolved path
0Error, buf is not overwritten

Resolve and overwrite the path in buf.

Definition at line 370 of file path.c.

371{
372 if (buf_is_empty(path))
373 return 0;
374
375 char s[PATH_MAX] = { 0 };
376
377 if (!realpath(buf_string(path), s))
378 return 0;
379
380 return buf_strcpy(path, s);
381}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_path_tidy()

bool mutt_path_tidy ( struct Buffer path,
bool  is_dir 
)

Remove unnecessary parts of a path.

Parameters
[in,out]pathPath to modify
[in]is_dirIs the path a directory?
Return values
trueSuccess

Remove unnecessary dots and slashes from a path

Definition at line 169 of file path.c.

170{
171 if (buf_is_empty(path) || (buf_at(path, 0) != '/'))
172 return false;
173
174 if (!mutt_path_tidy_slash(path->data, is_dir))
175 return false; // LCOV_EXCL_LINE
176
178 buf_fix_dptr(path);
179
180 return true;
181}
bool mutt_path_tidy_dotdot(char *buf)
Remove dot-dot-slash from a path.
Definition: path.c:109
bool mutt_path_tidy_slash(char *buf, bool is_dir)
Remove unnecessary slashes and dots.
Definition: path.c:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_path_tidy_dotdot()

bool mutt_path_tidy_dotdot ( char *  buf)

Remove dot-dot-slash from a path.

Parameters
[in,out]bufPath to modify
Return values
trueSuccess

Collapse dot-dot patterns, like '/dir/../'

Definition at line 109 of file path.c.

110{
111 if (!buf || (buf[0] != '/'))
112 return false;
113
114 char *dd = buf;
115
116 mutt_debug(LL_DEBUG3, "Collapse path: %s\n", buf);
117 while ((dd = strstr(dd, "/..")))
118 {
119 if (dd[3] == '/') /* paths follow dots */
120 {
121 char *dest = NULL;
122 if (dd != buf) /* not at start of string */
123 {
124 dd[0] = '\0';
125 dest = strrchr(buf, '/');
126 }
127 if (!dest)
128 dest = buf;
129
130 memmove(dest, dd + 3, strlen(dd + 3) + 1);
131 }
132 else if (dd[3] == '\0') /* dots at end of string */
133 {
134 if (dd == buf) /* at start of string */
135 {
136 dd[1] = '\0';
137 }
138 else
139 {
140 dd[0] = '\0';
141 char *s = strrchr(buf, '/');
142 if (s == buf)
143 s[1] = '\0';
144 else if (s)
145 s[0] = '\0';
146 }
147 }
148 else
149 {
150 dd += 3; /* skip over '/..dir/' */
151 continue;
152 }
153
154 dd = buf; /* restart at the beginning */
155 }
156
157 mutt_debug(LL_DEBUG3, "Collapsed to: %s\n", buf);
158 return true;
159}
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
+ Here is the caller graph for this function:

◆ mutt_path_tidy_slash()

bool mutt_path_tidy_slash ( char *  buf,
bool  is_dir 
)

Remove unnecessary slashes and dots.

Parameters
[in,out]bufPath to modify
[in]is_dirShould a trailing / be removed?
Return values
trueSuccess

Collapse repeated '//' and '/./'

Definition at line 58 of file path.c.

59{
60 if (!buf)
61 return false;
62
63 char *r = buf;
64 char *w = buf;
65
66 while (*r != '\0')
67 {
68 *w++ = *r++;
69
70 if (r[-1] == '/') /* After a '/' ... */
71 {
72 for (; (r[0] == '/') || (r[0] == '.'); r++)
73 {
74 if (r[0] == '/') /* skip multiple /s */
75 continue;
76 if (r[0] == '.')
77 {
78 if (r[1] == '/') /* skip /./ */
79 {
80 r++;
81 continue;
82 }
83 else if (r[1] == '\0') /* skip /.$ */
84 {
85 r[0] = '\0';
86 }
87 break; /* dot-anything-else isn't special */
88 }
89 }
90 }
91 }
92
93 /* Strip a trailing / as long as it's not the only character */
94 if (is_dir && (w > (buf + 1)) && (w[-1] == '/'))
95 w--;
96
97 *w = '\0';
98
99 return true;
100}
+ Here is the caller graph for this function:

◆ mutt_path_tilde()

bool mutt_path_tilde ( struct Buffer path,
const char *  homedir 
)

Expand '~' in a path.

Parameters
pathPath to modify
homedirHome directory for '~' substitution
Return values
trueSuccess

Behaviour:

  • ~/dir (~ expanded)
  • ~realuser/dir (~realuser expanded)
  • ~nonuser/dir (~nonuser not changed)

Definition at line 194 of file path.c.

195{
196 if (buf_is_empty(path) || (buf_at(path, 0) != '~'))
197 return false;
198
199 char result[PATH_MAX] = { 0 };
200 char *dir = NULL;
201 size_t len = 0;
202
203 if ((buf_at(path, 1) == '/') || (buf_at(path, 1) == '\0'))
204 {
205 if (!homedir)
206 {
207 mutt_debug(LL_DEBUG3, "no homedir\n");
208 return false;
209 }
210
211 len = mutt_str_copy(result, homedir, sizeof(result));
212 dir = path->data + 1;
213 }
214 else
215 {
216 char user[128] = { 0 };
217 dir = strchr(path->data + 1, '/');
218 if (dir)
219 mutt_str_copy(user, path->data + 1, MIN(dir - path->data, (unsigned) sizeof(user)));
220 else
221 mutt_str_copy(user, path->data + 1, sizeof(user));
222
223 struct passwd *pw = getpwnam(user);
224 if (!pw || !pw->pw_dir)
225 {
226 mutt_debug(LL_DEBUG1, "no such user: %s\n", user);
227 return false;
228 }
229
230 len = mutt_str_copy(result, pw->pw_dir, sizeof(result));
231 }
232
233 mutt_str_copy(result + len, dir, sizeof(result) - len);
234 buf_strcpy(path, result);
235
236 return true;
237}
#define MIN(a, b)
Definition: memory.h:32
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_path_to_absolute()

bool mutt_path_to_absolute ( char *  path,
const char *  reference 
)

Convert relative filepath to an absolute path.

Parameters
pathRelative path
referenceAbsolute path that path is relative to
Return values
trueSuccess
falseFailure

Use POSIX functions to convert a path to absolute, relatively to another path

Note
path should be at least of PATH_MAX length

Definition at line 333 of file path.c.

334{
335 if (!path || !reference)
336 return false;
337
338 /* if path is already absolute, don't do anything */
339 if ((strlen(path) > 1) && (path[0] == '/'))
340 {
341 return true;
342 }
343
344 struct Buffer *abs_path = buf_pool_get();
345
346 char *dirpath = mutt_path_dirname(reference);
347 buf_printf(abs_path, "%s/%s", dirpath, path);
348 FREE(&dirpath);
349
350 path = realpath(buf_string(abs_path), path);
351 if (!path && (errno != ENOENT))
352 {
353 mutt_perror(_("Error: converting path to absolute"));
354 buf_pool_release(&abs_path);
355 return false;
356 }
357
358 buf_pool_release(&abs_path);
359 return true;
360}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
#define mutt_perror(...)
Definition: logging2.h:93
#define FREE(x)
Definition: memory.h:45
#define _(a)
Definition: message.h:28
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
Definition: path.c:312
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
String manipulation buffer.
Definition: buffer.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function: