summaryrefslogtreecommitdiff
path: root/usr.bin/xinstall
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2003-05-11 18:18:34 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2003-05-11 18:18:34 +0000
commitfc2395fc3e8918a15c1ea31f804445d5e952b149 (patch)
tree5766a1e6f67149ab7c6041b0a4f33b49a2286aa0 /usr.bin/xinstall
parent201916e8c8ad047656a54faba017f264febd94ea (diff)
when doing sparse writes, we must write the last byte or the file will
be shortened. problem found by wcobb and naddy. ok millert@
Diffstat (limited to 'usr.bin/xinstall')
-rw-r--r--usr.bin/xinstall/xinstall.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c
index 25d4b5ec8a2..b84b0e42aa0 100644
--- a/usr.bin/xinstall/xinstall.c
+++ b/usr.bin/xinstall/xinstall.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xinstall.c,v 1.32 2003/05/07 22:38:06 millert Exp $ */
+/* $OpenBSD: xinstall.c,v 1.33 2003/05/11 18:18:33 tedu Exp $ */
/* $NetBSD: xinstall.c,v 1.9 1995/12/20 10:25:17 jonathan Exp $ */
/*
@@ -44,7 +44,7 @@ static char copyright[] =
#if 0
static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93";
#endif
-static char rcsid[] = "$OpenBSD: xinstall.c,v 1.32 2003/05/07 22:38:06 millert Exp $";
+static char rcsid[] = "$OpenBSD: xinstall.c,v 1.33 2003/05/11 18:18:33 tedu Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -91,6 +91,7 @@ void usage(void);
int create_newfile(char *, struct stat *);
int create_tempfile(char *, char *, size_t);
int file_write(int, char *, size_t, int *, int *, int);
+void file_flush(int, int);
int
main(argc, argv)
@@ -483,6 +484,8 @@ copy(from_fd, from_name, to_fd, to_name, size, sparse)
to_name, strerror(nw > 0 ? EIO : serrno));
}
}
+ if (sparse)
+ file_flush(to_fd, isem);
if (nr != 0) {
serrno = errno;
(void)unlink(to_name);
@@ -797,3 +800,35 @@ file_write(fd, str, cnt, rem, isempt, sz)
}
return(st - str);
}
+
+/*
+ * file_flush()
+ * when the last file block in a file is zero, many file systems will not
+ * let us create a hole at the end. To get the last block with zeros, we
+ * write the last BYTE with a zero (back up one byte and write a zero).
+ */
+
+void
+file_flush(int fd, int isempt)
+{
+ static char blnk[] = "\0";
+
+ /*
+ * silly test, but make sure we are only called when the last block is
+ * filled with all zeros.
+ */
+ if (!isempt)
+ return;
+
+ /*
+ * move back one byte and write a zero
+ */
+ if (lseek(fd, (off_t)-1, SEEK_CUR) < 0) {
+ warn("Failed seek on file");
+ return;
+ }
+
+ if (write(fd, blnk, 1) < 0)
+ warn("Failed write to file");
+ return;
+}