#!/bin/sh # This is a shell archive (produced by GNU sharutils 4.7). # To extract the files from this archive, save it to some FILE, remove # everything before the `#!/bin/sh' line above, then type `sh FILE'. # lock_dir=_sh03612 # # Existing files will *not* be overwritten, unless `-c' is specified. # This format requires very little intelligence at unshar time. # "if test", "echo", "mkdir", and "sed" may be needed. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 496 -rwxr-xr-x Amphibia.mk # 311 -rwxr-xr-x Posix.mk # 510 -rwxr-xr-x Makefile # 550 -rw-r--r-- counter.c # 2758 -rwxr-xr-x flist.c # 4112 -rwxr-xr-x path.c # 4677 -rwxr-xr-x posixio.c # 2913 -rwxr-xr-x swio.c # 5323 -rwxr-xr-x w32io.c # 2419 -rwxr-xr-x xcp.c # 111 -rw-r--r-- counter.h # 508 -rwxr-xr-x flist.h # 1982 -rwxr-xr-x io.h # 263 -rw-r--r-- path.h # 403 -rw-r--r-- test.sh # echo=echo shar_tty= shar_n= shar_c=' ' if test ! -d ${lock_dir} then : ; else ${echo} 'lock directory '${lock_dir}' exists' exit 1 fi if mkdir ${lock_dir} then : ; else ${echo} 'failed to create lock directory' exit 1 fi # ============= Amphibia.mk ============== if test -f 'Amphibia.mk' && test "$first_param" != -c; then ${echo} 'x -SKIPPING Amphibia.mk (file already exists)' else ${echo} 'x - extracting Amphibia.mk (text)' sed 's/^X//' << 'SHAR_EOF' > 'Amphibia.mk' && XCFLAGS=-g -Wall -pedantic XLDFLAGS=-g -Wall -pedantic X Xxcp: xcp.o path.o flist.o swio.o posixio.o w32io.o counter.o X Xxcp.o: path.h Xpath.o: path.h flist.h Xflist.o: flist.h io.h Xswio.o: io.h X Xw32io.o: io.h X cc -c $(CFLAGS) -DUSE_WIN32_RENAME w32io.c X Xposixio.o: io.h X cc -c $(CFLAGS) -DUSE_POSIX_RENAME posixio.c X Xclean: X -rm -rf *.o *.bak *.exe *~ xcp *.stackdump X Xshar: clean X shar -v *.mk Makefile *.c *.h test.sh X Xtar: clean X cd ..; tar cvfz xcp.tgz xcp X# DO NOT DELETE SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of Amphibia.mk failed' fi fi # ============= Posix.mk ============== if test -f 'Posix.mk' && test "$first_param" != -c; then ${echo} 'x -SKIPPING Posix.mk (file already exists)' else ${echo} 'x - extracting Posix.mk (text)' sed 's/^X//' << 'SHAR_EOF' > 'Posix.mk' && XCFLAGS=-g -Wall -pedantic XLDFLAGS=-g -Wall -pedantic X XSYSDEP = posixio.o X Xxcp: xcp.o path.o flist.o $(SYSDEP) X Xxcp.o: path.h Xpath.o: path.h flist.h Xflist.o: flist.h io.h Xw32io.o: io.h X Xclean: X -rm -rf *.o *.bak *.exe *~ xcp *.stackdump X Xtar: clean X cd ..; tar cvfz xcp.tgz xcp X# DO NOT DELETE SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of Posix.mk failed' fi fi # ============= Makefile ============== if test -f 'Makefile' && test "$first_param" != -c; then ${echo} 'x -SKIPPING Makefile (file already exists)' else ${echo} 'x - extracting Makefile (text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && XCFLAGS=-g -Wall -pedantic XLDFLAGS=-g -Wall -pedantic X Xxcp: xcp.o path.o flist.o swio.o posixio.o w32io.o counter.o X Xxcp.o: path.h Xpath.o: path.h flist.h Xflist.o: flist.h io.h Xswio.o: io.h X Xw32io.o: io.h X cc -c $(CFLAGS) -DUSE_WIN32_RENAME w32io.c X Xposixio.o: io.h X cc -c $(CFLAGS) -DUSE_POSIX_RENAME posixio.c X Xclean: X -rm -rf *.o *.bak *.exe *~ xcp *.stackdump X Xshar: clean X shar -V *.mk Makefile *.c *.h test.sh > ../xcp.shar X Xtar: clean X cd ..; tar cvfz xcp.tgz xcp X# DO NOT DELETE SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of Makefile failed' fi fi # ============= counter.c ============== if test -f 'counter.c' && test "$first_param" != -c; then ${echo} 'x -SKIPPING counter.c (file already exists)' else ${echo} 'x - extracting counter.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'counter.c' && X#include X#include "counter.h" X Xstatic int Enabled = 1; X Xstatic unsigned iScan = 0; Xstatic unsigned iCopy = 0; Xstatic unsigned iDele = 0; X X#define HACK 17u X X void Xcount_send(count_t type) X{ X switch (type) { X case ctEnable: X Enabled = 1; X return; X case ctDisable: X Enabled = 0; X return; X case ctScan: X iScan++; X break; X case ctCopy: X iScan++; X iCopy++; X break; X case ctDele: X iScan++; X iDele++; X break; X } X if ((iScan % HACK) == 1) { X printf("\r%8u scan, %8u copy, %8u dele\r", X iScan, iCopy, iDele); X fflush(stdout); X } X} SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of counter.c failed' fi fi # ============= flist.c ============== if test -f 'flist.c' && test "$first_param" != -c; then ${echo} 'x -SKIPPING flist.c (file already exists)' else ${echo} 'x - extracting flist.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'flist.c' && X#include X#include X#include X#include "flist.h" X#include "io.h" X Xconst char * Xflist_pick(flist_t *f, unsigned i) X{ X if (i > f->flist_n) { X return NULL; X } else { X return f->flist_ary[i]; X } X} X Xflist_t * Xflist_build(const char *dirpath) X{ X io_dirhandle_t d; X io_direntry_t *de; X flist_t *f; X unsigned i; X if ((d = io_diropen(dirpath)) == NULL) { X perror(dirpath); X goto err_with_nothing; X } X if ((f = malloc(sizeof *f)) == NULL) { X perror("malloc"); X goto err_with_d; X } X f->self = NULL; X f->flist_n = 0; X f->flist_na = 16; X f->flist_ary = malloc(f->flist_na * sizeof(f->flist_ary[0])); X if (f->flist_ary == NULL) { X perror("malloc"); X goto err_with_d_f; X } X while ((de = io_readdir(d)) != NULL) { X if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || X (de->d_name[1] == '.' && de->d_name[2] == '\0'))) { X continue; X } X if (f->flist_n >= f->flist_na) { X f->flist_ary = realloc(f->flist_ary, X f->flist_na * 2 * sizeof(f->flist_ary[0])); X if (f->flist_ary == NULL) { X perror("malloc"); X goto err_with_flist; X } X f->flist_na *= 2; X } X if ((f->flist_ary[f->flist_n] = strdup(de->d_name)) == NULL) { X perror("malloc"); X goto err_with_flist; X } X f->flist_n++; X } X if ((f->flist_dn = strdup(dirpath)) == NULL) { X goto err_with_flist; X } X io_closedir(d); X f->self = f; X return f; X Xerr_with_flist: X for (i = 0; i < f->flist_n; i++) { X free(f->flist_ary[i]); X } X free(f->flist_ary); Xerr_with_d_f: X free(f); Xerr_with_d: X io_closedir(d); Xerr_with_nothing: X return NULL; X} X Xvoid Xflist_dispose(flist_t *f) X{ X unsigned i; X if (f != f->self) { X printf("flist_dispose(%p): invalid file list\n", (void *)f); X return; X } X f->self = NULL; X for (i = 0; i < f->flist_n; i++) { X free(f->flist_ary[i]); X } X free(f->flist_ary); X free(f); X} X Xint XCompare(const void *a, const void *b) X{ X return strcmp(*(const char **)a, *(const char **)b); X} X Xint Xflist_each(flist_t *f, int (*func)(const char *path, void *arg), void *arg) X{ X unsigned i; X int r, stat; X if (f != f->self) { X printf("flist_each(%p): invalid file list\n", (void *)f); X return -1; X } X stat = 0; X for (i = 0; i < f->flist_n; i++) { X char *fullpath; X fullpath = io_join(f->flist_dn, f->flist_ary[i]); X if ((r = func(fullpath, arg)) != 0) { X stat = r; X } X free(fullpath); X } X return stat; X} X Xint Xflist_each_leaf(flist_t *f, X int (*func)(const char *path, void *arg), void *arg) X{ X unsigned i; X int r, stat; X if (f != f->self) { X printf("flist_each_leaf(%p): invalid file list\n", (void *)f); X return -1; X } X stat = 0; X for (i = 0; i < f->flist_n; i++) { X if ((r = func(f->flist_ary[i], arg)) != 0) { X stat = r; X } X } X return stat; X} X Xvoid Xflist_sort(flist_t *f) X{ X qsort(f->flist_ary, f->flist_n, sizeof(f->flist_ary[0]), Compare); X} SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of flist.c failed' fi fi # ============= path.c ============== if test -f 'path.c' && test "$first_param" != -c; then ${echo} 'x -SKIPPING path.c (file already exists)' else ${echo} 'x - extracting path.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'path.c' && X#include X#include X#include X#include "path.h" X#include "flist.h" X#include "io.h" X#include "counter.h" X Xint XPathDelete(const char *path, void *arg) X{ X return path_delete(path); X} X Xint Xdir_delete(const char *path) X{ X flist_t *f; X int r; X if ((f = flist_build(path)) == NULL) { X return -1; X } X flist_sort(f); X r = flist_each(f, PathDelete, NULL); X flist_dispose(f); X if (r == 0) { X if (io_rmdir(path) == -1) { X r = -1; X } X } X return r; X} X Xint Xpath_delete(const char *path) X{ X switch (io_filetype(path)) { X case ftNormal: X count_send(ctDele); X return io_delete(path); X case ftDirectory: X return dir_delete(path); X case ftMissing: X return 0; X case ftError: X default: X return -1; X } X} X Xint XPathList(const char *path, void *arg) X{ X return path_list(path, *((int *)arg)); X} X Xvoid XPrintL(const char *path, int level) X{ X int i; X for (i = 0; i < level; i++) { X putchar(' '); X } X printf("%s\n", path); X} X Xint Xdir_list(const char *path, int level) X{ X flist_t *f; X int r; X PrintL(path, level - 1); X if ((f = flist_build(path)) == NULL) { X return -1; X } X flist_sort(f); X r = flist_each(f, PathList, &level); X flist_dispose(f); X return r; X} X Xint Xpath_list(const char *path, int level) X{ X switch (io_filetype(path)) { X case ftDirectory: X return dir_list(path, level + 1); X case ftMissing: X case ftError: X return -1; X case ftNormal: X default: X PrintL(path, level); X return 0; X } X} X Xint Xpath_move(const char *path, const char *dest) X{ X if (io_rename(path, dest) == 0) { X goto Okay; X } X /* X * it would be better to check error code.... X */ X if (path_delete(dest) != 0) { X return -1; X } X if (io_rename(path, dest) != 0) { X return -1; X } XOkay: X return 0; X} X Xint XDirCopyDest(const char *leaf, void *arg) X{ X const char **dir_pair = arg; X const char *src, *dest; X int r; X count_send(ctScan); X if ((src = io_join(dir_pair[0], leaf)) == NULL) { X return -1; X } X if ((dest = io_join(dir_pair[1], leaf)) == NULL) { X free((char *)src); X return -1; X } X if (ftMissing != io_filetype(src)) { X free((char *)src); X free((char *)dest); X return 0; X } X r = path_delete(dest); X free((char *)src); X free((char *)dest); X return r; X} X Xint XDirCopySrc(const char *leaf, void *arg) X{ X const char **dir_pair = arg; X const char *src, *dest; X int r; X count_send(ctScan); X if ((src = io_join(dir_pair[0], leaf)) == NULL) { X return -1; X } X if ((dest = io_join(dir_pair[1], leaf)) == NULL) { X free((char *)src); X return -1; X } X r = path_copy(src, dest); X free((char *)src); X free((char *)dest); X return r; X} X Xint Xdir_copy(const char *src, const char *dest) X{ X flist_t *fsrc, *fdest; X const char *dir_pair[2]; X int r; X switch (io_filetype(dest)) { X case ftNormal: X io_delete(dest); X io_mkdir(dest); X break; X case ftDirectory: X break; X case ftMissing: X io_mkdir(dest); X break; X default: X printf("%s: bad file type\n", dest); X return -1; X } X dir_pair[0] = src; X dir_pair[1] = dest; X X if ((fdest = flist_build(dest)) == NULL) { X return -1; X } X flist_sort(fdest); X r = flist_each_leaf(fdest, DirCopyDest, dir_pair); X flist_dispose(fdest); X if (r != 0) { X return r; X } X X if ((fsrc = flist_build(src)) == NULL) { X return -1; X } X flist_sort(fsrc); X r = flist_each_leaf(fsrc, DirCopySrc, dir_pair); X flist_dispose(fsrc); X if (r != 0) { X return r; X } X X return 0; X} X Xint Xfile_copy(const char *src, const char *dest) X{ X switch (io_filetype(src)) { X case ftDirectory: X if (dir_delete(dest) != 0) { X return -1; X } X break; X case ftNormal: X case ftSystem: X if (io_file_update(src, dest)) { X return 0; X } X break; X case ftMissing: X break; X case ftError: X default: X break; X } X count_send(ctCopy); X return io_copy(src, dest); X} X Xint Xpath_copy(const char *src, const char *dest) X{ X switch (io_filetype(src)) { X case ftNormal: X return file_copy(src, dest); X break; X case ftDirectory: X return dir_copy(src, dest); X break; X case ftSystem: X return file_copy(src, dest); X break; X case ftMissing: X printf("%s: file vanished\n", src); X return -1; X case ftError: X default: X printf("%s: error or bad file type\n", src); X return -1; X } X} SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of path.c failed' fi fi # ============= posixio.c ============== if test -f 'posixio.c' && test "$first_param" != -c; then ${echo} 'x -SKIPPING posixio.c (file already exists)' else ${echo} 'x - extracting posixio.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'posixio.c' && X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include "io.h" X Xstatic int Verbose = 0; X Xvoid Xio_debug(int verbose) X{ X Verbose = verbose; X} X Xstatic void Xio_perror(const char *str) X{ X perror(str); X} X Xint Xio_delete(const char *path) X{ X printf("RM %s\n", path); X if (0 == unlink(path)) { X return 0; X } X switch (errno) { X case EACCES: X /* chmod ugo+w parent(path) and retry */ X /* fallthru */ X default: X io_perror(path); X return -1; X } X} X Xint Xio_mkdir(const char *path) X{ X if (Verbose) { X printf("MD %s\n", path); X } X if (0 != mkdir(path, 0777)) { X io_perror(path); X return -1; X } X return 0; X} X Xint Xio_rmdir(const char *path) X{ X if (Verbose) { X printf("RD %s\n", path); X } X if (rmdir(path) != 0) { X io_perror(path); X return -1; X } X return 0; X} X Xio_filetype_t Xio_filetype(const char *path) X{ X struct stat st; X if (Verbose >= 2) { X printf("QA %s\n", path); X } X if (stat(path, &st) == -1) { X if (errno == ENOENT) { X return ftMissing; X } X io_perror(path); X return ftError; X } X if (S_ISREG(st.st_mode)) { X return ftNormal; X } X if (S_ISDIR(st.st_mode)) { X return ftDirectory; X } X return ftSystem; X} X X#define COPYBUF 1024 * 1024 * 10 X Xint Xio_copy(const char *src, const char *dest) X{ X struct stat stsrc; X static char *buf = NULL; X ssize_t rst; X int ifd, ofd; X if (Verbose) { X printf("CP %s %s\n", src, dest); X } X if (buf == NULL) { X buf = malloc(COPYBUF); X if (buf == NULL) { X io_perror("malloc"); X return -1; X } X } X if ((ifd = open(src, O_RDONLY)) == -1) { X io_perror(src); X return -1; X } X if (fstat(ifd, &stsrc) == -1) { X io_perror(src); X goto error_with_only_ifd_open; X } X if ((ofd = open(dest, O_WRONLY)) == -1) { X if (errno != ENOENT) { X io_perror(dest); X goto error_with_only_ifd_open; X } X ofd = open(dest, O_WRONLY | O_CREAT, stsrc.st_mode); X if (ofd == -1) { X io_perror(dest); X goto error_with_only_ifd_open; X } X } else { X if (fchmod(ofd, stsrc.st_mode) == -1) { X io_perror(dest); X goto error_with_both_handle_open; X } X } X while ((rst = read(ifd, &buf, COPYBUF)) > 0) { X if (write(ofd, buf, rst) != rst) { X io_perror(dest); X goto error_with_both_handle_open; X } X } X if (close(ofd) == -1) { X io_perror(dest); X goto error_with_only_ifd_open; X } X if (close(ifd) == -1) { X io_perror(src); X return -1; X } X if (Verbose >= 2) { X printf(" ... ok\n"); X } X return 0; Xerror_with_both_handle_open: X close(ofd); Xerror_with_only_ifd_open: X close(ifd); X return -1; X} X Xint Xio_rename(const char *src, const char *dest) X{ X if (Verbose) { X printf("MV %s %s\n", src, dest); X } X if (rename(src, dest) == -1) { X io_perror(dest); X return -1; X } X return 0; X} X Xtypedef struct { X DIR *dh; X io_direntry_t de; X} DirHandle; X Xio_dirhandle_t Xio_diropen(const char *path) X{ X DirHandle *d; X if ((d = malloc(sizeof *d)) == NULL) { X perror("malloc"); X return NULL; X } X if ((d->dh = opendir(path)) == NULL) { X io_perror(path); X free(d); X return NULL; X } X return (io_dirhandle_t)d; X} X Xio_direntry_t * Xio_readdir(io_dirhandle_t dx) X{ X DirHandle *d = (DirHandle *)dx; X struct dirent *ent; X if (d->dh == NULL) { X return NULL; X } X if ((ent = readdir(d->dh)) == NULL) { X return NULL; X } X strcpy(d->de.d_name, ent->d_name); X return &(d->de); X} X Xint Xio_closedir(io_dirhandle_t dx) X{ X DirHandle *d = (DirHandle *)dx; X if (d->dh != NULL) { X closedir(d->dh); X } X free(d); X return 0; X} X Xint Xio_file_update(const char *cond, const char *obj) X{ X struct stat stc, sto; X X if (Verbose >= 2) { X printf("QU %s %s\n", cond, obj); X } X if (stat(cond, &stc) == -1) { X io_perror(cond); X goto Error; X } X if (stat(obj, &sto) == -1) { X switch (errno) { X case ENOENT: X goto Error; X default: X io_perror(obj); X goto Error; X } X } X X if (stc.st_size != sto.st_size) { X printf("%s: size %ld != %ld\n", obj, X (long)sto.st_size, X (long)stc.st_size); X goto Error; X } X X if (sto.st_mtime >= stc.st_mtime) { X return 1; X } X XError: X return 0; X} X Xchar * Xio_join(const char *dirname, const char *leafname) X{ X size_t nd, nl, nt; X char *buf; X nd = strlen(dirname); X nl = strlen(leafname); X nt = nd + 1 + nl; X if ((buf = malloc(nt + 1)) == NULL) { X return NULL; X } X memcpy(buf, dirname, nd); X buf[nd] = '/'; X memcpy(buf + nd + 1, leafname, nl); X buf[nt] = '\0'; X return buf; X} X Xvoid Xio_switch(int sym) X{ X puts("POSIX only: -w option ignored"); X} SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of posixio.c failed' fi fi # ============= swio.c ============== if test -f 'swio.c' && test "$first_param" != -c; then ${echo} 'x -SKIPPING swio.c (file already exists)' else ${echo} 'x - extracting swio.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'swio.c' && X#include X X#include "io.h" X#define USE_POSIX_RENAME X# include "io.h" X#undef USE_POSIX_RENAME X#define USE_WIN32_RENAME X# include "io.h" X#undef USE_WIN32_RENAME X#include "io.h" X Xstatic int Api = 'w'; X Xvoid Xio_switch(int sym) X{ X Api = sym; X} X Xvoid Xio_debug(int verbose) X{ X switch (Api) { X case 'w': X wio_debug(verbose); X break; X case 'p': X pio_debug(verbose); X break; X } X} X Xint Xio_delete(const char *path) X{ X switch (Api) { X case 'w': X return wio_delete(path); X case 'p': X return pio_delete(path); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xint Xio_mkdir(const char *path) X{ X switch (Api) { X case 'w': X return wio_mkdir(path); X case 'p': X return pio_mkdir(path); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xint Xio_rmdir(const char *path) X{ X switch (Api) { X case 'w': X return wio_rmdir(path); X case 'p': X return pio_rmdir(path); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xio_filetype_t Xio_filetype(const char *path) X{ X switch (Api) { X case 'w': X return wio_filetype(path); X case 'p': X return pio_filetype(path); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xint Xio_copy(const char *src, const char *dest) X{ X switch (Api) { X case 'w': X return wio_copy(src, dest); X case 'p': X return pio_copy(src, dest); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xint Xio_rename(const char *src, const char *dest) X{ X switch (Api) { X case 'w': X return wio_rename(src, dest); X case 'p': X return pio_rename(src, dest); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xio_dirhandle_t Xio_diropen(const char *path) X{ X switch (Api) { X case 'w': X return wio_diropen(path); X case 'p': X return pio_diropen(path); X default: X fputs("invalid api\n", stderr); X return NULL; X } X} X Xio_direntry_t * Xio_readdir(io_dirhandle_t dx) X{ X switch (Api) { X case 'w': X return wio_readdir(dx); X case 'p': X return pio_readdir(dx); X default: X fputs("invalid api\n", stderr); X return NULL; X } X} X Xint Xio_closedir(io_dirhandle_t dx) X{ X switch (Api) { X case 'w': X return wio_closedir(dx); X case 'p': X return pio_closedir(dx); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xint Xio_file_update(const char *cond, const char *obj) X{ X switch (Api) { X case 'w': X return wio_file_update(cond, obj); X case 'p': X return pio_file_update(cond, obj); X default: X fputs("invalid api\n", stderr); X return -1; X } X} X Xchar * Xio_join(const char *dirname, const char *leafname) X{ X switch (Api) { X case 'w': X return wio_join(dirname, leafname); X case 'p': X return pio_join(dirname, leafname); X default: X fputs("invalid api\n", stderr); X return NULL; X } X} SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of swio.c failed' fi fi # ============= w32io.c ============== if test -f 'w32io.c' && test "$first_param" != -c; then ${echo} 'x -SKIPPING w32io.c (file already exists)' else ${echo} 'x - extracting w32io.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'w32io.c' && X#include X#include X#include X#include X#include "io.h" X Xstatic int Verbose = 0; X Xvoid Xio_debug(int verbose) X{ X Verbose = verbose; X} X Xstatic void Xio_perror(const char *str) X{ X LPTSTR lpBuffer; X FormatMessage( X FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, X NULL, X GetLastError(), X LANG_USER_DEFAULT, X (LPTSTR)&lpBuffer, X 0, X NULL); X printf("%s: %s\n", str, lpBuffer); X LocalFree(lpBuffer); X} X Xint Xio_delete(const char *path) X{ X DWORD attr; X printf("RM %s\n", path); X if (DeleteFile(path)) { X return 0; X } X switch (GetLastError()) { X case ERROR_ACCESS_DENIED: X attr = GetFileAttributes(path); X attr &= ~(DWORD)FILE_ATTRIBUTE_READONLY; X SetFileAttributes(path, attr); X if (DeleteFile(path)) { X return 0; X } X /* fallthru */ X default: X io_perror(path); X return -1; X } X} X Xint Xio_mkdir(const char *path) X{ X SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, FALSE }; X if (Verbose) { X printf("MD %s\n", path); X } X if (CreateDirectory(path, &sa) != TRUE) { X io_perror(path); X return -1; X } X return 0; X} X Xint Xio_rmdir(const char *path) X{ X if (Verbose) { X printf("RD %s\n", path); X } X if (RemoveDirectory(path) != TRUE) { X io_perror(path); X return -1; X } X return 0; X} X Xio_filetype_t Xio_filetype(const char *path) X{ X DWORD st; X if (Verbose >= 2) { X printf("QA %s\n", path); X } X if ((st = GetFileAttributes(path)) == 0xFFFFFFFF) { X if (GetLastError() == ERROR_FILE_NOT_FOUND) { X return ftMissing; X } X io_perror(path); X return ftError; X } X if (FILE_ATTRIBUTE_DIRECTORY & st) { X return ftDirectory; X } X if (FILE_ATTRIBUTE_SYSTEM & st) { X return ftSystem; X } X return ftNormal; X} X Xint Xio_copy(const char *src, const char *dest) X{ X if (Verbose) { X printf("CP %s %s\n", src, dest); X } X if (CopyFile(src, dest, FALSE) == 0) { X io_perror(dest); X return -1; X } X return 0; X} X Xint Xio_rename(const char *src, const char *dest) X{ X if (Verbose) { X printf("MV %s %s\n", src, dest); X } X if (MoveFile(src, dest) == 0) { X io_perror(dest); X return -1; X } X return 0; X} X Xtypedef struct { X HANDLE dh; X WIN32_FIND_DATA df; X io_direntry_t de; X} DirHandle; X Xio_dirhandle_t Xio_diropen(const char *path) X{ X DirHandle *d; X char *pathbuf; X if ((d = malloc(sizeof *d)) == NULL) { X perror("malloc"); X return NULL; X } X if ((pathbuf = malloc(strlen(path) + 3)) == NULL) { X perror("malloc"); X free(d); X return NULL; X } X strcpy(pathbuf, path); X strcat(pathbuf, "\\*"); X d->dh = FindFirstFile(pathbuf, &(d->df)); X if (d->dh == INVALID_HANDLE_VALUE) { X io_perror(path); X free(pathbuf); X free(d); X return NULL; X } X free(pathbuf); X return (io_dirhandle_t)d; X} X Xio_direntry_t * Xio_readdir(io_dirhandle_t dx) X{ X DirHandle *d = (DirHandle *)dx; X if (d->dh == INVALID_HANDLE_VALUE) { X return NULL; X } X strcpy(d->de.d_name, d->df.cFileName); X if (d->dh == INVALID_HANDLE_VALUE) { X d->df.cFileName[0] = '\0'; X } else { X if (FALSE == FindNextFile(d->dh, &(d->df))) { X FindClose(d->dh); X d->dh = INVALID_HANDLE_VALUE; X } X } X return &(d->de); X} X Xint Xio_closedir(io_dirhandle_t dx) X{ X DirHandle *d = (DirHandle *)dx; X if (d->dh != INVALID_HANDLE_VALUE) { X FindClose(d->dh); X } X free(d); X return 0; X} X Xstatic int Xcompare_file_time(FILETIME *a, FILETIME *b) X{ X if (a->dwHighDateTime > b->dwHighDateTime) X return 1; X if (a->dwHighDateTime < b->dwHighDateTime) X return -1; X if (a->dwLowDateTime > b->dwLowDateTime) X return 1; X if (a->dwLowDateTime < b->dwLowDateTime) X return -1; X return 0; X} X Xint Xio_file_update(const char *cond, const char *obj) X{ X FILETIME tc, to; X DWORD sc, so; X HANDLE hc, ho; X SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, FALSE }; X X hc = CreateFile(cond, 0, FILE_SHARE_WRITE, &sa, OPEN_EXISTING, X FILE_ATTRIBUTE_NORMAL, 0); X if (hc == INVALID_HANDLE_VALUE) { X io_perror(cond); X goto false; X } X ho = CreateFile(obj, 0, FILE_SHARE_WRITE, &sa, OPEN_EXISTING, X FILE_ATTRIBUTE_NORMAL, 0); X if (ho == INVALID_HANDLE_VALUE) { X CloseHandle(hc); X goto false_hc; X } X X sc = GetFileSize(hc, NULL); X if (sc == 0xFFFFFFF) X goto false_hc_ho; X so = GetFileSize(ho, NULL); X if (so == 0xFFFFFFF) X goto false_hc_ho; X if (sc != so) { X printf("%s: size %ld != %ld\n", obj, (long)so, (long)sc); X goto false_hc_ho; X } X X if (GetFileTime(hc, NULL, NULL, &tc) == FALSE) X goto false_hc_ho; X if (GetFileTime(ho, NULL, NULL, &to) == FALSE) X goto false_hc_ho; X switch (compare_file_time(&tc, &to)) { X case -1: X case 0: X CloseHandle(ho); X CloseHandle(hc); X if (Verbose >= 2) { X printf("QU %s True\n", obj); X } X return 1; X default: X break; X } X Xfalse_hc_ho: X CloseHandle(ho); Xfalse_hc: X CloseHandle(hc); Xfalse: X if (Verbose >= 2) { X printf("QU %s False\n", obj); X } X return 0; X} X Xchar * Xio_join(const char *dirname, const char *leafname) X{ X size_t nd, nl, nt; X char *buf; X nd = strlen(dirname); X nl = strlen(leafname); X nt = nd + 1 + nl; X if ((buf = malloc(nt + 1)) == NULL) { X return NULL; X } X memcpy(buf, dirname, nd); X buf[nd] = '\\'; X memcpy(buf + nd + 1, leafname, nl); X buf[nt] = '\0'; X return buf; X} X Xvoid Xio_switch(int sym) X{ X puts("Win32 only: -p option ignored"); X} SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of w32io.c failed' fi fi # ============= xcp.c ============== if test -f 'xcp.c' && test "$first_param" != -c; then ${echo} 'x -SKIPPING xcp.c (file already exists)' else ${echo} 'x - extracting xcp.c (text)' sed 's/^X//' << 'SHAR_EOF' > 'xcp.c' && X#include X#include "io.h" X#include "path.h" X#include "counter.h" X Xtypedef enum { mUndef, mList, mCopy, mDelete, mMove } mode_t; X Xint Xhelp(void) X{ X puts("usage: xcp [-vd] [-r file] [-[mc] src dest] ..."); X puts(" -c src dest\t\tCopy src to dest"); X puts(" -d\t\t\tDebug"); X puts(" -l file\t\tList file"); X puts(" -m src dest\t\tMove src to dest"); X puts(" -p\t\t\tuse POSIX API"); X puts(" -r file\t\tRemove file"); X puts(" -v\t\t\tVerbose"); X puts(" -w\t\t\tuse Win32 API"); X return 0; X} X Xint Xxcp_option(const char *arg, mode_t *mode) X{ X count_send(ctEnable); X for (arg++; *arg; arg++) { X switch (*arg) { X case 'v': X case 'V': X io_debug(1); X count_send(ctEnable); X break; X case 'd': X case 'D': X io_debug(2); X count_send(ctDisable); X break; X case 'r': X case 'R': X *mode = mDelete; X break; X case 'l': X case 'L': X *mode = mList; X break; X case 'c': X case 'C': X *mode = mCopy; X break; X case 'm': X case 'M': X *mode = mMove; X break; X case 'h': X case 'H': X help(); X return -1; X case 'w': X case 'W': X io_switch('w'); X break; X case 'u': X case 'U': X case 'p': X case 'P': X io_switch('p'); X break; X default: X printf("undefined option '%c'\n", *arg); X help(); X return -1; X break; X } X } X return 0; X} X Xstatic int ArgInd = 0, ArgC = 0; Xstatic const char **ArgV = {NULL}; X Xstatic const char * XGetArg(void) X{ X if (ArgInd > ArgC || ArgInd < 0) { X return NULL; X } else { X return ArgV[ArgInd++]; X } X} X Xint Xxcp(void) X{ X int r = 0; X int n = 0; X const char *arg, *arg2; X mode_t mode = mUndef; X while ((arg = GetArg()) != NULL) { X if (arg[0] == '-') { X if ((r |= xcp_option(arg, &mode)) != 0) X return r; X continue; X } X switch (mode) { X case mDelete: X r |= path_delete(arg); X break; X case mList: X r |= path_list(arg, 0); X break; X case mMove: X if ((arg2 = GetArg()) != NULL) { X r |= path_move(arg, arg2); X } X break; X case mCopy: X if ((arg2 = GetArg()) != NULL) { X r |= path_copy(arg, arg2); X } X break; X case mUndef: X default: X help(); X return -1; X break; X } X n++; X } X if (n == 0) { X help(); X } X return r; X} X Xint Xmain(int argc, const char **argv) X{ X ArgC = argc; X ArgV = argv; X ArgInd = 1; X return xcp(); X} SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of xcp.c failed' fi fi # ============= counter.h ============== if test -f 'counter.h' && test "$first_param" != -c; then ${echo} 'x -SKIPPING counter.h (file already exists)' else ${echo} 'x - extracting counter.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'counter.h' && Xtypedef enum count_t { X ctDisable, ctEnable, ctScan, ctCopy, ctDele X} count_t; X Xvoid count_send(count_t type); SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of counter.h failed' fi fi # ============= flist.h ============== if test -f 'flist.h' && test "$first_param" != -c; then ${echo} 'x -SKIPPING flist.h (file already exists)' else ${echo} 'x - extracting flist.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'flist.h' && X/* flist.h */ X Xtypedef struct { X unsigned flist_n; X unsigned flist_na; X char **flist_ary; X char *flist_dn; X void *self; X} flist_t; X Xflist_t *flist_build(const char *dirpath); Xvoid flist_sort(flist_t *f); Xvoid flist_dispose(flist_t *f); Xint flist_each(flist_t *f, int (*func)(const char *path, void *arg), X void *arg); Xint flist_each_leaf(flist_t *f, int (*func)(const char *path, void *arg), X void *arg); X X#if 0 Xconst char *flist_pick(flist_t *f, unsigned i); X X# define flist_size(f) ((f)->flist_n) X#endif SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of flist.h failed' fi fi # ============= io.h ============== if test -f 'io.h' && test "$first_param" != -c; then ${echo} 'x -SKIPPING io.h (file already exists)' else ${echo} 'x - extracting io.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'io.h' && X/* io.h */ X X#undef io_delete X#undef io_rmdir X#undef io_mkdir X#undef io_filetype X#undef io_rename X#undef io_copy X#undef io_diropen X#undef io_readdir X#undef io_closedir X#undef io_file_update X#undef io_join X#undef io_debug X#undef io_switch X X#ifdef USE_POSIX_RENAME X# define io_delete pio_delete X# define io_rmdir pio_rmdir X# define io_mkdir pio_mkdir X# define io_filetype pio_filetype X# define io_rename pio_rename X# define io_copy pio_copy X# define io_diropen pio_diropen X# define io_readdir pio_readdir X# define io_closedir pio_closedir X# define io_file_update pio_file_update X# define io_join pio_join X# define io_debug pio_debug X# define io_switch pio_switch X#endif X X#ifdef USE_WIN32_RENAME X# define io_delete wio_delete X# define io_rmdir wio_rmdir X# define io_mkdir wio_mkdir X# define io_filetype wio_filetype X# define io_rename wio_rename X# define io_copy wio_copy X# define io_diropen wio_diropen X# define io_readdir wio_readdir X# define io_closedir wio_closedir X# define io_file_update wio_file_update X# define io_join wio_join X# define io_debug wio_debug X# define io_switch wio_switch X#endif X X#ifndef IO_FILETYPE_T_DEFINED X#define IO_FILETYPE_T_DEFINED X Xtypedef enum io_filetype_t { X ftError, ftMissing, ftSystem, ftDirectory, ftNormal X} io_filetype_t; X Xtypedef void *io_dirhandle_t; Xtypedef struct io_direntry_t { X char d_name[1024]; X} io_direntry_t; X X#endif X Xint io_delete(const char *path); Xint io_rmdir(const char *path); Xint io_mkdir(const char *path); Xio_filetype_t io_filetype(const char *path); Xint io_rename(const char *src, const char *dest); Xint io_copy(const char *src, const char *dest); X Xio_dirhandle_t io_diropen(const char *path); Xio_direntry_t *io_readdir(io_dirhandle_t d); Xint io_closedir(io_dirhandle_t d); X Xint io_file_update(const char *cond, const char *obj); X Xchar *io_join(const char *dirname, const char *leafname); X Xvoid io_debug(int verbose); X Xvoid io_switch(int sym); SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of io.h failed' fi fi # ============= path.h ============== if test -f 'path.h' && test "$first_param" != -c; then ${echo} 'x -SKIPPING path.h (file already exists)' else ${echo} 'x - extracting path.h (text)' sed 's/^X//' << 'SHAR_EOF' > 'path.h' && X/* pio.h */ X Xint dir_delete(const char *path); Xint path_is_dir(const char *path); Xint path_delete(const char *path); Xint path_list(const char *path, int level); Xint path_move(const char *path, const char *dest); Xint path_copy(const char *path, const char *dest); SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of path.h failed' fi fi # ============= test.sh ============== if test -f 'test.sh' && test "$first_param" != -c; then ${echo} 'x -SKIPPING test.sh (file already exists)' else ${echo} 'x - extracting test.sh (text)' sed 's/^X//' << 'SHAR_EOF' > 'test.sh' && X#!/bin/sh X Xmd() { X test -d $1 || mkdir $1 X} X Xecho test 1 Xmd zfoo Xmd zfoo/zbar Xmd zfoo/zbar/zbaz Xtouch zfoo/zbar/zbaz/quux X./xcp -L zfoo || echo exit code $? X./xcp -r zfoo || echo exit code $? X Xmd zfoo Xmd zfoo/zbar Xmd zfoo/zbar/zbaz Xtouch zfoo/zbar/zbaz/quux Xmkdir zquux Xtouch zquux/qqqq X./xcp -m zfoo zquux || echo exit code $? X./xcp -L zquux || echo exit code $? X./xcp -r zquux || echo exit code $? X X X SHAR_EOF : if test $? -ne 0 then ${echo} 'restore of test.sh failed' fi fi if rm -fr ${lock_dir} then ${echo} 'x - removed lock directory `'${lock_dir}\''.' else ${echo} 'x - failed to remove lock directory `'${lock_dir}\''.' exit 1 fi exit 0