X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=0.8 required=5.0 tests=BAYES_50,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org To: cygwin AT cygwin DOT com From: Dan Grayson Subject: Re: untarring symlinks with ../ fails randomly Date: Tue, 26 Apr 2011 15:08:52 +0000 (UTC) Lines: 69 Message-ID: References: <20110424121145 DOT GB30696 AT calimero DOT vinschen DOT de> <20110426074325 DOT GP3324 AT calimero DOT vinschen DOT de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit User-Agent: Loom/3.14 (http://gmane.org/) X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com (Re-posting yet again, didn't get through yesterday or today (?), this time from a different account.) Corinna, Debugging with gdb shows that "tar" is prepared for the possibility that symbolic links don't work and that hard links will have to be used instead. So, when it encounters a symbolic link, it creates a zero-length file with mode 0 as a placeholder, and it records the inode number of the new file. That way it can wait until all the regular files have been created, and then replace the placeholder by a symbolic link, or if that doesn't work, by a hard link to the existing file. However, a tar file can contain multiple entries corresponding to the same file name or path, so it may happen that the placeholder is no longer present at the end, having been replaced by another file. Hence, it will only replace the placeholder if the inode number and the creation time are unchanged. But, under cygwin, the creation time may change gratuitously after the creation of the file, at random! Hence the placeholder is sometimes left in place. My system is Windows 7. Here is a C program (simple test case) that illustrates it. #include #include #include #include #include int main () { static struct stat s; int i; char * fn [12] = { "tmpdir/a","tmpdir/b","tmpdir/c","tmpdir/d","tmpdir/e","tmpdir/f", "tmpdir/g","tmpdir/h","tmpdir/i","tmpdir/j","tmpdir/k","tmpdir/l" }; struct timespec ctime[12]; mkdir("tmpdir",0755); for (i=0; i<12; i++) { int fd = open(fn[i],O_EXCL|O_CREAT|O_WRONLY,0); fstat(fd,&s); ctime[i] = s.st_ctim; close(fd); } sleep(1); for (i=0; i<12; i++) { struct timespec ctime2; stat(fn[i],&s); ctime2 = s.st_ctim; if (ctime[i].tv_nsec != ctime2.tv_nsec) printf("ctime changed: file %s, %lu.%09lu -> %lu.%09lu\n", fn[i], ctime[i].tv_sec, ctime[i].tv_nsec, ctime2.tv_sec, ctime2.tv_nsec); } return 0; } Here is some sample output from the program. $ rm -rf tmpdir && gcc -Wall p.c && ./a.exe ctime changed: file tmpdir/c, 1303742293.177618900 -> 1303742293.178619000 ctime changed: file tmpdir/f, 1303742293.178619000 -> 1303742293.179619000 ctime changed: file tmpdir/h, 1303742293.179619000 -> 1303742293.180619100 ctime changed: file tmpdir/k, 1303742293.180619100 -> 1303742293.181619100 -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple