From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-3.7 required=3.0 tests=AWL,BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 23B4D1F4B4 for ; Sun, 13 Sep 2020 09:34:04 +0000 (UTC) Received: from localhost ([::1]:33080 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHOOY-0003GQ-Nb for normalperson@yhbt.net; Sun, 13 Sep 2020 05:34:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53524) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHOOU-0003GD-Fb for bug-gnulib@gnu.org; Sun, 13 Sep 2020 05:33:58 -0400 Received: from de.cellform.com ([88.217.224.109]:37524 helo=jocasta.intra) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHOOR-0007QL-Vf for bug-gnulib@gnu.org; Sun, 13 Sep 2020 05:33:57 -0400 Received: from jocasta.intra (localhost [127.0.0.1]) by jocasta.intra (8.15.2/8.15.2/Debian-14~deb10u1) with ESMTPS id 08D9Xgud017908 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sun, 13 Sep 2020 11:33:42 +0200 Received: (from john@localhost) by jocasta.intra (8.15.2/8.15.2/Submit) id 08D9XgOw017907; Sun, 13 Sep 2020 11:33:42 +0200 From: John Darrington To: bug-gnulib@gnu.org Subject: [PATCH] tmpdir.c (path_search_alloc): New function. Date: Sun, 13 Sep 2020 11:33:34 +0200 Message-Id: <20200913093334.17844-1-john@darrington.wattle.id.au> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=88.217.224.109; envelope-from=john@darrington.wattle.id.au; helo=jocasta.intra X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/13 05:33:43 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: "bug-gnulib" * lib/tmpdir.c (path_search_alloc): Define new function similar to path_search, but which allocates the buffer for the result instead of relying on the caller to preallocate it. *lib/tmpdir.h (path_search_alloc): Declare it. --- lib/tmpdir.c | 127 +++++++++++++++++++++++++++++++++++---------------- lib/tmpdir.h | 6 +++ 2 files changed, 93 insertions(+), 40 deletions(-) diff --git a/lib/tmpdir.c b/lib/tmpdir.c index 28ff99f58..70ab7007f 100644 --- a/lib/tmpdir.c +++ b/lib/tmpdir.c @@ -83,43 +83,23 @@ direxists (const char *dir) return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); } -/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is - non-null and exists, uses it; otherwise uses the first of $TMPDIR, - P_tmpdir, /tmp that exists. Copies into TMPL a template suitable - for use with mk[s]temp. Will fail (-1) if DIR is non-null and - doesn't exist, none of the searched dirs exists, or there's not - enough space in TMPL. */ -int -path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - bool try_tmpdir) + +static int +__path_search (char *tmpl, const char **dirx, const char *pfx, bool try_tmpdir) { const char *d; - size_t dlen, plen; - bool add_slash; - - if (!pfx || !pfx[0]) - { - pfx = "file"; - plen = 4; - } - else - { - plen = strlen (pfx); - if (plen > 5) - plen = 5; - } if (try_tmpdir) { d = __libc_secure_getenv ("TMPDIR"); if (d != NULL && direxists (d)) - dir = d; - else if (dir != NULL && direxists (dir)) + *dirx = d; + else if (*dirx != NULL && direxists (*dirx)) /* nothing */ ; else - dir = NULL; + *dirx = NULL; } - if (dir == NULL) + if (*dirx == NULL) { #if defined _WIN32 && ! defined __CYGWIN__ char dirbuf[PATH_MAX]; @@ -131,26 +111,63 @@ path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, directory (unless $TMPDIR is set). */ retval = GetTempPath (PATH_MAX, dirbuf); if (retval > 0 && retval < PATH_MAX && direxists (dirbuf)) - dir = dirbuf; + *dirx = dirbuf; else #endif - if (direxists (P_tmpdir)) - dir = P_tmpdir; - else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) - dir = "/tmp"; - else - { - __set_errno (ENOENT); - return -1; - } + if (direxists (P_tmpdir)) + *dirx = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + *dirx = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } } - dlen = strlen (dir); + return 0; +} + +static void +__impute_lengths (const char *pfx, const char *dir, size_t *plen, size_t *dlen, bool *add_slash) +{ + if (!pfx || !pfx[0]) + { + pfx = "file"; + *plen = 4; + } + else + { + *plen = strlen (pfx); + if (*plen > 5) + *plen = 5; + } + + *dlen = strlen (dir); #ifdef __VMS - add_slash = 0; + *add_slash = 0; #else - add_slash = dlen != 0 && !ISSLASH (dir[dlen - 1]); + *add_slash = *dlen != 0 && !ISSLASH (dir[*dlen - 1]); #endif +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + bool try_tmpdir) +{ + if (0 != __path_search (tmpl, &dir, pfx, try_tmpdir)) + return -1; + + size_t plen; + size_t dlen; + bool add_slash; + __impute_lengths (pfx, dir, &plen, &dlen, &add_slash); /* check we have room for "${dir}/${pfx}XXXXXX\0" */ if (tmpl_len < dlen + add_slash + plen + 6 + 1) @@ -163,3 +180,33 @@ path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, sprintf (tmpl + dlen, &"/%.*sXXXXXX"[!add_slash], (int) plen, pfx); return 0; } + + +/* Like path_search, but this function will allocate TMPL and fill + TMPL_LEN with the allocated length. The caller must free TMPL when + no longer required. */ +int +path_search_alloc (char **tmpl, size_t *tmpl_len, const char *dir, const char *pfx, + bool try_tmpdir) +{ + if (0 != __path_search (*tmpl, &dir, pfx, try_tmpdir)) + return -1; + + size_t plen; + size_t dlen; + bool add_slash; + __impute_lengths (pfx, dir, &plen, &dlen, &add_slash); + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + *tmpl = malloc (dlen + add_slash + plen + 6 + 1); + if (!*tmpl) + { + __set_errno (ENOMEM); + return -1; + } + *tmpl_len = dlen + add_slash + plen + 6 + 1; + + memcpy (*tmpl, dir, dlen); + sprintf (*tmpl + dlen, &"/%.*sXXXXXX"[!add_slash], (int) plen, pfx); + return 0; +} diff --git a/lib/tmpdir.h b/lib/tmpdir.h index 4d694a3d9..28c62fcc2 100644 --- a/lib/tmpdir.h +++ b/lib/tmpdir.h @@ -24,3 +24,9 @@ doesn't exist, none of the searched dirs exists, or there's not enough space in TMPL. */ extern int path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, bool try_tmpdir); + +/* Like path_search, except that TMPL is allocated automatically. + TMPL may not be null. *TMPL must be freed by the caller, when no longer needed. + After calling this function *TMPL_LEN will be set to the lenght of *TMPL. */ +extern int path_search_alloc (char **tmpl, size_t *tmpl_len, const char *dir, const char *pfx, + bool try_tmpdir); -- 2.20.1