예제 #1
0
/*
 * Attempt to parse the given URL; if successful, call fetchXGet().
 */
fetchIO *
fetchXGetURL(const char *URL, struct url_stat *us, const char *flags)
{
	struct url *u;
	fetchIO *f;

	if ((u = fetchParseURL(URL)) == NULL)
		return (NULL);

	f = fetchXGet(u, us, flags);

	fetchFreeURL(u);
	return (f);
}
예제 #2
0
/*
 * Attempt to parse the given URL; if successful, call fetchPut().
 */
fetchIO *
fetchPutURL(const char *URL, const char *flags)
{
	struct url *u;
	fetchIO *f;

	if ((u = fetchParseURL(URL)) == NULL)
		return (NULL);

	f = fetchPut(u, flags);

	fetchFreeURL(u);
	return (f);
}
예제 #3
0
파일: fetch.c 프로젝트: Gwenio/DragonFlyBSD
/*
 * Attempt to parse the given URL; if successful, call fetchList().
 */
struct url_ent *
fetchListURL(const char *URL, const char *flags)
{
	struct url *u;
	struct url_ent *ue;

	if ((u = fetchParseURL(URL)) == NULL)
		return (NULL);

	ue = fetchList(u, flags);

	fetchFreeURL(u);
	return (ue);
}
예제 #4
0
파일: fetch.c 프로젝트: Gwenio/DragonFlyBSD
/*
 * Attempt to parse the given URL; if successful, call fetchStat().
 */
int
fetchStatURL(const char *URL, struct url_stat *us, const char *flags)
{
	struct url *u;
	int s;

	if ((u = fetchParseURL(URL)) == NULL)
		return (-1);

	s = fetchStat(u, us, flags);

	fetchFreeURL(u);
	return (s);
}
예제 #5
0
파일: download.c 프로젝트: joyent/pkgin
/*
 * Open a pkg_summary and if newer than local return an open libfetch
 * connection to it.
 */
Sumfile *
sum_open(char *str_url, time_t *db_mtime)
{
	Sumfile		*sum = NULL;
	fetchIO		*f = NULL;
	struct url	*url;
	struct url_stat	st;

	url = fetchParseURL(str_url);

	if (url == NULL || (f = fetchXGet(url, &st, "")) == NULL)
		goto nofetch;

	if (st.size == -1) { /* could not obtain file size */
		*db_mtime = 0; /* not -1, don't force update */
		goto nofetch;
	}

	if (st.mtime <= *db_mtime) {
		/*
		 * -1 used to identify return type,
		 * local summary up-to-date
		 */
		*db_mtime = -1;
		goto nofetch;
	}

	*db_mtime = st.mtime;

#ifndef _MINIX /* XXX: SSIZE_MAX fails under MINIX */
	/* st.size is an off_t, it will be > SSIZE_MAX on 32 bits systems */
	if (sizeof(st.size) == sizeof(SSIZE_MAX) && st.size > SSIZE_MAX - 1)
		err(EXIT_FAILURE, "file is too large");
#endif

	XMALLOC(sum, sizeof(Sumfile));

	sum->fd = f;
	sum->url = url;
	sum->size = st.size;
	goto out;
nofetch:
	if (url)
		fetchFreeURL(url);
	if (f)
		fetchIO_close(f);
out:
	return sum;
}
예제 #6
0
파일: fetch.c 프로젝트: indianpoptart/xbps
/*
 * Attempt to parse the given URL; if successful, call fetchList().
 */
int
fetchListURL(struct url_list *ue, const char *URL, const char *pattern,
    const char *flags)
{
	struct url *u;
	int rv;

	if ((u = fetchParseURL(URL)) == NULL)
		return -1;

	rv = fetchList(ue, u, pattern, flags);

	fetchFreeURL(u);
	return rv;
}
예제 #7
0
int main(int argc, char **argv)
{
	struct db_connection dbc;
	struct utsname u;
	struct url *uo;
	char *url;

	if (dbc_open_fetchlist(&dbc))
		exit(EXIT_FAILURE);

	if (uname(&u))
	{
		perror("uname");
		dbc_abort(&dbc);
		exit(EXIT_FAILURE);
	}

	/* Build patch directory URL. */
	if (asprintf(&url, "%s%s/%s/%s", PATCHSITE_URL, u.machine, u.release,
		PATCHLIST_NAME) < 0)
	{
		perror("asprintf");
		dbc_abort(&dbc);
		exit(EXIT_FAILURE);
	}

	/* Fetch the directory list. */
	uo = fetchParseURL(url);
	if (!uo)
	{
		fprintf(stderr, "Invalid URL: %s", url);
		free(url);
		dbc_abort(&dbc);
		exit(EXIT_FAILURE);
	}

	fio = fetchGet(uo, "");

	/* Reading fio is done by yacc. */
	yyparse();

	fetchIO_close(fio);

	fetchFreeURL(uo);
	free(url);
	dbc_done(&dbc);
	exit(EXIT_SUCCESS);
}
예제 #8
0
파일: download.c 프로젝트: joyent/pkgin
/*
 * archive_read_open close callback.  Stop the progress meter and close the
 * libfetch handler.
 */
int
sum_close(struct archive *a, void *data)
{
	Sumfile	*sum = data;

	if (!parsable)
		stop_progress_meter();
	else
		printf(MSG_DOWNLOAD_END);

	fetchIO_close(sum->fd);
	fetchFreeURL(sum->url);
	XFREE(sum);

	return ARCHIVE_OK;
}
예제 #9
0
파일: common.c 프로젝트: bougyman/xbps
/*
 * Close connection
 */
int
fetch_close(conn_t *conn)
{
	int ret;

#ifdef WITH_SSL
	if (conn->ssl) {
		SSL_shutdown(conn->ssl);
		SSL_free(conn->ssl);
	}
#endif
	ret = close(conn->sd);
	if (conn->cache_url)
		fetchFreeURL(conn->cache_url);
	free(conn->ftp_home);
	free(conn->buf);
	free(conn);
	return (ret);
}
예제 #10
0
파일: main.c 프로젝트: petabi/pkgsrc
int
main(int argc, char *argv[])
{
    Boolean		 use_default_sfx = TRUE;
    Boolean 	 show_basename_only = FALSE;
    char		 lsdir[MaxPathSize];
    char		 sfx[MaxPathSize];
    char		*lsdirp = NULL;
    int		 ch;

    setprogname(argv[0]);

    if (argc < 2)
        usage();

    while ((ch = getopt(argc, argv, Options)) != -1)
        switch (ch) {
        case 'C':
            config_file = optarg;
            break;

        case 'K':
            pkgdb_set_dir(optarg, 3);
            break;

        case 'S':
            sfx[0] = 0x0;
            use_default_sfx = FALSE;
            break;

        case 'V':
            show_version();
        /* NOTREACHED */

        case 'b':
            show_basename_only = TRUE;
            break;

        case 'd':
            (void) strlcpy(lsdir, optarg, sizeof(lsdir));
            lsdirp = lsdir;
            break;

        case 'q':
            quiet = 1;
            break;

        case 's':
            (void) strlcpy(sfx, optarg, sizeof(sfx));
            use_default_sfx = FALSE;
            break;

        case 'v':
            ++verbose;
            break;

        default:
            usage();
            /* NOTREACHED */
        }

    argc -= optind;
    argv += optind;

    if (argc <= 0) {
        usage();
    }

    /*
     * config-var is reading the config file implicitly,
     * so skip it here.
     */
    if (strcasecmp(argv[0], "config-var") != 0)
        pkg_install_config();

    if (use_default_sfx)
        (void) strlcpy(sfx, DEFAULT_SFX, sizeof(sfx));

    if (strcasecmp(argv[0], "pmatch") == 0) {

        char *pattern, *pkg;

        argv++;		/* "pmatch" */

        if (argv[0] == NULL || argv[1] == NULL) {
            usage();
        }

        pattern = argv[0];
        pkg = argv[1];

        if (pkg_match(pattern, pkg)) {
            return 0;
        } else {
            return 1;
        }

    } else if (strcasecmp(argv[0], "rebuild") == 0) {

        rebuild();
        printf("Done.\n");


    } else if (strcasecmp(argv[0], "rebuild-tree") == 0) {

        rebuild_tree();
        printf("Done.\n");

    } else if (strcasecmp(argv[0], "check") == 0) {
        argv++;		/* "check" */

        check(argv);

        if (!quiet) {
            printf("Done.\n");
        }

    } else if (strcasecmp(argv[0], "lsall") == 0) {
        argv++;		/* "lsall" */

        while (*argv != NULL) {
            /* args specified */
            int     rc;
            const char *basep, *dir;

            dir = lsdirp ? lsdirp : dirname_of(*argv);
            basep = basename_of(*argv);

            if (show_basename_only)
                rc = match_local_files(dir, use_default_sfx, 1, basep, lsbasepattern, NULL);
            else
                rc = match_local_files(dir, use_default_sfx, 1, basep, lspattern, __UNCONST(dir));
            if (rc == -1)
                errx(EXIT_FAILURE, "Error from match_local_files(\"%s\", \"%s\", ...)",
                     dir, basep);

            argv++;
        }

    } else if (strcasecmp(argv[0], "lsbest") == 0) {
        argv++;		/* "lsbest" */

        while (*argv != NULL) {
            /* args specified */
            const char *basep, *dir;
            char *p;

            dir = lsdirp ? lsdirp : dirname_of(*argv);
            basep = basename_of(*argv);

            p = find_best_matching_file(dir, basep, use_default_sfx, 1);

            if (p) {
                if (show_basename_only)
                    printf("%s\n", p);
                else
                    printf("%s/%s\n", dir, p);
                free(p);
            }

            argv++;
        }
    } else if (strcasecmp(argv[0], "list") == 0 ||
               strcasecmp(argv[0], "dump") == 0) {

        pkgdb_dump();

    } else if (strcasecmp(argv[0], "add") == 0) {
        struct pkgdb_count count;

        count.files = 0;
        count.directories = 0;
        count.packages = 0;

        for (++argv; *argv != NULL; ++argv)
            add_pkg(*argv, &count);
    } else if (strcasecmp(argv[0], "set") == 0) {
        argv++;		/* "set" */
        set_unset_variable(argv, FALSE);
    } else if (strcasecmp(argv[0], "unset") == 0) {
        argv++;		/* "unset" */
        set_unset_variable(argv, TRUE);
    } else if (strcasecmp(argv[0], "config-var") == 0) {
        argv++;
        if (argv == NULL || argv[1] != NULL)
            errx(EXIT_FAILURE, "config-var takes exactly one argument");
        pkg_install_show_variable(argv[0]);
    } else if (strcasecmp(argv[0], "check-license") == 0) {
        if (argv[1] == NULL)
            errx(EXIT_FAILURE, "check-license takes exactly one argument");

        load_license_lists();

        switch (acceptable_pkg_license(argv[1])) {
        case 0:
            puts("no");
            return 0;
        case 1:
            puts("yes");
            return 0;
        case -1:
            errx(EXIT_FAILURE, "invalid license condition");
        }
    } else if (strcasecmp(argv[0], "check-single-license") == 0) {
        if (argv[1] == NULL)
            errx(EXIT_FAILURE, "check-license takes exactly one argument");
        load_license_lists();

        switch (acceptable_license(argv[1])) {
        case 0:
            puts("no");
            return 0;
        case 1:
            puts("yes");
            return 0;
        case -1:
            errx(EXIT_FAILURE, "invalid license");
        }
    }
#ifndef BOOTSTRAP
    else if (strcasecmp(argv[0], "findbest") == 0) {
        struct url *url;
        char *output;
        int rc;

        process_pkg_path();

        rc = 0;
        for (++argv; *argv != NULL; ++argv) {
            url = find_best_package(NULL, *argv, 1);
            if (url == NULL) {
                rc = 1;
                continue;
            }
            output = fetchStringifyURL(url);
            puts(output);
            fetchFreeURL(url);
            free(output);
        }

        return rc;
    } else if (strcasecmp(argv[0], "fetch-pkg-vulnerabilities") == 0) {
        fetch_pkg_vulnerabilities(--argc, ++argv);
    } else if (strcasecmp(argv[0], "check-pkg-vulnerabilities") == 0) {
        check_pkg_vulnerabilities(--argc, ++argv);
    } else if (strcasecmp(argv[0], "audit") == 0) {
        audit_pkgdb(--argc, ++argv);
    } else if (strcasecmp(argv[0], "audit-pkg") == 0) {
        audit_pkg(--argc, ++argv);
    } else if (strcasecmp(argv[0], "audit-batch") == 0) {
        audit_batch(--argc, ++argv);
    } else if (strcasecmp(argv[0], "audit-history") == 0) {
        audit_history(--argc, ++argv);
    } else if (strcasecmp(argv[0], "check-signature") == 0) {
        struct archive *pkg;
        int rc;

        rc = 0;
        for (--argc, ++argv; argc > 0; --argc, ++argv) {
            char *archive_name;

            pkg = open_archive(*argv, &archive_name);
            if (pkg == NULL) {
                warnx("%s could not be opened", *argv);
                continue;
            }
            if (pkg_full_signature_check(archive_name, &pkg))
                rc = 1;
            free(archive_name);
            if (!pkg)
                archive_read_finish(pkg);
        }
        return rc;
    } else if (strcasecmp(argv[0], "x509-sign-package") == 0) {
#ifdef HAVE_SSL
        --argc;
        ++argv;
        if (argc != 4)
            errx(EXIT_FAILURE, "x509-sign-package takes exactly four arguments");
        pkg_sign_x509(argv[0], argv[1], argv[2], argv[3]);
#else
        errx(EXIT_FAILURE, "OpenSSL support is not included");
#endif
    } else if (strcasecmp(argv[0], "gpg-sign-package") == 0) {
        --argc;
        ++argv;
        if (argc != 2)
            errx(EXIT_FAILURE, "gpg-sign-package takes exactly two arguments");
        pkg_sign_gpg(argv[0], argv[1]);
    }
#endif
    else {
        usage();
    }

    return 0;
}
예제 #11
0
파일: download.c 프로젝트: joyent/pkgin
/*
 * Download a package to the local cache.
 */
ssize_t
download_pkg(char *pkg_url, FILE *fp)
{
	struct url_stat st;
	size_t size, wrote;
	ssize_t fetched, written = 0;
	off_t statsize = 0;
	struct url *url;
	fetchIO *f = NULL;
	char buf[4096];
	char *pkg, *ptr;

	if ((url = fetchParseURL(pkg_url)) == NULL)
		errx(EXIT_FAILURE, "%s: parse failure", pkg_url);

	if ((f = fetchXGet(url, &st, "")) == NULL)
		errx(EXIT_FAILURE, "%s: %s", pkg_url, fetchLastErrString);

	/* Package not available */
	if (st.size == -1)
		return st.size;

	if ((pkg = strrchr(pkg_url, '/')) != NULL)
		pkg++;
	else
		pkg = (char *)pkg_url; /* should not happen */

	if (parsable) {
		printf(MSG_DOWNLOAD_START);
	} else {
		printf(MSG_DOWNLOADING, pkg);
		fflush(stdout);
		start_progress_meter(pkg, st.size, &statsize);
	}

	while (written < st.size) {
		if ((fetched = fetchIO_read(f, buf, sizeof(buf))) == 0)
			break;
		if (fetched == -1 && errno == EINTR)
			continue;
		if (fetched == -1)
			errx(EXIT_FAILURE, "fetch failure: %s",
			    fetchLastErrString);

		statsize += fetched;
		size = fetched;

		for (ptr = buf; size > 0; ptr += wrote, size -= wrote) {
			if ((wrote = fwrite(ptr, 1, size, fp)) < size) {
				if (ferror(fp) && errno == EINTR)
					clearerr(fp);
				else
					break;
			}
			written += wrote;
		}
	}

	if (parsable)
		printf(MSG_DOWNLOAD_END);
	else
		stop_progress_meter();

	fetchIO_close(f);
	fetchFreeURL(url);

	if (written != st.size)
		return -1;

	return written;
}
예제 #12
0
파일: fetch.c 프로젝트: Gwenio/DragonFlyBSD
/*
 * Fetch a file
 */
static int
fetch(char *URL, const char *path)
{
	struct url *url;
	struct url_stat us;
	struct stat sb, nsb;
	struct xferstat xs;
	FILE *f, *of;
	size_t size, readcnt, wr;
	off_t count;
	char flags[8];
	const char *slash;
	char *tmppath;
	int r;
	unsigned timeout;
	char *ptr;

	f = of = NULL;
	tmppath = NULL;

	timeout = 0;
	*flags = 0;
	count = 0;

	/* set verbosity level */
	if (v_level > 1)
		strcat(flags, "v");
	if (v_level > 2)
		fetchDebug = 1;

	/* parse URL */
	if ((url = fetchParseURL(URL)) == NULL) {
		warnx("%s: parse error", URL);
		goto failure;
	}

	/* if no scheme was specified, take a guess */
	if (*url->scheme == 0) {
		if (*url->host == 0)
			strcpy(url->scheme, SCHEME_FILE);
		else if (strncasecmp(url->host, "ftp.", 4) == 0)
			strcpy(url->scheme, SCHEME_FTP);
		else if (strncasecmp(url->host, "www.", 4) == 0)
			strcpy(url->scheme, SCHEME_HTTP);
	}

	/* common flags */
	switch (family) {
	case PF_INET:
		strcat(flags, "4");
		break;
	case PF_INET6:
		strcat(flags, "6");
		break;
	}

	/* FTP specific flags */
	if (strcmp(url->scheme, SCHEME_FTP) == 0) {
		if (p_flag)
			strcat(flags, "p");
		if (d_flag)
			strcat(flags, "d");
		if (U_flag)
			strcat(flags, "l");
		timeout = T_secs ? T_secs : ftp_timeout;
	}

	/* HTTP specific flags */
	if (strcmp(url->scheme, SCHEME_HTTP) == 0 ||
	    strcmp(url->scheme, SCHEME_HTTPS) == 0) {
		if (d_flag)
			strcat(flags, "d");
		if (A_flag)
			strcat(flags, "A");
		timeout = T_secs ? T_secs : http_timeout;
		if (i_flag) {
			if (stat(i_filename, &sb)) {
				warn("%s: stat()", i_filename);
				goto failure;
			}
			url->ims_time = sb.st_mtime;
			strcat(flags, "i");
		}
	}

	/* set the protocol timeout. */
	fetchTimeout = timeout;

	/* just print size */
	if (s_flag) {
		if (timeout)
			alarm(timeout);
		r = fetchStat(url, &us, flags);
		if (timeout)
			alarm(0);
		if (sigalrm || sigint)
			goto signal;
		if (r == -1) {
			warnx("%s", fetchLastErrString);
			goto failure;
		}
		if (us.size == -1)
			printf("Unknown\n");
		else
			printf("%jd\n", (intmax_t)us.size);
		goto success;
	}

	/*
	 * If the -r flag was specified, we have to compare the local
	 * and remote files, so we should really do a fetchStat()
	 * first, but I know of at least one HTTP server that only
	 * sends the content size in response to GET requests, and
	 * leaves it out of replies to HEAD requests.  Also, in the
	 * (frequent) case that the local and remote files match but
	 * the local file is truncated, we have sufficient information
	 * before the compare to issue a correct request.  Therefore,
	 * we always issue a GET request as if we were sure the local
	 * file was a truncated copy of the remote file; we can drop
	 * the connection later if we change our minds.
	 */
	sb.st_size = -1;
	if (!o_stdout) {
		r = stat(path, &sb);
		if (r == 0 && r_flag && S_ISREG(sb.st_mode)) {
			url->offset = sb.st_size;
		} else if (r == -1 || !S_ISREG(sb.st_mode)) {
			/*
			 * Whatever value sb.st_size has now is either
			 * wrong (if stat(2) failed) or irrelevant (if the
			 * path does not refer to a regular file)
			 */
			sb.st_size = -1;
		}
		if (r == -1 && errno != ENOENT) {
			warnx("%s: stat()", path);
			goto failure;
		}
	}

	/* start the transfer */
	if (timeout)
		alarm(timeout);
	f = fetchXGet(url, &us, flags);
	if (timeout)
		alarm(0);
	if (sigalrm || sigint)
		goto signal;
	if (f == NULL) {
		warnx("%s: %s", URL, fetchLastErrString);
		if (i_flag && strcmp(url->scheme, SCHEME_HTTP) == 0
		    && fetchLastErrCode == FETCH_OK
		    && strcmp(fetchLastErrString, "Not Modified") == 0) {
			/* HTTP Not Modified Response, return OK. */
			r = 0;
			goto done;
		} else
			goto failure;
	}
	if (sigint)
		goto signal;

	/* check that size is as expected */
	if (S_size) {
		if (us.size == -1) {
			warnx("%s: size unknown", URL);
		} else if (us.size != S_size) {
			warnx("%s: size mismatch: expected %jd, actual %jd",
			    URL, (intmax_t)S_size, (intmax_t)us.size);
			goto failure;
		}
	}

	/* symlink instead of copy */
	if (l_flag && strcmp(url->scheme, "file") == 0 && !o_stdout) {
		if (symlink(url->doc, path) == -1) {
			warn("%s: symlink()", path);
			goto failure;
		}
		goto success;
	}

	if (us.size == -1 && !o_stdout && v_level > 0)
		warnx("%s: size of remote file is not known", URL);
	if (v_level > 1) {
		if (sb.st_size != -1)
			fprintf(stderr, "local size / mtime: %jd / %ld\n",
			    (intmax_t)sb.st_size, (long)sb.st_mtime);
		if (us.size != -1)
			fprintf(stderr, "remote size / mtime: %jd / %ld\n",
			    (intmax_t)us.size, (long)us.mtime);
	}

	/* open output file */
	if (o_stdout) {
		/* output to stdout */
		of = stdout;
	} else if (r_flag && sb.st_size != -1) {
		/* resume mode, local file exists */
		if (!F_flag && us.mtime && sb.st_mtime != us.mtime) {
			/* no match! have to refetch */
			fclose(f);
			/* if precious, warn the user and give up */
			if (R_flag) {
				warnx("%s: local modification time "
				    "does not match remote", path);
				goto failure_keep;
			}
		} else if (us.size != -1) {
			if (us.size == sb.st_size)
				/* nothing to do */
				goto success;
			if (sb.st_size > us.size) {
				/* local file too long! */
				warnx("%s: local file (%jd bytes) is longer "
				    "than remote file (%jd bytes)", path,
				    (intmax_t)sb.st_size, (intmax_t)us.size);
				goto failure;
			}
			/* we got it, open local file */
			if ((of = fopen(path, "a")) == NULL) {
				warn("%s: fopen()", path);
				goto failure;
			}
			/* check that it didn't move under our feet */
			if (fstat(fileno(of), &nsb) == -1) {
				/* can't happen! */
				warn("%s: fstat()", path);
				goto failure;
			}
			if (nsb.st_dev != sb.st_dev ||
			    nsb.st_ino != nsb.st_ino ||
			    nsb.st_size != sb.st_size) {
				warnx("%s: file has changed", URL);
				fclose(of);
				of = NULL;
				sb = nsb;
			}
		}
	} else if (m_flag && sb.st_size != -1) {
		/* mirror mode, local file exists */
		if (sb.st_size == us.size && sb.st_mtime == us.mtime)
			goto success;
	}

	if (of == NULL) {
		/*
		 * We don't yet have an output file; either this is a
		 * vanilla run with no special flags, or the local and
		 * remote files didn't match.
		 */

		if (url->offset > 0) {
			/*
			 * We tried to restart a transfer, but for
			 * some reason gave up - so we have to restart
			 * from scratch if we want the whole file
			 */
			url->offset = 0;
			if ((f = fetchXGet(url, &us, flags)) == NULL) {
				warnx("%s: %s", URL, fetchLastErrString);
				goto failure;
			}
			if (sigint)
				goto signal;
		}

		/* construct a temporary file name */
		if (sb.st_size != -1 && S_ISREG(sb.st_mode)) {
			if ((slash = strrchr(path, '/')) == NULL)
				slash = path;
			else
				++slash;
			asprintf(&tmppath, "%.*s.fetch.XXXXXX.%s",
			    (int)(slash - path), path, slash);
			if (tmppath != NULL) {
				if (mkstemps(tmppath, strlen(slash)+1) == -1) {
					warn("%s: mkstemps()", path);
					goto failure;
				}

				of = fopen(tmppath, "w");
				chown(tmppath, sb.st_uid, sb.st_gid);
				chmod(tmppath, sb.st_mode & ALLPERMS);
			}
		}

		if (of == NULL)
			if ((of = fopen(path, "w")) == NULL) {
				warn("%s: fopen()", path);
			goto failure;
		}
	}
	count = url->offset;

	/* start the counter */
	stat_start(&xs, path, us.size, count);

	sigalrm = siginfo = sigint = 0;

	/* suck in the data */
	signal(SIGINFO, sig_handler);
	while (!sigint) {
		if (us.size != -1 && us.size - count < B_size &&
		    us.size - count >= 0)
			size = us.size - count;
		else
			size = B_size;
		if (siginfo) {
			stat_end(&xs);
			siginfo = 0;
		}

		if (size == 0)
			break;

		if ((readcnt = fread(buf, 1, size, f)) < size) {
			if (ferror(f) && errno == EINTR && !sigint)
				clearerr(f);
			else if (readcnt == 0)
				break;
		}

		stat_update(&xs, count += readcnt);
		for (ptr = buf; readcnt > 0; ptr += wr, readcnt -= wr)
			if ((wr = fwrite(ptr, 1, readcnt, of)) < readcnt) {
				if (ferror(of) && errno == EINTR && !sigint)
					clearerr(of);
				else
					break;
			}
		if (readcnt != 0)
			break;
	}
	if (!sigalrm)
		sigalrm = ferror(f) && errno == ETIMEDOUT;
	signal(SIGINFO, SIG_DFL);

	stat_end(&xs);

	/*
	 * If the transfer timed out or was interrupted, we still want to
	 * set the mtime in case the file is not removed (-r or -R) and
	 * the user later restarts the transfer.
	 */
 signal:
	/* set mtime of local file */
	if (!n_flag && us.mtime && !o_stdout && of != NULL &&
	    (stat(path, &sb) != -1) && sb.st_mode & S_IFREG) {
		struct timeval tv[2];

		fflush(of);
		tv[0].tv_sec = (long)(us.atime ? us.atime : us.mtime);
		tv[1].tv_sec = (long)us.mtime;
		tv[0].tv_usec = tv[1].tv_usec = 0;
		if (utimes(tmppath ? tmppath : path, tv))
			warn("%s: utimes()", tmppath ? tmppath : path);
	}

	/* timed out or interrupted? */
	if (sigalrm)
		warnx("transfer timed out");
	if (sigint) {
		warnx("transfer interrupted");
		goto failure;
	}

	/* timeout / interrupt before connection completley established? */
	if (f == NULL)
		goto failure;

	if (!sigalrm) {
		/* check the status of our files */
		if (ferror(f))
			warn("%s", URL);
		if (ferror(of))
			warn("%s", path);
		if (ferror(f) || ferror(of))
			goto failure;
	}

	/* did the transfer complete normally? */
	if (us.size != -1 && count < us.size) {
		warnx("%s appears to be truncated: %jd/%jd bytes",
		    path, (intmax_t)count, (intmax_t)us.size);
		goto failure_keep;
	}

	/*
	 * If the transfer timed out and we didn't know how much to
	 * expect, assume the worst (i.e. we didn't get all of it)
	 */
	if (sigalrm && us.size == -1) {
		warnx("%s may be truncated", path);
		goto failure_keep;
	}

 success:
	r = 0;
	if (tmppath != NULL && rename(tmppath, path) == -1) {
		warn("%s: rename()", path);
		goto failure_keep;
	}
	goto done;
 failure:
	if (of && of != stdout && !R_flag && !r_flag)
		if (stat(path, &sb) != -1 && (sb.st_mode & S_IFREG))
			unlink(tmppath ? tmppath : path);
	if (R_flag && tmppath != NULL && sb.st_size == -1)
		rename(tmppath, path); /* ignore errors here */
 failure_keep:
	r = -1;
	goto done;
 done:
	if (f)
		fclose(f);
	if (of && of != stdout)
		fclose(of);
	if (url)
		fetchFreeURL(url);
	if (tmppath != NULL)
		free(tmppath);
	return (r);
}
예제 #13
0
파일: fetch.c 프로젝트: ocochard/pkgng
int
pkg_fetch_file_to_fd(const char *url, int dest, time_t t)
{
	FILE *remote = NULL;
	struct url *u;
	struct url_stat st;
	off_t done = 0;
	off_t r;

	int64_t max_retry, retry;
	time_t begin_dl;
	time_t now;
	time_t last = 0;
	char buf[10240];
	char *doc;
	char docpath[MAXPATHLEN];
	int retcode = EPKG_OK;
	bool srv = false;
	bool http = false;
	char zone[MAXHOSTNAMELEN + 13];
	struct dns_srvinfo *srv_current = NULL;
	struct http_mirror *http_current = NULL;
	const char *mt;

	fetchTimeout = 30;

	if (pkg_config_int64(PKG_CONFIG_FETCH_RETRY, &max_retry) == EPKG_FATAL)
		max_retry = 3;

	retry = max_retry;

	u = fetchParseURL(url);
	doc = u->doc;
	while (remote == NULL) {
		if (retry == max_retry) {
			pkg_config_string(PKG_CONFIG_MIRRORS, &mt);
			if (mt != NULL && strncasecmp(mt, "srv", 3) == 0 && \
			    strcmp(u->scheme, "file") != 0) {
				srv = true;
				snprintf(zone, sizeof(zone),
				    "_%s._tcp.%s", u->scheme, u->host);
				pthread_mutex_lock(&mirror_mtx);
				if (srv_mirrors != NULL)
					srv_mirrors = dns_getsrvinfo(zone);
				pthread_mutex_unlock(&mirror_mtx);
				srv_current = srv_mirrors;
			} else if (mt != NULL && strncasecmp(mt, "http", 4) == 0 && \
			           strcmp(u->scheme, "file") != 0 && \
			           strcmp(u->scheme, "ftp") != 0) {
				http = true;
				snprintf(zone, sizeof(zone),
				    "%s://%s", u->scheme, u->host);
				pthread_mutex_lock(&mirror_mtx);
				if (STAILQ_EMPTY(&http_mirrors))
					gethttpmirrors(zone);
				pthread_mutex_unlock(&mirror_mtx);
				http_current = STAILQ_FIRST(&http_mirrors);
			}
		}

		if (srv && srv_mirrors != NULL)
			strlcpy(u->host, srv_current->host, sizeof(u->host));
		else if (http && !STAILQ_EMPTY(&http_mirrors)) {
			strlcpy(u->scheme, http_current->url->scheme, sizeof(u->scheme));
			strlcpy(u->host, http_current->url->host, sizeof(u->host));
			snprintf(docpath, MAXPATHLEN, "%s%s", http_current->url->doc, doc);
			u->doc = docpath;
			u->port = http_current->url->port;
		}

		remote = fetchXGet(u, &st, "");
		if (remote == NULL) {
			--retry;
			if (retry <= 0) {
				pkg_emit_error("%s: %s", url,
				    fetchLastErrString);
				retcode = EPKG_FATAL;
				goto cleanup;
			}
			if (srv && srv_mirrors != NULL) {
				srv_current = srv_current->next;
				if (srv_current == NULL)
					srv_current = srv_mirrors;
			} else if (http && !STAILQ_EMPTY(&http_mirrors)) {
				http_current = STAILQ_NEXT(http_current, next);
				if (http_current == NULL)
					http_current = STAILQ_FIRST(&http_mirrors);
			} else {
				sleep(1);
			}
		}
	}
	if (t != 0) {
		if (st.mtime <= t) {
			retcode = EPKG_UPTODATE;
			goto cleanup;
		}
	}

	begin_dl = time(NULL);
	while (done < st.size) {
		if ((r = fread(buf, 1, sizeof(buf), remote)) < 1)
			break;

		if (write(dest, buf, r) != r) {
			pkg_emit_errno("write", "");
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		done += r;
		now = time(NULL);
		/* Only call the callback every second */
		if (now > last || done == st.size) {
			pkg_emit_fetching(url, st.size, done, (now - begin_dl));
			last = now;
		}
	}

	if (ferror(remote)) {
		pkg_emit_error("%s: %s", url, fetchLastErrString);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	cleanup:

	if (remote != NULL)
		fclose(remote);

	/* restore original doc */
	u->doc = doc;

	fetchFreeURL(u);

	return (retcode);
}
예제 #14
0
파일: fetch.c 프로젝트: alepharchives/pkgng
int
pkg_fetch_file_to_fd(const char *url, int dest, time_t t)
{
	FILE *remote = NULL;
	struct url *u;
	struct url_stat st;
	off_t done = 0;
	off_t r;

	int64_t max_retry, retry;
	time_t begin_dl;
	time_t now;
	time_t last = 0;
	char buf[10240];
	int retcode = EPKG_OK;
	bool srv = false;
	char zone[MAXHOSTNAMELEN + 12];
	struct dns_srvinfo *mirrors, *current;

	current = mirrors = NULL;

	fetchTimeout = 30;

	if (pkg_config_int64(PKG_CONFIG_FETCH_RETRY, &max_retry) == EPKG_FATAL)
		max_retry = 3;

	retry = max_retry;

	u = fetchParseURL(url);
	while (remote == NULL) {
		if (retry == max_retry) {
			pkg_config_bool(PKG_CONFIG_SRV_MIRROR, &srv);
			if (srv) {
				if (strcmp(u->scheme, "file") != 0) {
					snprintf(zone, sizeof(zone),
					    "_%s._tcp.%s", u->scheme, u->host);
					mirrors = dns_getsrvinfo(zone);
					current = mirrors;
				}
			}
		}

		if (mirrors != NULL)
			strlcpy(u->host, current->host, sizeof(u->host));

		remote = fetchXGet(u, &st, "");
		if (remote == NULL) {
			--retry;
			if (retry <= 0) {
				pkg_emit_error("%s: %s", url,
				    fetchLastErrString);
				retcode = EPKG_FATAL;
				goto cleanup;
			}
			if (mirrors == NULL) {
				sleep(1);
			} else {
				current = current->next;
				if (current == NULL)
					current = mirrors;
			}
		}
	}
	if (t != 0) {
		if (st.mtime <= t) {
			retcode = EPKG_UPTODATE;
			goto cleanup;
		}
	}

	begin_dl = time(NULL);
	while (done < st.size) {
		if ((r = fread(buf, 1, sizeof(buf), remote)) < 1)
			break;

		if (write(dest, buf, r) != r) {
			pkg_emit_errno("write", "");
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		done += r;
		now = time(NULL);
		/* Only call the callback every second */
		if (now > last || done == st.size) {
			pkg_emit_fetching(url, st.size, done, (now - begin_dl));
			last = now;
		}
	}

	if (ferror(remote)) {
		pkg_emit_error("%s: %s", url, fetchLastErrString);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	cleanup:

	if (remote != NULL)
		fclose(remote);

	fetchFreeURL(u);

	return (retcode);
}
예제 #15
0
int
main(int argc, char **argv)
{
	struct termios tios;
	tcflag_t saved;
	struct url *url;
	FILE *in, *out;
	const size_t bufsize = 1024;
	char buf[bufsize], *fullpath, *base;
	char *passwd = NULL, *p, *user = NULL, *u;
	size_t n;
	int c;

	if (argc != 3)
		usage(1);

	while ((c = getopt(argc, argv, "hp:u:")) != -1)
		switch (c) {
		case 'h':
			usage(0);
			break;
		case 'p':
			passwd = optarg;
			break;
		case 'u':
			user = optarg;
			break;
		default:
			usage(1);
			break;
		}

	argc -= optind;
	argv += optind;

	in = inputfile(argv[0]);

	fullpath = malloc(strlen(argv[0]) + strlen(argv[1]) + 2);	
	if (fullpath == NULL)
		err(1, "malloc");
	strcpy(fullpath, argv[1]);
	base = fullpath + strlen(argv[1]);
	*base++ = '/';
	strcpy(base, argv[0]);

	fetchTimeout = 0;

	url = fetchParseURL(fullpath);
	if (url == NULL)
		errx(1, "parsing URL: %s", fetchLastErrString);
	
	if (user == NULL) {
		fprintf(stderr, "Username: "******"reading username");
		u = (char *)url->user;
		strsep(&u, "\n\r");
	} else {
		strlcpy(url->user, user, sizeof(url->user));
	}

	if (passwd == NULL) {
		fprintf(stderr, "Password: "******"reading password");
			tios.c_lflag = saved;
			tcsetattr(STDIN_FILENO, TCSAFLUSH | TCSASOFT, &tios);
		} else {
			if (fgets(url->pwd, sizeof(url->pwd), stdin) == NULL)
				err(1, "reading password");
		}
		p = (char *)url->pwd;
		strsep(&p, "\n\r");
	} else {
		strlcpy(url->pwd, passwd, sizeof(url->pwd));
	}

	out = fetchPutFTP(url, "");
	if (out == NULL) {
		printf("user: %s, pwd: %s\n", url->user, url->pwd);
		errx(1, "couldn't open a connection to %s: %s", fullpath,
		    fetchLastErrString);
	}

	while ((n = fread(buf, 1, bufsize, in)) > 0) {
		if (fwrite(buf, n, 1, out) != 1)
			err(1, "writing to %s", fullpath);
	}

	fclose(in);
	fclose(out);
	fetchFreeURL(url);

	return (0);
}