From: Peter Lieven Date: Mon, 23 Dec 2013 13:03:00 +0000 (+0100) Subject: add URL parsing functions X-Git-Tag: upstream/1.9.6^2~163^2~5 X-Git-Url: https://git.piment-noir.org/?p=deb_libnfs.git;a=commitdiff_plain;h=d2ec73c75a60604419171f6ea086a702607ad69f add URL parsing functions this adds the following 4 functions. see libnfs.h for details. struct nfs_url *nfs_parse_url_full(struct nfs_context *nfs, char *url); struct nfs_url *nfs_parse_url_dir(struct nfs_context *nfs, char *url); struct nfs_url *nfs_parse_url_incomplete(struct nfs_context *nfs, char *url); void nfs_destroy_url(struct nfs_url *url); Signed-off-by: Peter Lieven --- diff --git a/examples/nfs-ls.c b/examples/nfs-ls.c index 7aed4df..b52a435 100644 --- a/examples/nfs-ls.c +++ b/examples/nfs-ls.c @@ -152,13 +152,13 @@ void process_dir(struct nfs_context *nfs, char *dir, int level) { int main(int argc, char *argv[]) { struct nfs_context *nfs = NULL; - int i, ret, res; + int i, ret = 1, res; uint64_t offset; struct client client; struct nfsfh *nfsfh; struct statvfs stvfs; + struct nfs_url *url; exports export, tmp; - const char *url = NULL; char *server = NULL, *path = NULL, *strp; #ifdef WIN32 @@ -172,12 +172,9 @@ int main(int argc, char *argv[]) aros_init_socket(); #endif - url = argv[argc - 1]; - - if (url == NULL) { + if (argc < 2) { fprintf(stderr, "No URL specified.\n"); - print_usage(); - exit(10); + goto finished; } for (i=1; i < argc -1; i++) { @@ -186,80 +183,53 @@ int main(int argc, char *argv[]) } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--summary")) { summary++; } else { - print_usage(); - exit(10); + goto finished; } } - if (strncmp(url, "nfs://", 6)) { - fprintf(stderr, "Invalid URL specified.\n"); - print_usage(); - exit(10); - } - - server = strdup(url + 6); - if (server == NULL) { - fprintf(stderr, "Failed to strdup server string\n"); - exit(10); - } - if (server[0] == '/' || server[0] == '\0') { - fprintf(stderr, "Invalid server string.\n"); - free(server); - exit(10); - } - strp = strchr(server, '/'); - if (strp == NULL) { - fprintf(stderr, "Invalid URL specified.\n"); - print_usage(); - free(server); - exit(10); - } - path = strdup(strp); - if (path == NULL) { - fprintf(stderr, "Failed to strdup server string\n"); - free(server); - exit(10); - } - if (path[0] != '/') { - fprintf(stderr, "Invalid path.\n"); - free(server); - free(path); - exit(10); - } - *strp = 0; - - client.server = server; - client.export = path; - client.is_finished = 0; - nfs = nfs_init_context(); if (nfs == NULL) { printf("failed to init context\n"); goto finished; } - ret = nfs_mount(nfs, client.server, client.export); - if (ret != 0) { - printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs)); + url = nfs_parse_url_dir(nfs, argv[argc - 1]); + if (url == NULL) { + fprintf(stderr, "%s\n", nfs_get_error(nfs)); + goto finished; + } + + client.server = url->server; + client.export = url->path; + client.is_finished = 0; + + if (nfs_mount(nfs, client.server, client.export) != 0) { + fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(nfs)); goto finished; } process_dir(nfs, "", 16); if (summary) { - ret = nfs_statvfs(nfs, "/", &stvfs); - if (ret != 0) { + if (nfs_statvfs(nfs, "/", &stvfs) != 0) { goto finished; } printf("\n%12" PRId64 " of %12" PRId64 " bytes free.\n", stvfs.f_frsize * stvfs.f_bfree, stvfs.f_frsize * stvfs.f_blocks); } + + ret = 0; + finished: + if (ret) { + print_usage(); + } free(server); free(path); + nfs_destroy_url(url); if (nfs != NULL) { nfs_destroy_context(nfs); } - return 0; + return ret; } diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h index 094de3c..1035810 100644 --- a/include/nfsc/libnfs.h +++ b/include/nfsc/libnfs.h @@ -28,6 +28,12 @@ struct nfs_context; struct rpc_context; +struct nfs_url { + char *server; + char *path; + char *file; +}; + #if defined(WIN32) #define EXTERN __declspec( dllexport ) #else @@ -106,6 +112,31 @@ EXTERN struct nfs_context *nfs_init_context(void); EXTERN void nfs_destroy_context(struct nfs_context *nfs); +/* + * Parse a complete NFS URL including, server, path and + * filename. Fail if any component is missing. + */ +EXTERN struct nfs_url *nfs_parse_url_full(struct nfs_context *nfs, const char *url); + +/* + * Parse an NFS URL, but do not split path and file. File + * in the resulting struct remains NULL. + */ +EXTERN struct nfs_url *nfs_parse_url_dir(struct nfs_context *nfs, const char *url); + +/* + * Parse an NFS URL, but do not fail if file, path or even server is missing. + * Check elements of the resulting struct for NULL. + */ +EXTERN struct nfs_url *nfs_parse_url_incomplete(struct nfs_context *nfs, const char *url); + + +/* + * Free the URL struct returned by the nfs_parse_url_* functions. + */ +EXTERN void nfs_destroy_url(struct nfs_url *url); + + struct nfsfh; /* diff --git a/lib/libnfs.c b/lib/libnfs.c index 2e3e7f2..ec11ba5 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -173,6 +173,145 @@ char *nfs_get_error(struct nfs_context *nfs) return rpc_get_error(nfs->rpc); }; +static struct nfs_url *nfs_parse_url(struct nfs_context *nfs, char *url, int dir, int incomplete) +{ + struct nfs_url *urls; + char *strp, *flagsp, *strp2; + + if (strncmp(url, "nfs://", 6)) { + rpc_set_error(nfs->rpc, "Invalid URL specified"); + return NULL; + } + + urls = malloc(sizeof(struct nfs_url)); + if (urls == NULL) { + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + + urls->server = strdup(url + 6); + if (urls->server == NULL) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + + if (urls->server[0] == '/' || urls->server[0] == '\0' || + urls->server[0] == '?') { + if (incomplete) { + flagsp = strchr(urls->server, '?'); + goto flags; + } + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Invalid server string"); + return NULL; + } + + strp = strchr(urls->server, '/'); + if (strp == NULL) { + if (incomplete) { + flagsp = strchr(urls->server, '?'); + goto flags; + } + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified."); + return NULL; + } + + urls->path = strdup(strp); + if (urls->path == NULL) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + *strp = 0; + + if (dir) { + flagsp = strchr(urls->path, '?'); + goto flags; + } + + strp = strrchr(urls->path, '/'); + if (strp == NULL) { + if (incomplete) { + flagsp = strchr(urls->path, '?'); + goto flags; + } + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified."); + return NULL; + } + urls->file = strdup(strp); + if (urls->path == NULL) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + *strp = 0; + flagsp = strchr(urls->file, '?'); + +flags: + if (flagsp) { + *flagsp = 0; + } + + if (urls->file && !strlen(urls->file)) { + free(urls->file); + urls->file = NULL; + if (!incomplete) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified."); + return NULL; + } + } + + if (urls->server && strlen(urls->server) <= 1) { + free(urls->server); + urls->server = NULL; + } + + while (flagsp != NULL && *(flagsp+1) != 0) { + strp = flagsp + 1; + flagsp = strchr(strp, '&'); + if (flagsp) { + *flagsp = 0; + } + strp2 = strchr(strp, '='); + if (strp2) { + *strp2 = 0; + strp2++; + } + } + + return urls; +} + +struct nfs_url *nfs_parse_url_full(struct nfs_context *nfs, const char *url) +{ + return nfs_parse_url(nfs, url, 0, 0); +} + +struct nfs_url *nfs_parse_url_dir(struct nfs_context *nfs, const char *url) +{ + return nfs_parse_url(nfs, url, 1, 0); +} + +struct nfs_url *nfs_parse_url_incomplete(struct nfs_context *nfs, const char *url) +{ + return nfs_parse_url(nfs, url, 0, 1); +} + + +void nfs_destroy_url(struct nfs_url *url) +{ + if (url) { + free(url->server); + free(url->path); + free(url->file); + } + free(url); +} + struct nfs_context *nfs_init_context(void) { struct nfs_context *nfs;