home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / dsplit / part01 < prev    next >
Encoding:
Text File  |  1993-10-25  |  9.9 KB  |  352 lines

  1. Newsgroups: comp.sources.misc
  2. From: arnstein@netcom.com (David Arnstein)
  3. Subject: v40i051:  dsplit - A portable binary file splitter, Part01/01
  4. Message-ID: <1993Oct25.225703.7969@sparky.sterling.com>
  5. Summary: Binary file split program for MSDOS, Unix, C, Ansi C, C++...
  6. X-Md4-Signature: 905a06408c60a2f293cc8766af44930f
  7. Keywords: portable file split
  8. Sender: kent@sparky.sterling.com (Kent Landfield)
  9. Reply-To: arnstein@netcom.com
  10. Organization: My Own Internet Account!
  11. Date: Mon, 25 Oct 1993 22:57:03 GMT
  12. Approved: kent@sparky.sterling.com
  13.  
  14. Submitted-by: arnstein@netcom.com (David Arnstein)
  15. Posting-number: Volume 40, Issue 51
  16. Archive-name: dsplit/part01
  17. Environment: MS-DOS, UNIX
  18.  
  19. Here is a portable binary file splitting program.  It reads a binary file and
  20. splits it into pieces.  I use this program to put large binary files on floppy
  21. disks.  For this reason, the default size of the output files is 1,457,000
  22. bytes, which just about fills up a 1.44 MB floppy disk.
  23.  
  24. Unlike other binary split programs I have seen, dsplit does not malloc a huge
  25. block of memory.  Dsplit is suitable for use under MSDOS and other primitive
  26. operating systems.
  27.  
  28. To merge the pieces back into a single large file, use "cat" in Unix, or "copy"
  29. in MSDOS.  The MSDOS "copy" command uses plus-signs to indicate concatenation,
  30. eg
  31.    copy/b piece.001+piece.002+piece.003 opus.ps
  32. concatenates three files into file opus.ps.
  33.  
  34.    Usage:
  35.         dsplit [-size nnn] [input_file [output_base]]
  36.    Size        is size of each output file, in bytes.  The default is 1457000,
  37.            enough to fill a "1.44MB" diskette, save 152 bytes.
  38.    input_file  is the name of the file to split up.  A dash (-) indicates 
  39.                   standard input.  Defaults to standard input.
  40.    output_base is the name of the output files to be written, minus the
  41.                   extension.  Dsplit adds suffixes 000, 001, ...
  42.                   The default base name is dsplit.
  43.  
  44. It should compile using K&R C, ANSI C, or C++.  I have compiled it using
  45. Borland C++ 3.1, Sun cc, gcc, and g++.  Please notify me of any compilation
  46. problems, I would like to make this program portable!
  47.  
  48. I also have a dmerge program which is more convenient to use than MSDOS "copy,"
  49. but I have not put effort into making it super-portable.  You'd be better off
  50. obtaining a clone to the Unix "cat" command, several exist.  However, I can
  51. send you dmerge if you really want it.
  52.  
  53. Hope someone finds this useful.
  54.  
  55. David Arnstein
  56. arnstein@netcom.com
  57. ----------------------------------------------------
  58. #! /bin/sh
  59. # This is a shell archive.  Remove anything before this line, then feed it
  60. # into a shell via "sh file" or similar.  To overwrite existing files,
  61. # type "sh file -c".
  62. # Contents:  dsplit.c
  63. # Wrapped by kent@sparky on Mon Oct 25 17:53:36 1993
  64. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  65. echo If this archive is complete, you will see the following message:
  66. echo '          "shar: End of archive."'
  67. if test -f 'dsplit.c' -a "${1}" != "-c" ; then 
  68.   echo shar: Will not clobber existing file \"'dsplit.c'\"
  69. else
  70.   echo shar: Extracting \"'dsplit.c'\" \(6478 characters\)
  71.   sed "s/^X//" >'dsplit.c' <<'END_OF_FILE'
  72. X#ifdef lint
  73. X   static char RCSid[] = "$RCSfile: dsplit.c $ $Revision: 1.9 $ $Date: 1993/10/15 00:46:38 $";
  74. X#endif
  75. X/*
  76. X   Program dsplit:  Splits a large  file into pieces.
  77. X
  78. X   Usage:
  79. X        dsplit [-size nnn] [input_file [output_base]]
  80. X   Size        is size of each output file, in bytes.  The default is 1457000,
  81. X           enough to fill a "1.44MB" diskette, save 152 bytes.
  82. X   input_file  is the name of the file to split up.  A dash (-) indicates 
  83. X                  standard input.  Defaults to standard input.
  84. X   output_base is the name of the output files to be written, minus the
  85. X                  extension.  Dsplit adds suffixes 000, 001, ...
  86. X                  The default base name is dsplit.
  87. X*/
  88. X#include <ctype.h>
  89. X#include <stdlib.h>
  90. X#include <stdio.h>
  91. X#include <string.h>
  92. X#if (defined (__MSDOS__) || defined (WIN32))
  93. X#include <io.h>
  94. X#include <fcntl.h>
  95. X#endif /* __MSDOS__ or WIN32 */
  96. X#ifndef FILENAME_MAX
  97. X#define FILENAME_MAX 1024
  98. X#endif
  99. X
  100. X#define DEFAULT_NAME "dsplit"
  101. X#define DEFAULT_SIZE 1457000L
  102. X#if (defined (__MSDOS__) || defined (WIN32))
  103. X#   define READ_OPTIONS  "rb"
  104. X#   define WRITE_OPTIONS "wb"
  105. X#else
  106. X#   define READ_OPTIONS  "r"
  107. X#   define WRITE_OPTIONS "w"
  108. X#endif /* __MSDOS__ or WIN32 */
  109. X
  110. X#ifndef MIN
  111. X#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
  112. X#endif
  113. X
  114. Xstatic unsigned long output_size = DEFAULT_SIZE;
  115. Xstatic char* base_name = DEFAULT_NAME;
  116. Xstatic FILE* input_handle;
  117. Xstatic char* input_name = "-";
  118. X
  119. X#ifdef __STDC__
  120. Xstatic void init (int argc, char* argv[]);
  121. Xstatic int write_one (int count);
  122. Xstatic void ToLower (char* string);
  123. Xstatic void usage_error (void);
  124. X#else /* not __STDC__ */
  125. Xstatic void init (/* int argc, char* argv[] */);
  126. Xstatic int write_one (/* int count */);
  127. Xstatic void ToLower (/* char* string */);
  128. Xstatic void usage_error (/* void */);
  129. X#endif /* __STDC__ */
  130. X
  131. X
  132. X
  133. X#ifdef __STDC__
  134. Xint main (int argc, char* argv[])
  135. X#else
  136. Xint main (argc, argv)
  137. Xint argc;
  138. Xchar* argv[];
  139. X#endif
  140. X{
  141. X   int count;
  142. X
  143. X   /* Process command line arguments, open input file. */
  144. X   init (argc, argv);
  145. X
  146. X   /* Write the output files */
  147. X   for (count = 0 ; write_one (count) ; ++count)
  148. X      ;
  149. X
  150. X   /* Close input file (a matter of style) */
  151. X   if (fclose (input_handle) != 0)
  152. X   {
  153. X      (void)fprintf (stderr, "Could not close file \"%s\" for input\n",
  154. X     input_name);
  155. X      return 1;
  156. X   }
  157. X
  158. X   /* Normal successful conclusion */
  159. X   return 0;
  160. X}
  161. X
  162. X
  163. X
  164. X#ifdef __STDC__
  165. Xstatic void init (int argc, char* argv[])
  166. X#else
  167. Xstatic void init (argc, argv)
  168. Xint argc;
  169. Xchar* argv[];
  170. X#endif
  171. X{
  172. X   int iarg;
  173. X   int name_count;
  174. X
  175. X   /* Initialize the input file handle to standard input.  IBM's Toolset++
  176. X   won't let me do this statically, unfortunately. */
  177. X   input_handle = stdin;
  178. X
  179. X   /* Initialize for following loop */
  180. X   name_count = 0;
  181. X
  182. X   /* Loop over command line arguments */
  183. X   for (iarg = 1 ; iarg < argc ; ++iarg)
  184. X   {
  185. X      /* Point to argument,for convenience */
  186. X      char* arg = argv[iarg];
  187. X
  188. X      /* If this argument is an option */
  189. X      if (arg[0] == '-' && arg[1] != '\0')
  190. X      {
  191. X         /* Process option if recognized */
  192. X         ToLower (arg+1);
  193. X         if (strcmp (arg+1, "size") != 0)
  194. X            usage_error ();
  195. X     ++iarg;
  196. X     if (iarg >= argc)
  197. X        usage_error ();
  198. X     arg = argv[iarg];
  199. X     if (sscanf (arg, "%ld", &output_size) != 1)
  200. X     {
  201. X        (void)fprintf (stderr, "Illegal numeric expression \"%s\"\n", arg);
  202. X        exit (1);
  203. X     }
  204. X      } 
  205. X      else /* argument is not an option */
  206. X      {
  207. X         /* Argument is a name string.  Determine which one. */
  208. X         switch (name_count)
  209. X         {
  210. X         case 0:
  211. X            input_name = argv[iarg];
  212. X            break;
  213. X     case 1:
  214. X            base_name = argv[iarg];
  215. X        break;
  216. X     default:
  217. X        usage_error ();
  218. X        break;
  219. X         }
  220. X         ++name_count;
  221. X
  222. X      } /* End if this argument is an option */
  223. X
  224. X   }  /* End loop over command line arguments */
  225. X
  226. X   /* Open the input file */
  227. X   if (strcmp (input_name, "-") == 0)
  228. X   {
  229. X#  if (defined (__MSDOS__) || defined (WIN32))
  230. X      if (setmode (0, O_BINARY) == -1)
  231. X      {
  232. X         perror ("dsplit: setmode");
  233. X         exit (1);
  234. X      }
  235. X#  endif
  236. X   }
  237. X   else
  238. X   {
  239. X      if ((input_handle = fopen (input_name, READ_OPTIONS)) == NULL)
  240. X      {
  241. X     (void)fprintf (stderr, "Could not open file \"%s\" for input\n",
  242. X        input_name);
  243. X     exit (1);
  244. X      }
  245. X   }
  246. X}
  247. X
  248. X
  249. X
  250. X#ifdef __STDC__
  251. Xstatic int write_one (int count)
  252. X#else
  253. Xstatic int write_one (count)
  254. Xint count;
  255. X#endif
  256. X{
  257. X   char output_name[FILENAME_MAX];
  258. X   int bytes_written;
  259. X   unsigned long total_written;
  260. X   FILE* output_handle;
  261. X
  262. X   /* Read the first buffer full now, just to see if any data is left */
  263. X   static char buff[1024];
  264. X   int to_read = MIN (sizeof(buff), output_size);
  265. X   int bytes_read = fread (buff, 1, to_read, input_handle);
  266. X   if (bytes_read <= 0)
  267. X      return 0;
  268. X
  269. X   /* Open file for output */
  270. X   sprintf (output_name, "%s.%03d", base_name, count);
  271. X   output_handle = fopen (output_name, WRITE_OPTIONS);
  272. X   if (output_handle == NULL)
  273. X   {
  274. X      (void)fprintf (stderr,
  275. X         "Could not open file \"%s\" for output\n", output_name);
  276. X      exit (1);
  277. X   }
  278. X
  279. X   /* Write the first output buffer */
  280. X   bytes_written = fwrite (buff, 1, bytes_read, output_handle);
  281. X   if (bytes_written != bytes_read)
  282. X   {
  283. X      (void)fprintf (stderr, "Error writing to file \"%s\"\n", output_name);
  284. X      exit (1);
  285. X   }
  286. X   total_written = bytes_written;
  287. X
  288. X   /* Write output file */
  289. X   while (total_written < output_size)
  290. X   {
  291. X      to_read = MIN (sizeof(buff), output_size-total_written);
  292. X      bytes_read = fread (buff, 1, to_read, input_handle);
  293. X      if (bytes_read <= 0)
  294. X         break;
  295. X      bytes_written = fwrite (buff, 1, bytes_read, output_handle);
  296. X      if (bytes_written != bytes_read)
  297. X      {
  298. X         (void)fprintf (stderr, "Error writing to file \"%s\"\n", output_name);
  299. X         exit (1);
  300. X      }
  301. X      total_written += bytes_written;
  302. X   }
  303. X
  304. X   /* Close the output file, it is complete */
  305. X   if (fclose (output_handle) != 0)
  306. X   {
  307. X      (void)fprintf (stderr,
  308. X         "Could not close file \"%s\" for output\n", output_name);
  309. X      exit (1);
  310. X   }
  311. X
  312. X   /* Indicate whether more data remains to be transferred */
  313. X   return (bytes_read == to_read);
  314. X}
  315. X
  316. X
  317. X
  318. X#ifdef __STDC__
  319. Xstatic void ToLower (char* string)
  320. X#else
  321. Xstatic void ToLower (string)
  322. Xchar* string;
  323. X#endif
  324. X{
  325. X   
  326. X   while (*string != '\0')
  327. X      tolower (*string++);
  328. X}
  329. X
  330. X
  331. X
  332. X#ifdef __STDC__
  333. Xstatic void usage_error (void)
  334. X#else
  335. Xstatic void usage_error ()
  336. X#endif
  337. X{
  338. X   (void)fprintf (stderr, 
  339. X      "Usage: dsplit [-size nnn] [input_file [output_base]]\n");
  340. X   exit (1);
  341. X}
  342. X
  343. END_OF_FILE
  344.   if test 6478 -ne `wc -c <'dsplit.c'`; then
  345.     echo shar: \"'dsplit.c'\" unpacked with wrong size!
  346.   fi
  347.   # end of 'dsplit.c'
  348. fi
  349. echo shar: End of archive.
  350. exit 0
  351. exit 0 # Just in case...
  352.