status_t Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, size_t* _length) { ASSERT(cookie != NULL); ASSERT(_buffer != NULL); ASSERT(_length != NULL); struct stat st; status_t result = Stat(&st); if (result != B_OK) return result; if ((cookie->fMode & O_APPEND) != 0) pos = st.st_size; uint64 fileSize = max_c(st.st_size, pos + *_length); fMaxFileSize = max_c(fMaxFileSize, fileSize); if ((cookie->fMode & O_NOCACHE) != 0) { WriteDirect(cookie, pos, _buffer, _length); Commit(); } result = file_cache_set_size(fFileCache, fileSize); if (result != B_OK) return result; return file_cache_write(fFileCache, cookie, pos, _buffer, _length); }
status_t Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, size_t* _length) { ASSERT(cookie != NULL); ASSERT(_buffer != NULL); ASSERT(_length != NULL); if (pos < 0) pos = 0; if ((cookie->fMode & O_RWMASK) == O_RDONLY) return B_NOT_ALLOWED; if ((cookie->fMode & O_APPEND) != 0) pos = fMaxFileSize; uint64 fileSize = pos + *_length; if (fileSize > fMaxFileSize) { status_t result = file_cache_set_size(fFileCache, fileSize); if (result != B_OK) return result; fMaxFileSize = fileSize; fMetaCache.GrowFile(fMaxFileSize); } if ((cookie->fMode & O_NOCACHE) != 0) { WriteDirect(cookie, pos, _buffer, _length); Commit(); } return file_cache_write(fFileCache, cookie, pos, _buffer, _length); }
status_t Inode::Resize(Transaction& transaction, off_t size) { TRACE("Inode::Resize() ID:%" B_PRIdINO " size: %" B_PRIdOFF "\n", ID(), size); if (size < 0) return B_BAD_VALUE; off_t oldSize = Size(); if (size == oldSize) return B_OK; TRACE("Inode::Resize(): old size: %" B_PRIdOFF ", new size: %" B_PRIdOFF "\n", oldSize, size); status_t status; if (size > oldSize) { status = _EnlargeDataStream(transaction, size); if (status != B_OK) { // Restore original size _ShrinkDataStream(transaction, oldSize); } } else status = _ShrinkDataStream(transaction, size); TRACE("Inode::Resize(): Updating file map and cache\n"); if (status != B_OK) return status; file_cache_set_size(FileCache(), size); file_map_set_size(Map(), size); TRACE("Inode::Resize(): Writing back inode changes. Size: %" B_PRIdOFF "\n", Size()); return WriteBack(transaction); }
status_t Inode::Open(int mode, OpenFileCookie* cookie) { ASSERT(cookie != NULL); MutexLocker locker(fStateLock); OpenDelegationData data; data.fType = OPEN_DELEGATE_NONE; if (fOpenState == NULL) { RevalidateFileCache(); OpenState* state = new(std::nothrow) OpenState; if (state == NULL) return B_NO_MEMORY; state->fInfo = fInfo; state->fFileSystem = fFileSystem; state->fMode = mode & O_RWMASK; status_t result = OpenFile(state, mode, &data); if (result != B_OK) { delete state; return result; } fFileSystem->AddOpenFile(state); fOpenState = state; cookie->fOpenState = state; locker.Unlock(); } else { fOpenState->AcquireReference(); cookie->fOpenState = fOpenState; locker.Unlock(); int newMode = mode & O_RWMASK; int oldMode = fOpenState->fMode & O_RWMASK; if (oldMode != newMode && oldMode != O_RDWR) { if (oldMode == O_RDONLY) RecallReadDelegation(); status_t result = OpenFile(fOpenState, O_RDWR, &data); if (result != B_OK) { locker.Lock(); ReleaseOpenState(); return result; } fOpenState->fMode = O_RDWR; } else { int newMode = mode & O_RWMASK; uint32 allowed = 0; if (newMode == O_RDWR || newMode == O_RDONLY) allowed |= R_OK; if (newMode == O_RDWR || newMode == O_WRONLY) allowed |= W_OK; status_t result = Access(allowed); if (result != B_OK) { locker.Lock(); ReleaseOpenState(); return result; } } } if ((mode & O_TRUNC) == O_TRUNC) { struct stat st; st.st_size = 0; WriteStat(&st, B_STAT_SIZE); file_cache_set_size(fFileCache, 0); } cookie->fFileSystem = fFileSystem; cookie->fMode = mode; cookie->fLocks = NULL; if (data.fType != OPEN_DELEGATE_NONE) { Delegation* delegation = new(std::nothrow) Delegation(data, this, fOpenState->fClientID); if (delegation != NULL) { delegation->fInfo = fOpenState->fInfo; delegation->fFileSystem = fFileSystem; SetDelegation(delegation); } } return B_OK; }