[pacman-dev] [PATCH v2 0/4] Handle .alpm_db_version file
This is v2 of a patchset submitted long ago. It has been rebased and had its memory leaks fixed. With this patchset, pacman will create a local database directory if it is missing (but not the root of the database - i.e. /var/lib/pacman/ still needs to be present). When creating the database or finding an empty local database it will add the .alpm_db_version file and add the version. For existing pacman databases this file is created by the pacman-db-upgrade script. Finally the version of the local database is checked during db validation. Allan McRae (4): Create local database directory if it is missing Add version file when creating local database directory Add version file to empty local database Check the version of the local database during validation lib/libalpm/be_local.c | 119 +++++++++++++++++++++++++++++++++---------------- test/pacman/pmdb.py | 2 + test/pacman/pmtest.py | 3 ++ 3 files changed, 85 insertions(+), 39 deletions(-) -- 2.1.0
This means that a missing local database becomes an error (as it
should be immediately created). Note this only creates the "local"
directory and not its parent, which is checked for during locking.
Signed-off-by: Allan McRae
On 09/22/14 at 10:44pm, Allan McRae wrote:
This means that a missing local database becomes an error (as it should be immediately created). Note this only creates the "local" directory and not its parent, which is checked for during locking.
Signed-off-by: Allan McRae
--- lib/libalpm/be_local.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 9a9bdef..d18e9ad 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -366,6 +366,16 @@ static int is_dir(const char *path, struct dirent *entry) return 0; }
+static int local_db_create(alpm_db_t *db, const char *dbpath) +{ + if(mkdir(dbpath, 0755) != 0) { + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not create directory %s: %s\n"), + dbpath, strerror(errno)); + RET_ERR(db->handle, ALPM_ERR_DB_CREATE, -1); + } + return 0; +} + static int local_db_validate(alpm_db_t *db) { struct dirent *ent = NULL; @@ -387,12 +397,19 @@ static int local_db_validate(alpm_db_t *db) dbdir = opendir(dbpath); if(dbdir == NULL) { if(errno == ENOENT) { - /* database dir doesn't exist yet */ - db->status |= DB_STATUS_VALID; - db->status &= ~DB_STATUS_INVALID; - db->status &= ~DB_STATUS_EXISTS; - db->status |= DB_STATUS_MISSING; - return 0; + /* local database dir doesn't exist yet - create it */ + if(local_db_create(db, dbpath) == 0) { + db->status |= DB_STATUS_VALID; + db->status &= ~DB_STATUS_INVALID; + db->status &= ~DB_STATUS_EXISTS; + db->status |= DB_STATUS_MISSING;
The EXISTS and MISSING operations need to be switched with the ones below.
+ return 0; + } else { + db->status &= DB_STATUS_EXISTS; + db->status |= ~DB_STATUS_MISSING; + /* pm_errno is set by local_db_create */ + return -1; + } } else { RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } @@ -445,7 +462,9 @@ static int local_db_populate(alpm_db_t *db) if(db->status & DB_STATUS_INVALID) { RET_ERR(db->handle, ALPM_ERR_DB_INVALID, -1); } - /* note: DB_STATUS_MISSING is not fatal for local database */ + if(db->status & DB_STATUS_MISSING) { + RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1); + }
dbpath = _alpm_db_path(db); if(dbpath == NULL) { @@ -455,13 +474,6 @@ static int local_db_populate(alpm_db_t *db)
dbdir = opendir(dbpath); if(dbdir == NULL) { - if(errno == ENOENT) { - /* no database existing yet is not an error */ - db->status &= ~DB_STATUS_EXISTS; - db->status |= DB_STATUS_MISSING; - db->pkgcache = _alpm_pkghash_create(0); - return 0; - } RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } if(fstat(dirfd(dbdir), &buf) != 0) { -- 2.1.0
On 22/09/14 23:29, Andrew Gregory wrote:
On 09/22/14 at 10:44pm, Allan McRae wrote:
This means that a missing local database becomes an error (as it should be immediately created). Note this only creates the "local" directory and not its parent, which is checked for during locking.
Signed-off-by: Allan McRae
--- lib/libalpm/be_local.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 9a9bdef..d18e9ad 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -366,6 +366,16 @@ static int is_dir(const char *path, struct dirent *entry) return 0; }
+static int local_db_create(alpm_db_t *db, const char *dbpath) +{ + if(mkdir(dbpath, 0755) != 0) { + _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not create directory %s: %s\n"), + dbpath, strerror(errno)); + RET_ERR(db->handle, ALPM_ERR_DB_CREATE, -1); + } + return 0; +} + static int local_db_validate(alpm_db_t *db) { struct dirent *ent = NULL; @@ -387,12 +397,19 @@ static int local_db_validate(alpm_db_t *db) dbdir = opendir(dbpath); if(dbdir == NULL) { if(errno == ENOENT) { - /* database dir doesn't exist yet */ - db->status |= DB_STATUS_VALID; - db->status &= ~DB_STATUS_INVALID; - db->status &= ~DB_STATUS_EXISTS; - db->status |= DB_STATUS_MISSING; - return 0; + /* local database dir doesn't exist yet - create it */ + if(local_db_create(db, dbpath) == 0) { + db->status |= DB_STATUS_VALID; + db->status &= ~DB_STATUS_INVALID; + db->status &= ~DB_STATUS_EXISTS; + db->status |= DB_STATUS_MISSING;
The EXISTS and MISSING operations need to be switched with the ones below.
Moving the above to below is correct. However, I think the above should be: db->status |= DB_STATUS_EXISTS; db->status &= ~DB_STATUS_MISSING;
+ return 0; + } else { + db->status &= DB_STATUS_EXISTS; + db->status |= ~DB_STATUS_MISSING; + /* pm_errno is set by local_db_create */ + return -1; + } } else { RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } @@ -445,7 +462,9 @@ static int local_db_populate(alpm_db_t *db) if(db->status & DB_STATUS_INVALID) { RET_ERR(db->handle, ALPM_ERR_DB_INVALID, -1); } - /* note: DB_STATUS_MISSING is not fatal for local database */ + if(db->status & DB_STATUS_MISSING) { + RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1); + }
dbpath = _alpm_db_path(db); if(dbpath == NULL) { @@ -455,13 +474,6 @@ static int local_db_populate(alpm_db_t *db)
dbdir = opendir(dbpath); if(dbdir == NULL) { - if(errno == ENOENT) { - /* no database existing yet is not an error */ - db->status &= ~DB_STATUS_EXISTS; - db->status |= DB_STATUS_MISSING; - db->pkgcache = _alpm_pkghash_create(0); - return 0; - } RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); } if(fstat(dirfd(dbdir), &buf) != 0) { -- 2.1.0
The version of the local pacman database is stored in its root in the file
.alpm_db_version. The version is starting at 9, corresponding to the
next libalpm library version.
Signed-off-by: Allan McRae
If a user manually creates the local database directory, or has an empty
local database for some other reason, we silently add a version file
Signed-off-by: Allan McRae
When we check the database version directly, there is no longer a
need to scan for depends files.
Signed-off-by: Allan McRae
On 09/22/14 at 10:45pm, Allan McRae wrote:
When we check the database version directly, there is no longer a need to scan for depends files.
Signed-off-by: Allan McRae
--- It is much easier to look at the before and after here instead of the patch directly.
lib/libalpm/be_local.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-)
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 1707a76..2b7260e 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -398,9 +398,11 @@ static int local_db_validate(alpm_db_t *db) { struct dirent *ent = NULL; const char *dbpath; + DIR *dbdir; char dbverpath[PATH_MAX]; FILE *dbverfile; - DIR *dbdir; + int t; + size_t version;
if(db->status & DB_STATUS_VALID) { return 0; @@ -453,26 +455,15 @@ static int local_db_validate(alpm_db_t *db) local_db_add_version(db, dbpath); goto version_latest; } - fclose(dbverfile);
- while((ent = readdir(dbdir)) != NULL) { - const char *name = ent->d_name; - char path[PATH_MAX]; + t = fscanf(dbverfile, "%zu", &version); + (void)t;
- if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { - continue; - } - if(!is_dir(dbpath, ent)) { - continue; - } + fclose(dbverfile);
- snprintf(path, PATH_MAX, "%s%s/depends", dbpath, name); - if(access(path, F_OK) == 0) { - /* we found a depends file- bail */ - goto version_error; - } + if(version != ALPM_LOCAL_DB_VERSION) {
Add a check for t here to make sure fscanf succeeded. If fscanf failed there's no telling what's in version, and you can get rid of the (void)t.
+ goto version_error; } - /* we found no depends file after full scan */
version_latest: closedir(dbdir); -- 2.1.0
On Mon, Sep 22, 2014 at 7:44 AM, Allan McRae
This is v2 of a patchset submitted long ago. It has been rebased and had its memory leaks fixed.
With this patchset, pacman will create a local database directory if it is missing (but not the root of the database - i.e. /var/lib/pacman/ still needs to be present). When creating the database or finding an empty local database it will add the .alpm_db_version file and add the version. For existing pacman databases this file is created by the pacman-db-upgrade script. Finally the version of the local database is checked during db validation.
I'm fine with the idea, but on a more meta level, is there any reason this should be a hidden file? Why not just call it something like DB-VERSION so it is big and obvious? I find the idea of hidden files in non-user home directories less than ideal as it makes investigation that much harder until you remember to do a full `ls -la`. (For example: svn stores its version in the root of the repository in a `format` file, http://serverfault.com/questions/277441/difference-between-the-format-and-db... )
Allan McRae (4): Create local database directory if it is missing Add version file when creating local database directory Add version file to empty local database Check the version of the local database during validation
lib/libalpm/be_local.c | 119 +++++++++++++++++++++++++++++++++---------------- test/pacman/pmdb.py | 2 + test/pacman/pmtest.py | 3 ++ 3 files changed, 85 insertions(+), 39 deletions(-)
-- 2.1.0
On 23/09/14 00:02, Dan McGee wrote:
On Mon, Sep 22, 2014 at 7:44 AM, Allan McRae
wrote: This is v2 of a patchset submitted long ago. It has been rebased and had its memory leaks fixed.
With this patchset, pacman will create a local database directory if it is missing (but not the root of the database - i.e. /var/lib/pacman/ still needs to be present). When creating the database or finding an empty local database it will add the .alpm_db_version file and add the version. For existing pacman databases this file is created by the pacman-db-upgrade script. Finally the version of the local database is checked during db validation.
I'm fine with the idea, but on a more meta level, is there any reason this should be a hidden file? Why not just call it something like DB-VERSION so it is big and obvious? I find the idea of hidden files in non-user home directories less than ideal as it makes investigation that much harder until you remember to do a full `ls -la`.
(For example: svn stores its version in the root of the repository in a `format` file, http://serverfault.com/questions/277441/difference-between-the-format-and-db... )
I'm happy renaming this. I'll use ALPM_DB_VERSION unless someone speaks up.
participants (3)
-
Allan McRae
-
Andrew Gregory
-
Dan McGee