summaryrefslogtreecommitdiff
path: root/usr/src/lib/libnsctl/common/cache.c
diff options
context:
space:
mode:
authorJohn Forte <John.Forte@Sun.COM>2008-10-14 15:09:13 -0700
committerJohn Forte <John.Forte@Sun.COM>2008-10-14 15:09:13 -0700
commitfcf3ce441efd61da9bb2884968af01cb7c1452cc (patch)
tree0e80d59ad41702571586195bf099ccc14222ce02 /usr/src/lib/libnsctl/common/cache.c
parent247b82a1f1cb5ebd2d163bd9afdb1a3065611962 (diff)
downloadillumos-joyent-fcf3ce441efd61da9bb2884968af01cb7c1452cc.tar.gz
6745433 Merge NWS consolidation into OS/Net consolidation
Diffstat (limited to 'usr/src/lib/libnsctl/common/cache.c')
-rw-r--r--usr/src/lib/libnsctl/common/cache.c425
1 files changed, 425 insertions, 0 deletions
diff --git a/usr/src/lib/libnsctl/common/cache.c b/usr/src/lib/libnsctl/common/cache.c
new file mode 100644
index 0000000000..e4bbc21f25
--- /dev/null
+++ b/usr/src/lib/libnsctl/common/cache.c
@@ -0,0 +1,425 @@
+/*
+ * 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 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "libnsctl.h"
+#include <nsctl.h>
+
+
+static int _nsc_open_path(nsc_fd_t *);
+static int _nsc_open_check(nsc_fd_t *);
+
+
+/*
+ * Turn off ckdchk checking of nsc_open()'d volumes since we have no CKD
+ * formatted volumes right now. If/when we come back with CKD volumes,
+ * we could do this more sanely by completing the implementation of the
+ * CKD module, and having nsc_open() prevent any non-NSC_CKD_DISK open
+ * of a CKD volume.
+ * -- Simon, Thu Feb 18 10:49:46 GMT 1999
+ */
+static int ckdchk = 0;
+
+
+nsc_fd_t *
+nsc_open(path, flag, mode)
+char *path;
+int flag, mode;
+{
+ nsc_fd_t *fd;
+
+ if (strlen(path) >= NSC_MAXPATH) {
+ errno = ENAMETOOLONG;
+ return (0);
+ }
+
+ if (!(fd = (nsc_fd_t *)calloc(1, sizeof (nsc_fd_t))))
+ return (0);
+
+ if ((mode & O_ACCMODE) == O_WRONLY) {
+ mode &= ~O_ACCMODE;
+ mode |= O_RDWR;
+ }
+
+ fd->sf_flag = flag;
+ fd->sf_fmode = mode;
+
+ strcpy(fd->sf_path, path);
+
+ if (!_nsc_open_path(fd)) {
+ free(fd);
+ return (0);
+ }
+
+ if (ckdchk && !_nsc_open_check(fd)) {
+ (void) nsc_close(fd);
+ return (0);
+ }
+
+ return (fd);
+}
+
+
+nsc_fd_t *
+nsc_fdopen(id, path, mode)
+int id, mode;
+char *path;
+{
+ struct flock lk;
+ nsc_fd_t *fd;
+ int i;
+
+ if (strlen(path) >= NSC_MAXPATH) {
+ errno = ENAMETOOLONG;
+ return (0);
+ }
+
+ if (!(fd = (nsc_fd_t *)calloc(1, sizeof (nsc_fd_t))))
+ return (0);
+
+ lk.l_type = F_WRLCK;
+ lk.l_whence = SEEK_SET;
+ lk.l_start = 0;
+ lk.l_len = 0;
+
+ if (fcntl(id, F_SETLKW, &lk) < 0)
+ return (0);
+
+ i = fcntl(id, F_GETFL);
+
+ if ((mode & O_ACCMODE) != O_RDONLY) {
+ if ((i & O_ACCMODE) == O_RDONLY) {
+ errno = EBADF;
+ return (0);
+ }
+ }
+
+ if ((mode & O_ACCMODE) != O_WRONLY) {
+ if ((i & O_ACCMODE) == O_WRONLY) {
+ errno = EBADF;
+ return (0);
+ }
+ }
+
+ mode = (i & O_ACCMODE) | (mode & ~O_ACCMODE);
+
+ if (fcntl(id, F_SETFL, mode) < 0)
+ return (0);
+
+ if (lseek(id, 0, SEEK_SET) < 0)
+ return (0);
+
+ fd->sf_fd = id;
+ fd->sf_fmode = mode;
+
+ strcpy(fd->sf_path, path);
+
+ return (fd);
+}
+
+
+static int
+_nsc_open_path(fd)
+nsc_fd_t *fd;
+{
+ struct nscioc_open op;
+
+ memset(&op, 0, sizeof (op));
+
+ op.flag = fd->sf_flag;
+ op.mode = fd->sf_fmode;
+ strcpy(op.path, fd->sf_path);
+
+ if ((fd->sf_fd = open(_NSC_DEV_PATH, fd->sf_fmode)) < 0)
+ return (0);
+
+ if (ioctl(fd->sf_fd, NSCIOC_OPEN, &op) == 0)
+ return (1);
+
+ close(fd->sf_fd);
+ return (0);
+}
+
+
+static int
+_nsc_open_check(fd)
+nsc_fd_t *fd;
+{
+ struct flock lk;
+ char s[30];
+ pid_t pid;
+ int i;
+
+ if ((fd->sf_fmode & O_ACCMODE) == O_RDONLY)
+ return (1);
+
+ if (access(_NSC_CKDCHK_PATH, X_OK) != 0)
+ return (0);
+
+ lk.l_type = F_WRLCK;
+ lk.l_whence = SEEK_SET;
+ lk.l_start = 0;
+ lk.l_len = 0;
+
+ if (fcntl(fd->sf_fd, F_SETLKW, &lk) < 0)
+ return (0);
+
+ if ((pid = fork()) == 0) {
+ for (i = 1; i <= NSIG; i++)
+ signal(i, SIG_IGN);
+
+ for (i = fd->sf_fd; i <= 2 && (i = dup(i)) != -1; )
+ fd->sf_fd = i;
+
+ for (i = sysconf(_SC_OPEN_MAX); i >= 0; i--)
+ if (i != fd->sf_fd)
+ close(i);
+
+ fcntl(fd->sf_fd, F_SETFD, 0);
+
+ (void) open("/dev/null", 0);
+ (void) open(_NSC_CKDCHK_LOG, O_WRONLY|O_CREAT|O_APPEND, 0666);
+ (void) open(_NSC_CKDCHK_LOG, O_WRONLY|O_CREAT|O_APPEND, 0666);
+
+ (void) sprintf(s, "%d", fd->sf_fd);
+
+ (void) execl(_NSC_CKDCHK_PATH, "ckdchk", "-u", "-F",
+ s, fd->sf_path, 0);
+
+ exit(1);
+ }
+
+ return (pid != -1);
+}
+
+
+int
+nsc_close(fd)
+nsc_fd_t *fd;
+{
+ int rc;
+
+ if (!fd)
+ return (0);
+
+ rc = close(fd->sf_fd);
+ free(fd);
+
+ return (rc);
+}
+
+
+int
+nsc_reserve(fd)
+nsc_fd_t *fd;
+{
+ return ((fd) ? ioctl(fd->sf_fd, NSCIOC_RESERVE, 0) : 0);
+}
+
+
+int
+nsc_release(fd)
+nsc_fd_t *fd;
+{
+ if (!fd)
+ return (0);
+
+ if (ckdchk && (fd->sf_fmode & O_ACCMODE) != O_RDONLY) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (ioctl(fd->sf_fd, NSCIOC_RELEASE, 0));
+}
+
+
+int
+nsc_partsize(nsc_fd_t *fd, nsc_size_t *rvp)
+{
+ struct nscioc_partsize partsize;
+ int rc;
+
+ if (!fd)
+ return (0);
+
+ rc = ioctl(fd->sf_fd, NSCIOC_PARTSIZE, &partsize);
+ if (rc != 0) {
+ return (rc);
+ }
+
+ *rvp = (nsc_size_t)partsize.partsize;
+ return (0);
+}
+
+
+int
+nsc_fileno(fd)
+nsc_fd_t *fd;
+{
+ return ((fd) ? fd->sf_fd : -1);
+}
+
+
+void
+_nsc_nocheck()
+{
+ ckdchk = 0;
+}
+
+
+static int
+_nsc_do_ioctl(cmd, arg)
+int cmd;
+void *arg;
+{
+ int fd, rc, save_errno;
+
+ fd = open(_NSC_DEV_PATH, O_RDONLY);
+ if (fd < 0)
+ return (-1);
+
+ rc = save_errno = 0;
+ rc = ioctl(fd, cmd, arg);
+ if (rc < 0)
+ save_errno = errno;
+
+ close(fd);
+
+ errno = save_errno;
+ return (rc);
+}
+
+
+/*
+ * int
+ * nsc_freeze(char *path)
+ * Freeze a pathname
+ *
+ * Calling/Exit State:
+ * Returns 0 for success, or -1 and sets errno.
+ *
+ * Description:
+ * This is the user level interface to the nsctl freeze operation.
+ * See uts/common/ns/nsctl/nsc_freeze.c for more information.
+ */
+int
+nsc_freeze(path)
+char *path;
+{
+ if (strlen(path) >= NSC_MAXPATH) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ return (_nsc_do_ioctl(NSCIOC_FREEZE, path));
+}
+
+/*
+ * int
+ * nsc_unfreeze(char *path)
+ * Unfreeze a pathname
+ *
+ * Calling/Exit State:
+ * Returns 0 for success, or -1 and sets errno.
+ *
+ * Description:
+ * This is the user level interface to the nsctl unfreeze operation.
+ * See uts/common/ns/nsctl/nsc_freeze.c for more information.
+ */
+int
+nsc_unfreeze(path)
+char *path;
+{
+ if (strlen(path) >= NSC_MAXPATH) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ return (_nsc_do_ioctl(NSCIOC_UNFREEZE, path));
+}
+
+
+/*
+ * int
+ * nsc_isfrozen(char *path)
+ * Test if a pathname is frozen
+ *
+ * Calling/Exit State:
+ * Returns:
+ * 0 path is frozen
+ * 1 path is not frozen
+ * -1 error (errno will be set)
+ *
+ * Description
+ * This is the user level interface to to the nsctl isfrozen operation.
+ * See uts/common/ns/nsctl/nsc_freeze.c for more information.
+ */
+int
+nsc_isfrozen(path)
+char *path;
+{
+ if (strlen(path) >= NSC_MAXPATH) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ return (_nsc_do_ioctl(NSCIOC_ISFROZEN, path));
+}
+
+int
+nsc_gmem_sizes(int *size)
+{
+ return (_nsc_do_ioctl(NSCIOC_GLOBAL_SIZES, size));
+}
+
+int
+nsc_gmem_data(char *addr)
+{
+ return (_nsc_do_ioctl(NSCIOC_GLOBAL_DATA, addr));
+}
+
+/*
+ * int
+ * nsc_nvclean()
+ * mark nvmem clean, to prevent a warmstart of the cache on reboot
+ */
+int
+nsc_nvclean(int force)
+{
+ int cmd;
+
+ cmd = force ? NSCIOC_NVMEM_CLEANF : NSCIOC_NVMEM_CLEAN;
+
+ return (_nsc_do_ioctl(cmd, (void *)0));
+}