From patchwork Fri May 29 03:06:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 136015 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9C3644BA2E33 for ; Fri, 29 May 2026 03:07:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9C3644BA2E33 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IAKyOJi5 X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 01E434BA2E04 for ; Fri, 29 May 2026 03:06:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 01E434BA2E04 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 01E434BA2E04 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780023994; cv=none; b=ZqTusuvL4XnJkE1cX150Kv7C3EWYZ5qQDsyzZPIwcAD3XeVBAN+lcv7SWS93ltK1H06S9+983M0rJxxzT4wf/WSdBh6iKJbCEkAlJlnCa3NNsXZ4nCieEXrcm60xJlN26pLRqKHnwrfo9ScOw1Gu0uk4qtYtJ22J6mECCXN0U38= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780023994; c=relaxed/simple; bh=vRaa0bYg08tiapdEpxzFS6mZHfZKALM2sl/KNHfJfVQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=G9+uk8Uvbz8zcuu/8rU+lzalPA0V8Mr+m3V7q4lrCLzyKCm3UGo888IFhLXkJjZw/FfUb8xJCypUjQCb9fNjulJPgDFJg7c6Vkdo8bNFy7gG4DtlwsLovL++ok4ITJ4908UbJrXRTTXxgYc4MA1rp2RrxoYmsw5gA1C6VCUbwww= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IAKyOJi5 DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 01E434BA2E04 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780023993; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type; bh=ecET+MJN+PxqYnnnQPkxvy4e9OwGsibBKNVGT7C0Occ=; b=IAKyOJi5S/NFRqVOXXyvT/U2HZn1fHDgwmx7J6hLFbUugN4ZifYFE3qpzeTVq90oZIUm1K K4crZVVZz8AkJmJ926Aw2OezHx9OGCtP10VaFhFi4+N9aC2eHBAjH/2KFwDj0hu1GHWf+7 lDcgPsuU9UgiAo6PDZ+Yq+GXTJrMPVU= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-144-hoz2S6x8PeigVddUSnCeTQ-1; Thu, 28 May 2026 23:06:30 -0400 X-MC-Unique: hoz2S6x8PeigVddUSnCeTQ-1 X-Mimecast-MFC-AGG-ID: hoz2S6x8PeigVddUSnCeTQ_1780023989 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 10540195608F; Fri, 29 May 2026 03:06:29 +0000 (UTC) Received: from greed.delorie.com (unknown [10.22.88.14]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C29CC30001BB; Fri, 29 May 2026 03:06:28 +0000 (UTC) Received: from greed.delorie.com.redhat.com (localhost [127.0.0.1]) by greed.delorie.com (8.16.1/8.16.1) with ESMTP id 64T36Rfh1444364; Thu, 28 May 2026 23:06:27 -0400 From: DJ Delorie To: Adhemerval Zanella Netto Cc: libc-alpha@sourceware.org Subject: [PATCH v2 1/1] ldconfig: add --install option Date: Thu, 28 May 2026 23:06:27 -0400 Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: BEks6OEoT-Qva0PHMHiwMY9HZ2xsGJ7pgnhzpmtimIA_1780023989 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_HOSTKARMA_W, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, RCVD_IN_SBL_CSS, SPF_HELO_PASS, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Add --install option, which copies a pre-built ld.so.cache into place, honoring the cache and root options and defaults. This gives the user a canonical "correct" way to install a pre-built cache. --- NEWS | 2 + elf/ldconfig.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index e2173fa1aa..484d09e6b3 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,8 @@ Major new features: * Static PIE is now supported for arm-*-linux-gnueabi. It requires toolchain support to correctly set the expected linker options. +* Pre-built ld.so.cache files can be installed with ldconfig. + Deprecated and removed features, and other changes affecting compatibility: * Although malloc and related functions currently return pointers diff --git a/elf/ldconfig.c b/elf/ldconfig.c index 070e933df6..df225df6e9 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -104,6 +104,9 @@ static int opt_manual_link; /* Should we ignore an old auxiliary cache file? */ static int opt_ignore_aux_cache; +/* Install a pre-existing cache file instead of generating a new one. */ +static int opt_install; + /* Cache file to use. */ static char *cache_file; @@ -132,6 +135,7 @@ static const struct argp_option options[] = { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0}, { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new (default), old, or compat"), 0}, { "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0}, + { "install", 'I', NULL, 0, N_("install pre-existing cache file"), 0}, { NULL, 0, NULL, 0, NULL, 0 } }; @@ -197,6 +201,9 @@ parse_opt (int key, char *arg, struct argp_state *state) else if (strcmp (arg, "new") == 0) opt_format = opt_format_new; break; + case 'I': + opt_install = 1; + break; default: return ARGP_ERR_UNKNOWN; } @@ -1045,8 +1052,8 @@ main (int argc, char **argv) argp_parse (&argp, argc, argv, 0, &remaining, NULL); /* Remaining arguments are additional directories if opt_manual_link - is not set. */ - if (remaining != argc && !opt_manual_link) + and opt_install are not set. */ + if (remaining != argc && !opt_manual_link && !opt_install) { int i; for (i = remaining; i < argc; ++i) @@ -1139,6 +1146,135 @@ main (int argc, char **argv) exit (0); } + if (opt_install) + { + if (argv[remaining] == NULL) + error (EXIT_FAILURE, 0, _("Missing source file name")); + + char *source = (opt_chroot + ? chroot_canon (opt_chroot, argv[remaining]) + : argv[remaining]); + if (source == NULL) + error (EXIT_FAILURE, errno, _("Can't find %s"), argv[remaining]); + + int src_fd = open (source, O_RDONLY); + if (src_fd < 0) + error (EXIT_FAILURE, errno, _("Can't open %s"), source); + + char *dest = xmalloc (strlen (cache_file) + 1 + 1); + + /* This matches the temp file created by cache.c, and should be + on the same filesystem as the cache file. */ + sprintf(dest, "%s~", cache_file); + int dest_fd; + + struct stat st; + if (fstat (src_fd, &st) < 0) + error (EXIT_FAILURE, errno, _("Can't stat %s"), source); + + char buf[512]; + int r, w, sz = 0; + char *bp = buf; + + /* Read the first part of the file and verify it looks + reasonable. */ + while (sz < sizeof (buf) + && (r = read (src_fd, bp, sizeof (buf) - sz)) > 0) + { + sz += r; + bp += r; + } + if (r < 0) + error (EXIT_FAILURE, errno, _("Error reading file %s"), source); + + if (! ((sz >= sizeof (CACHEMAGIC) + && memcmp (buf, CACHEMAGIC, + sizeof (CACHEMAGIC) - 1) == 0) + || (sz >= sizeof (CACHEMAGIC_NEW) + && memcmp (buf, CACHEMAGIC_NEW, + sizeof (CACHEMAGIC_NEW) - 1) == 0))) + { + error (EXIT_FAILURE, 0, + _("File %s does not look like an ld.so.cache file"), + source); + } + + /* If the two files are on the same filesystem, we can just + rename it. */ + if (rename (source, cache_file) == 0) + { + /* A simple rename was sufficient. */ + close (src_fd); + exit (0); + } + /* Otherwise, a cross-filesystem copy/rename is needed. */ + + /* Now write that first part out. */ + dest_fd = open (dest, O_WRONLY, 0644); + if (dest_fd < 0) + error (EXIT_FAILURE, errno, _("Can't create %s"), dest); + + r = sz; + bp = buf; + while (r > 0 && (w = write (dest_fd, bp, r)) > 0) + { + r -= w; + bp += w; + } + if (w < 0) + { + unlink (dest); + close (dest_fd); + error (EXIT_FAILURE, errno, _("Error writing file %s"), dest); + } + + /* At this point, sz contains the number of bytes copied so far. + Copy the rest of the file. */ + while ((r = read (src_fd, buf, sizeof(buf))) > 0) + { + bp = buf; + while (r > 0 && (w = write (dest_fd, bp, r)) > 0) + { + bp += r; + r -= w; + sz += w; + } + if (w <= 0) + break; + } + + close (src_fd); + + /* Make sure we copied it all. */ + if (sz < st.st_size) + { + unlink (dest); + close (dest_fd); + error (EXIT_FAILURE, errno, _("Unable to copy file %s to %s"), + source, dest); + } + + /* Make sure user can always read the cache file */ + if (fchmod (dest_fd, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR)) + { + unlink (dest); + close (dest_fd); + error (EXIT_FAILURE, errno, + _("Changing access rights of %s to %#o failed"), dest, + S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR); + } + + fsync (dest_fd); + if (rename (dest, cache_file) < 0) + { + unlink (dest); + close (dest_fd); + error (EXIT_FAILURE, errno, _("Can't rename %s to %s"), dest, cache_file); + } + + close (dest_fd); + exit (0); + } if (opt_build_cache) init_cache ();