We're about to introduce support for encoding NFSv4 pathnames in
an NFS URI.  Add helpers for handling the details.

Note that this commit adds a new build dependency: liburiparser.
Not all current distributions have liburiparser.  RHEL / OL 6
do not have it, for example.

Signed-off-by: Chuck Lever <[email protected]>
---

 configure.ac               |    5 +
 src/fedfsd/Makefile.am     |    1 
 src/include/nsdb.h         |    7 +
 src/libnsdb/path.c         |  229 ++++++++++++++++++++++++++++++++++++++++++++
 src/nfsref/Makefile.am     |    1 
 src/nsdbc/Makefile.am      |    1 
 src/nsdbparams/Makefile.am |    1 
 7 files changed, 245 insertions(+), 0 deletions(-)

diff --git a/configure.ac b/configure.ac
index 9a848c5..31634cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,6 +123,11 @@ AC_CHECK_LIB([xml2], [xmlParseFile],
                 AC_DEFINE([HAVE_LIBXML2], [1],
                           [Define if you have libxml2])],
                [AC_MSG_ERROR([libxml2 not found.])])
+AC_CHECK_LIB([uriparser], [uriParseUriA],
+               [AC_SUBST([LIBURIPARSER], ["-luriparser"])
+                AC_DEFINE([HAVE_LIBURIPARSER], [1],
+                          [Define if you have liburiparser])],
+               [AC_MSG_ERROR([liburiparser not found.])])
 
 # Checks for header files.
 AC_CHECK_HEADERS([fcntl.h langinfo.h locale.h memory.h netdb.h netinet/in.h 
stdint.h stdlib.h string.h sys/socket.h syslog.h termios.h unistd.h wchar.h])
diff --git a/src/fedfsd/Makefile.am b/src/fedfsd/Makefile.am
index 47ee106..29050c2 100644
--- a/src/fedfsd/Makefile.am
+++ b/src/fedfsd/Makefile.am
@@ -29,6 +29,7 @@ sbin_PROGRAMS         = fedfsd
 fedfsd_SOURCES         = listen.c main.c privilege.c svc.c
 fedfsd_LDADD           = $(LIBTIRPC) $(LIBLDAP) $(LIBLBER) $(LIBXML2) \
                          $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) $(LIBCAP) \
+                         $(LIBURIPARSER) \
                          $(top_builddir)/src/libadmin/libadmin.la \
                          $(top_builddir)/src/libnsdb/libnsdb.la \
                          $(top_builddir)/src/libjunction/libjunction.la \
diff --git a/src/include/nsdb.h b/src/include/nsdb.h
index a115fae..d6c6841 100644
--- a/src/include/nsdb.h
+++ b/src/include/nsdb.h
@@ -28,6 +28,7 @@
 
 #include <netdb.h>
 #include <ldap.h>
+#include <uriparser/Uri.h>
 
 #include "fedfs_admin.h"
 #include "fedfs.h"
@@ -414,5 +415,11 @@ FedFsStatus         nsdb_path_array_to_fedfspathname(char 
* const *path_array,
                                FedFsPathName *fpath);
 FedFsStatus     nsdb_fedfspathname_to_path_array(FedFsPathName fpath,
                                char ***path_array);
+void            nsdb_assign_textrange(UriTextRangeA *text,
+                               const char *string);
+FedFsStatus     nsdb_path_array_to_uri_pathname(char * const *path_array,
+                               UriUriA *uri);
+FedFsStatus     nsdb_uri_pathname_to_path_array(const UriUriA *uri,
+                               char ***path_array);
 
 #endif /* !_FEDFS_NSDB_H_ */
diff --git a/src/libnsdb/path.c b/src/libnsdb/path.c
index e5506ea..6894ee2 100644
--- a/src/libnsdb/path.c
+++ b/src/libnsdb/path.c
@@ -38,6 +38,7 @@
 #include <ldap.h>
 
 #include <netinet/in.h>
+#include <uriparser/Uri.h>
 
 #include "nsdb.h"
 #include "junction.h"
@@ -723,3 +724,231 @@ nsdb_fedfspathname_to_path_array(FedFsPathName fpath, 
char ***path_array)
        *path_array = result;
        return FEDFS_OK;
 }
+
+/**
+ * Assign the value of "string" to a UriTextRangeA field
+ *
+ * @param text UriTextRangeA field to assign
+ * @param string NUL-terminated C string
+ *
+ * Note: "string" must not be freed until the text range
+ * is no longer used.
+ *
+ * Note: string is assumed to contain only single-width
+ * characters.
+ */
+void
+nsdb_assign_textrange(UriTextRangeA *text, const char *string)
+{
+       text->first = string;
+       text->afterLast = string + strlen(string);
+}
+
+/**
+ * Allocate a UriPathSegmentA
+ *
+ * @param name NUL-terminated C string containing path segment
+ * @return freshly allocated UriPathSegmentA object
+ */
+static UriPathSegmentA *
+nsdb_new_uri_path_segment(const char *name)
+{
+       UriPathSegmentA *new;
+
+       new = (UriPathSegmentA *)calloc(1, sizeof(*new));
+       if (new != NULL)
+               nsdb_assign_textrange(&new->text, name);
+       return new;
+}
+
+/**
+ * Release a list of UriPathSegmentA objects
+ *
+ * @param pos head of UriPathSegmentA list
+ */
+static void
+nsdb_free_path_segments(UriPathSegmentA *pos)
+{
+       UriPathSegmentA *next;
+
+       while (pos != NULL) {
+               next = pos->next;
+               free(pos);
+               pos = next;
+       }
+}
+
+/**
+ * Marshal the pathname component of an NFS URI
+ *
+ * @param path_array array of pointers to NUL-terminated C strings
+ * @param uri OUT: a filled-in UriUriA structure
+ * @return a FedFsStatus code
+ *
+ * Caller must free the members of the UriUriA object with
+ * uriFreeUriMembersA().
+ *
+ * @todo Proper i18n of pathname segments
+ */
+FedFsStatus
+nsdb_path_array_to_uri_pathname(char * const *path_array, UriUriA *uri)
+{
+       UriPathSegmentA *pos, *result;
+       size_t length, len;
+       char *component;
+       unsigned int i;
+
+       pos = nsdb_new_uri_path_segment("");
+       if (pos == NULL)
+               return FEDFS_ERR_SVRFAULT;
+       result = pos;
+
+       length = 0;
+       for (i = 0; path_array[i] != NULL; i++) {
+               component = path_array[i];
+               len = strlen(component);
+
+               if (len == 0) {
+                       xlog(D_GENERAL, "%s: Zero-length component", __func__);
+                       return FEDFS_ERR_BADNAME;
+               }
+               if (len > NAME_MAX) {
+                       xlog(D_GENERAL, "%s: Component length too long", 
__func__);
+                       return FEDFS_ERR_NAMETOOLONG;
+               }
+               if (strchr(component, '/') != NULL) {
+                       xlog(D_GENERAL, "%s: Local separator character "
+                                       "found in component", __func__);
+                       return FEDFS_ERR_BADNAME;
+               }
+               if (!nsdb_pathname_is_utf8(component)) {
+                       xlog(D_GENERAL, "%s: Bad character in component",
+                               __func__);
+                       return FEDFS_ERR_BADCHAR;
+               }
+
+               length += STRLEN_SLASH + len;
+
+               if (length > PATH_MAX) {
+                       xlog(D_GENERAL, "%s: Pathname too long", __func__);
+                       return FEDFS_ERR_NAMETOOLONG;
+               }
+
+               pos->next = nsdb_new_uri_path_segment(component);
+               if (pos->next == NULL) {
+                       nsdb_free_path_segments(result);
+                       return FEDFS_ERR_SVRFAULT;
+               }
+               pos = pos->next;
+       }
+
+       uri->pathHead = result;
+       return FEDFS_OK;
+}
+
+/**
+ * Return length in bytes of a URI pathname segment
+ *
+ * @param segment URI pathname segment
+ * @return count of bytes in segment
+ *
+ * XXX: Isn't there a uriparser API that does this?
+ */
+static size_t
+nsdb_uri_pathname_segment_size(const UriPathSegmentA *segment)
+{
+       if (segment->text.first == NULL)
+               return 0;
+       return segment->text.afterLast - segment->text.first;
+}
+
+/**
+ * Return number of segments in a URI pathname
+ *
+ * @param uri filled-in URI
+ * @return count of segments
+ *
+ * XXX: Isn't there a uriparser API that does this?
+ */
+static unsigned int
+nsdb_uri_pathname_segment_count(const UriUriA *uri)
+{
+       UriPathSegmentA *pos;
+       unsigned int result;
+
+       if (uri->pathHead->text.first == NULL)
+               return 0;
+
+       result = 1;
+       for (pos = uri->pathHead; pos != uri->pathTail; pos = pos->next)
+               result++;
+       return result;
+}
+
+/**
+ * Unmarshal the pathname component of an NFS URI
+ *
+ * @param uri a filled-in UriUriA structure
+ * @param path_array OUT: array of pointers to NUL-terminated C strings
+ * @return a FedFsStatus code
+ *
+ * Caller must free "path_array" with nsdb_free_string_array().
+ *
+ * @todo Proper i18n of pathname segments
+ * @todo Handling too many slashes in various places
+ */
+FedFsStatus
+nsdb_uri_pathname_to_path_array(const UriUriA *uri, char ***path_array)
+{
+       unsigned int i, count;
+       UriPathSegmentA *pos;
+       char **result = NULL;
+
+       if (uri->pathHead == NULL) {
+               xlog(D_GENERAL, "%s: NFS URI has no pathname component", 
__func__);
+               return FEDFS_ERR_BADNAME;
+       }
+
+       count = nsdb_uri_pathname_segment_count(uri);
+       if (count < 2) {
+               xlog(D_GENERAL, "%s: NFS URI has short pathname component", 
__func__);
+               return FEDFS_ERR_BADNAME;
+       }
+
+       pos = uri->pathHead->next;
+       if (count == 2 && nsdb_uri_pathname_segment_size(pos) == 0)
+               return nsdb_alloc_zero_component_pathname(path_array);
+
+       result = (char **)calloc(count + 1, sizeof(char *));
+       if (result == NULL) {
+               xlog(L_ERROR, "%s: Failed to allocate array",
+                       __func__);
+               return FEDFS_ERR_SVRFAULT;
+       }
+
+       for (i = 0; pos != NULL; pos = pos->next) {
+               size_t len;
+
+               len = nsdb_uri_pathname_segment_size(pos);
+               if (len > NAME_MAX) {
+                       nsdb_free_string_array(result);
+                       xlog(D_GENERAL, "%s: Component length too long",
+                               __func__);
+                       return FEDFS_ERR_NAMETOOLONG;
+               }
+               if (len == 0)
+                       continue;
+
+               result[i] = strndup((char *)pos->text.first, len);
+               if (result[i] == NULL) {
+                       nsdb_free_string_array(result);
+                       xlog(L_ERROR, "%s: Failed to allocate component string",
+                               __func__);
+                       return FEDFS_ERR_SVRFAULT;
+               }
+               i++;
+       }
+
+       *path_array = result;
+       return FEDFS_OK;
+}
diff --git a/src/nfsref/Makefile.am b/src/nfsref/Makefile.am
index 284d4b4..c8ef8c9 100644
--- a/src/nfsref/Makefile.am
+++ b/src/nfsref/Makefile.am
@@ -28,6 +28,7 @@ sbin_PROGRAMS         = nfsref
 nfsref_SOURCES         = add.c lookup.c nfsref.c remove.c
 LDADD                  = $(LIBLDAP) $(LIBLBER) $(LIBXML2) \
                          $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) \
+                         $(LIBURIPARSER) \
                          $(top_builddir)/src/libnsdb/libnsdb.la \
                          $(top_builddir)/src/libxlog/libxlog.la \
                          $(top_builddir)/src/libjunction/libjunction.la
diff --git a/src/nsdbc/Makefile.am b/src/nsdbc/Makefile.am
index bf0e057..e64d259 100644
--- a/src/nsdbc/Makefile.am
+++ b/src/nsdbc/Makefile.am
@@ -30,6 +30,7 @@ sbin_PROGRAMS         = nsdb-annotate nsdb-describe nsdb-list 
\
                          nsdb-create-fsl nsdb-delete-fsl nsdb-update-fsl
 LDADD                  = $(LIBLDAP) $(LIBLBER) $(LIBXML2) \
                          $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) \
+                         $(LIBURIPARSER) \
                          $(top_builddir)/src/libnsdb/libnsdb.la \
                          $(top_builddir)/src/libxlog/libxlog.la \
                          $(top_builddir)/src/libjunction/libjunction.la
diff --git a/src/nsdbparams/Makefile.am b/src/nsdbparams/Makefile.am
index 7b7911a..9deb9ea 100644
--- a/src/nsdbparams/Makefile.am
+++ b/src/nsdbparams/Makefile.am
@@ -28,6 +28,7 @@ sbin_PROGRAMS         = nsdbparams
 nsdbparams_SOURCES     = delete.c list.c main.c show.c update.c
 LDADD                  = $(LIBLDAP) $(LIBLBER) $(LIBXML2) \
                          $(LIBSQLITE3) $(LIBIDN) $(LIBUUID) $(LIBCAP) \
+                         $(LIBURIPARSER) \
                          $(top_builddir)/src/libnsdb/libnsdb.la \
                          $(top_builddir)/src/libjunction/libjunction.la \
                          $(top_builddir)/src/libxlog/libxlog.la


_______________________________________________
fedfs-utils-devel mailing list
[email protected]
https://oss.oracle.com/mailman/listinfo/fedfs-utils-devel

Reply via email to