/* * hoz - Hacha Open Zource * Copyright (C) 2004 Gustavo Picon (http://hoz.sourceforge.net/) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #if defined(WIN32) #define HOZ_PATHSEP '\\' #else #define HOZ_PATHSEP '/' #endif #include "hoz.h" char outpath[MAXLEN]; size_t fullsize, partsize, headersize; int showprogress, forceow, simulate; /** * hoz_echo - displays something based on a code * @code: the event code * @xtra: extra information about an event * * not all the events have a xtra parameter */ void hoz_echo(const int code, const char *xtra) { char foo[1024]; foo[0] = 0; switch (code) { case 301: hoz_print(HOZ_COPYRIGHT1); hoz_lf(); hoz_print(HOZ_COPYRIGHT2); hoz_lf(); break; case 401: hoz_echo(301, NULL); hoz_lf(); sprintf(foo, HOZ_USAGE_1, xtra); hoz_print(foo); hoz_lf(); hoz_print(HOZ_USAGE_2); hoz_lf(); hoz_print(HOZ_USAGE_3); hoz_lf(); hoz_print(HOZ_USAGE_4); hoz_lf(); hoz_print(HOZ_USAGE_5); hoz_lf(); hoz_print(HOZ_USAGE_6); hoz_lf(); hoz_print(HOZ_USAGE_7); hoz_lf(); hoz_print(HOZ_USAGE_8); hoz_lf(); hoz_print(HOZ_USAGE_9); hoz_lf(); break; case 402: /* * it's gone */ break; case 403: hoz_lf(); hoz_print(HOZ_ENDDOTO); hoz_lf(); break; case 404: hoz_lf(); sprintf(foo, HOZ_NOFILE, xtra); hoz_print(foo); hoz_lf(); break; case 405: hoz_lf(); sprintf(foo, HOZ_BADHEADER, xtra); hoz_print(foo); hoz_lf(); break; case 406: hoz_lf(); sprintf(foo, HOZ_BADPARTS, xtra); hoz_print(foo); hoz_lf(); break; case 407: hoz_lf(); sprintf(foo, HOZ_ERROPENWRITE, xtra); hoz_print(foo); hoz_lf(); break; case 408: hoz_lf(); sprintf(foo, HOZ_ERROPENREAD, xtra); hoz_print(foo); hoz_lf(); break; case 409: hoz_lf(); sprintf(foo, HOZ_ERRPARTSIZE, xtra); hoz_print(foo); hoz_lf(); break; case 410: hoz_lf(); sprintf(foo, HOZ_ERRPROCESS, xtra); hoz_print(foo); hoz_lf(); break; case 411: hoz_lf(); sprintf(foo, HOZ_ERROUTNODIR, xtra); hoz_print(foo); hoz_lf(); break; case 412: hoz_lf(); sprintf(foo, HOZ_ERRWRITE, xtra); hoz_print(foo); hoz_lf(); break; case 413: sprintf(foo, HOZ_BADARGSOPT, xtra); hoz_print(foo); hoz_lf(); sprintf(foo, HOZ_HMOREINFO, xtra); hoz_print(foo); hoz_lf(); break; case 414: sprintf(foo, HOZ_BADARGSFILE, xtra); hoz_print(foo); hoz_lf(); sprintf(foo, HOZ_HMOREINFO, xtra); hoz_print(foo); hoz_lf(); break; case 415: sprintf(foo, HOZ_HMOREINFO, xtra); hoz_print(foo); hoz_lf(); break; } } /** * hoz_cut_main - cut files main function * @ifname: "file.ext" file name */ int hoz_cut_main(const char *ifname) { FILE *f_in, *f_out; /* file handles */ clock_t initime; /* to calculate the time spent */ unsigned char buf[FILESTREAMSIZE + 1], /* buffer to copy */ foo[MAXLEN], /* current 'file.n' filename */ bar[MAXLEN], /* "?????" */ baz[MAXLEN], qux; /* useless byte in the header, * must be included for compat with hacha */ size_t i, /* foobar */ len, /* bytes read */ bfile, /* bytes read in current file file.n */ btotal, /* total bytes read */ dif; double elapsed; /* total time elapsed */ char *ifnopath; /* input fname without path */ f_in = fopen(ifname, "rb"); if (!f_in) { hoz_echo(408, NULL); return 408; } i = bfile = btotal = 0; ifnopath = hoz_nopath(ifname); sprintf(baz, "%s.%u", ifnopath, i); mergepath(outpath, baz, foo); remove(foo); f_out = fopen(foo, "ab"); if (!f_out) { fclose(f_in); hoz_echo(407, foo); return 407; } fullsize = fsize(ifname); /* store the time */ initime = clock(); /* begin control byte */ /* * This code was broken, thanks Eric for reporting this * sprintf(buf, "%u", partsize); * len = strlen(buf); * qux = 24 + len + strlen(ifnopath) + ((len <= 4) ? 1 : 3); */ sprintf(buf, "%u%u%s", partsize, fullsize, ifnopath); qux = 20 + strlen(buf); /* end control byte */ strcpy(bar, "?????"); sprintf(buf, "%s%c %s%s%s%u%s%u%s", bar, qux, bar, hoz_nopath(ifname), bar, fullsize, bar, partsize, bar); len = (size_t) strlen(buf); buf[6] = buf[7] = buf[8] = 0; if (fwrite(buf, sizeof(char), len, f_out) != len) { fclose(f_in); fclose(f_out); hoz_echo(412, foo); return 412; } sprintf(bar, HOZ_CUTTOFILE, hoz_nopath(foo)); hoz_print(bar); for (;;) { if (partsize <= FILESTREAMSIZE) { len = (size_t) fread(buf, sizeof(char), FILESTREAMSIZE, f_in); if (fwrite(buf, sizeof(char), len, f_out) != len) { fclose(f_in); fclose(f_out); hoz_echo(412, foo); return 412; } if (showprogress) { hoz_print(PROGRMETERSTR); /* progress meter? */ } bfile = len; btotal += len; fclose(f_out); hoz_lf(); sprintf(bar, HOZ_PROGRESS, btotal, fullsize, (float) ((float) btotal / (float) fullsize) * 100); hoz_print(bar); hoz_lf(); if (feof(f_in)) { break; } ++i; sprintf(baz, "%s.%u", ifnopath, i); mergepath(outpath, baz, foo); remove(foo); f_out = fopen(foo, "ab"); if (!f_out) { fclose(f_in); hoz_echo(407, foo); return 407; } sprintf(bar, HOZ_CUTTOFILE, hoz_nopath(foo)); hoz_print(bar); } else { len = (size_t) fread(buf, sizeof(char), FILESTREAMSIZE, f_in); if (bfile + len < partsize) { if (fwrite(buf, sizeof(char), len, f_out) != len) { fclose(f_in); fclose(f_out); hoz_echo(412, foo); return 412; } if (showprogress) { hoz_print(PROGRMETERSTR); /* progress meter? */ } bfile += len; } else { dif = partsize - bfile; if (fwrite(buf, sizeof(char), dif, f_out) != dif) { fclose(f_in); fclose(f_out); hoz_echo(412, foo); return 412; } if (showprogress) { hoz_print(PROGRMETERSTR); /* progress meter? */ } bfile += dif; fclose(f_out); hoz_lf(); sprintf(bar, HOZ_PROGRESS, btotal, fullsize, (float) ((float) btotal / (float) fullsize) * 100); hoz_print(bar); hoz_lf(); ++i; bfile = 0; sprintf(baz, "%s.%u", ifnopath, i); mergepath(outpath, baz, foo); remove(foo); f_out = fopen(foo, "ab"); if (!f_out) { fclose(f_in); hoz_echo(407, foo); return 407; } sprintf(bar, HOZ_CUTTOFILE, hoz_nopath(foo)); hoz_print(bar); if (fwrite(buf + dif, sizeof(char), len - dif, f_out) != (len - dif)) { fclose(f_in); fclose(f_out); hoz_echo(412, foo); return 412; } if (showprogress) { hoz_print(PROGRMETERSTR); /* progress meter? */ } bfile += (len - dif); } btotal += len; if (feof(f_in)) { hoz_lf(); sprintf(bar, HOZ_PROGRESS, btotal, fullsize, (float) ((float) btotal / (float) fullsize) * 100); hoz_print(bar); hoz_lf(); break; } } } sprintf(foo, "%s.%u", ifname, ++i); remove(foo); fclose(f_in); fclose(f_out); /* if the sum of the file sizes isn't the same as the original file size * then the operation failed */ if (btotal != fullsize) { sprintf(foo, "%u/%u", btotal, fullsize); hoz_echo(410, foo); return 410; } /* calculate the time spent in this operation */ elapsed = (double) (clock() - initime) / CLOCKS_PER_SEC; elapsed = (elapsed) ? elapsed : 0.001; /* can't be 0 seconds! */ /* yes */ hoz_lf(); sprintf(bar, HOZ_CUTEND, hoz_nopath(ifname), btotal, elapsed, (size_t) ((double) btotal / elapsed), outpath); hoz_print(bar); hoz_lf(); return 0; } /** * hoz_paste_main - paste files main function * @ifname: "file.0" file name */ int hoz_paste_main(const char *ifname) { FILE *f_in, *f_out; /* file handles */ clock_t initime; /* to calculate the time spent */ unsigned char buf[FILESTREAMSIZE + 1], /* buffer to copy */ foo[MAXLEN], /* current 'file.n' filename */ bar[MAXLEN], /* blah */ basename[MAXLEN], /* base filename (file.*) */ origfname[MAXLEN], *outfname; size_t i, /* foobar */ len, /* bytes read */ bfile, /* bytes read in current file file.n */ btotal; /* total bytes read */ double elapsed; /* total time elapsed */ /* verifying that the input filename ends in ".0" */ if (ifname[strlen(ifname) - 1] != '0' || ifname[strlen(ifname) - 2] != '.') { hoz_echo(403, NULL); return 403; } /* error if the input file can't be opened */ f_in = fopen(ifname, "r"); if (!f_in) { hoz_echo(404, ifname); return 404; } fclose(f_in); /* retrieving header info */ i = hoz_paste_hr(ifname, origfname); /* if hoz_paste_hr() returns an error, end process */ if (i) { return i; } /* storing the base file name, just removing the "0" from "file.0" */ strcpy(basename, ifname); basename[strlen(basename) - 1] = 0; /* total bytes read = 0 */ btotal = 0; outfname = (char *) malloc(sizeof(char) * (strlen(origfname) + strlen(outpath) + 3)); mergepath(outpath, origfname, outfname); /* if the file exists and !forceow, ask what to do */ if (!forceow && isfile(outfname) && !hoz_replace_ask(outfname)) { free(outfname); return 302; } /* removing the output file if it already exists */ remove(outfname); /* opening the output file: (b)inary (w)rite */ f_out = fopen(outfname, "wb"); /* error if can't be openned */ if (!f_out) { hoz_echo(407, outfname); free(outfname); return 407; } /* telling the user what are we doing */ hoz_lf(); sprintf(bar, HOZ_BEGINPASTE, origfname, fullsize); hoz_print(bar); hoz_lf(); hoz_lf(); /* store the time */ initime = clock(); for (i = 0;; i++) { /* generating the "file.n" string, storing it in foo */ sprintf(foo, "%s%d", basename, i); /* openning the input file: (b)inary (r)ead */ f_in = fopen(foo, "rb"); /* bytes read in file = 0 */ bfile = 0; if (!f_in) { break; /* last file, end */ } else { /* extracting file.n... */ sprintf(bar, HOZ_PASTEFILE, hoz_nopath(foo)); hoz_print(bar); if (i == 0) { /* if we are extracting the first file (*.0), * discard the header */ fread(buf, sizeof(char), headersize, f_in); } for (;;) { /* appending file.n to the output file */ len = (size_t) fread(buf, sizeof(char), FILESTREAMSIZE, f_in); if (len) { if (fwrite(buf, sizeof(char), len, f_out) != len) { fclose(f_in); fclose(f_out); hoz_echo(412, outfname); free(outfname); return 412; } /* fwrite(buf, sizeof(char), len, f_out); *//* argh! */ btotal += len; bfile += len; } if (showprogress) { hoz_print(PROGRMETERSTR); /* progress meter? */ } if (feof(f_in)) { break; } } /* displays info... */ hoz_lf(); sprintf(bar, HOZ_PROGRESS, btotal, fullsize, (float) ((float) btotal / (float) fullsize) * 100); hoz_print(bar); hoz_lf(); } /* close the file.n handle */ fclose(f_in); if (bfile < partsize) { /* if the current file.n file is smaller than the size defined in * the file.0 header for a partial file, end process */ break; } } /* close file handles */ fclose(f_out); /* if the extracted file size isn't the same as the file defined in the * file.0 header, then the operation failed */ if (btotal != fullsize) { if (btotal < fullsize) { hoz_lf(); sprintf(bar, HOZ_PASTEMISSING, foo); hoz_print(bar); hoz_lf(); } sprintf(foo, "%u/%u", btotal, fullsize); hoz_echo(406, foo); free(outfname); return 406; } /* calculate the time spent in this operation */ elapsed = (double) (clock() - initime) / CLOCKS_PER_SEC; elapsed = (elapsed) ? elapsed : 0.001; /* can't be 0 seconds! */ /* yes */ hoz_lf(); sprintf(bar, HOZ_PASTEEND, origfname, btotal, elapsed, (size_t) ((double) btotal / elapsed), outpath); hoz_print(bar); hoz_lf(); free(outfname); return 0; } /** * hoz_paste_hr - reads the header from the file.0 file * @ifname: "file.0" filename */ int hoz_paste_hr(const char *ifname, const char *origfname) { int i, read, ssize; char buf[FILESTREAMSIZE + 1], aux[MAXLEN], *foo, *bar; FILE *f; bar = (char *) origfname; headersize = 0; ssize = FILESTREAMSIZE; if (ssize < 512) { ssize = 512; } f = fopen(ifname, "rb"); read = (int) fread(buf, sizeof(char), ssize, f); foo = buf; if (!read || strncmp(foo, "?????", 5)) { hoz_echo(405, ifname); return 405; } foo += 5; headersize += 5; i = 0; for (i = 0; *foo != '?'; foo++, i++, headersize++) { if (i == 20) { hoz_echo(405, ifname); return 405; } } if (strncmp(foo, "?????", 5)) { hoz_echo(405, ifname); return 405; } foo += 5; headersize += 5; if (*foo == '?') { hoz_echo(405, ifname); return 405; } for (i = 0; *foo != '?'; foo++, i++, headersize++) { if (i == 255) { hoz_echo(405, ifname); return 405; } *bar++ = *foo; } *bar = '\0'; if (strncmp(foo, "?????", 5)) { hoz_echo(405, ifname); return 405; } foo += 5; headersize += 5; if (*foo == '?') { hoz_echo(405, ifname); return 405; } for (i = 0; *foo != '?'; foo++, i++, headersize++) { if (i == 255) { hoz_echo(405, ifname); return 405; } aux[i] = *foo; } aux[i] = 0; fullsize = (int) atol(aux); if (!fullsize) { hoz_echo(405, ifname); return 405; } if (strncmp(foo, "?????", 5)) { hoz_echo(405, ifname); return 405; } foo += 5; headersize += 5; if (*foo == '?') { hoz_echo(405, ifname); return 405; } for (i = 0; *foo != '?'; foo++, i++, headersize++) { if (i == 255) { hoz_echo(405, ifname); return 405; } aux[i] = *foo; } aux[i] = 0; partsize = (int) atol(aux); if (!partsize) { hoz_echo(405, ifname); return 405; } if (strncmp(foo, "?????", 5)) { hoz_echo(405, ifname); return 405; } foo += 5; headersize += 5; fclose(f); return 0; } /** * fsize - Retrieves the size of a file * @path: filename */ size_t fsize(const char *path) { struct stat stats; stat(path, &stats); return (size_t) stats.st_size; } /** * isfile - a file exists? * @path: path to file */ int isfile(const char *path) { struct stat stats; return (!stat(path, &stats) && S_ISREG(stats.st_mode)); } /** * isdir - a directory exists? * @path: path to dir */ int isdir(const char *path) { struct stat stats; return (!stat(path, &stats) && S_ISDIR(stats.st_mode)); } /** * hoz_nopath - returns a file name, without the path * @file: the full filename */ char *hoz_nopath(const char *file) { char *aux; aux = (char *) (file + strlen(file)); while (*aux != HOZ_PATHSEP) { if (aux == file) { return aux; } aux--; } return aux + 1; } /** * mergepath - returns a file name, without the path * @dir: the full diectory * @fname: the full filename * @out: the output */ int mergepath(const char *dir, const char *fname, char *out) { const char *dirp; dirp = dir; if (!fname || !*fname) { return -1; } if (strcmp(dir, ".")) { while (*dirp) { *out++ = *dirp++; } if (dirp > dir && *(dirp - 1) != HOZ_PATHSEP) { *out++ = HOZ_PATHSEP; } } while (*fname) { *out++ = *fname++; } *out = '\0'; return 0; } /* * atolp(string) * returns a _positive_ number extracted from the string * if the string wasn't a number a 0 will be returned */ int atolp(const char *s) { int n = 0; char *c = (char*)s; while (*c) { if (*c >= '0' && *c <= '9') { n *= 10; n += (*c++ - '0'); } else { return 0; } } return n; } /* * atolmp(string, multiplier) * returns a _positive_ number extracted from the string and multiplies it * always returns an integer, 0 if the string wasn't a number */ int atolmp(const char *s, const int mult) { size_t n = 0, p = 0, d = 1; char *c = (char*)s; while (*c) { if (*c == '.') { if (p) { return 0; /* more than one '.' in the string? error */ } p = 1; *c++; } else if (*c >= '0' && *c <= '9') { if (p) { d *= 10; /* final decimal division */ } n *= 10; n += (*c++ - '0'); } else { return 0; } } if (d) { n /= d; } n *= (size_t)mult; if (n < 0) { printf("DA FOC!\n"); /* number is too big for size_t, error */ return 0; } return n; }