forked from pool/patch
97 lines
2.4 KiB
Diff
97 lines
2.4 KiB
Diff
---
|
|
patch.c | 2 +-
|
|
util.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
util.h | 1 +
|
|
3 files changed, 52 insertions(+), 1 deletion(-)
|
|
|
|
Index: b/patch.c
|
|
===================================================================
|
|
--- a/patch.c
|
|
+++ b/patch.c
|
|
@@ -440,7 +440,7 @@ main (int argc, char **argv)
|
|
{
|
|
move_file (TMPREJNAME, &TMPREJNAME_needs_removal,
|
|
rej, instat.st_mode, false);
|
|
- if (! inerrno
|
|
+ if (! inerrno && !s_is_chrblkfifosock(rej)
|
|
&& (chmod (rej, (instat.st_mode
|
|
& ~(S_IXUSR|S_IXGRP|S_IXOTH)))
|
|
!= 0))
|
|
Index: b/util.c
|
|
===================================================================
|
|
--- a/util.c
|
|
+++ b/util.c
|
|
@@ -65,6 +65,49 @@ static bool fid_search (const char *, co
|
|
FROM_NEEDS_REMOVAL must be nonnull if FROM is nonnull.
|
|
Back up TO if BACKUP is true. */
|
|
|
|
+int
|
|
+s_is_chrblkfifosock (const char *path)
|
|
+{
|
|
+ int r;
|
|
+ struct stat st;
|
|
+
|
|
+ r = stat(path, &st);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+
|
|
+ return (((st.st_mode & S_IFMT) == S_IFCHR) ||
|
|
+ ((st.st_mode & S_IFMT) == S_IFBLK) ||
|
|
+ ((st.st_mode & S_IFMT) == S_IFIFO) ||
|
|
+ ((st.st_mode & S_IFMT) == S_IFSOCK));
|
|
+}
|
|
+
|
|
+void
|
|
+cat_file_to_dev (const char *from, const char *to)
|
|
+{
|
|
+ size_t i;
|
|
+ int fromfd, tofd;
|
|
+
|
|
+ fromfd = open(from, O_RDONLY);
|
|
+ if (fromfd < 0)
|
|
+ pfatal("could not open %s for reading", quotearg(from));
|
|
+
|
|
+ tofd = open(to, O_WRONLY | O_NONBLOCK);
|
|
+ if (tofd < 0)
|
|
+ pfatal("could not open %s for writing", quotearg(to));
|
|
+
|
|
+ while ((i = read (fromfd, buf, bufsize)) != 0)
|
|
+ {
|
|
+ if (i == (size_t) -1)
|
|
+ read_fatal ();
|
|
+ if (write (tofd, buf, i) != i)
|
|
+ write_fatal ();
|
|
+ }
|
|
+ if (close (fromfd) != 0)
|
|
+ read_fatal ();
|
|
+ if (close (tofd) != 0)
|
|
+ write_fatal ();
|
|
+}
|
|
+
|
|
void
|
|
move_file (char const *from, int volatile *from_needs_removal,
|
|
char *to, mode_t mode, bool backup)
|
|
@@ -165,6 +208,13 @@ move_file (char const *from, int volatil
|
|
goto rename_succeeded;
|
|
}
|
|
|
|
+ if (errno == EACCES && (s_is_chrblkfifosock(to) > 0))
|
|
+ {
|
|
+ cat_file_to_dev (from, to);
|
|
+ unlink(from);
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (errno == EXDEV)
|
|
{
|
|
if (! backup)
|
|
Index: b/util.h
|
|
===================================================================
|
|
--- a/util.h
|
|
+++ b/util.h
|
|
@@ -59,3 +59,4 @@ void remove_prefix (char *, size_t);
|
|
void removedirs (char *);
|
|
void set_signals (bool);
|
|
void write_fatal (void) __attribute__ ((noreturn));
|
|
+int s_is_chrblkfifosock (const char *);
|