forked from mirrors/gecko-dev
		
	 cfb8fb313f
			
		
	
	
		cfb8fb313f
		
	
	
	
	
		
			
			This patch was generated by running:
```
perl -p -i \
     -e 's/^(\s+)([a-zA-Z0-9.]+) = NS_ConvertUTF8toUTF16\((.*)\);/\1CopyUTF8toUTF16(\3, \2);/;' \
     -e 's/^(\s+)([a-zA-Z0-9.]+) = NS_ConvertUTF16toUTF8\((.*)\);/\1CopyUTF16toUTF8(\3, \2);/;' \
     $FILE
```
against every .cpp and .h in mozilla-central, and then fixing up the
inevitable errors that happen as a result of matching C++ expressions with
regexes.  The errors fell into three categories:
1. Calling the convert functions with `std::string::c_str()`; these were
   changed to simply pass the string instead, relying on implicit conversion
   to `mozilla::Span`.
2. Calling the convert functions with raw pointers, which is not permitted
   with the copy functions; these were changed to invoke `MakeStringSpan` first.
3. Other miscellaneous errors resulting from over-eager regexes and/or the
   replacement not being type-aware.  These changes were reverted.
Differential Revision: https://phabricator.services.mozilla.com/D88903
		
	
			
		
			
				
	
	
		
			207 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "IOInterposer.h"
 | |
| #include "NSPRInterposer.h"
 | |
| 
 | |
| #include "prio.h"
 | |
| #include "private/pprio.h"
 | |
| #include "nsDebug.h"
 | |
| #include "nscore.h"
 | |
| 
 | |
| #include <sys/param.h>
 | |
| #ifdef XP_MACOSX
 | |
| #  include <fcntl.h>
 | |
| #else
 | |
| #  include "prprf.h"
 | |
| #  include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| /* Original IO methods */
 | |
| PRCloseFN sCloseFn = nullptr;
 | |
| PRReadFN sReadFn = nullptr;
 | |
| PRWriteFN sWriteFn = nullptr;
 | |
| PRFsyncFN sFSyncFn = nullptr;
 | |
| PRFileInfoFN sFileInfoFn = nullptr;
 | |
| PRFileInfo64FN sFileInfo64Fn = nullptr;
 | |
| 
 | |
| static int32_t GetPathFromFd(int32_t aFd, char* aBuf, size_t aBufSize) {
 | |
| #ifdef XP_MACOSX
 | |
|   NS_ASSERTION(aBufSize >= MAXPATHLEN,
 | |
|                "aBufSize should be a least MAXPATHLEN long");
 | |
| 
 | |
|   return fcntl(aFd, F_GETPATH, aBuf);
 | |
| #else
 | |
|   char procPath[32];
 | |
|   if (PR_snprintf(procPath, sizeof(procPath), "/proc/self/fd/%i", aFd) ==
 | |
|       (PRUint32)-1) {
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   int32_t ret = readlink(procPath, aBuf, aBufSize - 1);
 | |
|   if (ret > -1) {
 | |
|     aBuf[ret] = '\0';
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * RAII class for timing the duration of an NSPR I/O call and reporting the
 | |
|  * result to the mozilla::IOInterposeObserver API.
 | |
|  */
 | |
| class NSPRIOAutoObservation : public mozilla::IOInterposeObserver::Observation {
 | |
|  public:
 | |
|   explicit NSPRIOAutoObservation(mozilla::IOInterposeObserver::Operation aOp,
 | |
|                                  PRFileDesc* aFd)
 | |
|       : mozilla::IOInterposeObserver::Observation(aOp, "NSPRIOInterposer") {
 | |
|     char filename[MAXPATHLEN];
 | |
|     if (mShouldReport && aFd &&
 | |
|         GetPathFromFd(PR_FileDesc2NativeHandle(aFd), filename,
 | |
|                       sizeof(filename)) != -1) {
 | |
|       CopyUTF8toUTF16(mozilla::MakeStringSpan(filename), mFilename);
 | |
|     } else {
 | |
|       mFilename.Truncate();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void Filename(nsAString& aFilename) override { aFilename = mFilename; }
 | |
| 
 | |
|   ~NSPRIOAutoObservation() override { Report(); }
 | |
| 
 | |
|  private:
 | |
|   nsString mFilename;
 | |
| };
 | |
| 
 | |
| PRStatus PR_CALLBACK interposedClose(PRFileDesc* aFd) {
 | |
|   // If we don't have a valid original function pointer something is very wrong.
 | |
|   NS_ASSERTION(sCloseFn, "NSPR IO Interposing: sCloseFn is NULL");
 | |
| 
 | |
|   NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpClose, aFd);
 | |
|   return sCloseFn(aFd);
 | |
| }
 | |
| 
 | |
| int32_t PR_CALLBACK interposedRead(PRFileDesc* aFd, void* aBuf, int32_t aAmt) {
 | |
|   // If we don't have a valid original function pointer something is very wrong.
 | |
|   NS_ASSERTION(sReadFn, "NSPR IO Interposing: sReadFn is NULL");
 | |
| 
 | |
|   NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpRead, aFd);
 | |
|   return sReadFn(aFd, aBuf, aAmt);
 | |
| }
 | |
| 
 | |
| int32_t PR_CALLBACK interposedWrite(PRFileDesc* aFd, const void* aBuf,
 | |
|                                     int32_t aAmt) {
 | |
|   // If we don't have a valid original function pointer something is very wrong.
 | |
|   NS_ASSERTION(sWriteFn, "NSPR IO Interposing: sWriteFn is NULL");
 | |
| 
 | |
|   NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpWrite, aFd);
 | |
|   return sWriteFn(aFd, aBuf, aAmt);
 | |
| }
 | |
| 
 | |
| PRStatus PR_CALLBACK interposedFSync(PRFileDesc* aFd) {
 | |
|   // If we don't have a valid original function pointer something is very wrong.
 | |
|   NS_ASSERTION(sFSyncFn, "NSPR IO Interposing: sFSyncFn is NULL");
 | |
| 
 | |
|   NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpFSync, aFd);
 | |
|   return sFSyncFn(aFd);
 | |
| }
 | |
| 
 | |
| PRStatus PR_CALLBACK interposedFileInfo(PRFileDesc* aFd, PRFileInfo* aInfo) {
 | |
|   // If we don't have a valid original function pointer something is very wrong.
 | |
|   NS_ASSERTION(sFileInfoFn, "NSPR IO Interposing: sFileInfoFn is NULL");
 | |
| 
 | |
|   NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpStat, aFd);
 | |
|   return sFileInfoFn(aFd, aInfo);
 | |
| }
 | |
| 
 | |
| PRStatus PR_CALLBACK interposedFileInfo64(PRFileDesc* aFd,
 | |
|                                           PRFileInfo64* aInfo) {
 | |
|   // If we don't have a valid original function pointer something is very wrong.
 | |
|   NS_ASSERTION(sFileInfo64Fn, "NSPR IO Interposing: sFileInfo64Fn is NULL");
 | |
| 
 | |
|   NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpStat, aFd);
 | |
|   return sFileInfo64Fn(aFd, aInfo);
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| void InitNSPRIOInterposing() {
 | |
|   // Check that we have not interposed any of the IO methods before
 | |
|   MOZ_ASSERT(!sCloseFn && !sReadFn && !sWriteFn && !sFSyncFn && !sFileInfoFn &&
 | |
|              !sFileInfo64Fn);
 | |
| 
 | |
|   // We can't actually use this assertion because we initialize this code
 | |
|   // before XPCOM is initialized, so NS_IsMainThread() always returns false.
 | |
|   // MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   // Get IO methods from NSPR and const cast the structure so we can modify it.
 | |
|   PRIOMethods* methods = const_cast<PRIOMethods*>(PR_GetFileMethods());
 | |
| 
 | |
|   // Something is badly wrong if we don't get IO methods... However, we don't
 | |
|   // want to crash over that in non-debug builds. This is unlikely to happen
 | |
|   // so an assert is enough, no need to report it to the caller.
 | |
|   MOZ_ASSERT(methods);
 | |
|   if (!methods) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Store original functions
 | |
|   sCloseFn = methods->close;
 | |
|   sReadFn = methods->read;
 | |
|   sWriteFn = methods->write;
 | |
|   sFSyncFn = methods->fsync;
 | |
|   sFileInfoFn = methods->fileInfo;
 | |
|   sFileInfo64Fn = methods->fileInfo64;
 | |
| 
 | |
|   // Overwrite with our interposed functions
 | |
|   methods->close = &interposedClose;
 | |
|   methods->read = &interposedRead;
 | |
|   methods->write = &interposedWrite;
 | |
|   methods->fsync = &interposedFSync;
 | |
|   methods->fileInfo = &interposedFileInfo;
 | |
|   methods->fileInfo64 = &interposedFileInfo64;
 | |
| }
 | |
| 
 | |
| void ClearNSPRIOInterposing() {
 | |
|   // If we have already cleared IO interposing, or not initialized it this is
 | |
|   // actually bad.
 | |
|   MOZ_ASSERT(sCloseFn && sReadFn && sWriteFn && sFSyncFn && sFileInfoFn &&
 | |
|              sFileInfo64Fn);
 | |
| 
 | |
|   // Get IO methods from NSPR and const cast the structure so we can modify it.
 | |
|   PRIOMethods* methods = const_cast<PRIOMethods*>(PR_GetFileMethods());
 | |
| 
 | |
|   // Something is badly wrong if we don't get IO methods... However, we don't
 | |
|   // want to crash over that in non-debug builds. This is unlikely to happen
 | |
|   // so an assert is enough, no need to report it to the caller.
 | |
|   MOZ_ASSERT(methods);
 | |
|   if (!methods) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Restore original functions
 | |
|   methods->close = sCloseFn;
 | |
|   methods->read = sReadFn;
 | |
|   methods->write = sWriteFn;
 | |
|   methods->fsync = sFSyncFn;
 | |
|   methods->fileInfo = sFileInfoFn;
 | |
|   methods->fileInfo64 = sFileInfo64Fn;
 | |
| 
 | |
|   // Forget about original functions
 | |
|   sCloseFn = nullptr;
 | |
|   sReadFn = nullptr;
 | |
|   sWriteFn = nullptr;
 | |
|   sFSyncFn = nullptr;
 | |
|   sFileInfoFn = nullptr;
 | |
|   sFileInfo64Fn = nullptr;
 | |
| }
 | |
| 
 | |
| }  // namespace mozilla
 |