//! @brief This function manages the HOST mass storage application //! void host_ms_task(void) { if( Is_host_ready() ) { // Here, Enumeration successfull, device is operationnal if(Is_new_device_connection_event()) { // Update MS driver in case of if( host_mem_install() ) { #if (HOST_UPGRADE_MODE==ENABLE) b_new_msc_connected = TRUE; #endif Led1_on(); } } #if (HOST_SYNC_MODE==ENABLE) // Sync operating mode(if available) if( 0 != host_mem_get_lun() ) { if(Is_joy_right()) // Sync device to host stream { Led0_on(); sync_on_going=1; copy_dir( (U8 code *)dir_usb_out_name, (U8 code *)dir_local_in_name, 1 ); sync_on_going=0; Led3_off(); Led0_off(); } if(Is_joy_left()) // Sync host to device stream { Led0_on(); sync_on_going=1; copy_dir( (U8 code *)dir_local_out_name, (U8 code *)dir_usb_in_name, 1 ); sync_on_going=0; Led0_off(); Led3_off(); } } #endif #if (HOST_UPGRADE_MODE==ENABLE) if( b_new_msc_connected ) { // A new MSC is connected then start upgrade routine b_new_msc_connected = FALSE; firm_upgrade_run(); } #endif } // Device disconnection... if( Is_device_disconnection_event() ) { // Update MS driver in case of host_mem_uninstall(); Led1_off(); } }
extern dword copy_dir(const char *src, const char *dest, t_copy_cb cb, t_copy_overwritecb ocb, void *data) { int dl = xrIoDopen(src); dword result = 0; SceIoDirent sid; if (dl < 0) { if (cb != NULL) cb(src, dest, false, data); return 0; } xrIoMkdir(dest, 0777); memset(&sid, 0, sizeof(SceIoDirent)); while (xrIoDread(dl, &sid)) { char copysrc[260], copydest[260]; if (sid.d_name[0] == '.') continue; SPRINTF_S(copysrc, "%s/%s", src, sid.d_name); SPRINTF_S(copydest, "%s/%s", dest, sid.d_name); if (FIO_S_ISDIR(sid.d_stat.st_mode)) { result += copy_dir(copysrc, copydest, cb, ocb, data); continue; } if (copy_file(copysrc, copydest, cb, ocb, data)) ++result; memset(&sid, 0, sizeof(SceIoDirent)); } xrIoDclose(dl); return result; }
/** Recursively copy the contents of one directory to another. The * destination must already exist. Returns true on success, and false * otherwise. */ bool copy_dir(const QString &source, const QString &dest) { /* Source and destination as QDir's */ QDir src(source); QDir dst(dest); /* Get contents of the directory */ QFileInfoList contents = src.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); /* Copy each entry in src to dst */ foreach (QFileInfo fileInfo, contents) { /* Get absolute path of source and destination */ QString fileName = fileInfo.fileName(); QString srcFilePath = src.absoluteFilePath(fileName); QString dstFilePath = dst.absoluteFilePath(fileName); if (fileInfo.isDir()) { /* This is a directory, make it and recurse */ if (!dst.mkdir(fileName)) return false; if (!copy_dir(srcFilePath, dstFilePath)) return false; } else if (fileInfo.isFile()) { /* This is a file, copy it */ if (!QFile::copy(srcFilePath, dstFilePath)) return false; } /* Ignore special files (e.g. symlinks, devices) */ }
static bool copy_entry(const char *source, const char *destination, uid_t uid, gid_t gid) { struct stat sb; if (lstat(source, &sb) != 0) return false; struct timeval tv[2]; tv[0].tv_sec = sb.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = sb.st_mtime; tv[1].tv_usec = 0; if (S_ISDIR(sb.st_mode)) { if (!copy_dir(source, destination, uid, gid, &sb)) return false; } else if (S_ISLNK(sb.st_mode)) { if (!copy_symlink(source, destination, uid, gid, &sb)) return false; } else if (S_ISREG(sb.st_mode)) { if (!copy_file(source, destination, uid, gid, &sb)) return false; } else { if (!copy_special(source, destination, uid, gid, &sb)) return false; } if (lutimes(destination, tv) != 0) return false; return true; }
extern u32 move_dir(const char *src, const char *dest, t_copy_cb cb, t_copy_overwritecb ocb, void *data) { u32 result = copy_dir(src, dest, cb, ocb, data); if (result > 0) utils_del_dir(src); return result; }
int copy_dir(string src, string dst, int dir_existed) { mixed *file; int count; int i; /* if (! is_root(previous_object())) return 0; */ count = 0; if (src[strlen(src) - 1] != '/') src += "/"; if (dst[strlen(dst) - 1] != '/') dst += "/"; // assure dst existed if (! dir_existed) assure_file(dst); file = get_dir(src, -1); if (! sizeof(file)) return count; write (HIC "复制目录(" + src + ") -- > (" + dst + ")。\n" NOR); i = sizeof(file); while (i--) { reset_eval_cost(); if (file[i][1] != -2) { if ( file_size(dst) == -1 ) { mkdir(dst); write("创建目录" + dst + "成功。\n"); } if (cp(src + file[i][0], dst + file[i][0])) { write(src + file[i][0] + " --> "); write(dst + file[i][0] + "\n"); count++; } } } i = sizeof(file); while (i--) { reset_eval_cost(); if (file[i][1] == -2) { mkdir(dst + file[i][0]); count += copy_dir(src + file[i][0], dst + file[i][0], DIR_EXISTED); } } return count; }
void copy_dir (const char * source , const char * dest ) { DIR * dirp ; struct dirent * dir_struct ; char path_dest_temp[PATH_MAX_LEN] = {0} ; char * temp_path ; int dest_length = strlen(dest) ; int is_dir_ret = 0 ; create_dir (source , dest) ; strcpy (path_dest_temp , dest) ; if (NULL == (dirp = opendir (source) ) ){ perror ("opendir error ") ; exit (1) ; } chdir (source) ; temp_path = get_current_dir_name () ; printf ("current path is %s\n",temp_path ) ; while( NULL != (dir_struct = readdir (dirp ) ) ) { // 文件名还是自己造吧 is_dir_ret = is_directory (dir_struct->d_name ) ; // 目录文件 if ( ISDIR == is_dir_ret ) { if ( !strcmp (dir_struct->d_name,".") ){ continue ; } else if (!strcmp (dir_struct->d_name , "..") ) { continue ; } printf ("copy a directory \n") ; strcpy ( path_dest_temp + dest_length , dir_struct->d_name) ; strcat (path_dest_temp , "/") ; copy_dir (dir_struct->d_name , path_dest_temp ) ; chdir ("..") ; } else if ( EXIST == is_dir_ret ) { // 普通文件 printf ("target is a normal file , and it exist ! we will creat a dir have the same name !\n") ; strcpy ( path_dest_temp + dest_length , dir_struct->d_name) ; copy (dir_struct->d_name , path_dest_temp ) ; } else { // 特殊文件 printf ("target is special file ! we will create it .\n") ; strcpy ( path_dest_temp + dest_length , dir_struct->d_name) ; copy (dir_struct->d_name , path_dest_temp ) ; } } free (temp_path) ; }
/// 这里应该做 错误检查 , 检查相对应模式下的错误情况 比如在copy 文件时 , source 不能是目录 , copy 目录时 , source 不能是文件等 必须做特殊处理 int copy_file (struct mode *oper_mode , int argc , char* argv[]) { // 保存 argv 中的 dest char path_buf[PATH_MAX_LEN] ; char source_path[PATH_MAX_LEN] ; // 这里 对于递归 , 接口写好! , directory , directory 参数 , 这样的话, 就可以调, target的话, bzero (path_buf , PATH_MAX_LEN) ; strcpy(source_path , argv[argc-2]) ; if( 1 == oper_mode->directory ) { printf ("copy directory!\n ") ; // source是目录 get_full_path (argv[argc-1] , path_buf) ; // 判断用户输入的是否符合自己规定 if ( '/' != path_buf[strlen(path_buf)-1] ){ strcat (path_buf , "/") ; } if ( '/' != source_path[strlen(source_path)-1] ) { strcat (source_path , "/" ) ; } cat_source_to_dest (source_path , path_buf) ; copy_dir (source_path,path_buf) ; return TRUE ; } else { // 全都处理成绝对路径 get_full_path (argv[argc-1] ,path_buf ) ; if (ISDIR == is_directory(path_buf )) { printf ("target is a direcroty !\n") ; // 首先处理名字 // 我需要st_mode 值 和 st_uid , st_gid值 然后去调函数设置 // 生成最终的文件名 if ( '/' != path_buf[strlen(path_buf)-1] ){ strcat (path_buf , "/") ; } cat_source_to_dest (argv[argc-2] , path_buf) ; path_buf[strlen(path_buf)-1] = 0 ; copy (argv[argc-2] , path_buf ) ; }else { // 判断文件是否存在 if (!access (path_buf , F_OK)) { // 存在 printf ("file now is exist ! overwrite it now !\n") ; } copy (argv[argc-2] , path_buf ) ; return TRUE ; } } return TRUE ; }
int copy_custom_files(const char* path_dist, const char* path_src) { if (ensure_path_mounted(path_dist) != 0) { LOGE("Can't mount %s\n", path_dist); return INSTALL_ERROR; } if (ensure_path_mounted(path_src) != 0) { LOGE("Can't mount %s\n", path_src); return INSTALL_ERROR; } if (copy_dir(path_dist, path_src) < 0) return INSTALL_ERROR; else return INSTALL_SUCCESS; }
int main(int argc,const string_t* argv){ int status,i; struct stat statbuf; if(argc<3) goto printhowto; if(stat(argv[argc-1],&statbuf)){ /* * The destination file/dir does not exist. */ if(argc>3) goto printhowto; }else{ /* * The destination file/dir does exist. */ if(S_ISDIR(statbuf.st_mode)) /* * The destination is a directory. */ goto copydir; else /*if(!(S_ISREG(statbuf.st_mode)))*/ /* * If the destination is not a directory, fail. */ goto printhowto; } return copy_object(argv[1],argv[2]); copydir: status = 0; for(i=1;i<argc-1;++i) if(copy_dir(argv[i],argv[argc-1])) status = 1; return status; printhowto: fprintf(stderr,"Usage: cp from-file-or-dir dest-name; or cp file1 ... fileN dest-dir\n"); return 1; }
void setup() { str_init(&conf.shell); str_init(&conf.output_dir); str_init(&conf.static_dir); str_append_str(&conf.shell, "/bin/sh"); str_append_str(&conf.output_dir, "_output"); str_append_str(&conf.static_dir, "_static"); if (0 != mkdir(conf.output_dir.s, 0777)) { if (EEXIST != errno) { fatal("Unable to mkdir %s\n", conf.output_dir.s); } } if (file_exists(conf.output_dir.s)) { if (0 != copy_dir(conf.static_dir.s, conf.output_dir.s)) { warn("Unable to copy %s to %s\n", conf.static_dir.s, conf.output_dir.s); } } }
/* * copy_dir() * * Copies either a directory or a single file within a directory. If the * source argument names a directory, we recursively copy that directory, * otherwise we copy a single file. */ static int copy_dir(const char *src, const char *dst, bool force) { DIR *srcdir; struct dirent *de = NULL; struct stat fst; if (src == NULL || dst == NULL) return -1; /* * Try to open the source directory - if it turns out not to be a * directory, assume that it's a file and copy that instead. */ if ((srcdir = opendir(src)) == NULL) { if (errno == ENOTDIR) return copy_file(src, dst, true); return -1; } if (mkdir(dst, S_IRWXU) != 0) { /* * ignore directory already exist error */ if (errno != EEXIST) return -1; } while ((de = readdir(srcdir)) != NULL) { char src_file[MAXPGPATH]; char dest_file[MAXPGPATH]; if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; memset(src_file, 0, sizeof(src_file)); memset(dest_file, 0, sizeof(dest_file)); snprintf(src_file, sizeof(src_file), "%s/%s", src, de->d_name); snprintf(dest_file, sizeof(dest_file), "%s/%s", dst, de->d_name); if (stat(src_file, &fst) < 0) { if (srcdir != NULL) { closedir(srcdir); srcdir = NULL; } return -1; } if (fst.st_mode & S_IFDIR) { /* recurse to handle subdirectories */ if (force) copy_dir(src_file, dest_file, true); } else if (fst.st_mode & S_IFREG) { if ((copy_file(src_file, dest_file, 1)) == -1) { if (srcdir != NULL) { closedir(srcdir); srcdir = NULL; } return -1; } } } if (srcdir != NULL) { closedir(srcdir); srcdir = NULL; } return 1; }
int copy_dir(const char* path_dist, const char* path_src) { int ret = 0; DIR* d; struct dirent* de; d = opendir(path_src); if (d == NULL) { LOGE("error opening %s: %s\n", path_src, strerror(errno)); return -1; } if (mkdir(path_dist, 0666) != 0) { if (errno != EEXIST) { LOGE("Can't mkdir %s (%s)\n", path_dist, strerror(errno)); return -1; } } //ui_print("copy %s to %s \n", path_src, path_dist); while ((de = readdir(d)) != NULL) { int name_len = strlen(de->d_name); if (de->d_type == DT_DIR) { // skip "." and ".." entries if (name_len == 1 && de->d_name[0] == '.') continue; if (name_len == 2 && de->d_name[0] == '.' && de->d_name[1] == '.') continue; char *path_dist_sub = dump_full_path(path_dist, de->d_name); char *path_src_sub = dump_full_path(path_src, de->d_name); if (path_dist_sub && path_src_sub) { if ( copy_dir(path_dist_sub, path_src_sub) ) { ret = -1; } } if (path_dist_sub) free(path_dist_sub); if (path_src_sub) free(path_src_sub); } else if (de->d_type == DT_REG ) { char *file_dist = dump_full_path(path_dist, de->d_name); char *file_src = dump_full_path(path_src, de->d_name); if (file_dist && file_src) { //ui_print("copy %s to %s \n", file_src, file_dist); if (copy_file(file_dist, file_src) < 0) { ret = -1; LOGE("Can't copy %s to %s \n", file_src, file_dist); } } if (file_dist) free(file_dist); if (file_src) free(file_src); } } closedir(d); return ret; }
/* * copy_entry - copy the entry of a directory * * Copy the entry src to dst. * Depending on the type of entry, this function will forward the * request to copy_dir(), copy_symlink(), copy_hardlink(), * copy_special(), or copy_file(). * * The access and modification time will not be modified. * * The permissions will be set to new_uid/new_gid. * * If new_uid (resp. new_gid) is equal to -1, the user (resp. group) will * not be modified. * * Only the files owned (resp. group-owned) by old_uid (resp. * old_gid) will be modified, unless old_uid (resp. old_gid) is set * to -1. */ static int copy_entry (const char *src, const char *dst, bool reset_selinux, uid_t old_uid, uid_t new_uid, gid_t old_gid, gid_t new_gid) { int err = 0; struct stat sb; struct link_name *lp; struct timeval mt[2]; if (LSTAT (src, &sb) == -1) { /* If we cannot stat the file, do not care. */ } else { #ifdef HAVE_STRUCT_STAT_ST_ATIM mt[0].tv_sec = sb.st_atim.tv_sec; mt[0].tv_usec = sb.st_atim.tv_nsec / 1000; #else /* !HAVE_STRUCT_STAT_ST_ATIM */ mt[0].tv_sec = sb.st_atime; # ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC mt[0].tv_usec = sb.st_atimensec / 1000; # else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */ mt[0].tv_usec = 0; # endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */ #endif /* !HAVE_STRUCT_STAT_ST_ATIM */ #ifdef HAVE_STRUCT_STAT_ST_MTIM mt[1].tv_sec = sb.st_mtim.tv_sec; mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000; #else /* !HAVE_STRUCT_STAT_ST_MTIM */ mt[1].tv_sec = sb.st_mtime; # ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC mt[1].tv_usec = sb.st_mtimensec / 1000; # else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */ mt[1].tv_usec = 0; # endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */ #endif /* !HAVE_STRUCT_STAT_ST_MTIM */ if (S_ISDIR (sb.st_mode)) { err = copy_dir (src, dst, reset_selinux, &sb, mt, old_uid, new_uid, old_gid, new_gid); } #ifdef S_IFLNK /* * Copy any symbolic links */ else if (S_ISLNK (sb.st_mode)) { err = copy_symlink (src, dst, reset_selinux, &sb, mt, old_uid, new_uid, old_gid, new_gid); } #endif /* S_IFLNK */ /* * See if this is a previously copied link */ else if ((lp = check_link (src, &sb)) != NULL) { err = copy_hardlink (dst, reset_selinux, lp); } /* * Deal with FIFOs and special files. The user really * shouldn't have any of these, but it seems like it * would be nice to copy everything ... */ else if (!S_ISREG (sb.st_mode)) { err = copy_special (src, dst, reset_selinux, &sb, mt, old_uid, new_uid, old_gid, new_gid); } /* * Create the new file and copy the contents. The new * file will be owned by the provided UID and GID values. */ else { err = copy_file (src, dst, reset_selinux, &sb, mt, old_uid, new_uid, old_gid, new_gid); } } return err; }
/* srcdir is to be considered a "skeleton" directory, in the manner of * /etc/skel, and destdir is a user's newly created home directory that needs * to be populated with the files in srcdir. */ static int copy_dir(pool *p, const char *src_dir, const char *dst_dir, uid_t uid, gid_t gid) { DIR *dh = NULL; struct dirent *dent = NULL; dh = opendir(src_dir); if (dh == NULL) { pr_log_pri(PR_LOG_WARNING, "CreateHome: error copying '%s' skel files: %s", src_dir, strerror(errno)); return -1; } while ((dent = readdir(dh)) != NULL) { struct stat st; char *src_path, *dst_path; pr_signals_handle(); /* Skip "." and ".." */ if (strncmp(dent->d_name, ".", 2) == 0 || strncmp(dent->d_name, "..", 3) == 0) { continue; } src_path = pdircat(p, src_dir, dent->d_name, NULL); dst_path = pdircat(p, dst_dir, dent->d_name, NULL); if (pr_fsio_lstat(src_path, &st) < 0) { pr_log_debug(DEBUG3, "CreateHome: unable to stat '%s' (%s), skipping", src_path, strerror(errno)); continue; } /* Is this path to a directory? */ if (S_ISDIR(st.st_mode)) { create_dir(dst_path, uid, gid, st.st_mode); copy_dir(p, src_path, dst_path, uid, gid); continue; /* Is this path to a regular file? */ } else if (S_ISREG(st.st_mode)) { mode_t dst_mode = st.st_mode; /* Make sure to prevent S{U,G}ID permissions on target files. */ if (dst_mode & S_ISUID) dst_mode &= ~S_ISUID; if (dst_mode & S_ISGID) dst_mode &= ~S_ISGID; (void) pr_fs_copy_file(src_path, dst_path); /* Make sure the destination file has the proper ownership and mode. */ if (pr_fsio_chown(dst_path, uid, gid) < 0) { pr_log_pri(PR_LOG_WARNING, "CreateHome: error chown'ing '%s' " "to %u/%u: %s", dst_path, (unsigned int) uid, (unsigned int) gid, strerror(errno)); } if (pr_fsio_chmod(dst_path, dst_mode) < 0) { pr_log_pri(PR_LOG_WARNING, "CreateHome: error chmod'ing '%s' to " "%04o: %s", dst_path, (unsigned int) dst_mode, strerror(errno)); } continue; /* Is this path a symlink? */ } else if (S_ISLNK(st.st_mode)) { copy_symlink(p, src_dir, src_path, dst_dir, dst_path, uid, gid); continue; /* All other file types are skipped */ } else { pr_log_debug(DEBUG3, "CreateHome: skipping skel file '%s'", src_path); continue; } } closedir(dh); return 0; }
/* Check for a CreateHome directive, and act on it if present. If not, do * nothing. */ int create_home(pool *p, const char *home, const char *user, uid_t uid, gid_t gid) { int res; unsigned long flags = 0; config_rec *c; mode_t dir_mode, dst_mode; uid_t dir_uid, dst_uid; gid_t dir_gid, dst_gid, home_gid; c = find_config(main_server->conf, CONF_PARAM, "CreateHome", FALSE); if (c == NULL || (c && *((unsigned char *) c->argv[0]) == FALSE)) { return 0; } /* Create the configured path. */ dir_uid = *((uid_t *) c->argv[4]); dir_gid = *((gid_t *) c->argv[5]); dir_mode = *((mode_t *) c->argv[2]); home_gid = *((gid_t *) c->argv[6]); flags = *((unsigned long *) c->argv[7]); dst_uid = uid; dst_gid = (home_gid == (gid_t) -1) ? gid : home_gid; dst_mode = *((mode_t *) c->argv[1]); if (!(flags & PR_MKHOME_FL_USE_USER_PRIVS)) { PRIVS_ROOT } pr_event_generate("core.creating-home", user); res = create_path(p, home, user, dir_uid, dir_gid, dir_mode, dst_uid, dst_gid, dst_mode); if (res < 0 && errno != EEXIST) { int xerrno = errno; PRIVS_RELINQUISH errno = xerrno; return -1; } if (res == 0 && c->argv[3]) { char *skel_dir = c->argv[3]; /* Populate the home directory with files from the configured * skeleton (a la /etc/skel) directory. */ pr_trace_msg(trace_channel, 9, "copying skel files from '%s' into '%s'", skel_dir, home); pr_log_debug(DEBUG4, "CreateHome: copying skel files from '%s' into '%s'", skel_dir, home); pr_event_generate("core.copying-skel", user); if (copy_dir(p, skel_dir, home, uid, gid) < 0) { pr_log_debug(DEBUG4, "CreateHome: error copying skel files"); } else { pr_event_generate("core.copied-skel", user); } } if (res == 0) { pr_event_generate("core.created-home", user); } PRIVS_RELINQUISH return 0; }
copy_dir () /* source und dest sind global; bei Fehler: return (1) */ { int source_len, dest_len, fd_source, fd_dest, error; char dta[44]; long old_dta, fail, size, count; error=0; source_len=strlen(source); dest_len=strlen(dest); old_dta=Fgetdta(); Fsetdta(dta); strcat(source,"\\*.*"); fail=Fsfirst(source,16); source[source_len]=0; while (!fail) { strcat(source,"\\"); strcat(source,dta+30); strcat(dest,"\\"); strcat(dest,dta+30); if (dta[21]==16) /* Directory */ { if (strcmp(dta+30,".")&&strcmp(dta+30,"..")) if (Dcreate(dest)) { printf("Ordner %s l„žt sich nicht anlegen.\n",dest); error=1; } else error|=copy_dir(source,dest); } else /* File */ { printf("%s nach %s\n",source,dest); if ((fd_source=Fopen(source,0))<0) { printf("Datei %s l„žt sich nicht ”ffnen.\n",source); error=1; } else if ((fd_dest=Fcreate(dest,dta[21]&~1))<0) { printf("Datei %s l„žt sich nicht einrichten.\n",dest); error=1; } else { size=*(long*)(dta+26); while (size) { count=(size<buf_size)?size:buf_size; size-=count; if (Fread(fd_source,count,buffer)!=count) { printf("Fehler beim Lesen von %s .\n",source); error=1; break; } if (Fwrite(fd_dest,count,buffer)!=count) { printf("Fehler beim Schreiben von %s .\n",dest); error=1; break; } } Fclose(fd_source); Fclose(fd_dest); fd_dest=Fopen(dest,1); Fdatime(fd_dest,dta+22,1); Fclose(fd_dest); } } source[source_len]=0; dest[dest_len]=0; fail=Fsnext(); } if (fail!=-49l) { printf("Ordner %s nicht gefunden.\n",source); error=1; } Fsetdta(old_dta); return (error); }
int cp_cmd(int argc, char **argv, FF_ENVIRONMENT *pEnv) { #ifdef FF_UNICODE_SUPPORT const wchar_t *szpSource, *szpDestination, *szpWildCard; #else const char *szpSource, *szpDestination, *szpWildCard; #endif char szsrcPath[FF_MAX_PATH], szdestPath[FF_MAX_PATH]; FF_DIRENT findData; FFT_GETOPT_CONTEXT optionContext; // CommandLine processing FF_T_BOOL bRecursive = FF_FALSE, bVerbose = FF_FALSE; // Option Flags. int option; memset(&optionContext, 0, sizeof(FFT_GETOPT_CONTEXT)); // Initialise the option context to zero. option = FFTerm_getopt(argc, (const char **) argv, "rRvx", &optionContext); // Get the command line option charachters. while(option != EOF) { // Process Commandline options switch(option) { case 'r': case 'R': bRecursive = FF_TRUE; // Set recursive flag if -r or -R appears on the commandline. break; case 'v': bVerbose = FF_TRUE; // Set verbose flag if -v appears on the commandline. break; case 'x': bExternal = FF_TRUE; break; default: break; } option = FFTerm_getopt(argc, (const char **) argv, "rRvx", &optionContext); // Get the next option. } szpSource = FFTerm_getarg(argc, (const char **) argv, 0, &optionContext); // The remaining options or non optional arguments. szpDestination = FFTerm_getarg(argc, (const char **) argv, 1, &optionContext); // getarg() retrieves them intelligently. if(!szpSource) { printf("%s: No source file argument.\n", argv[0]); // No source file provided. return 0; } if(!szpDestination) { printf("%s: No destination file argument.\n", argv[0]); // No destination provided. return 0; } ProcessPath(szsrcPath, szpSource, pEnv); // Process the paths into absolute paths. ProcessPath(szdestPath, szpDestination, pEnv); szpWildCard = GetWildcard(szpSource); // Get the last token of the source path. (This may include a wildCard). if(strchr(szpWildCard, '*')) { // If the 'WildCard' contains a * then its a wild card, otherwise its a file or directory. // WildCard Copying! //copy_wild(); return 0; } if(FF_FindFirst(pEnv->pIoman, &findData, szsrcPath)) { // Get the dirent for the file or directory, to detect if its a directory. // Not found! printf("%s: %s: no such file or directory.\n", argv[0], szpSource); return 0; } if(!strcmp(findData.FileName, szpWildCard) && (findData.Attrib & FF_FAT_ATTR_DIR)) { if(!bRecursive) { // Its a dir! printf("%s: omitting directory '%s'\n", argv[0], szsrcPath); return 0; } copy_dir(szsrcPath, szdestPath, bRecursive, bVerbose, pEnv);// Start the copying! return 0; } copy_file(szsrcPath, szdestPath, bVerbose, pEnv); // Final option, its simply a file to file copy return 0; }
static int copy_dir(const char *srcPath, const char *destPath, FF_T_BOOL bRecursive, FF_T_BOOL bVerbose, FF_ENVIRONMENT *pEnv) { FF_DIRENT findData; FF_ERROR RetVal; FF_T_INT8 szsrcFile[FF_MAX_PATH], szdestFile[FF_MAX_PATH]; //const char *szpWildCard; int i; strcpy(szsrcFile, srcPath); strcpy(szdestFile, destPath); // Ensure the paths both end in a '/' charachter i = strlen(szsrcFile); if(szsrcFile[i - 1] != '\\' || szsrcFile[i - 1] != '/') { strcat(szsrcFile, "\\"); } i = strlen(szdestFile); if(szdestFile[i - 1] != '\\' || szdestFile[i - 1] != '/') { strcat(szdestFile, "\\"); } RetVal = FF_FindFirst(pEnv->pIoman, &findData, szsrcFile); if(RetVal) { printf("cp: %s: No such file or directory.\n", srcPath); return 0; } while(!RetVal) { AppendFilename(szsrcFile, findData.FileName); AppendFilename(szdestFile, findData.FileName); if(!strcmp(szsrcFile, szdestFile)) { printf("cp: Source and Destination files are identical: illegal operation.\n"); return 0; } if((findData.Attrib & FF_FAT_ATTR_DIR)) { if(!(findData.FileName[0] == '.' && !findData.FileName[1]) && !(findData.FileName[0] == '.' && findData.FileName[1] == '.' && !findData.FileName[2])) { // Add the wild card onto the end! if(bRecursive) { strcat(szsrcFile, "\\"); //szpWildCard = getWildcard(srcPath); //strcat(szsrcFile, szpWildCard); strcat(szdestFile, "\\"); //szpWildCard = getWildcard(destPath); //strcat(szdestFile, szpWildCard); // Make the dir if it doesn't already exist! copy_dir(szsrcFile, szdestFile, bRecursive, bVerbose, pEnv); strcpy(szsrcFile, srcPath); // Reset the path. } } } else { copy_file(szsrcFile, szdestFile, bVerbose, pEnv); } RetVal = FF_FindNext(pEnv->pIoman, &findData); } return 0; }
static int copy_internal (const char *src_path, const char *dst_path, int new_dst, dev_t device, struct dir_list *ancestors, const struct cp_options *x, int command_line_arg, int *copy_into_self, int *rename_succeeded) { struct stat src_sb; struct stat dst_sb; mode_t src_mode; mode_t src_type; char *earlier_file = NULL; char *dst_backup = NULL; int backup_succeeded = 0; int delayed_fail; int copied_as_regular = 0; int ran_chown = 0; int preserve_metadata; if (x->move_mode && rename_succeeded) *rename_succeeded = 0; *copy_into_self = 0; if ((*(x->xstat)) (src_path, &src_sb)) { error (0, errno, _("cannot stat %s"), quote (src_path)); return 1; } src_type = src_sb.st_mode; src_mode = src_sb.st_mode; if (S_ISDIR (src_type) && !x->recursive) { error (0, 0, _("omitting directory %s"), quote (src_path)); return 1; } /* Detect the case in which the same source file appears more than once on the command line and no backup option has been selected. If so, simply warn and don't copy it the second time. This check is enabled only if x->src_info is non-NULL. */ if (command_line_arg) { if ( ! S_ISDIR (src_sb.st_mode) && x->backup_type == none && seen_file (x->src_info, src_path, &src_sb)) { error (0, 0, _("warning: source file %s specified more than once"), quote (src_path)); return 0; } record_file (x->src_info, src_path, &src_sb); } if (!new_dst) { if ((*(x->xstat)) (dst_path, &dst_sb)) { if (errno != ENOENT) { error (0, errno, _("cannot stat %s"), quote (dst_path)); return 1; } else { new_dst = 1; } } else { int return_now; int ok = same_file_ok (src_path, &src_sb, dst_path, &dst_sb, x, &return_now); if (return_now) return 0; if (! ok) { error (0, 0, _("%s and %s are the same file"), quote_n (0, src_path), quote_n (1, dst_path)); return 1; } if (!S_ISDIR (dst_sb.st_mode)) { if (S_ISDIR (src_type)) { error (0, 0, _("cannot overwrite non-directory %s with directory %s"), quote_n (0, dst_path), quote_n (1, src_path)); return 1; } /* Don't let the user destroy their data, even if they try hard: This mv command must fail (likewise for cp): rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c Otherwise, the contents of b/f would be lost. In the case of `cp', b/f would be lost if the user simulated a move using cp and rm. Note that it works fine if you use --backup=numbered. */ if (command_line_arg && x->backup_type != numbered && seen_file (x->dest_info, dst_path, &dst_sb)) { error (0, 0, _("will not overwrite just-created %s with %s"), quote_n (0, dst_path), quote_n (1, src_path)); return 1; } } if (!S_ISDIR (src_type)) { if (S_ISDIR (dst_sb.st_mode)) { error (0, 0, _("cannot overwrite directory %s with non-directory"), quote (dst_path)); return 1; } if (x->update && MTIME_CMP (src_sb, dst_sb) <= 0) { /* We're using --update and the source file is older than the destination file, so there is no need to copy or move. */ /* Pretend the rename succeeded, so the caller (mv) doesn't end up removing the source file. */ if (rename_succeeded) *rename_succeeded = 1; return 0; } } /* When there is an existing destination file, we may end up returning early, and hence not copying/moving the file. This may be due to an interactive `negative' reply to the prompt about the existing file. It may also be due to the use of the --reply=no option. */ if (!S_ISDIR (src_type)) { /* cp and mv treat -i and -f differently. */ if (x->move_mode) { if ((x->interactive == I_ALWAYS_NO && UNWRITABLE (dst_path, dst_sb.st_mode)) || ((x->interactive == I_ASK_USER || (x->interactive == I_UNSPECIFIED && x->stdin_tty && UNWRITABLE (dst_path, dst_sb.st_mode))) && (overwrite_prompt (dst_path, &dst_sb), 1) && ! yesno ())) { /* Pretend the rename succeeded, so the caller (mv) doesn't end up removing the source file. */ if (rename_succeeded) *rename_succeeded = 1; return 0; } } else { if (x->interactive == I_ALWAYS_NO || (x->interactive == I_ASK_USER && (overwrite_prompt (dst_path, &dst_sb), 1) && ! yesno ())) { return 0; } } } if (x->move_mode) { /* In move_mode, DEST may not be an existing directory. */ if (S_ISDIR (dst_sb.st_mode)) { error (0, 0, _("cannot overwrite directory %s"), quote (dst_path)); return 1; } /* Don't allow user to move a directory onto a non-directory. */ if (S_ISDIR (src_sb.st_mode) && !S_ISDIR (dst_sb.st_mode)) { error (0, 0, _("cannot move directory onto non-directory: %s -> %s"), quote_n (0, src_path), quote_n (0, dst_path)); return 1; } } if (x->backup_type != none && !S_ISDIR (dst_sb.st_mode)) { char *tmp_backup = find_backup_file_name (dst_path, x->backup_type); if (tmp_backup == NULL) xalloc_die (); /* Detect (and fail) when creating the backup file would destroy the source file. Before, running the commands cd /tmp; rm -f a a~; : > a; echo A > a~; cp --b=simple a~ a would leave two zero-length files: a and a~. */ /* FIXME: but simply change e.g., the final a~ to `./a~' and the source will still be destroyed. */ if (STREQ (tmp_backup, src_path)) { const char *fmt; fmt = (x->move_mode ? _("backing up %s would destroy source; %s not moved") : _("backing up %s would destroy source; %s not copied")); error (0, 0, fmt, quote_n (0, dst_path), quote_n (1, src_path)); free (tmp_backup); return 1; } dst_backup = (char *) alloca (strlen (tmp_backup) + 1); strcpy (dst_backup, tmp_backup); free (tmp_backup); if (rename (dst_path, dst_backup)) { if (errno != ENOENT) { error (0, errno, _("cannot backup %s"), quote (dst_path)); return 1; } else { dst_backup = NULL; } } else { backup_succeeded = 1; } new_dst = 1; } else if (! S_ISDIR (dst_sb.st_mode) && (x->unlink_dest_before_opening || (x->xstat == lstat && ! S_ISREG (src_sb.st_mode)))) { if (unlink (dst_path) && errno != ENOENT) { error (0, errno, _("cannot remove %s"), quote (dst_path)); return 1; } new_dst = 1; } } } /* If the source is a directory, we don't always create the destination directory. So --verbose should not announce anything until we're sure we'll create a directory. */ if (x->verbose && !S_ISDIR (src_type)) { printf ("%s -> %s", quote_n (0, src_path), quote_n (1, dst_path)); if (backup_succeeded) printf (_(" (backup: %s)"), quote (dst_backup)); putchar ('\n'); } /* Associate the destination path with the source device and inode so that if we encounter a matching dev/ino pair in the source tree we can arrange to create a hard link between the corresponding names in the destination tree. Sometimes, when preserving links, we have to record dev/ino even though st_nlink == 1: - when using -H and processing a command line argument; that command line argument could be a symlink pointing to another command line argument. With `cp -H --preserve=link', we hard-link those two destination files. - likewise for -L except that it applies to all files, not just command line arguments. Also record directory dev/ino when using --recursive. We'll use that info to detect this problem: cp -R dir dir. FIXME-maybe: ideally, directory info would be recorded in a separate hash table, since such entries are useful only while a single command line hierarchy is being copied -- so that separate table could be cleared between command line args. Using the same hash table to preserve hard links means that it may not be cleared. */ if ((x->preserve_links && (1 < src_sb.st_nlink || (command_line_arg && x->dereference == DEREF_COMMAND_LINE_ARGUMENTS) || x->dereference == DEREF_ALWAYS)) || (x->recursive && S_ISDIR (src_type))) { earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev); } /* Did we copy this inode somewhere else (in this command line argument) and therefore this is a second hard link to the inode? */ if (earlier_file) { /* Avoid damaging the destination filesystem by refusing to preserve hard-linked directories (which are found at least in Netapp snapshot directories). */ if (S_ISDIR (src_type)) { /* If src_path and earlier_file refer to the same directory entry, then warn about copying a directory into itself. */ if (same_name (src_path, earlier_file)) { error (0, 0, _("cannot copy a directory, %s, into itself, %s"), quote_n (0, top_level_src_path), quote_n (1, top_level_dst_path)); *copy_into_self = 1; } else { error (0, 0, _("will not create hard link %s to directory %s"), quote_n (0, dst_path), quote_n (1, earlier_file)); } goto un_backup; } { int link_failed; link_failed = link (earlier_file, dst_path); /* If the link failed because of an existing destination, remove that file and then call link again. */ if (link_failed && errno == EEXIST) { if (unlink (dst_path)) { error (0, errno, _("cannot remove %s"), quote (dst_path)); goto un_backup; } link_failed = link (earlier_file, dst_path); } if (link_failed) { error (0, errno, _("cannot create hard link %s to %s"), quote_n (0, dst_path), quote_n (1, earlier_file)); goto un_backup; } return 0; } } if (x->move_mode) { if (rename (src_path, dst_path) == 0) { if (x->verbose && S_ISDIR (src_type)) printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path)); if (rename_succeeded) *rename_succeeded = 1; if (command_line_arg) { /* Record destination dev/ino/filename, so that if we are asked to overwrite that file again, we can detect it and fail. */ /* It's fine to use the _source_ stat buffer (src_sb) to get the _destination_ dev/ino, since the rename above can't have changed those, and `mv' always uses lstat. We could limit it further by operating only on non-directories. */ record_file (x->dest_info, dst_path, &src_sb); } return 0; } /* FIXME: someday, consider what to do when moving a directory into itself but when source and destination are on different devices. */ /* This happens when attempting to rename a directory to a subdirectory of itself. */ if (errno == EINVAL /* When src_path is on an NFS file system, some types of clients, e.g., SunOS4.1.4 and IRIX-5.3, set errno to EIO instead. Testing for this here risks misinterpreting a real I/O error as an attempt to move a directory into itself, so FIXME: consider not doing this. */ || errno == EIO /* And with SunOS-4.1.4 client and OpenBSD-2.3 server, we get ENOTEMPTY. */ || errno == ENOTEMPTY) { /* FIXME: this is a little fragile in that it relies on rename(2) failing with a specific errno value. Expect problems on non-POSIX systems. */ error (0, 0, _("cannot move %s to a subdirectory of itself, %s"), quote_n (0, top_level_src_path), quote_n (1, top_level_dst_path)); /* Note that there is no need to call forget_created here, (compare with the other calls in this file) since the destination directory didn't exist before. */ *copy_into_self = 1; /* FIXME-cleanup: Don't return zero here; adjust mv.c accordingly. The only caller that uses this code (mv.c) ends up setting its exit status to nonzero when copy_into_self is nonzero. */ return 0; } /* WARNING: there probably exist systems for which an inter-device rename fails with a value of errno not handled here. If/as those are reported, add them to the condition below. If this happens to you, please do the following and send the output to the bug-reporting address (e.g., in the output of cp --help): touch k; perl -e 'rename "k","/tmp/k" or print "$!(",$!+0,")\n"' where your current directory is on one partion and /tmp is the other. Also, please try to find the E* errno macro name corresponding to the diagnostic and parenthesized integer, and include that in your e-mail. One way to do that is to run a command like this find /usr/include/. -type f \ | xargs grep 'define.*\<E[A-Z]*\>.*\<18\>' /dev/null where you'd replace `18' with the integer in parentheses that was output from the perl one-liner above. If necessary, of course, change `/tmp' to some other directory. */ if (errno != EXDEV) { /* There are many ways this can happen due to a race condition. When something happens between the initial xstat and the subsequent rename, we can get many different types of errors. For example, if the destination is initially a non-directory or non-existent, but it is created as a directory, the rename fails. If two `mv' commands try to rename the same file at about the same time, one will succeed and the other will fail. If the permissions on the directory containing the source or destination file are made too restrictive, the rename will fail. Etc. */ error (0, errno, _("cannot move %s to %s"), quote_n (0, src_path), quote_n (1, dst_path)); forget_created (src_sb.st_ino, src_sb.st_dev); return 1; } /* The rename attempt has failed. Remove any existing destination file so that a cross-device `mv' acts as if it were really using the rename syscall. */ if (unlink (dst_path) && errno != ENOENT) { error (0, errno, _("inter-device move failed: %s to %s; unable to remove target"), quote_n (0, src_path), quote_n (1, dst_path)); forget_created (src_sb.st_ino, src_sb.st_dev); return 1; } new_dst = 1; } delayed_fail = 0; /* In certain modes (cp's --symbolic-link), and for certain file types (symlinks and hard links) it doesn't make sense to preserve metadata, or it's possible to preserve only some of it. In such cases, set this variable to zero. */ preserve_metadata = 1; if (S_ISDIR (src_type)) { struct dir_list *dir; /* If this directory has been copied before during the recursion, there is a symbolic link to an ancestor directory of the symbolic link. It is impossible to continue to copy this, unless we've got an infinite disk. */ if (is_ancestor (&src_sb, ancestors)) { error (0, 0, _("cannot copy cyclic symbolic link %s"), quote (src_path)); goto un_backup; } /* Insert the current directory in the list of parents. */ dir = (struct dir_list *) alloca (sizeof (struct dir_list)); dir->parent = ancestors; dir->ino = src_sb.st_ino; dir->dev = src_sb.st_dev; if (new_dst || !S_ISDIR (dst_sb.st_mode)) { /* Create the new directory writable and searchable, so we can create new entries in it. */ if (mkdir (dst_path, (src_mode & x->umask_kill) | S_IRWXU)) { error (0, errno, _("cannot create directory %s"), quote (dst_path)); goto un_backup; } /* Insert the created directory's inode and device numbers into the search structure, so that we can avoid copying it again. */ if (remember_created (dst_path)) goto un_backup; if (x->verbose) printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path)); } /* Are we crossing a file system boundary? */ if (x->one_file_system && device != 0 && device != src_sb.st_dev) return 0; /* Copy the contents of the directory. */ if (copy_dir (src_path, dst_path, new_dst, &src_sb, dir, x, copy_into_self)) { /* Don't just return here -- otherwise, the failure to read a single file in a source directory would cause the containing destination directory not to have owner/perms set properly. */ delayed_fail = 1; } } #ifdef S_ISLNK else if (x->symbolic_link) { preserve_metadata = 0; if (*src_path != '/') { /* Check that DST_PATH denotes a file in the current directory. */ struct stat dot_sb; struct stat dst_parent_sb; char *dst_parent; int in_current_dir; dst_parent = dir_name (dst_path); in_current_dir = (STREQ (".", dst_parent) /* If either stat call fails, it's ok not to report the failure and say dst_path is in the current directory. Other things will fail later. */ || stat (".", &dot_sb) || stat (dst_parent, &dst_parent_sb) || SAME_INODE (dot_sb, dst_parent_sb)); free (dst_parent); if (! in_current_dir) { error (0, 0, _("%s: can make relative symbolic links only in current directory"), quote (dst_path)); goto un_backup; } } if (symlink (src_path, dst_path)) { error (0, errno, _("cannot create symbolic link %s to %s"), quote_n (0, dst_path), quote_n (1, src_path)); goto un_backup; } } #endif else if (x->hard_link) { preserve_metadata = 0; if (link (src_path, dst_path)) { error (0, errno, _("cannot create link %s"), quote (dst_path)); goto un_backup; } } else if (S_ISREG (src_type) || (x->copy_as_regular && !S_ISDIR (src_type) #ifdef S_ISLNK && !S_ISLNK (src_type) #endif )) { copied_as_regular = 1; /* POSIX says the permission bits of the source file must be used as the 3rd argument in the open call, but that's not consistent with historical practice. */ if (copy_reg (src_path, dst_path, x, get_dest_mode (x, src_mode), &new_dst, &src_sb)) goto un_backup; } else #ifdef S_ISFIFO if (S_ISFIFO (src_type)) { if (mkfifo (dst_path, get_dest_mode (x, src_mode))) { error (0, errno, _("cannot create fifo %s"), quote (dst_path)); goto un_backup; } } else #endif if (S_ISBLK (src_type) || S_ISCHR (src_type) #ifdef S_ISSOCK || S_ISSOCK (src_type) #endif ) { if (mknod (dst_path, get_dest_mode (x, src_mode), src_sb.st_rdev)) { error (0, errno, _("cannot create special file %s"), quote (dst_path)); goto un_backup; } } else #ifdef S_ISLNK if (S_ISLNK (src_type)) { char *src_link_val = xreadlink (src_path); if (src_link_val == NULL) { error (0, errno, _("cannot read symbolic link %s"), quote (src_path)); goto un_backup; } if (!symlink (src_link_val, dst_path)) free (src_link_val); else { int saved_errno = errno; int same_link = 0; if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode)) { /* See if the destination is already the desired symlink. */ size_t src_link_len = strlen (src_link_val); char *dest_link_val = (char *) alloca (src_link_len + 1); int dest_link_len = readlink (dst_path, dest_link_val, src_link_len + 1); if ((size_t) dest_link_len == src_link_len && strncmp (dest_link_val, src_link_val, src_link_len) == 0) same_link = 1; } free (src_link_val); if (! same_link) { error (0, saved_errno, _("cannot create symbolic link %s"), quote (dst_path)); goto un_backup; } } /* There's no need to preserve timestamps or permissions. */ preserve_metadata = 0; if (x->preserve_ownership) { /* Preserve the owner and group of the just-`copied' symbolic link, if possible. */ # if HAVE_LCHOWN if (DO_CHOWN (lchown, dst_path, src_sb.st_uid, src_sb.st_gid)) { error (0, errno, _("failed to preserve ownership for %s"), dst_path); goto un_backup; } # else /* Can't preserve ownership of symlinks. FIXME: maybe give a warning or even error for symlinks in directories with the sticky bit set -- there, not preserving owner/group is a potential security problem. */ # endif } } else #endif { error (0, 0, _("%s has unknown file type"), quote (src_path)); goto un_backup; } if (command_line_arg) record_file (x->dest_info, dst_path, NULL); if ( ! preserve_metadata) return 0; /* POSIX says that `cp -p' must restore the following: - permission bits - setuid, setgid bits - owner and group If it fails to restore any of those, we may give a warning but the destination must not be removed. FIXME: implement the above. */ /* Adjust the times (and if possible, ownership) for the copy. chown turns off set[ug]id bits for non-root, so do the chmod last. */ if (x->preserve_timestamps) { struct utimbuf utb; /* There's currently no interface to set file timestamps with better than 1-second resolution, so discard any fractional part of the source timestamp. */ utb.actime = src_sb.st_atime; utb.modtime = src_sb.st_mtime; if (utime (dst_path, &utb)) { error (0, errno, _("preserving times for %s"), quote (dst_path)); if (x->require_preserve) return 1; } } /* Avoid calling chown if we know it's not necessary. */ if (x->preserve_ownership && (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb))) { ran_chown = 1; if (DO_CHOWN (chown, dst_path, src_sb.st_uid, src_sb.st_gid)) { error (0, errno, _("failed to preserve ownership for %s"), quote (dst_path)); if (x->require_preserve) return 1; } } #if HAVE_STRUCT_STAT_ST_AUTHOR /* Preserve the st_author field. */ { file_t file = file_name_lookup (dst_path, 0, 0); if (file_chauthor (file, src_sb.st_author)) error (0, errno, _("failed to preserve authorship for %s"), quote (dst_path)); mach_port_deallocate (mach_task_self (), file); } #endif /* Permissions of newly-created regular files were set upon `open' in copy_reg. But don't return early if there were any special bits and we had to run chown, because the chown must have reset those bits. */ if ((new_dst && copied_as_regular) && !(ran_chown && (src_mode & ~S_IRWXUGO))) return delayed_fail; if ((x->preserve_mode || new_dst) && (x->copy_as_regular || S_ISREG (src_type) || S_ISDIR (src_type))) { if (chmod (dst_path, get_dest_mode (x, src_mode))) { error (0, errno, _("setting permissions for %s"), quote (dst_path)); if (x->set_mode || x->require_preserve) return 1; } } return delayed_fail; un_backup: /* We have failed to create the destination file. If we've just added a dev/ino entry via the remember_copied call above (i.e., unless we've just failed to create a hard link), remove the entry associating the source dev/ino with the destination file name, so we don't try to `preserve' a link to a file we didn't create. */ if (earlier_file == NULL) forget_created (src_sb.st_ino, src_sb.st_dev); if (dst_backup) { if (rename (dst_backup, dst_path)) error (0, errno, _("cannot un-backup %s"), quote (dst_path)); else { if (x->verbose) printf (_("%s -> %s (unbackup)\n"), quote_n (0, dst_backup), quote_n (1, dst_path)); } } return 1; }
static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, file_data_t*dir_list, const unsigned long int inode, const unsigned int depth) { /* Return value * -1: quit * 1: back * other: new inode * */ int quit=0; WINDOW *window=(WINDOW*)dir_data->display; do { int offset=0; int pos_num=0; file_data_t *pos=dir_list; int old_LINES=LINES; unsigned int status=FILE_STATUS_MARKED; aff_copy(window); wmove(window,3,0); aff_part(window, AFF_PART_ORDER|AFF_PART_STATUS, disk, partition); wmove(window,4,0); wprintw(window,"Directory %s\n",dir_data->current_directory); do { int i; int car; const file_data_t *current_file; for(i=0,current_file=dir_list;(current_file!=NULL) && (i<offset);current_file=current_file->next,i++); for(i=offset;(current_file!=NULL) &&((i-offset)<INTER_DIR);i++,current_file=current_file->next) { char str[11]; char datestr[80]; wmove(window, 6+i-offset, 0); wclrtoeol(window); /* before addstr for BSD compatibility */ if(current_file==pos) { wattrset(window, A_REVERSE); waddstr(window, ">"); } else waddstr(window, " "); if((current_file->status&FILE_STATUS_DELETED)!=0 && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(1)); else if((current_file->status&FILE_STATUS_MARKED)!=0 && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(2)); if(current_file->td_mtime!=0) { struct tm *tm_p; tm_p = localtime(¤t_file->td_mtime); snprintf(datestr, sizeof(datestr),"%2d-%s-%4d %02d:%02d", tm_p->tm_mday, monstr[tm_p->tm_mon], 1900 + tm_p->tm_year, tm_p->tm_hour, tm_p->tm_min); /* May have to use %d instead of %e */ } else { strncpy(datestr, " ",sizeof(datestr)); } mode_string(current_file->st_mode, str); wprintw(window, "%s %5u %5u ", str, (unsigned int)current_file->st_uid, (unsigned int)current_file->st_gid); wprintw(window, "%9llu", (long long unsigned int)current_file->st_size); /* screen may overlap due to long filename */ wprintw(window, " %s %s", datestr, current_file->name); if(((current_file->status&FILE_STATUS_DELETED)!=0 || (current_file->status&FILE_STATUS_MARKED)!=0) && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if(current_file==pos) wattroff(window, A_REVERSE); } wmove(window, 6-1, 51); wclrtoeol(window); if(offset>0) wprintw(window, "Previous"); /* Clear the last line, useful if overlapping */ wmove(window,6+i-offset,0); wclrtoeol(window); wmove(window, 6+INTER_DIR, 51); wclrtoeol(window); if(current_file!=NULL) wprintw(window, "Next"); if(dir_list==NULL) { wmove(window,6,0); wprintw(window,"No file found, filesystem may be damaged."); } /* Redraw the bottom of the screen everytime because very long filenames may have corrupt it*/ mvwaddstr(window,LINES-3,0,"Use "); if(depth>0) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window, "Left"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," arrow to go back, "); } if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"Right"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to change directory"); if((dir_data->capabilities&CAPA_LIST_DELETED)!=0) { waddstr(window,", "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"h"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if((dir_data->param&FLAG_LIST_DELETED)==0) waddstr(window," to unhide deleted files"); else waddstr(window," to hide deleted files"); } wmove(window,LINES-2,4); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"q"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to quit"); if(dir_data->copy_file!=NULL) { waddstr(window,", "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,":"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to select the current file, "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"a"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if((status&FILE_STATUS_MARKED)==FILE_STATUS_MARKED) waddstr(window," to select all files "); else waddstr(window," to deselect all files"); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); mvwaddstr(window,LINES-1,4,"C"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to copy the selected files, "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"c"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to copy the current file"); } wrefresh(window); /* Using gnome terminal under FC3, TERM=xterm, the screen is not always correct */ wredrawln(window,0,getmaxy(window)); /* redrawwin def is boggus in pdcur24 */ car=wgetch(window); wmove(window,5,0); wclrtoeol(window); switch(car) { case key_ESC: case 'q': case 'M': quit=1; break; case '-': case KEY_LEFT: case '4': if(depth>0) return 1; break; case 'h': if((dir_data->capabilities&CAPA_LIST_DELETED)!=0) dir_data->param^=FLAG_LIST_DELETED; return inode; } if(dir_list!=NULL) { switch(car) { case KEY_UP: case '8': if(pos->prev!=NULL) { pos=pos->prev; pos_num--; } break; case KEY_DOWN: case '2': if(pos->next!=NULL) { pos=pos->next; pos_num++; } break; case ':': if(!(pos->name[0]=='.' && pos->name[1]=='\0') && !(pos->name[0]=='.' && pos->name[1]=='.' && pos->name[2]=='\0')) pos->status^=FILE_STATUS_MARKED; if(pos->next!=NULL) { pos=pos->next; pos_num++; } break; case 'a': { file_data_t *tmp; for(tmp=dir_list; tmp!=NULL; tmp=tmp->next) { if((tmp->name[0]=='.' && tmp->name[1]=='\0') || (tmp->name[0]=='.' && tmp->name[1]=='.' && tmp->name[2]=='\0')) { tmp->status&=~FILE_STATUS_MARKED; } else { if((tmp->status & FILE_STATUS_MARKED)!=status) tmp->status^=FILE_STATUS_MARKED; } } status^=FILE_STATUS_MARKED; } break; case 'p': case 'P': case '+': case ' ': case KEY_RIGHT: case '\r': case '\n': case '6': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif if((pos!=NULL) && (LINUX_S_ISDIR(pos->st_mode)!=0)) { unsigned long int new_inode=pos->st_ino; if((new_inode!=inode) &&(strcmp(pos->name,".")!=0)) { if(strcmp(pos->name,"..")==0) return 1; if(strlen(dir_data->current_directory)+1+strlen(pos->name)+1<=sizeof(dir_data->current_directory)) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); strcat(dir_data->current_directory,pos->name); return (long int)new_inode; } } } break; case KEY_PPAGE: for(i=0;(i<INTER_DIR-1)&&(pos->prev!=NULL);i++) { pos=pos->prev; pos_num--; } break; case KEY_NPAGE: for(i=0;(i<INTER_DIR-1)&&(pos->next!=NULL);i++) { pos=pos->next; pos_num++; } break; case 'c': if(dir_data->copy_file!=NULL) { const unsigned int current_directory_namelength=strlen(dir_data->current_directory); if(strcmp(pos->name,"..")!=0 && current_directory_namelength+1+strlen(pos->name)<sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); if(strcmp(pos->name,".")!=0) strcat(dir_data->current_directory,pos->name); if(dir_data->local_dir==NULL) { if(LINUX_S_ISDIR(pos->st_mode)!=0) dir_data->local_dir=ask_location("Please select a destination where %s and any files below will be copied.", dir_data->current_directory, NULL); else dir_data->local_dir=ask_location("Please select a destination where %s will be copied.", dir_data->current_directory, NULL); } if(dir_data->local_dir!=NULL) { int res=-1; wmove(window,5,0); wclrtoeol(window); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copying, please wait..."); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); wrefresh(window); if(LINUX_S_ISDIR(pos->st_mode)!=0) { res=copy_dir(disk, partition, dir_data, pos); } else if(LINUX_S_ISREG(pos->st_mode)!=0) { res=dir_data->copy_file(disk, partition, dir_data, pos); } wmove(window,5,0); wclrtoeol(window); if(res < -1) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copy failed!"); } else { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2)); if(res < 0) wprintw(window,"Copy done! (Failed to copy some files)"); else wprintw(window,"Copy done!"); } if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); } dir_data->current_directory[current_directory_namelength]='\0'; } } break; case 'C': if(dir_data->copy_file!=NULL) { if(dir_data->local_dir==NULL) { dir_data->local_dir=ask_location("Please select a destination where the marked files will be copied.", NULL, NULL); } if(dir_data->local_dir!=NULL) { file_data_t *tmp; int copy_bad=0; int copy_ok=0; const unsigned int current_directory_namelength=strlen(dir_data->current_directory); wmove(window,5,0); wclrtoeol(window); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copying, please wait..."); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); wrefresh(window); for(tmp=dir_list; tmp!=NULL; tmp=tmp->next) { if((tmp->status&FILE_STATUS_MARKED)!=0 && current_directory_namelength + 1 + strlen(tmp->name) < sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); if(strcmp(tmp->name,".")!=0) strcat(dir_data->current_directory,tmp->name); if(LINUX_S_ISDIR(tmp->st_mode)!=0) { const int res=copy_dir(disk, partition, dir_data, tmp); if(res >=-1) { tmp->status&=~FILE_STATUS_MARKED; copy_ok=1; } else if(res < 0) copy_bad=1; } else if(LINUX_S_ISREG(tmp->st_mode)!=0) { if(dir_data->copy_file(disk, partition, dir_data, tmp) == 0) { tmp->status&=~FILE_STATUS_MARKED; copy_ok=1; } else copy_bad=1; } } dir_data->current_directory[current_directory_namelength]='\0'; } wmove(window,5,0); wclrtoeol(window); if(copy_bad > 0 && copy_ok==0) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copy failed!"); } else { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2)); if(copy_bad > 0) wprintw(window,"Copy done! (Failed to copy some files)"); else if(copy_ok == 0) wprintw(window,"No file selected"); else wprintw(window,"Copy done!"); } if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); } } break; case 'f': { const char *needle=ask_string_ncurses("Filename to find ? "); if(needle!=NULL && needle[0]!='\0') { file_data_t *pos_org=pos; const int pos_num_org=pos_num; while(strcmp(pos->name, needle)!=0 && pos->next!=NULL) { pos=pos->next; pos_num++; } if(strcmp(pos->name, needle)!=0) { pos=pos_org; pos_num=pos_num_org; } } } break; } if(pos_num<offset) offset=pos_num; if(pos_num>=offset+INTER_DIR) offset=pos_num-INTER_DIR+1; } } while(quit==0 && old_LINES==LINES); } while(quit==0); return -1; }
int makeflow_archive_copy_preserved_files(struct archive_instance *a, struct batch_task *t, char *task_path ) { struct batch_file *f; struct stat buf; struct list_cursor *cur = list_cursor_create(t->output_files); // Iterate through output files for(list_seek(cur, 0); list_get(cur, (void**)&f); list_next(cur)) { char *file_name = xxstrdup(f->outer_name); debug(D_MAKEFLOW_HOOK,"Trying to copy file to %s",file_name); char *file_to_check = xxstrdup(file_name); //Check to see if the directory was copied as an empty file/incorrectly stat(dirname(file_to_check),&buf); if(S_ISREG(buf.st_mode)){ debug(D_MAKEFLOW,"Removing empty file in the place of directory name %s",file_to_check); char *dirEmpty = string_format("rm -rf %s",file_to_check); system(dirEmpty); free(dirEmpty); } free(file_to_check); // Gets path of output file char *output_file_path = string_format("%s/output_files/%s",task_path,basename(file_name)); char *directory_name = xxstrdup(file_name); debug(D_MAKEFLOW_HOOK,"Creating directory %s",dirname(directory_name)); if(strcmp(directory_name,file_name) != 0){ //Create the upper level directory to copy the output files into if necessary if (!create_dir(directory_name, 0777) && errno != EEXIST){ debug(D_ERROR|D_MAKEFLOW_HOOK,"Failed to create directory %s",directory_name); free(directory_name); free(output_file_path); free(file_name); return 1; } } free(directory_name); // Copy output file or directory over to specified location if(path_is_dir(output_file_path) != 1){ int success = copy_file_to_file(output_file_path, file_name); free(output_file_path); free(file_name); if (!success) { list_cursor_destroy(cur); debug(D_ERROR|D_MAKEFLOW_HOOK,"Failed to copy output file %s to %s\n", output_file_path, file_name); return 1; } } else{ if(copy_dir(output_file_path, file_name) != 0){ list_cursor_destroy(cur); debug(D_ERROR|D_MAKEFLOW_HOOK,"Failed to copy output file %s to %s\n", output_file_path, file_name); free(output_file_path); free(file_name); return 1; } free(output_file_path); free(file_name); } } list_cursor_destroy(cur); return 0; }
static int copy_dir(pool *p, const char *src_dir, const char *dst_dir) { DIR *dh = NULL; struct dirent *dent = NULL; int res = 0; pool *iter_pool = NULL; dh = opendir(src_dir); if (dh == NULL) { pr_log_pri(PR_LOG_WARNING, MOD_COPY_VERSION ": error reading directory '%s': %s", src_dir, strerror(errno)); return -1; } while ((dent = readdir(dh)) != NULL) { struct stat st; char *src_path, *dst_path; pr_signals_handle(); /* Skip "." and ".." */ if (strncmp(dent->d_name, ".", 2) == 0 || strncmp(dent->d_name, "..", 3) == 0) { continue; } if (iter_pool != NULL) { destroy_pool(iter_pool); } iter_pool = pr_pool_create_sz(p, 128); src_path = pdircat(iter_pool, src_dir, dent->d_name, NULL); dst_path = pdircat(iter_pool, dst_dir, dent->d_name, NULL); if (pr_fsio_lstat(src_path, &st) < 0) { pr_log_debug(DEBUG3, MOD_COPY_VERSION ": unable to stat '%s' (%s), skipping", src_path, strerror(errno)); continue; } /* Is this path to a directory? */ if (S_ISDIR(st.st_mode)) { if (create_path(iter_pool, dst_path) < 0) { res = -1; break; } if (copy_dir(iter_pool, src_path, dst_path) < 0) { res = -1; break; } continue; /* Is this path to a regular file? */ } else if (S_ISREG(st.st_mode)) { cmd_rec *cmd; /* Dispatch fake COPY command, e.g. for mod_quotatab */ cmd = pr_cmd_alloc(iter_pool, 4, pstrdup(iter_pool, "SITE"), pstrdup(iter_pool, "COPY"), pstrdup(iter_pool, src_path), pstrdup(iter_pool, dst_path)); cmd->arg = pstrcat(iter_pool, "COPY ", src_path, " ", dst_path, NULL); cmd->cmd_class = CL_WRITE; pr_response_clear(&resp_list); pr_response_clear(&resp_err_list); if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) { int xerrno = errno; pr_log_debug(DEBUG3, MOD_COPY_VERSION ": COPY of '%s' to '%s' blocked by COPY handler: %s", src_path, dst_path, strerror(xerrno)); pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0); pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0); pr_response_clear(&resp_err_list); errno = xerrno; res = -1; break; } else { if (pr_fs_copy_file(src_path, dst_path) < 0) { pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0); pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0); pr_response_clear(&resp_err_list); res = -1; break; } else { char *abs_path; pr_cmd_dispatch_phase(cmd, POST_CMD, 0); pr_cmd_dispatch_phase(cmd, LOG_CMD, 0); pr_response_clear(&resp_list); /* Write a TransferLog entry as well. */ pr_fs_clear_cache2(dst_path); pr_fsio_stat(dst_path, &st); abs_path = dir_abs_path(p, dst_path, TRUE); if (session.sf_flags & SF_ANON) { xferlog_write(0, session.c->remote_name, st.st_size, abs_path, (session.sf_flags & SF_ASCII ? 'a' : 'b'), 'd', 'a', session.anon_user, 'c', "_"); } else { xferlog_write(0, session.c->remote_name, st.st_size, abs_path, (session.sf_flags & SF_ASCII ? 'a' : 'b'), 'd', 'r', session.user, 'c', "_"); } } } continue; /* Is this path a symlink? */ } else if (S_ISLNK(st.st_mode)) { if (copy_symlink(iter_pool, src_path, dst_path) < 0) { res = -1; break; } continue; /* All other file types are skipped */ } else { pr_log_debug(DEBUG3, MOD_COPY_VERSION ": skipping supported file '%s'", src_path); continue; } } if (iter_pool != NULL) { destroy_pool(iter_pool); } closedir(dh); return res; }
static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_data_t *dir) { static unsigned int dir_nbr=0; static unsigned long int inode_known[MAX_DIR_NBR]; file_data_t *dir_list; const unsigned int current_directory_namelength=strlen(dir_data->current_directory); file_data_t *current_file; char *dir_name; int copy_bad=0; int copy_ok=0; if(dir_data->get_dir==NULL || dir_data->copy_file==NULL) return -2; inode_known[dir_nbr++]=dir->st_ino; dir_name=mkdir_local(dir_data->local_dir, dir_data->current_directory); dir_list=dir_data->get_dir(disk, partition, dir_data, (const unsigned long int)dir->st_ino); for(current_file=dir_list;current_file!=NULL;current_file=current_file->next) { dir_data->current_directory[current_directory_namelength]='\0'; if(current_directory_namelength+1+strlen(current_file->name)<sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); strcat(dir_data->current_directory,current_file->name); if(LINUX_S_ISDIR(current_file->st_mode)!=0) { const unsigned long int new_inode=current_file->st_ino; unsigned int new_inode_ok=1; unsigned int i; if(new_inode<2) new_inode_ok=0; if(strcmp(current_file->name,"..")==0 || strcmp(current_file->name,".")==0) new_inode_ok=0; for(i=0;i<dir_nbr && new_inode_ok!=0;i++) if(new_inode==inode_known[i]) /* Avoid loop */ new_inode_ok=0; if(new_inode_ok>0) { int tmp; tmp=copy_dir(disk, partition, dir_data, current_file); if(tmp>=-1) copy_ok=1; if(tmp<0) copy_bad=1; } } else if(LINUX_S_ISREG(current_file->st_mode)!=0) { // log_trace("copy_file %s\n",dir_data->current_directory); int tmp; tmp=dir_data->copy_file(disk, partition, dir_data, current_file); if(tmp==0) copy_ok=1; else copy_bad=1; } } } dir_data->current_directory[current_directory_namelength]='\0'; delete_list_file(dir_list); set_date(dir_name, dir->td_atime, dir->td_mtime); free(dir_name); dir_nbr--; return (copy_bad>0?(copy_ok>0?-1:-2):0); }
/* * copy_dir: copy a directory * * If recurse is false, subdirectories are ignored. Anything that's not * a directory or a regular file is ignored. */ void copy_dir(char *fromdir, char *todir, bool recurse) { DIR *xldir; struct dirent *xlde; char fromfile[MAX_PG_PATH]; char tofile[MAX_PG_PATH]; if (mkdir(todir, S_IRWXU) != 0) ereport(ERROR, (errcode_file_access(), errmsg("could not create directory \"%s\": %m", todir))); xldir = alloc_dir(fromdir); if (xldir == NULL) ereport(ERROR, (errcode_file_access(), errmsg("could not open directory \"%s\": %m", fromdir))); while ((xlde = read_dir(xldir, fromdir)) != NULL) { struct stat fst; /* If we got a cancel signal during the copy of the directory, * quit */ CHECK_FOR_INTERRUPTS(); if (strcmp(xlde->d_name, ".") == 0 || strcmp(xlde->d_name, "..") == 0) continue; snprintf(fromfile, MAX_PG_PATH, "%s/%s", fromdir, xlde->d_name); snprintf(tofile, MAX_PG_PATH, "%s/%s", todir, xlde->d_name); if (lstat(fromfile, &fst) < 0) ereport(ERROR, (errcode_file_access(), errmsg("could not stat file \"%s\": %m", fromfile))); if (S_ISDIR(fst.st_mode)) { /* recurse to handle subdirectories */ if (recurse) copy_dir(fromfile, tofile, true); } else if (S_ISREG(fst.st_mode)) copy_file(fromfile, tofile); } free_dir(xldir); /* * Be paranoid here and fsync all files to ensure the copy is really * done. */ xldir = alloc_dir(todir); if (xldir == NULL) ereport(ERROR, (errcode_file_access(), errmsg("could not open directory \"%s\": %m", todir))); while ((xlde = read_dir(xldir, todir)) != NULL) { struct stat fst; if (strcmp(xlde->d_name, ".") == 0 || strcmp(xlde->d_name, "..") == 0) continue; snprintf(tofile, MAX_PG_PATH, "%s/%s", todir, xlde->d_name); /* * We don't need to sync subdirectories here since the recursive * copy_dir will do it before it returns */ if (lstat(tofile, &fst) < 0) ereport(ERROR, (errcode_file_access(), errmsg("could not stat file \"%s\": %m", tofile))); if (S_ISREG(fst.st_mode)) fsync_fname(tofile, false); } free_dir(xldir); /* * It's important to fsync the destination directory itself as * individual file fsyncs don't guarantee that the directory entry for * the file is synced. Recent versions of ext4 have made the window much * wider but it's been true for ext3 and other filesystems in the past. */ fsync_fname(todir, true); }
static int copy_paths(pool *p, const char *from, const char *to) { struct stat st; int res; xaset_t *set; set = get_dir_ctxt(p, (char *) to); res = pr_filter_allow_path(set, to); switch (res) { case 0: break; case PR_FILTER_ERR_FAILS_ALLOW_FILTER: pr_log_debug(DEBUG7, MOD_COPY_VERSION ": path '%s' denied by PathAllowFilter", to); errno = EPERM; return -1; case PR_FILTER_ERR_FAILS_DENY_FILTER: pr_log_debug(DEBUG7, MOD_COPY_VERSION ": path '%s' denied by PathDenyFilter", to); errno = EPERM; return -1; } /* Check whether from is a file, a directory, a symlink, or something * unsupported. */ res = pr_fsio_lstat(from, &st); if (res < 0) { int xerrno = errno; pr_log_debug(DEBUG7, MOD_COPY_VERSION ": error checking '%s': %s", from, strerror(xerrno)); errno = xerrno; return -1; } if (S_ISREG(st.st_mode)) { char *abs_path; pr_fs_clear_cache2(to); res = pr_fsio_stat(to, &st); if (res == 0) { unsigned char *allow_overwrite; allow_overwrite = get_param_ptr(CURRENT_CONF, "AllowOverwrite", FALSE); if (allow_overwrite == NULL || *allow_overwrite == FALSE) { pr_log_debug(DEBUG6, MOD_COPY_VERSION ": AllowOverwrite permission denied for '%s'", to); errno = EACCES; return -1; } } res = pr_fs_copy_file(from, to); if (res < 0) { int xerrno = errno; pr_log_debug(DEBUG7, MOD_COPY_VERSION ": error copying file '%s' to '%s': %s", from, to, strerror(xerrno)); errno = xerrno; return -1; } pr_fs_clear_cache2(to); if (pr_fsio_stat(to, &st) < 0) { pr_trace_msg(trace_channel, 3, "error stat'ing '%s': %s", to, strerror(errno)); } /* Write a TransferLog entry as well. */ abs_path = dir_abs_path(p, to, TRUE); if (session.sf_flags & SF_ANON) { xferlog_write(0, session.c->remote_name, st.st_size, abs_path, (session.sf_flags & SF_ASCII ? 'a' : 'b'), 'd', 'a', session.anon_user, 'c', "_"); } else { xferlog_write(0, session.c->remote_name, st.st_size, abs_path, (session.sf_flags & SF_ASCII ? 'a' : 'b'), 'd', 'r', session.user, 'c', "_"); } } else if (S_ISDIR(st.st_mode)) { res = create_path(p, to); if (res < 0) { int xerrno = errno; pr_log_debug(DEBUG7, MOD_COPY_VERSION ": error creating path '%s': %s", to, strerror(xerrno)); errno = xerrno; return -1; } res = copy_dir(p, from, to); if (res < 0) { int xerrno = errno; pr_log_debug(DEBUG7, MOD_COPY_VERSION ": error copying directory '%s' to '%s': %s", from, to, strerror(xerrno)); errno = xerrno; return -1; } } else if (S_ISLNK(st.st_mode)) { pr_fs_clear_cache2(to); res = pr_fsio_stat(to, &st); if (res == 0) { unsigned char *allow_overwrite; allow_overwrite = get_param_ptr(CURRENT_CONF, "AllowOverwrite", FALSE); if (allow_overwrite == NULL || *allow_overwrite == FALSE) { pr_log_debug(DEBUG6, MOD_COPY_VERSION ": AllowOverwrite permission denied for '%s'", to); errno = EACCES; return -1; } } res = copy_symlink(p, from, to); if (res < 0) { int xerrno = errno; pr_log_debug(DEBUG7, MOD_COPY_VERSION ": error copying symlink '%s' to '%s': %s", from, to, strerror(xerrno)); errno = xerrno; return -1; } } else { pr_log_debug(DEBUG7, MOD_COPY_VERSION ": unsupported file type for '%s'", from); errno = EINVAL; return -1; } return 0; }
/* Archive the specified file. * This includes several steps: * 1. Generate the id * 2. Copy file to id if non-existent * 3. Link back to creating task * @return 0 if successfully archived, 1 if failed at any point. */ static int makeflow_archive_file(struct archive_instance *a, struct batch_file *f, char *job_file_archive_path) { /* Generate the file archive id (content based) if does not exist. */ char * id; if(path_is_dir(f->inner_name) == 1){ f->hash = batch_file_generate_id_dir(f->inner_name); id = xxstrdup(f->hash); } else{ id = batch_file_generate_id(f); } struct stat buf; int rv = 0; char * file_archive_dir = string_format("%s/files/%.2s", a->dir, id); char * file_archive_path = string_format("%s/%s", file_archive_dir, id); char * job_file_archive_dir = NULL; /* Create the archive path with 2 character prefix. */ if (!create_dir(file_archive_dir, 0777) && errno != EEXIST){ debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create file archiving directory %s: %d %s\n", file_archive_dir, errno, strerror(errno)); rv = 1; goto FAIL; } /* Check if file is already archived */ if(stat(file_archive_path, &buf) >= 0) { debug(D_MAKEFLOW_HOOK, "file %s already archived at %s", f->outer_name, file_archive_path); /* File did not already exist, store in general file area */ } else { if(path_is_dir(f->outer_name) != 1){ if (!copy_file_to_file(f->outer_name, file_archive_path)){ debug(D_ERROR|D_MAKEFLOW_HOOK, "could not archive output file %s at %s: %d %s\n", f->outer_name, file_archive_path, errno, strerror(errno)); rv = 1; goto FAIL; } } else{ debug(D_MAKEFLOW,"COPYING %s to the archive",f->outer_name); if(copy_dir(f->outer_name,file_archive_path) != 0){ debug(D_ERROR|D_MAKEFLOW_HOOK, "could not archive output file %s at %s: %d %s\n", f->outer_name, file_archive_path, errno, strerror(errno)); rv = 1; goto FAIL; } } } /* Create the directory structure for job_file_archive. */ job_file_archive_dir = xxstrdup(job_file_archive_path); path_dirname(job_file_archive_path, job_file_archive_dir); if (!create_dir(job_file_archive_dir, 0777) && errno != EEXIST){ debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create job file directory %s: %d %s\n", file_archive_dir, errno, strerror(errno)); rv = 1; goto FAIL; } if(a->s3){ int result = 1; // Check to see if file already exists in the s3 bucket if(a->s3_check){ if(!in_s3_archive(a,id)){ result = makeflow_archive_s3_file(a,id,file_archive_path); } } else result = makeflow_archive_s3_file(a,id,file_archive_path); /* Copy file to the s3 bucket*/ if(!result){ debug(D_ERROR|D_MAKEFLOW_HOOK, "could not copy file %s to s3 bucket: %d %s\n", id, errno, strerror(errno)); rv = 1; goto FAIL; } } free(file_archive_path); file_archive_path = string_format("../../../../files/%.2s/%s", id, id); /* Create a symlink to task that used/created this file. */ int symlink_failure = symlink(file_archive_path, job_file_archive_path); if (symlink_failure && errno != EEXIST) { debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create symlink %s pointing to %s: %d %s\n", job_file_archive_path, file_archive_path, errno, strerror(errno)); rv = 1; goto FAIL; } FAIL: free(id); free(file_archive_dir); free(file_archive_path); free(job_file_archive_dir); return rv; }