From 29495ab53bebbdfde86dc9488acfe236d3669e57 Mon Sep 17 00:00:00 2001 From: Richard Nyberg Date: Sat, 14 Oct 2006 21:29:25 +0000 Subject: [PATCH] Add and use the function make_abs_path. realpath didn't fit my needs. make_abs_path doesn't need the directories to actually exist in the file system. --- cli/add.c | 4 +- misc/subr.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ misc/subr.h | 1 + 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/cli/add.c b/cli/add.c index 585529b..e88a0b0 100644 --- a/cli/add.c +++ b/cli/add.c @@ -89,8 +89,8 @@ cmd_add(int argc, char **argv) buf_write(&iob, td, tdlen); } buf_swrite(&iob, "\0"); - if (realpath(iob.buf, dpath) == NULL) - err(1, "realpath '%s'", dpath); + if ((errno = make_abs_path(iob.buf, dpath)) != 0) + err(1, "make_abs_path '%s'", dpath); code = btpd_add(ipc, mi, mi_size, dpath, name); if (code == 0 && start) { struct ipc_torrent tspec; diff --git a/misc/subr.c b/misc/subr.c index bc11d16..70a04af 100644 --- a/misc/subr.c +++ b/misc/subr.c @@ -276,3 +276,107 @@ find_btpd_dir(void) asprintf(&res, "%s/.btpd", home); return res; } + +int +make_abs_path(const char *in, char *out) +{ + int ii = 0, oi = 0, lastsep = 0; + switch (in[0]) { + case '\0': + return EINVAL; + case '/': + if (strlen(in) >= PATH_MAX) + return ENAMETOOLONG; + out[0] = '/'; + oi++; + ii++; + break; + default: + if (getcwd(out, PATH_MAX) == NULL) + return errno; + oi = strlen(out); + if (oi + strlen(in) + 1 >= PATH_MAX) + return ENAMETOOLONG; + out[oi] = '/'; + lastsep = oi; + oi++; + break; + } +after_slash: + while (in[ii] == '/') + ii++; + switch(in[ii]) { + case '\0': + goto end; + case '.': + ii++; + goto one_dot; + default: + goto normal; + } +one_dot: + switch (in[ii]) { + case '\0': + goto end; + case '/': + ii++; + goto after_slash; + case '.': + ii++; + goto two_dot; + default: + out[oi] = '.'; + oi++; + goto normal; + } +two_dot: + switch (in[ii]) { + case '\0': + if (lastsep == 0) + oi = 1; + else { + oi = lastsep; + while (out[oi - 1] != '/') + oi--; + lastsep = oi - 1; + } + goto end; + case '/': + if (lastsep == 0) + oi = 1; + else { + oi = lastsep; + while (out[oi - 1] != '/') + oi--; + lastsep = oi - 1; + } + ii++; + goto after_slash; + default: + out[oi] = '.'; + out[oi + 1] = '.'; + oi += 2; + goto normal; + } +normal: + switch (in[ii]) { + case '\0': + goto end; + case '/': + out[oi] = '/'; + lastsep = oi; + oi++; + ii++; + goto after_slash; + default: + out[oi] = in[ii]; + oi++; + ii++; + goto normal; + } +end: + if (oi == lastsep + 1 && lastsep != 0) + oi = lastsep; + out[oi] = '\0'; + return 0; +} diff --git a/misc/subr.h b/misc/subr.h index 8ef962c..fd9e002 100644 --- a/misc/subr.h +++ b/misc/subr.h @@ -36,5 +36,6 @@ int write_fully(int fd, const void *buf, size_t len); void *read_file(const char *path, void *buf, size_t *size); char *find_btpd_dir(void); +int make_abs_path(const char *in, char *out); #endif