1*9869SCasper.Dik@Sun.COM /* 2*9869SCasper.Dik@Sun.COM * CDDL HEADER START 3*9869SCasper.Dik@Sun.COM * 4*9869SCasper.Dik@Sun.COM * The contents of this file are subject to the terms of the 5*9869SCasper.Dik@Sun.COM * Common Development and Distribution License (the "License"). 6*9869SCasper.Dik@Sun.COM * You may not use this file except in compliance with the License. 7*9869SCasper.Dik@Sun.COM * 8*9869SCasper.Dik@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*9869SCasper.Dik@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*9869SCasper.Dik@Sun.COM * See the License for the specific language governing permissions 11*9869SCasper.Dik@Sun.COM * and limitations under the License. 12*9869SCasper.Dik@Sun.COM * 13*9869SCasper.Dik@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*9869SCasper.Dik@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*9869SCasper.Dik@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*9869SCasper.Dik@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*9869SCasper.Dik@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*9869SCasper.Dik@Sun.COM * 19*9869SCasper.Dik@Sun.COM * CDDL HEADER END 20*9869SCasper.Dik@Sun.COM */ 21*9869SCasper.Dik@Sun.COM 22*9869SCasper.Dik@Sun.COM /* 23*9869SCasper.Dik@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*9869SCasper.Dik@Sun.COM * Use is subject to license terms. 25*9869SCasper.Dik@Sun.COM */ 26*9869SCasper.Dik@Sun.COM 27*9869SCasper.Dik@Sun.COM #include <pkglib.h> 28*9869SCasper.Dik@Sun.COM 29*9869SCasper.Dik@Sun.COM #include <alloca.h> 30*9869SCasper.Dik@Sun.COM #include <assert.h> 31*9869SCasper.Dik@Sun.COM #include <door.h> 32*9869SCasper.Dik@Sun.COM #include <errno.h> 33*9869SCasper.Dik@Sun.COM #include <fcntl.h> 34*9869SCasper.Dik@Sun.COM #include <pthread.h> 35*9869SCasper.Dik@Sun.COM #include <spawn.h> 36*9869SCasper.Dik@Sun.COM #include <stdio.h> 37*9869SCasper.Dik@Sun.COM #include <stdlib.h> 38*9869SCasper.Dik@Sun.COM #include <strings.h> 39*9869SCasper.Dik@Sun.COM #include <sys/mman.h> 40*9869SCasper.Dik@Sun.COM #include <sys/param.h> 41*9869SCasper.Dik@Sun.COM #include <sys/stat.h> 42*9869SCasper.Dik@Sun.COM #include <sys/wait.h> 43*9869SCasper.Dik@Sun.COM #include <unistd.h> 44*9869SCasper.Dik@Sun.COM #include <libintl.h> 45*9869SCasper.Dik@Sun.COM 46*9869SCasper.Dik@Sun.COM #define PKGADD_MAX (512 * 1024) 47*9869SCasper.Dik@Sun.COM 48*9869SCasper.Dik@Sun.COM #define SADM_DIR "/var/sadm/install" 49*9869SCasper.Dik@Sun.COM 50*9869SCasper.Dik@Sun.COM #define PKGSERV_PATH "/usr/sadm/install/bin/pkgserv" 51*9869SCasper.Dik@Sun.COM 52*9869SCasper.Dik@Sun.COM #define ERR_PATH_TOO_BIG "alternate root path is too long" 53*9869SCasper.Dik@Sun.COM #define ERR_OPEN_DOOR "cannot open pkgserv door" 54*9869SCasper.Dik@Sun.COM #define ERR_START_SERVER "cannot start pkgserv daemon: %s" 55*9869SCasper.Dik@Sun.COM #define ERR_START_FILTER "cannot enumerate database entries" 56*9869SCasper.Dik@Sun.COM 57*9869SCasper.Dik@Sun.COM struct pkg_server { 58*9869SCasper.Dik@Sun.COM FILE *fp; 59*9869SCasper.Dik@Sun.COM char *curbuf; 60*9869SCasper.Dik@Sun.COM int buflen; 61*9869SCasper.Dik@Sun.COM int door; 62*9869SCasper.Dik@Sun.COM boolean_t onetime; 63*9869SCasper.Dik@Sun.COM }; 64*9869SCasper.Dik@Sun.COM 65*9869SCasper.Dik@Sun.COM static PKGserver current_server; 66*9869SCasper.Dik@Sun.COM 67*9869SCasper.Dik@Sun.COM static start_mode_t defmode = INVALID; 68*9869SCasper.Dik@Sun.COM static boolean_t registered = B_FALSE; 69*9869SCasper.Dik@Sun.COM static pid_t master_pid = -1; 70*9869SCasper.Dik@Sun.COM 71*9869SCasper.Dik@Sun.COM static void 72*9869SCasper.Dik@Sun.COM pkgfilename(char path[PATH_MAX], const char *root, const char *sadmdir, 73*9869SCasper.Dik@Sun.COM const char *file) 74*9869SCasper.Dik@Sun.COM { 75*9869SCasper.Dik@Sun.COM if (snprintf(path, PATH_MAX, "%s%s/%s", root == NULL ? "" : root, 76*9869SCasper.Dik@Sun.COM sadmdir == NULL ? SADM_DIR : sadmdir, file) >= PATH_MAX) { 77*9869SCasper.Dik@Sun.COM progerr(gettext(ERR_PATH_TOO_BIG)); 78*9869SCasper.Dik@Sun.COM exit(99); 79*9869SCasper.Dik@Sun.COM } 80*9869SCasper.Dik@Sun.COM } 81*9869SCasper.Dik@Sun.COM 82*9869SCasper.Dik@Sun.COM static void 83*9869SCasper.Dik@Sun.COM pkgexit_close(void) 84*9869SCasper.Dik@Sun.COM { 85*9869SCasper.Dik@Sun.COM if (current_server != NULL) 86*9869SCasper.Dik@Sun.COM pkgcloseserver(current_server); 87*9869SCasper.Dik@Sun.COM } 88*9869SCasper.Dik@Sun.COM 89*9869SCasper.Dik@Sun.COM static PKGserver 90*9869SCasper.Dik@Sun.COM pkgopenserver_i(const char *root, const char *sadmdir, boolean_t readonly, 91*9869SCasper.Dik@Sun.COM start_mode_t mode) 92*9869SCasper.Dik@Sun.COM { 93*9869SCasper.Dik@Sun.COM PKGserver server; 94*9869SCasper.Dik@Sun.COM struct door_info di; 95*9869SCasper.Dik@Sun.COM pid_t pid; 96*9869SCasper.Dik@Sun.COM int stat; 97*9869SCasper.Dik@Sun.COM int first = B_TRUE; 98*9869SCasper.Dik@Sun.COM char *cmd[16]; 99*9869SCasper.Dik@Sun.COM int args; 100*9869SCasper.Dik@Sun.COM char pkgdoor[PATH_MAX]; 101*9869SCasper.Dik@Sun.COM extern char **environ; 102*9869SCasper.Dik@Sun.COM char *prog; 103*9869SCasper.Dik@Sun.COM char pidbuf[12]; 104*9869SCasper.Dik@Sun.COM 105*9869SCasper.Dik@Sun.COM if (current_server != NULL) 106*9869SCasper.Dik@Sun.COM return (current_server); 107*9869SCasper.Dik@Sun.COM 108*9869SCasper.Dik@Sun.COM if (!registered) { 109*9869SCasper.Dik@Sun.COM registered = B_TRUE; 110*9869SCasper.Dik@Sun.COM (void) atexit(pkgexit_close); 111*9869SCasper.Dik@Sun.COM } 112*9869SCasper.Dik@Sun.COM if (readonly) { 113*9869SCasper.Dik@Sun.COM int fd; 114*9869SCasper.Dik@Sun.COM 115*9869SCasper.Dik@Sun.COM (void) strcpy(pkgdoor, "/tmp/pkgdoor.XXXXXX"); 116*9869SCasper.Dik@Sun.COM if ((fd = mkstemp(pkgdoor)) < 0) { 117*9869SCasper.Dik@Sun.COM progerr(gettext(ERR_OPEN_DOOR)); 118*9869SCasper.Dik@Sun.COM return (NULL); 119*9869SCasper.Dik@Sun.COM } 120*9869SCasper.Dik@Sun.COM (void) close(fd); 121*9869SCasper.Dik@Sun.COM } else { 122*9869SCasper.Dik@Sun.COM pkgfilename(pkgdoor, root, sadmdir, PKGDOOR); 123*9869SCasper.Dik@Sun.COM } 124*9869SCasper.Dik@Sun.COM 125*9869SCasper.Dik@Sun.COM server = malloc(sizeof (*server)); 126*9869SCasper.Dik@Sun.COM 127*9869SCasper.Dik@Sun.COM if (server == NULL) 128*9869SCasper.Dik@Sun.COM goto return_null; 129*9869SCasper.Dik@Sun.COM 130*9869SCasper.Dik@Sun.COM server->fp = NULL; 131*9869SCasper.Dik@Sun.COM server->onetime = readonly; 132*9869SCasper.Dik@Sun.COM 133*9869SCasper.Dik@Sun.COM openserver: 134*9869SCasper.Dik@Sun.COM server->door = open(pkgdoor, O_RDWR); 135*9869SCasper.Dik@Sun.COM 136*9869SCasper.Dik@Sun.COM if (server->door >= 0) { 137*9869SCasper.Dik@Sun.COM if (door_info(server->door, &di) == 0 && di.di_target >= 0) { 138*9869SCasper.Dik@Sun.COM pkgcmd_t n; 139*9869SCasper.Dik@Sun.COM n.cmd = PKG_NOP; 140*9869SCasper.Dik@Sun.COM server->buflen = 1024; 141*9869SCasper.Dik@Sun.COM server->curbuf = malloc(1024); 142*9869SCasper.Dik@Sun.COM if (server->curbuf == NULL || 143*9869SCasper.Dik@Sun.COM pkgcmd(server, &n, sizeof (n), NULL, NULL, NULL)) { 144*9869SCasper.Dik@Sun.COM pkgcloseserver(server); 145*9869SCasper.Dik@Sun.COM return (NULL); 146*9869SCasper.Dik@Sun.COM } 147*9869SCasper.Dik@Sun.COM return (current_server = server); 148*9869SCasper.Dik@Sun.COM } 149*9869SCasper.Dik@Sun.COM 150*9869SCasper.Dik@Sun.COM (void) close(server->door); 151*9869SCasper.Dik@Sun.COM } 152*9869SCasper.Dik@Sun.COM 153*9869SCasper.Dik@Sun.COM if (!first || mode == NEVER) 154*9869SCasper.Dik@Sun.COM goto return_null; 155*9869SCasper.Dik@Sun.COM 156*9869SCasper.Dik@Sun.COM first = B_FALSE; 157*9869SCasper.Dik@Sun.COM 158*9869SCasper.Dik@Sun.COM args = 0; 159*9869SCasper.Dik@Sun.COM cmd[args++] = strrchr(PKGSERV_PATH, '/') + 1; 160*9869SCasper.Dik@Sun.COM if (root != NULL && strcmp(root, "/") != 0) { 161*9869SCasper.Dik@Sun.COM cmd[args++] = "-R"; 162*9869SCasper.Dik@Sun.COM cmd[args++] = (char *)root; 163*9869SCasper.Dik@Sun.COM } 164*9869SCasper.Dik@Sun.COM if (sadmdir != NULL && strcmp(sadmdir, SADM_DIR) != 0) { 165*9869SCasper.Dik@Sun.COM cmd[args++] = "-d"; 166*9869SCasper.Dik@Sun.COM cmd[args++] = (char *)sadmdir; 167*9869SCasper.Dik@Sun.COM } 168*9869SCasper.Dik@Sun.COM if (readonly) { 169*9869SCasper.Dik@Sun.COM cmd[args++] = "-r"; 170*9869SCasper.Dik@Sun.COM cmd[args++] = pkgdoor; 171*9869SCasper.Dik@Sun.COM } 172*9869SCasper.Dik@Sun.COM prog = get_prog_name(); 173*9869SCasper.Dik@Sun.COM if (prog != NULL) { 174*9869SCasper.Dik@Sun.COM cmd[args++] = "-N"; 175*9869SCasper.Dik@Sun.COM cmd[args++] = prog; 176*9869SCasper.Dik@Sun.COM } 177*9869SCasper.Dik@Sun.COM 178*9869SCasper.Dik@Sun.COM switch (mode) { 179*9869SCasper.Dik@Sun.COM case FLUSH_LOG: 180*9869SCasper.Dik@Sun.COM cmd[args++] = "-e"; 181*9869SCasper.Dik@Sun.COM break; 182*9869SCasper.Dik@Sun.COM case RUN_ONCE: 183*9869SCasper.Dik@Sun.COM cmd[args++] = "-o"; 184*9869SCasper.Dik@Sun.COM break; 185*9869SCasper.Dik@Sun.COM case PERMANENT: 186*9869SCasper.Dik@Sun.COM cmd[args++] = "-p"; 187*9869SCasper.Dik@Sun.COM break; 188*9869SCasper.Dik@Sun.COM default: 189*9869SCasper.Dik@Sun.COM break; 190*9869SCasper.Dik@Sun.COM } 191*9869SCasper.Dik@Sun.COM 192*9869SCasper.Dik@Sun.COM if (master_pid != -1) { 193*9869SCasper.Dik@Sun.COM cmd[args++] = "-P"; 194*9869SCasper.Dik@Sun.COM (void) snprintf(pidbuf, sizeof (pidbuf), "%d", master_pid); 195*9869SCasper.Dik@Sun.COM cmd[args++] = pidbuf; 196*9869SCasper.Dik@Sun.COM } 197*9869SCasper.Dik@Sun.COM cmd[args++] = NULL; 198*9869SCasper.Dik@Sun.COM assert(args <= sizeof (cmd)/sizeof (char *)); 199*9869SCasper.Dik@Sun.COM 200*9869SCasper.Dik@Sun.COM if (posix_spawn(&pid, PKGSERV_PATH, NULL, NULL, cmd, environ) == 0) { 201*9869SCasper.Dik@Sun.COM server->onetime |= mode == RUN_ONCE; 202*9869SCasper.Dik@Sun.COM while (wait4(pid, &stat, 0, NULL) != -1) { 203*9869SCasper.Dik@Sun.COM if (WIFEXITED(stat)) { 204*9869SCasper.Dik@Sun.COM int s = WEXITSTATUS(stat); 205*9869SCasper.Dik@Sun.COM if (s == 0 || s == 1) 206*9869SCasper.Dik@Sun.COM if (mode == FLUSH_LOG) 207*9869SCasper.Dik@Sun.COM goto return_null; 208*9869SCasper.Dik@Sun.COM else 209*9869SCasper.Dik@Sun.COM goto openserver; 210*9869SCasper.Dik@Sun.COM if (s == 2) 211*9869SCasper.Dik@Sun.COM goto return_null; 212*9869SCasper.Dik@Sun.COM break; 213*9869SCasper.Dik@Sun.COM } else if (WIFSIGNALED(stat)) { 214*9869SCasper.Dik@Sun.COM break; 215*9869SCasper.Dik@Sun.COM } 216*9869SCasper.Dik@Sun.COM } 217*9869SCasper.Dik@Sun.COM } 218*9869SCasper.Dik@Sun.COM 219*9869SCasper.Dik@Sun.COM progerr(gettext(ERR_START_SERVER), strerror(errno)); 220*9869SCasper.Dik@Sun.COM 221*9869SCasper.Dik@Sun.COM return_null: 222*9869SCasper.Dik@Sun.COM if (readonly) 223*9869SCasper.Dik@Sun.COM (void) unlink(pkgdoor); 224*9869SCasper.Dik@Sun.COM free(server); 225*9869SCasper.Dik@Sun.COM return (NULL); 226*9869SCasper.Dik@Sun.COM } 227*9869SCasper.Dik@Sun.COM 228*9869SCasper.Dik@Sun.COM PKGserver 229*9869SCasper.Dik@Sun.COM pkgopenserver(const char *root, const char *sadmdir, boolean_t ro) 230*9869SCasper.Dik@Sun.COM { 231*9869SCasper.Dik@Sun.COM return (pkgopenserver_i(root, sadmdir, ro, pkgservergetmode())); 232*9869SCasper.Dik@Sun.COM } 233*9869SCasper.Dik@Sun.COM 234*9869SCasper.Dik@Sun.COM start_mode_t 235*9869SCasper.Dik@Sun.COM pkgparsemode(const char *mode) 236*9869SCasper.Dik@Sun.COM { 237*9869SCasper.Dik@Sun.COM if (strcasecmp(mode, MODE_PERMANENT) == 0) { 238*9869SCasper.Dik@Sun.COM return (PERMANENT); 239*9869SCasper.Dik@Sun.COM } else if (strncasecmp(mode, MODE_TIMEOUT, 240*9869SCasper.Dik@Sun.COM sizeof (MODE_TIMEOUT) - 1) == 0) { 241*9869SCasper.Dik@Sun.COM const char *pidstr = mode + sizeof (MODE_TIMEOUT) - 1; 242*9869SCasper.Dik@Sun.COM if (pidstr[0] != '\0') { 243*9869SCasper.Dik@Sun.COM master_pid = atoi(pidstr); 244*9869SCasper.Dik@Sun.COM if (master_pid <= 1 || kill(master_pid, 0) != 0) 245*9869SCasper.Dik@Sun.COM master_pid = -1; 246*9869SCasper.Dik@Sun.COM } 247*9869SCasper.Dik@Sun.COM 248*9869SCasper.Dik@Sun.COM return (TIMEOUT); 249*9869SCasper.Dik@Sun.COM } else if (strcasecmp(mode, MODE_RUN_ONCE) == 0) { 250*9869SCasper.Dik@Sun.COM return (RUN_ONCE); 251*9869SCasper.Dik@Sun.COM } else { 252*9869SCasper.Dik@Sun.COM progerr(gettext("invalid pkgserver mode: %s"), mode); 253*9869SCasper.Dik@Sun.COM exit(99); 254*9869SCasper.Dik@Sun.COM /*NOTREACHED*/ 255*9869SCasper.Dik@Sun.COM } 256*9869SCasper.Dik@Sun.COM } 257*9869SCasper.Dik@Sun.COM 258*9869SCasper.Dik@Sun.COM char * 259*9869SCasper.Dik@Sun.COM pkgmodeargument(start_mode_t mode) 260*9869SCasper.Dik@Sun.COM { 261*9869SCasper.Dik@Sun.COM static char timebuf[sizeof (PKGSERV_MODE) + sizeof (MODE_TIMEOUT) + 10]; 262*9869SCasper.Dik@Sun.COM 263*9869SCasper.Dik@Sun.COM switch (mode) { 264*9869SCasper.Dik@Sun.COM case PERMANENT: 265*9869SCasper.Dik@Sun.COM return (PKGSERV_MODE MODE_PERMANENT); 266*9869SCasper.Dik@Sun.COM case TIMEOUT: 267*9869SCasper.Dik@Sun.COM (void) snprintf(timebuf, sizeof (timebuf), 268*9869SCasper.Dik@Sun.COM PKGSERV_MODE MODE_TIMEOUT "%d", 269*9869SCasper.Dik@Sun.COM (master_pid > 1 && kill(master_pid, 0) == 0) ? master_pid : 270*9869SCasper.Dik@Sun.COM getpid()); 271*9869SCasper.Dik@Sun.COM return (timebuf); 272*9869SCasper.Dik@Sun.COM case RUN_ONCE: 273*9869SCasper.Dik@Sun.COM return (PKGSERV_MODE MODE_RUN_ONCE); 274*9869SCasper.Dik@Sun.COM } 275*9869SCasper.Dik@Sun.COM progerr(gettext("Bad pkgserv mode: %d"), (int)mode); 276*9869SCasper.Dik@Sun.COM exit(99); 277*9869SCasper.Dik@Sun.COM } 278*9869SCasper.Dik@Sun.COM 279*9869SCasper.Dik@Sun.COM void 280*9869SCasper.Dik@Sun.COM pkgserversetmode(start_mode_t mode) 281*9869SCasper.Dik@Sun.COM { 282*9869SCasper.Dik@Sun.COM if (mode == DEFAULTMODE || mode == INVALID) { 283*9869SCasper.Dik@Sun.COM char *var = getenv(SUNW_PKG_SERVERMODE); 284*9869SCasper.Dik@Sun.COM 285*9869SCasper.Dik@Sun.COM if (var != NULL) 286*9869SCasper.Dik@Sun.COM defmode = pkgparsemode(var); 287*9869SCasper.Dik@Sun.COM else 288*9869SCasper.Dik@Sun.COM defmode = DEFAULTMODE; 289*9869SCasper.Dik@Sun.COM } else { 290*9869SCasper.Dik@Sun.COM defmode = mode; 291*9869SCasper.Dik@Sun.COM } 292*9869SCasper.Dik@Sun.COM } 293*9869SCasper.Dik@Sun.COM 294*9869SCasper.Dik@Sun.COM start_mode_t 295*9869SCasper.Dik@Sun.COM pkgservergetmode(void) 296*9869SCasper.Dik@Sun.COM { 297*9869SCasper.Dik@Sun.COM if (defmode == INVALID) 298*9869SCasper.Dik@Sun.COM pkgserversetmode(DEFAULTMODE); 299*9869SCasper.Dik@Sun.COM return (defmode); 300*9869SCasper.Dik@Sun.COM } 301*9869SCasper.Dik@Sun.COM 302*9869SCasper.Dik@Sun.COM void 303*9869SCasper.Dik@Sun.COM pkgcloseserver(PKGserver server) 304*9869SCasper.Dik@Sun.COM { 305*9869SCasper.Dik@Sun.COM 306*9869SCasper.Dik@Sun.COM if (server->fp != NULL) 307*9869SCasper.Dik@Sun.COM (void) fclose(server->fp); 308*9869SCasper.Dik@Sun.COM free(server->curbuf); 309*9869SCasper.Dik@Sun.COM if (server->onetime) { 310*9869SCasper.Dik@Sun.COM pkgcmd_t cmd; 311*9869SCasper.Dik@Sun.COM cmd.cmd = PKG_EXIT; 312*9869SCasper.Dik@Sun.COM (void) pkgcmd(server, &cmd, sizeof (cmd), NULL, NULL, NULL); 313*9869SCasper.Dik@Sun.COM } 314*9869SCasper.Dik@Sun.COM (void) close(server->door); 315*9869SCasper.Dik@Sun.COM if (server == current_server) 316*9869SCasper.Dik@Sun.COM current_server = NULL; 317*9869SCasper.Dik@Sun.COM free(server); 318*9869SCasper.Dik@Sun.COM } 319*9869SCasper.Dik@Sun.COM 320*9869SCasper.Dik@Sun.COM int 321*9869SCasper.Dik@Sun.COM pkgcmd(PKGserver srv, void *cmd, size_t len, char **result, size_t *rlen, 322*9869SCasper.Dik@Sun.COM int *fd) 323*9869SCasper.Dik@Sun.COM { 324*9869SCasper.Dik@Sun.COM door_arg_t da; 325*9869SCasper.Dik@Sun.COM 326*9869SCasper.Dik@Sun.COM da.data_ptr = cmd; 327*9869SCasper.Dik@Sun.COM da.data_size = len; 328*9869SCasper.Dik@Sun.COM da.desc_ptr = NULL; 329*9869SCasper.Dik@Sun.COM da.desc_num = 0; 330*9869SCasper.Dik@Sun.COM da.rbuf = result == NULL ? NULL : *result; 331*9869SCasper.Dik@Sun.COM da.rsize = rlen == NULL ? 0 : *rlen; 332*9869SCasper.Dik@Sun.COM 333*9869SCasper.Dik@Sun.COM if (door_call(srv->door, &da) != 0) { 334*9869SCasper.Dik@Sun.COM if (((pkgcmd_t *)cmd)->cmd == PKG_EXIT && errno == EINTR) 335*9869SCasper.Dik@Sun.COM return (0); 336*9869SCasper.Dik@Sun.COM return (-1); 337*9869SCasper.Dik@Sun.COM } 338*9869SCasper.Dik@Sun.COM 339*9869SCasper.Dik@Sun.COM if (da.desc_ptr != NULL) { 340*9869SCasper.Dik@Sun.COM int i = 0; 341*9869SCasper.Dik@Sun.COM if (fd != NULL) 342*9869SCasper.Dik@Sun.COM *fd = da.desc_ptr[i++].d_data.d_desc.d_descriptor; 343*9869SCasper.Dik@Sun.COM for (; i < da.desc_num; i++) 344*9869SCasper.Dik@Sun.COM (void) close(da.desc_ptr[i].d_data.d_desc.d_descriptor); 345*9869SCasper.Dik@Sun.COM } 346*9869SCasper.Dik@Sun.COM /* Error return */ 347*9869SCasper.Dik@Sun.COM if (da.data_size == sizeof (int)) { 348*9869SCasper.Dik@Sun.COM int x = *(int *)da.data_ptr; 349*9869SCasper.Dik@Sun.COM if (x != 0) { 350*9869SCasper.Dik@Sun.COM if (result == NULL || da.rbuf != *result) 351*9869SCasper.Dik@Sun.COM (void) munmap(da.rbuf, da.rsize); 352*9869SCasper.Dik@Sun.COM return (x); 353*9869SCasper.Dik@Sun.COM } 354*9869SCasper.Dik@Sun.COM } 355*9869SCasper.Dik@Sun.COM 356*9869SCasper.Dik@Sun.COM /* Other result */ 357*9869SCasper.Dik@Sun.COM if (result != NULL) { 358*9869SCasper.Dik@Sun.COM /* Make sure that the result is at the start of the buffer. */ 359*9869SCasper.Dik@Sun.COM if (da.data_ptr != NULL && da.rbuf != da.data_ptr) 360*9869SCasper.Dik@Sun.COM (void) memmove(da.rbuf, da.data_ptr, da.data_size); 361*9869SCasper.Dik@Sun.COM *result = da.rbuf; 362*9869SCasper.Dik@Sun.COM *rlen = da.data_size; 363*9869SCasper.Dik@Sun.COM } else if (da.rbuf != NULL) { 364*9869SCasper.Dik@Sun.COM (void) munmap(da.rbuf, da.rsize); 365*9869SCasper.Dik@Sun.COM } 366*9869SCasper.Dik@Sun.COM return (0); 367*9869SCasper.Dik@Sun.COM } 368*9869SCasper.Dik@Sun.COM 369*9869SCasper.Dik@Sun.COM /* 370*9869SCasper.Dik@Sun.COM * Pkgsync: 371*9869SCasper.Dik@Sun.COM * If the server is running, make sure that the contents 372*9869SCasper.Dik@Sun.COM * file is written. 373*9869SCasper.Dik@Sun.COM * If the server is not running, check for the log file; 374*9869SCasper.Dik@Sun.COM * if there's a non-empty log file, we need to start the server 375*9869SCasper.Dik@Sun.COM * as it will incorporate the log file into the contents file. 376*9869SCasper.Dik@Sun.COM * And then check if the door is present. If it doesn't, we don't 377*9869SCasper.Dik@Sun.COM * need to call it. 378*9869SCasper.Dik@Sun.COM */ 379*9869SCasper.Dik@Sun.COM 380*9869SCasper.Dik@Sun.COM boolean_t 381*9869SCasper.Dik@Sun.COM pkgsync_needed(const char *root, const char *sadmdir, boolean_t want_quit) 382*9869SCasper.Dik@Sun.COM { 383*9869SCasper.Dik@Sun.COM struct stat pbuf; 384*9869SCasper.Dik@Sun.COM char pkgfile[PATH_MAX]; 385*9869SCasper.Dik@Sun.COM boolean_t sync_needed, running; 386*9869SCasper.Dik@Sun.COM int fd; 387*9869SCasper.Dik@Sun.COM struct door_info di; 388*9869SCasper.Dik@Sun.COM 389*9869SCasper.Dik@Sun.COM pkgfilename(pkgfile, root, sadmdir, PKGLOG); 390*9869SCasper.Dik@Sun.COM 391*9869SCasper.Dik@Sun.COM sync_needed = stat(pkgfile, &pbuf) == 0 && pbuf.st_size > 0; 392*9869SCasper.Dik@Sun.COM 393*9869SCasper.Dik@Sun.COM if (!sync_needed && !want_quit) 394*9869SCasper.Dik@Sun.COM return (B_FALSE); 395*9869SCasper.Dik@Sun.COM 396*9869SCasper.Dik@Sun.COM pkgfilename(pkgfile, root, sadmdir, PKGDOOR); 397*9869SCasper.Dik@Sun.COM 398*9869SCasper.Dik@Sun.COM /* sync_needed == B_TRUE || want_quit == B_TRUE */ 399*9869SCasper.Dik@Sun.COM running = B_FALSE; 400*9869SCasper.Dik@Sun.COM 401*9869SCasper.Dik@Sun.COM fd = open(pkgfile, O_RDWR); 402*9869SCasper.Dik@Sun.COM 403*9869SCasper.Dik@Sun.COM if (fd >= 0) { 404*9869SCasper.Dik@Sun.COM if (door_info(fd, &di) == 0) { 405*9869SCasper.Dik@Sun.COM /* It's mounted, so the server is likely there */ 406*9869SCasper.Dik@Sun.COM running = B_TRUE; 407*9869SCasper.Dik@Sun.COM } 408*9869SCasper.Dik@Sun.COM (void) close(fd); 409*9869SCasper.Dik@Sun.COM } 410*9869SCasper.Dik@Sun.COM return (running || sync_needed); 411*9869SCasper.Dik@Sun.COM } 412*9869SCasper.Dik@Sun.COM 413*9869SCasper.Dik@Sun.COM int 414*9869SCasper.Dik@Sun.COM pkgsync(const char *root, const char *sadmdir, boolean_t force_quit) 415*9869SCasper.Dik@Sun.COM { 416*9869SCasper.Dik@Sun.COM void *server; 417*9869SCasper.Dik@Sun.COM pkgcmd_t cmd; 418*9869SCasper.Dik@Sun.COM 419*9869SCasper.Dik@Sun.COM /* No need to write contents file; don't start if not running */ 420*9869SCasper.Dik@Sun.COM if (!pkgsync_needed(root, sadmdir, force_quit)) 421*9869SCasper.Dik@Sun.COM return (0); 422*9869SCasper.Dik@Sun.COM 423*9869SCasper.Dik@Sun.COM server = pkgopenserver_i(root, sadmdir, B_FALSE, FLUSH_LOG); 424*9869SCasper.Dik@Sun.COM /* 425*9869SCasper.Dik@Sun.COM * We're assuming that it started the server and exited immediately. 426*9869SCasper.Dik@Sun.COM * If that didn't work, there's nothing we can do. 427*9869SCasper.Dik@Sun.COM */ 428*9869SCasper.Dik@Sun.COM if (server == NULL) 429*9869SCasper.Dik@Sun.COM return (0); 430*9869SCasper.Dik@Sun.COM 431*9869SCasper.Dik@Sun.COM cmd.cmd = force_quit ? PKG_EXIT : PKG_DUMP; 432*9869SCasper.Dik@Sun.COM 433*9869SCasper.Dik@Sun.COM (void) pkgcmd(server, &cmd, sizeof (cmd), NULL, NULL, NULL); 434*9869SCasper.Dik@Sun.COM (void) pkgcloseserver(server); 435*9869SCasper.Dik@Sun.COM return (0); 436*9869SCasper.Dik@Sun.COM } 437*9869SCasper.Dik@Sun.COM 438*9869SCasper.Dik@Sun.COM int 439*9869SCasper.Dik@Sun.COM pkgservercommitfile(VFP_T *a_vfp, PKGserver server) 440*9869SCasper.Dik@Sun.COM { 441*9869SCasper.Dik@Sun.COM size_t len = vfpGetModifiedLen(a_vfp); 442*9869SCasper.Dik@Sun.COM ssize_t rem = len; 443*9869SCasper.Dik@Sun.COM size_t off; 444*9869SCasper.Dik@Sun.COM pkgfilter_t *pcmd; 445*9869SCasper.Dik@Sun.COM char *map = a_vfp->_vfpStart; 446*9869SCasper.Dik@Sun.COM 447*9869SCasper.Dik@Sun.COM if (len < PKGADD_MAX) 448*9869SCasper.Dik@Sun.COM pcmd = alloca(sizeof (*pcmd) + len); 449*9869SCasper.Dik@Sun.COM else 450*9869SCasper.Dik@Sun.COM pcmd = alloca(sizeof (*pcmd) + PKGADD_MAX); 451*9869SCasper.Dik@Sun.COM 452*9869SCasper.Dik@Sun.COM 453*9869SCasper.Dik@Sun.COM off = 0; 454*9869SCasper.Dik@Sun.COM pcmd->cmd = PKG_ADDLINES; 455*9869SCasper.Dik@Sun.COM while (rem > 0) { 456*9869SCasper.Dik@Sun.COM char *p = map + off; 457*9869SCasper.Dik@Sun.COM len = rem; 458*9869SCasper.Dik@Sun.COM 459*9869SCasper.Dik@Sun.COM if (len >= PKGADD_MAX) { 460*9869SCasper.Dik@Sun.COM len = PKGADD_MAX - 1; 461*9869SCasper.Dik@Sun.COM while (p[len] != '\n' && len > 0) 462*9869SCasper.Dik@Sun.COM len--; 463*9869SCasper.Dik@Sun.COM if (p[len] != '\n') 464*9869SCasper.Dik@Sun.COM return (-1); 465*9869SCasper.Dik@Sun.COM len++; 466*9869SCasper.Dik@Sun.COM } 467*9869SCasper.Dik@Sun.COM (void) memcpy(&pcmd->buf[0], p, len); 468*9869SCasper.Dik@Sun.COM pcmd->len = len; 469*9869SCasper.Dik@Sun.COM 470*9869SCasper.Dik@Sun.COM if (pkgcmd(server, pcmd, sizeof (*pcmd) + len - 1, 471*9869SCasper.Dik@Sun.COM NULL, NULL, NULL) != 0) { 472*9869SCasper.Dik@Sun.COM return (-1); 473*9869SCasper.Dik@Sun.COM } 474*9869SCasper.Dik@Sun.COM rem -= len; 475*9869SCasper.Dik@Sun.COM off += len; 476*9869SCasper.Dik@Sun.COM } 477*9869SCasper.Dik@Sun.COM pcmd->len = 0; 478*9869SCasper.Dik@Sun.COM pcmd->cmd = PKG_PKGSYNC; 479*9869SCasper.Dik@Sun.COM if (pkgcmd(server, pcmd, sizeof (*pcmd), NULL, NULL, NULL) != 0) 480*9869SCasper.Dik@Sun.COM return (-1); 481*9869SCasper.Dik@Sun.COM 482*9869SCasper.Dik@Sun.COM /* Mark it unmodified. */ 483*9869SCasper.Dik@Sun.COM vfpTruncate(a_vfp); 484*9869SCasper.Dik@Sun.COM (void) vfpClearModified(a_vfp); 485*9869SCasper.Dik@Sun.COM 486*9869SCasper.Dik@Sun.COM return (0); 487*9869SCasper.Dik@Sun.COM } 488*9869SCasper.Dik@Sun.COM 489*9869SCasper.Dik@Sun.COM int 490*9869SCasper.Dik@Sun.COM pkgopenfilter(PKGserver server, const char *filt) 491*9869SCasper.Dik@Sun.COM { 492*9869SCasper.Dik@Sun.COM int fd; 493*9869SCasper.Dik@Sun.COM pkgfilter_t *pfcmd; 494*9869SCasper.Dik@Sun.COM int clen = filt == NULL ? 0 : strlen(filt); 495*9869SCasper.Dik@Sun.COM int len = sizeof (*pfcmd) + clen; 496*9869SCasper.Dik@Sun.COM 497*9869SCasper.Dik@Sun.COM pfcmd = alloca(len); 498*9869SCasper.Dik@Sun.COM 499*9869SCasper.Dik@Sun.COM if (server->fp != NULL) { 500*9869SCasper.Dik@Sun.COM (void) fclose(server->fp); 501*9869SCasper.Dik@Sun.COM server->fp = NULL; 502*9869SCasper.Dik@Sun.COM } 503*9869SCasper.Dik@Sun.COM 504*9869SCasper.Dik@Sun.COM pfcmd->cmd = PKG_FILTER; 505*9869SCasper.Dik@Sun.COM pfcmd->len = clen; 506*9869SCasper.Dik@Sun.COM if (filt != NULL) 507*9869SCasper.Dik@Sun.COM (void) strcpy(pfcmd->buf, filt); 508*9869SCasper.Dik@Sun.COM 509*9869SCasper.Dik@Sun.COM fd = -1; 510*9869SCasper.Dik@Sun.COM 511*9869SCasper.Dik@Sun.COM if (pkgcmd(server, pfcmd, len, NULL, NULL, &fd) != 0 || fd == -1) { 512*9869SCasper.Dik@Sun.COM progerr(gettext(ERR_START_FILTER)); 513*9869SCasper.Dik@Sun.COM return (-1); 514*9869SCasper.Dik@Sun.COM } 515*9869SCasper.Dik@Sun.COM (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 516*9869SCasper.Dik@Sun.COM 517*9869SCasper.Dik@Sun.COM server->fp = fdopen(fd, "r"); 518*9869SCasper.Dik@Sun.COM if (server->fp == NULL) { 519*9869SCasper.Dik@Sun.COM (void) close(fd); 520*9869SCasper.Dik@Sun.COM progerr(gettext(ERR_START_FILTER)); 521*9869SCasper.Dik@Sun.COM return (-1); 522*9869SCasper.Dik@Sun.COM } 523*9869SCasper.Dik@Sun.COM return (0); 524*9869SCasper.Dik@Sun.COM } 525*9869SCasper.Dik@Sun.COM 526*9869SCasper.Dik@Sun.COM void 527*9869SCasper.Dik@Sun.COM pkgclosefilter(PKGserver server) 528*9869SCasper.Dik@Sun.COM { 529*9869SCasper.Dik@Sun.COM if (server->fp != NULL) { 530*9869SCasper.Dik@Sun.COM (void) fclose(server->fp); 531*9869SCasper.Dik@Sun.COM server->fp = NULL; 532*9869SCasper.Dik@Sun.COM } 533*9869SCasper.Dik@Sun.COM } 534*9869SCasper.Dik@Sun.COM 535*9869SCasper.Dik@Sun.COM /* 536*9869SCasper.Dik@Sun.COM * Report the next entry from the contents file. 537*9869SCasper.Dik@Sun.COM */ 538*9869SCasper.Dik@Sun.COM char * 539*9869SCasper.Dik@Sun.COM pkggetentry(PKGserver server, int *len, int *pathlen) 540*9869SCasper.Dik@Sun.COM { 541*9869SCasper.Dik@Sun.COM int num[2]; 542*9869SCasper.Dik@Sun.COM 543*9869SCasper.Dik@Sun.COM if (server->fp == NULL) 544*9869SCasper.Dik@Sun.COM return (NULL); 545*9869SCasper.Dik@Sun.COM 546*9869SCasper.Dik@Sun.COM if (feof(server->fp) || ferror(server->fp)) 547*9869SCasper.Dik@Sun.COM return (NULL); 548*9869SCasper.Dik@Sun.COM 549*9869SCasper.Dik@Sun.COM if (fread(num, sizeof (int), 2, server->fp) != 2) 550*9869SCasper.Dik@Sun.COM return (NULL); 551*9869SCasper.Dik@Sun.COM 552*9869SCasper.Dik@Sun.COM if (num[0] > server->buflen) { 553*9869SCasper.Dik@Sun.COM free(server->curbuf); 554*9869SCasper.Dik@Sun.COM server->buflen = num[0]; 555*9869SCasper.Dik@Sun.COM server->curbuf = malloc(server->buflen); 556*9869SCasper.Dik@Sun.COM if (server->curbuf == NULL) 557*9869SCasper.Dik@Sun.COM return (NULL); 558*9869SCasper.Dik@Sun.COM } 559*9869SCasper.Dik@Sun.COM if (fread(server->curbuf, 1, num[0], server->fp) != num[0]) 560*9869SCasper.Dik@Sun.COM return (NULL); 561*9869SCasper.Dik@Sun.COM 562*9869SCasper.Dik@Sun.COM *len = num[0]; 563*9869SCasper.Dik@Sun.COM *pathlen = num[1]; 564*9869SCasper.Dik@Sun.COM 565*9869SCasper.Dik@Sun.COM return (server->curbuf); 566*9869SCasper.Dik@Sun.COM } 567*9869SCasper.Dik@Sun.COM 568*9869SCasper.Dik@Sun.COM char * 569*9869SCasper.Dik@Sun.COM pkggetentry_named(PKGserver server, const char *path, int *len, int *pathlen) 570*9869SCasper.Dik@Sun.COM { 571*9869SCasper.Dik@Sun.COM int plen = strlen(path); 572*9869SCasper.Dik@Sun.COM pkgfilter_t *pcmd = alloca(sizeof (*pcmd) + plen); 573*9869SCasper.Dik@Sun.COM char *result; 574*9869SCasper.Dik@Sun.COM unsigned int rlen; 575*9869SCasper.Dik@Sun.COM 576*9869SCasper.Dik@Sun.COM pcmd->cmd = PKG_FINDFILE; 577*9869SCasper.Dik@Sun.COM *pathlen = pcmd->len = plen; 578*9869SCasper.Dik@Sun.COM (void) memcpy(pcmd->buf, path, pcmd->len + 1); 579*9869SCasper.Dik@Sun.COM 580*9869SCasper.Dik@Sun.COM result = server->curbuf; 581*9869SCasper.Dik@Sun.COM rlen = server->buflen; 582*9869SCasper.Dik@Sun.COM 583*9869SCasper.Dik@Sun.COM if (pkgcmd(server, pcmd, sizeof (*pcmd) + pcmd->len, 584*9869SCasper.Dik@Sun.COM &result, &rlen, NULL) != 0) { 585*9869SCasper.Dik@Sun.COM return (NULL); 586*9869SCasper.Dik@Sun.COM } 587*9869SCasper.Dik@Sun.COM if (rlen == 0) 588*9869SCasper.Dik@Sun.COM return (NULL); 589*9869SCasper.Dik@Sun.COM 590*9869SCasper.Dik@Sun.COM /* Result too big */ 591*9869SCasper.Dik@Sun.COM if (result != server->curbuf) { 592*9869SCasper.Dik@Sun.COM free(server->curbuf); 593*9869SCasper.Dik@Sun.COM server->buflen = rlen; 594*9869SCasper.Dik@Sun.COM server->curbuf = malloc(server->buflen); 595*9869SCasper.Dik@Sun.COM if (server->curbuf == NULL) 596*9869SCasper.Dik@Sun.COM return (NULL); 597*9869SCasper.Dik@Sun.COM (void) memcpy(server->curbuf, result, rlen); 598*9869SCasper.Dik@Sun.COM (void) munmap(result, rlen); 599*9869SCasper.Dik@Sun.COM } 600*9869SCasper.Dik@Sun.COM *len = rlen; 601*9869SCasper.Dik@Sun.COM 602*9869SCasper.Dik@Sun.COM return (server->curbuf); 603*9869SCasper.Dik@Sun.COM } 604