archive: honor username/groupname instead of uid/gid
Take the uid/gid from passwd and group.cute-signatures
parent
43cb554c3f
commit
3062d681f9
|
@ -244,6 +244,7 @@ int main(int argc, char **argv)
|
|||
memset(&dbopts, 0, sizeof(dbopts));
|
||||
list_init(&dbopts.repository_list);
|
||||
umask(0);
|
||||
apk_id_cache_init();
|
||||
|
||||
applet = deduce_applet(argc, argv);
|
||||
num_options = ARRAY_SIZE(generic_options) + 1;
|
||||
|
@ -365,6 +366,7 @@ int main(int argc, char **argv)
|
|||
|
||||
r = applet->main(ctx, &db, argc, argv);
|
||||
apk_db_close(&db);
|
||||
apk_id_cache_free();
|
||||
|
||||
if (r == -EINVAL)
|
||||
return usage(applet);
|
||||
|
|
|
@ -95,4 +95,10 @@ int apk_file_get_info(int atfd, const char *filename, unsigned int flags,
|
|||
int apk_url_download(const char *url, int atfd, const char *file);
|
||||
const char *apk_url_local_file(const char *url);
|
||||
|
||||
void apk_id_cache_init(void);
|
||||
void apk_id_cache_free(void);
|
||||
void apk_id_cache_reset(void);
|
||||
uid_t apk_resolve_uid(const char *username, uid_t default_uid);
|
||||
uid_t apk_resolve_gid(const char *groupname, uid_t default_gid);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -388,7 +388,10 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
|
|||
break;
|
||||
}
|
||||
if (r == 0) {
|
||||
r = fchownat(atfd, fn, ae->uid, ae->gid, atflags);
|
||||
r = fchownat(atfd, fn,
|
||||
apk_resolve_uid(ae->uname, ae->uid),
|
||||
apk_resolve_gid(ae->gname, ae->gid),
|
||||
atflags);
|
||||
if (r < 0) {
|
||||
apk_error("Failed to set ownership on %s: %s",
|
||||
fn, strerror(errno));
|
||||
|
|
126
src/io.c
126
src/io.c
|
@ -15,9 +15,12 @@
|
|||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "apk_defines.h"
|
||||
#include "apk_io.h"
|
||||
#include "apk_hash.h"
|
||||
|
||||
struct apk_fd_istream {
|
||||
struct apk_istream is;
|
||||
|
@ -715,3 +718,126 @@ size_t apk_ostream_write_string(struct apk_ostream *os, const char *string)
|
|||
|
||||
return len;
|
||||
}
|
||||
|
||||
struct cache_item {
|
||||
apk_hash_node hash_node;
|
||||
unsigned int genid;
|
||||
union {
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
unsigned short len;
|
||||
char name[];
|
||||
};
|
||||
|
||||
static apk_blob_t cache_item_get_key(apk_hash_item item)
|
||||
{
|
||||
struct cache_item *ci = (struct cache_item *) item;
|
||||
return APK_BLOB_PTR_LEN(ci->name, ci->len);
|
||||
}
|
||||
|
||||
static const struct apk_hash_ops id_hash_ops = {
|
||||
.node_offset = offsetof(struct cache_item, hash_node),
|
||||
.get_key = cache_item_get_key,
|
||||
.hash_key = apk_blob_hash,
|
||||
.compare = apk_blob_compare,
|
||||
.delete_item = (apk_hash_delete_f) free,
|
||||
};
|
||||
|
||||
static struct cache_item *resolve_cache_item(struct apk_hash *hash, apk_blob_t name)
|
||||
{
|
||||
struct cache_item *ci;
|
||||
unsigned long h;
|
||||
|
||||
h = id_hash_ops.hash_key(name);
|
||||
ci = (struct cache_item *) apk_hash_get_hashed(hash, name, h);
|
||||
if (ci != NULL)
|
||||
return ci;
|
||||
|
||||
ci = calloc(1, sizeof(struct cache_item) + name.len);
|
||||
if (ci == NULL)
|
||||
return NULL;
|
||||
|
||||
ci->len = name.len;
|
||||
memcpy(ci->name, name.ptr, name.len);
|
||||
apk_hash_insert_hashed(hash, ci, h);
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
static unsigned int id_genid = 0;
|
||||
static struct apk_hash uid_cache, gid_cache;
|
||||
|
||||
void apk_id_cache_init(void)
|
||||
{
|
||||
apk_hash_init(&uid_cache, &id_hash_ops, 256);
|
||||
apk_hash_init(&gid_cache, &id_hash_ops, 256);
|
||||
id_genid = 1;
|
||||
}
|
||||
|
||||
void apk_id_cache_free(void)
|
||||
{
|
||||
apk_hash_free(&uid_cache);
|
||||
apk_hash_free(&gid_cache);
|
||||
}
|
||||
|
||||
void apk_id_cache_reset(void)
|
||||
{
|
||||
id_genid++;
|
||||
if (id_genid == 0)
|
||||
id_genid = 1;
|
||||
}
|
||||
|
||||
uid_t apk_resolve_uid(const char *username, uid_t default_uid)
|
||||
{
|
||||
struct cache_item *ci;
|
||||
struct passwd pwent, *pwd;
|
||||
char buf[1024];
|
||||
int r;
|
||||
|
||||
ci = resolve_cache_item(&uid_cache, APK_BLOB_STR(username));
|
||||
if (ci == NULL)
|
||||
return default_uid;
|
||||
|
||||
if (ci->genid != id_genid) {
|
||||
r = getpwnam_r(username, &pwent, buf, sizeof(buf), &pwd);
|
||||
if (pwd != NULL)
|
||||
ci->uid = pwd->pw_uid;
|
||||
else
|
||||
ci->uid = -1;
|
||||
if (r == 0)
|
||||
ci->genid = id_genid;
|
||||
}
|
||||
|
||||
if (ci->uid != -1)
|
||||
return ci->uid;
|
||||
|
||||
return default_uid;
|
||||
}
|
||||
|
||||
uid_t apk_resolve_gid(const char *groupname, uid_t default_gid)
|
||||
{
|
||||
struct cache_item *ci;
|
||||
struct group grent, *grp;
|
||||
char buf[1024];
|
||||
int r;
|
||||
|
||||
ci = resolve_cache_item(&gid_cache, APK_BLOB_STR(groupname));
|
||||
if (ci == NULL)
|
||||
return default_gid;
|
||||
|
||||
if (ci->genid != id_genid) {
|
||||
r = getgrnam_r(groupname, &grent, buf, sizeof(buf), &grp);
|
||||
if (grp != NULL)
|
||||
ci->gid = grp->gr_gid;
|
||||
else
|
||||
ci->gid = -1;
|
||||
if (r == 0)
|
||||
ci->genid = id_genid;
|
||||
}
|
||||
|
||||
if (ci->gid != -1)
|
||||
return ci->gid;
|
||||
|
||||
return default_gid;
|
||||
}
|
||||
|
|
|
@ -910,6 +910,8 @@ int apk_ipkg_run_script(struct apk_installed_package *ipkg, int root_fd,
|
|||
}
|
||||
waitpid(pid, &status, 0);
|
||||
unlinkat(root_fd, fn, 0);
|
||||
apk_id_cache_reset();
|
||||
|
||||
if (WIFEXITED(status))
|
||||
return WEXITSTATUS(status);
|
||||
return -1;
|
||||
|
|
Loading…
Reference in New Issue