Change wrealpath to return a maybe_t

Simplify the wrealpath interface and avoid manual invocations of free() by
changing wrealpath to return a maybe_t<wcstring>.
This commit is contained in:
ridiculousfish 2017-10-11 00:08:26 -07:00
parent 05c0cb713d
commit 1f130bcc9c
4 changed files with 16 additions and 21 deletions

View file

@ -37,10 +37,8 @@ int builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
return STATUS_INVALID_ARGS; return STATUS_INVALID_ARGS;
} }
wchar_t *real_path = wrealpath(argv[optind], NULL); if (auto real_path = wrealpath(argv[optind])) {
if (real_path) { streams.out.append(*real_path);
streams.out.append(real_path);
free((void *)real_path);
} else { } else {
// We don't actually know why it failed. We should check errno. // We don't actually know why it failed. We should check errno.
streams.err.append_format(_(L"%ls: Invalid path: %ls\n"), cmd, argv[optind]); streams.err.append_format(_(L"%ls: Invalid path: %ls\n"), cmd, argv[optind]);

View file

@ -1182,13 +1182,15 @@ static void expand_home_directory(wcstring &input) {
} }
} }
const wchar_t *realhome = home ? wrealpath(home->as_string(), NULL) : nullptr; maybe_t<wcstring> realhome;
if (home)
realhome = wrealpath(home->as_string());
if (realhome) { if (realhome) {
input.replace(input.begin(), input.begin() + tail_idx, realhome); input.replace(input.begin(), input.begin() + tail_idx, *realhome);
} else { } else {
input[0] = L'~'; input[0] = L'~';
} }
free((void *)realhome);
} }
} }

View file

@ -338,10 +338,10 @@ void safe_perror(const char *message) {
errno = err; errno = err;
} }
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) { maybe_t<wcstring> wrealpath(const wcstring &pathname) {
if (pathname.size() == 0) return NULL; if (pathname.empty()) return none();
cstring real_path(""); cstring real_path;
cstring narrow_path = wcs2string(pathname); cstring narrow_path = wcs2string(pathname);
// Strip trailing slashes. This is needed to be bug-for-bug compatible with GNU realpath which // Strip trailing slashes. This is needed to be bug-for-bug compatible with GNU realpath which
@ -370,7 +370,7 @@ wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
} else { } else {
// Only call realpath() on the portion up to the last component. // Only call realpath() on the portion up to the last component.
narrow_res = realpath(narrow_path.substr(0, pathsep_idx).c_str(), tmpbuff); narrow_res = realpath(narrow_path.substr(0, pathsep_idx).c_str(), tmpbuff);
if (!narrow_res) return NULL; if (!narrow_res) return none();
pathsep_idx++; pathsep_idx++;
} }
real_path.append(narrow_res); real_path.append(narrow_res);
@ -379,12 +379,7 @@ wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
real_path.append(narrow_path.substr(pathsep_idx, cstring::npos)); real_path.append(narrow_path.substr(pathsep_idx, cstring::npos));
} }
} }
wcstring wreal_path = str2wcstring(real_path); return str2wcstring(real_path);
if (resolved_path) {
wcslcpy(resolved_path, wreal_path.c_str(), PATH_MAX);
return resolved_path;
}
return wcsdup(wreal_path.c_str());
} }
wcstring wdirname(const wcstring &path) { wcstring wdirname(const wcstring &path) {

View file

@ -10,6 +10,7 @@
#include <string> #include <string>
#include "common.h" #include "common.h"
#include "maybe.h"
/// Wide character version of fopen(). This sets CLO_EXEC. /// Wide character version of fopen(). This sets CLO_EXEC.
FILE *wfopen(const wcstring &path, const char *mode); FILE *wfopen(const wcstring &path, const char *mode);
@ -58,10 +59,9 @@ const wcstring wgetcwd();
/// Wide character version of chdir(). /// Wide character version of chdir().
int wchdir(const wcstring &dir); int wchdir(const wcstring &dir);
/// Wide character version of realpath function. Just like the GNU version of realpath, wrealpath /// Wide character version of realpath function.
/// will accept 0 as the value for the second argument, in which case the result will be allocated /// \returns the canonicalized path, or none if the path is invalid.
/// using malloc, and must be free'd by the user. maybe_t<wcstring> wrealpath(const wcstring &pathname);
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path);
/// Wide character version of readdir(). /// Wide character version of readdir().
bool wreaddir(DIR *dir, wcstring &out_name); bool wreaddir(DIR *dir, wcstring &out_name);