svn commit: r367809 - head/contrib/elftoolchain/elfcopy

Dimitry Andric dim at FreeBSD.org
Wed Nov 18 18:41:00 UTC 2020


Author: dim
Date: Wed Nov 18 18:40:58 2020
New Revision: 367809
URL: https://svnweb.freebsd.org/changeset/base/367809

Log:
  When elftoolchain's objcopy (or strip) is rewriting a file in-place,
  make it create the temporary file in the same directory as the source
  file by default, instead of always using $TMPDIR or /tmp. If creating
  that file fails because the directory is not writable, also fallback to
  $TMPDIR or /tmp.
  
  This has also been submitted upstream as:
  https://sourceforge.net/p/elftoolchain/tickets/597/
  
  Reported by:	cem
  PR:		250872
  MFC after:	2 weeks

Modified:
  head/contrib/elftoolchain/elfcopy/archive.c
  head/contrib/elftoolchain/elfcopy/elfcopy.h
  head/contrib/elftoolchain/elfcopy/main.c

Modified: head/contrib/elftoolchain/elfcopy/archive.c
==============================================================================
--- head/contrib/elftoolchain/elfcopy/archive.c	Wed Nov 18 17:50:33 2020	(r367808)
+++ head/contrib/elftoolchain/elfcopy/archive.c	Wed Nov 18 18:40:58 2020	(r367809)
@@ -68,7 +68,7 @@ process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj
 	int		 fd;
 
 	/* Output to a temporary file. */
-	create_tempfile(&tempfile, &fd);
+	create_tempfile(NULL, &tempfile, &fd);
 	if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL)
 		errx(EXIT_FAILURE, "elf_begin() failed: %s",
 		    elf_errmsg(-1));

Modified: head/contrib/elftoolchain/elfcopy/elfcopy.h
==============================================================================
--- head/contrib/elftoolchain/elfcopy/elfcopy.h	Wed Nov 18 17:50:33 2020	(r367808)
+++ head/contrib/elftoolchain/elfcopy/elfcopy.h	Wed Nov 18 18:40:58 2020	(r367809)
@@ -298,7 +298,7 @@ void	create_scn(struct elfcopy *_ecp);
 void	create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
 void	create_symtab(struct elfcopy *_ecp);
 void	create_symtab_data(struct elfcopy *_ecp);
-void	create_tempfile(char **_fn, int *_fd);
+void	create_tempfile(const char *_src, char **_fn, int *_fd);
 void	finalize_external_symtab(struct elfcopy *_ecp);
 void	free_elf(struct elfcopy *_ecp);
 void	free_sec_act(struct elfcopy *_ecp);

Modified: head/contrib/elftoolchain/elfcopy/main.c
==============================================================================
--- head/contrib/elftoolchain/elfcopy/main.c	Wed Nov 18 17:50:33 2020	(r367808)
+++ head/contrib/elftoolchain/elfcopy/main.c	Wed Nov 18 18:40:58 2020	(r367809)
@@ -512,44 +512,57 @@ free_elf(struct elfcopy *ecp)
 
 /* Create a temporary file. */
 void
-create_tempfile(char **fn, int *fd)
+create_tempfile(const char *src, char **fn, int *fd)
 {
+	static const char _TEMPDIR[] = "/tmp/";
+	static const char _TEMPFILE[] = "ecp.XXXXXXXX";
 	const char	*tmpdir;
-	char		*cp, *tmpf;
-	size_t		 tlen, plen;
+	char		*tmpf;
+	size_t		 tlen, slen, plen;
 
-#define	_TEMPFILE "ecp.XXXXXXXX"
-#define	_TEMPFILEPATH "/tmp/ecp.XXXXXXXX"
-
 	if (fn == NULL || fd == NULL)
 		return;
-	/* Repect TMPDIR environment variable. */
-	tmpdir = getenv("TMPDIR");
-	if (tmpdir != NULL && *tmpdir != '\0') {
-		tlen = strlen(tmpdir);
-		plen = strlen(_TEMPFILE);
-		tmpf = malloc(tlen + plen + 2);
+	for (;;) {
+		if (src == NULL) {
+			/* Respect TMPDIR environment variable. */
+			tmpdir = getenv("TMPDIR");
+			if (tmpdir == NULL || *tmpdir == '\0')
+				tmpdir = _TEMPDIR;
+			tlen = strlen(tmpdir);
+			slen = tmpdir[tlen - 1] == '/' ? 0 : 1;
+		} else {
+			/* Create temporary file relative to source file. */
+			if ((tmpdir = strrchr(src, '/')) == NULL) {
+				/* No path, only use a template filename. */
+				tlen = 0;
+			} else {
+				/* Append the template after the slash. */
+				tlen = ++tmpdir - src;
+				tmpdir = src;
+			}
+			slen = 0;
+		}
+		plen = strlen(_TEMPFILE) + 1;
+		tmpf = malloc(tlen + slen + plen);
 		if (tmpf == NULL)
 			err(EXIT_FAILURE, "malloc failed");
-		strncpy(tmpf, tmpdir, tlen);
-		cp = &tmpf[tlen - 1];
-		if (*cp++ != '/')
-			*cp++ = '/';
-		strncpy(cp, _TEMPFILE, plen);
-		cp[plen] = '\0';
-	} else {
-		tmpf = strdup(_TEMPFILEPATH);
-		if (tmpf == NULL)
-			err(EXIT_FAILURE, "strdup failed");
+		if (tlen > 0)
+			memcpy(tmpf, tmpdir, tlen);
+		if (slen > 0)
+			tmpf[tlen] = '/';
+		/* Copy template filename including NUL terminator. */
+		memcpy(tmpf + tlen + slen, _TEMPFILE, plen);
+		if ((*fd = mkstemp(tmpf)) != -1)
+			break;
+		if (errno != EACCES || src == NULL)
+			err(EXIT_FAILURE, "mkstemp %s failed", tmpf);
+		/* Permission denied, try again using TMPDIR or /tmp. */
+		free(tmpf);
+		src = NULL;
 	}
-	if ((*fd = mkstemp(tmpf)) == -1)
-		err(EXIT_FAILURE, "mkstemp %s failed", tmpf);
 	if (fchmod(*fd, 0644) == -1)
 		err(EXIT_FAILURE, "fchmod %s failed", tmpf);
 	*fn = tmpf;
-
-#undef _TEMPFILE
-#undef _TEMPFILEPATH
 }
 
 /*
@@ -571,16 +584,16 @@ copy_from_tempfile(const char *src, const char *dst, i
 		if (rename(src, dst) >= 0) {
 			*outfd = infd;
 			return (0);
-		} else if (errno != EXDEV)
+		} else if (errno != EXDEV && errno != EACCES)
 			return (-1);
-	
+
 		/*
 		 * If the rename() failed due to 'src' and 'dst' residing in
 		 * two different file systems, invoke a helper function in
 		 * libelftc to do the copy.
 		 */
 
-		if (unlink(dst) < 0)
+		if (errno != EACCES && unlink(dst) < 0)
 			return (-1);
 	}
 
@@ -630,7 +643,7 @@ create_file(struct elfcopy *ecp, const char *src, cons
 		err(EXIT_FAILURE, "fstat %s failed", src);
 
 	if (dst == NULL)
-		create_tempfile(&tempfile, &ofd);
+		create_tempfile(src, &tempfile, &ofd);
 	else
 		if ((ofd = open(dst, O_RDWR|O_CREAT, 0755)) == -1)
 			err(EXIT_FAILURE, "open %s failed", dst);
@@ -663,7 +676,7 @@ create_file(struct elfcopy *ecp, const char *src, cons
 			if (ecp->oed == ELFDATANONE)
 				ecp->oed = ELFDATA2LSB;
 		}
-		create_tempfile(&elftemp, &efd);
+		create_tempfile(src, &elftemp, &efd);
 		if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL)
 			errx(EXIT_FAILURE, "elf_begin() failed: %s",
 			    elf_errmsg(-1));
@@ -723,7 +736,7 @@ create_file(struct elfcopy *ecp, const char *src, cons
 					    tempfile);
 				free(tempfile);
 			}
-			create_tempfile(&tempfile, &ofd0);
+			create_tempfile(src, &tempfile, &ofd0);
 
 
 			/*


More information about the svn-src-head mailing list