add URL parsing functions
authorPeter Lieven <pl@kamp.de>
Mon, 23 Dec 2013 13:03:00 +0000 (14:03 +0100)
committerPeter Lieven <pl@kamp.de>
Mon, 23 Dec 2013 13:03:00 +0000 (14:03 +0100)
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 <pl@kamp.de>
examples/nfs-ls.c
include/nfsc/libnfs.h
lib/libnfs.c

index 7aed4dfe6cc6260ce1fd1b88635d6b7d601cf615..b52a4351b07ad196379036f928823d9236499142 100644 (file)
@@ -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;
 }
 
index 094de3c27027bad8280853d924f6a2a1fd3aed9b..10358100f889a878388a18f840fdcb03b8ff80d4 100644 (file)
 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;
 
 /*
index 2e3e7f2d77e473bd6ccbee459bc442d316efce58..ec11ba5558ca30d592eea1069ee3e322e08864e2 100644 (file)
@@ -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;