void op_ldi(t_env *env, t_process *p, unsigned char arg[4][4], size_t *t) { size_t a1; size_t a2; size_t a3; size_t val; if (t[0] == 1) a1 = r_to_n(arg[0], 1); else a1 = r_to_n(arg[0], 2); if (t[1] == 1) a2 = r_to_n(arg[1], 1); else a2 = r_to_n(arg[1], 2); a3 = r_to_n(arg[2], 1); if ((t[0] == 1 && !is_reg(a1)) || (t[1] == 1 && !is_reg(a2)) || !is_reg(a3)) return ; if (t[0] == 1) a1 = r_to_n(p->reg[a1 - 1], REG_SIZE); else if (t[0] == 2) { a1 = mem_to_n(env->mem, mod_idx(a1, p, 2), 4); } if (t[1] == 1) a2 = r_to_n(p->reg[a2 - 1], REG_SIZE); val = mem_to_n(env->mem, mod_idx2(a1, a2, p), REG_SIZE); n_to_r(p->reg[a3 - 1], REG_SIZE, val); }
void op_sti(t_env *env, t_process *p, unsigned char arg[4][4], size_t *t) { size_t a1; unsigned int a2; unsigned int a3; size_t val; a1 = r_to_n(arg[0], 1); if (t[1] == 1) a2 = r_to_n(arg[1], 1); else a2 = r_to_n(arg[1], 2); if (t[2] == 1) a3 = r_to_n(arg[2], 1); else a3 = r_to_n(arg[2], 2); if (!is_reg(a1) || (t[1] == 1 && !is_reg(a2)) || (t[2] == 1 && !is_reg(a3))) return ; a1 = r_to_n(p->reg[a1 - 1], REG_SIZE); if (t[1] == 1) a2 = r_to_n(p->reg[a2 - 1], REG_SIZE); else if (t[1] == 2) a2 = mem_to_n(env->mem, mod_idx(a2, p, 2), 4); if (t[2] == 1) a3 = r_to_n(p->reg[a3 - 1], REG_SIZE); val = mod_idx2(a2, a3, p); n_to_mem(env, p, val, a1); }
static void changed (guestfs_h *g1, struct file *file1, guestfs_h *g2, struct file *file2, int st, int cst) { /* Did file content change? */ if (cst != 0 || (is_reg (file1->stat->st_mode) && is_reg (file2->stat->st_mode) && (file1->stat->st_mtime_sec != file2->stat->st_mtime_sec || file1->stat->st_ctime_sec != file2->stat->st_ctime_sec || file1->stat->st_size != file2->stat->st_size))) { output_start_line (); output_string ("="); output_file (g1, file1); output_end_line (); if (!csv) { /* Display file changes. */ output_flush (); diff (file1, g1, file2, g2); } } /* Did just stats change? */ else if (st != 0) { output_start_line (); output_string ("-"); output_file (g1, file1); output_end_line (); output_start_line (); output_string ("+"); output_file (g2, file2); output_end_line (); /* Display stats fields that changed. */ output_start_line (); output_string ("#"); output_string ("changed:"); #define COMPARE_STAT(n) \ if (file1->stat->n != file2->stat->n) output_string (#n) COMPARE_STAT (st_dev); COMPARE_STAT (st_ino); COMPARE_STAT (st_mode); COMPARE_STAT (st_nlink); COMPARE_STAT (st_uid); COMPARE_STAT (st_gid); COMPARE_STAT (st_rdev); COMPARE_STAT (st_size); COMPARE_STAT (st_blksize); COMPARE_STAT (st_blocks); COMPARE_STAT (st_atime_sec); COMPARE_STAT (st_mtime_sec); COMPARE_STAT (st_ctime_sec); #undef COMPARE_STAT if (guestfs_compare_xattr_list (file1->xattrs, file2->xattrs)) output_string ("xattrs"); output_end_line (); } }
/* Run a diff on two files. */ static void diff (struct file *file1, guestfs_h *g1, struct file *file2, guestfs_h *g2) { CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g1); CLEANUP_FREE char *tmpd, *tmpda = NULL, *tmpdb = NULL, *cmd = NULL; int r; assert (is_reg (file1->stat->st_mode)); assert (is_reg (file2->stat->st_mode)); if (asprintf (&tmpd, "%s/virtdiffXXXXXX", tmpdir) < 0) { perror ("asprintf"); exit (EXIT_FAILURE); } if (mkdtemp (tmpd) == NULL) { perror ("mkdtemp"); exit (EXIT_FAILURE); } if (asprintf (&tmpda, "%s/a", tmpd) < 0 || asprintf (&tmpdb, "%s/b", tmpd) < 0) { perror ("asprintf"); exit (EXIT_FAILURE); } if (guestfs_download (g1, file1->path, tmpda) == -1) goto out; if (guestfs_download (g2, file2->path, tmpdb) == -1) goto out; /* Note that the tmpdir is safe, and the rest of the path * should not need quoting. */ if (asprintf (&cmd, "diff -u '%s' '%s' | tail -n +3", tmpda, tmpdb) < 0) { perror ("asprintf"); exit (EXIT_FAILURE); } if (verbose) fprintf (stderr, "%s\n", cmd); r = system (cmd); if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) { fprintf (stderr, _("%s: external diff command failed\n"), guestfs_int_program_name); goto out; } printf ("@@ %s @@\n", _("End of diff")); out: unlink (tmpda); unlink (tmpdb); rmdir (tmpd); }
void ft_add(t_vm *data, t_proc *process) { if (is_reg(process, 0) && is_reg(process, 1) && is_reg(process, 2)) { if (verbose_operations(data)) ft_printf("P %4d | add r%d r%d r%d\n", ID, MEMORY(PC + 2), MEMORY(PC + 3), MEMORY(PC + 4)); REG(2) = REG(0) + REG(1); process->carry = (REG(2)) ? 0 : 1; } advance_pc(data, process); }
inline bool is_concrete() { assert(is_reg(), "must be"); #ifndef AMD64 if (is_Register()) return true; #endif // AMD64 return is_even(value()); }
t_files *dispatch(t_opm_params *opm) { t_files *to_list; char *path; int i; to_list = (t_files *)ft_memalloc(sizeof(t_files) * 1); to_list->files = ft_vectnew(); to_list->dirs = ft_vectnew(); i = 0; while (i < opm->params->total) { path = arm_getparam_name(opm->params, i); if (is_reg(path)) ft_vectadd(to_list->files, file_initdata(path, NULL)); else if (is_dir(path)) ft_vectadd(to_list->dirs, file_initdata(path, NULL)); else if (is_lnk(path)) case_link(path, opm, to_list); else perror(ft_strjoin("ls: ", path)); i++; } return (to_list); }
void print_opnd_type(Opnd o) { if(is_reg(o)) { if(is_hard_reg(o)) { std::cout << "(is hard reg)"; } else if(is_virtual_reg(o)) { std::cout << "(is virtual reg)[$vr"<<get_reg(o)<<"]"; } else { std::cout << "(is undeterminate reg)"; } } else if(is_immed(o)) { if(is_immed_integer(o)) { std::cout << "(is immed integer)"; } else if(is_immed_string(o)) { std::cout << "(is immed string)"; } else { std::cout << "(is undeterminate immed)"; } } else if(is_addr(o)) { if(is_addr_sym(o)) { FormattedText ft; Sym *symbol = get_sym(o); symbol->print(ft); char* addr_name; addr_name = (char*)(symbol->get_name()).c_str(); std::cout << "(is addr sym)["<<addr_name<<"]"; } else if(is_addr_exp(o)) { std::cout << "(is addr exp)"; } else { std::cout << "(is undeterminate addr)"; } } else if(is_var(o)) { FormattedText ft; VarSym *vsym = get_var(o); vsym->print(ft); char* var_name; var_name = (char*)(vsym->get_name()).c_str(); std::cout << "(is var)["<<var_name<<"]"; } else if(is_null(o)) { std::cout << "(is null)"; } else { std::cout << "(I don't know) !!!)"; } return; }
WRITE3res *nfsproc3_write_3_svc(WRITE3args * argp, struct svc_req * rqstp) { static WRITE3res result; char *path; int fd, res, res_close; PREP(path, argp->file); result.status = join(is_reg(), exports_rw()); /* handle write of owned files */ write_by_owner(rqstp, st_cache); if (result.status == NFS3_OK) { /* We allow caching of the fd only for unstable writes. This is to prevent generating a new write verifier for failed stable writes, when the fd was not in the cache. Besides, for stable writes, the fd will be removed from the cache by fd_close() below, so adding it to and removing it from the cache is just a waste of CPU cycles */ fd = fd_open(path, argp->file, UNFS3_FD_WRITE, (argp->stable == UNSTABLE)); if (fd != -1) { res = backend_pwrite(fd, argp->data.data_val, argp->data.data_len, (off64_t)argp->offset); /* close for real if not UNSTABLE write */ if (argp->stable == UNSTABLE) res_close = fd_close(fd, UNFS3_FD_WRITE, FD_CLOSE_VIRT); else res_close = fd_close(fd, UNFS3_FD_WRITE, FD_CLOSE_REAL); /* we always do fsync(), never fdatasync() */ if (argp->stable == DATA_SYNC) argp->stable = FILE_SYNC; if (res != -1 && res_close != -1) { result.WRITE3res_u.resok.count = res; result.WRITE3res_u.resok.committed = argp->stable; memcpy(result.WRITE3res_u.resok.verf, wverf, NFS3_WRITEVERFSIZE); } else { /* error during write or close */ result.status = write_write_err(); } } else /* could not open for writing */ result.status = write_open_err(); } /* overlaps with resfail */ result.WRITE3res_u.resok.file_wcc.before = get_pre_cached(); result.WRITE3res_u.resok.file_wcc.after = get_post_stat(path, rqstp); return &result; }
const char* name() { if (is_reg()) { return regName[value()]; } else if (!is_valid()) { return "BAD"; } else { // shouldn't really be called with stack return "STACKED REG"; } }
void VMRegImpl::print_on(outputStream* st) const { if( is_reg() ) { assert( VMRegImpl::regName[value()], "" ); st->print("%s",VMRegImpl::regName[value()]); } else if (is_stack()) { int stk = value() - stack0->value(); st->print("[%d]", stk*4); } else { st->print("BAD!"); } }
inline bool VMRegImpl::is_concrete() { assert(is_reg(), "must be"); int v = value(); if ( v < ConcreteRegisterImpl::max_gpr ) { return is_even(v); } // F0..F31 if ( v <= ConcreteRegisterImpl::max_gpr + 31) return true; if ( v < ConcreteRegisterImpl::max_fpr) { return is_even(v); } assert(false, "what register?"); return false; }
int get_param(int param_nb, t_vm *data, t_proc *process) { int param_value; if (PARAM_TYPE(param_nb) == REG_CODE && is_reg(process, param_nb)) param_value = REG(param_nb); else if (PARAM_TYPE(param_nb) == DIR_CODE) param_value = PARAM(param_nb); else if (PARAM_TYPE(param_nb) == IND_CODE) param_value = ft_ramcpy(data, 4, PC + PARAM(param_nb)); else return (ERR_CODE_PARAM); return (param_value); }
int get_param_long(t_vm *data, t_proc *process, int param, int *val) { if (PARAM_TYPE(param) == REG_CODE) { if (is_reg(process, param)) *val = REG(param); else return (0); } else if (process->arg_type[param] == DIR_CODE) *val = PARAM(param); else *val = ft_ramcpy(data, 4, (process->pc + process->av[param])); return (1); }
void op_xor(t_env *env, t_process *p, unsigned char arg[4][4], size_t *t) { unsigned int a1; unsigned int a2; size_t a3; p->carry = 0; a1 = r_to_n(arg[0], t[0]); a2 = r_to_n(arg[1], t[1]); a3 = r_to_n(arg[2], 1); if ((t[0] == 1 && !is_reg(a1)) || (t[1] == 1 && !is_reg(a2)) || !is_reg(a3)) return ; if (t[0] == 1) a1 = r_to_n(p->reg[a1 - 1], REG_SIZE); if (t[1] == 1) a2 = r_to_n(p->reg[a2 - 1], REG_SIZE); if (t[0] == 2) a1 = mem_to_n(env->mem, mod_idx(a1, p, 2), 4); if (t[1] == 2) a2 = mem_to_n(env->mem, mod_idx(a2, p, 2), 4); n_to_r(p->reg[a3 - 1], 4, a1 ^ a2); if (!(a1 ^ a2)) p->carry = 1; }
/** * retourne le type du token * @param chaine le token à analyser * @return un entier correspondant au type du token * */ int get_type(char* chaine) { if (is_hexa32(chaine)) return HEXA32; if (is_hexa8(chaine)) return HEXA8; if (is_objet(chaine)) return OBJET; if (is_reg(chaine)) return REG; if (is_range(chaine)) return RANGE; if (is_integer32(chaine)) return INTEGER32; if (is_integer8(chaine)) return INTEGER8; return UNKNOWN; }
size_t hash(const Opnd opnd) { if (is_reg(opnd)) { int reg = get_reg(opnd); if (is_virtual_reg(opnd)) reg = -(reg + 1); return reg << 1; } else if (is_var(opnd)) { return (size_t)get_var(opnd) | 1; } else if (is_immed_integer(opnd)) { Integer i = get_immed_integer(opnd); if (i.is_c_string_int()) return string_hash(i.chars()); else return i.c_long(); } else if (is_immed_string(opnd)) { return string_hash(get_immed_string(opnd).chars()); } claim(false, "Operand kind %d isn't yet hashable", get_kind(opnd)); return 0; }
COMMIT3res *nfsproc3_commit_3_svc(COMMIT3args * argp, struct svc_req * rqstp) { static COMMIT3res result; char *path; int res; PREP(path, argp->file); result.status = join(is_reg(), exports_rw()); if (result.status == NFS3_OK) { res = fd_sync(argp->file); if (res != -1) memcpy(result.COMMIT3res_u.resok.verf, wverf, NFS3_WRITEVERFSIZE); else /* error during fsync() or close() */ result.status = NFS3ERR_IO; } /* overlaps with resfail */ result.COMMIT3res_u.resfail.file_wcc.before = get_pre_cached(); result.COMMIT3res_u.resfail.file_wcc.after = get_post_stat(path, rqstp); return &result; }
// This really ought to check that the register is "real" in the sense that // we don't try and get the VMReg number of a physical register that doesn't // have an expressible part. That would be pd specific code VMReg next() { assert((is_reg() && value() < stack0->value() - 1) || is_stack(), "must be"); return (VMReg)(intptr_t)(value() + 1); }
static int process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) { char *tmp_dst = NULL; char *abs_dst = NULL; char *tmp; glob_t g; int err = 0; int i; if (dst) { tmp_dst = xstrdup(dst); tmp_dst = make_absolute(tmp_dst, pwd); } memset(&g, 0, sizeof(g)); debug3("Looking up %s", src); if (glob(src, 0, NULL, &g)) { error("File \"%s\" not found.", src); err = -1; goto out; } /* If multiple matches, dst may be directory or unspecified */ if (g.gl_matchc > 1 && tmp_dst && !remote_is_dir(conn, tmp_dst)) { error("Multiple files match, but \"%s\" is not a directory", tmp_dst); err = -1; goto out; } for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!is_reg(g.gl_pathv[i])) { error("skipping non-regular file %s", g.gl_pathv[i]); continue; } if (infer_path(g.gl_pathv[i], &tmp)) { err = -1; goto out; } if (g.gl_matchc == 1 && tmp_dst) { /* If directory specified, append filename */ if (remote_is_dir(conn, tmp_dst)) { if (infer_path(g.gl_pathv[0], &tmp)) { err = 1; goto out; } abs_dst = path_append(tmp_dst, tmp); xfree(tmp); } else abs_dst = xstrdup(tmp_dst); } else if (tmp_dst) { abs_dst = path_append(tmp_dst, tmp); xfree(tmp); } else abs_dst = make_absolute(tmp, pwd); printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1) err = -1; } out: if (abs_dst) xfree(abs_dst); if (tmp_dst) xfree(tmp_dst); globfree(&g); return(err); }
VMReg prev() { assert((is_stack() && value() > stack0->value()) || (is_reg() && value() != 0), "must be"); return (VMReg)(intptr_t)(value() - 1); }
/* Visit each directory/file/etc entry in the tree. This just stores * the data in the tree. Note we don't store file content, but we * keep the guestfs handle open so we can pull that out later if we * need to. */ static int visit_entry (const char *dir, const char *name, const struct guestfs_statns *stat_orig, const struct guestfs_xattr_list *xattrs_orig, void *vt) { struct tree *t = vt; char *path = NULL, *csum = NULL; struct guestfs_statns *stat = NULL; struct guestfs_xattr_list *xattrs = NULL; size_t i; path = full_path (dir, name); /* Copy the stats and xattrs because the visit function will * free them after we return. */ stat = guestfs_copy_statns (stat_orig); if (stat == NULL) { perror ("guestfs_copy_stat"); goto error; } xattrs = guestfs_copy_xattr_list (xattrs_orig); if (xattrs == NULL) { perror ("guestfs_copy_xattr_list"); goto error; } if (checksum && is_reg (stat->st_mode)) { csum = guestfs_checksum (t->g, checksum, path); if (!csum) goto error; } /* If --atime option was NOT passed, flatten the atime field. */ if (!atime) stat->st_atime_sec = stat->st_atime_nsec = 0; /* If --dir-links option was NOT passed, flatten nlink field in * directories. */ if (!dir_links && is_dir (stat->st_mode)) stat->st_nlink = 0; /* If --dir-times option was NOT passed, flatten time fields in * directories. */ if (!dir_times && is_dir (stat->st_mode)) stat->st_atime_sec = stat->st_mtime_sec = stat->st_ctime_sec = stat->st_atime_nsec = stat->st_mtime_nsec = stat->st_ctime_nsec = 0; /* Add the pathname and stats to the list. */ i = t->nr_files++; if (i >= t->allocated) { struct file *old_files = t->files; size_t old_allocated = t->allocated; /* Number of entries in an F15 guest was 111524, and in a * Windows guest was 10709. */ if (old_allocated == 0) t->allocated = 1024; else t->allocated = old_allocated * 2; t->files = realloc (old_files, t->allocated * sizeof (struct file)); if (t->files == NULL) { perror ("realloc"); t->files = old_files; t->allocated = old_allocated; goto error; } } t->files[i].path = path; t->files[i].stat = stat; t->files[i].xattrs = xattrs; t->files[i].csum = csum; return 0; error: free (path); free (csum); guestfs_free_statns (stat); guestfs_free_xattr_list (xattrs); return -1; }
static void output_file (guestfs_h *g, struct file *file) { const char *filetype; size_t i; CLEANUP_FREE char *link = NULL; if (is_reg (file->stat->st_mode)) filetype = "-"; else if (is_dir (file->stat->st_mode)) filetype = "d"; else if (is_chr (file->stat->st_mode)) filetype = "c"; else if (is_blk (file->stat->st_mode)) filetype = "b"; else if (is_fifo (file->stat->st_mode)) filetype = "p"; else if (is_lnk (file->stat->st_mode)) filetype = "l"; else if (is_sock (file->stat->st_mode)) filetype = "s"; else filetype = "u"; output_string (filetype); output_int64_perms (file->stat->st_mode & 07777); output_int64_size (file->stat->st_size); /* Display extra fields when enabled. */ if (enable_uids) { output_int64_uid (file->stat->st_uid); output_int64_uid (file->stat->st_gid); } if (enable_times) { if (atime) output_int64_time (file->stat->st_atime_sec, file->stat->st_atime_nsec); output_int64_time (file->stat->st_mtime_sec, file->stat->st_mtime_nsec); output_int64_time (file->stat->st_ctime_sec, file->stat->st_ctime_nsec); } if (enable_extra_stats) { output_int64_dev (file->stat->st_dev); output_int64 (file->stat->st_ino); output_int64 (file->stat->st_nlink); output_int64_dev (file->stat->st_rdev); output_int64 (file->stat->st_blocks); } if (file->csum) output_string (file->csum); output_string (file->path); if (is_lnk (file->stat->st_mode)) { /* XXX Fix this for NTFS. */ link = guestfs_readlink (g, file->path); if (link) output_string_link (link); } if (enable_xattrs) { for (i = 0; i < file->xattrs->len; ++i) { output_string (file->xattrs->val[i].attrname); output_binary (file->xattrs->val[i].attrval, file->xattrs->val[i].attrval_len); } } }
READ3res *nfsproc3_read_3_svc(READ3args * argp, struct svc_req * rqstp) { static READ3res result; char *path; int fd, res; static char buf[NFS_MAXDATA_TCP + 1]; unsigned int maxdata; if (get_socket_type(rqstp) == SOCK_STREAM) maxdata = NFS_MAXDATA_TCP; else maxdata = NFS_MAXDATA_UDP; PREP(path, argp->file); result.status = is_reg(); /* handle reading of executables */ read_executable(rqstp, st_cache); /* handle read of owned files */ read_by_owner(rqstp, st_cache); /* if bigger than rtmax, truncate length */ if (argp->count > maxdata) argp->count = maxdata; if (result.status == NFS3_OK) { fd = fd_open(path, argp->file, UNFS3_FD_READ, TRUE); if (fd != -1) { /* read one more to check for eof */ res = backend_pread(fd, buf, argp->count + 1, (off64_t)argp->offset); /* eof if we could not read one more */ result.READ3res_u.resok.eof = (res <= (int64) argp->count); /* close for real when hitting eof */ if (result.READ3res_u.resok.eof) fd_close(fd, UNFS3_FD_READ, FD_CLOSE_REAL); else { fd_close(fd, UNFS3_FD_READ, FD_CLOSE_VIRT); res--; } if (res >= 0) { result.READ3res_u.resok.count = res; result.READ3res_u.resok.data.data_len = res; result.READ3res_u.resok.data.data_val = buf; } else { /* error during read() */ /* EINVAL means unreadable object */ if (errno == EINVAL) result.status = NFS3ERR_INVAL; else result.status = NFS3ERR_IO; } } else /* opening for read failed */ result.status = read_err(); } /* overlaps with resfail */ result.READ3res_u.resok.file_attributes = get_post_stat(path, rqstp); return &result; }
inline bool is_concrete() { assert(is_reg(), "must be"); return is_even(value()); }
/* This is the function which is called to display all files and * directories, and it's where the magic happens. We are called with * full stat and extended attributes for each file, so there is no * penalty for displaying anything in those structures. However if we * need other things (eg. checksum) we may have to go back to the * appliance and then there can be a very large penalty. */ static int show_file (const char *dir, const char *name, const struct guestfs_stat *stat, const struct guestfs_xattr_list *xattrs, void *unused) { const char *filetype; CLEANUP_FREE char *path = NULL, *csum = NULL, *link = NULL; /* Display the basic fields. */ output_start_line (); if (is_reg (stat->mode)) filetype = "-"; else if (is_dir (stat->mode)) filetype = "d"; else if (is_chr (stat->mode)) filetype = "c"; else if (is_blk (stat->mode)) filetype = "b"; else if (is_fifo (stat->mode)) filetype = "p"; else if (is_lnk (stat->mode)) filetype = "l"; else if (is_sock (stat->mode)) filetype = "s"; else filetype = "u"; output_string (filetype); output_int64_perms (stat->mode & 07777); output_int64_size (stat->size); /* Display extra fields when enabled. */ if (enable_uids) { output_int64_uid (stat->uid); output_int64_uid (stat->gid); } if (enable_times) { output_int64_time (stat->atime); output_int64_time (stat->mtime); output_int64_time (stat->ctime); } if (enable_extra_stats) { output_int64_dev (stat->dev); output_int64 (stat->ino); output_int64 (stat->nlink); output_int64_dev (stat->rdev); output_int64 (stat->blocks); } /* Disabled for now -- user would definitely want these to be interpreted. if (enable_xattrs) output_xattrs (xattrs); */ path = full_path (dir, name); if (checksum && is_reg (stat->mode)) { csum = guestfs_checksum (g, checksum, path); if (!csum) exit (EXIT_FAILURE); output_string (csum); } output_string (path); if (is_lnk (stat->mode)) /* XXX Fix this for NTFS. */ link = guestfs_readlink (g, path); if (link) output_string_link (link); output_end_line (); return 0; }
int transfer_begin(struct job *j) { int res; char *pread = NULL, *pwrite = NULL; size_t p_len; pthread_mutex_lock(&m_transfer); if (t_state.active) { DEBUG("called transfer_begin while a transfer is active!"); pthread_mutex_unlock(&m_transfer); return TRANSFER_FAIL; } pthread_mutex_unlock(&m_transfer); p_len = strlen(j->path); if (j->op == JOB_PUSH) { pread = cache_path2(j->path, p_len); pwrite = remote_path2(j->path, p_len); } else if (j->op == JOB_PULL) { pread = remote_path2(j->path, p_len); pwrite = cache_path2(j->path, p_len); } if (!pread || !pwrite) { free(pread); free(pwrite); errno = ENOMEM; return -1; } if (is_reg(pread)) { if (!is_reg(pwrite) && !is_nonexist(pwrite)) { DEBUG("write target is non-regular file: %s", pwrite); free(pread); free(pwrite); return TRANSFER_FAIL; } pthread_mutex_lock(&m_transfer); t_state.active = true; t_state.job = j; t_state.offset = 0; pthread_mutex_unlock(&m_transfer); res = transfer(pread, pwrite); free(pread); free(pwrite); return res; } /* if symlink, copy instantly */ else if (is_lnk(pread)) { DEBUG("push/pull on symlink"); copy_symlink(pread, pwrite); copy_attrs(pread, pwrite); free(pread); free(pwrite); return TRANSFER_FINISH; } else if (is_dir(pread)) { DEBUG("push/pull on DIR"); clone_dir(pread, pwrite); copy_attrs(pread, pwrite); free(pread); free(pwrite); return TRANSFER_FINISH; } else { ERROR("cannot read file %s", pread); free(pread); free(pwrite); return TRANSFER_FAIL; } DEBUG("wtf"); return TRANSFER_FAIL; }