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; }
/* 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); }
/* 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); }