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