From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ua1-x92f.google.com (mail-ua1-x92f.google.com [IPv6:2607:f8b0:4864:20::92f]) by sourceware.org (Postfix) with ESMTPS id 218D83858C2C for ; Fri, 21 Jan 2022 16:27:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 218D83858C2C Received: by mail-ua1-x92f.google.com with SMTP id b16so17849694uaq.4 for ; Fri, 21 Jan 2022 08:27:47 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:cc:references:from:in-reply-to :content-transfer-encoding; bh=Sk+a9vFtpkokEWGe1tR3xh6r98eMnyoLF4ST102iRW0=; b=AyVKke3DxQ4U3CMN5SRDPELXrnfo+HYS8Axw5h3GNcmxz9Q3aBkE/d0YmzFKDlbiDP x3aILxLIHh+6n52GmLu/6NKFjHVo3GkcJRMo8JFMAE79gGiVxBcqJ/bSOpi5+xIYmFxw fayQFjHUvU2x5ndkyNzzvxU3CAru/WDwBTMkW1t9yMds/lr7Iv1h4YOrOEXitY0Tjlq6 pcrSbDX+p8CmCtxnSzZvfo6bpgDMy1gepGESid8853gPmw5LC0cOwKpZ5ebjaxkFe+w2 0jMFHtDsQWtLhwRlQ5ggHucYKZK0psyshesC/ZGpAc0bGWpcPKSlWLVAryzjO9/1frWS Myjw== X-Gm-Message-State: AOAM5303mwyY+DThRLObZQw1cP/QXcxYvpD1C2CokpDWdGkV1LJzPPQD Tgoxp7OgnEdpdejlz5jLlrvIVg== X-Google-Smtp-Source: ABdhPJwMW7+09HXHxBJq8rLrvN2XYMJsPbl+MaZK/MhaOWamVbCp3Q49F5gdeS5mjf5rO0ocQXN5FA== X-Received: by 2002:a05:6102:b0a:: with SMTP id b10mr1870192vst.39.1642782466392; Fri, 21 Jan 2022 08:27:46 -0800 (PST) Received: from ?IPV6:2804:431:c7cb:27f8:f8b7:bc61:9607:9ecb? ([2804:431:c7cb:27f8:f8b7:bc61:9607:9ecb]) by smtp.gmail.com with ESMTPSA id y127sm1489433vkc.12.2022.01.21.08.27.44 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 21 Jan 2022 08:27:46 -0800 (PST) Message-ID: Date: Fri, 21 Jan 2022 13:27:42 -0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0 Subject: Re: [PATCH v3 1/3] support: Add helpers to create paths longer than PATH_MAX Content-Language: en-US To: Siddhesh Poyarekar , libc-alpha@sourceware.org Cc: eggert@cs.ucla.edu, fweimer@redhat.com References: <20220119082147.3352868-1-siddhesh@sourceware.org> <20220120093252.1911498-1-siddhesh@sourceware.org> <20220120093252.1911498-2-siddhesh@sourceware.org> From: Adhemerval Zanella In-Reply-To: <20220120093252.1911498-2-siddhesh@sourceware.org> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, NICE_REPLY_A, 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: Fri, 21 Jan 2022 16:27:49 -0000 On 20/01/2022 06:32, Siddhesh Poyarekar 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 LGTM, thanks. Reviewed-by: Adhemerval Zanella > --- > support/temp_file.c | 159 +++++++++++++++++++++++++++++++++++++++++--- > support/temp_file.h | 9 +++ > 2 files changed, 159 insertions(+), 9 deletions(-) > > diff --git a/support/temp_file.c b/support/temp_file.c > index e7bb8aadb9..e41128c2d4 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,20 @@ 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[NAME_MAX + 1]; > +static bool toolong_initialized; > +static size_t toolong_path_max; > + I think it is suffice for current tests, although it would need to change if any tests requires more than one large path. > +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 +62,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 +106,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 +115,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_initialized (void) > +{ > + if (!toolong_initialized) > + FAIL_EXIT1 ("uninitialized toolong directory tree\n"); > +} > + > +static void > +initialize_toolong (const char *base) > +{ > + long name_max = pathconf (base, _PC_NAME_MAX); > + name_max = (name_max < 0 ? 64 > + : (name_max < sizeof (toolong_subdir) ? name_max > + : sizeof (toolong_subdir) - 1)); > + > + long path_max = pathconf (base, _PC_PATH_MAX); > + path_max = (path_max < 0 ? 1024 > + : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX); > + > + /* Sanity check to ensure that the test does not create temporary directories > + in different filesystems because this API doesn't support it. */ > + if (toolong_initialized) > + { > + if (name_max != strlen (toolong_subdir)) > + FAIL_UNSUPPORTED ("name_max: Temporary directories in different" > + " filesystems not supported yet\n"); > + if (path_max != toolong_path_max) > + FAIL_UNSUPPORTED ("path_max: Temporary directories in different" > + " filesystems not supported yet\n"); > + return; > + } > + > + toolong_path_max = path_max; > + > + size_t len = name_max; > + memset (toolong_subdir, 'X', len); > + toolong_initialized = true; > +} > + Ok. > +char * > +support_create_and_chdir_toolong_temp_directory (const char *basename) > +{> + char *base = create_temp_directory_internal (basename, true); > + xchdir (base); > + > + initialize_toolong (base); > + > + 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 <= toolong_path_max / sz; i++) > + { > + int ret = mkdir (toolong_subdir, S_IRWXU); > + if (ret != 0 && errno == ENAMETOOLONG) > + FAIL_UNSUPPORTED ("Filesystem does not support creating too long " > + "directory trees\n"); > + else if (ret != 0) > + FAIL_EXIT1 ("Failed to create directory tree: %m\n"); > + xchdir (toolong_subdir); > + } > + return base; > +} > > void > -support_set_test_dir (const char *path) > +support_chdir_toolong_temp_directory (const char *base) > { > - test_dir = path; > + ensure_toolong_initialized (); > + > + xchdir (base); > + > + size_t sz = strlen (toolong_subdir); > + for (size_t i = 0; i <= toolong_path_max / sz; i++) > + xchdir (toolong_subdir); > +} > + > +/* Helper functions called by the test skeleton follow. */ > + > +static void > +remove_toolong_subdirs (const char *base) > +{ > + ensure_toolong_initialized (); > + > + if (chdir (base) != 0) > + { > + printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n", > + base); > + return; > + } I think there is no much we co in such case. > + > + /* Descend. */ > + int levels = 0; > + size_t sz = strlen (toolong_subdir); > + for (levels = 0; levels <= toolong_path_max / sz; levels++) > + if (chdir (toolong_subdir) != 0) > + { > + printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n", > + toolong_subdir); > + break; > + } > + > + /* 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 +255,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); > @@ -147,3 +282,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 */