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