Пример #1
0
int ssh_send(const char *path, FILE *fp, putmode_t how,
       transfer_mode_t mode, ftp_transfer_func hookf)
{
  uint64_t offset = ftp->restart_offset;

  reset_transfer_info();
  ftp->ti.size = ftp->ti.restart_size = offset;
  ftp->restart_offset = 0L;

  ftp->ti.transfer_is_put = true;

  if(how == putUnique) {
    ftp_err(_("Unique put with SSH not implemented yet\n"));
    return -1;
  }

  char* p = ftp_path_absolute(path);
  stripslash(p);
  ftp_cache_flush_mark_for(p);

  if(how == putAppend) {
    ftp_set_tmp_verbosity(vbNone);
    offset = ftp_filesize(p);
  }

  int r = do_write(p, fp, hookf, offset);
  free(p);

  transfer_finished();
  return r;
}
Пример #2
0
int ssh_send(const char *path, FILE *fp, putmode_t how,
			 transfer_mode_t mode, ftp_transfer_func hookf)
{
	int r;
	long offset = ftp->restart_offset;
	char *p;

	reset_transfer_info();
	ftp->ti.size = ftp->ti.restart_size = offset;
	ftp->restart_offset = 0L;

	ftp->ti.transfer_is_put = true;

	if(how == putUnique) {
		ftp_err("Unique put with SSH not implemented yet\n");
		return -1;
#if 0
		/* try to figure out remote filename */
		char *e = strstr(ftp->reply, " for ");
		if(e) {
			int l;
			e += 5;
			l = strlen(e);
			if(l) {
				free(ftp->ti.local_name);
				if(*e == '\'')
					ftp->ti.local_name = xstrndup(e+1, l-3);
				else
					ftp->ti.local_name = xstrndup(e, l-1);
				ftp_trace("parsed unique filename as '%s'\n",
						  ftp->ti.local_name);
			}
		}
#endif
	}

	p = ftp_path_absolute(path);
	stripslash(p);

	ftp_cache_flush_mark_for(p);

	if(how == putAppend) {
		ftp_set_tmp_verbosity(vbNone);
		offset = ftp_filesize(p);
	}

	r = ssh_send_binary(p, fp, hookf, offset);
	free(p);

	transfer_finished();

	return 0;
}
Пример #3
0
/* returns:
 * 0   ok, remove file from list
 * -1  failure
 */
static int getfile(const rfile *fi, unsigned int opt,
             const char *output, const char *destname)
{
    struct stat sb;
    char* dest = NULL;
    getmode_t how = getNormal;
    bool mkunique = false;
    int r, ret = -1;

    if((get_glob_mask && fnmatch(get_glob_mask, base_name_ptr(fi->path),
                                 FNM_EXTMATCH) == FNM_NOMATCH)
#ifdef HAVE_REGEX
       || (get_rx_mask_set && regexec(&get_rx_mask, base_name_ptr(fi->path),
                                      0, 0, 0) == REG_NOMATCH)
#endif
        )
    {
        return 0;
    }

    if(!output)
        output = ".";

    if(test(opt, GET_PARENTS)) {
        char *apath = base_dir_xptr(fi->path);
        if (asprintf(&dest, "%s%s/%s", output, apath, destname) == -1)
        {
          free(apath);
          fprintf(stderr, _("Failed to allocate memory.\n"));
          return -1;
        }
        free(apath);
    } else {
        /* check if -o option is given, if GET_OUTPUT_FILE is set, we only
         * transfer one file and output is set to the filename. However, if
         * the destination already exists and is a directory, we assume
         * that the user meant a directory */

        int dest_is_file = test(opt, GET_OUTPUT_FILE);

        if(stat(output, &sb) == 0) {
            if(S_ISDIR(sb.st_mode)) {
                dest_is_file = false;
            }
        }

        if(dest_is_file)
            dest = xstrdup(output);
        else
            if (asprintf(&dest, "%s/%s", output, destname) == -1)
            {
              fprintf(stderr, _("Failed to allocate memory.\n"));
              return -1;
            }
    }

    /* make sure destination directory exists */
    {
        char *destdir = base_dir_xptr(dest);
        if(destdir) {
            bool r = make_path(destdir);
            if(!r) {
                if (errno == EEXIST)
                  ftp_err("`%s' exists but is not a directory\n", destdir);
                else
                  ftp_err("%s: %s\n", destdir, strerror(errno));
                transfer_mail_msg(_("Couldn't create directory: %s\n"),
                                  destdir);
                free(destdir);
                return -1;
            }
            /* change permission and group, if requested */
            if(test(opt, GET_CHMOD)) {
                if(stat(destdir, &sb) == 0) {
                    mode_t m = sb.st_mode;
                    m = mode_adjust(m, cmod);
                    if(chmod(destdir, m) != 0)
                        perror(destdir);
                }           }
            if(test(opt, GET_CHGRP)) {
                if(chown(destdir, -1, group_change) != 0)
                    perror(dest);
            }
            free(destdir);
        }
    }

    /* check if destination file exists */
    if(stat(dest, &sb) == 0) {
        if(test(opt, GET_SKIP_EXISTING)) {
            if(test(opt, GET_VERBOSE)) {
							char* sp = shortpath(dest, 42, gvLocalHomeDir);
              fprintf(stderr, _("Local file '%s' exists, skipping...\n"),
                      sp);
							stats_file(STATS_SKIP, 0);
							free(sp);
						}
            return 0;
        }
        if(test(opt, GET_UNIQUE))
            mkunique = true;
        else if(test(opt, GET_APPEND))
            how = getAppend;
        else if(test(opt, GET_NEWER)) {
            struct tm *fan = gmtime(&sb.st_mtime);
            time_t ft = ftp_filetime(fi->path, test(opt, GET_FORCE_NEWER));
            sb.st_mtime = gmt_mktime(fan);

            ftp_trace("get -n: remote file: %s", ctime(&ft));
            ftp_trace("get -n: local file: %s\n", ctime(&sb.st_mtime));

            if(sb.st_mtime >= ft && ft != (time_t)-1) {
                if(test(opt, GET_VERBOSE)) {
									char* sp = shortpath(dest, 30, gvLocalHomeDir);
                    ftp_err(_(
                        "Local file '%s' is newer than remote, skipping...\n"),
                            sp);
									stats_file(STATS_SKIP, 0);
									free(sp);
								}
                return 0;
            }
        } else if(!test(opt, GET_RESUME)) {
            if(!get_owbatch && !gvSighupReceived) {
                struct tm *fan = gmtime(&sb.st_mtime);
                time_t ft = ftp_filetime(fi->path, test(opt, GET_FORCE_NEWER));
                int a;
                char *e;

                sb.st_mtime = gmt_mktime(fan);
                e = xstrdup(ctime(&sb.st_mtime));
								char* sp = shortpath(dest, 42, gvLocalHomeDir);
                a = ask(ASKYES|ASKNO|ASKUNIQUE|ASKCANCEL|ASKALL|ASKRESUME,
                        ASKRESUME,
                        _("Local file '%s' exists\nLocal: %lld bytes, %sRemote: %lld bytes, %sOverwrite?"),
                        sp,
                        (unsigned long long) sb.st_size, e ? e : "unknown date\n",
                        ftp_filesize(fi->path), ctime(&ft));
								free(sp);
                free(e);
                if(a == ASKCANCEL) {
                    get_quit = true;
                    return 0;
                }
                else if(a == ASKNO)
                    return 0;
                else if(a == ASKUNIQUE)
                    mkunique = true;
                else if(a == ASKALL) {
                    get_owbatch = true;
                }
                else if(a == ASKRESUME)
                    opt |= GET_RESUME; /* for this file only */
                /* else a == ASKYES */
            }
        }
        if(test(opt, GET_RESUME))
            how = getResume;
    }

    if(mkunique) {
        char* newdest = make_unique_filename(dest);
        free(dest);
        dest = newdest;
    }

    /* the file doesn't exist or we choosed to overwrite it, or changed dest */

    if(rislink(fi) && test(opt, GET_NO_DEREFERENCE)) {
        /* remove any existing destination */
        unlink(dest);
        ftp_err(_("symlinking '%s' to '%s'\n"), dest, fi->link);
        if(symlink(fi->link, dest) != 0)
            perror(dest);
        ret = 0;
    }
    else {
        r = do_the_get(fi->path, dest, how, opt);

        if(r == 0) {
			stats_file(STATS_SUCCESS, ftp->ti.total_size);
            ret = 0;
            if(test(opt, GET_PRESERVE))
                get_preserve_attribs(fi, dest);
            if(test(opt, GET_CHMOD)) {
                mode_t m = rfile_getmode(fi);
                m = mode_adjust(m, cmod);
                if(chmod(dest, m) != 0)
                    perror(dest);
            }
            if(test(opt, GET_CHGRP)) {
                if(chown(dest, -1, group_change) != 0)
                    perror(dest);
            }
            if(test(opt, GET_DELETE_AFTER)) {
                bool dodel = false;
								char* sp = shortpath(fi->path, 42, ftp->homedir);
                if(!test(opt, GET_FORCE)
                   && !get_delbatch && !gvSighupReceived)
                {
                    int a = ask(ASKYES|ASKNO|ASKCANCEL|ASKALL, ASKYES,
                                _("Delete remote file '%s'?"), sp);
                    if(a == ASKALL) {
                        get_delbatch = true;
                        dodel = true;
                    }
                    else if(a == ASKCANCEL)
                        get_quit = true;
                    else if(a != ASKNO)
                        dodel = true;
                } else
                    dodel = true;

                if(dodel) {
                    ftp_unlink(fi->path);
                    if(ftp->code == ctComplete)
                        fprintf(stderr, _("%s: deleted\n"), sp);
                    else
                        fprintf(stderr, _("error deleting '%s': %s\n"),
															  sp, ftp_getreply(false));
                }
								free(sp);
            }
        } else {
			stats_file(STATS_FAIL, 0);
			ret = -1;
		}
    }

    free(dest);
    return ret;
}
Пример #4
0
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));
		}
	}
}
Пример #5
0
/* transfers SRCFILE on SRCFTP to DESTFILE on DESTFTP
 * using pasv mode on SRCFTP and port mode on DESTFTP
 *
 */
int ftp_fxpfile(Ftp *srcftp, const char *srcfile,
				Ftp *destftp, const char *destfile,
				fxpmode_t how, transfer_mode_t mode)
{
	int r;
	unsigned int old_reply_timeout;
	Ftp *thisftp;
	unsigned char addr[6];

/*	printf("FxP: %s -> %s\n", srcftp->url->hostname, destftp->url->hostname);*/

	if(srcftp == destftp) {
		ftp_err(_("FxP between same hosts\n"));
		return -1;
	}

#ifdef HAVE_LIBSSH
	if(ftp->session) {
		ftp_err("FxP with SSH not implemented\n");
		return -1;
	}
#endif

	thisftp = ftp; /* save currently active connection */

	/* setup source side */
	ftp_use(srcftp);
	ftp_type(mode);
  // TODO: IPv6 support
	if(!ftp_pasv(false, addr, NULL)) {
		ftp_use(thisftp);
		return -1;
	}
	ftp->ti.total_size = -1;

	/* setup destination side */
	ftp_use(destftp);
	ftp_type(mode);
	ftp_cmd("PORT %d,%d,%d,%d,%d,%d",
			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
	if(ftp->code != ctComplete) {
		ftp_use(thisftp);
		return -1;
	}
	ftp->ti.total_size = -1;

	ftp_use(destftp);

	if(how == fxpResume) {
		rfile *f;

		f = ftp_get_file(destfile);
		if(f && f->size != (unsigned long long)-1)
			ftp->restart_offset = f->size;
		else {
			ftp->restart_offset = ftp_filesize(destfile);
			if(ftp->restart_offset == (unsigned long long)-1) {
				ftp_err(_("unable to get remote filesize of '%s',"
						  " unable to resume\n"),
						destfile);
				ftp->restart_offset = 0L;
			}
		}
	} else
		ftp->restart_offset = 0L;

	if(ftp->restart_offset) {
		/* RESTart on destftp */
		ftp_cmd("REST %ld", ftp->restart_offset);
		if(ftp->code != ctContinue)
			return -1;
		ftp_use(srcftp);
		ftp_cmd("REST %ld", ftp->restart_offset);
		if(ftp->code != ctContinue)
			return -1;
	}

	/* issue a STOR command on DESTFTP */
	ftp_use(destftp);
	switch(how) {
	case fxpUnique:
		if(ftp->has_stou_command) {
			ftp_cmd("STOU %s", destfile);
			if(ftp->fullcode == 502)
				ftp->has_stou_command = false;
		} else {
			ftp->code = ctError;
			ftp->fullcode = 502;
		}
		break;
	case fxpAppend:
		ftp_cmd("APPE %s", destfile);
		break;
	case fxpNormal:
	default:
		ftp_cmd("STOR %s", destfile);
		break;
	}

	ftp_cache_flush_mark_for(destfile);

	if(ftp->code != ctPrelim) {
		ftp_use(thisftp);
		return -1;
	}

	/* issue a RETR command on SRCFTP */
	ftp_use(srcftp);
	ftp_cmd("RETR %s", srcfile);
	if(ftp->code != ctPrelim) {
		ftp_use(destftp);
		ftp_abort(NULL);
		ftp_use(thisftp);
		return -1;
	}

	ftp_use(destftp);
	old_reply_timeout = ftp->reply_timeout;
	ftp_reply_timeout(0);
	ftp_read_reply();
	ftp_reply_timeout(old_reply_timeout);

	r = (ftp->code == ctComplete ? 0 : -1);

	ftp_use(srcftp);
	old_reply_timeout = ftp->reply_timeout;
	ftp_reply_timeout(0);
	ftp_read_reply();
	ftp_reply_timeout(old_reply_timeout);

	ftp_use(thisftp);

	return r;
}
Пример #6
0
int ftp_putfile(const char *infile, const char *outfile, putmode_t how,
				transfer_mode_t mode, ftp_transfer_func hookf)
{
	FILE *fp;
	int r;
	struct stat statbuf;

	if(stat(infile, &statbuf) != 0) {
		perror(infile);
		return -1;
	}

	if(S_ISDIR(statbuf.st_mode)) {
		ftp_err(_("%s: is a directory\n"), infile);
		return -1;
	}

	fp = fopen(infile, "r");
	if(fp == 0) {
		perror(infile);
		return -1;
	}

	ftp->ti.total_size = statbuf.st_size;
	free(ftp->ti.remote_name);
	free(ftp->ti.local_name);
	ftp->ti.remote_name = xstrdup(infile); /* actually local file, or _target_ */
	ftp->ti.local_name = xstrdup(outfile); /* actually remote file, or _source_ */

	if(how == putResume) {
		rfile *f;

		f = ftp_get_file(outfile);
		if(f && f->size != (unsigned long long)-1)
			ftp->restart_offset = f->size;
		else {
			ftp->restart_offset = ftp_filesize(outfile);
			if(ftp->restart_offset == (unsigned long long)-1) {
				ftp_err(_("unable to get remote filesize of '%s',"
						  " unable to resume\n"),
						outfile);
				ftp->restart_offset = 0L;
			}
		}
	} else
		ftp->restart_offset = 0L;


	if(ftp->restart_offset > 0L) {
		if(fseek(fp, ftp->restart_offset, SEEK_SET) != 0) {
			ftp_err(_("%s: %s, transfer cancelled\n"),
					outfile, strerror(errno));
			fclose(fp);
			return -1;
		}
	}

	foo_hookf = hookf;

#ifdef HAVE_LIBSSH
	if(ftp->session)
		r = ssh_send(outfile, fp, how, mode, hookf);
	else
#endif
		r = ftp_send(outfile, fp, how, mode, hookf);
	fclose(fp);
	return r;
}