diff options
Diffstat (limited to 'copy')
-rw-r--r-- | copy/Makefile | 58 | ||||
-rw-r--r-- | copy/copy-help.pd | 15 | ||||
-rw-r--r-- | copy/copy.c | 205 |
3 files changed, 278 insertions, 0 deletions
diff --git a/copy/Makefile b/copy/Makefile new file mode 100644 index 0000000..0600286 --- /dev/null +++ b/copy/Makefile @@ -0,0 +1,58 @@ +NAME=copy +CSYM=copy + +LIBDIR=/usr/local/lib +PDDIR=$(LIBDIR)/pd +INSTALLPATH=$(PDDIR)/extra/ + +current: pd_darwin + + +# ----------------------- Linux ----------------------- + +pd_linux: $(NAME).pd_linux + +.SUFFIXES: .pd_linux + +LINUXCFLAGS = -ggdb -DPD -O3 -fPIC -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch + +# Debug +#LINUXCFLAGS = -ggdb -g -DPD -O0 -fPIC -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch + +LINUXINCLUDE = -I/usr/include -I./include -I../../../pd/src + +.c.pd_linux: + $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -c $(NAME).c + ld --export-dynamic -shared -o $(NAME).pd_linux $(NAME).o -lc + strip --strip-unneeded $(NAME).pd_linux + rm -f *.o + +# ----------------------- Mac OSX ----------------------- + +pd_darwin: $(NAME).pd_darwin + +.SUFFIXES: .pd_darwin + +DARWINCFLAGS = -DPD -O3 -Wall -W -Wshadow -Wstrict-prototypes \ + -Wno-unused -Wno-parentheses -Wno-switch -L/usr/local/lib/ + +DARWININCLUDE = $(LINUXINCLUDE) + +.c.pd_darwin: + $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) -c $(NAME).c + $(CC) -bundle -undefined suppress -flat_namespace -o $(NAME).pd_darwin $(NAME).o + rm -f *.o + +# ----------------------- Generic ----------------------- + +clean: + rm -f *.o *.pd_* so_locations + +install: + cp copy.pd_linux $(INSTALLPATH) + install -d $(PDDIR)/doc/5.reference/copy/ + install -m 644 doc/help-* $(PDDIR)/doc/5.reference/ diff --git a/copy/copy-help.pd b/copy/copy-help.pd new file mode 100644 index 0000000..cef5b57 --- /dev/null +++ b/copy/copy-help.pd @@ -0,0 +1,15 @@ +#N canvas 470 62 398 308 10; +#X obj 46 119 copy; +#X obj 46 154 sel 0 1; +#X msg 65 179 set copied; +#X msg 46 209 set failed; +#X symbolatom 46 250 10 0 0 0 - - -, f 10; +#X msg 46 62 list /source/path /destination/path; +#X text 42 21 [copy] copy file from source path to destination path +; +#X connect 0 0 1 0; +#X connect 1 0 3 0; +#X connect 1 1 2 0; +#X connect 2 0 4 0; +#X connect 3 0 4 0; +#X connect 5 0 0 0; diff --git a/copy/copy.c b/copy/copy.c new file mode 100644 index 0000000..d943aaa --- /dev/null +++ b/copy/copy.c @@ -0,0 +1,205 @@ +/* copy - copy a file from one path to another preserving permissions + * + * Author: Jamie Bullock <jamie@jamiebullock.com> + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org/> + */ + +#include "m_pd.h" + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <poll.h> +#include <stdlib.h> +#include <sys/stat.h> + +#ifdef __APPLE__ +#define O_BINARY 0 +#endif + +#define CONSOLE_PREFIX "[copy]: " + +typedef struct _copy +{ + t_object x_obj; + t_outlet *outlet; +} +t_copy; + +t_class *copy_class; + +int copy(const char *source, const char *target); + +void *copy_new(t_symbol *s, int argc, t_atom *argv) +{ + t_copy *x = (t_copy *)pd_new(copy_class); + x->outlet = outlet_new(&x->x_obj, &s_float); + post(CONSOLE_PREFIX "copy file from source path to destination path"); + return (void *)x; +} + +void copy_list(t_copy *x, t_symbol *s, int ac, t_atom *av) +{ + char source[MAXPDSTRING]; + char target[MAXPDSTRING]; + + if(ac != 2 || (av[0].a_type != A_SYMBOL && av[1].a_type != A_SYMBOL)) + { + pd_error(x, "expected a list containing <source path> <destination path>"); + } + + atom_string(&av[0], source, MAXPDSTRING); + atom_string(&av[1], target, MAXPDSTRING); + + int rv = copy(source, target); + rv++; + + if(rv) + { + post(CONSOLE_PREFIX "%s successfully copied to %s", source, target); + } + + outlet_float(x->outlet, (t_float)rv); +} + +void copy_setup(void) +{ + copy_class = class_new(gensym("copy"), + (t_newmethod)copy_new, + 0, sizeof(t_copy), 0, + A_GIMME, 0); + class_addlist(copy_class, copy_list); +} + +void block(int fd, int event) +{ + struct pollfd topoll; + topoll.fd = fd; + topoll.events = event; + poll(&topoll, 1, -1); + // no need to check errors - if the stream is bust then the + // next read/write will tell us +} + +int copy_data_buffer(int fdin, int fdout, void *buf, size_t bufsize) +{ + for(;;) + { + void *pos; + // read data to buffer + ssize_t bytestowrite = read(fdin, buf, bufsize); + if (bytestowrite == 0) break; // end of input + if (bytestowrite == -1) + { + if (errno == EINTR) continue; // signal handled + if (errno == EAGAIN) + { + block(fdin, POLLIN); + continue; + } + return -1; + } + + // write data from buffer + pos = buf; + while (bytestowrite > 0) + { + ssize_t bytes_written = write(fdout, pos, bytestowrite); + if (bytes_written == -1) + { + if (errno == EINTR) continue; + if (errno == EAGAIN) + { + block(fdout, POLLOUT); + continue; + } + return -1; + } + bytestowrite -= bytes_written; + pos += bytes_written; + } + } + return 0; +} + +#ifndef FILECOPY_BUFFER_SIZE +#define FILECOPY_BUFFER_SIZE (64*1024) +#endif + +int copy_data(int fdin, int fdout) +{ + for (size_t bufsize = FILECOPY_BUFFER_SIZE; bufsize >= 256; bufsize /= 2) + { + void *buffer = malloc(bufsize); + if (buffer != NULL) + { + int result = copy_data_buffer(fdin, fdout, buffer, bufsize); + free(buffer); + return result; + } + } + + return -1; +} + +int copy(const char *source, const char *target) +{ + struct stat info; + + int fdin = open(source, O_RDONLY|O_BINARY, 0); + if (fdin == -1) + { + error(CONSOLE_PREFIX "invalid input"); + return -1; + } + + int rv = fstat(fdin, &info); + + if(rv == -1) + { + error(CONSOLE_PREFIX "stat failed\n"); + return -1; + } + + int fdout = open(target, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, info.st_mode); + if (fdout == -1) + { + error(CONSOLE_PREFIX "invalid output\n"); + close(fdin); + return -1; + } + + rv = copy_data(fdin, fdout); + + if (rv == -1) + { + error(CONSOLE_PREFIX "copy failed\n"); + } + + return 0; +} |