19869SCasper.Dik@Sun.COM /* 29869SCasper.Dik@Sun.COM * CDDL HEADER START 39869SCasper.Dik@Sun.COM * 49869SCasper.Dik@Sun.COM * The contents of this file are subject to the terms of the 59869SCasper.Dik@Sun.COM * Common Development and Distribution License (the "License"). 69869SCasper.Dik@Sun.COM * You may not use this file except in compliance with the License. 79869SCasper.Dik@Sun.COM * 89869SCasper.Dik@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99869SCasper.Dik@Sun.COM * or http://www.opensolaris.org/os/licensing. 109869SCasper.Dik@Sun.COM * See the License for the specific language governing permissions 119869SCasper.Dik@Sun.COM * and limitations under the License. 129869SCasper.Dik@Sun.COM * 139869SCasper.Dik@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 149869SCasper.Dik@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159869SCasper.Dik@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 169869SCasper.Dik@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 179869SCasper.Dik@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 189869SCasper.Dik@Sun.COM * 199869SCasper.Dik@Sun.COM * CDDL HEADER END 209869SCasper.Dik@Sun.COM */ 219869SCasper.Dik@Sun.COM 229869SCasper.Dik@Sun.COM /* 23*11770SCasper.Dik@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 249869SCasper.Dik@Sun.COM * Use is subject to license terms. 259869SCasper.Dik@Sun.COM */ 269869SCasper.Dik@Sun.COM 279869SCasper.Dik@Sun.COM #include <pkglib.h> 289869SCasper.Dik@Sun.COM 299869SCasper.Dik@Sun.COM #include <alloca.h> 309869SCasper.Dik@Sun.COM #include <assert.h> 319869SCasper.Dik@Sun.COM #include <door.h> 329869SCasper.Dik@Sun.COM #include <errno.h> 339869SCasper.Dik@Sun.COM #include <fcntl.h> 349869SCasper.Dik@Sun.COM #include <pthread.h> 359869SCasper.Dik@Sun.COM #include <spawn.h> 369869SCasper.Dik@Sun.COM #include <stdio.h> 379869SCasper.Dik@Sun.COM #include <stdlib.h> 389869SCasper.Dik@Sun.COM #include <strings.h> 399869SCasper.Dik@Sun.COM #include <sys/mman.h> 409869SCasper.Dik@Sun.COM #include <sys/param.h> 419869SCasper.Dik@Sun.COM #include <sys/stat.h> 429869SCasper.Dik@Sun.COM #include <sys/wait.h> 439869SCasper.Dik@Sun.COM #include <unistd.h> 449869SCasper.Dik@Sun.COM #include <libintl.h> 45*11770SCasper.Dik@Sun.COM #include <sys/mnttab.h> 46*11770SCasper.Dik@Sun.COM #include <sys/mkdev.h> 479869SCasper.Dik@Sun.COM 489869SCasper.Dik@Sun.COM #define PKGADD_MAX (512 * 1024) 499869SCasper.Dik@Sun.COM 509869SCasper.Dik@Sun.COM #define SADM_DIR "/var/sadm/install" 519869SCasper.Dik@Sun.COM 529869SCasper.Dik@Sun.COM #define PKGSERV_PATH "/usr/sadm/install/bin/pkgserv" 539869SCasper.Dik@Sun.COM 549869SCasper.Dik@Sun.COM #define ERR_PATH_TOO_BIG "alternate root path is too long" 559869SCasper.Dik@Sun.COM #define ERR_OPEN_DOOR "cannot open pkgserv door" 569869SCasper.Dik@Sun.COM #define ERR_START_SERVER "cannot start pkgserv daemon: %s" 579869SCasper.Dik@Sun.COM #define ERR_START_FILTER "cannot enumerate database entries" 58*11770SCasper.Dik@Sun.COM #define ERR_FIND_SADM "cannot find sadm directory" 599869SCasper.Dik@Sun.COM 609869SCasper.Dik@Sun.COM struct pkg_server { 619869SCasper.Dik@Sun.COM FILE *fp; 629869SCasper.Dik@Sun.COM char *curbuf; 639869SCasper.Dik@Sun.COM int buflen; 649869SCasper.Dik@Sun.COM int door; 659869SCasper.Dik@Sun.COM boolean_t onetime; 669869SCasper.Dik@Sun.COM }; 679869SCasper.Dik@Sun.COM 689869SCasper.Dik@Sun.COM static PKGserver current_server; 699869SCasper.Dik@Sun.COM 709869SCasper.Dik@Sun.COM static start_mode_t defmode = INVALID; 719869SCasper.Dik@Sun.COM static boolean_t registered = B_FALSE; 729869SCasper.Dik@Sun.COM static pid_t master_pid = -1; 739869SCasper.Dik@Sun.COM 749869SCasper.Dik@Sun.COM static void 759869SCasper.Dik@Sun.COM pkgfilename(char path[PATH_MAX], const char *root, const char *sadmdir, 769869SCasper.Dik@Sun.COM const char *file) 779869SCasper.Dik@Sun.COM { 789869SCasper.Dik@Sun.COM if (snprintf(path, PATH_MAX, "%s%s/%s", root == NULL ? "" : root, 799869SCasper.Dik@Sun.COM sadmdir == NULL ? SADM_DIR : sadmdir, file) >= PATH_MAX) { 809869SCasper.Dik@Sun.COM progerr(gettext(ERR_PATH_TOO_BIG)); 819869SCasper.Dik@Sun.COM exit(99); 829869SCasper.Dik@Sun.COM } 839869SCasper.Dik@Sun.COM } 849869SCasper.Dik@Sun.COM 859869SCasper.Dik@Sun.COM static void 86*11770SCasper.Dik@Sun.COM free_xmnt(struct extmnttab *xmnt) 87*11770SCasper.Dik@Sun.COM { 88*11770SCasper.Dik@Sun.COM free(xmnt->mnt_special); 89*11770SCasper.Dik@Sun.COM free(xmnt->mnt_mountp); 90*11770SCasper.Dik@Sun.COM free(xmnt->mnt_fstype); 91*11770SCasper.Dik@Sun.COM } 92*11770SCasper.Dik@Sun.COM 93*11770SCasper.Dik@Sun.COM static void 94*11770SCasper.Dik@Sun.COM copy_xmnt(const struct extmnttab *xmnt, struct extmnttab *saved) 95*11770SCasper.Dik@Sun.COM { 96*11770SCasper.Dik@Sun.COM 97*11770SCasper.Dik@Sun.COM free_xmnt(saved); 98*11770SCasper.Dik@Sun.COM 99*11770SCasper.Dik@Sun.COM /* 100*11770SCasper.Dik@Sun.COM * Copy everything and then strdup the strings we later use and NULL 101*11770SCasper.Dik@Sun.COM * the ones we don't. 102*11770SCasper.Dik@Sun.COM */ 103*11770SCasper.Dik@Sun.COM *saved = *xmnt; 104*11770SCasper.Dik@Sun.COM 105*11770SCasper.Dik@Sun.COM if (saved->mnt_special != NULL) 106*11770SCasper.Dik@Sun.COM saved->mnt_special = strdup(saved->mnt_special); 107*11770SCasper.Dik@Sun.COM if (saved->mnt_mountp != NULL) 108*11770SCasper.Dik@Sun.COM saved->mnt_mountp = strdup(saved->mnt_mountp); 109*11770SCasper.Dik@Sun.COM if (saved->mnt_fstype != NULL) 110*11770SCasper.Dik@Sun.COM saved->mnt_fstype = strdup(saved->mnt_fstype); 111*11770SCasper.Dik@Sun.COM 112*11770SCasper.Dik@Sun.COM saved->mnt_mntopts = NULL; 113*11770SCasper.Dik@Sun.COM saved->mnt_time = NULL; 114*11770SCasper.Dik@Sun.COM } 115*11770SCasper.Dik@Sun.COM 116*11770SCasper.Dik@Sun.COM static int 117*11770SCasper.Dik@Sun.COM testdoor(char *path) 118*11770SCasper.Dik@Sun.COM { 119*11770SCasper.Dik@Sun.COM int dir; 120*11770SCasper.Dik@Sun.COM int fd; 121*11770SCasper.Dik@Sun.COM struct door_info di; 122*11770SCasper.Dik@Sun.COM int res; 123*11770SCasper.Dik@Sun.COM 124*11770SCasper.Dik@Sun.COM dir = open(path, O_RDONLY); 125*11770SCasper.Dik@Sun.COM 126*11770SCasper.Dik@Sun.COM if (dir == -1) 127*11770SCasper.Dik@Sun.COM return (-1); 128*11770SCasper.Dik@Sun.COM 129*11770SCasper.Dik@Sun.COM fd = openat(dir, PKGDOOR, O_RDWR); 130*11770SCasper.Dik@Sun.COM (void) close(dir); 131*11770SCasper.Dik@Sun.COM if (fd == -1) 132*11770SCasper.Dik@Sun.COM return (-1); 133*11770SCasper.Dik@Sun.COM 134*11770SCasper.Dik@Sun.COM res = door_info(fd, &di); 135*11770SCasper.Dik@Sun.COM (void) close(fd); 136*11770SCasper.Dik@Sun.COM return (res); 137*11770SCasper.Dik@Sun.COM } 138*11770SCasper.Dik@Sun.COM 139*11770SCasper.Dik@Sun.COM /* 140*11770SCasper.Dik@Sun.COM * We need to make sure that we can locate the pkgserv and the door; 141*11770SCasper.Dik@Sun.COM * lofs mounts makes this more difficult: "nosub" mounts don't propagate 142*11770SCasper.Dik@Sun.COM * the door and doors created in lofs mounts are not propagated back to 143*11770SCasper.Dik@Sun.COM * the original filesystem. 144*11770SCasper.Dik@Sun.COM * Here we peel off the lofs mount points until we're 145*11770SCasper.Dik@Sun.COM * at /var/sadm/install or 146*11770SCasper.Dik@Sun.COM * we find a working door or 147*11770SCasper.Dik@Sun.COM * there's nothing more to peel off. 148*11770SCasper.Dik@Sun.COM * The fullpath parameter is used to return the result (stored in *sadmdir), 149*11770SCasper.Dik@Sun.COM * root is used but returned in the computed sadmdir and so the caller should 150*11770SCasper.Dik@Sun.COM * not use "root" any longer or set it to NULL. 151*11770SCasper.Dik@Sun.COM */ 152*11770SCasper.Dik@Sun.COM static void 153*11770SCasper.Dik@Sun.COM pkgfindrealsadmdir(char fullpath[PATH_MAX], const char *root, 154*11770SCasper.Dik@Sun.COM const char **sadmdir) 155*11770SCasper.Dik@Sun.COM { 156*11770SCasper.Dik@Sun.COM struct stat buf; 157*11770SCasper.Dik@Sun.COM struct extmnttab xmnt; 158*11770SCasper.Dik@Sun.COM FILE *mnttab = NULL; 159*11770SCasper.Dik@Sun.COM char temp[PATH_MAX]; 160*11770SCasper.Dik@Sun.COM struct extmnttab saved = {NULL, NULL, NULL, NULL, NULL, 0, 0}; 161*11770SCasper.Dik@Sun.COM 162*11770SCasper.Dik@Sun.COM if (snprintf(temp, PATH_MAX, "%s%s", 163*11770SCasper.Dik@Sun.COM root == NULL ? "" : root, 164*11770SCasper.Dik@Sun.COM *sadmdir == NULL ? SADM_DIR : *sadmdir) >= PATH_MAX) { 165*11770SCasper.Dik@Sun.COM progerr(gettext(ERR_PATH_TOO_BIG)); 166*11770SCasper.Dik@Sun.COM exit(99); 167*11770SCasper.Dik@Sun.COM } 168*11770SCasper.Dik@Sun.COM 169*11770SCasper.Dik@Sun.COM if (stat(temp, &buf) != 0) { 170*11770SCasper.Dik@Sun.COM progerr(gettext(ERR_FIND_SADM)); 171*11770SCasper.Dik@Sun.COM exit(99); 172*11770SCasper.Dik@Sun.COM } 173*11770SCasper.Dik@Sun.COM 174*11770SCasper.Dik@Sun.COM /* 175*11770SCasper.Dik@Sun.COM * To find the underlying mount point, you will need to 176*11770SCasper.Dik@Sun.COM * search the mnttab and find our mountpoint and the underlying 177*11770SCasper.Dik@Sun.COM * filesystem. 178*11770SCasper.Dik@Sun.COM * To find the mount point: use the longest prefix but limit 179*11770SCasper.Dik@Sun.COM * us to the filesystems with the same major/minor numbers. 180*11770SCasper.Dik@Sun.COM * To find the underlying mount point: find a non-lofs file 181*11770SCasper.Dik@Sun.COM * system or a <mnt> <mnt> entry (fake mountpoint for zones). 182*11770SCasper.Dik@Sun.COM */ 183*11770SCasper.Dik@Sun.COM for (;;) { 184*11770SCasper.Dik@Sun.COM size_t max = 0; 185*11770SCasper.Dik@Sun.COM 186*11770SCasper.Dik@Sun.COM if (realpath(temp, fullpath) == NULL) { 187*11770SCasper.Dik@Sun.COM progerr(gettext(ERR_FIND_SADM)); 188*11770SCasper.Dik@Sun.COM exit(99); 189*11770SCasper.Dik@Sun.COM } 190*11770SCasper.Dik@Sun.COM 191*11770SCasper.Dik@Sun.COM if (strcmp(fullpath, SADM_DIR) == 0) 192*11770SCasper.Dik@Sun.COM break; 193*11770SCasper.Dik@Sun.COM 194*11770SCasper.Dik@Sun.COM if (testdoor(fullpath) == 0) 195*11770SCasper.Dik@Sun.COM break; 196*11770SCasper.Dik@Sun.COM 197*11770SCasper.Dik@Sun.COM if (mnttab == NULL) 198*11770SCasper.Dik@Sun.COM mnttab = fopen(MNTTAB, "r"); 199*11770SCasper.Dik@Sun.COM else 200*11770SCasper.Dik@Sun.COM resetmnttab(mnttab); 201*11770SCasper.Dik@Sun.COM 202*11770SCasper.Dik@Sun.COM while (getextmntent(mnttab, &xmnt, 0) == 0) { 203*11770SCasper.Dik@Sun.COM size_t len; 204*11770SCasper.Dik@Sun.COM 205*11770SCasper.Dik@Sun.COM if (major(buf.st_dev) != xmnt.mnt_major || 206*11770SCasper.Dik@Sun.COM minor(buf.st_dev) != xmnt.mnt_minor) 207*11770SCasper.Dik@Sun.COM continue; 208*11770SCasper.Dik@Sun.COM 209*11770SCasper.Dik@Sun.COM len = strlen(xmnt.mnt_mountp); 210*11770SCasper.Dik@Sun.COM if (len < max) 211*11770SCasper.Dik@Sun.COM continue; 212*11770SCasper.Dik@Sun.COM 213*11770SCasper.Dik@Sun.COM if (strncmp(xmnt.mnt_mountp, fullpath, len) == 0 && 214*11770SCasper.Dik@Sun.COM (len == 1 || fullpath[len] == '/' || 215*11770SCasper.Dik@Sun.COM fullpath[len] == '\0')) { 216*11770SCasper.Dik@Sun.COM max = len; 217*11770SCasper.Dik@Sun.COM copy_xmnt(&xmnt, &saved); 218*11770SCasper.Dik@Sun.COM } 219*11770SCasper.Dik@Sun.COM } 220*11770SCasper.Dik@Sun.COM if (strcmp(saved.mnt_fstype, "lofs") != 0 || 221*11770SCasper.Dik@Sun.COM strcmp(saved.mnt_mountp, saved.mnt_special) == 0) { 222*11770SCasper.Dik@Sun.COM break; 223*11770SCasper.Dik@Sun.COM } 224*11770SCasper.Dik@Sun.COM /* Create a new path in the underlying filesystem. */ 225*11770SCasper.Dik@Sun.COM if (snprintf(temp, PATH_MAX, "%s%s", saved.mnt_special, 226*11770SCasper.Dik@Sun.COM &fullpath[max]) >= PATH_MAX) { 227*11770SCasper.Dik@Sun.COM progerr(gettext(ERR_PATH_TOO_BIG)); 228*11770SCasper.Dik@Sun.COM exit(99); 229*11770SCasper.Dik@Sun.COM } 230*11770SCasper.Dik@Sun.COM } 231*11770SCasper.Dik@Sun.COM 232*11770SCasper.Dik@Sun.COM if (mnttab != NULL) { 233*11770SCasper.Dik@Sun.COM free_xmnt(&saved); 234*11770SCasper.Dik@Sun.COM (void) fclose(mnttab); 235*11770SCasper.Dik@Sun.COM } 236*11770SCasper.Dik@Sun.COM *sadmdir = fullpath; 237*11770SCasper.Dik@Sun.COM } 238*11770SCasper.Dik@Sun.COM 239*11770SCasper.Dik@Sun.COM static void 2409869SCasper.Dik@Sun.COM pkgexit_close(void) 2419869SCasper.Dik@Sun.COM { 2429869SCasper.Dik@Sun.COM if (current_server != NULL) 2439869SCasper.Dik@Sun.COM pkgcloseserver(current_server); 2449869SCasper.Dik@Sun.COM } 2459869SCasper.Dik@Sun.COM 2469869SCasper.Dik@Sun.COM static PKGserver 2479869SCasper.Dik@Sun.COM pkgopenserver_i(const char *root, const char *sadmdir, boolean_t readonly, 2489869SCasper.Dik@Sun.COM start_mode_t mode) 2499869SCasper.Dik@Sun.COM { 2509869SCasper.Dik@Sun.COM PKGserver server; 2519869SCasper.Dik@Sun.COM struct door_info di; 2529869SCasper.Dik@Sun.COM pid_t pid; 2539869SCasper.Dik@Sun.COM int stat; 2549869SCasper.Dik@Sun.COM int first = B_TRUE; 2559869SCasper.Dik@Sun.COM char *cmd[16]; 2569869SCasper.Dik@Sun.COM int args; 2579869SCasper.Dik@Sun.COM char pkgdoor[PATH_MAX]; 258*11770SCasper.Dik@Sun.COM char realsadmdir[PATH_MAX]; 2599869SCasper.Dik@Sun.COM extern char **environ; 2609869SCasper.Dik@Sun.COM char *prog; 2619869SCasper.Dik@Sun.COM char pidbuf[12]; 2629869SCasper.Dik@Sun.COM 2639869SCasper.Dik@Sun.COM if (current_server != NULL) 2649869SCasper.Dik@Sun.COM return (current_server); 2659869SCasper.Dik@Sun.COM 2669869SCasper.Dik@Sun.COM if (!registered) { 2679869SCasper.Dik@Sun.COM registered = B_TRUE; 2689869SCasper.Dik@Sun.COM (void) atexit(pkgexit_close); 2699869SCasper.Dik@Sun.COM } 2709869SCasper.Dik@Sun.COM if (readonly) { 2719869SCasper.Dik@Sun.COM int fd; 2729869SCasper.Dik@Sun.COM 2739869SCasper.Dik@Sun.COM (void) strcpy(pkgdoor, "/tmp/pkgdoor.XXXXXX"); 2749869SCasper.Dik@Sun.COM if ((fd = mkstemp(pkgdoor)) < 0) { 2759869SCasper.Dik@Sun.COM progerr(gettext(ERR_OPEN_DOOR)); 2769869SCasper.Dik@Sun.COM return (NULL); 2779869SCasper.Dik@Sun.COM } 2789869SCasper.Dik@Sun.COM (void) close(fd); 2799869SCasper.Dik@Sun.COM } else { 280*11770SCasper.Dik@Sun.COM pkgfindrealsadmdir(realsadmdir, root, &sadmdir); 281*11770SCasper.Dik@Sun.COM root = NULL; 2829869SCasper.Dik@Sun.COM pkgfilename(pkgdoor, root, sadmdir, PKGDOOR); 2839869SCasper.Dik@Sun.COM } 2849869SCasper.Dik@Sun.COM 2859869SCasper.Dik@Sun.COM server = malloc(sizeof (*server)); 2869869SCasper.Dik@Sun.COM 2879869SCasper.Dik@Sun.COM if (server == NULL) 2889869SCasper.Dik@Sun.COM goto return_null; 2899869SCasper.Dik@Sun.COM 2909869SCasper.Dik@Sun.COM server->fp = NULL; 2919869SCasper.Dik@Sun.COM server->onetime = readonly; 2929869SCasper.Dik@Sun.COM 2939869SCasper.Dik@Sun.COM openserver: 2949869SCasper.Dik@Sun.COM server->door = open(pkgdoor, O_RDWR); 2959869SCasper.Dik@Sun.COM 2969869SCasper.Dik@Sun.COM if (server->door >= 0) { 2979869SCasper.Dik@Sun.COM if (door_info(server->door, &di) == 0 && di.di_target >= 0) { 2989869SCasper.Dik@Sun.COM pkgcmd_t n; 2999869SCasper.Dik@Sun.COM n.cmd = PKG_NOP; 3009869SCasper.Dik@Sun.COM server->buflen = 1024; 3019869SCasper.Dik@Sun.COM server->curbuf = malloc(1024); 3029869SCasper.Dik@Sun.COM if (server->curbuf == NULL || 3039869SCasper.Dik@Sun.COM pkgcmd(server, &n, sizeof (n), NULL, NULL, NULL)) { 3049869SCasper.Dik@Sun.COM pkgcloseserver(server); 3059869SCasper.Dik@Sun.COM return (NULL); 3069869SCasper.Dik@Sun.COM } 3079869SCasper.Dik@Sun.COM return (current_server = server); 3089869SCasper.Dik@Sun.COM } 3099869SCasper.Dik@Sun.COM 3109869SCasper.Dik@Sun.COM (void) close(server->door); 3119869SCasper.Dik@Sun.COM } 3129869SCasper.Dik@Sun.COM 3139869SCasper.Dik@Sun.COM if (!first || mode == NEVER) 3149869SCasper.Dik@Sun.COM goto return_null; 3159869SCasper.Dik@Sun.COM 3169869SCasper.Dik@Sun.COM first = B_FALSE; 3179869SCasper.Dik@Sun.COM 3189869SCasper.Dik@Sun.COM args = 0; 3199869SCasper.Dik@Sun.COM cmd[args++] = strrchr(PKGSERV_PATH, '/') + 1; 3209869SCasper.Dik@Sun.COM if (root != NULL && strcmp(root, "/") != 0) { 3219869SCasper.Dik@Sun.COM cmd[args++] = "-R"; 3229869SCasper.Dik@Sun.COM cmd[args++] = (char *)root; 3239869SCasper.Dik@Sun.COM } 3249869SCasper.Dik@Sun.COM if (sadmdir != NULL && strcmp(sadmdir, SADM_DIR) != 0) { 3259869SCasper.Dik@Sun.COM cmd[args++] = "-d"; 3269869SCasper.Dik@Sun.COM cmd[args++] = (char *)sadmdir; 3279869SCasper.Dik@Sun.COM } 3289869SCasper.Dik@Sun.COM if (readonly) { 3299869SCasper.Dik@Sun.COM cmd[args++] = "-r"; 3309869SCasper.Dik@Sun.COM cmd[args++] = pkgdoor; 3319869SCasper.Dik@Sun.COM } 3329869SCasper.Dik@Sun.COM prog = get_prog_name(); 3339869SCasper.Dik@Sun.COM if (prog != NULL) { 3349869SCasper.Dik@Sun.COM cmd[args++] = "-N"; 3359869SCasper.Dik@Sun.COM cmd[args++] = prog; 3369869SCasper.Dik@Sun.COM } 3379869SCasper.Dik@Sun.COM 3389869SCasper.Dik@Sun.COM switch (mode) { 3399869SCasper.Dik@Sun.COM case FLUSH_LOG: 3409869SCasper.Dik@Sun.COM cmd[args++] = "-e"; 3419869SCasper.Dik@Sun.COM break; 3429869SCasper.Dik@Sun.COM case RUN_ONCE: 3439869SCasper.Dik@Sun.COM cmd[args++] = "-o"; 3449869SCasper.Dik@Sun.COM break; 3459869SCasper.Dik@Sun.COM case PERMANENT: 3469869SCasper.Dik@Sun.COM cmd[args++] = "-p"; 3479869SCasper.Dik@Sun.COM break; 3489869SCasper.Dik@Sun.COM default: 3499869SCasper.Dik@Sun.COM break; 3509869SCasper.Dik@Sun.COM } 3519869SCasper.Dik@Sun.COM 3529869SCasper.Dik@Sun.COM if (master_pid != -1) { 3539869SCasper.Dik@Sun.COM cmd[args++] = "-P"; 3549869SCasper.Dik@Sun.COM (void) snprintf(pidbuf, sizeof (pidbuf), "%d", master_pid); 3559869SCasper.Dik@Sun.COM cmd[args++] = pidbuf; 3569869SCasper.Dik@Sun.COM } 3579869SCasper.Dik@Sun.COM cmd[args++] = NULL; 3589869SCasper.Dik@Sun.COM assert(args <= sizeof (cmd)/sizeof (char *)); 3599869SCasper.Dik@Sun.COM 3609869SCasper.Dik@Sun.COM if (posix_spawn(&pid, PKGSERV_PATH, NULL, NULL, cmd, environ) == 0) { 3619869SCasper.Dik@Sun.COM server->onetime |= mode == RUN_ONCE; 3629869SCasper.Dik@Sun.COM while (wait4(pid, &stat, 0, NULL) != -1) { 3639869SCasper.Dik@Sun.COM if (WIFEXITED(stat)) { 3649869SCasper.Dik@Sun.COM int s = WEXITSTATUS(stat); 3659869SCasper.Dik@Sun.COM if (s == 0 || s == 1) 3669869SCasper.Dik@Sun.COM if (mode == FLUSH_LOG) 3679869SCasper.Dik@Sun.COM goto return_null; 3689869SCasper.Dik@Sun.COM else 3699869SCasper.Dik@Sun.COM goto openserver; 3709869SCasper.Dik@Sun.COM if (s == 2) 3719869SCasper.Dik@Sun.COM goto return_null; 3729869SCasper.Dik@Sun.COM break; 3739869SCasper.Dik@Sun.COM } else if (WIFSIGNALED(stat)) { 3749869SCasper.Dik@Sun.COM break; 3759869SCasper.Dik@Sun.COM } 3769869SCasper.Dik@Sun.COM } 3779869SCasper.Dik@Sun.COM } 3789869SCasper.Dik@Sun.COM 3799869SCasper.Dik@Sun.COM progerr(gettext(ERR_START_SERVER), strerror(errno)); 3809869SCasper.Dik@Sun.COM 3819869SCasper.Dik@Sun.COM return_null: 3829869SCasper.Dik@Sun.COM if (readonly) 3839869SCasper.Dik@Sun.COM (void) unlink(pkgdoor); 3849869SCasper.Dik@Sun.COM free(server); 3859869SCasper.Dik@Sun.COM return (NULL); 3869869SCasper.Dik@Sun.COM } 3879869SCasper.Dik@Sun.COM 3889869SCasper.Dik@Sun.COM PKGserver 3899869SCasper.Dik@Sun.COM pkgopenserver(const char *root, const char *sadmdir, boolean_t ro) 3909869SCasper.Dik@Sun.COM { 3919869SCasper.Dik@Sun.COM return (pkgopenserver_i(root, sadmdir, ro, pkgservergetmode())); 3929869SCasper.Dik@Sun.COM } 3939869SCasper.Dik@Sun.COM 3949869SCasper.Dik@Sun.COM start_mode_t 3959869SCasper.Dik@Sun.COM pkgparsemode(const char *mode) 3969869SCasper.Dik@Sun.COM { 3979869SCasper.Dik@Sun.COM if (strcasecmp(mode, MODE_PERMANENT) == 0) { 3989869SCasper.Dik@Sun.COM return (PERMANENT); 3999869SCasper.Dik@Sun.COM } else if (strncasecmp(mode, MODE_TIMEOUT, 4009869SCasper.Dik@Sun.COM sizeof (MODE_TIMEOUT) - 1) == 0) { 4019869SCasper.Dik@Sun.COM const char *pidstr = mode + sizeof (MODE_TIMEOUT) - 1; 4029869SCasper.Dik@Sun.COM if (pidstr[0] != '\0') { 4039869SCasper.Dik@Sun.COM master_pid = atoi(pidstr); 4049869SCasper.Dik@Sun.COM if (master_pid <= 1 || kill(master_pid, 0) != 0) 4059869SCasper.Dik@Sun.COM master_pid = -1; 4069869SCasper.Dik@Sun.COM } 4079869SCasper.Dik@Sun.COM 4089869SCasper.Dik@Sun.COM return (TIMEOUT); 4099869SCasper.Dik@Sun.COM } else if (strcasecmp(mode, MODE_RUN_ONCE) == 0) { 4109869SCasper.Dik@Sun.COM return (RUN_ONCE); 4119869SCasper.Dik@Sun.COM } else { 4129869SCasper.Dik@Sun.COM progerr(gettext("invalid pkgserver mode: %s"), mode); 4139869SCasper.Dik@Sun.COM exit(99); 4149869SCasper.Dik@Sun.COM /*NOTREACHED*/ 4159869SCasper.Dik@Sun.COM } 4169869SCasper.Dik@Sun.COM } 4179869SCasper.Dik@Sun.COM 4189869SCasper.Dik@Sun.COM char * 4199869SCasper.Dik@Sun.COM pkgmodeargument(start_mode_t mode) 4209869SCasper.Dik@Sun.COM { 4219869SCasper.Dik@Sun.COM static char timebuf[sizeof (PKGSERV_MODE) + sizeof (MODE_TIMEOUT) + 10]; 4229869SCasper.Dik@Sun.COM 4239869SCasper.Dik@Sun.COM switch (mode) { 4249869SCasper.Dik@Sun.COM case PERMANENT: 4259869SCasper.Dik@Sun.COM return (PKGSERV_MODE MODE_PERMANENT); 4269869SCasper.Dik@Sun.COM case TIMEOUT: 4279869SCasper.Dik@Sun.COM (void) snprintf(timebuf, sizeof (timebuf), 4289869SCasper.Dik@Sun.COM PKGSERV_MODE MODE_TIMEOUT "%d", 4299869SCasper.Dik@Sun.COM (master_pid > 1 && kill(master_pid, 0) == 0) ? master_pid : 4309869SCasper.Dik@Sun.COM getpid()); 4319869SCasper.Dik@Sun.COM return (timebuf); 4329869SCasper.Dik@Sun.COM case RUN_ONCE: 4339869SCasper.Dik@Sun.COM return (PKGSERV_MODE MODE_RUN_ONCE); 4349869SCasper.Dik@Sun.COM } 4359869SCasper.Dik@Sun.COM progerr(gettext("Bad pkgserv mode: %d"), (int)mode); 4369869SCasper.Dik@Sun.COM exit(99); 4379869SCasper.Dik@Sun.COM } 4389869SCasper.Dik@Sun.COM 4399869SCasper.Dik@Sun.COM void 4409869SCasper.Dik@Sun.COM pkgserversetmode(start_mode_t mode) 4419869SCasper.Dik@Sun.COM { 4429869SCasper.Dik@Sun.COM if (mode == DEFAULTMODE || mode == INVALID) { 4439869SCasper.Dik@Sun.COM char *var = getenv(SUNW_PKG_SERVERMODE); 4449869SCasper.Dik@Sun.COM 4459869SCasper.Dik@Sun.COM if (var != NULL) 4469869SCasper.Dik@Sun.COM defmode = pkgparsemode(var); 4479869SCasper.Dik@Sun.COM else 4489869SCasper.Dik@Sun.COM defmode = DEFAULTMODE; 4499869SCasper.Dik@Sun.COM } else { 4509869SCasper.Dik@Sun.COM defmode = mode; 4519869SCasper.Dik@Sun.COM } 4529869SCasper.Dik@Sun.COM } 4539869SCasper.Dik@Sun.COM 4549869SCasper.Dik@Sun.COM start_mode_t 4559869SCasper.Dik@Sun.COM pkgservergetmode(void) 4569869SCasper.Dik@Sun.COM { 4579869SCasper.Dik@Sun.COM if (defmode == INVALID) 4589869SCasper.Dik@Sun.COM pkgserversetmode(DEFAULTMODE); 4599869SCasper.Dik@Sun.COM return (defmode); 4609869SCasper.Dik@Sun.COM } 4619869SCasper.Dik@Sun.COM 4629869SCasper.Dik@Sun.COM void 4639869SCasper.Dik@Sun.COM pkgcloseserver(PKGserver server) 4649869SCasper.Dik@Sun.COM { 4659869SCasper.Dik@Sun.COM 4669869SCasper.Dik@Sun.COM if (server->fp != NULL) 4679869SCasper.Dik@Sun.COM (void) fclose(server->fp); 4689869SCasper.Dik@Sun.COM free(server->curbuf); 4699869SCasper.Dik@Sun.COM if (server->onetime) { 4709869SCasper.Dik@Sun.COM pkgcmd_t cmd; 4719869SCasper.Dik@Sun.COM cmd.cmd = PKG_EXIT; 4729869SCasper.Dik@Sun.COM (void) pkgcmd(server, &cmd, sizeof (cmd), NULL, NULL, NULL); 4739869SCasper.Dik@Sun.COM } 4749869SCasper.Dik@Sun.COM (void) close(server->door); 4759869SCasper.Dik@Sun.COM if (server == current_server) 4769869SCasper.Dik@Sun.COM current_server = NULL; 4779869SCasper.Dik@Sun.COM free(server); 4789869SCasper.Dik@Sun.COM } 4799869SCasper.Dik@Sun.COM 4809869SCasper.Dik@Sun.COM int 4819869SCasper.Dik@Sun.COM pkgcmd(PKGserver srv, void *cmd, size_t len, char **result, size_t *rlen, 4829869SCasper.Dik@Sun.COM int *fd) 4839869SCasper.Dik@Sun.COM { 4849869SCasper.Dik@Sun.COM door_arg_t da; 4859869SCasper.Dik@Sun.COM 4869869SCasper.Dik@Sun.COM da.data_ptr = cmd; 4879869SCasper.Dik@Sun.COM da.data_size = len; 4889869SCasper.Dik@Sun.COM da.desc_ptr = NULL; 4899869SCasper.Dik@Sun.COM da.desc_num = 0; 4909869SCasper.Dik@Sun.COM da.rbuf = result == NULL ? NULL : *result; 4919869SCasper.Dik@Sun.COM da.rsize = rlen == NULL ? 0 : *rlen; 4929869SCasper.Dik@Sun.COM 4939869SCasper.Dik@Sun.COM if (door_call(srv->door, &da) != 0) { 4949869SCasper.Dik@Sun.COM if (((pkgcmd_t *)cmd)->cmd == PKG_EXIT && errno == EINTR) 4959869SCasper.Dik@Sun.COM return (0); 4969869SCasper.Dik@Sun.COM return (-1); 4979869SCasper.Dik@Sun.COM } 4989869SCasper.Dik@Sun.COM 4999869SCasper.Dik@Sun.COM if (da.desc_ptr != NULL) { 5009869SCasper.Dik@Sun.COM int i = 0; 5019869SCasper.Dik@Sun.COM if (fd != NULL) 5029869SCasper.Dik@Sun.COM *fd = da.desc_ptr[i++].d_data.d_desc.d_descriptor; 5039869SCasper.Dik@Sun.COM for (; i < da.desc_num; i++) 5049869SCasper.Dik@Sun.COM (void) close(da.desc_ptr[i].d_data.d_desc.d_descriptor); 5059869SCasper.Dik@Sun.COM } 5069869SCasper.Dik@Sun.COM /* Error return */ 5079869SCasper.Dik@Sun.COM if (da.data_size == sizeof (int)) { 5089869SCasper.Dik@Sun.COM int x = *(int *)da.data_ptr; 5099869SCasper.Dik@Sun.COM if (x != 0) { 5109869SCasper.Dik@Sun.COM if (result == NULL || da.rbuf != *result) 5119869SCasper.Dik@Sun.COM (void) munmap(da.rbuf, da.rsize); 5129869SCasper.Dik@Sun.COM return (x); 5139869SCasper.Dik@Sun.COM } 5149869SCasper.Dik@Sun.COM } 5159869SCasper.Dik@Sun.COM 5169869SCasper.Dik@Sun.COM /* Other result */ 5179869SCasper.Dik@Sun.COM if (result != NULL) { 5189869SCasper.Dik@Sun.COM /* Make sure that the result is at the start of the buffer. */ 5199869SCasper.Dik@Sun.COM if (da.data_ptr != NULL && da.rbuf != da.data_ptr) 5209869SCasper.Dik@Sun.COM (void) memmove(da.rbuf, da.data_ptr, da.data_size); 5219869SCasper.Dik@Sun.COM *result = da.rbuf; 5229869SCasper.Dik@Sun.COM *rlen = da.data_size; 5239869SCasper.Dik@Sun.COM } else if (da.rbuf != NULL) { 5249869SCasper.Dik@Sun.COM (void) munmap(da.rbuf, da.rsize); 5259869SCasper.Dik@Sun.COM } 5269869SCasper.Dik@Sun.COM return (0); 5279869SCasper.Dik@Sun.COM } 5289869SCasper.Dik@Sun.COM 5299869SCasper.Dik@Sun.COM /* 5309869SCasper.Dik@Sun.COM * Pkgsync: 5319869SCasper.Dik@Sun.COM * If the server is running, make sure that the contents 5329869SCasper.Dik@Sun.COM * file is written. 5339869SCasper.Dik@Sun.COM * If the server is not running, check for the log file; 5349869SCasper.Dik@Sun.COM * if there's a non-empty log file, we need to start the server 5359869SCasper.Dik@Sun.COM * as it will incorporate the log file into the contents file. 5369869SCasper.Dik@Sun.COM * And then check if the door is present. If it doesn't, we don't 5379869SCasper.Dik@Sun.COM * need to call it. 5389869SCasper.Dik@Sun.COM */ 5399869SCasper.Dik@Sun.COM 5409869SCasper.Dik@Sun.COM boolean_t 5419869SCasper.Dik@Sun.COM pkgsync_needed(const char *root, const char *sadmdir, boolean_t want_quit) 5429869SCasper.Dik@Sun.COM { 5439869SCasper.Dik@Sun.COM struct stat pbuf; 5449869SCasper.Dik@Sun.COM char pkgfile[PATH_MAX]; 5459869SCasper.Dik@Sun.COM boolean_t sync_needed, running; 5469869SCasper.Dik@Sun.COM int fd; 5479869SCasper.Dik@Sun.COM struct door_info di; 5489869SCasper.Dik@Sun.COM 5499869SCasper.Dik@Sun.COM pkgfilename(pkgfile, root, sadmdir, PKGLOG); 5509869SCasper.Dik@Sun.COM 5519869SCasper.Dik@Sun.COM sync_needed = stat(pkgfile, &pbuf) == 0 && pbuf.st_size > 0; 5529869SCasper.Dik@Sun.COM 5539869SCasper.Dik@Sun.COM if (!sync_needed && !want_quit) 5549869SCasper.Dik@Sun.COM return (B_FALSE); 5559869SCasper.Dik@Sun.COM 5569869SCasper.Dik@Sun.COM pkgfilename(pkgfile, root, sadmdir, PKGDOOR); 5579869SCasper.Dik@Sun.COM 5589869SCasper.Dik@Sun.COM /* sync_needed == B_TRUE || want_quit == B_TRUE */ 5599869SCasper.Dik@Sun.COM running = B_FALSE; 5609869SCasper.Dik@Sun.COM 5619869SCasper.Dik@Sun.COM fd = open(pkgfile, O_RDWR); 5629869SCasper.Dik@Sun.COM 5639869SCasper.Dik@Sun.COM if (fd >= 0) { 5649869SCasper.Dik@Sun.COM if (door_info(fd, &di) == 0) { 5659869SCasper.Dik@Sun.COM /* It's mounted, so the server is likely there */ 5669869SCasper.Dik@Sun.COM running = B_TRUE; 5679869SCasper.Dik@Sun.COM } 5689869SCasper.Dik@Sun.COM (void) close(fd); 5699869SCasper.Dik@Sun.COM } 5709869SCasper.Dik@Sun.COM return (running || sync_needed); 5719869SCasper.Dik@Sun.COM } 5729869SCasper.Dik@Sun.COM 5739869SCasper.Dik@Sun.COM int 5749869SCasper.Dik@Sun.COM pkgsync(const char *root, const char *sadmdir, boolean_t force_quit) 5759869SCasper.Dik@Sun.COM { 5769869SCasper.Dik@Sun.COM void *server; 5779869SCasper.Dik@Sun.COM pkgcmd_t cmd; 5789869SCasper.Dik@Sun.COM 5799869SCasper.Dik@Sun.COM /* No need to write contents file; don't start if not running */ 5809869SCasper.Dik@Sun.COM if (!pkgsync_needed(root, sadmdir, force_quit)) 5819869SCasper.Dik@Sun.COM return (0); 5829869SCasper.Dik@Sun.COM 5839869SCasper.Dik@Sun.COM server = pkgopenserver_i(root, sadmdir, B_FALSE, FLUSH_LOG); 5849869SCasper.Dik@Sun.COM /* 5859869SCasper.Dik@Sun.COM * We're assuming that it started the server and exited immediately. 5869869SCasper.Dik@Sun.COM * If that didn't work, there's nothing we can do. 5879869SCasper.Dik@Sun.COM */ 5889869SCasper.Dik@Sun.COM if (server == NULL) 5899869SCasper.Dik@Sun.COM return (0); 5909869SCasper.Dik@Sun.COM 5919869SCasper.Dik@Sun.COM cmd.cmd = force_quit ? PKG_EXIT : PKG_DUMP; 5929869SCasper.Dik@Sun.COM 5939869SCasper.Dik@Sun.COM (void) pkgcmd(server, &cmd, sizeof (cmd), NULL, NULL, NULL); 5949869SCasper.Dik@Sun.COM (void) pkgcloseserver(server); 5959869SCasper.Dik@Sun.COM return (0); 5969869SCasper.Dik@Sun.COM } 5979869SCasper.Dik@Sun.COM 5989869SCasper.Dik@Sun.COM int 5999869SCasper.Dik@Sun.COM pkgservercommitfile(VFP_T *a_vfp, PKGserver server) 6009869SCasper.Dik@Sun.COM { 6019869SCasper.Dik@Sun.COM size_t len = vfpGetModifiedLen(a_vfp); 6029869SCasper.Dik@Sun.COM ssize_t rem = len; 6039869SCasper.Dik@Sun.COM size_t off; 6049869SCasper.Dik@Sun.COM pkgfilter_t *pcmd; 6059869SCasper.Dik@Sun.COM char *map = a_vfp->_vfpStart; 6069869SCasper.Dik@Sun.COM 6079869SCasper.Dik@Sun.COM if (len < PKGADD_MAX) 6089869SCasper.Dik@Sun.COM pcmd = alloca(sizeof (*pcmd) + len); 6099869SCasper.Dik@Sun.COM else 6109869SCasper.Dik@Sun.COM pcmd = alloca(sizeof (*pcmd) + PKGADD_MAX); 6119869SCasper.Dik@Sun.COM 6129869SCasper.Dik@Sun.COM 6139869SCasper.Dik@Sun.COM off = 0; 6149869SCasper.Dik@Sun.COM pcmd->cmd = PKG_ADDLINES; 6159869SCasper.Dik@Sun.COM while (rem > 0) { 6169869SCasper.Dik@Sun.COM char *p = map + off; 6179869SCasper.Dik@Sun.COM len = rem; 6189869SCasper.Dik@Sun.COM 6199869SCasper.Dik@Sun.COM if (len >= PKGADD_MAX) { 6209869SCasper.Dik@Sun.COM len = PKGADD_MAX - 1; 6219869SCasper.Dik@Sun.COM while (p[len] != '\n' && len > 0) 6229869SCasper.Dik@Sun.COM len--; 6239869SCasper.Dik@Sun.COM if (p[len] != '\n') 6249869SCasper.Dik@Sun.COM return (-1); 6259869SCasper.Dik@Sun.COM len++; 6269869SCasper.Dik@Sun.COM } 6279869SCasper.Dik@Sun.COM (void) memcpy(&pcmd->buf[0], p, len); 6289869SCasper.Dik@Sun.COM pcmd->len = len; 6299869SCasper.Dik@Sun.COM 6309869SCasper.Dik@Sun.COM if (pkgcmd(server, pcmd, sizeof (*pcmd) + len - 1, 6319869SCasper.Dik@Sun.COM NULL, NULL, NULL) != 0) { 6329869SCasper.Dik@Sun.COM return (-1); 6339869SCasper.Dik@Sun.COM } 6349869SCasper.Dik@Sun.COM rem -= len; 6359869SCasper.Dik@Sun.COM off += len; 6369869SCasper.Dik@Sun.COM } 6379869SCasper.Dik@Sun.COM pcmd->len = 0; 6389869SCasper.Dik@Sun.COM pcmd->cmd = PKG_PKGSYNC; 6399869SCasper.Dik@Sun.COM if (pkgcmd(server, pcmd, sizeof (*pcmd), NULL, NULL, NULL) != 0) 6409869SCasper.Dik@Sun.COM return (-1); 6419869SCasper.Dik@Sun.COM 6429869SCasper.Dik@Sun.COM /* Mark it unmodified. */ 6439869SCasper.Dik@Sun.COM vfpTruncate(a_vfp); 6449869SCasper.Dik@Sun.COM (void) vfpClearModified(a_vfp); 6459869SCasper.Dik@Sun.COM 6469869SCasper.Dik@Sun.COM return (0); 6479869SCasper.Dik@Sun.COM } 6489869SCasper.Dik@Sun.COM 6499869SCasper.Dik@Sun.COM int 6509869SCasper.Dik@Sun.COM pkgopenfilter(PKGserver server, const char *filt) 6519869SCasper.Dik@Sun.COM { 6529869SCasper.Dik@Sun.COM int fd; 6539869SCasper.Dik@Sun.COM pkgfilter_t *pfcmd; 6549869SCasper.Dik@Sun.COM int clen = filt == NULL ? 0 : strlen(filt); 6559869SCasper.Dik@Sun.COM int len = sizeof (*pfcmd) + clen; 6569869SCasper.Dik@Sun.COM 6579869SCasper.Dik@Sun.COM pfcmd = alloca(len); 6589869SCasper.Dik@Sun.COM 6599869SCasper.Dik@Sun.COM if (server->fp != NULL) { 6609869SCasper.Dik@Sun.COM (void) fclose(server->fp); 6619869SCasper.Dik@Sun.COM server->fp = NULL; 6629869SCasper.Dik@Sun.COM } 6639869SCasper.Dik@Sun.COM 6649869SCasper.Dik@Sun.COM pfcmd->cmd = PKG_FILTER; 6659869SCasper.Dik@Sun.COM pfcmd->len = clen; 6669869SCasper.Dik@Sun.COM if (filt != NULL) 6679869SCasper.Dik@Sun.COM (void) strcpy(pfcmd->buf, filt); 6689869SCasper.Dik@Sun.COM 6699869SCasper.Dik@Sun.COM fd = -1; 6709869SCasper.Dik@Sun.COM 6719869SCasper.Dik@Sun.COM if (pkgcmd(server, pfcmd, len, NULL, NULL, &fd) != 0 || fd == -1) { 6729869SCasper.Dik@Sun.COM progerr(gettext(ERR_START_FILTER)); 6739869SCasper.Dik@Sun.COM return (-1); 6749869SCasper.Dik@Sun.COM } 6759869SCasper.Dik@Sun.COM (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 6769869SCasper.Dik@Sun.COM 6779869SCasper.Dik@Sun.COM server->fp = fdopen(fd, "r"); 6789869SCasper.Dik@Sun.COM if (server->fp == NULL) { 6799869SCasper.Dik@Sun.COM (void) close(fd); 6809869SCasper.Dik@Sun.COM progerr(gettext(ERR_START_FILTER)); 6819869SCasper.Dik@Sun.COM return (-1); 6829869SCasper.Dik@Sun.COM } 6839869SCasper.Dik@Sun.COM return (0); 6849869SCasper.Dik@Sun.COM } 6859869SCasper.Dik@Sun.COM 6869869SCasper.Dik@Sun.COM void 6879869SCasper.Dik@Sun.COM pkgclosefilter(PKGserver server) 6889869SCasper.Dik@Sun.COM { 6899869SCasper.Dik@Sun.COM if (server->fp != NULL) { 6909869SCasper.Dik@Sun.COM (void) fclose(server->fp); 6919869SCasper.Dik@Sun.COM server->fp = NULL; 6929869SCasper.Dik@Sun.COM } 6939869SCasper.Dik@Sun.COM } 6949869SCasper.Dik@Sun.COM 6959869SCasper.Dik@Sun.COM /* 6969869SCasper.Dik@Sun.COM * Report the next entry from the contents file. 6979869SCasper.Dik@Sun.COM */ 6989869SCasper.Dik@Sun.COM char * 6999869SCasper.Dik@Sun.COM pkggetentry(PKGserver server, int *len, int *pathlen) 7009869SCasper.Dik@Sun.COM { 7019869SCasper.Dik@Sun.COM int num[2]; 7029869SCasper.Dik@Sun.COM 7039869SCasper.Dik@Sun.COM if (server->fp == NULL) 7049869SCasper.Dik@Sun.COM return (NULL); 7059869SCasper.Dik@Sun.COM 7069869SCasper.Dik@Sun.COM if (feof(server->fp) || ferror(server->fp)) 7079869SCasper.Dik@Sun.COM return (NULL); 7089869SCasper.Dik@Sun.COM 7099869SCasper.Dik@Sun.COM if (fread(num, sizeof (int), 2, server->fp) != 2) 7109869SCasper.Dik@Sun.COM return (NULL); 7119869SCasper.Dik@Sun.COM 7129869SCasper.Dik@Sun.COM if (num[0] > server->buflen) { 7139869SCasper.Dik@Sun.COM free(server->curbuf); 7149869SCasper.Dik@Sun.COM server->buflen = num[0]; 7159869SCasper.Dik@Sun.COM server->curbuf = malloc(server->buflen); 7169869SCasper.Dik@Sun.COM if (server->curbuf == NULL) 7179869SCasper.Dik@Sun.COM return (NULL); 7189869SCasper.Dik@Sun.COM } 7199869SCasper.Dik@Sun.COM if (fread(server->curbuf, 1, num[0], server->fp) != num[0]) 7209869SCasper.Dik@Sun.COM return (NULL); 7219869SCasper.Dik@Sun.COM 7229869SCasper.Dik@Sun.COM *len = num[0]; 7239869SCasper.Dik@Sun.COM *pathlen = num[1]; 7249869SCasper.Dik@Sun.COM 7259869SCasper.Dik@Sun.COM return (server->curbuf); 7269869SCasper.Dik@Sun.COM } 7279869SCasper.Dik@Sun.COM 7289869SCasper.Dik@Sun.COM char * 7299869SCasper.Dik@Sun.COM pkggetentry_named(PKGserver server, const char *path, int *len, int *pathlen) 7309869SCasper.Dik@Sun.COM { 7319869SCasper.Dik@Sun.COM int plen = strlen(path); 7329869SCasper.Dik@Sun.COM pkgfilter_t *pcmd = alloca(sizeof (*pcmd) + plen); 7339869SCasper.Dik@Sun.COM char *result; 7349869SCasper.Dik@Sun.COM unsigned int rlen; 7359869SCasper.Dik@Sun.COM 7369869SCasper.Dik@Sun.COM pcmd->cmd = PKG_FINDFILE; 7379869SCasper.Dik@Sun.COM *pathlen = pcmd->len = plen; 7389869SCasper.Dik@Sun.COM (void) memcpy(pcmd->buf, path, pcmd->len + 1); 7399869SCasper.Dik@Sun.COM 7409869SCasper.Dik@Sun.COM result = server->curbuf; 7419869SCasper.Dik@Sun.COM rlen = server->buflen; 7429869SCasper.Dik@Sun.COM 7439869SCasper.Dik@Sun.COM if (pkgcmd(server, pcmd, sizeof (*pcmd) + pcmd->len, 7449869SCasper.Dik@Sun.COM &result, &rlen, NULL) != 0) { 7459869SCasper.Dik@Sun.COM return (NULL); 7469869SCasper.Dik@Sun.COM } 7479869SCasper.Dik@Sun.COM if (rlen == 0) 7489869SCasper.Dik@Sun.COM return (NULL); 7499869SCasper.Dik@Sun.COM 7509869SCasper.Dik@Sun.COM /* Result too big */ 7519869SCasper.Dik@Sun.COM if (result != server->curbuf) { 7529869SCasper.Dik@Sun.COM free(server->curbuf); 7539869SCasper.Dik@Sun.COM server->buflen = rlen; 7549869SCasper.Dik@Sun.COM server->curbuf = malloc(server->buflen); 7559869SCasper.Dik@Sun.COM if (server->curbuf == NULL) 7569869SCasper.Dik@Sun.COM return (NULL); 7579869SCasper.Dik@Sun.COM (void) memcpy(server->curbuf, result, rlen); 7589869SCasper.Dik@Sun.COM (void) munmap(result, rlen); 7599869SCasper.Dik@Sun.COM } 7609869SCasper.Dik@Sun.COM *len = rlen; 7619869SCasper.Dik@Sun.COM 7629869SCasper.Dik@Sun.COM return (server->curbuf); 7639869SCasper.Dik@Sun.COM } 764