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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/stat.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <stdlib.h> 33 #include <errno.h> 34 #include <string.h> 35 #include <strings.h> 36 37 #include "prtable.h" 38 #include "prutil.h" 39 #include "prfile.h" 40 41 #define FDS_TABLE_SIZE 1024 42 43 static fd_t *fd_tbl = NULL; 44 static int fd_max; 45 static int fd_cnt; 46 static int fd_cnt_cur; 47 static int fd_cnt_old; 48 static fds_t *fds_tbl[FDS_TABLE_SIZE]; 49 50 void 51 fd_init(int n) 52 { 53 fd_max = n; 54 fd_cnt = fd_cnt_cur = fd_cnt_old = 0; 55 fd_tbl = Zalloc(sizeof (fd_t) * n); 56 (void) memset(fds_tbl, 0, sizeof (fds_t *) * FDS_TABLE_SIZE); 57 } 58 59 void 60 fd_exit() 61 { 62 if (fd_tbl) 63 free(fd_tbl); 64 } 65 66 void 67 fd_close(fd_t *fdp) 68 { 69 if (fdp) { 70 if (fdp->fd_fd >= 0 && fdp->fd_name[0] != '\0') { 71 (void) close(fdp->fd_fd); 72 fd_cnt--; 73 } 74 75 (void) memset(fdp, 0, sizeof (fd_t)); 76 fdp->fd_fd = -1; 77 } 78 } 79 80 void 81 fd_closeall() 82 { 83 fd_t *fdp = fd_tbl; 84 int i; 85 86 for (i = 0; i < fd_max; i++) { 87 fd_close(fdp); 88 fdp++; 89 } 90 } 91 92 static void 93 fd_recycle() 94 { 95 fd_t *fdp = fd_tbl; 96 int counter; 97 int i; 98 99 counter = abs(fd_cnt_old - fd_cnt) + NUM_RESERVED_FD; 100 101 for (i = 0; i < fd_max; i++, fdp++) { 102 103 if (fdp->fd_fd == -1) 104 continue; /* skip recycled ones */ 105 106 if (fdp->fd_name[0] != '\0') { /* file has name */ 107 (void) close(fdp->fd_fd); 108 fd_cnt--; 109 counter--; 110 fdp->fd_fd = -1; 111 } 112 113 if (counter == 0) 114 break; 115 } 116 } 117 118 fd_t * 119 fd_open(char *name, int flags, fd_t *fdp) 120 { 121 fd_t *fdp_new; 122 int fd; 123 124 if (fd_cnt > fd_max - NUM_RESERVED_FD) 125 fd_recycle(); 126 127 if (fdp != NULL) { 128 if ((strcmp(fdp->fd_name, name) == 0) && (fdp->fd_fd >= 0)) { 129 fd_cnt_cur++; 130 return (fdp); 131 } 132 } 133 134 again: fd = open(name, flags); 135 136 if (fd == -1) { 137 if ((errno == EMFILE) || (errno == ENFILE)) { 138 fd_recycle(); 139 goto again; 140 } 141 fdp_new = NULL; 142 } else { 143 fdp_new = &fd_tbl[fd]; 144 fdp_new->fd_fd = fd; 145 fdp_new->fd_flags = flags; 146 (void) strcpy(fdp_new->fd_name, name); 147 fd_cnt++; 148 fd_cnt_cur++; 149 } 150 return (fdp_new); 151 } 152 153 int 154 fd_getfd(fd_t *fdp) 155 { 156 return (fdp->fd_fd); 157 } 158 159 void 160 fd_update() 161 { 162 fd_cnt_old = fd_cnt_cur; 163 fd_cnt_cur = 0; 164 } 165 166 fds_t * 167 fds_get(pid_t pid) 168 { 169 fds_t *fdsp; 170 int hash = pid % FDS_TABLE_SIZE; 171 172 for (fdsp = fds_tbl[hash]; fdsp; fdsp = fdsp->fds_next) 173 if (fdsp->fds_pid == pid) /* searching for pid */ 174 return (fdsp); 175 176 fdsp = Zalloc(sizeof (fds_t)); /* adding new if pid was not found */ 177 fdsp->fds_pid = pid; 178 fdsp->fds_next = fds_tbl[hash]; 179 fds_tbl[hash] = fdsp; 180 return (fdsp); 181 } 182 183 void 184 fds_rm(pid_t pid) 185 { 186 fds_t *fds; 187 fds_t *fds_prev = NULL; 188 int hash = pid % FDS_TABLE_SIZE; 189 190 for (fds = fds_tbl[hash]; fds && fds->fds_pid != pid; 191 fds = fds->fds_next) /* finding pid */ 192 fds_prev = fds; 193 194 if (fds) { /* if pid was found */ 195 196 fd_close(fds->fds_psinfo); 197 fd_close(fds->fds_usage); 198 fd_close(fds->fds_lpsinfo); 199 fd_close(fds->fds_lusage); 200 201 if (fds_prev) 202 fds_prev->fds_next = fds->fds_next; 203 else 204 fds_tbl[hash] = fds->fds_next; 205 206 free(fds); 207 } 208 } 209