1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/ctfs.h> 27 #include <unistd.h> 28 #include <fcntl.h> 29 #include <errno.h> 30 #include <limits.h> 31 #include <stdio.h> 32 #include <assert.h> 33 #include <libuutil.h> 34 #include <libintl.h> 35 #include <string.h> 36 #include <procfs.h> 37 #include <libcontract.h> 38 #include <libcontract_priv.h> 39 #include "libcontract_impl.h" 40 #include "process_dump.h" 41 #include "device_dump.h" 42 43 44 contract_type_t types[CTT_MAXTYPE] = { 45 { "process", event_process }, 46 { "device", event_device } 47 }; 48 49 static int 50 close_on_exec(int fd) 51 { 52 int flags = fcntl(fd, F_GETFD, 0); 53 if ((flags != -1) && (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1)) 54 return (0); 55 return (-1); 56 } 57 58 int 59 contract_latest(ctid_t *id) 60 { 61 int cfd, r; 62 ct_stathdl_t st; 63 ctid_t result; 64 65 if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1) 66 return (errno); 67 68 if ((r = ct_status_read(cfd, CTD_COMMON, &st)) != 0) { 69 (void) close(cfd); 70 return (r); 71 } 72 73 result = ct_status_get_id(st); 74 ct_status_free(st); 75 (void) close(cfd); 76 77 *id = result; 78 return (0); 79 } 80 81 int 82 contract_open(ctid_t ctid, const char *type, const char *file, int oflag) 83 { 84 char path[PATH_MAX]; 85 int n, fd; 86 87 assert((oflag & O_CREAT) == 0); 88 89 if (type == NULL) 90 type = "all"; 91 92 n = snprintf(path, PATH_MAX, CTFS_ROOT "/%s/%ld/%s", type, ctid, file); 93 if (n >= PATH_MAX) { 94 errno = ENAMETOOLONG; 95 return (-1); 96 } 97 98 fd = open64(path, oflag); 99 if (fd != -1) { 100 if (close_on_exec(fd) == -1) { 101 int err = errno; 102 (void) close(fd); 103 errno = err; 104 return (-1); 105 } 106 } 107 return (fd); 108 } 109 110 int 111 contract_abandon_id(ctid_t ctid) 112 { 113 int fd, err; 114 115 fd = contract_open(ctid, "all", "ctl", O_WRONLY); 116 if (fd == -1) 117 return (errno); 118 119 err = ct_ctl_abandon(fd); 120 (void) close(fd); 121 122 return (err); 123 } 124 125 ctid_t 126 getctid(void) 127 { 128 int fd; 129 psinfo_t ps; 130 131 if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1) 132 return (-1); 133 if (read(fd, &ps, sizeof (ps)) != sizeof (ps)) { 134 (void) close(fd); 135 return (-1); 136 } 137 (void) close(fd); 138 return (ps.pr_contract); 139 } 140 141 void 142 contract_event_dump(FILE *file, ct_evthdl_t hdl, int verbose) 143 { 144 ct_typeid_t type; 145 struct ctlib_event_info *info = hdl; 146 147 type = info->event.ctev_cttype; 148 types[type].type_event(file, hdl, verbose); 149 } 150 151 void 152 contract_negend_dump(FILE *file, ct_evthdl_t ev) 153 { 154 ctevid_t nevid = 0; 155 ctid_t my_ctid = ct_event_get_ctid(ev); 156 ctid_t new_ctid = 0; 157 char *s; 158 159 (void) ct_event_get_nevid(ev, &nevid); 160 (void) ct_event_get_newct(ev, &new_ctid); 161 162 if (new_ctid != my_ctid) { 163 s = dgettext(TEXT_DOMAIN, "negotiation %llu succeeded\n"); 164 } else { 165 s = dgettext(TEXT_DOMAIN, "negotiation %llu failed\n"); 166 } 167 /*LINTED*/ 168 (void) fprintf(file, s, (unsigned long long)nevid); 169 } 170