From patchwork Thu Nov 29 01:50:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 202640 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "userp1040.oracle.com", Issuer "VeriSign Class 3 International Server CA - G3" (not verified)) by ozlabs.org (Postfix) with ESMTPS id DF6C32C0086 for ; Thu, 29 Nov 2012 12:50:28 +1100 (EST) Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) by userp1040.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id qAT1oP3K031619 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 29 Nov 2012 01:50:26 GMT Received: from oss.oracle.com (oss-external.oracle.com [137.254.96.51]) by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id qAT1oPCR000072 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 29 Nov 2012 01:50:25 GMT Received: from localhost ([127.0.0.1] helo=oss.oracle.com) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1TdtGj-00083E-2o; Wed, 28 Nov 2012 17:50:25 -0800 Received: from ucsinet21.oracle.com ([156.151.31.93]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1TdtGd-000833-Oa for fedfs-utils-devel@oss.oracle.com; Wed, 28 Nov 2012 17:50:19 -0800 Received: from acsinet13.oracle.com (acsinet13.oracle.com [141.146.126.235]) by ucsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id qAT1oIQv029667 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 29 Nov 2012 01:50:19 GMT Received: from mail-ia0-f171.google.com (mail-ia0-f171.google.com [209.85.210.171]) by acsinet13.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id qAT1nQXC002765 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Thu, 29 Nov 2012 01:50:18 GMT Received: by mail-ia0-f171.google.com with SMTP id b35so8185184iac.2 for ; Wed, 28 Nov 2012 17:50:18 -0800 (PST) Received: by 10.50.182.166 with SMTP id ef6mr21446102igc.65.1354153818048; Wed, 28 Nov 2012 17:50:18 -0800 (PST) Received: from seurat.1015granger.net (adsl-99-26-161-222.dsl.sfldmi.sbcglobal.net. [99.26.161.222]) by mx.google.com with ESMTPS id eo7sm195913igc.12.2012.11.28.17.50.17 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 28 Nov 2012 17:50:17 -0800 (PST) From: Chuck Lever To: fedfs-utils-devel@oss.oracle.com Date: Wed, 28 Nov 2012 20:50:16 -0500 Message-ID: <20121129015016.2497.67318.stgit@seurat.1015granger.net> In-Reply-To: <20121129014751.2497.93909.stgit@seurat.1015granger.net> References: <20121129014751.2497.93909.stgit@seurat.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Flow-Control-Info: class=Default reputation=ipRepBelow100 ip=209.85.210.171 ct-class=R5 ct-vol1=-97 ct-vol2=8 ct-vol3=7 ct-risk=49 ct-spam1=78 ct-spam2=8 ct-bulk=5 rcpts=1 size=10536 X-MM-CT-Classification: not spam X-MM-CT-RefID: str=0001.0A090202.50B6BF5A.004D,ss=1,re=-2.300,fgs=0 Subject: [fedfs-utils] [PATCH 6/8] libnsdb: Add URI pathname parser helpers X-BeenThere: fedfs-utils-devel@oss.oracle.com X-Mailman-Version: 2.1.9 Precedence: list Reply-To: fedfs-utils Developers List-Id: fedfs-utils Developers List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: fedfs-utils-devel-bounces@oss.oracle.com Errors-To: fedfs-utils-devel-bounces@oss.oracle.com X-Source-IP: acsinet22.oracle.com [141.146.126.238] 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 --- 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 #include +#include #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 #include +#include #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