1 /* 2 * Copyright 2002-2009, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Tyler Dauwalder 7 * Ingo Weinhold, bonefish@users.sf.net 8 */ 9 10 11 #include <fcntl.h> 12 #include <unistd.h> 13 14 #include <Directory.h> 15 #include <Entry.h> 16 #include <File.h> 17 #include <fs_interface.h> 18 #include <NodeMonitor.h> 19 #include "storage_support.h" 20 21 #include <syscalls.h> 22 #include <umask.h> 23 24 25 // Creates an uninitialized BFile. 26 BFile::BFile() 27 : 28 fMode(0) 29 { 30 } 31 32 33 // Creates a copy of the supplied BFile. 34 BFile::BFile(const BFile& file) 35 : 36 fMode(0) 37 { 38 *this = file; 39 } 40 41 42 // Creates a BFile and initializes it to the file referred to by 43 // the supplied entry_ref and according to the specified open mode. 44 BFile::BFile(const entry_ref* ref, uint32 openMode) 45 : 46 fMode(0) 47 { 48 SetTo(ref, openMode); 49 } 50 51 52 // Creates a BFile and initializes it to the file referred to by 53 // the supplied BEntry and according to the specified open mode. 54 BFile::BFile(const BEntry* entry, uint32 openMode) 55 : 56 fMode(0) 57 { 58 SetTo(entry, openMode); 59 } 60 61 62 // Creates a BFile and initializes it to the file referred to by 63 // the supplied path name and according to the specified open mode. 64 BFile::BFile(const char* path, uint32 openMode) 65 : 66 fMode(0) 67 { 68 SetTo(path, openMode); 69 } 70 71 72 // Creates a BFile and initializes it to the file referred to by 73 // the supplied path name relative to the specified BDirectory and 74 // according to the specified open mode. 75 BFile::BFile(const BDirectory *dir, const char* path, uint32 openMode) 76 : 77 fMode(0) 78 { 79 SetTo(dir, path, openMode); 80 } 81 82 83 // Frees all allocated resources. 84 BFile::~BFile() 85 { 86 // Also called by the BNode destructor, but we rather try to avoid 87 // problems with calling virtual functions in the base class destructor. 88 // Depending on the compiler implementation an object may be degraded to 89 // an object of the base class after the destructor of the derived class 90 // has been executed. 91 close_fd(); 92 } 93 94 95 // Re-initializes the BFile to the file referred to by the 96 // supplied entry_ref and according to the specified open mode. 97 status_t 98 BFile::SetTo(const entry_ref* ref, uint32 openMode) 99 { 100 Unset(); 101 102 if (!ref) 103 return (fCStatus = B_BAD_VALUE); 104 105 // if ref->name is absolute, let the path-only SetTo() do the job 106 if (BPrivate::Storage::is_absolute_path(ref->name)) 107 return SetTo(ref->name, openMode); 108 109 openMode |= O_CLOEXEC; 110 111 int fd = _kern_open_entry_ref(ref->device, ref->directory, ref->name, 112 openMode, DEFFILEMODE & ~__gUmask); 113 if (fd >= 0) { 114 set_fd(fd); 115 fMode = openMode; 116 fCStatus = B_OK; 117 } else 118 fCStatus = fd; 119 120 return fCStatus; 121 } 122 123 124 // Re-initializes the BFile to the file referred to by the 125 // supplied BEntry and according to the specified open mode. 126 status_t 127 BFile::SetTo(const BEntry* entry, uint32 openMode) 128 { 129 Unset(); 130 131 if (!entry) 132 return (fCStatus = B_BAD_VALUE); 133 if (entry->InitCheck() != B_OK) 134 return (fCStatus = entry->InitCheck()); 135 136 openMode |= O_CLOEXEC; 137 138 int fd = _kern_open(entry->fDirFd, entry->fName, openMode | O_CLOEXEC, 139 DEFFILEMODE & ~__gUmask); 140 if (fd >= 0) { 141 set_fd(fd); 142 fMode = openMode; 143 fCStatus = B_OK; 144 } else 145 fCStatus = fd; 146 147 return fCStatus; 148 } 149 150 151 // Re-initializes the BFile to the file referred to by the 152 // supplied path name and according to the specified open mode. 153 status_t 154 BFile::SetTo(const char* path, uint32 openMode) 155 { 156 Unset(); 157 158 if (!path) 159 return (fCStatus = B_BAD_VALUE); 160 161 openMode |= O_CLOEXEC; 162 163 int fd = _kern_open(-1, path, openMode, DEFFILEMODE & ~__gUmask); 164 if (fd >= 0) { 165 set_fd(fd); 166 fMode = openMode; 167 fCStatus = B_OK; 168 } else 169 fCStatus = fd; 170 171 return fCStatus; 172 } 173 174 175 // Re-initializes the BFile to the file referred to by the 176 // supplied path name relative to the specified BDirectory and 177 // according to the specified open mode. 178 status_t 179 BFile::SetTo(const BDirectory* dir, const char* path, uint32 openMode) 180 { 181 Unset(); 182 183 if (!dir) 184 return (fCStatus = B_BAD_VALUE); 185 186 openMode |= O_CLOEXEC; 187 188 int fd = _kern_open(dir->fDirFd, path, openMode, DEFFILEMODE & ~__gUmask); 189 if (fd >= 0) { 190 set_fd(fd); 191 fMode = openMode; 192 fCStatus = B_OK; 193 } else 194 fCStatus = fd; 195 196 return fCStatus; 197 } 198 199 200 // Reports whether or not the file is readable. 201 bool 202 BFile::IsReadable() const 203 { 204 return InitCheck() == B_OK 205 && ((fMode & O_RWMASK) == O_RDONLY || (fMode & O_RWMASK) == O_RDWR); 206 } 207 208 209 // Reports whether or not the file is writable. 210 bool 211 BFile::IsWritable() const 212 { 213 return InitCheck() == B_OK 214 && ((fMode & O_RWMASK) == O_WRONLY || (fMode & O_RWMASK) == O_RDWR); 215 } 216 217 218 // Reads a number of bytes from the file into a buffer. 219 ssize_t 220 BFile::Read(void* buffer, size_t size) 221 { 222 if (InitCheck() != B_OK) 223 return InitCheck(); 224 return _kern_read(get_fd(), -1, buffer, size); 225 } 226 227 228 // Reads a number of bytes from a certain position within the file 229 // into a buffer. 230 ssize_t 231 BFile::ReadAt(off_t location, void* buffer, size_t size) 232 { 233 if (InitCheck() != B_OK) 234 return InitCheck(); 235 if (location < 0) 236 return B_BAD_VALUE; 237 238 return _kern_read(get_fd(), location, buffer, size); 239 } 240 241 242 // Writes a number of bytes from a buffer into the file. 243 ssize_t 244 BFile::Write(const void* buffer, size_t size) 245 { 246 if (InitCheck() != B_OK) 247 return InitCheck(); 248 return _kern_write(get_fd(), -1, buffer, size); 249 } 250 251 252 // Writes a number of bytes from a buffer at a certain position 253 // into the file. 254 ssize_t 255 BFile::WriteAt(off_t location, const void* buffer, size_t size) 256 { 257 if (InitCheck() != B_OK) 258 return InitCheck(); 259 if (location < 0) 260 return B_BAD_VALUE; 261 262 return _kern_write(get_fd(), location, buffer, size); 263 } 264 265 266 // Seeks to another read/write position within the file. 267 off_t 268 BFile::Seek(off_t offset, uint32 seekMode) 269 { 270 if (InitCheck() != B_OK) 271 return B_FILE_ERROR; 272 return _kern_seek(get_fd(), offset, seekMode); 273 } 274 275 276 // Gets the current read/write position within the file. 277 off_t 278 BFile::Position() const 279 { 280 if (InitCheck() != B_OK) 281 return B_FILE_ERROR; 282 return _kern_seek(get_fd(), 0, SEEK_CUR); 283 } 284 285 286 // Sets the size of the file. 287 status_t 288 BFile::SetSize(off_t size) 289 { 290 if (InitCheck() != B_OK) 291 return InitCheck(); 292 if (size < 0) 293 return B_BAD_VALUE; 294 struct stat statData; 295 statData.st_size = size; 296 return set_stat(statData, B_STAT_SIZE | B_STAT_SIZE_INSECURE); 297 } 298 299 300 // Gets the size of the file. 301 status_t 302 BFile::GetSize(off_t* size) const 303 { 304 return BStatable::GetSize(size); 305 } 306 307 308 // Assigns another BFile to this BFile. 309 BFile& 310 BFile::operator=(const BFile &file) 311 { 312 if (&file != this) { 313 // no need to assign us to ourselves 314 Unset(); 315 if (file.InitCheck() == B_OK) { 316 // duplicate the file descriptor 317 int fd = _kern_dup(file.get_fd()); 318 // set it 319 if (fd >= 0) { 320 fFd = fd; 321 fMode = file.fMode; 322 fCStatus = B_OK; 323 } else 324 fCStatus = fd; 325 } 326 } 327 return *this; 328 } 329 330 331 // FBC 332 void BFile::_PhiloFile1() {} 333 void BFile::_PhiloFile2() {} 334 void BFile::_PhiloFile3() {} 335 void BFile::_PhiloFile4() {} 336 void BFile::_PhiloFile5() {} 337 void BFile::_PhiloFile6() {} 338 339 340 /*! Gets the file descriptor of the BFile. 341 342 To be used instead of accessing the BNode's private \c fFd member directly. 343 344 \returns The file descriptor, or -1 if not properly initialized. 345 */ 346 int 347 BFile::get_fd() const 348 { 349 return fFd; 350 } 351 352 353 //! Overrides BNode::close_fd() for binary compatibility with BeOS R5. 354 void 355 BFile::close_fd() 356 { 357 BNode::close_fd(); 358 } 359