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) 2000-2001 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 "rdimpl.h" 38#include "rdtable.h" 39#include "rdutil.h" 40#include "rdfile.h" 41 42#define FDS_TABLE_SIZE 1024 43 44static fd_t *fd_tbl = NULL; 45static int fd_max; 46static int fd_cnt; 47static int fd_cnt_cur; 48static int fd_cnt_old; 49static fds_t *fds_tbl[FDS_TABLE_SIZE]; 50 51void 52fd_init(int n) 53{ 54 fd_max = n; 55 fd_cnt = fd_cnt_cur = fd_cnt_old = 0; 56 fd_tbl = Zalloc(sizeof (fd_t) * n); 57 (void) memset(fds_tbl, 0, sizeof (fds_t *) * FDS_TABLE_SIZE); 58} 59 60void 61fd_exit() 62{ 63 if (fd_tbl) 64 free(fd_tbl); 65} 66 67void 68fd_close(fd_t *fdp) 69{ 70 if (fdp) { 71 if (fdp->fd_fd >= 0 && fdp->fd_name[0] != '\0') { 72 (void) close(fdp->fd_fd); 73 fd_cnt--; 74 } 75 76 (void) memset(fdp, 0, sizeof (fd_t)); 77 fdp->fd_fd = -1; 78 } 79} 80 81void 82fd_closeall() 83{ 84 fd_t *fdp = fd_tbl; 85 int i; 86 87 for (i = 0; i < fd_max; i++) { 88 fd_close(fdp); 89 fdp++; 90 } 91} 92 93 94int 95fd_count() 96{ 97 fd_t *fdp = fd_tbl; 98 int count = 0; 99 int i; 100 101 for (i = 0; i < fd_max; i++, fdp++) { 102 if (fdp->fd_name[0] != '\0') { 103 ++count; 104 } 105 } 106 return (count); 107} 108 109 110static void 111fd_recycle() 112{ 113 fd_t *fdp = fd_tbl; 114 int counter; 115 int i; 116 117 counter = abs(fd_cnt_old - fd_cnt) + NUM_RESERVED_FD; 118 119 for (i = 0; i < fd_max; i++, fdp++) { 120 121 if (fdp->fd_fd == -1) 122 continue; /* skip recycled ones */ 123 124 if (fdp->fd_name[0] != '\0') { /* file has name */ 125 (void) close(fdp->fd_fd); 126 fd_cnt--; 127 counter--; 128 fdp->fd_fd = -1; 129 } 130 131 if (counter == 0) 132 break; 133 } 134} 135 136fd_t * 137fd_open(char *name, int flags, fd_t *fdp) 138{ 139 fd_t *fdp_new; 140 int fd; 141 142 if (fd_cnt > fd_max - NUM_RESERVED_FD) 143 fd_recycle(); 144 145 if (fdp != NULL) { 146 if ((strcmp(fdp->fd_name, name) == 0) && (fdp->fd_fd >= 0)) { 147 fd_cnt_cur++; 148 return (fdp); 149 } 150 } 151 152again: fd = open(name, flags); 153 154 if (fd == -1) { 155 if ((errno == EMFILE) || (errno == ENFILE)) { 156 fd_recycle(); 157 goto again; 158 } 159 fdp_new = NULL; 160 } else { 161 fdp_new = &fd_tbl[fd]; 162 fdp_new->fd_fd = fd; 163 fdp_new->fd_flags = flags; 164 (void) strcpy(fdp_new->fd_name, name); 165 fd_cnt++; 166 fd_cnt_cur++; 167 } 168 return (fdp_new); 169} 170 171int 172fd_getfd(fd_t *fdp) 173{ 174 return (fdp->fd_fd); 175} 176 177void 178fd_update() 179{ 180 fd_cnt_old = fd_cnt_cur; 181 fd_cnt_cur = 0; 182} 183 184fds_t * 185fds_get(pid_t pid) 186{ 187 fds_t *fdsp; 188 int hash = pid % FDS_TABLE_SIZE; 189 190 for (fdsp = fds_tbl[hash]; fdsp; fdsp = fdsp->fds_next) 191 if (fdsp->fds_pid == pid) /* searching for pid */ 192 return (fdsp); 193 194 fdsp = Zalloc(sizeof (fds_t)); /* adding new if pid was not found */ 195 fdsp->fds_pid = pid; 196 fdsp->fds_next = fds_tbl[hash]; 197 fds_tbl[hash] = fdsp; 198 return (fdsp); 199} 200 201void 202fds_rm(pid_t pid) 203{ 204 fds_t *fds; 205 fds_t *fds_prev = NULL; 206 int hash = pid % FDS_TABLE_SIZE; 207 208 for (fds = fds_tbl[hash]; fds && fds->fds_pid != pid; 209 fds = fds->fds_next) /* finding pid */ 210 fds_prev = fds; 211 212 if (fds) { /* if pid was found */ 213 214 fd_close(fds->fds_psinfo); 215 fd_close(fds->fds_usage); 216 fd_close(fds->fds_lpsinfo); 217 fd_close(fds->fds_lusage); 218 219 if (fds_prev) 220 fds_prev->fds_next = fds->fds_next; 221 else 222 fds_tbl[hash] = fds->fds_next; 223 224 free(fds); 225 } 226} 227