2006-03-02 14:06:52 -05:00
|
|
|
/*
|
2011-06-19 00:24:06 -04:00
|
|
|
* be_local.c : backend for the local database
|
2007-11-16 21:18:45 -05:00
|
|
|
*
|
2014-01-01 05:24:48 -05:00
|
|
|
* Copyright (c) 2006-2014 Pacman Development Team <pacman-dev@archlinux.org>
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
|
2007-11-16 21:18:45 -05:00
|
|
|
*
|
2006-03-02 14:06:52 -05:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2007-12-10 23:55:22 -05:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2006-03-02 14:06:52 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
2009-11-14 14:26:37 -05:00
|
|
|
#include <stdint.h> /* intmax_t */
|
2006-03-02 14:06:52 -05:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <limits.h> /* PATH_MAX */
|
2007-03-05 17:13:33 -05:00
|
|
|
|
2012-05-01 04:12:13 -04:00
|
|
|
/* libarchive */
|
|
|
|
#include <archive.h>
|
|
|
|
#include <archive_entry.h>
|
|
|
|
|
2007-03-05 17:13:33 -05:00
|
|
|
/* libalpm */
|
|
|
|
#include "db.h"
|
|
|
|
#include "alpm_list.h"
|
2013-01-28 20:23:25 -05:00
|
|
|
#include "libarchive-compat.h"
|
2006-03-02 14:06:52 -05:00
|
|
|
#include "log.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "alpm.h"
|
2006-10-15 15:31:03 -04:00
|
|
|
#include "handle.h"
|
2006-11-20 04:10:23 -05:00
|
|
|
#include "package.h"
|
2007-11-13 00:01:14 -05:00
|
|
|
#include "deps.h"
|
2012-07-12 16:29:59 -04:00
|
|
|
#include "filelist.h"
|
2006-10-15 15:31:03 -04:00
|
|
|
|
2013-07-16 07:34:54 -04:00
|
|
|
/* local database format version */
|
|
|
|
size_t ALPM_LOCAL_DB_VERSION = 9;
|
|
|
|
|
2011-06-28 23:02:58 -04:00
|
|
|
static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq);
|
|
|
|
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
#define LAZY_LOAD(info, errret) \
|
|
|
|
do { \
|
2011-06-28 23:02:58 -04:00
|
|
|
if(!(pkg->infolevel & info)) { \
|
|
|
|
local_db_read(pkg, info); \
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
|
|
|
/* Cache-specific accessor functions. These implementations allow for lazy
|
|
|
|
* loading by the files backend when a data member is actually needed
|
|
|
|
* rather than loading all pieces of information when the package is first
|
|
|
|
* initialized.
|
|
|
|
*/
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static const char *_cache_get_desc(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
|
|
|
return pkg->desc;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static const char *_cache_get_url(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
|
|
|
return pkg->url;
|
|
|
|
}
|
|
|
|
|
2011-09-07 11:21:47 -04:00
|
|
|
static alpm_time_t _cache_get_builddate(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, 0);
|
|
|
|
return pkg->builddate;
|
|
|
|
}
|
|
|
|
|
2011-09-07 11:21:47 -04:00
|
|
|
static alpm_time_t _cache_get_installdate(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, 0);
|
|
|
|
return pkg->installdate;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static const char *_cache_get_packager(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
|
|
|
return pkg->packager;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static const char *_cache_get_arch(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
|
|
|
return pkg->arch;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static off_t _cache_get_isize(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, -1);
|
|
|
|
return pkg->isize;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_pkgreason_t _cache_get_reason(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, -1);
|
|
|
|
return pkg->reason;
|
|
|
|
}
|
|
|
|
|
2012-02-18 01:31:37 -05:00
|
|
|
static alpm_pkgvalidation_t _cache_get_validation(alpm_pkg_t *pkg)
|
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, -1);
|
|
|
|
return pkg->validation;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_licenses(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
|
|
|
return pkg->licenses;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_groups(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
|
|
|
return pkg->groups;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static int _cache_has_scriptlet(alpm_pkg_t *pkg)
|
2010-12-13 22:00:23 -05:00
|
|
|
{
|
2011-06-28 23:02:58 -04:00
|
|
|
LAZY_LOAD(INFRQ_SCRIPTLET, NULL);
|
2010-12-13 22:00:23 -05:00
|
|
|
return pkg->scriptlet;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_depends(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
2010-10-30 01:35:43 -04:00
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
return pkg->depends;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_optdepends(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
2010-10-30 01:35:43 -04:00
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
return pkg->optdepends;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_conflicts(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
2010-10-30 01:35:43 -04:00
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
return pkg->conflicts;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_provides(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
2010-10-30 01:35:43 -04:00
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
return pkg->provides;
|
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_replaces(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
|
|
|
LAZY_LOAD(INFRQ_DESC, NULL);
|
|
|
|
return pkg->replaces;
|
|
|
|
}
|
|
|
|
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
static alpm_filelist_t *_cache_get_files(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
2011-06-28 23:02:58 -04:00
|
|
|
LAZY_LOAD(INFRQ_FILES, NULL);
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
return &(pkg->files);
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
static alpm_list_t *_cache_get_backup(alpm_pkg_t *pkg)
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
{
|
2011-06-28 23:02:58 -04:00
|
|
|
LAZY_LOAD(INFRQ_FILES, NULL);
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
return pkg->backup;
|
|
|
|
}
|
|
|
|
|
2008-05-11 17:49:01 -04:00
|
|
|
/**
|
|
|
|
* Open a package changelog for reading. Similar to fopen in functionality,
|
|
|
|
* except that the returned 'file stream' is from the database.
|
|
|
|
* @param pkg the package (from db) to read the changelog
|
|
|
|
* @return a 'file stream' to the package changelog
|
|
|
|
*/
|
2011-06-28 09:26:39 -04:00
|
|
|
static void *_cache_changelog_open(alpm_pkg_t *pkg)
|
2008-05-11 17:49:01 -04:00
|
|
|
{
|
2011-08-18 00:25:19 -04:00
|
|
|
alpm_db_t *db = alpm_pkg_get_db(pkg);
|
2011-09-30 12:08:49 -04:00
|
|
|
char *clfile = _alpm_local_db_pkgpath(db, pkg, "changelog");
|
|
|
|
FILE *f = fopen(clfile, "r");
|
|
|
|
free(clfile);
|
|
|
|
return f;
|
2008-05-11 17:49:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read data from an open changelog 'file stream'. Similar to fread in
|
|
|
|
* functionality, this function takes a buffer and amount of data to read.
|
|
|
|
* @param ptr a buffer to fill with raw changelog data
|
|
|
|
* @param size the size of the buffer
|
|
|
|
* @param pkg the package that the changelog is being read from
|
|
|
|
* @param fp a 'file stream' to the package changelog
|
|
|
|
* @return the number of characters read, or 0 if there is no more data
|
|
|
|
*/
|
2010-12-18 09:15:05 -05:00
|
|
|
static size_t _cache_changelog_read(void *ptr, size_t size,
|
2011-09-18 18:07:05 -04:00
|
|
|
const alpm_pkg_t UNUSED *pkg, void *fp)
|
2008-05-11 17:49:01 -04:00
|
|
|
{
|
2011-03-20 20:45:57 -04:00
|
|
|
return fread(ptr, 1, size, (FILE *)fp);
|
2008-05-11 17:49:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Close a package changelog for reading. Similar to fclose in functionality,
|
|
|
|
* except that the 'file stream' is from the database.
|
|
|
|
* @param pkg the package that the changelog was read from
|
|
|
|
* @param fp a 'file stream' to the package changelog
|
|
|
|
* @return whether closing the package changelog stream was successful
|
|
|
|
*/
|
2011-06-28 09:26:39 -04:00
|
|
|
static int _cache_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp)
|
2008-05-11 17:49:01 -04:00
|
|
|
{
|
2011-03-20 20:45:57 -04:00
|
|
|
return fclose((FILE *)fp);
|
2008-05-11 17:49:01 -04:00
|
|
|
}
|
|
|
|
|
2012-05-01 04:12:13 -04:00
|
|
|
/**
|
|
|
|
* Open a package mtree file for reading.
|
|
|
|
* @param pkg the local package to read the changelog of
|
|
|
|
* @return a archive structure for the package mtree file
|
|
|
|
*/
|
|
|
|
static struct archive *_cache_mtree_open(alpm_pkg_t *pkg)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
struct archive *mtree;
|
|
|
|
|
|
|
|
alpm_db_t *db = alpm_pkg_get_db(pkg);
|
|
|
|
char *mtfile = _alpm_local_db_pkgpath(db, pkg, "mtree");
|
|
|
|
|
|
|
|
if(access(mtfile, F_OK) != 0) {
|
|
|
|
/* there is no mtree file for this package */
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((mtree = archive_read_new()) == NULL) {
|
|
|
|
pkg->handle->pm_errno = ALPM_ERR_LIBARCHIVE;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-01-28 22:22:42 -05:00
|
|
|
_alpm_archive_read_support_filter_all(mtree);
|
2012-05-01 04:12:13 -04:00
|
|
|
archive_read_support_format_mtree(mtree);
|
|
|
|
|
2013-01-28 20:23:25 -05:00
|
|
|
if((r = _alpm_archive_read_open_file(mtree, mtfile, ALPM_BUFFER_SIZE))) {
|
2012-05-01 04:12:13 -04:00
|
|
|
_alpm_log(pkg->handle, ALPM_LOG_ERROR, _("error while reading file %s: %s\n"),
|
|
|
|
mtfile, archive_error_string(mtree));
|
|
|
|
pkg->handle->pm_errno = ALPM_ERR_LIBARCHIVE;
|
2013-01-28 20:23:25 -05:00
|
|
|
_alpm_archive_read_free(mtree);
|
2012-05-01 04:12:13 -04:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(mtfile);
|
|
|
|
return mtree;
|
|
|
|
|
|
|
|
error:
|
|
|
|
free(mtfile);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read next entry from a package mtree file.
|
|
|
|
* @param pkg the package that the mtree file is being read from
|
|
|
|
* @param archive the archive structure reading from the mtree file
|
|
|
|
* @param entry an archive_entry to store the entry header information
|
|
|
|
* @return 0 if end of archive is reached, non-zero otherwise.
|
|
|
|
*/
|
|
|
|
static int _cache_mtree_next(const alpm_pkg_t UNUSED *pkg,
|
|
|
|
struct archive *mtree, struct archive_entry **entry)
|
|
|
|
{
|
|
|
|
return archive_read_next_header(mtree, entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Close a package mtree file for reading.
|
|
|
|
* @param pkg the package that the mtree file was read from
|
|
|
|
* @param mtree the archive structure use for reading from the mtree file
|
|
|
|
* @return whether closing the package changelog stream was successful
|
|
|
|
*/
|
|
|
|
static int _cache_mtree_close(const alpm_pkg_t UNUSED *pkg,
|
|
|
|
struct archive *mtree)
|
|
|
|
{
|
2013-01-28 20:23:25 -05:00
|
|
|
return _alpm_archive_read_free(mtree);
|
2012-05-01 04:12:13 -04:00
|
|
|
}
|
|
|
|
|
2011-06-28 23:02:58 -04:00
|
|
|
static int _cache_force_load(alpm_pkg_t *pkg)
|
|
|
|
{
|
|
|
|
return local_db_read(pkg, INFRQ_ALL);
|
|
|
|
}
|
|
|
|
|
2010-10-14 00:09:20 -04:00
|
|
|
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
/** The local database operations struct. Get package fields through
|
|
|
|
* lazy accessor methods that handle any backend loading and caching
|
|
|
|
* logic.
|
|
|
|
*/
|
|
|
|
static struct pkg_operations local_pkg_ops = {
|
|
|
|
.get_desc = _cache_get_desc,
|
|
|
|
.get_url = _cache_get_url,
|
|
|
|
.get_builddate = _cache_get_builddate,
|
|
|
|
.get_installdate = _cache_get_installdate,
|
|
|
|
.get_packager = _cache_get_packager,
|
|
|
|
.get_arch = _cache_get_arch,
|
|
|
|
.get_isize = _cache_get_isize,
|
|
|
|
.get_reason = _cache_get_reason,
|
2012-02-18 01:31:37 -05:00
|
|
|
.get_validation = _cache_get_validation,
|
2010-12-13 22:00:23 -05:00
|
|
|
.has_scriptlet = _cache_has_scriptlet,
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
.get_licenses = _cache_get_licenses,
|
|
|
|
.get_groups = _cache_get_groups,
|
|
|
|
.get_depends = _cache_get_depends,
|
|
|
|
.get_optdepends = _cache_get_optdepends,
|
|
|
|
.get_conflicts = _cache_get_conflicts,
|
|
|
|
.get_provides = _cache_get_provides,
|
|
|
|
.get_replaces = _cache_get_replaces,
|
|
|
|
.get_files = _cache_get_files,
|
|
|
|
.get_backup = _cache_get_backup,
|
2008-05-11 17:49:01 -04:00
|
|
|
|
|
|
|
.changelog_open = _cache_changelog_open,
|
|
|
|
.changelog_read = _cache_changelog_read,
|
|
|
|
.changelog_close = _cache_changelog_close,
|
2011-06-28 23:02:58 -04:00
|
|
|
|
2012-05-01 04:12:13 -04:00
|
|
|
.mtree_open = _cache_mtree_open,
|
|
|
|
.mtree_next = _cache_mtree_next,
|
|
|
|
.mtree_close = _cache_mtree_close,
|
|
|
|
|
2011-06-28 23:02:58 -04:00
|
|
|
.force_load = _cache_force_load,
|
Complete rework of package accessor logic
Hopefully we've finally arrived at package handling nirvana, or at least
this commit will get us a heck of a lot closer. The former method of getting
the depends list for a package was the following:
1. call alpm_pkg_get_depends()
2. this method would check if the package came from the cache
3. if so, ensure our cache level is correct, otherwise call db_load
4. finally return the depends list
Why did this suck? Because getting the depends list from the package
shouldn't care about whether the package was loaded from a file, from the
'package cache', or some other system which we can't even use because the
damn thing is so complicated. It should just return the depends list.
So what does this commit change? It adds a pointer to a struct of function
pointers to every package for all of these 'package operations' as I've
decided to call them (I know, sounds completely straightforward, right?). So
now when we call an alpm_pkg_get-* function, we don't do any of the cache
logic or anything else there- we let the actual backend handle it by
delegating all work to the method at pkg->ops->get_depends.
Now that be_package has achieved equal status with be_files, we can treat
packages from these completely different load points differently. We know a
package loaded from a zip file will have all of its fields populated, so
we can set up all its accessor functions to be direct accessors. On the
other hand, the packages loaded from the local and sync DBs are not always
fully-loaded, so their accessor functions are routed through the same logic
as before.
Net result? More code. However, this code now make it roughly 52 times
easier to open the door to something like a read-only tar.gz database
backend.
Are you still reading? I'm impressed. Looking at the patch will probably be
clearer than this long-winded explanation.
Signed-off-by: Dan McGee <dan@archlinux.org>
[Allan: rebase and adjust]
Signed-off-by: Allan McRae <allan@archlinux.org>
2008-05-11 17:00:33 -04:00
|
|
|
};
|
|
|
|
|
2011-06-28 00:11:43 -04:00
|
|
|
static int checkdbdir(alpm_db_t *db)
|
2010-10-10 23:47:18 -04:00
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
const char *path = _alpm_db_path(db);
|
|
|
|
|
|
|
|
if(stat(path, &buf) != 0) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n",
|
2010-10-10 23:47:18 -04:00
|
|
|
path);
|
|
|
|
if(_alpm_makepath(path) != 0) {
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_SYSTEM, -1);
|
2010-10-10 23:47:18 -04:00
|
|
|
}
|
|
|
|
} else if(!S_ISDIR(buf.st_mode)) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_WARNING, _("removing invalid database: %s\n"), path);
|
2010-10-10 23:47:18 -04:00
|
|
|
if(unlink(path) != 0 || _alpm_makepath(path) != 0) {
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_SYSTEM, -1);
|
2010-10-10 23:47:18 -04:00
|
|
|
}
|
|
|
|
}
|
2011-03-20 20:45:57 -04:00
|
|
|
return 0;
|
2010-10-10 23:47:18 -04:00
|
|
|
}
|
2009-10-09 13:11:27 -04:00
|
|
|
|
2010-10-05 12:44:32 -04:00
|
|
|
static int is_dir(const char *path, struct dirent *entry)
|
|
|
|
{
|
2010-11-16 21:13:36 -05:00
|
|
|
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
|
2011-03-01 14:39:43 -05:00
|
|
|
if(entry->d_type != DT_UNKNOWN) {
|
2011-03-20 20:45:57 -04:00
|
|
|
return (entry->d_type == DT_DIR);
|
2011-03-01 14:39:43 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
char buffer[PATH_MAX];
|
|
|
|
struct stat sbuf;
|
|
|
|
|
|
|
|
snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name);
|
|
|
|
|
2011-04-20 20:45:16 -04:00
|
|
|
if(!stat(buffer, &sbuf)) {
|
2011-03-20 20:45:57 -04:00
|
|
|
return S_ISDIR(sbuf.st_mode);
|
2011-03-01 14:39:43 -05:00
|
|
|
}
|
2010-10-05 12:44:32 -04:00
|
|
|
}
|
|
|
|
|
2011-03-20 20:45:57 -04:00
|
|
|
return 0;
|
2010-10-05 12:44:32 -04:00
|
|
|
}
|
|
|
|
|
2013-07-16 07:34:54 -04:00
|
|
|
static int local_db_add_version(alpm_db_t UNUSED *db, const char *dbpath)
|
|
|
|
{
|
|
|
|
char dbverpath[PATH_MAX];
|
|
|
|
FILE *dbverfile;
|
|
|
|
|
|
|
|
snprintf(dbverpath, PATH_MAX, "%sALPM_DB_VERSION", dbpath);
|
|
|
|
|
|
|
|
dbverfile = fopen(dbverpath, "w");
|
|
|
|
fprintf(dbverfile, "%zu\n", ALPM_LOCAL_DB_VERSION);
|
|
|
|
fclose(dbverfile);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-22 07:12:04 -04:00
|
|
|
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);
|
|
|
|
}
|
2013-07-16 07:34:54 -04:00
|
|
|
local_db_add_version(db, dbpath);
|
2014-09-22 07:12:04 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-06-28 00:11:43 -04:00
|
|
|
static int local_db_validate(alpm_db_t *db)
|
2011-04-20 20:54:01 -04:00
|
|
|
{
|
|
|
|
struct dirent *ent = NULL;
|
|
|
|
const char *dbpath;
|
2013-07-16 07:51:16 -04:00
|
|
|
DIR *dbdir;
|
2013-07-16 07:48:38 -04:00
|
|
|
char dbverpath[PATH_MAX];
|
|
|
|
FILE *dbverfile;
|
2013-07-16 07:51:16 -04:00
|
|
|
int t;
|
|
|
|
size_t version;
|
2011-04-20 20:54:01 -04:00
|
|
|
|
2011-06-07 21:42:15 -04:00
|
|
|
if(db->status & DB_STATUS_VALID) {
|
|
|
|
return 0;
|
|
|
|
}
|
2011-08-17 22:06:04 -04:00
|
|
|
if(db->status & DB_STATUS_INVALID) {
|
|
|
|
return -1;
|
|
|
|
}
|
2011-06-07 21:42:15 -04:00
|
|
|
|
2011-04-20 20:54:01 -04:00
|
|
|
dbpath = _alpm_db_path(db);
|
|
|
|
if(dbpath == NULL) {
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
|
2011-04-20 20:54:01 -04:00
|
|
|
}
|
2013-07-16 07:48:38 -04:00
|
|
|
|
2011-04-20 20:54:01 -04:00
|
|
|
dbdir = opendir(dbpath);
|
|
|
|
if(dbdir == NULL) {
|
|
|
|
if(errno == ENOENT) {
|
2014-09-22 07:12:04 -04:00
|
|
|
/* 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;
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
db->status &= ~DB_STATUS_EXISTS;
|
|
|
|
db->status |= DB_STATUS_MISSING;
|
|
|
|
/* pm_errno is set by local_db_create */
|
|
|
|
return -1;
|
|
|
|
}
|
2011-04-20 20:54:01 -04:00
|
|
|
} else {
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
|
2011-04-20 20:54:01 -04:00
|
|
|
}
|
|
|
|
}
|
2011-08-17 22:06:04 -04:00
|
|
|
db->status |= DB_STATUS_EXISTS;
|
|
|
|
db->status &= ~DB_STATUS_MISSING;
|
2011-04-20 20:54:01 -04:00
|
|
|
|
2013-07-16 07:51:16 -04:00
|
|
|
snprintf(dbverpath, PATH_MAX, "%sALPM_DB_VERSION", dbpath);
|
2013-07-16 07:48:38 -04:00
|
|
|
|
|
|
|
if((dbverfile = fopen(dbverpath, "r")) == NULL) {
|
|
|
|
/* create dbverfile if local database is empty - otherwise version error */
|
|
|
|
while((ent = readdir(dbdir)) != NULL) {
|
|
|
|
const char *name = ent->d_name;
|
|
|
|
if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
goto version_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
local_db_add_version(db, dbpath);
|
|
|
|
goto version_latest;
|
|
|
|
}
|
|
|
|
|
2013-07-16 07:51:16 -04:00
|
|
|
t = fscanf(dbverfile, "%zu", &version);
|
|
|
|
fclose(dbverfile);
|
2011-04-20 20:54:01 -04:00
|
|
|
|
2013-07-16 07:51:16 -04:00
|
|
|
if(t != 1) {
|
|
|
|
goto version_error;
|
|
|
|
}
|
2011-04-20 20:54:01 -04:00
|
|
|
|
2013-07-16 07:51:16 -04:00
|
|
|
if(version != ALPM_LOCAL_DB_VERSION) {
|
|
|
|
goto version_error;
|
2011-04-20 20:54:01 -04:00
|
|
|
}
|
2013-07-16 07:48:38 -04:00
|
|
|
|
|
|
|
version_latest:
|
|
|
|
closedir(dbdir);
|
2011-06-07 21:42:15 -04:00
|
|
|
db->status |= DB_STATUS_VALID;
|
2011-08-17 22:06:04 -04:00
|
|
|
db->status &= ~DB_STATUS_INVALID;
|
2013-07-16 07:48:38 -04:00
|
|
|
return 0;
|
2011-04-20 20:54:01 -04:00
|
|
|
|
2013-07-16 07:48:38 -04:00
|
|
|
version_error:
|
|
|
|
closedir(dbdir);
|
|
|
|
db->status &= ~DB_STATUS_VALID;
|
|
|
|
db->status |= DB_STATUS_INVALID;
|
|
|
|
db->handle->pm_errno = ALPM_ERR_DB_VERSION;
|
|
|
|
return -1;
|
2011-04-20 20:54:01 -04:00
|
|
|
}
|
|
|
|
|
2011-06-28 00:11:43 -04:00
|
|
|
static int local_db_populate(alpm_db_t *db)
|
2006-03-02 14:06:52 -05:00
|
|
|
{
|
2011-02-15 17:56:44 -05:00
|
|
|
size_t est_count;
|
|
|
|
int count = 0;
|
2011-01-24 18:48:54 -05:00
|
|
|
struct stat buf;
|
2006-03-02 14:06:52 -05:00
|
|
|
struct dirent *ent = NULL;
|
2009-09-14 23:44:51 -04:00
|
|
|
const char *dbpath;
|
2009-01-19 14:45:12 -05:00
|
|
|
DIR *dbdir;
|
2006-03-02 14:06:52 -05:00
|
|
|
|
2011-08-17 22:06:04 -04:00
|
|
|
if(db->status & DB_STATUS_INVALID) {
|
|
|
|
RET_ERR(db->handle, ALPM_ERR_DB_INVALID, -1);
|
|
|
|
}
|
2014-09-22 07:12:04 -04:00
|
|
|
if(db->status & DB_STATUS_MISSING) {
|
|
|
|
RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1);
|
|
|
|
}
|
2011-08-17 22:06:04 -04:00
|
|
|
|
2009-09-14 23:44:51 -04:00
|
|
|
dbpath = _alpm_db_path(db);
|
2010-10-20 02:59:34 -04:00
|
|
|
if(dbpath == NULL) {
|
2011-05-02 17:25:47 -04:00
|
|
|
/* pm_errno set in _alpm_db_path() */
|
|
|
|
return -1;
|
2010-10-20 02:59:34 -04:00
|
|
|
}
|
2011-04-20 20:54:01 -04:00
|
|
|
|
2009-09-14 23:44:51 -04:00
|
|
|
dbdir = opendir(dbpath);
|
2009-01-19 14:45:12 -05:00
|
|
|
if(dbdir == NULL) {
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
|
2009-01-19 14:45:12 -05:00
|
|
|
}
|
2011-01-24 18:48:54 -05:00
|
|
|
if(fstat(dirfd(dbdir), &buf) != 0) {
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
|
2011-02-15 17:56:44 -05:00
|
|
|
}
|
2011-08-17 22:06:04 -04:00
|
|
|
db->status |= DB_STATUS_EXISTS;
|
|
|
|
db->status &= ~DB_STATUS_MISSING;
|
2011-02-15 17:56:44 -05:00
|
|
|
if(buf.st_nlink >= 2) {
|
|
|
|
est_count = buf.st_nlink;
|
|
|
|
} else {
|
|
|
|
/* Some filesystems don't subscribe to the two-implicit links school of
|
|
|
|
* thought, e.g. BTRFS, HFS+. See
|
|
|
|
* http://kerneltrap.org/mailarchive/linux-btrfs/2010/1/23/6723483/thread
|
|
|
|
*/
|
|
|
|
est_count = 0;
|
2011-04-02 14:26:27 -04:00
|
|
|
while(readdir(dbdir) != NULL) {
|
2011-02-15 17:56:44 -05:00
|
|
|
est_count++;
|
|
|
|
}
|
|
|
|
rewinddir(dbdir);
|
|
|
|
}
|
|
|
|
if(est_count >= 2) {
|
2012-03-09 14:40:55 -05:00
|
|
|
/* subtract the '.' and '..' pointers to get # of children */
|
2011-02-15 17:56:44 -05:00
|
|
|
est_count -= 2;
|
2011-01-24 18:48:54 -05:00
|
|
|
}
|
2011-01-24 20:49:34 -05:00
|
|
|
|
2012-01-02 14:29:40 -05:00
|
|
|
db->pkgcache = _alpm_pkghash_create(est_count);
|
2011-02-07 17:59:04 -05:00
|
|
|
if(db->pkgcache == NULL){
|
|
|
|
closedir(dbdir);
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_MEMORY, -1);
|
2011-02-07 17:59:04 -05:00
|
|
|
}
|
2011-01-24 20:49:34 -05:00
|
|
|
|
2009-01-19 14:45:12 -05:00
|
|
|
while((ent = readdir(dbdir)) != NULL) {
|
2008-05-12 19:56:14 -04:00
|
|
|
const char *name = ent->d_name;
|
2010-10-09 09:31:29 -04:00
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
alpm_pkg_t *pkg;
|
2008-01-11 01:01:58 -05:00
|
|
|
|
2008-05-12 19:56:14 -04:00
|
|
|
if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2010-10-05 12:44:32 -04:00
|
|
|
if(!is_dir(dbpath, ent)) {
|
2008-05-12 19:56:14 -04:00
|
|
|
continue;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
2007-01-31 01:48:06 -05:00
|
|
|
|
2008-05-13 20:03:54 -04:00
|
|
|
pkg = _alpm_pkg_new();
|
2007-01-31 01:48:06 -05:00
|
|
|
if(pkg == NULL) {
|
2009-01-19 14:45:12 -05:00
|
|
|
closedir(dbdir);
|
2011-07-01 12:01:39 -04:00
|
|
|
RET_ERR(db->handle, ALPM_ERR_MEMORY, -1);
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
2007-06-17 23:25:07 -04:00
|
|
|
/* split the db entry name */
|
2010-10-27 02:41:01 -04:00
|
|
|
if(_alpm_splitname(name, &(pkg->name), &(pkg->version),
|
|
|
|
&(pkg->name_hash)) != 0) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("invalid name for database entry '%s'\n"),
|
2008-05-12 19:56:14 -04:00
|
|
|
name);
|
|
|
|
_alpm_pkg_free(pkg);
|
2007-05-18 02:19:00 -04:00
|
|
|
continue;
|
2007-01-31 01:48:06 -05:00
|
|
|
}
|
2007-03-03 03:13:59 -05:00
|
|
|
|
2009-11-13 10:42:42 -05:00
|
|
|
/* duplicated database entries are not allowed */
|
2011-01-24 20:49:34 -05:00
|
|
|
if(_alpm_pkghash_find(db->pkgcache, pkg->name)) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name);
|
2009-11-13 10:42:42 -05:00
|
|
|
_alpm_pkg_free(pkg);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-04-01 01:37:19 -04:00
|
|
|
pkg->origin = ALPM_PKG_FROM_LOCALDB;
|
Fix double filelist issue when upgrading a package
Due to the way we funk around with package data loading, we had a condition
where the filelist got doubled up because it was loaded twice.
Packages are originally loaded with INFRQ_BASE. In an upgrade/sync, the
package is checked for file conflicts next, leaving us in an "INFRQ_BASE |
INFRQ_FILES" state. Later, when committing a single package, we have an
explicit call to _alpm_local_db_read() with INFRQ_ALL as the level. Because
the package's level did not match this, we skipped over our previous "does
the incoming level match where I'm at" shortcut, and continued to load
things again, because of a lack of fine-grained checking for each of DESC,
FILES, and INSTALL.
The end result is we loaded the filelist twice, causing our remove logic to
iterate twice over the installed files, spewing a bunch of "cannot find file
X" messages.
Fix the problem by doing a bit more bitmasking logic throughout the load
method, and also fix the sanity check at the beginning of the function- this
should *only* be used for local packages as opposed to the "not a package"
check that was there before.
A debug log message was added to upgraderemove as well to match the one
already in the normal remove codepath.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-01-11 19:46:10 -05:00
|
|
|
pkg->origin_data.db = db;
|
|
|
|
pkg->ops = &local_pkg_ops;
|
2011-06-03 13:44:01 -04:00
|
|
|
pkg->handle = db->handle;
|
Fix double filelist issue when upgrading a package
Due to the way we funk around with package data loading, we had a condition
where the filelist got doubled up because it was loaded twice.
Packages are originally loaded with INFRQ_BASE. In an upgrade/sync, the
package is checked for file conflicts next, leaving us in an "INFRQ_BASE |
INFRQ_FILES" state. Later, when committing a single package, we have an
explicit call to _alpm_local_db_read() with INFRQ_ALL as the level. Because
the package's level did not match this, we skipped over our previous "does
the incoming level match where I'm at" shortcut, and continued to load
things again, because of a lack of fine-grained checking for each of DESC,
FILES, and INSTALL.
The end result is we loaded the filelist twice, causing our remove logic to
iterate twice over the installed files, spewing a bunch of "cannot find file
X" messages.
Fix the problem by doing a bit more bitmasking logic throughout the load
method, and also fix the sanity check at the beginning of the function- this
should *only* be used for local packages as opposed to the "not a package"
check that was there before.
A debug log message was added to upgraderemove as well to match the one
already in the normal remove codepath.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-01-11 19:46:10 -05:00
|
|
|
|
2007-03-03 03:13:59 -05:00
|
|
|
/* explicitly read with only 'BASE' data, accessors will handle the rest */
|
2011-06-28 23:02:58 -04:00
|
|
|
if(local_db_read(pkg, INFRQ_BASE) == -1) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("corrupted database entry '%s'\n"), name);
|
2007-04-26 21:08:34 -04:00
|
|
|
_alpm_pkg_free(pkg);
|
2008-05-12 19:56:14 -04:00
|
|
|
continue;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
2010-10-13 04:04:07 -04:00
|
|
|
|
2008-05-12 19:56:14 -04:00
|
|
|
/* add to the collection */
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n",
|
2008-05-12 19:56:14 -04:00
|
|
|
pkg->name, db->treename);
|
2011-01-24 20:49:34 -05:00
|
|
|
db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg);
|
2008-05-12 19:56:14 -04:00
|
|
|
count++;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
2009-01-19 14:45:12 -05:00
|
|
|
closedir(dbdir);
|
2011-01-24 20:49:34 -05:00
|
|
|
if(count > 0) {
|
|
|
|
db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp);
|
|
|
|
}
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n",
|
2011-05-02 18:25:45 -04:00
|
|
|
count, db->treename);
|
|
|
|
|
2011-03-20 20:45:57 -04:00
|
|
|
return count;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
2010-10-10 23:47:18 -04:00
|
|
|
/* Note: the return value must be freed by the caller */
|
2011-11-22 20:09:58 -05:00
|
|
|
char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info,
|
|
|
|
const char *filename)
|
2010-10-10 23:47:18 -04:00
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
char *pkgpath;
|
|
|
|
const char *dbpath;
|
|
|
|
|
|
|
|
dbpath = _alpm_db_path(db);
|
|
|
|
len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3;
|
2011-09-19 14:43:13 -04:00
|
|
|
len += filename ? strlen(filename) : 0;
|
2011-07-01 12:01:39 -04:00
|
|
|
MALLOC(pkgpath, len, RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL));
|
2011-09-19 14:43:13 -04:00
|
|
|
sprintf(pkgpath, "%s%s-%s/%s", dbpath, info->name, info->version,
|
|
|
|
filename ? filename : "");
|
2011-03-20 20:45:57 -04:00
|
|
|
return pkgpath;
|
2010-10-10 23:47:18 -04:00
|
|
|
}
|
|
|
|
|
2011-07-03 14:37:04 -04:00
|
|
|
#define READ_NEXT() do { \
|
2014-08-06 16:36:00 -04:00
|
|
|
if(safe_fgets(line, sizeof(line), fp) == NULL && !feof(fp)) goto error; \
|
2012-05-28 17:32:11 -04:00
|
|
|
_alpm_strip_newline(line, 0); \
|
2011-07-03 14:37:04 -04:00
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define READ_AND_STORE(f) do { \
|
|
|
|
READ_NEXT(); \
|
|
|
|
STRDUP(f, line, goto error); \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define READ_AND_STORE_ALL(f) do { \
|
|
|
|
char *linedup; \
|
2014-08-06 16:36:00 -04:00
|
|
|
if(safe_fgets(line, sizeof(line), fp) == NULL) {\
|
2011-09-18 18:32:15 -04:00
|
|
|
if(!feof(fp)) goto error; else break; \
|
|
|
|
} \
|
2012-05-28 17:32:11 -04:00
|
|
|
if(_alpm_strip_newline(line, 0) == 0) break; \
|
2011-07-03 14:37:04 -04:00
|
|
|
STRDUP(linedup, line, goto error); \
|
|
|
|
f = alpm_list_add(f, linedup); \
|
|
|
|
} while(1) /* note the while(1) and not (0) */
|
2010-10-10 23:47:18 -04:00
|
|
|
|
2011-08-09 02:00:16 -04:00
|
|
|
#define READ_AND_SPLITDEP(f) do { \
|
2014-08-06 16:36:00 -04:00
|
|
|
if(safe_fgets(line, sizeof(line), fp) == NULL) {\
|
2011-09-18 18:32:15 -04:00
|
|
|
if(!feof(fp)) goto error; else break; \
|
|
|
|
} \
|
2012-05-28 17:32:11 -04:00
|
|
|
if(_alpm_strip_newline(line, 0) == 0) break; \
|
2014-09-15 12:06:47 -04:00
|
|
|
f = alpm_list_add(f, alpm_dep_from_string(line)); \
|
2011-08-09 02:00:16 -04:00
|
|
|
} while(1) /* note the while(1) and not (0) */
|
|
|
|
|
2011-06-28 23:02:58 -04:00
|
|
|
static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
|
2006-03-02 14:06:52 -05:00
|
|
|
{
|
|
|
|
FILE *fp = NULL;
|
2010-07-07 18:12:42 -04:00
|
|
|
char line[1024];
|
2011-06-28 23:02:58 -04:00
|
|
|
alpm_db_t *db = info->origin_data.db;
|
2006-11-01 01:30:47 -05:00
|
|
|
|
2007-03-11 23:02:57 -04:00
|
|
|
/* bitmask logic here:
|
|
|
|
* infolevel: 00001111
|
|
|
|
* inforeq: 00010100
|
|
|
|
* & result: 00000100
|
|
|
|
* == to inforeq? nope, we need to load more info. */
|
|
|
|
if((info->infolevel & inforeq) == inforeq) {
|
Fix double filelist issue when upgrading a package
Due to the way we funk around with package data loading, we had a condition
where the filelist got doubled up because it was loaded twice.
Packages are originally loaded with INFRQ_BASE. In an upgrade/sync, the
package is checked for file conflicts next, leaving us in an "INFRQ_BASE |
INFRQ_FILES" state. Later, when committing a single package, we have an
explicit call to _alpm_local_db_read() with INFRQ_ALL as the level. Because
the package's level did not match this, we skipped over our previous "does
the incoming level match where I'm at" shortcut, and continued to load
things again, because of a lack of fine-grained checking for each of DESC,
FILES, and INSTALL.
The end result is we loaded the filelist twice, causing our remove logic to
iterate twice over the installed files, spewing a bunch of "cannot find file
X" messages.
Fix the problem by doing a bit more bitmasking logic throughout the load
method, and also fix the sanity check at the beginning of the function- this
should *only* be used for local packages as opposed to the "not a package"
check that was there before.
A debug log message was added to upgraderemove as well to match the one
already in the normal remove codepath.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-01-11 19:46:10 -05:00
|
|
|
/* already loaded all of this info, do nothing */
|
2011-03-20 20:45:57 -04:00
|
|
|
return 0;
|
2006-11-22 04:03:41 -05:00
|
|
|
}
|
2011-07-29 18:03:07 -04:00
|
|
|
|
|
|
|
if(info->infolevel & INFRQ_ERROR) {
|
|
|
|
/* We've encountered an error loading this package before. Don't attempt
|
|
|
|
* repeated reloads, just give up. */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-03-09 14:40:55 -05:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_FUNCTION,
|
|
|
|
"loading package data for %s : level=0x%x\n",
|
2008-01-01 20:57:02 -05:00
|
|
|
info->name, inforeq);
|
2006-11-01 01:30:47 -05:00
|
|
|
|
2011-09-19 14:43:13 -04:00
|
|
|
/* clear out 'line', to be certain - and to make valgrind happy */
|
|
|
|
memset(line, 0, sizeof(line));
|
2006-03-02 14:06:52 -05:00
|
|
|
|
|
|
|
/* DESC */
|
Fix double filelist issue when upgrading a package
Due to the way we funk around with package data loading, we had a condition
where the filelist got doubled up because it was loaded twice.
Packages are originally loaded with INFRQ_BASE. In an upgrade/sync, the
package is checked for file conflicts next, leaving us in an "INFRQ_BASE |
INFRQ_FILES" state. Later, when committing a single package, we have an
explicit call to _alpm_local_db_read() with INFRQ_ALL as the level. Because
the package's level did not match this, we skipped over our previous "does
the incoming level match where I'm at" shortcut, and continued to load
things again, because of a lack of fine-grained checking for each of DESC,
FILES, and INSTALL.
The end result is we loaded the filelist twice, causing our remove logic to
iterate twice over the installed files, spewing a bunch of "cannot find file
X" messages.
Fix the problem by doing a bit more bitmasking logic throughout the load
method, and also fix the sanity check at the beginning of the function- this
should *only* be used for local packages as opposed to the "not a package"
check that was there before.
A debug log message was added to upgraderemove as well to match the one
already in the normal remove codepath.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-01-11 19:46:10 -05:00
|
|
|
if(inforeq & INFRQ_DESC && !(info->infolevel & INFRQ_DESC)) {
|
2011-09-28 05:43:23 -04:00
|
|
|
char *path = _alpm_local_db_pkgpath(db, info, "desc");
|
2011-09-19 14:43:13 -04:00
|
|
|
if(!path || (fp = fopen(path, "r")) == NULL) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2006-03-02 14:06:52 -05:00
|
|
|
goto error;
|
|
|
|
}
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2006-03-02 14:06:52 -05:00
|
|
|
while(!feof(fp)) {
|
2014-08-06 16:36:00 -04:00
|
|
|
if(safe_fgets(line, sizeof(line), fp) == NULL && !feof(fp)) {
|
2011-08-28 23:20:41 -04:00
|
|
|
goto error;
|
|
|
|
}
|
2012-05-28 17:32:11 -04:00
|
|
|
if(_alpm_strip_newline(line, 0) == 0) {
|
2011-08-28 23:20:41 -04:00
|
|
|
/* length of stripped line was zero */
|
|
|
|
continue;
|
|
|
|
}
|
2008-05-03 13:59:11 -04:00
|
|
|
if(strcmp(line, "%NAME%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_NEXT();
|
|
|
|
if(strcmp(line, info->name) != 0) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: name "
|
2008-05-03 13:59:11 -04:00
|
|
|
"mismatch on package %s\n"), db->treename, info->name);
|
|
|
|
}
|
|
|
|
} else if(strcmp(line, "%VERSION%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_NEXT();
|
|
|
|
if(strcmp(line, info->version) != 0) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: version "
|
2008-05-03 13:59:11 -04:00
|
|
|
"mismatch on package %s\n"), db->treename, info->name);
|
|
|
|
}
|
|
|
|
} else if(strcmp(line, "%DESC%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_AND_STORE(info->desc);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%GROUPS%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_AND_STORE_ALL(info->groups);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%URL%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_AND_STORE(info->url);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%LICENSE%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_AND_STORE_ALL(info->licenses);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%ARCH%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_AND_STORE(info->arch);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%BUILDDATE%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_NEXT();
|
2011-01-07 21:35:43 -05:00
|
|
|
info->builddate = _alpm_parsedate(line);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%INSTALLDATE%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_NEXT();
|
2011-01-07 21:35:43 -05:00
|
|
|
info->installdate = _alpm_parsedate(line);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%PACKAGER%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_AND_STORE(info->packager);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%REASON%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_NEXT();
|
2011-08-29 13:12:54 -04:00
|
|
|
info->reason = (alpm_pkgreason_t)atoi(line);
|
2012-02-18 01:31:37 -05:00
|
|
|
} else if(strcmp(line, "%VALIDATION%") == 0) {
|
|
|
|
alpm_list_t *i, *v = NULL;
|
|
|
|
READ_AND_STORE_ALL(v);
|
|
|
|
for(i = v; i; i = alpm_list_next(i))
|
|
|
|
{
|
|
|
|
if(strcmp(i->data, "none") == 0) {
|
|
|
|
info->validation |= ALPM_PKG_VALIDATION_NONE;
|
|
|
|
} else if(strcmp(i->data, "md5") == 0) {
|
|
|
|
info->validation |= ALPM_PKG_VALIDATION_MD5SUM;
|
|
|
|
} else if(strcmp(i->data, "sha256") == 0) {
|
|
|
|
info->validation |= ALPM_PKG_VALIDATION_SHA256SUM;
|
|
|
|
} else if(strcmp(i->data, "pgp") == 0) {
|
|
|
|
info->validation |= ALPM_PKG_VALIDATION_SIGNATURE;
|
|
|
|
} else {
|
|
|
|
_alpm_log(db->handle, ALPM_LOG_WARNING,
|
|
|
|
_("unknown validation type for package %s: %s\n"),
|
|
|
|
info->name, (const char *)i->data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FREELIST(v);
|
2010-10-11 01:06:10 -04:00
|
|
|
} else if(strcmp(line, "%SIZE%") == 0) {
|
2011-07-03 14:37:04 -04:00
|
|
|
READ_NEXT();
|
2011-09-02 20:26:07 -04:00
|
|
|
info->isize = _alpm_strtoofft(line);
|
2008-01-11 01:01:58 -05:00
|
|
|
} else if(strcmp(line, "%REPLACES%") == 0) {
|
2011-08-09 02:00:16 -04:00
|
|
|
READ_AND_SPLITDEP(info->replaces);
|
2010-10-30 01:35:43 -04:00
|
|
|
} else if(strcmp(line, "%DEPENDS%") == 0) {
|
2011-08-09 02:00:16 -04:00
|
|
|
READ_AND_SPLITDEP(info->depends);
|
2010-10-30 01:35:43 -04:00
|
|
|
} else if(strcmp(line, "%OPTDEPENDS%") == 0) {
|
2011-07-17 19:54:06 -04:00
|
|
|
READ_AND_SPLITDEP(info->optdepends);
|
2010-10-30 01:35:43 -04:00
|
|
|
} else if(strcmp(line, "%CONFLICTS%") == 0) {
|
2011-08-09 02:00:16 -04:00
|
|
|
READ_AND_SPLITDEP(info->conflicts);
|
2010-10-30 01:35:43 -04:00
|
|
|
} else if(strcmp(line, "%PROVIDES%") == 0) {
|
2011-08-09 02:00:16 -04:00
|
|
|
READ_AND_SPLITDEP(info->provides);
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
fp = NULL;
|
2011-07-29 18:03:07 -04:00
|
|
|
info->infolevel |= INFRQ_DESC;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
2010-10-30 01:35:43 -04:00
|
|
|
/* FILES */
|
Fix double filelist issue when upgrading a package
Due to the way we funk around with package data loading, we had a condition
where the filelist got doubled up because it was loaded twice.
Packages are originally loaded with INFRQ_BASE. In an upgrade/sync, the
package is checked for file conflicts next, leaving us in an "INFRQ_BASE |
INFRQ_FILES" state. Later, when committing a single package, we have an
explicit call to _alpm_local_db_read() with INFRQ_ALL as the level. Because
the package's level did not match this, we skipped over our previous "does
the incoming level match where I'm at" shortcut, and continued to load
things again, because of a lack of fine-grained checking for each of DESC,
FILES, and INSTALL.
The end result is we loaded the filelist twice, causing our remove logic to
iterate twice over the installed files, spewing a bunch of "cannot find file
X" messages.
Fix the problem by doing a bit more bitmasking logic throughout the load
method, and also fix the sanity check at the beginning of the function- this
should *only* be used for local packages as opposed to the "not a package"
check that was there before.
A debug log message was added to upgraderemove as well to match the one
already in the normal remove codepath.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-01-11 19:46:10 -05:00
|
|
|
if(inforeq & INFRQ_FILES && !(info->infolevel & INFRQ_FILES)) {
|
2011-09-28 05:43:23 -04:00
|
|
|
char *path = _alpm_local_db_pkgpath(db, info, "files");
|
2011-09-19 14:43:13 -04:00
|
|
|
if(!path || (fp = fopen(path, "r")) == NULL) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2006-03-02 14:06:52 -05:00
|
|
|
goto error;
|
|
|
|
}
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2014-08-06 16:36:00 -04:00
|
|
|
while(safe_fgets(line, sizeof(line), fp)) {
|
2012-05-28 17:32:11 -04:00
|
|
|
_alpm_strip_newline(line, 0);
|
2010-10-30 01:35:43 -04:00
|
|
|
if(strcmp(line, "%FILES%") == 0) {
|
2011-11-22 20:09:58 -05:00
|
|
|
size_t files_count = 0, files_size = 0, len;
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
alpm_file_t *files = NULL;
|
|
|
|
|
2014-08-06 16:36:00 -04:00
|
|
|
while(safe_fgets(line, sizeof(line), fp) &&
|
2012-05-28 17:32:11 -04:00
|
|
|
(len = _alpm_strip_newline(line, 0))) {
|
2014-02-09 05:28:22 -05:00
|
|
|
if(!_alpm_greedy_grow((void **)&files, &files_size,
|
|
|
|
(files_size ? files_size + sizeof(alpm_file_t) : 8 * sizeof(alpm_file_t)))) {
|
|
|
|
goto error;
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
}
|
2011-11-22 20:09:58 -05:00
|
|
|
/* since we know the length of the file string already,
|
|
|
|
* we can do malloc + memcpy rather than strdup */
|
2012-04-30 00:23:54 -04:00
|
|
|
len += 1;
|
2014-03-08 01:58:30 -05:00
|
|
|
MALLOC(files[files_count].name, len, goto error);
|
2012-04-30 00:23:54 -04:00
|
|
|
memcpy(files[files_count].name, line, len);
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
files_count++;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
/* attempt to hand back any memory we don't need */
|
|
|
|
files = realloc(files, sizeof(alpm_file_t) * files_count);
|
2012-07-12 14:50:56 -04:00
|
|
|
/* make sure the list is sorted */
|
|
|
|
qsort(files, files_count, sizeof(alpm_file_t), _alpm_files_cmp);
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
info->files.count = files_count;
|
|
|
|
info->files.files = files;
|
2010-10-30 01:35:43 -04:00
|
|
|
} else if(strcmp(line, "%BACKUP%") == 0) {
|
2014-08-06 16:36:00 -04:00
|
|
|
while(safe_fgets(line, sizeof(line), fp) && _alpm_strip_newline(line, 0)) {
|
2011-06-28 00:39:43 -04:00
|
|
|
alpm_backup_t *backup;
|
|
|
|
CALLOC(backup, 1, sizeof(alpm_backup_t), goto error);
|
2011-06-16 14:15:11 -04:00
|
|
|
if(_alpm_split_backup(line, &backup)) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
info->backup = alpm_list_add(info->backup, backup);
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
2007-02-28 11:37:24 -05:00
|
|
|
}
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
fp = NULL;
|
2011-07-29 18:03:07 -04:00
|
|
|
info->infolevel |= INFRQ_FILES;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* INSTALL */
|
Fix double filelist issue when upgrading a package
Due to the way we funk around with package data loading, we had a condition
where the filelist got doubled up because it was loaded twice.
Packages are originally loaded with INFRQ_BASE. In an upgrade/sync, the
package is checked for file conflicts next, leaving us in an "INFRQ_BASE |
INFRQ_FILES" state. Later, when committing a single package, we have an
explicit call to _alpm_local_db_read() with INFRQ_ALL as the level. Because
the package's level did not match this, we skipped over our previous "does
the incoming level match where I'm at" shortcut, and continued to load
things again, because of a lack of fine-grained checking for each of DESC,
FILES, and INSTALL.
The end result is we loaded the filelist twice, causing our remove logic to
iterate twice over the installed files, spewing a bunch of "cannot find file
X" messages.
Fix the problem by doing a bit more bitmasking logic throughout the load
method, and also fix the sanity check at the beginning of the function- this
should *only* be used for local packages as opposed to the "not a package"
check that was there before.
A debug log message was added to upgraderemove as well to match the one
already in the normal remove codepath.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-01-11 19:46:10 -05:00
|
|
|
if(inforeq & INFRQ_SCRIPTLET && !(info->infolevel & INFRQ_SCRIPTLET)) {
|
2011-09-28 05:43:23 -04:00
|
|
|
char *path = _alpm_local_db_pkgpath(db, info, "install");
|
2008-06-15 20:15:36 -04:00
|
|
|
if(access(path, F_OK) == 0) {
|
2006-03-02 14:06:52 -05:00
|
|
|
info->scriptlet = 1;
|
|
|
|
}
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2011-07-29 18:03:07 -04:00
|
|
|
info->infolevel |= INFRQ_SCRIPTLET;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
2011-03-20 20:45:57 -04:00
|
|
|
return 0;
|
2006-03-02 14:06:52 -05:00
|
|
|
|
|
|
|
error:
|
2011-07-29 18:03:07 -04:00
|
|
|
info->infolevel |= INFRQ_ERROR;
|
2006-03-02 14:06:52 -05:00
|
|
|
if(fp) {
|
|
|
|
fclose(fp);
|
|
|
|
}
|
2011-03-20 20:45:57 -04:00
|
|
|
return -1;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
int _alpm_local_db_prepare(alpm_db_t *db, alpm_pkg_t *info)
|
2009-01-02 04:12:22 -05:00
|
|
|
{
|
|
|
|
mode_t oldmask;
|
|
|
|
int retval = 0;
|
2011-09-19 14:43:13 -04:00
|
|
|
char *pkgpath;
|
2009-01-02 04:12:22 -05:00
|
|
|
|
2009-01-19 16:54:00 -05:00
|
|
|
if(checkdbdir(db) != 0) {
|
2011-03-20 20:45:57 -04:00
|
|
|
return -1;
|
2009-01-19 16:54:00 -05:00
|
|
|
}
|
2009-01-02 04:12:22 -05:00
|
|
|
|
2009-01-19 16:54:00 -05:00
|
|
|
oldmask = umask(0000);
|
2011-09-28 05:43:23 -04:00
|
|
|
pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
|
2009-01-02 04:12:22 -05:00
|
|
|
|
|
|
|
if((retval = mkdir(pkgpath, 0755)) != 0) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not create directory %s: %s\n"),
|
2009-01-19 16:54:00 -05:00
|
|
|
pkgpath, strerror(errno));
|
2009-01-02 04:12:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
free(pkgpath);
|
|
|
|
umask(oldmask);
|
|
|
|
|
2011-03-20 20:45:57 -04:00
|
|
|
return retval;
|
2009-01-02 04:12:22 -05:00
|
|
|
}
|
|
|
|
|
2012-03-09 15:10:04 -05:00
|
|
|
static void write_deps(FILE *fp, const char *header, alpm_list_t *deplist)
|
|
|
|
{
|
|
|
|
alpm_list_t *lp;
|
|
|
|
if(!deplist) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fputs(header, fp);
|
|
|
|
fputc('\n', fp);
|
|
|
|
for(lp = deplist; lp; lp = lp->next) {
|
|
|
|
char *depstring = alpm_dep_compute_string(lp->data);
|
2012-03-09 15:24:48 -05:00
|
|
|
fputs(depstring, fp);
|
|
|
|
fputc('\n', fp);
|
2012-03-09 15:10:04 -05:00
|
|
|
free(depstring);
|
|
|
|
}
|
|
|
|
fputc('\n', fp);
|
|
|
|
}
|
|
|
|
|
2011-06-28 00:59:04 -04:00
|
|
|
int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
|
2006-03-02 14:06:52 -05:00
|
|
|
{
|
|
|
|
FILE *fp = NULL;
|
|
|
|
mode_t oldmask;
|
2011-09-19 14:43:13 -04:00
|
|
|
alpm_list_t *lp;
|
2006-03-02 14:06:52 -05:00
|
|
|
int retval = 0;
|
|
|
|
|
2011-08-28 20:46:09 -04:00
|
|
|
if(db == NULL || info == NULL || !(db->status & DB_STATUS_LOCAL)) {
|
2011-03-20 20:45:57 -04:00
|
|
|
return -1;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* make sure we have a sane umask */
|
2009-01-02 04:12:22 -05:00
|
|
|
oldmask = umask(0022);
|
2006-03-02 14:06:52 -05:00
|
|
|
|
|
|
|
/* DESC */
|
|
|
|
if(inforeq & INFRQ_DESC) {
|
2011-09-19 14:43:13 -04:00
|
|
|
char *path;
|
2012-04-24 22:01:55 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_DEBUG,
|
|
|
|
"writing %s-%s DESC information back to db\n",
|
2007-07-10 14:24:58 -04:00
|
|
|
info->name, info->version);
|
2011-09-28 05:43:23 -04:00
|
|
|
path = _alpm_local_db_pkgpath(db, info, "desc");
|
2011-09-19 14:43:13 -04:00
|
|
|
if(!path || (fp = fopen(path, "w")) == NULL) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"),
|
2011-06-07 17:13:58 -04:00
|
|
|
path, strerror(errno));
|
2007-01-24 03:51:50 -05:00
|
|
|
retval = -1;
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2006-03-02 14:06:52 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2006-03-02 14:06:52 -05:00
|
|
|
fprintf(fp, "%%NAME%%\n%s\n\n"
|
2007-02-12 20:46:33 -05:00
|
|
|
"%%VERSION%%\n%s\n\n", info->name, info->version);
|
2008-01-11 01:01:58 -05:00
|
|
|
if(info->desc) {
|
2007-02-12 20:46:33 -05:00
|
|
|
fprintf(fp, "%%DESC%%\n"
|
|
|
|
"%s\n\n", info->desc);
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
2010-10-13 07:18:03 -04:00
|
|
|
if(info->url) {
|
|
|
|
fprintf(fp, "%%URL%%\n"
|
|
|
|
"%s\n\n", info->url);
|
|
|
|
}
|
|
|
|
if(info->arch) {
|
|
|
|
fprintf(fp, "%%ARCH%%\n"
|
|
|
|
"%s\n\n", info->arch);
|
|
|
|
}
|
|
|
|
if(info->builddate) {
|
|
|
|
fprintf(fp, "%%BUILDDATE%%\n"
|
2011-09-07 11:21:47 -04:00
|
|
|
"%jd\n\n", (intmax_t)info->builddate);
|
2010-10-13 07:18:03 -04:00
|
|
|
}
|
|
|
|
if(info->installdate) {
|
|
|
|
fprintf(fp, "%%INSTALLDATE%%\n"
|
2011-09-07 11:21:47 -04:00
|
|
|
"%jd\n\n", (intmax_t)info->installdate);
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
2010-10-13 07:18:03 -04:00
|
|
|
if(info->packager) {
|
|
|
|
fprintf(fp, "%%PACKAGER%%\n"
|
|
|
|
"%s\n\n", info->packager);
|
|
|
|
}
|
|
|
|
if(info->isize) {
|
|
|
|
/* only write installed size, csize is irrelevant once installed */
|
|
|
|
fprintf(fp, "%%SIZE%%\n"
|
|
|
|
"%jd\n\n", (intmax_t)info->isize);
|
|
|
|
}
|
|
|
|
if(info->reason) {
|
|
|
|
fprintf(fp, "%%REASON%%\n"
|
|
|
|
"%u\n\n", info->reason);
|
|
|
|
}
|
2012-04-24 22:01:55 -04:00
|
|
|
if(info->groups) {
|
|
|
|
fputs("%GROUPS%\n", fp);
|
|
|
|
for(lp = info->groups; lp; lp = lp->next) {
|
|
|
|
fputs(lp->data, fp);
|
|
|
|
fputc('\n', fp);
|
|
|
|
}
|
|
|
|
fputc('\n', fp);
|
|
|
|
}
|
|
|
|
if(info->licenses) {
|
|
|
|
fputs("%LICENSE%\n", fp);
|
|
|
|
for(lp = info->licenses; lp; lp = lp->next) {
|
|
|
|
fputs(lp->data, fp);
|
|
|
|
fputc('\n', fp);
|
|
|
|
}
|
|
|
|
fputc('\n', fp);
|
|
|
|
}
|
2012-02-18 01:31:37 -05:00
|
|
|
if(info->validation) {
|
|
|
|
fputs("%VALIDATION%\n", fp);
|
|
|
|
if(info->validation & ALPM_PKG_VALIDATION_NONE) {
|
|
|
|
fputs("none\n", fp);
|
|
|
|
}
|
|
|
|
if(info->validation & ALPM_PKG_VALIDATION_MD5SUM) {
|
|
|
|
fputs("md5\n", fp);
|
|
|
|
}
|
|
|
|
if(info->validation & ALPM_PKG_VALIDATION_SHA256SUM) {
|
|
|
|
fputs("sha256\n", fp);
|
|
|
|
}
|
|
|
|
if(info->validation & ALPM_PKG_VALIDATION_SIGNATURE) {
|
|
|
|
fputs("pgp\n", fp);
|
|
|
|
}
|
2012-03-09 15:24:48 -05:00
|
|
|
fputc('\n', fp);
|
2012-02-18 01:31:37 -05:00
|
|
|
}
|
2012-03-09 15:10:04 -05:00
|
|
|
|
|
|
|
write_deps(fp, "%REPLACES%", info->replaces);
|
|
|
|
write_deps(fp, "%DEPENDS%", info->depends);
|
|
|
|
write_deps(fp, "%OPTDEPENDS%", info->optdepends);
|
|
|
|
write_deps(fp, "%CONFLICTS%", info->conflicts);
|
|
|
|
write_deps(fp, "%PROVIDES%", info->provides);
|
2010-10-30 01:35:43 -04:00
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
fp = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FILES */
|
|
|
|
if(inforeq & INFRQ_FILES) {
|
2011-09-19 14:43:13 -04:00
|
|
|
char *path;
|
2012-04-24 22:01:55 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_DEBUG,
|
|
|
|
"writing %s-%s FILES information back to db\n",
|
2010-10-30 01:35:43 -04:00
|
|
|
info->name, info->version);
|
2011-09-28 05:43:23 -04:00
|
|
|
path = _alpm_local_db_pkgpath(db, info, "files");
|
2011-09-19 14:43:13 -04:00
|
|
|
if(!path || (fp = fopen(path, "w")) == NULL) {
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"),
|
2011-06-07 17:13:58 -04:00
|
|
|
path, strerror(errno));
|
2010-10-30 01:35:43 -04:00
|
|
|
retval = -1;
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
2010-10-30 01:35:43 -04:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-09-19 14:43:13 -04:00
|
|
|
free(path);
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
if(info->files.count) {
|
|
|
|
size_t i;
|
2012-03-09 15:24:48 -05:00
|
|
|
fputs("%FILES%\n", fp);
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
for(i = 0; i < info->files.count; i++) {
|
|
|
|
const alpm_file_t *file = info->files.files + i;
|
2012-03-09 15:24:48 -05:00
|
|
|
fputs(file->name, fp);
|
|
|
|
fputc('\n', fp);
|
2010-10-30 01:35:43 -04:00
|
|
|
}
|
2012-03-09 15:24:48 -05:00
|
|
|
fputc('\n', fp);
|
2010-10-30 01:35:43 -04:00
|
|
|
}
|
|
|
|
if(info->backup) {
|
2012-03-09 15:24:48 -05:00
|
|
|
fputs("%BACKUP%\n", fp);
|
2010-10-30 01:35:43 -04:00
|
|
|
for(lp = info->backup; lp; lp = lp->next) {
|
2011-06-16 14:16:49 -04:00
|
|
|
const alpm_backup_t *backup = lp->data;
|
2011-06-16 14:15:11 -04:00
|
|
|
fprintf(fp, "%s\t%s\n", backup->name, backup->hash);
|
2010-10-30 01:35:43 -04:00
|
|
|
}
|
2012-03-09 15:24:48 -05:00
|
|
|
fputc('\n', fp);
|
2010-10-30 01:35:43 -04:00
|
|
|
}
|
2006-03-02 14:06:52 -05:00
|
|
|
fclose(fp);
|
|
|
|
fp = NULL;
|
|
|
|
}
|
|
|
|
|
2014-01-01 04:40:49 -05:00
|
|
|
/* INSTALL and MTREE */
|
|
|
|
/* nothing needed here (automatically extracted) */
|
2006-03-02 14:06:52 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
umask(oldmask);
|
|
|
|
|
|
|
|
if(fp) {
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
|
2011-03-20 20:45:57 -04:00
|
|
|
return retval;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
2011-06-28 09:26:39 -04:00
|
|
|
int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_t *info)
|
2006-03-02 14:06:52 -05:00
|
|
|
{
|
2008-05-30 02:52:27 -04:00
|
|
|
int ret = 0;
|
2012-01-18 22:43:00 -05:00
|
|
|
DIR *dirp;
|
|
|
|
struct dirent *dp;
|
|
|
|
char *pkgpath;
|
|
|
|
size_t pkgpath_len;
|
2006-03-02 14:06:52 -05:00
|
|
|
|
2012-01-18 22:43:00 -05:00
|
|
|
pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
|
|
|
|
if(!pkgpath) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
pkgpath_len = strlen(pkgpath);
|
|
|
|
|
|
|
|
dirp = opendir(pkgpath);
|
|
|
|
if(!dirp) {
|
2012-11-24 13:15:04 -05:00
|
|
|
free(pkgpath);
|
2012-01-18 22:43:00 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* go through the local DB entry, removing the files within, which we know
|
|
|
|
* are not nested directories of any kind. */
|
|
|
|
for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
|
|
|
|
if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) {
|
|
|
|
char name[PATH_MAX];
|
|
|
|
if(pkgpath_len + strlen(dp->d_name) + 2 > PATH_MAX) {
|
|
|
|
/* file path is too long to remove, hmm. */
|
|
|
|
ret = -1;
|
|
|
|
} else {
|
|
|
|
sprintf(name, "%s/%s", pkgpath, dp->d_name);
|
|
|
|
if(unlink(name)) {
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(dirp);
|
|
|
|
|
|
|
|
/* after removing all enclosed files, we can remove the directory itself. */
|
|
|
|
if(rmdir(pkgpath)) {
|
2008-05-30 02:52:27 -04:00
|
|
|
ret = -1;
|
|
|
|
}
|
2012-01-18 22:43:00 -05:00
|
|
|
free(pkgpath);
|
2011-03-20 20:45:57 -04:00
|
|
|
return ret;
|
2006-03-02 14:06:52 -05:00
|
|
|
}
|
|
|
|
|
2012-02-02 00:45:52 -05:00
|
|
|
int SYMEXPORT alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason)
|
|
|
|
{
|
|
|
|
ASSERT(pkg != NULL, return -1);
|
2012-04-01 01:37:19 -04:00
|
|
|
ASSERT(pkg->origin == ALPM_PKG_FROM_LOCALDB,
|
2012-02-02 00:45:52 -05:00
|
|
|
RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
|
|
|
|
ASSERT(pkg->origin_data.db == pkg->handle->db_local,
|
|
|
|
RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
|
|
|
|
|
|
|
|
_alpm_log(pkg->handle, ALPM_LOG_DEBUG,
|
|
|
|
"setting install reason %u for %s\n", reason, pkg->name);
|
|
|
|
if(alpm_pkg_get_reason(pkg) == reason) {
|
|
|
|
/* we are done */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* set reason (in pkgcache) */
|
|
|
|
pkg->reason = reason;
|
|
|
|
/* write DESC */
|
|
|
|
if(_alpm_local_db_write(pkg->handle->db_local, pkg, INFRQ_DESC)) {
|
|
|
|
RET_ERR(pkg->handle, ALPM_ERR_DB_WRITE, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-10-09 06:16:15 -04:00
|
|
|
struct db_operations local_db_ops = {
|
2011-06-08 00:05:21 -04:00
|
|
|
.validate = local_db_validate,
|
2010-12-13 21:19:32 -05:00
|
|
|
.populate = local_db_populate,
|
2010-10-09 06:16:15 -04:00
|
|
|
.unregister = _alpm_db_unregister,
|
|
|
|
};
|
|
|
|
|
2011-06-28 00:11:43 -04:00
|
|
|
alpm_db_t *_alpm_db_register_local(alpm_handle_t *handle)
|
2010-10-09 06:16:15 -04:00
|
|
|
{
|
2011-06-28 00:11:43 -04:00
|
|
|
alpm_db_t *db;
|
2010-10-09 06:16:15 -04:00
|
|
|
|
2011-07-01 12:01:38 -04:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "registering local database\n");
|
2010-10-09 06:16:15 -04:00
|
|
|
|
|
|
|
db = _alpm_db_new("local", 1);
|
|
|
|
if(db == NULL) {
|
2011-07-01 12:01:39 -04:00
|
|
|
handle->pm_errno = ALPM_ERR_DB_CREATE;
|
2011-06-03 16:24:01 -04:00
|
|
|
return NULL;
|
2010-10-09 06:16:15 -04:00
|
|
|
}
|
2011-03-20 20:56:55 -04:00
|
|
|
db->ops = &local_db_ops;
|
2011-06-03 13:06:25 -04:00
|
|
|
db->handle = handle;
|
2013-03-09 18:28:28 -05:00
|
|
|
db->usage = ALPM_DB_USAGE_ALL;
|
2010-10-09 06:16:15 -04:00
|
|
|
|
2011-04-20 20:54:01 -04:00
|
|
|
if(local_db_validate(db)) {
|
|
|
|
/* pm_errno set in local_db_validate() */
|
|
|
|
_alpm_db_free(db);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-10-09 06:16:15 -04:00
|
|
|
handle->db_local = db;
|
2011-03-20 20:45:57 -04:00
|
|
|
return db;
|
2010-10-09 06:16:15 -04:00
|
|
|
}
|
|
|
|
|
2014-01-22 18:06:11 -05:00
|
|
|
/* vim: set noet: */
|