9front - general discussion about 9front
 help / color / mirror / Atom feed
From: rgl@antares-labs.eu
To: 9front@9front.org
Subject: Re: [9front] tar: write directory metadata after file extraction
Date: Sun, 3 Nov 2019 16:35:24 +0100	[thread overview]
Message-ID: <E3098FCE6E69CEE3BEE51210589E15BA@antares-labs.eu> (raw)
In-Reply-To: AA5BAE62A5C074D149164AEF805412E6@antares-labs.eu

[-- Attachment #1: Type: text/plain, Size: 77 bytes --]

ok, here's the corrected version to keep the original directory mode intact.

[-- Attachment #2: Type: text/plain, Size: 2334 bytes --]

diff -r fe7fc19b1e64 sys/src/cmd/tar.c
--- a/sys/src/cmd/tar.c	Sun Nov 03 15:20:57 2019 +0100
+++ b/sys/src/cmd/tar.c	Sun Nov 03 16:31:09 2019 +0100
@@ -129,6 +129,13 @@
 	int	open;
 } Pushstate;
 
+typedef struct {
+	Hdr	*hp;
+	int	fd;
+	long	mtime;
+	ulong	mode;
+} Leftover;
+
 #define OTHER(rdwr) ((rdwr) == Rd? Wr: Rd)
 
 static int fixednblock;
@@ -153,6 +160,9 @@
 static Hdr *tpblk, *endblk;
 static Hdr *curblk;
 
+static Leftover *scraps;
+static int nscrap;
+
 static void
 usage(void)
 {
@@ -238,6 +248,40 @@
 	return docompress? comps: nil;
 }
 
+/* leftover directories management */
+
+static void wrmeta(int, Hdr*, long, int);
+
+static void
+pushleftover(Hdr *hp, int fd, long mtime, ulong mode)
+{
+	Leftover *l;
+
+	/* looking for a better alloc strategy */
+	scraps = realloc(scraps, ++nscrap*sizeof(Leftover));
+	if(scraps == nil)
+		sysfatal("realloc: %r");
+	l = scraps+(nscrap-1);
+	l->hp = hp;
+	l->fd = fd;
+	l->mtime = mtime;
+	l->mode = mode;
+}
+
+static void
+flushleftovers(void)
+{
+	Leftover *l;
+
+	while(nscrap-- > 0){
+		l = scraps+nscrap;
+		wrmeta(l->fd, l->hp, l->mtime, l->mode);
+		close(l->fd);
+	}
+	free(scraps);
+	scraps = nil;
+}
+
 /*
  * push a filter, cmd, onto fd.  if input, it's an input descriptor.
  * returns a descriptor to replace fd, or -1 on error.
@@ -1145,11 +1189,12 @@
 {
 	int fd = -1, dir = 0;
 	long mtime = strtol(hp->mtime, nil, 8);
-	ulong mode = strtoul(hp->mode, nil, 8) & 0777;
+	ulong mode0 = strtoul(hp->mode, nil, 8) & 0777, mode;
 	Off bytes = hdrsize(hp);		/* for printing */
 	ulong blksleft = BYTES2TBLKS(arsize(hp));
 
 	/* fiddle name, figure out mode and blocks */
+	mode = mode0;
 	if (isdir(hp)) {
 		mode |= DMDIR|0700;
 		dir = 1;
@@ -1182,14 +1227,14 @@
 
 	copyfromar(ar, fd, fname, blksleft, bytes);
 
-	/* touch up meta data and close */
+	/* touch up meta data and close, dirs are saved for later */
 	if (fd >= 0) {
-		/*
-		 * directories should be wstated *after* we're done
-		 * creating files in them, but we don't do that.
-		 */
 		if (settime)
-			wrmeta(fd, hp, mtime, mode);
+			if (dir) {
+				pushleftover(hp, fd, mtime, mode0);
+				return;
+			} else
+				wrmeta(fd, hp, mtime, mode0);
 		close(fd);
 	}
 }
@@ -1275,6 +1320,7 @@
 		else
 			skip(ar, hp, longname);
 	}
+	flushleftovers();
 
 	if (comp)
 		return pushclose(&ps);

                 reply	other threads:[~2019-11-03 15:35 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E3098FCE6E69CEE3BEE51210589E15BA@antares-labs.eu \
    --to=rgl@antares-labs.eu \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).