From patchwork Fri Apr 1 03:22:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Conole X-Patchwork-Id: 604577 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3qbmt61Nyqz9sBM for ; Fri, 1 Apr 2016 14:23:09 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 89997108A9; Thu, 31 Mar 2016 20:22:58 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id D216A10899 for ; Thu, 31 Mar 2016 20:22:56 -0700 (PDT) Received: from bar6.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id 674AC162206 for ; Thu, 31 Mar 2016 21:22:56 -0600 (MDT) X-ASG-Debug-ID: 1459480976-0b32373533b63a0001-byXFYA Received: from mx3-pf3.cudamail.com ([192.168.14.3]) by bar6.cudamail.com with ESMTP id nFMac6Fb6rKF4B2P (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 31 Mar 2016 21:22:56 -0600 (MDT) X-Barracuda-Envelope-From: aconole@redhat.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.3 Received: from unknown (HELO mx1.redhat.com) (209.132.183.28) by mx3-pf3.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 1 Apr 2016 03:22:55 -0000 Received-SPF: pass (mx3-pf3.cudamail.com: SPF record at _spf1.redhat.com designates 209.132.183.28 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-Barracuda-RBL-IP: 209.132.183.28 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0262890E55; Fri, 1 Apr 2016 03:22:54 +0000 (UTC) Received: from aconole-fed23.redhat.com (vpn-61-171.rdu2.redhat.com [10.10.61.171]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u313Mngr005094; Thu, 31 Mar 2016 23:22:53 -0400 X-CudaMail-Envelope-Sender: aconole@redhat.com From: Aaron Conole To: dev@openvswitch.org, Flavio Leitner , Kevin Traynor , Panu Matilainen , RobertX Wojciechowicz , Sean K Mooney , Andy Zhou , Daniele Di Proietto , Zoltan Kiss , Christian Ehrhardt , Ben Pfaff X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-V3-330064222 X-CudaMail-DTE: 033116 X-CudaMail-Originating-IP: 209.132.183.28 Date: Thu, 31 Mar 2016 23:22:43 -0400 X-ASG-Orig-Subj: [##CM-V3-330064222##][PATCH 2/8] util: Add a path canonicalizer Message-Id: <1459480969-15593-3-git-send-email-aconole@redhat.com> In-Reply-To: <1459480969-15593-1-git-send-email-aconole@redhat.com> References: <1459480969-15593-1-git-send-email-aconole@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Barracuda-Connect: UNKNOWN[192.168.14.3] X-Barracuda-Start-Time: 1459480976 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Subject: [ovs-dev] [PATCH 2/8] util: Add a path canonicalizer X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" This commit adds a new function (ovs_realpath) to perform the role of realpath on various operating systems. The purpose is to ensure that a given path to file exists, and to return a completely resolved path (sans '.' and '..'). Signed-off-by: Aaron Conole --- v11: * Added configure.ac | 2 +- lib/util.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/util.h | 1 + tests/library.at | 5 +++++ tests/test-util.c | 23 +++++++++++++++++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 05d80d5..a490260 100644 --- a/configure.ac +++ b/configure.ac @@ -105,7 +105,7 @@ AC_CHECK_DECLS([sys_siglist], [], [], [[#include ]]) AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec], [], [], [[#include ]]) AC_CHECK_MEMBERS([struct ifreq.ifr_flagshigh], [], [], [[#include ]]) -AC_CHECK_FUNCS([mlockall strnlen getloadavg statvfs getmntent_r]) +AC_CHECK_FUNCS([mlockall strnlen getloadavg statvfs getmntent_r realpath]) AC_CHECK_HEADERS([mntent.h sys/statvfs.h linux/types.h linux/if_ether.h stdatomic.h]) AC_CHECK_HEADERS([net/if_mib.h], [], [], [[#include #include ]]) diff --git a/lib/util.c b/lib/util.c index 94311ac..6bb6d9e 100644 --- a/lib/util.c +++ b/lib/util.c @@ -2098,6 +2098,58 @@ is_stdout_a_tty(void) return (isatty(STDOUT_FILENO) && t && strcmp(t, "dumb") != 0); } +/* Derives, from the pathname pointed to by path, an absolute pathname that + * names the same file, whose resolution does not involve '.', '..' or + * symbolic links. If path is null or does not exist, returns NULL. + */ +char * +ovs_realpath(const char *path) +{ + if (!path) { + return NULL; + } + char *realpath_res = NULL; + +#ifdef HAVE_REALPATH + realpath_res = realpath(path, NULL); + if (realpath_res == NULL) { + goto error; + } + struct stat s; + int err = stat(realpath_res, &s); + if (err) { + goto error; + } + return realpath_res; +#elif defined(_WIN32) + realpath_res = xstrdup(path); + DWORD ret = GetFullPathName(path, strlen(realpath_res), realpath_res, + NULL); + if (ret == 0) { + goto error; + } else if (ret > strlen(realpath_res)) { + DWORD new_ret; + char *new_path = (char *)xrealloc(realpath_res, ret); + if (new_path == NULL) { + goto error; + } + realpath_res = new_path; + new_ret = GetFullPathName(path, strlen(realpath_res), realpath_res, + NULL); + if (new_ret == 0 || new_ret != ret ) { + goto error; + } + } + return realpath_res; +#else +#error Need realpath() on this platform +#endif + +error: + free(realpath_res); + return NULL; +} + #ifdef _WIN32 char * diff --git a/lib/util.h b/lib/util.h index 41c5ea6..8d7f335 100644 --- a/lib/util.h +++ b/lib/util.h @@ -220,6 +220,7 @@ char *dir_name(const char *file_name); char *base_name(const char *file_name); #endif char *abs_file_name(const char *dir, const char *file_name); +char *ovs_realpath(const char *path); char *follow_symlinks(const char *filename); diff --git a/tests/library.at b/tests/library.at index e1bac92..b6561e5 100644 --- a/tests/library.at +++ b/tests/library.at @@ -234,3 +234,8 @@ AT_CLEANUP AT_SETUP([test rcu]) AT_CHECK([ovstest test-rcu-quiesce], [0], []) AT_CLEANUP + +AT_SETUP([test ovs_realpath]) +AT_CHECK([ovstest test-util realpath \ +/tmp/../tmp/../usr/bin/.//../share:/usr/share /tmpNOEXISTS:], [0], []) +AT_CLEANUP diff --git a/tests/test-util.c b/tests/test-util.c index ef45903..2755200 100644 --- a/tests/test-util.c +++ b/tests/test-util.c @@ -1128,6 +1128,28 @@ test_snprintf(struct ovs_cmdl_context *ctx OVS_UNUSED) ovs_assert(snprintf(NULL, 0, "abcde") == 5); } +static void +test_ovs_realpath(struct ovs_cmdl_context *ctx) +{ + int i; + for (i = 1; i < ctx->argc; i++) { + char *str_toks = NULL; + char *path = strtok_r(ctx->argv[i], ":", &str_toks); + ovs_assert(path != NULL); + + char *check = strtok_r(NULL, ":", &str_toks); + char *rpath = ovs_realpath(path); + + if (check) { + ovs_assert(rpath != NULL); + ovs_assert(!strcmp(check, rpath)); + free(rpath); + } else { + ovs_assert(rpath == NULL); + } + } +} + #ifndef _WIN32 static void test_file_name(struct ovs_cmdl_context *ctx) @@ -1164,6 +1186,7 @@ static const struct ovs_cmdl_command commands[] = { {"assert", NULL, 0, 0, test_assert}, {"ovs_scan", NULL, 0, 0, test_ovs_scan}, {"snprintf", NULL, 0, 0, test_snprintf}, + {"realpath", NULL, 1, INT_MAX, test_ovs_realpath}, #ifndef _WIN32 {"file_name", NULL, 1, INT_MAX, test_file_name}, #endif