summaryrefslogtreecommitdiffstats
path: root/misc-utils/dsplit.c
blob: c3c22a305a352489b4439e1560809d95f0254173 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#ifdef lint
   static char RCSid[] = "$RCSfile: dsplit.c,v $ $Revision: 1.9 $ $Date: 1995/03/12 01:31:03 $";
#endif
/*
   Program dsplit:  Splits a large  file into pieces.

   Usage:
        dsplit [-size nnn] [input_file [output_base]]
   Size        is size of each output file, in bytes.  The default is 1457000,
	       enough to fill a "1.44MB" diskette, save 152 bytes.
   input_file  is the name of the file to split up.  A dash (-) indicates 
                  standard input.  Defaults to standard input.
   output_base is the name of the output files to be written, minus the
                  extension.  Dsplit adds suffixes 000, 001, ...
                  The default base name is dsplit.
*/
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if (defined (__MSDOS__) || defined (WIN32))
#include <io.h>
#include <fcntl.h>
#endif /* __MSDOS__ or WIN32 */
#ifndef FILENAME_MAX
#define FILENAME_MAX 1024
#endif

#define DEFAULT_NAME "dsplit"
#define DEFAULT_SIZE 1457000L
#if (defined (__MSDOS__) || defined (WIN32))
#   define READ_OPTIONS  "rb"
#   define WRITE_OPTIONS "wb"
#else
#   define READ_OPTIONS  "r"
#   define WRITE_OPTIONS "w"
#endif /* __MSDOS__ or WIN32 */

#ifndef MIN
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
#endif

static unsigned long output_size = DEFAULT_SIZE;
static char* base_name = DEFAULT_NAME;
static FILE* input_handle;
static char* input_name = "-";

#ifdef __STDC__
static void init (int argc, char* argv[]);
static int write_one (int count);
static void ToLower (char* string);
static void usage_error (void);
#else /* not __STDC__ */
static void init (/* int argc, char* argv[] */);
static int write_one (/* int count */);
static void ToLower (/* char* string */);
static void usage_error (/* void */);
#endif /* __STDC__ */



#ifdef __STDC__
int main (int argc, char* argv[])
#else
int main (argc, argv)
int argc;
char* argv[];
#endif
{
   int count;

   /* Process command line arguments, open input file. */
   init (argc, argv);

   /* Write the output files */
   for (count = 0 ; write_one (count) ; ++count)
      ;

   /* Close input file (a matter of style) */
   if (fclose (input_handle) != 0)
   {
      (void)fprintf (stderr, "Could not close file \"%s\" for input\n",
	 input_name);
      return 1;
   }

   /* Normal successful conclusion */
   return 0;
}



#ifdef __STDC__
static void init (int argc, char* argv[])
#else
static void init (argc, argv)
int argc;
char* argv[];
#endif
{
   int iarg;
   int name_count;

   /* Initialize the input file handle to standard input.  IBM's Toolset++
   won't let me do this statically, unfortunately. */
   input_handle = stdin;

   /* Initialize for following loop */
   name_count = 0;

   /* Loop over command line arguments */
   for (iarg = 1 ; iarg < argc ; ++iarg)
   {
      /* Point to argument,for convenience */
      char* arg = argv[iarg];

      /* If this argument is an option */
      if (arg[0] == '-' && arg[1] != '\0')
      {
         /* Process option if recognized */
         ToLower (arg+1);
         if (strcmp (arg+1, "size") != 0)
            usage_error ();
	 ++iarg;
	 if (iarg >= argc)
	    usage_error ();
	 arg = argv[iarg];
	 if (sscanf (arg, "%ld", &output_size) != 1)
	 {
	    (void)fprintf (stderr, "Illegal numeric expression \"%s\"\n", arg);
	    exit (1);
	 }
      } 
      else /* argument is not an option */
      {
         /* Argument is a name string.  Determine which one. */
         switch (name_count)
         {
         case 0:
            input_name = argv[iarg];
            break;
	 case 1:
            base_name = argv[iarg];
	    break;
	 default:
	    usage_error ();
	    break;
         }
         ++name_count;

      } /* End if this argument is an option */

   }  /* End loop over command line arguments */

   /* Open the input file */
   if (strcmp (input_name, "-") == 0)
   {
#  if (defined (__MSDOS__) || defined (WIN32))
      if (setmode (0, O_BINARY) == -1)
      {
         perror ("dsplit: setmode");
         exit (1);
      }
#  endif
   }
   else
   {
      if ((input_handle = fopen (input_name, READ_OPTIONS)) == NULL)
      {
	 (void)fprintf (stderr, "Could not open file \"%s\" for input\n",
	    input_name);
	 exit (1);
      }
   }
}



#ifdef __STDC__
static int write_one (int count)
#else
static int write_one (count)
int count;
#endif
{
   char output_name[FILENAME_MAX];
   int bytes_written;
   unsigned long total_written;
   FILE* output_handle;

   /* Read the first buffer full now, just to see if any data is left */
   static char buff[1024];
   int to_read = MIN (sizeof(buff), output_size);
   int bytes_read = fread (buff, 1, to_read, input_handle);
   if (bytes_read <= 0)
      return 0;

   /* Open file for output */
   sprintf (output_name, "%s.%03d", base_name, count);
   output_handle = fopen (output_name, WRITE_OPTIONS);
   if (output_handle == NULL)
   {
      (void)fprintf (stderr,
         "Could not open file \"%s\" for output\n", output_name);
      exit (1);
   }

   /* Write the first output buffer */
   bytes_written = fwrite (buff, 1, bytes_read, output_handle);
   if (bytes_written != bytes_read)
   {
      (void)fprintf (stderr, "Error writing to file \"%s\"\n", output_name);
      exit (1);
   }
   total_written = bytes_written;

   /* Write output file */
   while (total_written < output_size)
   {
      to_read = MIN (sizeof(buff), output_size-total_written);
      bytes_read = fread (buff, 1, to_read, input_handle);
      if (bytes_read <= 0)
         break;
      bytes_written = fwrite (buff, 1, bytes_read, output_handle);
      if (bytes_written != bytes_read)
      {
         (void)fprintf (stderr, "Error writing to file \"%s\"\n", output_name);
         exit (1);
      }
      total_written += bytes_written;
   }

   /* Close the output file, it is complete */
   if (fclose (output_handle) != 0)
   {
      (void)fprintf (stderr,
         "Could not close file \"%s\" for output\n", output_name);
      exit (1);
   }

   /* Indicate whether more data remains to be transferred */
   return (bytes_read == to_read);
}



#ifdef __STDC__
static void ToLower (char* string)
#else
static void ToLower (string)
char* string;
#endif
{
   
   while (*string != '\0')
      tolower (*string++);
}



#ifdef __STDC__
static void usage_error (void)
#else
static void usage_error ()
#endif
{
   (void)fprintf (stderr, 
      "Usage: dsplit [-size nnn] [input_file [output_base]]\n");
   exit (1);
}