summaryrefslogtreecommitdiffstats
path: root/tests/dup-clobber.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/dup-clobber.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/tests/dup-clobber.c b/tests/dup-clobber.c
new file mode 100644
index 0000000..4e7add2
--- /dev/null
+++ b/tests/dup-clobber.c
@@ -0,0 +1,103 @@
+/* Demonstrate that setting disk->needs_clobber in ped_disk_duplicate
+ is necessary. With that, this test passes. Without it, the last
+ sectors of the disk are cleared, and this test fails. */
+#include <config.h>
+#include <parted/parted.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "closeout.h"
+#include "progname.h"
+
+static void
+seek_to_final_sector (int fd, PedSector ss)
+{
+ /* Seek to EOF. */
+ off_t off = lseek (fd, 0, SEEK_END);
+
+ /* That had better succeed and determine that the size is > 2 sectors
+ and an exact multiple of ss. */
+ assert (2 * ss < off);
+ assert (off % ss == 0);
+
+ /* Back up one sector. */
+ off = lseek (fd, -ss, SEEK_CUR);
+ assert (0 < off);
+}
+
+static void
+scribble_on_final_sector (char const *file_name, PedSector ss)
+{
+ assert (0 < ss);
+ assert (ss % 512 == 0);
+ int fd = open (file_name, O_WRONLY);
+ assert (0 <= fd);
+
+ seek_to_final_sector (fd, ss);
+
+ /* Fill the final sector with ascii 'G's. */
+ char *buf = malloc (ss);
+ assert (buf);
+ memset (buf, 'G', ss);
+ assert (write (fd, buf, ss) == ss);
+ free (buf);
+ assert (close (fd) == 0);
+}
+
+int
+main (int argc, char **argv)
+{
+ atexit (close_stdout);
+ set_program_name (argv[0]);
+
+ if (argc != 1)
+ return EXIT_FAILURE;
+
+ char const *dev_name = "dev-file";
+
+ /* Create a file. */
+ int fd = open (dev_name, O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ assert (0 <= fd);
+ off_t size = 8 * 1024 * 1024;
+ assert (ftruncate (fd, size) == 0);
+ assert (close (fd) == 0);
+
+ PedDevice *dev = ped_device_get (dev_name);
+ assert (dev);
+
+ PedDisk *disk = ped_disk_new_fresh (dev, ped_disk_type_get ("msdos"));
+ assert (disk);
+
+ assert (ped_disk_commit(disk));
+
+ PedSector ss = dev->sector_size;
+ scribble_on_final_sector (dev_name, ss);
+
+ /* Before the fix, this ped_disk_duplicate call would always set
+ copy->needs_clobber, thus causing the subsequent commit to
+ mistakenly clobber 9KiB at each end of the disk. */
+ PedDisk *copy = ped_disk_duplicate (disk);
+ assert (ped_disk_commit(copy));
+
+ ped_disk_destroy (copy);
+ ped_disk_destroy (disk);
+ ped_device_destroy (dev);
+
+ /* Read the final sector and ensure it's still all 'G's. */
+ fd = open (dev_name, O_RDONLY);
+ assert (0 <= fd);
+ seek_to_final_sector (fd, ss);
+ char *buf = malloc (ss);
+ assert (buf);
+ assert (read (fd, buf, ss) == ss);
+ unsigned int i;
+ for (i = 0; i < ss; i++)
+ assert (buf[i] == 'G');
+ free (buf);
+
+ return EXIT_SUCCESS;
+}