From owner-svn-src-head@freebsd.org Fri Jul 10 00:24:42 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id E92F535A68A; Fri, 10 Jul 2020 00:24:42 +0000 (UTC) (envelope-from eugen@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4B2v1k5wDfz3bVk; Fri, 10 Jul 2020 00:24:42 +0000 (UTC) (envelope-from eugen@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id AE223196F0; Fri, 10 Jul 2020 00:24:42 +0000 (UTC) (envelope-from eugen@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 06A0Og1D081216; Fri, 10 Jul 2020 00:24:42 GMT (envelope-from eugen@FreeBSD.org) Received: (from eugen@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06A0OgPW081215; Fri, 10 Jul 2020 00:24:42 GMT (envelope-from eugen@FreeBSD.org) Message-Id: <202007100024.06A0OgPW081215@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: eugen set sender to eugen@FreeBSD.org using -f From: Eugene Grosbein Date: Fri, 10 Jul 2020 00:24:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r363064 - head/usr.bin/xinstall X-SVN-Group: head X-SVN-Commit-Author: eugen X-SVN-Commit-Paths: head/usr.bin/xinstall X-SVN-Commit-Revision: 363064 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Jul 2020 00:24:43 -0000 Author: eugen Date: Fri Jul 10 00:24:42 2020 New Revision: 363064 URL: https://svnweb.freebsd.org/changeset/base/363064 Log: Optimize install(1) a bit. Currently, "install -s -S" behaviour is inefficient for upgrade. First it finds that destination file already exists and copies source file to temporary file. Then it calls strip(1) with name of temporary file as single agrument and our strip(1) creates another temporary file in the /tmp (or TMPDIR) making another copy that is finally copied to DESTDIR third time. Meantime, strip(1) has an option "-o dst" to specify destination so install(1) is allowed to skip initial copying from obj to DESTDIR. This change makes it do so. Take a look at https://reviews.freebsd.org/D25551 for details and efficiency numbers (in short: upto 32% gained for installword). MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D25551 Modified: head/usr.bin/xinstall/xinstall.c Modified: head/usr.bin/xinstall/xinstall.c ============================================================================== --- head/usr.bin/xinstall/xinstall.c Fri Jul 10 00:24:06 2020 (r363063) +++ head/usr.bin/xinstall/xinstall.c Fri Jul 10 00:24:42 2020 (r363064) @@ -147,7 +147,7 @@ static void install_dir(char *); static void metadata_log(const char *, const char *, struct timespec *, const char *, const char *, off_t); static int parseid(const char *, id_t *); -static void strip(const char *); +static int strip(const char *, const char *, char **); static int trymmap(int); static void usage(void); @@ -767,12 +767,13 @@ install(const char *from_name, const char *to_name, u_ { struct stat from_sb, temp_sb, to_sb; struct timespec tsb[2]; - int devnull, files_match, from_fd, serrno, target; + int devnull, files_match, from_fd, serrno, stripped, target; int tempcopy, temp_fd, to_fd; char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN]; char *digestresult; - files_match = 0; + digestresult = NULL; + files_match = stripped = 0; from_fd = -1; to_fd = -1; @@ -858,19 +859,24 @@ install(const char *from_name, const char *to_name, u_ (void)printf("install: %s -> %s\n", from_name, to_name); } - if (!devnull) - digestresult = copy(from_fd, from_name, to_fd, - tempcopy ? tempfile : to_name, from_sb.st_size); - else - digestresult = NULL; + if (!devnull) { + if (dostrip) + stripped = strip(tempcopy ? tempfile : to_name, + from_name, &digestresult); + else + digestresult = copy(from_fd, from_name, to_fd, + tempcopy ? tempfile : to_name, from_sb.st_size); + } } if (dostrip) { - strip(tempcopy ? tempfile : to_name); + if (!stripped) + (void)strip(tempcopy ? tempfile : to_name, NULL, + &digestresult); /* - * Re-open our fd on the target, in case we used a strip - * that does not work in-place -- like GNU binutils strip. + * Re-open our fd on the target, in case + * we did not strip in-place. */ close(to_fd); to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY, 0); @@ -1057,7 +1063,9 @@ install(const char *from_name, const char *to_name, u_ /* * compare -- - * compare two files; non-zero means files differ + * Compare two files; non-zero means files differ. + * Compute digest and return its address in *dresp + * unless it points to pre-computed digest. */ static int compare(int from_fd, const char *from_name __unused, size_t from_len, @@ -1066,15 +1074,17 @@ compare(int from_fd, const char *from_name __unused, s { char *p, *q; int rv; - int done_compare; + int do_digest, done_compare; DIGEST_CTX ctx; rv = 0; if (from_len != to_len) return 1; + do_digest = (digesttype != DIGEST_NONE && dresp != NULL && + *dresp == NULL); if (from_len <= MAX_CMP_SIZE) { - if (dresp != NULL) + if (do_digest) digest_init(&ctx); done_compare = 0; if (trymmap(from_fd) && trymmap(to_fd)) { @@ -1090,7 +1100,7 @@ compare(int from_fd, const char *from_name __unused, s } rv = memcmp(p, q, from_len); - if (dresp != NULL) + if (do_digest) digest_update(&ctx, p, from_len); munmap(p, from_len); munmap(q, from_len); @@ -1117,7 +1127,8 @@ compare(int from_fd, const char *from_name __unused, s rv = 1; /* out of sync */ } else rv = 1; /* read failure */ - digest_update(&ctx, buf1, n1); + if (do_digest) + digest_update(&ctx, buf1, n1); } lseek(from_fd, 0, SEEK_SET); lseek(to_fd, 0, SEEK_SET); @@ -1125,7 +1136,7 @@ compare(int from_fd, const char *from_name __unused, s } else rv = 1; /* don't bother in this case */ - if (dresp != NULL) { + if (do_digest) { if (rv == 0) *dresp = digest_end(&ctx, NULL); else @@ -1298,13 +1309,16 @@ copy(int from_fd, const char *from_name, int to_fd, co /* * strip -- - * use strip(1) to strip the target file + * Use strip(1) to strip the target file. + * Just invoke strip(1) on to_name if from_name is NULL, + * else try to run "strip -o to_name -- from_name" and return 0 on failure. + * Return 1 on success and assign result of digest_file(to_name) to *dresp. */ -static void -strip(const char *to_name) +static int +strip(const char *to_name, const char *from_name, char **dresp) { const char *stripbin; - const char *args[3]; + const char *args[6]; pid_t pid; int error, status; @@ -1312,8 +1326,16 @@ strip(const char *to_name) if (stripbin == NULL) stripbin = "strip"; args[0] = stripbin; - args[1] = to_name; - args[2] = NULL; + if (from_name == NULL) { + args[1] = to_name; + args[2] = NULL; + } else { + args[1] = "-o"; + args[2] = to_name; + args[3] = "--"; + args[4] = from_name; + args[5] = NULL; + } error = posix_spawnp(&pid, stripbin, NULL, NULL, __DECONST(char **, args), environ); if (error != 0) { @@ -1329,9 +1351,14 @@ strip(const char *to_name) } if (status != 0) { (void)unlink(to_name); + if (from_name != NULL) + return (0); errx(EX_SOFTWARE, "strip command %s failed on %s", stripbin, to_name); } + if (dresp != NULL) + *dresp = digest_file(to_name); + return (1); } /*