NS_IMETHODIMP FileDescriptorOutputStream::Flush() { if (NS_WARN_IF(!fd)) return NS_ERROR_FAILURE; return PR_Sync(fd) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; }
NS_IMETHODIMP nsMsgFileStream::Flush(void) { if (mFileDesc == nsnull) return NS_BASE_STREAM_CLOSED; PRInt32 cnt = PR_Sync(mFileDesc); if (cnt == -1) return NS_ErrorAccordingToNSPR(); return NS_OK; }
NS_IMETHODIMP nsFileOutputStream::Flush(void) { if (mFD == nsnull) return NS_BASE_STREAM_CLOSED; PRInt32 cnt = PR_Sync(mFD); if (cnt == -1) { return NS_ErrorAccordingToNSPR(); } return NS_OK; }
NS_IMETHODIMP MsgFileStream::Flush(void) { if (mFileDesc == nullptr) return NS_BASE_STREAM_CLOSED; int32_t cnt = PR_Sync(mFileDesc); if (cnt == -1) return ErrorAccordingToNSPR(); return NS_OK; }
NS_IMETHOD Flush(void) { PR_Sync(PR_GetSpecialFD(PR_StandardOutput)); return NS_OK; }
void file_flush(file_t file) { PR_Sync((PRFileDesc*)file); }
//---------------------------------------------------------------------------------------- static int CrudeFileCopy(const char* in, const char* out) //---------------------------------------------------------------------------------------- { char buf[1024]; // Used as buffer for the copy loop PRInt32 rbytes, wbytes; // Number of bytes read and written in copy loop struct stat in_stat; // Stores informations from the stat syscall int stat_result = -1, ret; PRFileDesc * pFileDescIn, * pFileDescOut; // Src and dest pointers // Check if the pointers to filenames are valid NS_ASSERTION(in && out, "CrudeFileCopy should be called with pointers to filenames..."); // Check if the pointers are the same, if so, no need to copy A to A if (in == out) return 0; // Check if content of the pointers are the sames, if so, no need to copy A to A if (strcmp(in,out) == 0) return 0; // Retrieve the 'in' file attributes stat_result = stat(in, &in_stat); if(stat_result != 0) { // test if stat failed, it can happen if the file does not exist, is not // readable or is not available ( can happen with NFS mounts ) return -1; // Return an error } // Open the input file for binary read pFileDescIn = PR_Open(in, PR_RDONLY, 0444); if (pFileDescIn == 0) { return -1; // Open failed, return an error } // Open the output file for binary write pFileDescOut = PR_Open(out, PR_WRONLY | PR_CREATE_FILE, 0600); if (pFileDescOut == 0) { // Open failed, need to close input file, then return an error PR_Close(pFileDescOut); // Close the output file return -1; // Open failed, return an error } // Copy the data if (CrudeFileCopy_DoCopy(pFileDescIn, pFileDescOut, buf, sizeof(buf)) != 0) { // Error case PR_Close(pFileDescOut); // Close output file PR_Close(pFileDescIn); // Close input file PR_Delete(out); // Destroy output file return -1; // Return an error } // There is no need for error handling here. This should have worked, but even // if it fails, the data are now copied to destination, thus there is no need // for the function to fail on the input file error PR_Close(pFileDescIn); // It is better to call fsync and test return code before exiting to be sure // data are actually written on disk. Data loss can happen with NFS mounts if (PR_Sync(pFileDescOut) != PR_SUCCESS) { // Test if the fsync function succeeded PR_Close(pFileDescOut); // Close output file PR_Delete(out); // Destroy output file return -1; // Return an error } // Copy is done, close both file if (PR_Close(pFileDescOut) != PR_SUCCESS) // Close output file { // Output file was not closed :( PR_Delete(out); // Destroy output file return -1; // Return an error } ret = chmod(out, in_stat.st_mode & 0777); // Set the new file file mode if (ret != 0) // Test if the chmod function succeeded { PR_Delete(out); // Destroy output file return -1; // Return an error } return 0; // Still here ? ok so it worked :) } // nsFileSpec::CrudeFileCopy
JD_METHOD_(JDBool) CNSAdapter_NSPR::JD_Sync(void* fd) { return PR_Sync((PRFileDesc*)fd); }
GMPErr Write(const nsCString& aRecordName, const nsTArray<uint8_t>& aBytes) override { if (!IsOpen(aRecordName)) { return GMPClosedErr; } Record* record = nullptr; mRecords.Get(aRecordName, &record); MOZ_ASSERT(record && !!record->mFileDesc); // IsOpen() guarantees this. // Write operations overwrite the entire record. So close it now. PR_Close(record->mFileDesc); record->mFileDesc = nullptr; // Writing 0 bytes means removing (deleting) the file. if (aBytes.Length() == 0) { nsresult rv = RemoveStorageFile(record->mFilename); if (NS_WARN_IF(NS_FAILED(rv))) { // Could not delete file -> Continue with trying to erase the contents. } else { return GMPNoErr; } } // Write operations overwrite the entire record. So re-open the file // in truncate mode, to clear its contents. if (NS_FAILED(OpenStorageFile(record->mFilename, Truncate, &record->mFileDesc))) { return GMPGenericErr; } // Store the length of the record name followed by the record name // at the start of the file. int32_t bytesWritten = 0; char buf[sizeof(uint32_t)] = {0}; LittleEndian::writeUint32(buf, aRecordName.Length()); bytesWritten = PR_Write(record->mFileDesc, buf, MOZ_ARRAY_LENGTH(buf)); if (bytesWritten != MOZ_ARRAY_LENGTH(buf)) { NS_WARNING("Failed to write GMPStorage record name length."); return GMPRecordCorrupted; } bytesWritten = PR_Write(record->mFileDesc, aRecordName.get(), aRecordName.Length()); if (bytesWritten != (int32_t)aRecordName.Length()) { NS_WARNING("Failed to write GMPStorage record name."); return GMPRecordCorrupted; } bytesWritten = PR_Write(record->mFileDesc, aBytes.Elements(), aBytes.Length()); if (bytesWritten != (int32_t)aBytes.Length()) { NS_WARNING("Failed to write GMPStorage record data."); return GMPRecordCorrupted; } // Try to sync the file to disk, so that in the event of a crash, // the record is less likely to be corrupted. PR_Sync(record->mFileDesc); return GMPNoErr; }