/* filecopy - filecopy a file from one path to another preserving permissions * * Author: Jamie Bullock * * This is free and unencumbered software released into the public domain. * * Anyone is free to filecopy, 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 filecopyright laws, the author or authors * of this software dedicate any and all filecopyright 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 filecopyright 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 */ #include "m_pd.h" #include #include #include #include #include #include #ifdef __APPLE__ #define O_BINARY 0 #endif #ifdef WIN32 #define open _open #define close _close #define fdopen _fdopen #define fdclose _fdclose #endif #define CONSOLE_PREFIX "[filecopy]: " typedef struct _filecopy { t_object x_obj; t_outlet *outlet; } t_filecopy; t_class *filecopy_class; static int do_copy(const char *source, const char *target); void *filecopy_new(t_symbol *s, int argc, t_atom *argv) { t_filecopy *x = (t_filecopy *)pd_new(filecopy_class); x->outlet = outlet_new(&x->x_obj, &s_float); post(CONSOLE_PREFIX "copy file from source path to destination path"); return (void *)x; } static void filecopy_list(t_filecopy *x, t_symbol *s, int ac, t_atom *av) { char source[MAXPDSTRING]; char target[MAXPDSTRING]; int rv; if(ac != 2 || (av[0].a_type != A_SYMBOL && av[1].a_type != A_SYMBOL)) { pd_error(x, "expected a list containing "); } atom_string(&av[0], source, MAXPDSTRING); atom_string(&av[1], target, MAXPDSTRING); rv = do_copy(source, target); rv++; if(rv) { post(CONSOLE_PREFIX "%s successfully copied to %s", source, target); } outlet_float(x->outlet, (t_float)rv); } void filecopy_setup(void) { filecopy_class = class_new(gensym("filecopy"), (t_newmethod)filecopy_new, 0, sizeof(t_filecopy), 0, A_GIMME, 0); class_addlist(filecopy_class, filecopy_list); } static int copy_data(FILE *source, FILE *target) { char buffer[BUFSIZ]; size_t n; while ((n = fread(buffer, sizeof(char), sizeof(buffer), source)) > 0) { if (fwrite(buffer, sizeof(char), n, target) != n) { error("write failed"); return -1; } } return 0; } static int do_copy(const char *source, const char *target) { struct stat info; int rv; int rv2; int fdtarget; int fdsource; FILE *fsource; FILE *ftarget; fdsource = open(source, O_RDONLY|O_BINARY, 0); if (fdsource == -1) { error(CONSOLE_PREFIX "invalid input"); return -1; } rv = fstat(fdsource, &info); if(rv == -1) { error(CONSOLE_PREFIX "stat failed\n"); return -1; } fdtarget = open(target, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, info.st_mode); if (fdtarget == -1) { error(CONSOLE_PREFIX "invalid output\n"); close(fdsource); return -1; } fsource = fdopen(fdsource, "rb"); ftarget = fdopen(fdtarget, "wb"); rv = copy_data(fsource, ftarget); if (rv == -1) { error(CONSOLE_PREFIX "filecopy failed"); } rv = fclose(fsource); rv2 = fclose(ftarget); if (rv || rv2) { error(CONSOLE_PREFIX "file close failed"); rv = -1; } return rv; }