static int
match_best_file(const char *filename, void *cookie)
{
	struct best_file_match_arg *arg = cookie;
	const char *active_filename;
	char *filtered_filename;

	if (arg->filter_suffix) {
		size_t len;

		len = strlen(filename);
		if (len < 5 ||
		    (memcmp(filename + len - 4, ".tgz", 4) != 0 &&
		     memcmp(filename + len - 4, ".tbz", 4) != 0)) {
			warnx("filename %s does not contain a recognized suffix", filename);
			return -1;
		}
		filtered_filename = xmalloc(len - 4 + 1);
		memcpy(filtered_filename, filename, len - 4);
		filtered_filename[len - 4] = '\0';
		active_filename = filtered_filename;
	} else {
		filtered_filename = NULL;
		active_filename = filename;
	}

	switch (pkg_order(arg->pattern, active_filename, arg->best_current_match_filtered)) {
	case 0:
	case 2:
		/*
		 * Either current package doesn't match or
		 * the older match is better. Nothing to do.
		 */
		free(filtered_filename);
		return 0;
	case 1:
		/* Current package is better, remember it. */
		free(arg->best_current_match);
		free(arg->best_current_match_filtered);
		arg->best_current_match = xstrdup(filename);
		if (filtered_filename != NULL)
			arg->best_current_match_filtered = filtered_filename;
		else
			arg->best_current_match_filtered = xstrdup(active_filename);
		return 0;
	default:
		errx(EXIT_FAILURE, "Invalid error from pkg_order");
		/* NOTREACHED */
	}
}
static int
match_best_installed(const char *pkg, void *cookie)
{
	struct best_installed_match_arg *arg = cookie;

	switch (pkg_order(arg->pattern, pkg, arg->best_current_match)) {
	case 0:
	case 2:
		/*
		 * Either current package doesn't match or
		 * the older match is better. Nothing to do.
		 */
		break;
	case 1:
		/* Current package is better, remember it. */
		free(arg->best_current_match);
		arg->best_current_match = xstrdup(pkg);
		break;
	}
	return 0;
}
示例#3
0
/* for a given wildcard http:// URL, find the best matching pkg */
static char *
http_expand_URL(const char *base, char *pattern)
{
    char    best[MaxPathSize];
    char    s_best[MaxPathSize];
    char    line[BUFSIZ];
    char    filename[MaxPathSize];
    FILE   *fp;
    int	pipefds[2];
    int     state;
    pid_t   pid;

    *best = '\0';
    *s_best = '\0';

    /* Set up a pipe for getting the file list */
    if (pipe(pipefds) == -1) {
        warnx("cannot create pipe");
        return NULL;
    }
    if ((pid = fork()) == -1) {
        warnx("cannot fork ftp process");
        return NULL;
    }
    if (pid == 0) {		/* The child */
        if (dup2(pipefds[1], STDOUT_FILENO) == -1) {
            warnx("dup2 failed before starting ftp");
            _exit(2);
        }
        close(pipefds[0]);
        close(pipefds[1]);
        /* get URL contents to stdout and thus to parent,
         * silently */
        execlp("ftp", "ftp", "-V", "-o", "-", base, NULL);
        warnx("failed to execute ftp");
        _exit(2);
    }

    /* parent */
    close(pipefds[1]);

    if ((fp=fdopen(pipefds[0], "r")) == NULL)
        warn("can't fdopen pipe end");
    else {
        char s_pattern[MaxPathSize];
        int len, offset;

        /* strip of .t[bg]z for comparison */
        strip_txz(s_pattern, NULL, pattern);

        /* initialize http_extract_fn internal state */
        http_extract_fn(NULL, NULL, 0);

        /* read line from HTTP output and extract filenames */
        while (fgets(line, sizeof(line), fp) != NULL) {
            len = offset = 0;
            while ((len=http_extract_fn(line+offset, filename,
                                        sizeof(filename))) > 0) {
                char s_filename[MaxPathSize];

                offset += len;
                strip_txz(s_filename, NULL, filename);

                if (pkg_order(s_pattern, s_filename,
                              *s_best != '\0' ? s_best : NULL) == 1) {
                    strlcpy(best, filename, sizeof(best));
                    strlcpy(s_best, s_filename, sizeof(best));
                }
            }
        }

    }

    fclose(fp);

    /* wait for child to exit */
    if (waitpid(pid, &state, 0) < 0) {
        /* error has been reported by child */
        return NULL;
    }

    if (best[0] == '\0') {
        if (Verbose)
            warnx("nothing appropriate found");
        return NULL;
    }

    return strdup(best);

}
示例#4
0
/* for a given wildcard ftp:// URL, find the best matching pkg */
static char *
ftp_expand_URL(const char *base, char *pattern)
{
    char *s, buf[MaxPathSize];
    char tmpname[MaxPathSize];
    char best[MaxPathSize];
    char s_best[MaxPathSize];
    int rc, got_list, tfd, retry_tbz;

    retry_tbz = 0;
    best[0]='\0';
    s_best[0]='\0';

    rc = ftp_start(base);
    if (rc == -1) {
        warnx("ftp_start() failed");
        return NULL;
    }

    strlcpy(tmpname, "/var/tmp/pkg.XXXXXX", sizeof(tmpname));
    tfd=mkstemp(tmpname);
    if (tfd == -1) {
        warnx("Cannot generate temp file for ftp(1)'s nlist output");
        return NULL;
    }
    close(tfd); /* We don't need the file descriptor, but will use
		       the file in a second */

    s=strpbrk(pattern, "<>[]?*{"); /* Could leave out "[]?*" here;
					* ftp(1) is not that stupid */
    if (!s) {
        /* This should only happen when getting here with (only) a package
         * name specified to pkg_add, and PKG_PATH containing some URL.
         */
        (void) snprintf(buf, sizeof(buf), "nlist %s %s\n", pattern, tmpname);
    } else {
        /* replace possible version(wildcard) given with "-*".
         * we can't use the pkg wildcards here as dewey compare
         * and alternates won't be handled by ftp(1); sort
         * out later, using pkg_match() */
        if (retry_tbz) {
retry_with_tbz:
            (void) snprintf(buf,  sizeof(buf), "nlist %.*s*.tbz %s\n",
                            (int)(s-pattern), pattern, tmpname);
            retry_tbz = 0;
        } else {
            (void) snprintf(buf,  sizeof(buf), "nlist %.*s*.tgz %s\n",
                            (int)(s-pattern), pattern, tmpname);
            retry_tbz = 1;
        }
    }

    rc = ftp_cmd(buf, "\n(550|450|226).*\n"); /* catch errors */
    if (rc != 226)
        got_list = 0;
    else
        got_list = 1;

    /* Sync - don't remove */
    rc = ftp_cmd("cd .\n", "\n(550|250|257).*\n");
    if (rc != 250) {
        warnx("chdir failed!");
        unlink(tmpname);	/* remove clutter */
        return NULL;
    }

    if (got_list == 1 && access(tmpname, R_OK)==0) {
        FILE *f;
        char filename[MaxPathSize];

        f=fopen(tmpname, "r");
        if (f == NULL) {
            warn("fopen");
            unlink(tmpname);	/* remove clutter */
            return NULL;
        }
        /* The following loop is basically the same as the readdir() loop
         * in findmatchingname() */
        while (fgets(filename, sizeof(filename), f)) {

            /*
             * We need to strip off any .t[bg]z etc.
             * suffix here
             */

            char s_filename[MaxPathSize];
            char s_pattern[MaxPathSize];

            filename[strlen(filename)-1] = '\0';

            strip_txz(s_filename, NULL, filename);
            strip_txz(s_pattern, NULL, pattern);

            if (pkg_order(s_pattern, s_filename,
                          s_best[0] != '\0' ? s_best : NULL) == 1) {
                strlcpy(s_best, s_filename, sizeof(s_best));
                strlcpy(best, filename, sizeof(best));
            }
        }
        (void) fclose(f);
    }

    if (retry_tbz)
        goto retry_with_tbz;

    if (best[0] == '\0' && Verbose)
        warnx("nothing appropriate found");

    unlink(tmpname);

    if (best[0] == '\0')
        return NULL;

    return strdup(best);
}