From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from blue.oak.relay.mailchannels.net (blue.oak.relay.mailchannels.net [23.83.215.20]) by sourceware.org (Postfix) with ESMTPS id 150C93858032; Wed, 19 Jan 2022 10:21:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 150C93858032 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gotplt.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 6944862225E; Wed, 19 Jan 2022 10:14:15 +0000 (UTC) Received: from pdx1-sub0-mail-a306.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 2BF2962215B; Wed, 19 Jan 2022 10:14:04 +0000 (UTC) Received: from pdx1-sub0-mail-a306.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.114.196.230 (trex/6.4.3); Wed, 19 Jan 2022 10:14:15 +0000 Received: from [192.168.1.174] (unknown [1.186.224.209]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a306.dreamhost.com (Postfix) with ESMTPSA id 4Jf1hB2ZpDz1Pb; Wed, 19 Jan 2022 02:14:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gotplt.org; s=gotplt.org; t=1642587243; bh=NYjibWaT5+MAzAGVIHx6ZDdtUfI=; h=Date:Subject:To:From:Content-Type:Content-Transfer-Encoding; b=EXxpX5MtmtMDqsZgDkEVltqoBsCQLp+cVmf9OobiM1ulvEluC/N4GlI2JCldtAdm/ /gKMYRbPgZ4pdQ0L4KV1dhXcusboNYvvSORSjxQEJBOuO6W4SvqwMIv//iK+cAUMOG KF4ht2IiZ7e888Q/siPzo3QHfCujc89ztCPbUOPY= Message-ID: <6b838050-35ef-f867-6553-b50016b0ba14@gotplt.org> Date: Wed, 19 Jan 2022 15:43:56 +0530 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.4.0 Subject: Re: [PATCH v2 1/3] support: Add helpers to create paths longer than PATH_MAX Content-Language: en-US To: Siddhesh Poyarekar , libc-alpha@sourceware.org References: <20220119082147.3352868-1-siddhesh@sourceware.org> <20220119082147.3352868-2-siddhesh@sourceware.org> From: Siddhesh Poyarekar In-Reply-To: <20220119082147.3352868-2-siddhesh@sourceware.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-3036.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, NICE_REPLY_A, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Jan 2022 10:21:09 -0000 On 19/01/2022 13:51, Siddhesh Poyarekar via Libc-alpha wrote: > Add new helpers support_create_and_chdir_toolong_temp_directory and > support_chdir_toolong_temp_directory to create and descend into > directory trees longer than PATH_MAX. > > Signed-off-by: Siddhesh Poyarekar > --- > support/temp_file.c | 173 +++++++++++++++++++++++++++++++++++++++++--- > support/temp_file.h | 9 +++ > 2 files changed, 173 insertions(+), 9 deletions(-) > > diff --git a/support/temp_file.c b/support/temp_file.c > index e7bb8aadb9..59060e573f 100644 > --- a/support/temp_file.c > +++ b/support/temp_file.c > @@ -1,5 +1,6 @@ > /* Temporary file handling for tests. > Copyright (C) 1998-2022 Free Software Foundation, Inc. > + Copyright The GNU Tools Authors. > This file is part of the GNU C Library. > > The GNU C Library is free software; you can redistribute it and/or > @@ -20,15 +21,17 @@ > some 32-bit platforms. */ > #define _FILE_OFFSET_BITS 64 > > +#include > #include > #include > #include > > +#include > #include > #include > #include > #include > -#include > +#include > > /* List of temporary files. */ > static struct temp_name_list > @@ -36,14 +39,32 @@ static struct temp_name_list > struct temp_name_list *next; > char *name; > pid_t owner; > + bool toolong; > } *temp_name_list; > > /* Location of the temporary files. Set by the test skeleton via > support_set_test_dir. The string is not be freed. */ > static const char *test_dir = _PATH_TMP; > > -void > -add_temp_file (const char *name) > +/* Name of subdirectories in a too long temporary directory tree. */ > +static char *toolong_subdir; > +static bool toolong_subdir_initialized; > + > +/* Return the maximum size of path on the target. */ > +static inline size_t > +get_path_max (void) > +{ > +#ifdef PATH_MAX > + return PATH_MAX; > +#else > + size_t path_max = pathconf ("/", _PC_PATH_MAX); > + return (path_max < 0 ? 1024 > + : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX); > +#endif > +} > + > +static void > +add_temp_file_internal (const char *name, bool toolong) > { > struct temp_name_list *newp > = (struct temp_name_list *) xcalloc (sizeof (*newp), 1); > @@ -53,12 +74,19 @@ add_temp_file (const char *name) > newp->name = newname; > newp->next = temp_name_list; > newp->owner = getpid (); > + newp->toolong = toolong; > temp_name_list = newp; > } > else > free (newp); > } > > +void > +add_temp_file (const char *name) > +{ > + add_temp_file_internal (name, false); > +} > + > int > create_temp_file_in_dir (const char *base, const char *dir, char **filename) > { > @@ -90,8 +118,8 @@ create_temp_file (const char *base, char **filename) > return create_temp_file_in_dir (base, test_dir, filename); > } > > -char * > -support_create_temp_directory (const char *base) > +static char * > +create_temp_directory_internal (const char *base, bool toolong) > { > char *path = xasprintf ("%s/%sXXXXXX", test_dir, base); > if (mkdtemp (path) == NULL) > @@ -99,16 +127,132 @@ support_create_temp_directory (const char *base) > printf ("error: mkdtemp (\"%s\"): %m", path); > exit (1); > } > - add_temp_file (path); > + add_temp_file_internal (path, toolong); > return path; > } > > -/* Helper functions called by the test skeleton follow. */ > +char * > +support_create_temp_directory (const char *base) > +{ > + return create_temp_directory_internal (base, false); > +} > + > +static void > +ensure_toolong_subdir_initialized (void) > +{ > + if (!toolong_subdir_initialized) > + FAIL_EXIT1 ("uninitialized toolong directory tree\n"); > +} > + > +static void > +initialize_toolong_subdir (void) > +{ > + size_t sz = NAME_MAX; > + char testname[NAME_MAX]; > + int ret; > + > + if (toolong_subdir_initialized) > + return; > + > + memset (testname, 'X', sz - 1); > + > + /* Explore the name limit on the file system. This should typically be > + NAME_MAX, but it could be less on some fuse filesystems. */ > + do > + { > + struct stat statbuf; > + > + testname[sz - 1] = '\0'; > + ret = stat (testname, &statbuf); > + } > + while (ret != 0 && errno == ENAMETOOLONG && (sz = sz / 2) > 0); > + > + if (ret != 0 && errno == ENAMETOOLONG) > + FAIL_EXIT1 ("stat (%s) failed with ENAMETOOLONG\n", testname); > + > + toolong_subdir = xmalloc (sz); > + strcpy (toolong_subdir, testname); > + toolong_subdir_initialized = true; > +} > + > +char * > +support_create_and_chdir_toolong_temp_directory (const char *basename) > +{ > + size_t path_max = get_path_max (); > + > + char *base = create_temp_directory_internal (basename, true); > + > + xchdir (base); > + > + initialize_toolong_subdir (); > + > + size_t sz = strlen (toolong_subdir); > + > + /* Create directories and descend into them so that the final path is larger > + than PATH_MAX. */ > + for (size_t i = 0; i <= path_max / sz; i++) > + { > + xmkdir (toolong_subdir, S_IRWXU); This still doesn't work on the trybot, which somehow fails with ENAMETOOLONG even though stat() on that length worked in initialize_toolong_subdir. I'm going to need to reproduce the environment properly to figure out what's going on. Siddhesh > + xchdir (toolong_subdir); > + } > + return base; > +} > > void > -support_set_test_dir (const char *path) > +support_chdir_toolong_temp_directory (const char *base) > { > - test_dir = path; > + size_t path_max = get_path_max (); > + ensure_toolong_subdir_initialized (); > + > + xchdir (base); > + > + size_t sz = strlen (toolong_subdir); > + for (size_t i = 0; i <= path_max / sz; i++) > + xchdir (toolong_subdir); > +} > + > +/* Helper functions called by the test skeleton follow. */ > + > +static void > +remove_toolong_subdirs (const char *base) > +{ > + size_t path_max = get_path_max (); > + > + ensure_toolong_subdir_initialized (); > + > + if (chdir (base) != 0) > + { > + printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n", > + base); > + return; > + } > + > + /* Descend. */ > + int levels = 0; > + size_t sz = strlen (toolong_subdir); > + for (levels = 0; levels <= path_max / sz; levels++) > + if (chdir (toolong_subdir) != 0) > + { > + printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n", > + toolong_subdir); > + return; > + } > + > + /* Ascend and remove. */ > + while (--levels >= 0) > + { > + if (chdir ("..") != 0) > + { > + printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n"); > + return; > + } > + if (remove (toolong_subdir) != 0) > + { > + printf ("warning: could not remove subdirectory: %s: %m\n", > + toolong_subdir); > + return; > + } > + } > } > > void > @@ -123,6 +267,9 @@ support_delete_temp_files (void) > around, to prevent PID reuse.) */ > if (temp_name_list->owner == pid) > { > + if (temp_name_list->toolong) > + remove_toolong_subdirs (temp_name_list->name); > + > if (remove (temp_name_list->name) != 0) > printf ("warning: could not remove temporary file: %s: %m\n", > temp_name_list->name); > @@ -133,6 +280,8 @@ support_delete_temp_files (void) > free (temp_name_list); > temp_name_list = next; > } > + > + free (toolong_subdir); > } > > void > @@ -147,3 +296,9 @@ support_print_temp_files (FILE *f) > fprintf (f, ")\n"); > } > } > + > +void > +support_set_test_dir (const char *path) > +{ > + test_dir = path; > +} > diff --git a/support/temp_file.h b/support/temp_file.h > index 50a443abe4..8459ddda72 100644 > --- a/support/temp_file.h > +++ b/support/temp_file.h > @@ -44,6 +44,15 @@ int create_temp_file_in_dir (const char *base, const char *dir, > returns. The caller should free this string. */ > char *support_create_temp_directory (const char *base); > > +/* Create a temporary directory tree that is longer than PATH_MAX and schedule > + it for deletion. BASENAME is used as a prefix for the unique directory > + name, which the function returns. The caller should free this string. */ > +char *support_create_and_chdir_toolong_temp_directory (const char *basename); > + > +/* Change into the innermost directory of the directory tree BASE, which was > + created using support_create_and_chdir_toolong_temp_directory. */ > +void support_chdir_toolong_temp_directory (const char *base); > + > __END_DECLS > > #endif /* SUPPORT_TEMP_FILE_H */