btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / bin / unchop.c
blob9c99b4db594d4c20700fa4d244d6a74b16649e53
1 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
2 //
3 // Copyright (c) 2001-2003, OpenBeOS
4 //
5 // This software is part of the OpenBeOS distribution and is covered
6 // by the MIT License.
7 //
8 //
9 // File: unchop.c
10 // Author: Daniel Reinhold (danielre@users.sf.net)
11 // Description: recreates a file previously split with chop
13 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
15 #include <OS.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <sys/stat.h>
25 void append_file (int, int);
26 void do_unchop (char *, char *);
27 void replace (char *, char *);
28 char *temp_file (void);
29 void usage (void);
30 bool valid_file (char *);
33 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
34 // globals
36 #define BLOCKSIZE 64 * 1024 // file data is read in BLOCKSIZE blocks
37 static char Block[BLOCKSIZE]; // and stored in the global Block array
39 static int Errors = 0;
43 void
44 usage()
46 printf("Usage: unchop file\n");
47 printf("Concatenates files named file00, file01... into file\n");
51 int
52 main(int argc, char *argv[])
54 if (argc != 2) {
55 usage();
56 return 0;
58 else {
59 char *origfile = argv[1];
60 char *tmpfile = origfile;
61 bool needs_replace = false;
63 if (valid_file(origfile)) {
64 // output file already exists -- write to temp file
65 tmpfile = temp_file();
66 needs_replace = true;
69 do_unchop(tmpfile, origfile);
71 if (needs_replace) {
72 if (Errors == 0)
73 replace(origfile, tmpfile);
74 else
75 remove(tmpfile);
79 return Errors;
83 void
84 do_unchop(char *outfile, char *basename)
86 int fdout = open(outfile, O_WRONLY|O_CREAT|O_APPEND);
87 if (fdout < 0)
88 fprintf(stderr, "can't open '%s': %s\n", outfile, strerror(errno));
90 else {
91 int i;
92 char fnameN[256];
94 for (i = 0; i < 999999; ++i) {
95 sprintf(fnameN, "%s%02d", basename, i);
97 if (valid_file(fnameN)) {
98 int fdin = open(fnameN, O_RDONLY);
99 if (fdin < 0) {
100 fprintf(stderr, "can't open '%s': %s\n", fnameN, strerror(errno));
101 ++Errors;
102 } else {
103 append_file(fdin, fdout);
104 close(fdin);
106 } else {
107 if (i == 0)
108 printf("No chunk files present (%s)", fnameN);
109 break;
112 close(fdout);
117 void
118 append_file(int fdin, int fdout)
120 // appends the entire contents of the input file
121 // to the output file
123 ssize_t got;
125 for (;;) {
126 got = read(fdin, Block, BLOCKSIZE);
127 if (got <= 0)
128 break;
130 write(fdout, Block, got);
135 bool
136 valid_file(char *fname)
138 // for this program, a valid file is one that:
139 // a) exists (that always helps)
140 // b) is a regular file (not a directory, link, etc.)
142 struct stat e;
144 if (stat(fname, &e) == -1) {
145 // no such file
146 return false;
149 return (S_ISREG(e.st_mode));
153 void
154 replace(char *origfile, char *newfile)
156 // replace the contents of the original file
157 // with the contents of the new file
159 char buf[1000];
161 // delete the original file
162 remove(origfile);
164 // rename the new file to the original file name
165 sprintf(buf, "mv \"%s\" \"%s\"", newfile, origfile);
166 system(buf);
170 char *
171 temp_file(void)
173 // creates a new, temporary file and returns its name
175 char *tmp = tmpnam(NULL);
177 FILE *fp = fopen(tmp, "w");
178 fclose(fp);
180 return tmp;