/** Initialize the transaction. */ int SYMEXPORT alpm_trans_init(alpm_handle_t *handle, alpm_transflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress) { alpm_trans_t *trans; /* Sanity checks */ CHECK_HANDLE(handle, return -1); ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, -1)); /* lock db */ if(!(flags & ALPM_TRANS_FLAG_NOLOCK)) { if(_alpm_handle_lock(handle)) { RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1); } } CALLOC(trans, 1, sizeof(alpm_trans_t), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); trans->flags = flags; trans->cb_event = event; trans->cb_conv = conv; trans->cb_progress = progress; trans->state = STATE_INITIALIZED; handle->trans = trans; return 0; }
/** Update a package database * * An update of the package database \a db will be attempted. Unless * \a force is true, the update will only be performed if the remote * database was modified since the last update. * * This operation requires a database lock, and will return an applicable error * if the lock could not be obtained. * * Example: * @code * alpm_list_t *syncs = alpm_get_syncdbs(); * for(i = syncs; i; i = alpm_list_next(i)) { * alpm_db_t *db = alpm_list_getdata(i); * result = alpm_db_update(0, db); * * if(result < 0) { * printf("Unable to update database: %s\n", alpm_strerrorlast()); * } else if(result == 1) { * printf("Database already up to date\n"); * } else { * printf("Database updated\n"); * } * } * @endcode * * @ingroup alpm_databases * @note After a successful update, the \link alpm_db_get_pkgcache() * package cache \endlink will be invalidated * @param force if true, then forces the update, otherwise update only in case * the database isn't up to date * @param db pointer to the package database to update * @return 0 on success, -1 on error (pm_errno is set accordingly), 1 if up to * to date */ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db) { char *syncpath; alpm_list_t *i; int ret = -1; mode_t oldmask; alpm_handle_t *handle; alpm_siglevel_t level; /* Sanity checks */ ASSERT(db != NULL, return -1); handle = db->handle; handle->pm_errno = 0; ASSERT(db != handle->db_local, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); ASSERT(db->servers != NULL, RET_ERR(handle, ALPM_ERR_SERVER_NONE, -1)); syncpath = get_sync_dir(handle); if(!syncpath) { return -1; } /* make sure we have a sane umask */ oldmask = umask(0022); level = alpm_db_get_siglevel(db); /* attempt to grab a lock */ if(_alpm_handle_lock(handle)) { free(syncpath); umask(oldmask); RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1); } for(i = db->servers; i; i = i->next) { const char *server = i->data; struct dload_payload payload; size_t len; int sig_ret = 0; memset(&payload, 0, sizeof(struct dload_payload)); /* set hard upper limit of 25MiB */ payload.max_size = 25 * 1024 * 1024; /* print server + filename into a buffer */ len = strlen(server) + strlen(db->treename) + 5; /* TODO fix leak syncpath and umask unset */ MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); snprintf(payload.fileurl, len, "%s/%s.db", server, db->treename); payload.handle = handle; payload.force = force; payload.unlink_on_fail = 1; ret = _alpm_download(&payload, syncpath, NULL); _alpm_dload_payload_reset(&payload); if(ret == 0 && (level & ALPM_SIG_DATABASE)) { /* an existing sig file is no good at this point */ char *sigpath = _alpm_sigpath(handle, _alpm_db_path(db)); if(!sigpath) { ret = -1; break; } unlink(sigpath); free(sigpath); /* if we downloaded a DB, we want the .sig from the same server */ /* print server + filename into a buffer (leave space for .sig) */ len = strlen(server) + strlen(db->treename) + 9; /* TODO fix leak syncpath and umask unset */ MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); snprintf(payload.fileurl, len, "%s/%s.db.sig", server, db->treename); payload.handle = handle; payload.force = 1; payload.errors_ok = (level & ALPM_SIG_DATABASE_OPTIONAL); /* set hard upper limit of 16KiB */ payload.max_size = 16 * 1024; sig_ret = _alpm_download(&payload, syncpath, NULL); /* errors_ok suppresses error messages, but not the return code */ sig_ret = payload.errors_ok ? 0 : sig_ret; _alpm_dload_payload_reset(&payload); } if(ret != -1 && sig_ret != -1) { break; } } if(ret == 1) { /* files match, do nothing */ handle->pm_errno = 0; goto cleanup; } else if(ret == -1) { /* pm_errno was set by the download code */ _alpm_log(handle, ALPM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerror(handle->pm_errno)); goto cleanup; } /* Cache needs to be rebuilt */ _alpm_db_free_pkgcache(db); /* clear all status flags regarding validity/existence */ db->status &= ~DB_STATUS_VALID; db->status &= ~DB_STATUS_INVALID; db->status &= ~DB_STATUS_EXISTS; db->status &= ~DB_STATUS_MISSING; if(sync_db_validate(db)) { /* pm_errno should be set */ ret = -1; } cleanup: if(_alpm_handle_unlock(handle)) { _alpm_log(handle, ALPM_LOG_WARNING, _("could not remove lock file %s\n"), handle->lockfile); } free(syncpath); umask(oldmask); return ret; }
/** Update a package database * * An update of the package database \a db will be attempted. Unless * \a force is true, the update will only be performed if the remote * database was modified since the last update. * * This operation requires a database lock, and will return an applicable error * if the lock could not be obtained. * * Example: * @code * alpm_list_t *syncs = alpm_get_syncdbs(); * for(i = syncs; i; i = alpm_list_next(i)) { * alpm_db_t *db = alpm_list_getdata(i); * result = alpm_db_update(0, db); * * if(result < 0) { * printf("Unable to update database: %s\n", alpm_strerrorlast()); * } else if(result == 1) { * printf("Database already up to date\n"); * } else { * printf("Database updated\n"); * } * } * @endcode * * @ingroup alpm_databases * @note After a successful update, the \link alpm_db_get_pkgcache() * package cache \endlink will be invalidated * @param force if true, then forces the update, otherwise update only in case * the database isn't up to date * @param db pointer to the package database to update * @return 0 on success, -1 on error (pm_errno is set accordingly), 1 if up to * to date */ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db) { char *syncpath; const char *dbext; alpm_list_t *i; int updated = 0; int ret = -1; mode_t oldmask; alpm_handle_t *handle; alpm_siglevel_t level; /* Sanity checks */ ASSERT(db != NULL, return -1); handle = db->handle; handle->pm_errno = 0; ASSERT(db != handle->db_local, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); ASSERT(db->servers != NULL, RET_ERR(handle, ALPM_ERR_SERVER_NONE, -1)); if(!(db->usage & ALPM_DB_USAGE_SYNC)) { return 0; } syncpath = get_sync_dir(handle); if(!syncpath) { return -1; } /* force update of invalid databases to fix potential mismatched database/signature */ if(db->status & DB_STATUS_INVALID) { force = 1; } /* make sure we have a sane umask */ oldmask = umask(0022); level = alpm_db_get_siglevel(db); /* attempt to grab a lock */ if(_alpm_handle_lock(handle)) { free(syncpath); umask(oldmask); RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1); } dbext = db->handle->dbext; for(i = db->servers; i; i = i->next) { const char *server = i->data, *final_db_url = NULL; struct dload_payload payload; size_t len; int sig_ret = 0; memset(&payload, 0, sizeof(struct dload_payload)); /* set hard upper limit of 25MiB */ payload.max_size = 25 * 1024 * 1024; /* print server + filename into a buffer */ len = strlen(server) + strlen(db->treename) + strlen(dbext) + 2; MALLOC(payload.fileurl, len, { free(syncpath); umask(oldmask); RET_ERR(handle, ALPM_ERR_MEMORY, -1); } );