mksparse.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* This file is part of GNU tar test suite
  2. Copyright (C) 2004 Free Software Foundation, Inc.
  3. This program is free software; you can redistribute it and/or modify it
  4. under the terms of the GNU General Public License as published by the
  5. Free Software Foundation; either version 2, or (at your option) any later
  6. version.
  7. This program is distributed in the hope that it will be useful, but
  8. WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
  10. Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with this program; if not, write to the Free Software Foundation, Inc.,
  13. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  14. #ifdef HAVE_CONFIG_H
  15. # include <config.h>
  16. #endif
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <stdarg.h>
  21. #include <fcntl.h>
  22. #include <string.h>
  23. char *progname;
  24. char *buffer;
  25. size_t buffer_size;
  26. static void die (char const *, ...) __attribute__ ((noreturn,
  27. format (printf, 1, 2)));
  28. static void
  29. die (char const *fmt, ...)
  30. {
  31. va_list ap;
  32. fprintf (stderr, "%s: ", progname);
  33. va_start (ap, fmt);
  34. vfprintf (stderr, fmt, ap);
  35. va_end (ap);
  36. fprintf (stderr, "\n");
  37. exit (1);
  38. }
  39. static void
  40. mkhole (int fd, off_t displ)
  41. {
  42. if (lseek (fd, displ, SEEK_CUR) == -1)
  43. {
  44. perror ("lseek");
  45. exit (1);
  46. }
  47. ftruncate (fd, lseek (fd, 0, SEEK_CUR));
  48. }
  49. static void
  50. mksparse (int fd, off_t displ, char *marks)
  51. {
  52. for (; *marks; marks++)
  53. {
  54. memset (buffer, *marks, buffer_size);
  55. if (write(fd, buffer, buffer_size) != buffer_size)
  56. {
  57. perror ("write");
  58. exit (1);
  59. }
  60. if (lseek (fd, displ, SEEK_CUR) == -1)
  61. {
  62. perror ("lseek");
  63. exit (1);
  64. }
  65. }
  66. }
  67. static void usage (void) __attribute__ ((noreturn));
  68. static void
  69. usage (void)
  70. {
  71. printf ("Usage: mksparse filename blocksize disp letters [disp letters...] [disp]\n");
  72. exit (1);
  73. }
  74. static int
  75. xlat_suffix (off_t *vp, char *p)
  76. {
  77. if (p[1])
  78. return 1;
  79. switch (p[0])
  80. {
  81. case 'g':
  82. case 'G':
  83. *vp *= 1024;
  84. case 'm':
  85. case 'M':
  86. *vp *= 1024;
  87. case 'k':
  88. case 'K':
  89. *vp *= 1024;
  90. break;
  91. default:
  92. return 1;
  93. }
  94. return 0;
  95. }
  96. int
  97. main (int argc, char **argv)
  98. {
  99. int i;
  100. int fd;
  101. char *p;
  102. off_t n;
  103. progname = strrchr (argv[0], '/');
  104. if (progname)
  105. progname++;
  106. else
  107. progname = argv[0];
  108. if (argc < 4)
  109. usage ();
  110. fd = open (argv[1], O_CREAT|O_TRUNC|O_RDWR, 0644);
  111. if (fd < 0)
  112. die ("cannot open %s", argv[1]);
  113. n = strtoul (argv[2], &p, 0);
  114. if (n <= 0 || (*p && xlat_suffix (&n, p)))
  115. die ("Invalid buffer size: %s", argv[2]);
  116. buffer_size = n;
  117. buffer = malloc (buffer_size);
  118. if (!buffer)
  119. die ("Not enough memory");
  120. for (i = 3; i < argc; i += 2)
  121. {
  122. off_t displ;
  123. displ = strtoul (argv[i], &p, 0);
  124. if (displ < 0 || (*p && xlat_suffix (&displ, p)))
  125. die ("Invalid displacement: %s", argv[i]);
  126. if (i == argc-1)
  127. {
  128. mkhole (fd, displ);
  129. break;
  130. }
  131. else
  132. mksparse (fd, displ, argv[i+1]);
  133. }
  134. close(fd);
  135. return 0;
  136. }