bug-patch
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug-patch] Does patch ignore Linux ACLs?


From: Bruno Haible
Subject: Re: [bug-patch] Does patch ignore Linux ACLs?
Date: Sat, 16 Oct 2010 12:52:10 +0200
User-agent: KMail/1.9.9

[dropped bug-diffutils]

Paul Eggert wrote:
> > And suddenly the test file lost its ACL - do'h!
> 
> The file didn't lose its ACL.  What happens is that
> a copy was created, and then renamed over the original.
> At one point chmod is applied to the copy, so that it
> has the right permissions.  That's what removes the
> default ACL.
> 
> This does appear to be a bug.  One possible fix
> would be for 'patch' to not do the chmod unless it really
> needs to, which typically it doesn't.

This would only fix the case when 'patch' is used without option '-b'
AND the file resides on a different device than the temporary directory.
Then, as you say, the file is being copied over, and removing the 'chmod'
system call would fix the problem. Here's an 'strace' extract:

===============================================================================
$ patch < xx

open("/tmp/poDJ6nXu", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_LARGEFILE, 0100644) = 3

open("file1", O_RDONLY|O_LARGEFILE)     = 5
read(5, "Important notes\n---------------\n"..., 26738) = 26738
close(5)                                = 0

write(1, "patching file file1\n", 20)   = 20

write(3, "Important notes\n---------------\n"..., 4096) = 4096
write(3, "0-03-18  pty             This mo"..., 4096) = 4096
write(3, "ing convention of the functions\n"..., 4096) = 4096
write(3, "rs around Winsock functions, so "..., 4096) = 4096
write(3, " isnand-nolibm. The include file"..., 4096) = 4096
write(3, "here is also a new module gpl-3."..., 4096) = 4096
write(3, "L.\n            linked-list\n     "..., 2162) = 2162

close(3)                                = 0

rename("/tmp/poDJ6nXu", "file1")        = -1 EXDEV (Invalid cross-device link)
unlink("file1")                         = 0
open("file1", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0100644) = 3
open("/tmp/poDJ6nXu", O_RDONLY|O_LARGEFILE) = 5
read(5, "Important notes\n---------------\n"..., 8192) = 8192
write(3, "Important notes\n---------------\n"..., 8192) = 8192
read(5, "ing convention of the functions\n"..., 8192) = 8192
write(3, "ing convention of the functions\n"..., 8192) = 8192
read(5, " isnand-nolibm. The include file"..., 8192) = 8192
write(3, " isnand-nolibm. The include file"..., 8192) = 8192
read(5, "L.\n            linked-list\n     "..., 8192) = 2162
write(3, "L.\n            linked-list\n     "..., 2162) = 2162
read(5, "", 8192)                       = 0
close(5)                                = 0

close(3)                                = 0
chmod("file1", 0100644)                 = 0

unlink("/tmp/poDJ6nXu")                 = 0
===============================================================================

A different case is when 'patch -b' is used AND the file resides on a different
device than the temporary directory. In this case, the old file is renamed
away before the new contents is written. Therefore, you need to copy the ACL
from the old inode to the new inode. The easiest way to do so is using the
copy_acl() function from gnulib's 'acl' module. Note that copy_acl() should
then be used instead of chmod(), because on some systems, calling chmod()
erases the ACL. See gnulib/lib/copy-file.c for how it can be done.

===============================================================================
$ patch -b < xx

open("/tmp/poP0adpq", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_LARGEFILE, 0100644) = 3

open("file1", O_RDONLY|O_LARGEFILE)     = 5
read(5, "Important notes\n---------------\n"..., 26738) = 26738
close(5)                                = 0

write(1, "patching file file1\n", 20)   = 20

write(3, "Important notes\n---------------\n"..., 4096) = 4096
write(3, "0-03-18  pty             This mo"..., 4096) = 4096
write(3, "ing convention of the functions\n"..., 4096) = 4096
write(3, "rs around Winsock functions, so "..., 4096) = 4096
write(3, " isnand-nolibm. The include file"..., 4096) = 4096
write(3, "here is also a new module gpl-3."..., 4096) = 4096
write(3, "L.\n            linked-list\n     "..., 2162) = 2162

close(3)                                = 0

rename("file1", "file1.orig")           = 0
rename("/tmp/poP0adpq", "file1")        = -1 EXDEV (Invalid cross-device link)
open("file1", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0100644) = 3
open("/tmp/poP0adpq", O_RDONLY|O_LARGEFILE) = 5
read(5, "Important notes\n---------------\n"..., 8192) = 8192
write(3, "Important notes\n---------------\n"..., 8192) = 8192
read(5, "ing convention of the functions\n"..., 8192) = 8192
write(3, "ing convention of the functions\n"..., 8192) = 8192
read(5, " isnand-nolibm. The include file"..., 8192) = 8192
write(3, " isnand-nolibm. The include file"..., 8192) = 8192
read(5, "L.\n            linked-list\n     "..., 8192) = 2162
write(3, "L.\n            linked-list\n     "..., 2162) = 2162
read(5, "", 8192)                       = 0
close(5)                                = 0

close(3)                                = 0
chmod("file1", 0100644)                 = 0

unlink("/tmp/poP0adpq")                 = 0
===============================================================================

If, however, the file resides on the same device as the temporary directory,
the rename() system call succeeds, and the chmod() call is actually necessary.
'patch' needs to copy the ACL, and it needs to do it _before_ renaming the file
(because after renaming it, the original inode is gone and with it the ACL).

===============================================================================
$ patch < xx

open("/tmp/pous2L8Y", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_LARGEFILE, 0100644) = 3

open("file1", O_RDONLY|O_LARGEFILE)     = 5
read(5, "Important notes\n---------------\n"..., 26738) = 26738
close(5)                                = 0

write(1, "patching file file1\n", 20)   = 20

write(3, "Important notes\n---------------\n"..., 4096) = 4096
write(3, "0-03-18  pty             This mo"..., 4096) = 4096
write(3, "ing convention of the functions\n"..., 4096) = 4096
write(3, "rs around Winsock functions, so "..., 4096) = 4096
write(3, " isnand-nolibm. The include file"..., 4096) = 4096
write(3, "here is also a new module gpl-3."..., 4096) = 4096
write(3, "L.\n            linked-list\n     "..., 2162) = 2162

close(3)                                = 0

rename("/tmp/pous2L8Y", "file1")        = 0
chmod("file1", 0100644)                 = 0

unlink("/tmp/pous2L8Y")                 = -1 ENOENT (No such file or directory)
===============================================================================

Bruno



reply via email to

[Prev in Thread] Current Thread [Next in Thread]