1// FDManager.cpp 2 3#include <new> 4 5#include <dirent.h> 6#include <errno.h> 7#include <fcntl.h> 8 9#include <Directory.h> 10#include <Entry.h> 11#include <File.h> 12#include <fs_attr.h> 13 14#include "AutoLocker.h" 15#include "FDManager.h" 16 17// FD constants 18static const int32 kDefaultFDLimit = 512; 19static const int32 kFDLimitIncrement = 128; 20 21// private BeOS syscall to set the FD limit 22extern "C" int _kset_fd_limit_(int num); 23 24// constructor 25FDManager::FDManager() 26 : fLock("FD manager"), 27 fFDLimit(kDefaultFDLimit) 28{ 29} 30 31// destructor 32FDManager::~FDManager() 33{ 34} 35 36// Init 37status_t 38FDManager::Init() 39{ 40 return _kset_fd_limit_(fFDLimit); 41} 42 43// CreateDefault 44status_t 45FDManager::CreateDefault() 46{ 47 if (sManager) 48 return B_OK; 49 50 FDManager* manager = new(nothrow) FDManager; 51 if (!manager) 52 return B_NO_MEMORY; 53 54 status_t error = manager->Init(); 55 if (error != B_OK) { 56 delete manager; 57 return error; 58 } 59 60 sManager = manager; 61 return B_OK; 62} 63 64// DeleteDefault 65void 66FDManager::DeleteDefault() 67{ 68 if (sManager) { 69 delete sManager; 70 sManager = NULL; 71 } 72} 73 74// GetDefault 75FDManager* 76FDManager::GetDefault() 77{ 78 return sManager; 79} 80 81// SetDirectory 82status_t 83FDManager::SetDirectory(BDirectory* directory, const node_ref* ref) 84{ 85 status_t error = directory->SetTo(ref); 86 87 if (error == B_NO_MORE_FDS) { 88 GetDefault()->_IncreaseLimit(); 89 error = directory->SetTo(ref); 90 } 91 92 return error; 93} 94 95// SetEntry 96status_t 97FDManager::SetEntry(BEntry* entry, const entry_ref* ref) 98{ 99 status_t error = entry->SetTo(ref); 100 101 if (error == B_NO_MORE_FDS) { 102 GetDefault()->_IncreaseLimit(); 103 error = entry->SetTo(ref); 104 } 105 106 return error; 107} 108 109// SetEntry 110status_t 111FDManager::SetEntry(BEntry* entry, const char* path) 112{ 113 status_t error = entry->SetTo(path); 114 115 if (error == B_NO_MORE_FDS) { 116 GetDefault()->_IncreaseLimit(); 117 error = entry->SetTo(path); 118 } 119 120 return error; 121} 122 123// SetFile 124status_t 125FDManager::SetFile(BFile* file, const char* path, uint32 openMode) 126{ 127 status_t error = file->SetTo(path, openMode); 128 129 if (error == B_NO_MORE_FDS) { 130 GetDefault()->_IncreaseLimit(); 131 error = file->SetTo(path, openMode); 132 } 133 134 return error; 135} 136 137// SetNode 138status_t 139FDManager::SetNode(BNode* node, const entry_ref* ref) 140{ 141 status_t error = node->SetTo(ref); 142 143 if (error == B_NO_MORE_FDS) { 144 GetDefault()->_IncreaseLimit(); 145 error = node->SetTo(ref); 146 } 147 148 return error; 149} 150 151// Open 152status_t 153FDManager::Open(const char* path, uint32 openMode, mode_t mode, int& fd) 154{ 155 status_t error = B_OK; 156 fd = open(path, openMode, mode); 157 if (fd < 0) 158 error = errno; 159 160 if (error == B_NO_MORE_FDS) { 161 GetDefault()->_IncreaseLimit(); 162 163 error = B_OK; 164 fd = open(path, openMode, mode); 165 if (fd < 0) 166 error = errno; 167 } 168 169 return error; 170} 171 172// OpenDir 173status_t 174FDManager::OpenDir(const char* path, DIR*& dir) 175{ 176 status_t error = B_OK; 177 dir = opendir(path); 178 if (!dir) 179 error = errno; 180 181 if (error == B_NO_MORE_FDS) { 182 GetDefault()->_IncreaseLimit(); 183 184 error = B_OK; 185 dir = opendir(path); 186 if (!dir) 187 error = errno; 188 } 189 190 return error; 191} 192 193// OpenAttrDir 194status_t 195FDManager::OpenAttrDir(const char* path, DIR*& dir) 196{ 197 status_t error = B_OK; 198 dir = fs_open_attr_dir(path); 199 if (!dir) 200 error = errno; 201 202 if (error == B_NO_MORE_FDS) { 203 GetDefault()->_IncreaseLimit(); 204 205 error = B_OK; 206 dir = fs_open_attr_dir(path); 207 if (!dir) 208 error = errno; 209 } 210 211 return error; 212} 213 214// _IncreaseLimit 215status_t 216FDManager::_IncreaseLimit() 217{ 218 AutoLocker<Locker> _(fLock); 219 220 int32 newLimit = fFDLimit + kFDLimitIncrement; 221 222 status_t error = _kset_fd_limit_(newLimit); 223 if (error == B_OK) 224 fFDLimit = newLimit; 225 226 return error; 227} 228 229 230// sManager 231FDManager* FDManager::sManager = NULL; 232