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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Interfaces for getting device configuration data from kernel 31 * through the devinfo driver. 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <fcntl.h> 39 #include <unistd.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #include <stdarg.h> 43 #include <unistd.h> 44 #include <libgen.h> 45 #include "libdevinfo.h" 46 47 /* Function Prototypes */ 48 static int di_dli_open(char *, int, short, int); 49 50 #define DLI_NAME 0x1 51 52 /* 53 * Private hotplug interfaces to be used between cfgadm pci plugin and 54 * devfsadm link generator. 55 */ 56 57 58 /* 59 * returns a devlink info file name derived from <path> 60 * callers need to free the returned string 61 */ 62 char * 63 di_dli_name(char *path) 64 { 65 #define dliroot "/etc/devices/dli/info." 66 #define dliroot_len (sizeof (dliroot) - 1) 67 68 char *dlipath; 69 int dlipathsz; 70 char *basep; 71 72 basep = basename(path); 73 dlipathsz = strlen(basep) + dliroot_len + 1; 74 dlipath = malloc(sizeof (char) * dlipathsz); 75 76 (void) snprintf(dlipath, dlipathsz, "%s%s", dliroot, basep); 77 dlipath[dlipathsz - 1] = '\0'; 78 return (dlipath); 79 80 #undef dlipre 81 #undef dlipre_len 82 #undef dliroot 83 #undef dliroot_len 84 } 85 86 87 static int 88 di_dli_open(char *path, int oflag, short l_type, int flags) 89 { 90 int fd; 91 char *dlipath, *dlipath_dir, *dlipath_dup; 92 struct stat statbuf; 93 int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 94 flock_t lock; 95 96 dlipath = (flags & DLI_NAME) ? di_dli_name(path) : (char *)path; 97 dlipath_dup = strdup(dlipath); 98 dlipath_dir = dirname(dlipath_dup); 99 100 if (stat(dlipath_dir, &statbuf) < 0) { 101 if (mkdirp(dlipath_dir, 102 S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) { 103 fd = -1; 104 goto OUT; 105 } 106 } 107 108 fd = open(dlipath, oflag, mode); 109 if (fd < 0) 110 goto OUT; 111 112 if (fchmod(fd, mode) < 0) { 113 (void) close(fd); 114 fd = -1; 115 goto OUT; 116 } 117 118 bzero(&lock, sizeof (lock)); 119 lock.l_type = l_type; 120 if (fcntl(fd, F_SETLKW, &lock) < 0) { 121 (void) close(fd); 122 fd = -1; 123 } 124 OUT: 125 free(dlipath_dup); 126 if (flags & DLI_NAME) 127 free(dlipath); 128 return (fd); 129 } 130 131 132 int 133 di_dli_openr(char *path) 134 { 135 return (di_dli_open(path, O_RDONLY, F_RDLCK, DLI_NAME)); 136 } 137 138 139 int 140 di_dli_openw(char *path) 141 { 142 return (di_dli_open(path, O_RDWR | O_SYNC | O_TRUNC | O_CREAT, 143 F_WRLCK, DLI_NAME)); 144 } 145 146 147 void 148 di_dli_close(int fd) 149 { 150 flock_t lock; 151 if (fd < 0) 152 return; 153 154 bzero(&lock, sizeof (lock)); 155 lock.l_type = F_UNLCK; 156 (void) fcntl(fd, F_SETLK, &lock); 157 (void) close(fd); 158 } 159