core-admin/dom0/aux-tools/qfile-dom0-unpacker.c
Marek Marczykowski d9d7a69c27 dom0+vm: Tools for downloading dom0 update by VM (#198)
Mainly 4 parts:
 - scripts for providing rpmdb and yum repos to VM (choosen by qvm-set-updatevm)
 - VM script for downloading updates (qubes_download_dom0_updates.sh)
 - qfile-dom0-unpacker which receive updates, check signatures and place its in dom0 local yum repo
 - qvm-dom0-upgrade which calls all of above and after all yum gpk-update-viewer

Besides qvm-dom0-upgrade, updates are checked every 6h and user is prompted if
want to download it. At dom0 side gpk-update-icon (disabled yet) should notice
new updates in "local" repo.
2011-06-22 00:44:48 +02:00

87 lines
1.8 KiB
C

#define _GNU_SOURCE
#include <ioall.h>
#include <grp.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <sys/fsuid.h>
#include <gui-fatal.h>
#include <errno.h>
#include "filecopy.h"
int prepare_creds_return_uid(char *username)
{
struct passwd *pwd;
pwd = getpwnam(username);
if (!pwd) {
perror("getpwnam");
exit(1);
}
setenv("HOME", pwd->pw_dir, 1);
setenv("USER", username, 1);
setgid(pwd->pw_gid);
initgroups(username, pwd->pw_gid);
setfsuid(pwd->pw_uid);
return pwd->pw_uid;
}
void wait_for_child(int statusfd)
{
int status;
if (read(statusfd, &status, sizeof status)!=sizeof status)
gui_fatal("File copy error: Internal error reading status from unpacker");
errno = status;
switch (status) {
case LEGAL_EOF: break;
case 0: gui_fatal("File copy: Connection terminated unexpectedly"); break;
case EINVAL: gui_fatal("File copy: Corrupted data from packer"); break;
case EEXIST: gui_fatal("File copy: not overwriting existing file. Clean ~/incoming, and retry copy"); break;
default: gui_fatal("File copy");
}
}
extern void do_unpack(int);
int main(int argc, char ** argv)
{
char *incoming_dir;
int pipefds[2];
int uid;
if (argc < 3) {
fprintf(stderr, "Invalid parameters, usage: %s user dir\n", argv[0]);
exit(1);
}
pipe(pipefds);
uid = prepare_creds_return_uid(argv[1]);
incoming_dir = argv[2];
mkdir(incoming_dir, 0700);
if (chdir(incoming_dir))
gui_fatal("Error chdir to %s", incoming_dir);
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
if (chroot(incoming_dir)) //impossible
gui_fatal("Error chroot to %s", incoming_dir);
setuid(uid);
close(pipefds[0]);
do_unpack(pipefds[1]);
exit(0);
default:;
}
setuid(uid);
close(pipefds[1]);
wait_for_child(pipefds[0]);
return 0;
}