static char *ftplist_completion_function(const char *text, int state) { static int len; static listitem *lip = 0; if(!state) { len = strlen(text); lip = gvFtpList->first; } while(lip) { char *name; Ftp *f = (Ftp *)lip->data; lip = lip->next; if(f->url == 0) /* Ftp not connected */ continue; name = f->url->alias ? f->url->alias : f->url->hostname; if(strncmp(name, text, len) == 0) return bash_backslash_quote(name); } return 0; }
static int do_read(const char* infile, FILE* fp, getmode_t mode, ftp_transfer_func hookf, uint64_t offset) { if (gvSSHTrySCP && !offset) { char* escaped = bash_backslash_quote(infile); /* try to set up a scp connection */ ssh_scp scp = ssh_scp_new(ftp->session, SSH_SCP_READ, escaped); free(escaped); if (scp != NULL) { int rc = ssh_scp_init(scp); if (rc == SSH_OK) return do_scp_read(scp, infile, fp, mode, hookf); ssh_scp_free(scp); } } time_t then = time(NULL) - 1; ftp_set_close_handler(); if (hookf) hookf(&ftp->ti); ftp->ti.begin = false; /* check if remote file is not a directory */ sftp_attributes attrib = sftp_stat(ftp->sftp_session, infile); if (!attrib) return -1; if (S_ISDIR(attrib->permissions)) { ftp_err(_("Cannot download a directory: %s\n"), infile); sftp_attributes_free(attrib); return -1; } sftp_attributes_free(attrib); /* open remote file */ sftp_file file = sftp_open(ftp->sftp_session, infile, O_RDONLY, 0); if (!file) { ftp_err(_("Cannot open file for reading: %s\n"), ssh_get_error(ftp->session)); return -1; } /* seek to offset */ int r = sftp_seek64(file, offset); if (r != SSH_OK) { ftp_err(_("Failed to seek: %s\n"), ssh_get_error(ftp->session)); sftp_close(file); return -1; } /* read file */ char buffer[SSH_BUFSIZ]; ssize_t nbytes = 0; while ((nbytes = sftp_read(file, buffer, sizeof(buffer))) > 0) { if (ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } errno = 0; if (fwrite(buffer, nbytes, 1, fp) != 1) { ftp_err(_("Error while writing to file: %s\n"), strerror(errno)); ftp->ti.ioerror = true; sftp_close(file); return -1; } ftp->ti.size += nbytes; if (hookf) { time_t now = time(NULL); if (now > then) { hookf(&ftp->ti); then = now; } } } if (nbytes < 0) { ftp_err(_("Error while reading from file: %s\n"), ssh_get_error(ftp->session)); r = -1; } sftp_close(file); return r; }
static void putfile(const char *path, struct stat *sb, unsigned opt, const char *output) { putmode_t how = putNormal; bool file_exists = false; char *dest, *dpath; int r; bool dir_created; char *dest_dir, *q_dest_dir; if((put_glob_mask && fnmatch(put_glob_mask, base_name_ptr(path), FNM_EXTMATCH) == FNM_NOMATCH) #ifdef HAVE_REGEX || (put_rx_mask_set && regexec(&put_rx_mask, base_name_ptr(path), 0, 0, 0) == REG_NOMATCH) #endif ) return; if(!output) output = "."; if(test(opt, PUT_PARENTS)) { char *p = base_dir_xptr(path); asprintf(&dest, "%s/%s/%s", output, p, base_name_ptr(path)); free(p); } else if(test(opt, PUT_OUTPUT_FILE)) dest = xstrdup(output); else asprintf(&dest, "%s/%s", output, base_name_ptr(path)); path_collapse(dest); /* make sure destination directory exists */ dpath = base_dir_xptr(dest); dest_dir = ftp_path_absolute(dpath); q_dest_dir = bash_backslash_quote(dest_dir); r = ftp_mkpath(q_dest_dir); free(q_dest_dir); free(dest_dir); if(r == -1) { transfer_mail_msg(_("failed to create directory %s\n"), dest_dir); free(dpath); free(dest); return; } dir_created = (r == 1); if(!dir_created && !test(opt, PUT_UNIQUE) && !test(opt, PUT_FORCE)) { rfile *f; f = ftp_get_file(dest); file_exists = (f != 0); if(f && risdir(f)) { /* can't overwrite a directory */ printf(_("%s: is a directory\n"), dest); free(dest); return; } } if(test(opt, PUT_APPEND)) { how = putAppend; } else if(file_exists) { if(test(opt, PUT_SKIP_EXISTING)) { printf(_("Remote file '%s' exists, skipping...\n"), shortpath(dest, 42, ftp->homedir)); free(dest); return; } else if(test(opt, PUT_NEWER)) { time_t ft = ftp_filetime(dest); if(ft != (time_t)-1 && ft >= sb->st_mtime) { printf(_("Remote file '%s' is newer than local, skipping...\n"), shortpath(dest, 42, ftp->homedir)); free(dest); return; } } else if(!test(opt, PUT_RESUME)) { if(!put_owbatch) { struct tm *fan = gmtime(&sb->st_mtime); time_t ft; int a; rfile *f; char *e; f = ftp_get_file(dest); ft = ftp_filetime(f->path); sb->st_mtime = gmt_mktime(fan); e = xstrdup(ctime(&sb->st_mtime)); a = ask(ASKYES|ASKNO|ASKUNIQUE|ASKCANCEL|ASKALL|ASKRESUME, ASKRESUME, _("Remote file '%s' exists\nLocal: %lld bytes, %sRemote: %lld bytes, %sOverwrite?"), shortpath(dest, 42, ftp->homedir), (unsigned long long) sb->st_size, e ? e : "unknown size", ftp_filesize(f->path), ctime(&ft)); free(e); if(a == ASKCANCEL) { put_quit = true; free(dest); return; } else if(a == ASKNO) { free(dest); return; } else if(a == ASKUNIQUE) opt |= PUT_UNIQUE; /* for this file only */ else if(a == ASKALL) put_owbatch = true; else if(a == ASKRESUME) opt |= PUT_RESUME; /* for this file only */ /* else a == ASKYES */ } } } if(test(opt, PUT_RESUME)) how = putResume; if(test(opt, PUT_UNIQUE)) how = putUnique; r = do_the_put(path, dest, how, opt); free(dest); if(r != 0) return; if(test(opt, PUT_PRESERVE)) { if(ftp->has_site_chmod_command) ftp_chmod(ftp->ti.local_name, get_mode_string(sb->st_mode)); } if(test(opt, PUT_DELETE_AFTER)) { bool dodel = false; if(!test(opt, PUT_FORCE) && !put_delbatch) { int a = ask(ASKYES|ASKNO|ASKCANCEL|ASKALL, ASKYES, _("Delete local file '%s'?"), shortpath(path, 42, gvLocalHomeDir)); if(a == ASKALL) { put_delbatch = true; dodel = true; } else if(a == ASKCANCEL) put_quit = true; else if(a != ASKNO) dodel = true; } else dodel = true; if(dodel) { if(unlink(path) == 0) printf(_("%s: deleted\n"), shortpath(path, 42, gvLocalHomeDir)); else printf(_("error deleting '%s': %s\n"), shortpath(path, 42, gvLocalHomeDir), strerror(errno)); } } }
/* Quote a filename using double quotes, single quotes, or backslashes depending on the value of completion_quoting_style. If we're completing using backslashes, we need to quote some additional characters (those that readline treats as word breaks), so we call quote_word_break_chars on the result. */ char *bash_quote_filename (char *s, int rtype, char *qcp) { char *rtext, *mtext, *ret; int rlen, cs; rtext = (char *)NULL; /* If RTYPE == MULT_MATCH, it means that there is more than one match. In this case, we do not add the closing quote or attempt to perform tilde expansion. If RTYPE == SINGLE_MATCH, we try to perform tilde expansion, because single and double quotes inhibit tilde expansion by the shell. */ mtext = s; if (mtext[0] == '~' && rtype == SINGLE_MATCH) mtext = tilde_expand_home (s, gvLocalHomeDir); cs = completion_quoting_style; /* Might need to modify the default completion style based on *qcp, since it's set to any user-provided opening quote. */ if (*qcp == '"') cs = COMPLETE_DQUOTE; else if (*qcp == '\'') cs = COMPLETE_SQUOTE; #if defined (BANG_HISTORY) else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE && history_expansion_inhibited == 0 && strchr (mtext, '!')) cs = COMPLETE_BSQUOTE; if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE && history_expansion_inhibited == 0 && strchr (mtext, '!')) { cs = COMPLETE_BSQUOTE; *qcp = '\0'; } #endif switch (cs) { case COMPLETE_DQUOTE: rtext = bash_double_quote (mtext); break; case COMPLETE_SQUOTE: rtext = bash_single_quote (mtext); break; case COMPLETE_BSQUOTE: rtext = bash_backslash_quote (mtext); break; } if (mtext != s) free (mtext); /* We may need to quote additional characters: those that readline treats as word breaks that are not quoted by backslash_quote. */ if (rtext && cs == COMPLETE_BSQUOTE) { mtext = quote_word_break_chars (rtext); free (rtext); rtext = mtext; } /* Leave the opening quote intact. The readline completion code takes care of avoiding doubled opening quotes. */ rlen = strlen (rtext); ret = xmalloc (rlen + 1); strcpy (ret, rtext); /* If there are multiple matches, cut off the closing quote. */ if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE) ret[rlen - 1] = '\0'; free (rtext); return ret; }