make_abs_path doesn't need the directories to actually exist in the file system.master
@@ -89,8 +89,8 @@ cmd_add(int argc, char **argv) | |||||
buf_write(&iob, td, tdlen); | buf_write(&iob, td, tdlen); | ||||
} | } | ||||
buf_swrite(&iob, "\0"); | 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); | code = btpd_add(ipc, mi, mi_size, dpath, name); | ||||
if (code == 0 && start) { | if (code == 0 && start) { | ||||
struct ipc_torrent tspec; | struct ipc_torrent tspec; | ||||
@@ -276,3 +276,107 @@ find_btpd_dir(void) | |||||
asprintf(&res, "%s/.btpd", home); | asprintf(&res, "%s/.btpd", home); | ||||
return res; | 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; | |||||
} |
@@ -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); | void *read_file(const char *path, void *buf, size_t *size); | ||||
char *find_btpd_dir(void); | char *find_btpd_dir(void); | ||||
int make_abs_path(const char *in, char *out); | |||||
#endif | #endif |