예제 #1
0
/* Open an outer archive with the given filename. */
static struct archive *open_outer(const char *filename)
{
    struct archive *outer;
    int r;

    outer = archive_read_new();
    if (!outer) {
        opkg_msg(ERROR, "Failed to create outer archive object.\n");
        return NULL;
    }

    /* Outer package is in 'ar' format, uncompressed. */
    r = archive_read_support_format_ar(outer);
    if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Ar format not supported: %s\n",
                 archive_error_string(outer));
        goto err_cleanup;
    }

    r = archive_read_open_filename(outer, filename, EXTRACT_BUFFER_LEN);
    if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Failed to open package '%s': %s\n", filename,
                 archive_error_string(outer));
        goto err_cleanup;
    }

    return outer;

 err_cleanup:
    archive_read_free(outer);
    return NULL;
}
예제 #2
0
파일: pkg_src.c 프로젝트: Droid-MAX/opkg
int pkg_src_download_signature(pkg_src_t * src)
{
    int err = 0;
    char *url;
    char *sigfile;
    const char *sigext;

    if (strcmp(opkg_config->signature_type, "gpg-asc") == 0)
        sigext = "asc";
    else
        sigext = "sig";

    sprintf_alloc(&sigfile, "%s/%s.%s", opkg_config->lists_dir, src->name,
                  sigext);

    /* get the url for the sig file */
    if (src->extra_data)        /* debian style? */
        sprintf_alloc(&url, "%s/%s/Packages.%s", src->value, src->extra_data,
                      sigext);
    else
        sprintf_alloc(&url, "%s/Packages.%s", src->value, sigext);

    err = opkg_download(url, sigfile, NULL, NULL);
    if (err) {
        opkg_msg(ERROR, "Failed to download signature for %s.\n", src->name);
        goto cleanup;
    }

    opkg_msg(DEBUG, "Downloaded signature for %s.\n", src->name);

 cleanup:
    free(sigfile);
    free(url);
    return err;
}
예제 #3
0
파일: conffile.c 프로젝트: HulaBurger/opkg
int conffile_has_been_modified(conffile_t * conffile)
{
    char *md5sum;
    char *filename = conffile->name;
    char *root_filename;
    int ret = 1;

    if (conffile->value == NULL) {
        opkg_msg(NOTICE, "Conffile %s has no md5sum.\n", conffile->name);
        return 1;
    }

    root_filename = root_filename_alloc(filename);

    md5sum = file_md5sum_alloc(root_filename);

    if (md5sum && (ret = strcmp(md5sum, conffile->value))) {
        opkg_msg(INFO, "Conffile %s:\n\told md5=%s\n\tnew md5=%s\n",
                 conffile->name, md5sum, conffile->value);
    }

    free(root_filename);
    if (md5sum)
        free(md5sum);

    return ret;
}
예제 #4
0
int pkg_extract_control_files_to_dir_with_prefix(pkg_t * pkg, const char *dir,
                                                 const char *prefix)
{
    int r = -1;
    char *dir_with_prefix;
    struct opkg_ar *ar;

    sprintf_alloc(&dir_with_prefix, "%s/%s", dir, prefix);

    ar = ar_open_pkg_control_archive(pkg->local_filename);
    if (!ar) {
        opkg_msg(ERROR, "Failed to extract control.tar.gz from package '%s'.\n",
                 pkg->local_filename);
        goto cleanup;
    }

    r = ar_extract_all(ar, dir_with_prefix);
    if (r < 0)
        opkg_msg(ERROR,
                 "Failed to extract all control files from package '%s'.\n",
                 pkg->local_filename);

 cleanup:
    free(dir_with_prefix);
    if (ar)
        ar_close(ar);
    return r;
}
예제 #5
0
파일: pkg_depends.c 프로젝트: beyonwiz/opkg
enum version_constraint str_to_constraint(const char **str)
{
    if (strncmp(*str, "<<", 2) == 0) {
        *str += 2;
        return EARLIER;
    } else if (strncmp(*str, "<=", 2) == 0) {
        *str += 2;
        return EARLIER_EQUAL;
    } else if (strncmp(*str, ">=", 2) == 0) {
        *str += 2;
        return LATER_EQUAL;
    } else if (strncmp(*str, ">>", 2) == 0) {
        *str += 2;
        return LATER;
    } else if (strncmp(*str, "=", 1) == 0) {
        *str += 1;
        return EQUAL;
    }
    /* should these be here to support deprecated designations; dpkg does */
    else if (strncmp(*str, "<", 1) == 0) {
        *str += 1;
        opkg_msg(NOTICE,
                 "Deprecated version constraint '<' was used with the same "
                 "meaning as '<='. Use '<<' for EARLIER constraint.\n");
        return EARLIER_EQUAL;
    } else if (strncmp(*str, ">", 1) == 0) {
        *str += 1;
        opkg_msg(NOTICE,
                 "Deprecated version constraint '>' was used with the same "
                 "meaning as '>='. Use '>>' for LATER constraint.\n");
        return LATER_EQUAL;
    } else {
        return NONE;
    }
}
예제 #6
0
/* Extract an entry to disk, returns 0 on success or <0 on error. */
static int extract_entry(struct archive *a, struct archive_entry *entry,
                         struct archive *disk)
{
    int r;
    int retries = 0;

 retry:
    r = archive_read_extract2(a, entry, disk);
    switch (r) {
    case ARCHIVE_OK:
        break;

    case ARCHIVE_WARN:
        opkg_msg(NOTICE, "Warning when extracting archive entry: %s\n",
                 archive_error_string(a));
        break;

    case ARCHIVE_RETRY:
        opkg_msg(ERROR, "Failed to extract archive entry '%s': %s\n",
                 archive_entry_pathname(entry), archive_error_string(a));
        if (retries++ < 3) {
            opkg_msg(NOTICE, "Retrying...\n");
            goto retry;
        } else
            return -1;

    default:
        opkg_msg(ERROR, "Failed to extract archive entry '%s': %s\n",
                 archive_entry_pathname(entry), archive_error_string(a));
        return -1;
    }

    return 0;
}
예제 #7
0
파일: opkg_remove.c 프로젝트: beyonwiz/opkg
/*
 * Find and remove packages that were autoinstalled and are orphaned
 * by the removal of pkg.
 */
static int remove_autoinstalled(pkg_t * pkg)
{
    int i, j;
    int err = 0;
    int n_deps;
    pkg_t *p;
    struct compound_depend *cdep;
    abstract_pkg_t **dependents;
    int r;

    int count = pkg->pre_depends_count + pkg->depends_count
        + pkg->recommends_count + pkg->suggests_count;

    for (i = 0; i < count; i++) {
        cdep = &pkg->depends[i];
        /* Only remove dependency types which would normally be autoinstalled,
         * namely the types PREDEPEND, DEPEND and RECOMMEND. We don't consider
         * SUGGEST which are not normally autoinstalled and we don't consider
         * CONFLICTS or GREEDY_DEPEND either.
         */
        int uninteresting = cdep->type != PREDEPEND
                && cdep->type != DEPEND
                && cdep->type != RECOMMEND;
        if (uninteresting)
            continue;
        for (j = 0; j < cdep->possibility_count; j++) {
            p = pkg_hash_fetch_installed_by_name(cdep->possibilities[j]->pkg->
                                                 name);

            /* If the package is not installed, this could have
             * been a circular dependency and the package has
             * already been removed.
             */
            if (!p)
                return -1;

            if (!p->auto_installed)
                continue;

            n_deps = pkg_has_installed_dependents(p, &dependents);
            if (n_deps == 0) {
                opkg_msg(NOTICE,
                         "%s was autoinstalled and is "
                         "now orphaned, removing.\n", p->name);
                r = opkg_remove_pkg(p);
                if (r != 0)
                    err = -1;
            } else
                opkg_msg(INFO,
                         "%s was autoinstalled and is " "still required by %d "
                         "installed packages.\n", p->name, n_deps);

            free(dependents);
        }
    }

    return err;
}
예제 #8
0
static int
opkg_download_cache(const char *src, const char *dest_file_name,
	curl_progress_func cb, void *data)
{
    char *cache_name = xstrdup(src);
    char *cache_location, *p;
    int err = 0;

    if (!conf->cache || str_starts_with(src, "file:")) {
	err = opkg_download(src, dest_file_name, cb, data, 0);
	goto out1;
    }

    if(!file_is_dir(conf->cache)){
	    opkg_msg(ERROR, "%s is not a directory.\n",
			    conf->cache);
	    err = 1;
	    goto out1;
    }

    for (p = cache_name; *p; p++)
	if (*p == '/')
	    *p = ',';	/* looks nicer than | or # */

    sprintf_alloc(&cache_location, "%s/%s", conf->cache, cache_name);
    if (file_exists(cache_location))
	opkg_msg(NOTICE, "Copying %s.\n", cache_location);
    else {
       /* cache file with funky name not found, try simple name */
        free(cache_name);
        char *filename = strrchr(dest_file_name,'/');
        if (filename)
           cache_name = xstrdup(filename+1); // strip leading '/'
        else
           cache_name = xstrdup(dest_file_name);
        free(cache_location);
        sprintf_alloc(&cache_location, "%s/%s", conf->cache, cache_name);
        if (file_exists(cache_location))
           opkg_msg(NOTICE, "Copying %s.\n", cache_location);
        else  {
 	    err = opkg_download(src, cache_location, cb, data, 0);
	    if (err) {
	       (void) unlink(cache_location);
	       goto out2;
	  }
	}
    }

    err = file_copy(cache_location, dest_file_name);


out2:
    free(cache_location);
out1:
    free(cache_name);
    return err;
}
예제 #9
0
static X509_STORE *
setup_verify(char *CAfile, char *CApath)
{
    X509_STORE *store = NULL;
    X509_LOOKUP *lookup = NULL;

    if(!(store = X509_STORE_new())){
        // Something bad is happening...
        goto end;
    }

    // adds the X509 file lookup method
    lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file());
    if (lookup == NULL){
        goto end;
    }

    // Autenticating against one CA file
    if (CAfile) {
        if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
            // Invalid CA => Bye bye
            opkg_msg(ERROR, "Error loading file %s.\n", CAfile);
            goto end;
        }
    } else {
        X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
    }

    // Now look into CApath directory if supplied
    lookup = X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
    if (lookup == NULL){
        goto end;
    }

    if (CApath) {
        if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
            opkg_msg(ERROR, "Error loading directory %s.\n", CApath);
            goto end;
        }
    } else {
        X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
    }

    // All right !
    ERR_clear_error();
    return store;

end:

    X509_STORE_free(store);
    return NULL;

}
예제 #10
0
/* Print destination paths at DEBUG level. */
static void print_paths(struct archive_entry *entry)
{
    const char *path = archive_entry_pathname(entry);
    const char *hardlink = archive_entry_hardlink(entry);
    const char *symlink = archive_entry_symlink(entry);
    if (hardlink)
        opkg_msg(DEBUG, "Extracting '%s', hardlink to '%s'.\n", path, hardlink);
    else if (symlink)
        opkg_msg(DEBUG, "Extracting '%s', symlink to '%s'.\n", path, symlink);
    else
        opkg_msg(DEBUG, "Extracting '%s'.\n", path);

}
예제 #11
0
/* Open an inner archive at the current position within the given outer archive. */
static struct archive *open_inner(struct archive *outer)
{
    struct archive *inner;
    struct inner_data *data;
    int r;

    inner = archive_read_new();
    if (!inner) {
        opkg_msg(ERROR, "Failed to create inner archive object.\n");
        return NULL;
    }

    data = (struct inner_data *)xmalloc(sizeof(struct inner_data));
    data->buffer = xmalloc(EXTRACT_BUFFER_LEN);
    data->outer = outer;

    /* Inner package is in 'tar' format, gzip compressed. */
    r = archive_read_support_filter_gzip(inner);
    if (r == ARCHIVE_WARN) {
        /* libarchive returns ARCHIVE_WARN if the filter is provided by
         * an external program.
         */
        opkg_msg(INFO, "Gzip support provided by external program.\n");
    } else if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Gzip format not supported.\n");
        goto err_cleanup;
    }

    r = archive_read_support_format_tar(inner);
    if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Tar format not supported: %s\n",
                 archive_error_string(outer));
        goto err_cleanup;
    }

    r = archive_read_open(inner, data, NULL, inner_read, inner_close);
    if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Failed to open inner archive: %s\n",
                 archive_error_string(inner));
        goto err_cleanup;
    }

    return inner;

 err_cleanup:
    archive_read_free(inner);
    free(data->buffer);
    free(data);
    return NULL;
}
예제 #12
0
static int copy_to_stream(struct archive *a, FILE * stream)
{
    void *buffer;
    size_t sz_out, sz_in;
    int eof;
    size_t len = EXTRACT_BUFFER_LEN;

    buffer = xmalloc(len);

    while (1) {
        sz_in = read_data(a, buffer, len, &eof);
        if (eof) {
            free(buffer);
            return 0;
        }
        if (sz_in == 0)
            goto err_cleanup;

        /* Now write data to the output stream. */
        sz_out = fwrite(buffer, 1, sz_in, stream);
        if (sz_out < sz_in) {
            opkg_msg(ERROR, "Failed to write data to stream: %s\n",
                     strerror(errno));
            goto err_cleanup;
        }
    }

 err_cleanup:
    free(buffer);
    return -1;
}
예제 #13
0
파일: pkg_depends.c 프로젝트: beyonwiz/opkg
pkg_vec_t *pkg_hash_fetch_conflicts(pkg_t * pkg)
{
    pkg_vec_t *installed_conflicts;
    abstract_pkg_t *ab_pkg;

    /*
     * this is a setup to check for redundant/cyclic dependency checks,
     * which are marked at the abstract_pkg level
     */
    ab_pkg = pkg->parent;
    if (!ab_pkg) {
        opkg_msg(ERROR, "Internal error: %s not in hash table\n", pkg->name);
        return (pkg_vec_t *) NULL;
    }

    installed_conflicts = pkg_vec_alloc();

    __pkg_hash_fetch_conflicts(pkg, installed_conflicts);
    __pkg_hash_fetch_conflictees(pkg, installed_conflicts);

    if (installed_conflicts->len)
        return installed_conflicts;
    pkg_vec_free(installed_conflicts);
    return (pkg_vec_t *) NULL;
}
예제 #14
0
/* Transform all path components of the given entry. This includes hardlink and
 * symlink paths as well as the destination path.
 *
 * Returns 0 on success, 1 where the file does not need to be extracted and <0
 * on error.
 */
static int transform_all_paths(struct archive_entry *entry, const char *dest)
{
    char *path;
    const char *filename;
    int r;

    r = transform_dest_path(entry, dest);
    if (r)
        return r;

    /* Next transform hardlink and symlink destinations. */
    filename = archive_entry_hardlink(entry);
    if (filename) {
        /* Apply the same transform to the hardlink path as was applied
         * to the destination path.
         */
        path = join_paths(dest, filename);
        if (!path) {
            opkg_msg(ERROR, "Not extracting '%s': Hardlink to nowhere.\n",
                     archive_entry_pathname(entry));
            return 1;
        }

        archive_entry_set_hardlink(entry, path);
        free(path);
    }

    /* Currently no transform to perform for symlinks. */

    return 0;
}
예제 #15
0
파일: file_util.c 프로젝트: Droid-MAX/opkg
int file_decompress(const char *in, const char *out)
{
    int r;
    struct opkg_ar *ar;
    FILE *f;

    ar = ar_open_compressed_file(in);
    if (!ar)
        return -1;

    /* Open output file. */
    f = fopen(out, "w");
    if (!f) {
        opkg_msg(ERROR, "Failed to open output file '%s': %s\n", out,
                 strerror(errno));
        r = -1;
        goto cleanup;
    }

    /* Copy decompressed data. */
    r = ar_copy_to_stream(ar, f);
    if (r < 0)
        goto cleanup;

    /* Success */
    r = 0;

 cleanup:
    ar_close(ar);
    if (f)
        fclose(f);

    return r;
}
예제 #16
0
파일: file_util.c 프로젝트: Droid-MAX/opkg
static int copy_file_data(FILE * src_file, FILE * dst_file)
{
    size_t nread, nwritten;
    char buffer[BUFSIZ];

    while (1) {
        nread = fread(buffer, 1, BUFSIZ, src_file);

        if (nread != BUFSIZ && ferror(src_file)) {
            opkg_perror(ERROR, "read");
            return -1;
        }

        /* Check for EOF. */
        if (nread == 0)
            return 0;

        nwritten = fwrite(buffer, 1, nread, dst_file);

        if (nwritten != nread) {
            if (ferror(dst_file))
                opkg_perror(ERROR, "write");
            else
                opkg_msg(ERROR, "Unable to write all data.\n");
            return -1;
        }
    }
}
예제 #17
0
static struct archive *open_compressed_file(const char *filename)
{
    struct archive *ar;
    int r;

    ar = archive_read_new();
    if (!ar) {
        opkg_msg(ERROR,
                 "Failed to create archive object for compressed file.\n");
        return NULL;
    }

    /* Support raw data in gzip compression format. */
    r = archive_read_support_filter_gzip(ar);
    if (r == ARCHIVE_WARN) {
        /* libarchive returns ARCHIVE_WARN if the filter is provided by
         * an external program.
         */
        opkg_msg(INFO, "Gzip support provided by external program.\n");
    } else if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Gzip format not supported: %s\n",
                 archive_error_string(ar));
        goto err_cleanup;
    }

    r = archive_read_support_format_raw(ar);
    if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Raw format not supported: %s\n",
                 archive_error_string(ar));
        goto err_cleanup;
    }

    /* Open input file and prepare for reading. */
    r = archive_read_open_filename(ar, filename, EXTRACT_BUFFER_LEN);
    if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Failed to open compressed file '%s': %s\n", filename,
                 archive_error_string(ar));
        goto err_cleanup;
    }

    return ar;

 err_cleanup:
    archive_read_free(ar);
    return NULL;
}
예제 #18
0
/* Read data from an archive into a buffer. Returns 0 on error as the return
 * value is an unsigned size_t. If an eof pointer is provided, it will be set to
 * 1 on EOF or 0 otherwise.
 */
static size_t read_data(struct archive *a, void *buffer, size_t len, int *eof)
{
    ssize_t r;
    int retries = 0;

    if (eof)
        *eof = 0;

 retry:
    /* Read data into buffer. */
    r = archive_read_data(a, buffer, len);
    if (r > 0) {
        /* We got good data. */
        return (size_t) r;
    }
    switch (r) {
    case 0:
        /* We reached EOF. */
        if (eof)
            *eof = 1;
        return 0;

    case ARCHIVE_WARN:
        /* We don't know the size read so we have to treat this
         * as an error.
         */
        opkg_msg(ERROR, "Warning when reading data from archive: %s\n",
                 archive_error_string(a));
        return 0;

    case ARCHIVE_RETRY:
        opkg_msg(ERROR, "Failed to read data from archive: %s\n",
                 archive_error_string(a));
        if (retries++ < 3) {
            opkg_msg(NOTICE, "Retrying...");
            goto retry;
        } else
            return 0;

    default:
        opkg_msg(ERROR, "Failed to read data from archive: %s\n",
                 archive_error_string(a));
        return 0;
    }
}
예제 #19
0
파일: pkg_src.c 프로젝트: Droid-MAX/opkg
int pkg_src_download(pkg_src_t * src)
{
    int err = 0;
    char *url;
    char *feed;
    const char *url_filename;

    sprintf_alloc(&feed, "%s/%s", opkg_config->lists_dir, src->name);

    url_filename = src->gzip ? "Packages.gz" : "Packages";
    if (src->extra_data)        /* debian style? */
        sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
                      url_filename);
    else
        sprintf_alloc(&url, "%s/%s", src->value, url_filename);

    if (src->gzip) {
        char *cache_location;

        cache_location = opkg_download_cache(url, NULL, NULL);
        if (!cache_location) {
            err = -1;
            goto cleanup;
        }

        err = file_decompress(cache_location, feed);
        free(cache_location);
        if (err) {
            opkg_msg(ERROR, "Couldn't decompress feed for source %s.",
                     src->name);
            goto cleanup;
        }
    } else {
        err = opkg_download(url, feed, NULL, NULL);
        if (err)
            goto cleanup;
    }

    opkg_msg(DEBUG, "Downloaded package list for %s.\n", src->name);

 cleanup:
    free(feed);
    free(url);
    return err;
}
예제 #20
0
파일: pkg_depends.c 프로젝트: beyonwiz/opkg
/**
 * pkg_breaks_reverse_dep returns 1 if pkg does not satisfy the version
 * constraints of the packages which depend upon pkg and otherwise returns 0.
 */
int pkg_breaks_reverse_dep(pkg_t * pkg)
{
    /* We consider only the abstract_pkg_t to which pkg belongs (ie. that which
     * shares its name) not the abstract pkgs which it provides as dependence on
     * a virtual package should never involve a version constraint.
     */
    abstract_pkg_t *rev_dep;
    abstract_pkg_t *apkg = pkg->parent;
    unsigned int i = 0;
    unsigned int j, k, m;
    unsigned int n_rev_deps;

    n_rev_deps = apkg->depended_upon_by->len;
    for (i = 0; i < n_rev_deps; i++) {
        rev_dep = apkg->depended_upon_by->pkgs[i];
        unsigned int npkgs = rev_dep->pkgs->len;

        for (j = 0; j < npkgs; j++) {
            pkg_t *cmp_pkg = rev_dep->pkgs->pkgs[j];
            compound_depend_t *cdeps = cmp_pkg->depends;
            unsigned int ncdeps = cmp_pkg->depends_count;

            /* Only check dependencies of a package which either will be
             * installed or will remain installed.
             */
            if (cmp_pkg->state_want != SW_INSTALL)
                continue;

            /* Find the dependence on apkg. */
            for (k = 0; k < ncdeps; k++) {
                depend_t **deps = cdeps[k].possibilities;
                unsigned int ndeps = cdeps[k].possibility_count;

                /* Skip recommends and suggests. */
                if (cdeps[k].type != PREDEPEND && cdeps[k].type != DEPEND)
                    continue;

                for (m = 0; m < ndeps; m++) {
                    /* Is this the dependence on apkg? */
                    if (deps[m]->pkg != apkg)
                        continue;

                    if (!version_constraints_satisfied(deps[m], pkg)) {
                        opkg_msg(DEBUG,
                                 "Installing %s %s would break reverse dependency from %s.\n",
                                 pkg->name, pkg->version, cmp_pkg->name);
                        return 1;
                    }
                }
            }
        }
    }

    return 0;
}
예제 #21
0
int pkg_extract_data_files_to_dir(pkg_t * pkg, const char *dir)
{
    int r;
    struct opkg_ar *ar;

    ar = ar_open_pkg_data_archive(pkg->local_filename);
    if (!ar) {
        opkg_msg(ERROR, "Failed to extract data.tar.gz from package '%s'.\n",
                 pkg->local_filename);
        return -1;
    }

    r = ar_extract_all(ar, dir);
    if (r < 0)
        opkg_msg(ERROR, "Failed to extract data files from package '%s'.\n",
                 pkg->local_filename);

    ar_close(ar);
    return r;
}
예제 #22
0
int pkg_extract_control_file_to_stream(pkg_t * pkg, FILE * stream)
{
    int r;
    struct opkg_ar *ar;

    ar = ar_open_pkg_control_archive(pkg->local_filename);
    if (!ar) {
        opkg_msg(ERROR, "Failed to extract control.tar.gz from package '%s'.\n",
                 pkg->local_filename);
        return -1;
    }

    r = ar_extract_file_to_stream(ar, "control", stream);
    if (r < 0)
        opkg_msg(ERROR, "Failed to extract control file from package '%s'.\n",
                 pkg->local_filename);

    ar_close(ar);
    return r;
}
예제 #23
0
파일: pkg_src.c 프로젝트: Droid-MAX/opkg
int pkg_src_verify(pkg_src_t * src)
{
    int err = 0;
    char *feed;
    char *sigfile;
    const char *sigext;

    if (strcmp(opkg_config->signature_type, "gpg-asc") == 0)
        sigext = "asc";
    else
        sigext = "sig";

    sprintf_alloc(&feed, "%s/%s", opkg_config->lists_dir, src->name);
    sprintf_alloc(&sigfile, "%s.%s", feed, sigext);

    if (!file_exists(sigfile)) {
        opkg_msg(ERROR,
                 "Signature file is missing for %s. "
                 "Perhaps you need to run 'opkg update'?\n", src->name);
        err = -1;
        goto cleanup;
    }

    err = opkg_verify_signature(feed, sigfile);
    if (err) {
        opkg_msg(ERROR, "Signature verification failed for %s.\n", src->name);
        goto cleanup;
    }

    opkg_msg(DEBUG, "Signature verification passed for %s.\n", src->name);

 cleanup:
    if (err) {
        /* Remove incorrect files. */
        unlink(feed);
        unlink(sigfile);
    }
    free(sigfile);
    free(feed);
    return err;
}
예제 #24
0
/* Like system(3), but with error messages printed if the fork fails
   or if the child process dies due to an uncaught signal. Also, the
   return value is a bit simpler:

   -1 if there was any problem
   Otherwise, the 8-bit return value of the program ala WEXITSTATUS
   as defined in <sys/wait.h>.
*/
int
xsystem(const char *argv[])
{
	int status;
	pid_t pid;

	pid = vfork();

	switch (pid) {
	case -1:
		opkg_perror(ERROR, "%s: vfork", argv[0]);
		return -1;
	case 0:
		/* child */
		execvp(argv[0], (char*const*)argv);
		_exit(-1);
	default:
		/* parent */
		break;
	}

	if (waitpid(pid, &status, 0) == -1) {
		opkg_perror(ERROR, "%s: waitpid", argv[0]);
		return -1;
	}

	if (WIFSIGNALED(status)) {
		opkg_msg(ERROR, "%s: Child killed by signal %d.\n",
			argv[0], WTERMSIG(status));
		return -1;
	}

	if (!WIFEXITED(status)) {
		/* shouldn't happen */
		opkg_msg(ERROR, "%s: Your system is broken: got status %d "
			"from waitpid.\n", argv[0], status);
		return -1;
	}

	return WEXITSTATUS(status);
}
예제 #25
0
/* Read a header from the given archive object and handle all possible outcomes.
 * The returned pointer is managed by libarchive and should not be freed by the
 * caller.
 *
 * If the caller needs to know whether EOF was hit without an error, they can
 * pass an eof pointer which will be set to 1 in this case or 0 otherwise.
 */
static struct archive_entry *read_header(struct archive *ar, int *eof)
{
    struct archive_entry *entry;
    int r;
    int retries = 0;

    if (eof)
        *eof = 0;

 retry:
    r = archive_read_next_header(ar, &entry);
    switch (r) {
    case ARCHIVE_OK:
        break;

    case ARCHIVE_WARN:
        opkg_msg(NOTICE, "Warning when reading ar archive header: %s\n",
                 archive_error_string(ar));
        break;

    case ARCHIVE_EOF:
        if (eof)
            *eof = 1;
        return NULL;

    case ARCHIVE_RETRY:
        opkg_msg(ERROR, "Failed to read archive header: %s\n",
                 archive_error_string(ar));
        if (retries++ < 3)
            goto retry;
        else
            return NULL;

    default:
        opkg_msg(ERROR, "Failed to read archive header: %s\n",
                 archive_error_string(ar));
        return NULL;
    }

    return entry;
}
예제 #26
0
/*
 * Downloads file from url, installs in package database, return package name.
 */
int
opkg_prepare_url_for_install(const char *url, char **namep)
{
     int err = 0;
     pkg_t *pkg;

     pkg = pkg_new();

     if (str_starts_with(url, "http://")
	 || str_starts_with(url, "ftp://")) {
	  char *tmp_file;
	  char *file_basec = xstrdup(url);
	  char *file_base = basename(file_basec);

	  sprintf_alloc(&tmp_file, "%s/%s", conf->tmp_dir, file_base);
	  err = opkg_download(url, tmp_file, NULL, NULL, 0);
	  if (err)
	       return err;

	  err = pkg_init_from_file(pkg, tmp_file);
	  if (err)
	       return err;

	  free(tmp_file);
	  free(file_basec);

     } else if (strcmp(&url[strlen(url) - 4], OPKG_PKG_EXTENSION) == 0
                || strcmp(&url[strlen(url) - 4], IPKG_PKG_EXTENSION) == 0
		|| strcmp(&url[strlen(url) - 4], DPKG_PKG_EXTENSION) == 0) {

	  err = pkg_init_from_file(pkg, url);
	  if (err)
	       return err;
	  opkg_msg(DEBUG2, "Package %s provided by hand (%s).\n",
		  pkg->name, pkg->local_filename);
          pkg->provided_by_hand = 1;

     } else {
       pkg_deinit(pkg);
       free(pkg);
       return 0;
     }

     pkg->dest = conf->default_dest;
     pkg->state_want = SW_INSTALL;
     pkg->state_flag |= SF_PREFER;
     hash_insert_pkg(pkg, 1);

     if (namep) {
	  *namep = pkg->name;
     }
     return 0;
}
예제 #27
0
int pkg_extract_data_file_names_to_stream(pkg_t * pkg, FILE * stream)
{
    int r;
    struct opkg_ar *ar;

    ar = ar_open_pkg_data_archive(pkg->local_filename);
    if (!ar) {
        opkg_msg(ERROR, "Failed to extract data.tar.gz from package '%s'.\n",
                 pkg->local_filename);
        return -1;
    }

    r = ar_extract_paths_to_stream(ar, stream);
    if (r < 0)
        opkg_msg(ERROR,
                 "Failed to extract data file names from package '%s'.\n",
                 pkg->local_filename);

    ar_close(ar);
    return r;
}
예제 #28
0
int
file_copy(const char *src, const char *dest)
{
	int err;

	err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS);
	if (err)
		opkg_msg(ERROR, "Failed to copy file %s to %s.\n",
				src, dest);

	return err;
}
예제 #29
0
/*
 * this is an open table keyed by strings
 */
void hash_table_init(const char *name, hash_table_t * hash, int len)
{
    if (hash->entries != NULL) {
        opkg_msg(ERROR, "Internal error: non empty hash table.\n");
        return;
    }

    memset(hash, 0, sizeof(hash_table_t));

    hash->name = name;
    hash->n_buckets = len;
    hash->entries = xcalloc(hash->n_buckets, sizeof(hash_entry_t));
}
예제 #30
0
static struct archive *open_disk(int flags)
{
    struct archive *disk;
    int r;

    disk = archive_write_disk_new();
    if (!disk) {
        opkg_msg(ERROR, "Failed to create disk archive object.\n");
        return NULL;
    }

    r = archive_write_disk_set_options(disk, flags);
    if (r == ARCHIVE_WARN)
        opkg_msg(NOTICE, "Warning when setting disk options: %s\n",
                 archive_error_string(disk));
    else if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Failed to set disk options: %s\n",
                 archive_error_string(disk));
        goto err_cleanup;
    }

    r = archive_write_disk_set_standard_lookup(disk);
    if (r == ARCHIVE_WARN)
        opkg_msg(NOTICE,
                 "Warning when setting user/group lookup functions: %s\n",
                 archive_error_string(disk));
    else if (r != ARCHIVE_OK) {
        opkg_msg(ERROR, "Failed to set user/group lookup functions: %s\n",
                 archive_error_string(disk));
        goto err_cleanup;
    }

    return disk;

 err_cleanup:
    archive_write_free(disk);
    return NULL;
}