NS_IMETHODIMP nsTemporaryFileInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, uint32_t count, uint32_t * result) { NS_ASSERTION(result, "null ptr"); NS_ASSERTION(mCurPos <= mEndPos, "bad stream state"); *result = 0; if (mClosed) { return NS_BASE_STREAM_CLOSED; } mozilla::MutexAutoLock lock(mFileDescOwner->FileMutex()); int64_t offset = PR_Seek64(mFileDescOwner->mFD, mCurPos, PR_SEEK_SET); if (offset == -1) { return NS_ErrorAccordingToNSPR(); } // Limit requested count to the amount remaining in our section of the file. count = std::min(count, uint32_t(mEndPos - mCurPos)); char buf[4096]; while (*result < count) { uint32_t bufCount = std::min(count - *result, (uint32_t) sizeof(buf)); int32_t bytesRead = PR_Read(mFileDescOwner->mFD, buf, bufCount); if (bytesRead < 0) { return NS_ErrorAccordingToNSPR(); } int32_t bytesWritten = 0; while (bytesWritten < bytesRead) { uint32_t writerCount = 0; nsresult rv = writer(this, closure, buf + bytesWritten, *result, bytesRead - bytesWritten, &writerCount); if (NS_FAILED(rv) || writerCount == 0) { // nsIInputStream::ReadSegments' contract specifies that errors // from writer are not propagated to ReadSegments' caller. // // If writer fails, leaving bytes still in buf, that's okay: we // only update mCurPos to reflect successful writes, so the call // to PR_Seek64 at the top will restart us at the right spot. return NS_OK; } NS_ASSERTION(writerCount <= (uint32_t) (bytesRead - bytesWritten), "writer should not write more than we asked it to write"); bytesWritten += writerCount; *result += writerCount; mCurPos += writerCount; } } return NS_OK; }
NS_IMETHODIMP nsMsgFileStream::Seek(PRInt32 whence, PRInt64 offset) { if (mFileDesc == nsnull) return NS_BASE_STREAM_CLOSED; nsInt64 cnt = PR_Seek64(mFileDesc, offset, (PRSeekWhence)whence); if (cnt == nsInt64(-1)) { return NS_ErrorAccordingToNSPR(); } return NS_OK; }
NS_IMETHODIMP nsMsgFileStream::Tell(PRInt64 *result) { if (mFileDesc == nsnull) return NS_BASE_STREAM_CLOSED; nsInt64 cnt = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR); if (cnt == nsInt64(-1)) { return NS_ErrorAccordingToNSPR(); } *result = cnt; return NS_OK; }
NS_IMETHODIMP MsgFileStream::Tell(int64_t *result) { if (mFileDesc == nullptr) return NS_BASE_STREAM_CLOSED; int64_t cnt = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR); if (cnt == int64_t(-1)) { return ErrorAccordingToNSPR(); } *result = cnt; return NS_OK; }
nsresult FileBlockCache::Seek(int64_t aOffset) { mFileMonitor.AssertCurrentThreadOwns(); if (mFDCurrentPos != aOffset) { int64_t result = PR_Seek64(mFD, aOffset, PR_SEEK_SET); if (result != aOffset) { NS_WARNING("Failed to seek media cache file"); return NS_ERROR_FAILURE; } mFDCurrentPos = result; } return NS_OK; }
void file_seteof(file_t file) { #if defined(XP_WIN) SetEndOfFile((HANDLE)PR_FileDesc2NativeHandle((PRFileDesc*)file)); #elif defined(XP_UNIX) PRInt64 offset = PR_Seek64((PRFileDesc*)file, 0, SEEK_CUR); if (offset < 1) { return; } ftruncate(PR_FileDesc2NativeHandle((PRFileDesc*)file), offset); #else #error not implemented #endif }
NS_IMETHODIMP MsgFileStream::Seek(int32_t whence, int64_t offset) { if (mFileDesc == nullptr) return NS_BASE_STREAM_CLOSED; bool seekingToEnd = whence == PR_SEEK_END && offset == 0; if (seekingToEnd && mSeekedToEnd) return NS_OK; int64_t cnt = PR_Seek64(mFileDesc, offset, (PRSeekWhence)whence); if (cnt == int64_t(-1)) { return ErrorAccordingToNSPR(); } mSeekedToEnd = seekingToEnd; return NS_OK; }
void * _MD_MemMap(PRFileMap *fmap, PROffset64 offset, PRUint32 len) { PRUint32 rv; void *addr; /* prevent mappings beyond EOF + remainder of page */ if (offset + len > fmap->md.maxExtent) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } if (PR_Seek64(fmap->fd, offset, PR_SEEK_SET) == -1) { return NULL; } /* try for high memory, fall back to low memory if hi-mem fails */ #if defined(MOZ_OS2_HIGH_MEMORY) rv = DosAllocMem(&addr, len, OBJ_ANY | PAG_COMMIT | PAG_READ | PAG_WRITE); if (rv) #endif { rv = DosAllocMem(&addr, len, PAG_COMMIT | PAG_READ | PAG_WRITE); if (rv) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, rv); return NULL; } } if (PR_Read(fmap->fd, addr, len) == -1) { DosFreeMem(addr); return NULL; } /* don't permit writes if readonly */ if (fmap->prot == PR_PROT_READONLY) { rv = DosSetMem(addr, len, PAG_READ); if (rv) { DosFreeMem(addr); PR_SetError(PR_UNKNOWN_ERROR, rv); return NULL; } } return addr; }
NS_IMETHODIMP nsTemporaryFileInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, uint32_t count, uint32_t * result) { NS_ASSERTION(result, "null ptr"); NS_ASSERTION(mStartPos <= mEndPos, "bad stream state"); *result = 0; if (mClosed) { return NS_BASE_STREAM_CLOSED; } mozilla::MutexAutoLock lock(mFileDescOwner->FileMutex()); PR_Seek64(mFileDescOwner->mFD, mStartPos, PR_SEEK_SET); count = std::min(count, uint32_t(mEndPos - mStartPos)); uint32_t remainBufCount = count; char buf[4096]; while (remainBufCount > 0) { uint32_t bufCount = std::min(remainBufCount, (uint32_t)sizeof(buf)); int32_t read_result = PR_Read(mFileDescOwner->mFD, buf, bufCount); if (read_result < 0) { return NS_ErrorAccordingToNSPR(); } uint32_t write_result = 0; nsresult rv = writer(this, closure, buf, count - remainBufCount, bufCount, &write_result); remainBufCount -= bufCount; if (NS_SUCCEEDED(rv)) { NS_ASSERTION(write_result <= bufCount, "writer should not write more than we asked it to write"); } mStartPos += bufCount; } *result = count; return NS_OK; }
bool mozilla::fallocate(PRFileDesc *aFD, int64_t aLength) { #if defined(HAVE_POSIX_FALLOCATE) return posix_fallocate(PR_FileDesc2NativeHandle(aFD), 0, aLength) == 0; #elif defined(XP_WIN) int64_t oldpos = PR_Seek64(aFD, 0, PR_SEEK_CUR); if (oldpos == -1) return false; if (PR_Seek64(aFD, aLength, PR_SEEK_SET) != aLength) return false; bool retval = (0 != SetEndOfFile((HANDLE)PR_FileDesc2NativeHandle(aFD))); PR_Seek64(aFD, oldpos, PR_SEEK_SET); return retval; #elif defined(XP_OS2) return aLength <= UINT32_MAX && 0 == DosSetFileSize(PR_FileDesc2NativeHandle(aFD), (uint32_t)aLength); #elif defined(XP_MACOSX) int fd = PR_FileDesc2NativeHandle(aFD); fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, aLength}; // Try to get a continous chunk of disk space int ret = fcntl(fd, F_PREALLOCATE, &store); if (-1 == ret) { // OK, perhaps we are too fragmented, allocate non-continuous store.fst_flags = F_ALLOCATEALL; ret = fcntl(fd, F_PREALLOCATE, &store); if (-1 == ret) return false; } return 0 == ftruncate(fd, aLength); #elif defined(XP_UNIX) // The following is copied from fcntlSizeHint in sqlite /* If the OS does not have posix_fallocate(), fake it. First use ** ftruncate() to set the file size, then write a single byte to ** the last byte in each block within the extended region. This ** is the same technique used by glibc to implement posix_fallocate() ** on systems that do not have a real fallocate() system call. */ int64_t oldpos = PR_Seek64(aFD, 0, PR_SEEK_CUR); if (oldpos == -1) return false; struct stat buf; int fd = PR_FileDesc2NativeHandle(aFD); if (fstat(fd, &buf)) return false; if (buf.st_size >= aLength) return false; const int nBlk = buf.st_blksize; if (!nBlk) return false; if (ftruncate(fd, aLength)) return false; int nWrite; // Return value from write() int64_t iWrite = ((buf.st_size + 2 * nBlk - 1) / nBlk) * nBlk - 1; // Next offset to write to while (iWrite < aLength) { nWrite = 0; if (PR_Seek64(aFD, iWrite, PR_SEEK_SET) == iWrite) nWrite = PR_Write(aFD, "", 1); if (nWrite != 1) break; iWrite += nBlk; } PR_Seek64(aFD, oldpos, PR_SEEK_SET); return nWrite == 1; #endif return false; }
int main(int argc, char **argv) { PRFileDesc *fd; PRInt64 offset, position; PRInt32 nbytes; char buf[MESSAGE_SIZE]; #ifdef _WIN32 HANDLE hFile; LARGE_INTEGER li; #endif /* _WIN32 */ LL_I2L(offset, 1); LL_SHL(offset, offset, 32); #ifdef _WIN32 hFile = CreateFile(TEST_FILE_NAME, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFile failed\n"); exit(1); } li.QuadPart = offset; li.LowPart = SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN); if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) { fprintf(stderr, "SetFilePointer failed\n"); exit(1); } PR_ASSERT(li.QuadPart == offset); strcpy(buf, MESSAGE); if (WriteFile(hFile, buf, sizeof(buf), &nbytes, NULL) == 0) { fprintf(stderr, "WriteFile failed\n"); exit(1); } PR_ASSERT(nbytes == sizeof(buf)); if (CloseHandle(hFile) == 0) { fprintf(stderr, "CloseHandle failed\n"); exit(1); } #endif /* _WIN32 */ memset(buf, 0, sizeof(buf)); fd = PR_Open(TEST_FILE_NAME, PR_RDONLY, 0666); if (fd == NULL) { fprintf(stderr, "PR_Open failed\n"); exit(1); } position = PR_Seek64(fd, offset, PR_SEEK_SET); if (!LL_GE_ZERO(position)) { fprintf(stderr, "PR_Seek64 failed\n"); exit(1); } PR_ASSERT(LL_EQ(position, offset)); nbytes = PR_Read(fd, buf, sizeof(buf)); if (nbytes != sizeof(buf)) { fprintf(stderr, "PR_Read failed\n"); exit(1); } if (strcmp(buf, MESSAGE)) { fprintf(stderr, "corrupt data:$%s$\n", buf); exit(1); } if (PR_Close(fd) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) { fprintf(stderr, "PR_Delete failed\n"); exit(1); } printf("PASS\n"); return 0; }
nsresult CacheFileMetadata::SyncReadMetadata(nsIFile *aFile) { LOG(("CacheFileMetadata::SyncReadMetadata() [this=%p]", this)); MOZ_ASSERT(!mListener); MOZ_ASSERT(!mHandle); MOZ_ASSERT(!mHashArray); MOZ_ASSERT(!mBuf); MOZ_ASSERT(!mWriteBuf); MOZ_ASSERT(mKey.IsEmpty()); nsresult rv; int64_t fileSize; rv = aFile->GetFileSize(&fileSize); if (NS_FAILED(rv)) { // Don't bloat the console return rv; } PRFileDesc *fd; rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0600, &fd); NS_ENSURE_SUCCESS(rv, rv); int64_t offset = PR_Seek64(fd, fileSize - sizeof(uint32_t), PR_SEEK_SET); if (offset == -1) { PR_Close(fd); return NS_ERROR_FAILURE; } uint32_t metaOffset; int32_t bytesRead = PR_Read(fd, &metaOffset, sizeof(uint32_t)); if (bytesRead != sizeof(uint32_t)) { PR_Close(fd); return NS_ERROR_FAILURE; } metaOffset = NetworkEndian::readUint32(&metaOffset); if (metaOffset > fileSize) { PR_Close(fd); return NS_ERROR_FAILURE; } mBufSize = fileSize - metaOffset; mBuf = static_cast<char *>(moz_xmalloc(mBufSize)); DoMemoryReport(MemoryUsage()); offset = PR_Seek64(fd, metaOffset, PR_SEEK_SET); if (offset == -1) { PR_Close(fd); return NS_ERROR_FAILURE; } bytesRead = PR_Read(fd, mBuf, mBufSize); PR_Close(fd); if (bytesRead != static_cast<int32_t>(mBufSize)) { return NS_ERROR_FAILURE; } rv = ParseMetadata(metaOffset, 0, false); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
int file_seek(file_t file, PRInt64 offset) { return PR_Seek64((PRFileDesc*)file, offset, PR_SEEK_SET) == offset; }