summaryrefslogtreecommitdiff
path: root/usr/src/lib/libpkg/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libpkg/common')
-rw-r--r--usr/src/lib/libpkg/common/mapfile-vers14
-rw-r--r--usr/src/lib/libpkg/common/pkglib.h74
-rw-r--r--usr/src/lib/libpkg/common/pkgserv.c603
-rw-r--r--usr/src/lib/libpkg/common/srchcfile.c953
4 files changed, 794 insertions, 850 deletions
diff --git a/usr/src/lib/libpkg/common/mapfile-vers b/usr/src/lib/libpkg/common/mapfile-vers
index 7cb5ad56f3..f1fd2a8001 100644
--- a/usr/src/lib/libpkg/common/mapfile-vers
+++ b/usr/src/lib/libpkg/common/mapfile-vers
@@ -132,6 +132,9 @@ SUNWprivate {
path_valid;
pkg_passphrase_cb;
pkgalias;
+ pkgclosefilter;
+ pkgcloseserver;
+ pkgcmd;
pkgerr;
pkgerr_add;
pkgerr_clear;
@@ -142,9 +145,18 @@ SUNWprivate {
pkgerr_num;
pkgexecl;
pkgexecv;
+ pkggetentry;
+ pkggetentry_named;
pkghead;
pkglist_cont;
+ pkgmodeargument;
pkgmount;
+ pkgopenfilter;
+ pkgopenserver;
+ pkgparsemode;
+ pkgservercommitfile;
+ pkgservergetmode;
+ pkgserversetmode;
pkgstrAddToken;
pkgstrContainsToken;
pkgstrConvertPathToBasename;
@@ -160,6 +172,8 @@ SUNWprivate {
pkgstrRemoveLeadingWhitespace;
pkgstrRemoveToken;
pkgstrScaleNumericString;
+ pkgsync;
+ pkgsync_needed;
pkgtrans;
pkgumount;
ppkgmap;
diff --git a/usr/src/lib/libpkg/common/pkglib.h b/usr/src/lib/libpkg/common/pkglib.h
index 418cf632f7..04b17730ca 100644
--- a/usr/src/lib/libpkg/common/pkglib.h
+++ b/usr/src/lib/libpkg/common/pkglib.h
@@ -49,6 +49,58 @@ extern "C" {
#include "cfext.h"
/*
+ * The contents database file interface.
+ */
+
+typedef struct pkg_server *PKGserver;
+
+/* Some commands modify the internal database: add them here */
+#define PKG_WRITE_COMMAND(cmd) ((cmd) == PKG_ADDLINES)
+
+#define PKG_EXIT 0x0
+#define PKG_FINDFILE 0x1
+#define PKG_DUMP 0x2
+#define PKG_PKGSYNC 0x3
+#define PKG_FILTER 0x4
+#define PKG_ADDLINES 0x5
+#define PKG_NOP 0x6
+
+#define SUNW_PKG_SERVERMODE "SUNW_PKG_SERVERMODE"
+
+#define PKGSERV_MODE "pkg-server-mode="
+#define PKGSERV_MODE_LEN (sizeof (PKGSERV_MODE) - 1)
+
+#define MODE_PERMANENT "permanent"
+#define MODE_RUN_ONCE "run_once"
+#define MODE_TIMEOUT "timeout"
+
+#define MAXLOGFILESIZE (20 * 1024 * 1024)
+
+#define PKGLOG "pkglog"
+#define PKGDOOR ".door"
+
+typedef enum {
+ INVALID, /* Not initialized */
+ NEVER, /* Don't start, does check if it is running. */
+ FLUSH_LOG, /* Run it once to incorporate the log. */
+ RUN_ONCE, /* Run until the current client stops. */
+ TIMEOUT, /* Run until a timeout occurs. */
+ PERMANENT, /* Run until it is externally terminated. */
+ DEFAULTMODE = TIMEOUT /* The default mode, must come last */
+} start_mode_t;
+
+typedef struct pkgcmd {
+ int cmd;
+ char buf[1];
+} pkgcmd_t;
+
+typedef struct pkgfilter {
+ int cmd;
+ int len;
+ char buf[1];
+} pkgfilter_t;
+
+/*
* Virtual File Protocol definitions
*/
@@ -428,8 +480,7 @@ extern void set_passphrase_prompt(char *);
extern void set_passphrase_passarg(char *);
extern int pkg_passphrase_cb(char *, int, int, void *);
-extern int srchcfile(struct cfent *ept, char *path, VFP_T *vfp,
- VFP_T *vfpout);
+extern int srchcfile(struct cfent *ept, char *path, PKGserver server);
extern struct group *cgrgid(gid_t gid);
extern struct group *cgrnam(char *nam);
extern struct passwd *cpwnam(char *nam);
@@ -518,6 +569,25 @@ extern int vfpWriteToFile(VFP_T *a_vfp, char *a_path);
boolean_t enable_local_fs(void);
boolean_t restore_local_fs(void);
+/* pkgserv.c */
+extern PKGserver pkgopenserver(const char *, const char *, boolean_t);
+extern void pkgcloseserver(PKGserver);
+extern int pkgcmd(PKGserver, void *, size_t, char **, size_t *,
+ int *);
+extern boolean_t pkgsync_needed(const char *, const char *, boolean_t);
+extern int pkgsync(const char *, const char *, boolean_t);
+extern int pkgservercommitfile(VFP_T *, PKGserver);
+extern int pkgopenfilter(PKGserver server, const char *pkginst);
+extern void pkgclosefilter(PKGserver);
+extern char *pkggetentry(PKGserver, int *, int *);
+extern char *pkggetentry_named(PKGserver, const char *, int *,
+ int *);
+extern void pkgserversetmode(start_mode_t);
+extern start_mode_t pkgservergetmode(void);
+extern start_mode_t pkgparsemode(const char *);
+extern char *pkgmodeargument(start_mode_t);
+
+
#else /* __STDC__ */
extern FILE *epopen();
diff --git a/usr/src/lib/libpkg/common/pkgserv.c b/usr/src/lib/libpkg/common/pkgserv.c
new file mode 100644
index 0000000000..729f3c02a8
--- /dev/null
+++ b/usr/src/lib/libpkg/common/pkgserv.c
@@ -0,0 +1,603 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <pkglib.h>
+
+#include <alloca.h>
+#include <assert.h>
+#include <door.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <libintl.h>
+
+#define PKGADD_MAX (512 * 1024)
+
+#define SADM_DIR "/var/sadm/install"
+
+#define PKGSERV_PATH "/usr/sadm/install/bin/pkgserv"
+
+#define ERR_PATH_TOO_BIG "alternate root path is too long"
+#define ERR_OPEN_DOOR "cannot open pkgserv door"
+#define ERR_START_SERVER "cannot start pkgserv daemon: %s"
+#define ERR_START_FILTER "cannot enumerate database entries"
+
+struct pkg_server {
+ FILE *fp;
+ char *curbuf;
+ int buflen;
+ int door;
+ boolean_t onetime;
+};
+
+static PKGserver current_server;
+
+static start_mode_t defmode = INVALID;
+static boolean_t registered = B_FALSE;
+static pid_t master_pid = -1;
+
+static void
+pkgfilename(char path[PATH_MAX], const char *root, const char *sadmdir,
+ const char *file)
+{
+ if (snprintf(path, PATH_MAX, "%s%s/%s", root == NULL ? "" : root,
+ sadmdir == NULL ? SADM_DIR : sadmdir, file) >= PATH_MAX) {
+ progerr(gettext(ERR_PATH_TOO_BIG));
+ exit(99);
+ }
+}
+
+static void
+pkgexit_close(void)
+{
+ if (current_server != NULL)
+ pkgcloseserver(current_server);
+}
+
+static PKGserver
+pkgopenserver_i(const char *root, const char *sadmdir, boolean_t readonly,
+ start_mode_t mode)
+{
+ PKGserver server;
+ struct door_info di;
+ pid_t pid;
+ int stat;
+ int first = B_TRUE;
+ char *cmd[16];
+ int args;
+ char pkgdoor[PATH_MAX];
+ extern char **environ;
+ char *prog;
+ char pidbuf[12];
+
+ if (current_server != NULL)
+ return (current_server);
+
+ if (!registered) {
+ registered = B_TRUE;
+ (void) atexit(pkgexit_close);
+ }
+ if (readonly) {
+ int fd;
+
+ (void) strcpy(pkgdoor, "/tmp/pkgdoor.XXXXXX");
+ if ((fd = mkstemp(pkgdoor)) < 0) {
+ progerr(gettext(ERR_OPEN_DOOR));
+ return (NULL);
+ }
+ (void) close(fd);
+ } else {
+ pkgfilename(pkgdoor, root, sadmdir, PKGDOOR);
+ }
+
+ server = malloc(sizeof (*server));
+
+ if (server == NULL)
+ goto return_null;
+
+ server->fp = NULL;
+ server->onetime = readonly;
+
+openserver:
+ server->door = open(pkgdoor, O_RDWR);
+
+ if (server->door >= 0) {
+ if (door_info(server->door, &di) == 0 && di.di_target >= 0) {
+ pkgcmd_t n;
+ n.cmd = PKG_NOP;
+ server->buflen = 1024;
+ server->curbuf = malloc(1024);
+ if (server->curbuf == NULL ||
+ pkgcmd(server, &n, sizeof (n), NULL, NULL, NULL)) {
+ pkgcloseserver(server);
+ return (NULL);
+ }
+ return (current_server = server);
+ }
+
+ (void) close(server->door);
+ }
+
+ if (!first || mode == NEVER)
+ goto return_null;
+
+ first = B_FALSE;
+
+ args = 0;
+ cmd[args++] = strrchr(PKGSERV_PATH, '/') + 1;
+ if (root != NULL && strcmp(root, "/") != 0) {
+ cmd[args++] = "-R";
+ cmd[args++] = (char *)root;
+ }
+ if (sadmdir != NULL && strcmp(sadmdir, SADM_DIR) != 0) {
+ cmd[args++] = "-d";
+ cmd[args++] = (char *)sadmdir;
+ }
+ if (readonly) {
+ cmd[args++] = "-r";
+ cmd[args++] = pkgdoor;
+ }
+ prog = get_prog_name();
+ if (prog != NULL) {
+ cmd[args++] = "-N";
+ cmd[args++] = prog;
+ }
+
+ switch (mode) {
+ case FLUSH_LOG:
+ cmd[args++] = "-e";
+ break;
+ case RUN_ONCE:
+ cmd[args++] = "-o";
+ break;
+ case PERMANENT:
+ cmd[args++] = "-p";
+ break;
+ default:
+ break;
+ }
+
+ if (master_pid != -1) {
+ cmd[args++] = "-P";
+ (void) snprintf(pidbuf, sizeof (pidbuf), "%d", master_pid);
+ cmd[args++] = pidbuf;
+ }
+ cmd[args++] = NULL;
+ assert(args <= sizeof (cmd)/sizeof (char *));
+
+ if (posix_spawn(&pid, PKGSERV_PATH, NULL, NULL, cmd, environ) == 0) {
+ server->onetime |= mode == RUN_ONCE;
+ while (wait4(pid, &stat, 0, NULL) != -1) {
+ if (WIFEXITED(stat)) {
+ int s = WEXITSTATUS(stat);
+ if (s == 0 || s == 1)
+ if (mode == FLUSH_LOG)
+ goto return_null;
+ else
+ goto openserver;
+ if (s == 2)
+ goto return_null;
+ break;
+ } else if (WIFSIGNALED(stat)) {
+ break;
+ }
+ }
+ }
+
+ progerr(gettext(ERR_START_SERVER), strerror(errno));
+
+return_null:
+ if (readonly)
+ (void) unlink(pkgdoor);
+ free(server);
+ return (NULL);
+}
+
+PKGserver
+pkgopenserver(const char *root, const char *sadmdir, boolean_t ro)
+{
+ return (pkgopenserver_i(root, sadmdir, ro, pkgservergetmode()));
+}
+
+start_mode_t
+pkgparsemode(const char *mode)
+{
+ if (strcasecmp(mode, MODE_PERMANENT) == 0) {
+ return (PERMANENT);
+ } else if (strncasecmp(mode, MODE_TIMEOUT,
+ sizeof (MODE_TIMEOUT) - 1) == 0) {
+ const char *pidstr = mode + sizeof (MODE_TIMEOUT) - 1;
+ if (pidstr[0] != '\0') {
+ master_pid = atoi(pidstr);
+ if (master_pid <= 1 || kill(master_pid, 0) != 0)
+ master_pid = -1;
+ }
+
+ return (TIMEOUT);
+ } else if (strcasecmp(mode, MODE_RUN_ONCE) == 0) {
+ return (RUN_ONCE);
+ } else {
+ progerr(gettext("invalid pkgserver mode: %s"), mode);
+ exit(99);
+ /*NOTREACHED*/
+ }
+}
+
+char *
+pkgmodeargument(start_mode_t mode)
+{
+ static char timebuf[sizeof (PKGSERV_MODE) + sizeof (MODE_TIMEOUT) + 10];
+
+ switch (mode) {
+ case PERMANENT:
+ return (PKGSERV_MODE MODE_PERMANENT);
+ case TIMEOUT:
+ (void) snprintf(timebuf, sizeof (timebuf),
+ PKGSERV_MODE MODE_TIMEOUT "%d",
+ (master_pid > 1 && kill(master_pid, 0) == 0) ? master_pid :
+ getpid());
+ return (timebuf);
+ case RUN_ONCE:
+ return (PKGSERV_MODE MODE_RUN_ONCE);
+ }
+ progerr(gettext("Bad pkgserv mode: %d"), (int)mode);
+ exit(99);
+}
+
+void
+pkgserversetmode(start_mode_t mode)
+{
+ if (mode == DEFAULTMODE || mode == INVALID) {
+ char *var = getenv(SUNW_PKG_SERVERMODE);
+
+ if (var != NULL)
+ defmode = pkgparsemode(var);
+ else
+ defmode = DEFAULTMODE;
+ } else {
+ defmode = mode;
+ }
+}
+
+start_mode_t
+pkgservergetmode(void)
+{
+ if (defmode == INVALID)
+ pkgserversetmode(DEFAULTMODE);
+ return (defmode);
+}
+
+void
+pkgcloseserver(PKGserver server)
+{
+
+ if (server->fp != NULL)
+ (void) fclose(server->fp);
+ free(server->curbuf);
+ if (server->onetime) {
+ pkgcmd_t cmd;
+ cmd.cmd = PKG_EXIT;
+ (void) pkgcmd(server, &cmd, sizeof (cmd), NULL, NULL, NULL);
+ }
+ (void) close(server->door);
+ if (server == current_server)
+ current_server = NULL;
+ free(server);
+}
+
+int
+pkgcmd(PKGserver srv, void *cmd, size_t len, char **result, size_t *rlen,
+ int *fd)
+{
+ door_arg_t da;
+
+ da.data_ptr = cmd;
+ da.data_size = len;
+ da.desc_ptr = NULL;
+ da.desc_num = 0;
+ da.rbuf = result == NULL ? NULL : *result;
+ da.rsize = rlen == NULL ? 0 : *rlen;
+
+ if (door_call(srv->door, &da) != 0) {
+ if (((pkgcmd_t *)cmd)->cmd == PKG_EXIT && errno == EINTR)
+ return (0);
+ return (-1);
+ }
+
+ if (da.desc_ptr != NULL) {
+ int i = 0;
+ if (fd != NULL)
+ *fd = da.desc_ptr[i++].d_data.d_desc.d_descriptor;
+ for (; i < da.desc_num; i++)
+ (void) close(da.desc_ptr[i].d_data.d_desc.d_descriptor);
+ }
+ /* Error return */
+ if (da.data_size == sizeof (int)) {
+ int x = *(int *)da.data_ptr;
+ if (x != 0) {
+ if (result == NULL || da.rbuf != *result)
+ (void) munmap(da.rbuf, da.rsize);
+ return (x);
+ }
+ }
+
+ /* Other result */
+ if (result != NULL) {
+ /* Make sure that the result is at the start of the buffer. */
+ if (da.data_ptr != NULL && da.rbuf != da.data_ptr)
+ (void) memmove(da.rbuf, da.data_ptr, da.data_size);
+ *result = da.rbuf;
+ *rlen = da.data_size;
+ } else if (da.rbuf != NULL) {
+ (void) munmap(da.rbuf, da.rsize);
+ }
+ return (0);
+}
+
+/*
+ * Pkgsync:
+ * If the server is running, make sure that the contents
+ * file is written.
+ * If the server is not running, check for the log file;
+ * if there's a non-empty log file, we need to start the server
+ * as it will incorporate the log file into the contents file.
+ * And then check if the door is present. If it doesn't, we don't
+ * need to call it.
+ */
+
+boolean_t
+pkgsync_needed(const char *root, const char *sadmdir, boolean_t want_quit)
+{
+ struct stat pbuf;
+ char pkgfile[PATH_MAX];
+ boolean_t sync_needed, running;
+ int fd;
+ struct door_info di;
+
+ pkgfilename(pkgfile, root, sadmdir, PKGLOG);
+
+ sync_needed = stat(pkgfile, &pbuf) == 0 && pbuf.st_size > 0;
+
+ if (!sync_needed && !want_quit)
+ return (B_FALSE);
+
+ pkgfilename(pkgfile, root, sadmdir, PKGDOOR);
+
+ /* sync_needed == B_TRUE || want_quit == B_TRUE */
+ running = B_FALSE;
+
+ fd = open(pkgfile, O_RDWR);
+
+ if (fd >= 0) {
+ if (door_info(fd, &di) == 0) {
+ /* It's mounted, so the server is likely there */
+ running = B_TRUE;
+ }
+ (void) close(fd);
+ }
+ return (running || sync_needed);
+}
+
+int
+pkgsync(const char *root, const char *sadmdir, boolean_t force_quit)
+{
+ void *server;
+ pkgcmd_t cmd;
+
+ /* No need to write contents file; don't start if not running */
+ if (!pkgsync_needed(root, sadmdir, force_quit))
+ return (0);
+
+ server = pkgopenserver_i(root, sadmdir, B_FALSE, FLUSH_LOG);
+ /*
+ * We're assuming that it started the server and exited immediately.
+ * If that didn't work, there's nothing we can do.
+ */
+ if (server == NULL)
+ return (0);
+
+ cmd.cmd = force_quit ? PKG_EXIT : PKG_DUMP;
+
+ (void) pkgcmd(server, &cmd, sizeof (cmd), NULL, NULL, NULL);
+ (void) pkgcloseserver(server);
+ return (0);
+}
+
+int
+pkgservercommitfile(VFP_T *a_vfp, PKGserver server)
+{
+ size_t len = vfpGetModifiedLen(a_vfp);
+ ssize_t rem = len;
+ size_t off;
+ pkgfilter_t *pcmd;
+ char *map = a_vfp->_vfpStart;
+
+ if (len < PKGADD_MAX)
+ pcmd = alloca(sizeof (*pcmd) + len);
+ else
+ pcmd = alloca(sizeof (*pcmd) + PKGADD_MAX);
+
+
+ off = 0;
+ pcmd->cmd = PKG_ADDLINES;
+ while (rem > 0) {
+ char *p = map + off;
+ len = rem;
+
+ if (len >= PKGADD_MAX) {
+ len = PKGADD_MAX - 1;
+ while (p[len] != '\n' && len > 0)
+ len--;
+ if (p[len] != '\n')
+ return (-1);
+ len++;
+ }
+ (void) memcpy(&pcmd->buf[0], p, len);
+ pcmd->len = len;
+
+ if (pkgcmd(server, pcmd, sizeof (*pcmd) + len - 1,
+ NULL, NULL, NULL) != 0) {
+ return (-1);
+ }
+ rem -= len;
+ off += len;
+ }
+ pcmd->len = 0;
+ pcmd->cmd = PKG_PKGSYNC;
+ if (pkgcmd(server, pcmd, sizeof (*pcmd), NULL, NULL, NULL) != 0)
+ return (-1);
+
+ /* Mark it unmodified. */
+ vfpTruncate(a_vfp);
+ (void) vfpClearModified(a_vfp);
+
+ return (0);
+}
+
+int
+pkgopenfilter(PKGserver server, const char *filt)
+{
+ int fd;
+ pkgfilter_t *pfcmd;
+ int clen = filt == NULL ? 0 : strlen(filt);
+ int len = sizeof (*pfcmd) + clen;
+
+ pfcmd = alloca(len);
+
+ if (server->fp != NULL) {
+ (void) fclose(server->fp);
+ server->fp = NULL;
+ }
+
+ pfcmd->cmd = PKG_FILTER;
+ pfcmd->len = clen;
+ if (filt != NULL)
+ (void) strcpy(pfcmd->buf, filt);
+
+ fd = -1;
+
+ if (pkgcmd(server, pfcmd, len, NULL, NULL, &fd) != 0 || fd == -1) {
+ progerr(gettext(ERR_START_FILTER));
+ return (-1);
+ }
+ (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ server->fp = fdopen(fd, "r");
+ if (server->fp == NULL) {
+ (void) close(fd);
+ progerr(gettext(ERR_START_FILTER));
+ return (-1);
+ }
+ return (0);
+}
+
+void
+pkgclosefilter(PKGserver server)
+{
+ if (server->fp != NULL) {
+ (void) fclose(server->fp);
+ server->fp = NULL;
+ }
+}
+
+/*
+ * Report the next entry from the contents file.
+ */
+char *
+pkggetentry(PKGserver server, int *len, int *pathlen)
+{
+ int num[2];
+
+ if (server->fp == NULL)
+ return (NULL);
+
+ if (feof(server->fp) || ferror(server->fp))
+ return (NULL);
+
+ if (fread(num, sizeof (int), 2, server->fp) != 2)
+ return (NULL);
+
+ if (num[0] > server->buflen) {
+ free(server->curbuf);
+ server->buflen = num[0];
+ server->curbuf = malloc(server->buflen);
+ if (server->curbuf == NULL)
+ return (NULL);
+ }
+ if (fread(server->curbuf, 1, num[0], server->fp) != num[0])
+ return (NULL);
+
+ *len = num[0];
+ *pathlen = num[1];
+
+ return (server->curbuf);
+}
+
+char *
+pkggetentry_named(PKGserver server, const char *path, int *len, int *pathlen)
+{
+ int plen = strlen(path);
+ pkgfilter_t *pcmd = alloca(sizeof (*pcmd) + plen);
+ char *result;
+ unsigned int rlen;
+
+ pcmd->cmd = PKG_FINDFILE;
+ *pathlen = pcmd->len = plen;
+ (void) memcpy(pcmd->buf, path, pcmd->len + 1);
+
+ result = server->curbuf;
+ rlen = server->buflen;
+
+ if (pkgcmd(server, pcmd, sizeof (*pcmd) + pcmd->len,
+ &result, &rlen, NULL) != 0) {
+ return (NULL);
+ }
+ if (rlen == 0)
+ return (NULL);
+
+ /* Result too big */
+ if (result != server->curbuf) {
+ free(server->curbuf);
+ server->buflen = rlen;
+ server->curbuf = malloc(server->buflen);
+ if (server->curbuf == NULL)
+ return (NULL);
+ (void) memcpy(server->curbuf, result, rlen);
+ (void) munmap(result, rlen);
+ }
+ *len = rlen;
+
+ return (server->curbuf);
+}
diff --git a/usr/src/lib/libpkg/common/srchcfile.c b/usr/src/lib/libpkg/common/srchcfile.c
index dd24a855cd..bacfc5c622 100644
--- a/usr/src/lib/libpkg/common/srchcfile.c
+++ b/usr/src/lib/libpkg/common/srchcfile.c
@@ -27,8 +27,6 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-
-
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
@@ -46,7 +44,6 @@
* Forward declarations
*/
-static void findend(char **cp);
static int getend(char **cp);
static int getstr(char **cp, int n, char *str, int separator[]);
@@ -66,31 +63,10 @@ static int decisionTableInit = 0;
* These arrays must be indexable by an unsigned char.
*/
-static int ISPKGPATHSEP[UCHAR_MAX+1];
static int ISWORDSEP[UCHAR_MAX+1];
static int ISPKGNAMESEP[UCHAR_MAX+1];
/*
- * Name: WRITEDATA
- * Description: write out data to VFP_T given start and end pointers
- * Arguments: VFP - (VFP_T *) - [RO, *RW]
- * Contents file VFP to narrow search on
- * FIRSTPOS - (char *) - [RO, *RO]
- * Pointer to first byte to write out
- * LASTPOS - (char *) - [RO, *RO]
- * Pointer to last byte to write out
- */
-
-#define WRITEDATA(VFP, FIRSTPOS, LASTPOS) \
- { \
- ssize_t XXlenXX; \
- /* compute number of bytes skipped */ \
- XXlenXX = (ptrdiff_t)(LASTPOS) - (ptrdiff_t)(FIRSTPOS); \
- /* write the bytes out */ \
- vfpPutBytes((VFP), (FIRSTPOS), XXlenXX); \
- }
-
-/*
* Name: COPYPATH
* Description: copy path limiting size to destination capacity
* Arguments: DEST - (char []) - [RW]
@@ -112,214 +88,6 @@ static int ISPKGNAMESEP[UCHAR_MAX+1];
}
/*
- * Name: narrowSearch
- * Description: narrow the search location for a specified path
- * The contents and package map files are always sorted by path.
- * This function is given a target path to search for given the
- * current location in a contents file. It is assured that the
- * target path has not been searched for yet in the contents file
- * so the current location in the contents file is guaranteed to
- * be less than the location of the target path (if present).
- * Given this employ a binary search to speed up the search for
- * the path nearest to a specified target path.
- * Arguments: a_vfp - (VFP_T *) - [RO, *RW]
- * Contents file VFP to narrow search on
- * a_path - (char *) - [RO, *RO]
- * Pointer to path to search for
- * a_pathLen - (size_t) - [RO]
- * Length of string (a_path)
- * Returns: char * - pointer to first byte of entry in contents file that
- * is guaranteed to be the closest match to the specified
- * a_path without being "greater than" the path.
- * == (char *)NULL if no entry found
- */
-
-static char *
-narrowSearch(VFP_T *a_vfp, char *a_path, size_t a_pathLen)
-{
- char *phigh;
- char *plow;
- char *pmid;
- int n;
- size_t plen;
-
- /* if no path to compare, start at beginning */
-
- if ((a_path == (char *)NULL) || (*a_path == '\0')) {
- return ((char *)NULL);
- }
-
- /* if the contents file is empty, resort to sequential search */
-
- if (vfpGetBytesRemaining(a_vfp) <= 1) {
- return ((char *)NULL);
- }
-
- /*
- * test against first path - if the path specified is less than the
- * first path in the contents file, then the path can be inserted
- * before the first entry in the contents file.
- */
-
- /* locate start of first line */
-
- plow = vfpGetCurrCharPtr(a_vfp);
- pmid = plow;
-
- /* if first path not absolute, resort to sequential search */
-
- if (*pmid != '/') {
- return ((char *)NULL);
- }
-
- /* find end of path */
-
- while (ISPKGPATHSEP[(int)*pmid] == 0) {
- pmid++;
- }
-
- /* determine length of path */
-
- plen = (ptrdiff_t)pmid - (ptrdiff_t)plow;
-
- /* compare target path with current path */
-
- n = strncmp(a_path, plow, plen);
- if (n == 0) {
- /* if lengths same exact match return position found */
- if (a_pathLen == plen) {
- return (plow);
- }
- /* not exact match - a_path > pm */
- n = a_pathLen;
- }
-
- /* return if target is less than or equal to first entry */
-
- if (n <= 0) {
- return (plow);
- }
-
- /*
- * test against last path - if the path specified is greater than the
- * last path in the contents file, then the path can be appended after
- * the last entry in the contents file.
- */
-
- /* locate start of last line */
-
- plow = vfpGetCurrCharPtr(a_vfp);
- pmid = vfpGetLastCharPtr(a_vfp);
-
- while ((pmid > plow) && (!((pmid[0] == '/') && (pmid[-1] == '\n')))) {
- pmid--;
- }
-
- /* if absolute path, do comparison */
-
- if ((pmid > plow) && (*pmid == '/')) {
- plow = pmid;
-
- /* find end of path */
-
- while (ISPKGPATHSEP[(int)*pmid] == 0) {
- pmid++;
- }
-
- /* determine length of path */
-
- plen = (ptrdiff_t)pmid - (ptrdiff_t)plow;
-
- /* compare target path with current path */
-
- n = strncmp(a_path, plow, plen);
- if (n == 0) {
- /* if lengths same exact match return position found */
- if (a_pathLen == plen) {
- return (plow);
- }
- /* not exact match - a_path > pm */
- n = a_pathLen;
- }
-
- /* return if target is greater than or equal to entry */
-
- if (n >= 0) {
- return (plow);
- }
- }
- /*
- * firstPath < targetpath < lastPath:
- * binary search looking for closest "less than" match
- */
-
- plow = vfpGetCurrCharPtr(a_vfp);
- phigh = vfpGetLastCharPtr(a_vfp);
-
- for (;;) {
- char *pm;
-
- /* determine number of bytes left in search area */
-
- plen = (ptrdiff_t)phigh - (ptrdiff_t)plow;
-
- /* calculate mid point between current low and high points */
-
- pmid = plow + (plen >> 1);
-
- /* backup and find first "\n/" -or- start of buffer */
-
- while ((pmid > plow) &&
- (!((pmid[0] == '/') && (pmid[-1] == '\n')))) {
- pmid--;
- }
-
- /* return lowest line found if current line not past that */
-
- if (pmid <= plow) {
- return (plow);
- }
-
- /* remember start of this line */
-
- pm = pmid;
-
- /* find end of path */
-
- while (ISPKGPATHSEP[(int)*pmid] == 0) {
- pmid++;
- }
-
- /* determine length of path */
-
- plen = (ptrdiff_t)pmid - (ptrdiff_t)pm;
-
- /* compare target path with current path */
-
- n = strncmp(a_path, pm, plen);
-
- if (n == 0) {
- /* if lengths same exact match return position found */
- if (a_pathLen == plen) {
- return (pm);
- }
- /* not exact match - a_path > pm */
- n = a_pathLen;
- }
-
-
- /* not exact match - determine which watermark to split */
-
- if (n > 0) { /* a_path > pm */
- plow = pm;
- } else { /* a_path < pm */
- phigh = pm;
- }
- }
- /*NOTREACHED*/
-}
-
-/*
* Name: srchcfile
* Description: search contents file looking for closest match to entry,
* creating a new contents file if output contents file specified
@@ -329,34 +97,20 @@ narrowSearch(VFP_T *a_vfp, char *a_path, size_t a_pathLen)
* - path to search for in contents file
* - If path is "*", then the next entry is returned;
* the next entry always matches this path
- * - If the path is (char *)NULL or "", then all remaining
- * entries are processed and copied out to the
- * file specified by cfTmpVFp
- * cfVfp - (VFP_T *) - [RO, *RW]
- * - VFP_T open on contents file to search
- * cfTmpVfp - (VFP_T *) - [RO, *RW]
- * - VFP_T open on temporary contents file to populate
+ * PKGserver
+ * - our door to the database server.
+ *
* Returns: int
* < 0 - error occurred
* - Use getErrstr to retrieve character-string describing
* the reason for failure
* == 0 - no match found
* - specified path not in the contents file
- * - all contents of cfVfp copied to cfTmpVfp
- * - current character of cfVfp is at end of file
* == 1 - exact match found
* - specified path found in contents file
- * - contents of cfVfp up to entry found copied to cfTmpVfp
- * - current character of cfVfp is first character of
- * entry found
* - this value is always returned if path is "*" and the
- * next entry is returned - -1 is returned when no more
+ * next entry is returned - 0 is returned when no more
* entries are left to process
- * == 2 - entry found which is GREATER than path specified
- * - specified path would fit BEFORE entry found
- * - contents of cfVfp up to entry found copied to cfTmpVfp
- * - current character of cfVfp is first character of
- * entry found
* Side Effects:
* - The ept structure supplied is filled in with a description of
* the item that caused the search to terminate, except in the
@@ -368,23 +122,19 @@ narrowSearch(VFP_T *a_vfp, char *a_path, size_t a_pathLen)
*/
int
-srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
+srchcfile(struct cfent *ept, char *path, PKGserver server)
{
- char *cpath_start = (char *)NULL;
- char *firstPos = vfpGetCurrCharPtr(cfVfp);
- char *lastPos = NULL;
- char *pos;
+ char *cpath_start = NULL;
char classname[CLSSIZ+1];
char pkgname[PKGSIZ+1];
int anypath = 0;
int c;
- int dataSkipped = 0;
- int n;
- int rdpath;
- size_t cpath_len = 0;
- size_t pathLength;
+ int cpath_len = 0;
struct pinfo *lastpinfo;
struct pinfo *pinfo;
+ char *p;
+ char *curbuf;
+ int linelen; /* includes NUL */
/*
* this code does not use nested subroutines because execution time
@@ -394,7 +144,6 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
/* initialize local variables */
setErrstr(NULL); /* no error message currently cached */
- pathLength = (path == (char *)NULL ? 0 : strlen(path));
lpath[0] = '\0';
lpath[sizeof (lpath)-1] = '\0';
@@ -431,17 +180,6 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
*/
/*
- * Separators for path names, normal space and =
- * for linked filenames
- */
- bzero(ISPKGPATHSEP, sizeof (ISPKGPATHSEP));
- ISPKGPATHSEP['='] = 1; /* = */
- ISPKGPATHSEP[' '] = 1; /* space */
- ISPKGPATHSEP['\t'] = 1; /* horizontal-tab */
- ISPKGPATHSEP['\n'] = 1; /* new-line */
- ISPKGPATHSEP['\0'] = 1; /* NULL character */
-
- /*
* Separators for normal words
*/
bzero(ISWORDSEP, sizeof (ISWORDSEP));
@@ -465,16 +203,10 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
decisionTableInit = 1;
}
- /* if no bytes in contents file, return 0 */
-
- if (vfpGetBytesRemaining(cfVfp) <= 1) {
- return (0);
- }
-
/* if the path to scan for is empty, act like no path was specified */
- if ((path != (char *)NULL) && (*path == '\0')) {
- path = (char *)NULL;
+ if ((path != NULL) && (*path == '\0')) {
+ path = NULL;
}
/*
@@ -482,7 +214,7 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
* we encounter as a match, otherwise we return an error
*/
- if ((path != (char *)NULL) && (path[0] != '/')) {
+ if ((path != NULL) && (path[0] != '/')) {
if (strcmp(path, "*") != 0) {
setErrstr(pkg_gt(ERR_ILLEGAL_SEARCH_PATH));
return (-1);
@@ -492,497 +224,100 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
/* attempt to narrow down the search for the specified path */
- if (anypath == 0) {
- char *np;
-
- np = narrowSearch(cfVfp, path, pathLength);
- if (np != (char *)NULL) {
- dataSkipped = 1;
- lastPos = np;
- vfpSetCurrCharPtr(cfVfp, np);
- }
- }
+ if (anypath == 0 && path == NULL)
+ return (0);
- /*
- * If the path to search for in the source contents file is NULL, then
- * this is a request to scan to the end of the source contents file. If
- * there is a temporary contents file to copy entries to, all that needs
- * to be done is to copy the data remaining from the current location in
- * the source contents file to the end of the temporary contents file.
- * if there is no temporary contents file to copy to, then all that
- * needs to be done is to seek to the end of the source contents file.
- */
+ /* determine first character of the next entry */
+ if (anypath == 0)
+ curbuf = pkggetentry_named(server, path, &linelen, &cpath_len);
+ else
+ curbuf = pkggetentry(server, &linelen, &cpath_len);
- if ((anypath == 0) && (path == (char *)NULL)) {
- if (cfTmpVfp != (VFP_T *)NULL) {
- if (vfpGetBytesRemaining(cfVfp) > 0) {
- WRITEDATA(cfTmpVfp, firstPos,
- vfpGetLastCharPtr(cfVfp)+1);
- }
- *vfpGetLastCharPtr(cfTmpVfp) = '\0';
- }
- vfpSeekToEnd(cfVfp);
+ if (curbuf == NULL)
return (0);
- }
/*
- * *********************************************************************
- * main loop processing entries from the contents file looking for
- * the specified path
- * *********************************************************************
+ * current entry DOES start with absolute path
+ * set ept->path to point to lpath
+ * set cpath_start/cpath_len to point to the file name
*/
- for (;;) {
- char *p;
-
- /* not reading old style entry */
-
- rdpath = 0;
-
- /* determine first character of the next entry */
-
- if (vfpGetBytesRemaining(cfVfp) <= 0) {
- /* no bytes in contents file current char is NULL */
-
- c = '\0';
- } else {
- /* grab path from first entry */
-
- c = vfpGetcNoInc(cfVfp);
- }
-
- /* save current position in file */
-
- pos = vfpGetCurrCharPtr(cfVfp);
-
- /*
- * =============================================================
- * at the first character of the next entry in the contents file
- * if not absolute path check for exceptions and old style entry
- * --> if end of contents file write out skipped data and return
- * --> if comment character skip to end of line and restart loop
- * --> else process "old style entry: ftype class path"
- * =============================================================
- */
-
- if (c != '/') {
- /* if NULL character then end of contents file found */
-
- if (c == '\0') {
- /* write out skipped data before returning */
- if (dataSkipped &&
- (cfTmpVfp != (VFP_T *)NULL)) {
- WRITEDATA(cfTmpVfp, firstPos, lastPos);
- *vfpGetLastCharPtr(cfTmpVfp) = '\0';
- }
-
- return (0); /* no more entries */
- }
-
- /* ignore lines that begin with #, : or a "space" */
-
- if ((isspace(c) != 0) || (c == '#') || (c == ':')) {
- /* line is a comment */
- findend(&vfpGetCurrCharPtr(cfVfp));
- continue;
- }
-
- /*
- * old style entry - format is:
- * ftype class path
- * set ept->ftype to the type
- * set ept->class to the class
- * set ept->path to point to lpath
- * set cpath_start/cpath_len to point to the file name
- * set rdpath to '1' to indicate old style entry parsed
- */
-
- while (isspace((c = vfpGetc(cfVfp))))
- ;
-
- switch (c) {
- case '?': case 'f': case 'v': case 'e': case 'l':
- case 's': case 'p': case 'c': case 'b': case 'd':
- case 'x':
- /* save ftype */
- ept->ftype = (char)c;
-
- /* save class */
- if (getstr(&vfpGetCurrCharPtr(cfVfp), CLSSIZ,
- ept->pkg_class, ISWORDSEP)) {
- setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- }
-
- /*
- * locate file name up to "=", set cpath_start
- * and cpath_len to point to the file name
- */
- cpath_start = vfpGetCurrCharPtr(cfVfp);
- p = vfpGetCurrCharPtr(cfVfp);
-
- /*
- * skip past all bytes until first '= \t\n\0':
- */
- while (ISPKGPATHSEP[(int)*p] == 0) {
- p++;
- }
-
- cpath_len = vfpGetCurrPtrDelta(cfVfp, p);
-
- /*
- * if the path is zero bytes, line is corrupted
- */
-
- if (cpath_len < 1) {
- setErrstr(ERR_CANNOT_READ_PATHNAME_FLD);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- }
-
- vfpIncCurrPtrBy(cfVfp, cpath_len);
-
- /* set path to point to local path cache */
- ept->path = lpath;
-
- /* set flag indicating path already parsed */
- rdpath = 1;
- break;
-
- case '\0':
- /* end of line before new-line seen */
- vfpDecCurrPtr(cfVfp);
- setErrstr(ERR_INCOMPLETE_ENTRY);
- return (-1);
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- /* volume number seen */
- setErrstr(ERR_VOLUMENO_UNEXPECTED);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
-
- case 'i':
- /* type i files are not cataloged */
- setErrstr(ERR_FTYPE_I_UNEXPECTED);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
-
- default:
- /* unknown ftype */
- setErrstr(ERR_UNKNOWN_FTYPE);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- }
- } else {
- /*
- * current entry DOES start with absolute path
- * set ept->path to point to lpath
- * set cpath_start/cpath_len to point to the file name
- */
- /* copy first token into path element of passed structure */
-
- cpath_start = vfpGetCurrCharPtr(cfVfp);
-
- p = cpath_start;
-
- /*
- * skip past all bytes until first from '= \t\n\0':
- */
-
- while (ISPKGPATHSEP[(int)*p] == 0) {
- p++;
- }
-
- cpath_len = vfpGetCurrPtrDelta(cfVfp, p);
-
- vfpIncCurrPtrBy(cfVfp, cpath_len);
-
- if (vfpGetcNoInc(cfVfp) == '\0') {
- setErrstr(ERR_INCOMPLETE_ENTRY);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- }
-
- ept->path = lpath;
- }
-
- /*
- * =============================================================
- * if absolute path then the path is collected and we are at the
- * first byte following the absolute path name;
- * if not an absolute path then an old style entry, ept has been
- * filled with the type and class and path name.
- * determine if we have read the pathname which identifies
- * the entry we are searching for
- * =============================================================
- */
-
- if (anypath != 0) {
- n = 0; /* next entry is "equal to" */
- } else if (path == (char *)NULL) {
- n = 1; /* next entry is "greater than" */
- } else {
- n = strncmp(path, cpath_start, cpath_len);
- if ((n == 0) && (cpath_len != pathLength)) {
- n = cpath_len;
- }
- }
+ /* copy first token into path element of passed structure */
- /* get first character following the end of the path */
+ cpath_start = curbuf;
- c = vfpGetc(cfVfp);
+ p = cpath_start + cpath_len;
- /*
- * if an exact match, always parse out the local path
- */
+ ept->path = lpath;
- if (n == 0) {
- /*
- * we want to return information about this path in
- * the structure provided, so parse any local path
- * and jump to code which parses rest of the input line
- */
- if (c == '=') {
- /* parse local path specification */
- if (getstr(&vfpGetCurrCharPtr(cfVfp), PATH_MAX,
- mylocal, ISWORDSEP)) {
-
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- setErrstr(ERR_CANNOT_READ_LL_PATH);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- }
- ept->ainfo.local = mylocal;
- }
- }
-
- /*
- * if an exact match and processing a new style entry, read the
- * remaining information from the new style entry - if this is
- * an old style entry (rdpath != 0) then the existing info has
- * already been processed as it exists before the pathname and
- * not after like a new style entry
- */
-
- if (n == 0 && rdpath == 0) {
- while (isspace((c = vfpGetc(cfVfp))))
- ;
-
- switch (c) {
- case '?': case 'f': case 'v': case 'e': case 'l':
- case 's': case 'p': case 'c': case 'b': case 'd':
- case 'x':
- /* save ftype */
- ept->ftype = (char)c;
-
- /* save class */
- if (getstr(&vfpGetCurrCharPtr(cfVfp), CLSSIZ,
- ept->pkg_class, ISWORDSEP)) {
-
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- }
- break; /* we already read the pathname */
-
- case '\0':
- /* end of line before new-line seen */
- vfpDecCurrPtr(cfVfp);
-
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- setErrstr(ERR_INCOMPLETE_ENTRY);
- return (-1);
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
-
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- setErrstr(ERR_VOLUMENO_UNEXPECTED);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
-
- case 'i':
-
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- setErrstr(ERR_FTYPE_I_UNEXPECTED);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
-
- default:
- /* unknown ftype */
+ /* copy path found to 'lpath' */
+ COPYPATH(lpath, cpath_start, cpath_len);
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
+ /* get first character following the end of the path */
- setErrstr(ERR_UNKNOWN_FTYPE);
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- }
- }
+ c = *p++;
- /*
- * if an exact match all processing is completed; break out of
- * the main processing loop and finish processing this entry
- * prior to returning to the caller.
- */
-
- if (n == 0) {
- break;
+ /*
+ * we want to return information about this path in
+ * the structure provided, so parse any local path
+ * and jump to code which parses rest of the input line
+ */
+ if (c == '=') {
+ /* parse local path specification */
+ if (getstr(&p, PATH_MAX, mylocal, ISWORDSEP)) {
+ setErrstr(ERR_CANNOT_READ_LL_PATH);
+ return (-1);
}
+ ept->ainfo.local = mylocal;
+ }
- /*
- * this entry is not an exact match for the path being searched
- * for - if this entry is GREATER THAN the path being searched
- * for then finish processing and return GREATER THAN result
- * to the caller so the entry for the path being searched for
- * can be added to the contents file.
- */
-
- if (n < 0) {
- /*
- * the entry we want would fit BEFORE the one we just
- * read, so we need to unread what we've read by
- * seeking back to the start of this entry
- */
-
- vfpSetCurrCharPtr(cfVfp, pos);
+ /*
+ * if an exact match and processing a new style entry, read the
+ * remaining information from the new style entry.
+ */
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
+ while (isspace((c = *p++)))
+ ;
- /* write out any skipped data before returning */
- if (dataSkipped && (cfTmpVfp != (VFP_T *)NULL)) {
- WRITEDATA(cfTmpVfp, firstPos, lastPos);
- }
+ switch (c) {
+ case '?': case 'f': case 'v': case 'e': case 'l':
+ case 's': case 'p': case 'c': case 'b': case 'd':
+ case 'x':
+ /* save ftype */
+ ept->ftype = (char)c;
- return (2); /* path would insert here */
+ /* save class */
+ if (getstr(&p, CLSSIZ, ept->pkg_class, ISWORDSEP)) {
+ setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
+ return (-1);
}
+ break; /* we already read the pathname */
- /*
- * This entry is "LESS THAN" the specified path to search for
- * need to process the next entry from the contents file. First,
- * if writing to new contents file, update new contents file if
- * processing old style entry; otherwise, update skipped data
- * information to remember current last byte of skipped data.
- */
-
- if (cfTmpVfp != (VFP_T *)NULL) {
- char *px;
- ssize_t len;
-
- if (rdpath != 0) {
- /* modify record: write out any skipped data */
- if (dataSkipped) {
- WRITEDATA(cfTmpVfp, firstPos, lastPos);
- }
-
- /*
- * copy what we've read and the rest of this
- * line onto the specified output stream
- */
- vfpPutBytes(cfTmpVfp, cpath_start, cpath_len);
- vfpPutc(cfTmpVfp, c);
- vfpPutc(cfTmpVfp, ept->ftype);
- vfpPutc(cfTmpVfp, ' ');
- vfpPuts(cfTmpVfp, ept->pkg_class);
-
- px = strchr(vfpGetCurrCharPtr(cfVfp), '\n');
-
- if (px == (char *)NULL) {
- len = vfpGetBytesRemaining(cfVfp);
- vfpPutBytes(cfTmpVfp,
- vfpGetCurrCharPtr(cfVfp), len);
- vfpPutc(cfTmpVfp, '\n');
- vfpSeekToEnd(cfVfp);
- } else {
- len = vfpGetCurrPtrDelta(cfVfp, px);
- vfpPutBytes(cfTmpVfp,
- vfpGetCurrCharPtr(cfVfp), len);
- vfpIncCurrPtrBy(cfVfp, len);
- }
-
- /* reset skiped bytes if any data skipped */
- if (dataSkipped) {
- dataSkipped = 0;
- lastPos = (char *)NULL;
- firstPos = vfpGetCurrCharPtr(cfVfp);
- }
- } else {
- /* skip data */
- dataSkipped = 1;
-
- px = strchr(vfpGetCurrCharPtr(cfVfp), '\n');
-
- if (px == (char *)NULL) {
- vfpSeekToEnd(cfVfp);
- } else {
- len = vfpGetCurrPtrDelta(cfVfp, px)+1;
- vfpIncCurrPtrBy(cfVfp, len);
- }
- lastPos = vfpGetCurrCharPtr(cfVfp);
- }
- } else {
- /*
- * since this isn't the entry we want, just read the
- * stream until we find the end of this entry and
- * then start this search loop again
- */
- char *px;
-
- px = strchr(vfpGetCurrCharPtr(cfVfp), '\n');
-
- if (px == (char *)NULL) {
- vfpSeekToEnd(cfVfp);
+ case '\0':
+ /* end of line before new-line seen */
+ setErrstr(ERR_INCOMPLETE_ENTRY);
+ return (-1);
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ setErrstr(ERR_VOLUMENO_UNEXPECTED);
+ return (-1);
- setErrstr(pkg_gt(ERR_MISSING_NEWLINE));
- findend(&vfpGetCurrCharPtr(cfVfp));
- return (-1);
- } else {
- ssize_t len;
+ case 'i':
+ setErrstr(ERR_FTYPE_I_UNEXPECTED);
+ return (-1);
- len = vfpGetCurrPtrDelta(cfVfp, px)+1;
- vfpIncCurrPtrBy(cfVfp, len);
- }
- }
+ default:
+ /* unknown ftype */
+ setErrstr(ERR_UNKNOWN_FTYPE);
+ return (-1);
}
- /*
- * *********************************************************************
- * end of main loop processing entries from contents file
- * the loop is broken out of when an exact match for the
- * path being searched for has been found and the type is one of:
- * - ?fvelspcbdx
- * at this point parsing is at the first character past the full path
- * name on an exact match for the path being looked for - parse the
- * remainder of the entries information into the ept structure.
- * *********************************************************************
- */
-
/* link/symbolic link must have link destination */
if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
- (ept->ainfo.local == NULL)) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
+ (ept->ainfo.local == NULL)) {
setErrstr(ERR_NO_LINK_SOURCE_SPECIFIED);
- findend(&vfpGetCurrCharPtr(cfVfp));
return (-1);
}
@@ -991,15 +326,9 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
ept->ainfo.major = BADMAJOR;
ept->ainfo.minor = BADMINOR;
- if (getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
- (long *)&ept->ainfo.major, BADMAJOR) ||
- getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
- (long *)&ept->ainfo.minor, BADMINOR)) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
+ if (getnumvfp(&p, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
+ getnumvfp(&p, 10, (long *)&ept->ainfo.minor, BADMINOR)) {
setErrstr(pkg_gt(ERR_CANNOT_READ_MM_NUMS));
- findend(&vfpGetCurrCharPtr(cfVfp));
return (-1);
}
}
@@ -1007,21 +336,16 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
/* most types have mode, owner, group identification components */
if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
- (ept->ftype == 'b') || (ept->ftype == 'p') ||
- (ept->ftype == 'f') || (ept->ftype == 'v') ||
- (ept->ftype == 'e')) {
+ (ept->ftype == 'b') || (ept->ftype == 'p') ||
+ (ept->ftype == 'f') || (ept->ftype == 'v') ||
+ (ept->ftype == 'e')) {
/* mode, owner, group should be here */
- if (getnumvfp(&vfpGetCurrCharPtr(cfVfp), 8,
- (long *)&ept->ainfo.mode, BADMODE) ||
- getstr(&vfpGetCurrCharPtr(cfVfp), sizeof (ept->ainfo.owner),
- ept->ainfo.owner, ISWORDSEP) ||
- getstr(&vfpGetCurrCharPtr(cfVfp), sizeof (ept->ainfo.group),
- ept->ainfo.group, ISWORDSEP)) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
+ if (getnumvfp(&p, 8, (long *)&ept->ainfo.mode, BADMODE) ||
+ getstr(&p, sizeof (ept->ainfo.owner), ept->ainfo.owner,
+ ISWORDSEP) ||
+ getstr(&p, sizeof (ept->ainfo.group), ept->ainfo.group,
+ ISWORDSEP)) {
setErrstr(ERR_CANNOT_READ_MOG);
- findend(&vfpGetCurrCharPtr(cfVfp));
return (-1);
}
}
@@ -1029,19 +353,13 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
/* i/f/v/e have size, checksum, modification time components */
if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
- (ept->ftype == 'v') || (ept->ftype == 'e')) {
+ (ept->ftype == 'v') || (ept->ftype == 'e')) {
/* look for content description */
- if (getlnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
- (fsblkcnt_t *)&ept->cinfo.size, BADCONT) ||
- getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
- (long *)&ept->cinfo.cksum, BADCONT) ||
- getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
- (long *)&ept->cinfo.modtime, BADCONT)) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
+ if (getlnumvfp(&p, 10, (fsblkcnt_t *)&ept->cinfo.size,
+ BADCONT) ||
+ getnumvfp(&p, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
+ getnumvfp(&p, 10, (long *)&ept->cinfo.modtime, BADCONT)) {
setErrstr(ERR_CANNOT_READ_CONTENT_INFO);
- findend(&vfpGetCurrCharPtr(cfVfp));
return (-1);
}
}
@@ -1049,22 +367,6 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
/* i files processing is completed - return 'exact match found' */
if (ept->ftype == 'i') {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- if (getend(&vfpGetCurrCharPtr(cfVfp))) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- setErrstr(ERR_EXTRA_TOKENS);
- return (-1);
- }
-
- /* write out any skipped data before returning */
- if (dataSkipped && (cfTmpVfp != (VFP_T *)NULL)) {
- WRITEDATA(cfTmpVfp, firstPos, lastPos);
- }
-
return (1);
}
@@ -1073,16 +375,11 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
*/
lastpinfo = (struct pinfo *)NULL;
- while ((c = getstr(&vfpGetCurrCharPtr(cfVfp), sizeof (pkgname),
- pkgname, ISPKGNAMESEP)) <= 0) {
+ while ((c = getstr(&p, sizeof (pkgname), pkgname, ISPKGNAMESEP)) <= 0) {
/* if c < 0 the string was too long to fix in the buffer */
if (c < 0) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
setErrstr(ERR_PACKAGE_NAME_TOO_LONG);
- findend(&vfpGetCurrCharPtr(cfVfp));
return (-1);
}
@@ -1090,11 +387,7 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
pinfo = (struct pinfo *)calloc(1, sizeof (struct pinfo));
if (!pinfo) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
setErrstr(ERR_NO_MEMORY);
- findend(&vfpGetCurrCharPtr(cfVfp));
return (-1);
}
if (!lastpinfo) {
@@ -1105,31 +398,31 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
lastpinfo = pinfo;
if ((pkgname[0] == '-') || (pkgname[0] == '+') ||
- (pkgname[0] == '*') || (pkgname[0] == '~') ||
- (pkgname[0] == '!') || (pkgname[0] == '%')) {
+ (pkgname[0] == '*') || (pkgname[0] == '~') ||
+ (pkgname[0] == '!') || (pkgname[0] == '%')) {
pinfo->status = pkgname[0];
(void) strlcpy(pinfo->pkg, pkgname+1,
- sizeof (pinfo->pkg));
+ sizeof (pinfo->pkg));
} else {
(void) strlcpy(pinfo->pkg, pkgname,
- sizeof (pinfo->pkg));
+ sizeof (pinfo->pkg));
}
/* pkg/[:[ftype][:class] */
- c = (vfpGetc(cfVfp));
+ c = *p++;
if (c == '\\') {
/* get alternate ftype */
pinfo->editflag++;
- c = (vfpGetc(cfVfp));
+ c = *p++;
}
if (c == ':') {
/* get special classname */
- (void) getstr(&vfpGetCurrCharPtr(cfVfp),
- sizeof (classname), classname, ISWORDSEP);
+ (void) getstr(&p, sizeof (classname), classname,
+ ISWORDSEP);
(void) strlcpy(pinfo->aclass, classname,
- sizeof (pinfo->aclass));
- c = (vfpGetc(cfVfp));
+ sizeof (pinfo->aclass));
+ c = *p++;
}
ept->npkgs++;
@@ -1142,11 +435,7 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
/* if package not separated by a space return an error */
if (!isspace(c)) {
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
setErrstr(ERR_BAD_ENTRY_END);
- findend(&vfpGetCurrCharPtr(cfVfp));
return (-1);
}
}
@@ -1155,18 +444,10 @@ srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
* parsing of the entry is complete
*/
- /* copy path found to 'lpath' */
- COPYPATH(lpath, cpath_start, cpath_len);
-
- /* write out any skipped data before returning */
- if (dataSkipped && (cfTmpVfp != (VFP_T *)NULL)) {
- WRITEDATA(cfTmpVfp, firstPos, lastPos);
- }
-
/* if not at the end of the entry, make it so */
if ((c != '\n') && (c != '\0')) {
- if (getend(&vfpGetCurrCharPtr(cfVfp)) && ept->pinfo) {
+ if (getend(&p) && ept->pinfo) {
setErrstr(ERR_EXTRA_TOKENS);
return (-1);
}
@@ -1202,7 +483,7 @@ getstr(char **cp, int n, char *str, int separator[])
/* compute length based on delimiter found or not */
p1 = p;
- while (separator[(int)*p1] == 0) {
+ while (separator[(int)(*(unsigned char *)p1)] == 0) {
p1++;
}
@@ -1252,27 +533,3 @@ getend(char **cp)
*cp = ++p;
return (n);
}
-
-static void
-findend(char **cp)
-{
- char *p1;
- char *p = *cp;
-
- /* if at end of buffer return no more characters left */
-
- if (*p == '\0') {
- return;
- }
-
- /* find the end of the line */
-
- p1 = strchr(p, '\n');
-
- if (p1 != (char *)NULL) {
- *cp = ++p1;
- return;
- }
-
- *cp = strchr(p, '\0');
-}