LCOV - app.info - netwerk/base/src/nsFileStreams.cpp

LCOV - code coverage report
| Current view: | directory - netwerk/base/src - nsFileStreams.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 366 | 306 | 83.6 %
| Date: | 2012-04-21 | Functions: | 58 | 54 | 93.1 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : #include "IPC/IPCMessageUtils.h"
          39                 :
          40                 : #if defined(XP_UNIX) || defined(XP_BEOS)
          41                 : #include <unistd.h>
          42                 : #elif defined(XP_WIN)
          43                 : #include <windows.h>
          44                 : #elif defined(XP_OS2)
          45                 : #define INCL_DOSERRORS
          46                 : #include <os2.h>
          47                 : #else
          48                 : // XXX add necessary include file for ftruncate (or equivalent)
          49                 : #endif
          50                 :
          51                 : #include "private/pprio.h"
          52                 :
          53                 : #include "nsFileStreams.h"
          54                 : #include "nsILocalFile.h"
          55                 : #include "nsXPIDLString.h"
          56                 : #include "prerror.h"
          57                 : #include "nsCRT.h"
          58                 : #include "nsIFile.h"
          59                 : #include "nsDirectoryIndexStream.h"
          60                 : #include "nsMimeTypes.h"
          61                 : #include "nsReadLine.h"
          62                 : #include "nsNetUtil.h"
          63                 : #include "nsIClassInfoImpl.h"
          64                 :
          65                 : #define NS_NO_INPUT_BUFFERING 1 // see http://bugzilla.mozilla.org/show_bug.cgi?id=41067
          66                 :
          67                 : ////////////////////////////////////////////////////////////////////////////////
          68                 : // nsFileStream
          69                 :
          70           19807 : nsFileStream::nsFileStream()
          71                 :     : mFD(nsnull)
          72                 :     , mBehaviorFlags(0)
          73           19807 :     , mDeferredOpen(false)
          74                 : {
          75           19807 : }
          76                 :
          77           39614 : nsFileStream::~nsFileStream()
          78                 : {
          79           19807 :     Close();
          80           39614 : }
          81                 :
          82          305780 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileStream, nsISeekableStream)
          83                 :
          84                 : nsresult
          85           50322 : nsFileStream::Close()
          86                 : {
          87           50322 :     CleanUpOpen();
          88                 :
          89           50322 :     nsresult rv = NS_OK;
          90           50322 :     if (mFD) {
          91           19300 :         if (PR_Close(mFD) == PR_FAILURE)
          92               0 :             rv = NS_BASE_STREAM_OSERROR;
          93           19300 :         mFD = nsnull;
          94                 :     }
          95           50322 :     return rv;
          96                 : }
          97                 :
          98                 : NS_IMETHODIMP
          99            6401 : nsFileStream::Seek(PRInt32 whence, PRInt64 offset)
         100                 : {
         101            6401 :     nsresult rv = DoPendingOpen();
         102            6401 :     NS_ENSURE_SUCCESS(rv, rv);
         103                 :
         104            6401 :     if (mFD == nsnull)
         105               0 :         return NS_BASE_STREAM_CLOSED;
         106                 :
         107            6401 :     PRInt64 cnt = PR_Seek64(mFD, offset, (PRSeekWhence)whence);
         108            6401 :     if (cnt == PRInt64(-1)) {
         109               0 :         return NS_ErrorAccordingToNSPR();
         110                 :     }
         111            6401 :     return NS_OK;
         112                 : }
         113                 :
         114                 : NS_IMETHODIMP
         115            4226 : nsFileStream::Tell(PRInt64 *result)
         116                 : {
         117            4226 :     nsresult rv = DoPendingOpen();
         118            4226 :     NS_ENSURE_SUCCESS(rv, rv);
         119                 :
         120            4226 :     if (mFD == nsnull)
         121               0 :         return NS_BASE_STREAM_CLOSED;
         122                 :
         123            4226 :     PRInt64 cnt = PR_Seek64(mFD, 0, PR_SEEK_CUR);
         124            4226 :     if (cnt == PRInt64(-1)) {
         125               0 :         return NS_ErrorAccordingToNSPR();
         126                 :     }
         127            4226 :     *result = cnt;
         128            4226 :     return NS_OK;
         129                 : }
         130                 :
         131                 : NS_IMETHODIMP
         132             962 : nsFileStream::SetEOF()
         133                 : {
         134             962 :     if (mFD == nsnull)
         135               0 :         return NS_BASE_STREAM_CLOSED;
         136                 :
         137                 : #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
         138                 :     // Some system calls require an EOF offset.
         139                 :     PRInt64 offset;
         140             962 :     nsresult rv = Tell(&offset);
         141             962 :     if (NS_FAILED(rv)) return rv;
         142                 : #endif
         143                 :
         144                 : #if defined(XP_UNIX) || defined(XP_BEOS)
         145             962 :     if (ftruncate(PR_FileDesc2NativeHandle(mFD), offset) != 0) {
         146               0 :         NS_ERROR("ftruncate failed");
         147               0 :         return NS_ERROR_FAILURE;
         148                 :     }
         149                 : #elif defined(XP_WIN)
         150                 :     if (!SetEndOfFile((HANDLE) PR_FileDesc2NativeHandle(mFD))) {
         151                 :         NS_ERROR("SetEndOfFile failed");
         152                 :         return NS_ERROR_FAILURE;
         153                 :     }
         154                 : #elif defined(XP_OS2)
         155                 :     if (DosSetFileSize((HFILE) PR_FileDesc2NativeHandle(mFD), offset) != NO_ERROR) {
         156                 :         NS_ERROR("DosSetFileSize failed");
         157                 :         return NS_ERROR_FAILURE;
         158                 :     }
         159                 : #else
         160                 :     // XXX not implemented
         161                 : #endif
         162                 :
         163             962 :     return NS_OK;
         164                 : }
         165                 :
         166                 : nsresult
         167           20054 : nsFileStream::MaybeOpen(nsILocalFile* aFile, PRInt32 aIoFlags, PRInt32 aPerm,
         168                 :                         bool aDeferred)
         169                 : {
         170           20054 :     mOpenParams.ioFlags = aIoFlags;
         171           20054 :     mOpenParams.perm = aPerm;
         172                 :
         173           20054 :     if (aDeferred) {
         174                 :         // Clone the file, as it may change between now and the deferred open
         175            2260 :         nsCOMPtr<nsIFile> file;
         176            1130 :         nsresult rv = aFile->Clone(getter_AddRefs(file));
         177            1130 :         NS_ENSURE_SUCCESS(rv, rv);
         178                 :
         179            1130 :         mOpenParams.localFile = do_QueryInterface(file);
         180            1130 :         NS_ENSURE_TRUE(mOpenParams.localFile, NS_ERROR_UNEXPECTED);
         181                 :
         182            1130 :         mDeferredOpen = true;
         183            1130 :         return NS_OK;
         184                 :     }
         185                 :
         186           18924 :     mOpenParams.localFile = aFile;
         187                 :
         188           18924 :     return DoOpen();
         189                 : }
         190                 :
         191                 : void
         192           70367 : nsFileStream::CleanUpOpen()
         193                 : {
         194           70367 :     mOpenParams.localFile = nsnull;
         195           70367 :     mDeferredOpen = false;
         196           70367 : }
         197                 :
         198                 : nsresult
         199           20045 : nsFileStream::DoOpen()
         200                 : {
         201           20045 :     NS_PRECONDITION(mOpenParams.localFile, "Must have a file to open");
         202                 :
         203                 :     PRFileDesc* fd;
         204           20045 :     nsresult rv = mOpenParams.localFile->OpenNSPRFileDesc(mOpenParams.ioFlags, mOpenParams.perm, &fd);
         205           20045 :     CleanUpOpen();
         206           20045 :     if (NS_FAILED(rv)) return rv;
         207           19300 :     mFD = fd;
         208                 :
         209           19300 :     return NS_OK;
         210                 : }
         211                 :
         212                 : nsresult
         213          567152 : nsFileStream::DoPendingOpen()
         214                 : {
         215          567152 :     if (!mDeferredOpen) {
         216          566031 :         return NS_OK;
         217                 :     }
         218                 :
         219            1121 :     return DoOpen();
         220                 : }
         221                 :
         222                 : ////////////////////////////////////////////////////////////////////////////////
         223                 : // nsFileInputStream
         224                 :
         225           92914 : NS_IMPL_ADDREF_INHERITED(nsFileInputStream, nsFileStream)
         226           92914 : NS_IMPL_RELEASE_INHERITED(nsFileInputStream, nsFileStream)
         227                 :
         228                 : NS_IMPL_CLASSINFO(nsFileInputStream, NULL, nsIClassInfo::THREADSAFE,
         229                 :                   NS_LOCALFILEINPUTSTREAM_CID)
         230                 :
         231           81572 : NS_INTERFACE_MAP_BEGIN(nsFileInputStream)
         232           81572 :     NS_INTERFACE_MAP_ENTRY(nsFileStream)
         233           80740 :     NS_INTERFACE_MAP_ENTRY(nsIInputStream)
         234           56787 :     NS_INTERFACE_MAP_ENTRY(nsIFileInputStream)
         235           25489 :     NS_INTERFACE_MAP_ENTRY(nsILineInputStream)
         236           24997 :     NS_INTERFACE_MAP_ENTRY(nsIIPCSerializable)
         237           24997 :     NS_IMPL_QUERY_CLASSINFO(nsFileInputStream)
         238           22128 : NS_INTERFACE_MAP_END_INHERITING(nsFileStream)
         239                 :
         240             925 : NS_IMPL_CI_INTERFACE_GETTER5(nsFileInputStream,
         241                 :                              nsIInputStream,
         242                 :                              nsIFileInputStream,
         243                 :                              nsISeekableStream,
         244                 :                              nsILineInputStream,
         245             925 :                              nsIIPCSerializable)
         246                 :
         247                 : nsresult
         248           15613 : nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
         249                 : {
         250           15613 :     NS_ENSURE_NO_AGGREGATION(aOuter);
         251                 :
         252           15613 :     nsFileInputStream* stream = new nsFileInputStream();
         253           15613 :     if (stream == nsnull)
         254               0 :         return NS_ERROR_OUT_OF_MEMORY;
         255           15613 :     NS_ADDREF(stream);
         256           15613 :     nsresult rv = stream->QueryInterface(aIID, aResult);
         257           15613 :     NS_RELEASE(stream);
         258           15613 :     return rv;
         259                 : }
         260                 :
         261                 : nsresult
         262           15666 : nsFileInputStream::Open(nsIFile* aFile, PRInt32 aIOFlags, PRInt32 aPerm)
         263                 : {
         264           15666 :     nsresult rv = NS_OK;
         265                 :
         266                 :     // If the previous file is open, close it
         267           15666 :     if (mFD) {
         268               0 :         rv = Close();
         269               0 :         if (NS_FAILED(rv)) return rv;
         270                 :     }
         271                 :
         272                 :     // Open the file
         273           31332 :     nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFile, &rv);
         274           15666 :     if (NS_FAILED(rv)) return rv;
         275           15666 :     if (aIOFlags == -1)
         276           13294 :         aIOFlags = PR_RDONLY;
         277           15666 :     if (aPerm == -1)
         278           13864 :         aPerm = 0;
         279                 :
         280                 :     rv = MaybeOpen(localFile, aIOFlags, aPerm,
         281           15666 :                    mBehaviorFlags & nsIFileInputStream::DEFER_OPEN);
         282           15666 :     if (NS_FAILED(rv)) return rv;
         283                 :
         284           14924 :     if (mBehaviorFlags & DELETE_ON_CLOSE) {
         285                 :         // POSIX compatible filesystems allow a file to be unlinked while a
         286                 :         // file descriptor is still referencing the file.  since we've already
         287                 :         // opened the file descriptor, we'll try to remove the file.  if that
         288                 :         // fails, then we'll just remember the nsIFile and remove it after we
         289                 :         // close the file descriptor.
         290               1 :         rv = aFile->Remove(false);
         291               1 :         if (NS_SUCCEEDED(rv)) {
         292                 :           // No need to remove it later. Clear the flag.
         293               1 :           mBehaviorFlags &= ~DELETE_ON_CLOSE;
         294                 :         }
         295                 :     }
         296                 :
         297           14924 :     return NS_OK;
         298                 : }
         299                 :
         300                 : NS_IMETHODIMP
         301           15662 : nsFileInputStream::Init(nsIFile* aFile, PRInt32 aIOFlags, PRInt32 aPerm,
         302                 :                         PRInt32 aBehaviorFlags)
         303                 : {
         304           15662 :     NS_ENSURE_TRUE(!mFD, NS_ERROR_ALREADY_INITIALIZED);
         305           15662 :     NS_ENSURE_TRUE(!mDeferredOpen, NS_ERROR_ALREADY_INITIALIZED);
         306                 :
         307           15662 :     mBehaviorFlags = aBehaviorFlags;
         308                 :
         309           15662 :     mFile = aFile;
         310           15662 :     mIOFlags = aIOFlags;
         311           15662 :     mPerm = aPerm;
         312                 :
         313           15662 :     return Open(aFile, aIOFlags, aPerm);
         314                 : }
         315                 :
         316                 : NS_IMETHODIMP
         317           19989 : nsFileInputStream::Close()
         318                 : {
         319                 :     // null out mLineBuffer in case Close() is called again after failing
         320           19989 :     PR_FREEIF(mLineBuffer);
         321           19989 :     nsresult rv = nsFileStream::Close();
         322           19989 :     if (NS_FAILED(rv)) return rv;
         323           19989 :     if (mFile && (mBehaviorFlags & DELETE_ON_CLOSE)) {
         324               0 :         rv = mFile->Remove(false);
         325               0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to delete file");
         326                 :         // If we don't need to save the file for reopening, free it up
         327               0 :         if (!(mBehaviorFlags & REOPEN_ON_REWIND)) {
         328               0 :           mFile = nsnull;
         329                 :         }
         330                 :     }
         331           19989 :     return rv;
         332                 : }
         333                 :
         334                 : NS_IMETHODIMP
         335           14869 : nsFileInputStream::Available(PRUint32* aResult)
         336                 : {
         337           14869 :     nsresult rv = DoPendingOpen();
         338           14869 :     NS_ENSURE_SUCCESS(rv, rv);
         339                 :
         340           14869 :     if (!mFD) {
         341               2 :         return NS_BASE_STREAM_CLOSED;
         342                 :     }
         343                 :
         344                 :     // PR_Available with files over 4GB returns an error, so we have to
         345                 :     // use the 64-bit version of PR_Available.
         346           14867 :     PRInt64 avail = PR_Available64(mFD);
         347           14867 :     if (avail == -1) {
         348               0 :         return NS_ErrorAccordingToNSPR();
         349                 :     }
         350                 :
         351                 :     // If available is greater than 4GB, return 4GB
         352           14867 :     *aResult = avail > PR_UINT32_MAX ? PR_UINT32_MAX : (PRUint32)avail;
         353           14867 :     return NS_OK;
         354                 : }
         355                 :
         356                 : NS_IMETHODIMP
         357           32424 : nsFileInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aResult)
         358                 : {
         359           32424 :     nsresult rv = DoPendingOpen();
         360           32424 :     NS_ENSURE_SUCCESS(rv, rv);
         361                 :
         362           32424 :     if (!mFD) {
         363              13 :         *aResult = 0;
         364              13 :         return NS_OK;
         365                 :     }
         366                 :
         367           32411 :     PRInt32 bytesRead = PR_Read(mFD, aBuf, aCount);
         368           32411 :     if (bytesRead == -1) {
         369               0 :         return NS_ErrorAccordingToNSPR();
         370                 :     }
         371                 :     // Check if we're at the end of file and need to close
         372           32411 :     if (mBehaviorFlags & CLOSE_ON_EOF) {
         373            1284 :         if (bytesRead == 0) {
         374             213 :             Close();
         375                 :         }
         376                 :     }
         377                 :
         378           32411 :     *aResult = bytesRead;
         379           32411 :     return NS_OK;
         380                 : }
         381                 :
         382                 : NS_IMETHODIMP
         383           48996 : nsFileInputStream::ReadLine(nsACString& aLine, bool* aResult)
         384                 : {
         385           48996 :     nsresult rv = DoPendingOpen();
         386           48996 :     NS_ENSURE_SUCCESS(rv, rv);
         387                 :
         388           48996 :     if (!mLineBuffer) {
         389             353 :         nsresult rv = NS_InitLineBuffer(&mLineBuffer);
         390             353 :         if (NS_FAILED(rv)) return rv;
         391                 :     }
         392           48996 :     return NS_ReadLine(this, mLineBuffer, aLine, aResult);
         393                 : }
         394                 :
         395                 : NS_IMETHODIMP
         396             324 : nsFileInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
         397                 :                                 PRUint32 aCount, PRUint32* aResult)
         398                 : {
         399                 :     // ReadSegments is not implemented because it would be inefficient when
         400                 :     // the writer does not consume all data.  If you want to call ReadSegments,
         401                 :     // wrap a BufferedInputStream around the file stream.  That will call
         402                 :     // Read().
         403                 :
         404                 :     // If this is ever implemented you might need to modify
         405                 :     // nsPartialFileInputStream::ReadSegments
         406                 :
         407             324 :     return NS_ERROR_NOT_IMPLEMENTED;
         408                 : }
         409                 :
         410                 : NS_IMETHODIMP
         411              46 : nsFileInputStream::IsNonBlocking(bool *aNonBlocking)
         412                 : {
         413              46 :     *aNonBlocking = false;
         414              46 :     return NS_OK;
         415                 : }
         416                 :
         417                 : NS_IMETHODIMP
         418             913 : nsFileInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
         419                 : {
         420             913 :     nsresult rv = DoPendingOpen();
         421             913 :     NS_ENSURE_SUCCESS(rv, rv);
         422                 :
         423             913 :     PR_FREEIF(mLineBuffer); // this invalidates the line buffer
         424             913 :     if (!mFD) {
         425               4 :         if (mBehaviorFlags & REOPEN_ON_REWIND) {
         426               4 :             nsresult rv = Reopen();
         427               4 :             if (NS_FAILED(rv)) {
         428               1 :                 return rv;
         429                 :             }
         430                 :         } else {
         431               0 :             return NS_BASE_STREAM_CLOSED;
         432                 :         }
         433                 :     }
         434                 :
         435             912 :     return nsFileStream::Seek(aWhence, aOffset);
         436                 : }
         437                 :
         438                 : bool
         439               0 : nsFileInputStream::Read(const IPC::Message *aMsg, void **aIter)
         440                 : {
         441                 :     using IPC::ReadParam;
         442                 :
         443               0 :     nsCString path;
         444                 :     bool followLinks;
         445                 :     PRInt32 flags;
         446               0 :     if (!ReadParam(aMsg, aIter, &path) ||
         447               0 :         !ReadParam(aMsg, aIter, &followLinks) ||
         448               0 :         !ReadParam(aMsg, aIter, &flags))
         449               0 :         return false;
         450                 :
         451               0 :     nsCOMPtr<nsILocalFile> file;
         452               0 :     nsresult rv = NS_NewNativeLocalFile(path, followLinks, getter_AddRefs(file));
         453               0 :     if (NS_FAILED(rv))
         454               0 :         return false;
         455                 :
         456                 :     // IO flags = -1 means readonly, and
         457                 :     // permissions are unimportant since we're reading
         458               0 :     rv = Init(file, -1, -1, flags);
         459               0 :     if (NS_FAILED(rv))
         460               0 :         return false;
         461                 :
         462               0 :     return true;
         463                 : }
         464                 :
         465                 : void
         466               0 : nsFileInputStream::Write(IPC::Message *aMsg)
         467                 : {
         468                 :     using IPC::WriteParam;
         469                 :
         470               0 :     nsCString path;
         471               0 :     mFile->GetNativePath(path);
         472               0 :     WriteParam(aMsg, path);
         473               0 :     nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(mFile);
         474                 :     bool followLinks;
         475               0 :     localFile->GetFollowLinks(&followLinks);
         476               0 :     WriteParam(aMsg, followLinks);
         477               0 :     WriteParam(aMsg, mBehaviorFlags);
         478               0 : }
         479                 :
         480                 : ////////////////////////////////////////////////////////////////////////////////
         481                 : // nsPartialFileInputStream
         482                 :
         483                 : // Don't forward to nsFileInputStream as we don't want to QI to
         484                 : // nsIFileInputStream
         485            2920 : NS_IMPL_ISUPPORTS_INHERITED3(nsPartialFileInputStream,
         486                 :                              nsFileStream,
         487                 :                              nsIInputStream,
         488                 :                              nsIPartialFileInputStream,
         489                 :                              nsILineInputStream)
         490                 :
         491                 : nsresult
         492              62 : nsPartialFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID,
         493                 :                                  void **aResult)
         494                 : {
         495              62 :     NS_ENSURE_NO_AGGREGATION(aOuter);
         496                 :
         497              62 :     nsPartialFileInputStream* stream = new nsPartialFileInputStream();
         498                 :
         499              62 :     NS_ADDREF(stream);
         500              62 :     nsresult rv = stream->QueryInterface(aIID, aResult);
         501              62 :     NS_RELEASE(stream);
         502              62 :     return rv;
         503                 : }
         504                 :
         505                 : NS_IMETHODIMP
         506              62 : nsPartialFileInputStream::Init(nsIFile* aFile, PRUint64 aStart,
         507                 :                                PRUint64 aLength, PRInt32 aIOFlags,
         508                 :                                PRInt32 aPerm, PRInt32 aBehaviorFlags)
         509                 : {
         510              62 :     mStart = aStart;
         511              62 :     mLength = aLength;
         512              62 :     mPosition = 0;
         513                 :
         514                 :     nsresult rv = nsFileInputStream::Init(aFile, aIOFlags, aPerm,
         515              62 :                                           aBehaviorFlags);
         516              62 :     NS_ENSURE_SUCCESS(rv, rv);
         517                 :
         518              62 :     return nsFileInputStream::Seek(NS_SEEK_SET, mStart);
         519                 : }
         520                 :
         521                 : NS_IMETHODIMP
         522            1889 : nsPartialFileInputStream::Tell(PRInt64 *aResult)
         523                 : {
         524                 :     PRInt64 tell;
         525            1889 :     nsresult rv = nsFileInputStream::Tell(&tell);
         526            1889 :     if (NS_SUCCEEDED(rv)) {
         527            1889 :         *aResult = tell - mStart;
         528                 :     }
         529            1889 :     return rv;
         530                 : }
         531                 :
         532                 : NS_IMETHODIMP
         533            1889 : nsPartialFileInputStream::Available(PRUint32* aResult)
         534                 : {
         535                 :     PRUint32 available;
         536            1889 :     nsresult rv = nsFileInputStream::Available(&available);
         537            1889 :     if (NS_SUCCEEDED(rv)) {
         538            1889 :         *aResult = TruncateSize(available);
         539                 :     }
         540            1889 :     return rv;
         541                 : }
         542                 :
         543                 : NS_IMETHODIMP
         544             313 : nsPartialFileInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aResult)
         545                 : {
         546             313 :     PRUint32 readsize = TruncateSize(aCount);
         547             313 :     if (readsize == 0 && mBehaviorFlags & CLOSE_ON_EOF) {
         548               4 :         Close();
         549               4 :         *aResult = 0;
         550               4 :         return NS_OK;
         551                 :     }
         552                 :
         553             309 :     nsresult rv = nsFileInputStream::Read(aBuf, readsize, aResult);
         554             309 :     if (NS_SUCCEEDED(rv)) {
         555             309 :         mPosition += readsize;
         556                 :     }
         557             309 :     return rv;
         558                 : }
         559                 :
         560                 : NS_IMETHODIMP
         561             614 : nsPartialFileInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
         562                 : {
         563                 :     PRInt64 offset;
         564             614 :     switch (aWhence) {
         565                 :         case NS_SEEK_SET:
         566             166 :             offset = mStart + aOffset;
         567             166 :             break;
         568                 :         case NS_SEEK_CUR:
         569             309 :             offset = mStart + mPosition + aOffset;
         570             309 :             break;
         571                 :         case NS_SEEK_END:
         572             139 :             offset = mStart + mLength + aOffset;
         573             139 :             break;
         574                 :         default:
         575               0 :             return NS_ERROR_ILLEGAL_VALUE;
         576                 :     }
         577                 :
         578             614 :     if (offset < (PRInt64)mStart || offset > (PRInt64)(mStart + mLength)) {
         579             271 :         return NS_ERROR_INVALID_ARG;
         580                 :     }
         581                 :
         582             343 :     nsresult rv = nsFileInputStream::Seek(NS_SEEK_SET, offset);
         583             343 :     if (NS_SUCCEEDED(rv)) {
         584             342 :         mPosition = offset - mStart;
         585                 :     }
         586             343 :     return rv;
         587                 : }
         588                 :
         589                 : ////////////////////////////////////////////////////////////////////////////////
         590                 : // nsFileOutputStream
         591                 :
         592          103626 : NS_IMPL_ISUPPORTS_INHERITED2(nsFileOutputStream,
         593                 :                              nsFileStream,
         594                 :                              nsIOutputStream,
         595                 :                              nsIFileOutputStream)
         596                 :
         597                 : nsresult
         598            2627 : nsFileOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
         599                 : {
         600            2627 :     NS_ENSURE_NO_AGGREGATION(aOuter);
         601                 :
         602            2627 :     nsFileOutputStream* stream = new nsFileOutputStream();
         603            2627 :     if (stream == nsnull)
         604               0 :         return NS_ERROR_OUT_OF_MEMORY;
         605            2627 :     NS_ADDREF(stream);
         606            2627 :     nsresult rv = stream->QueryInterface(aIID, aResult);
         607            2627 :     NS_RELEASE(stream);
         608            2627 :     return rv;
         609                 : }
         610                 :
         611                 : NS_IMETHODIMP
         612            4388 : nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm,
         613                 :                          PRInt32 behaviorFlags)
         614                 : {
         615            4388 :     NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
         616            4388 :     NS_ENSURE_TRUE(!mDeferredOpen, NS_ERROR_ALREADY_INITIALIZED);
         617                 :
         618            4388 :     mBehaviorFlags = behaviorFlags;
         619                 :
         620                 :     nsresult rv;
         621            8776 :     nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file, &rv);
         622            4388 :     if (NS_FAILED(rv)) return rv;
         623            4388 :     if (ioFlags == -1)
         624              88 :         ioFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
         625            4388 :     if (perm <= 0)
         626            1228 :         perm = 0664;
         627                 :
         628                 :     return MaybeOpen(localFile, ioFlags, perm,
         629            4388 :                      mBehaviorFlags & nsIFileOutputStream::DEFER_OPEN);
         630                 : }
         631                 :
         632                 : NS_IMETHODIMP
         633           10526 : nsFileOutputStream::Close()
         634                 : {
         635           10526 :     return nsFileStream::Close();
         636                 : }
         637                 :
         638                 : NS_IMETHODIMP
         639          457824 : nsFileOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *result)
         640                 : {
         641          457824 :     nsresult rv = DoPendingOpen();
         642          457824 :     NS_ENSURE_SUCCESS(rv, rv);
         643                 :
         644          457821 :     if (mFD == nsnull)
         645               2 :         return NS_BASE_STREAM_CLOSED;
         646                 :
         647          457819 :     PRInt32 cnt = PR_Write(mFD, buf, count);
         648          457819 :     if (cnt == -1) {
         649               0 :         return NS_ErrorAccordingToNSPR();
         650                 :     }
         651          457819 :     *result = cnt;
         652          457819 :     return NS_OK;
         653                 : }
         654                 :
         655                 : NS_IMETHODIMP
         656            1499 : nsFileOutputStream::Flush(void)
         657                 : {
         658            1499 :     nsresult rv = DoPendingOpen();
         659            1499 :     NS_ENSURE_SUCCESS(rv, rv);
         660                 :
         661            1499 :     if (mFD == nsnull)
         662               0 :         return NS_BASE_STREAM_CLOSED;
         663                 :
         664            1499 :     PRInt32 cnt = PR_Sync(mFD);
         665            1499 :     if (cnt == -1) {
         666               0 :         return NS_ErrorAccordingToNSPR();
         667                 :     }
         668            1499 :     return NS_OK;
         669                 : }
         670                 :
         671                 : NS_IMETHODIMP
         672               0 : nsFileOutputStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
         673                 : {
         674               0 :     NS_NOTREACHED("WriteFrom (see source comment)");
         675               0 :     return NS_ERROR_NOT_IMPLEMENTED;
         676                 :     // File streams intentionally do not support this method.
         677                 :     // If you need something like this, then you should wrap
         678                 :     // the file stream using nsIBufferedOutputStream
         679                 : }
         680                 :
         681                 : NS_IMETHODIMP
         682             412 : nsFileOutputStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
         683                 : {
         684             412 :     return NS_ERROR_NOT_IMPLEMENTED;
         685                 :     // File streams intentionally do not support this method.
         686                 :     // If you need something like this, then you should wrap
         687                 :     // the file stream using nsIBufferedOutputStream
         688                 : }
         689                 :
         690                 : NS_IMETHODIMP
         691             248 : nsFileOutputStream::IsNonBlocking(bool *aNonBlocking)
         692                 : {
         693             248 :     *aNonBlocking = false;
         694             248 :     return NS_OK;
         695                 : }
         696                 :
         697                 : ////////////////////////////////////////////////////////////////////////////////
         698                 : // nsSafeFileOutputStream
         699                 :
         700           36545 : NS_IMPL_ISUPPORTS_INHERITED3(nsSafeFileOutputStream,
         701                 :                              nsFileOutputStream,
         702                 :                              nsISafeOutputStream,
         703                 :                              nsIOutputStream,
         704                 :                              nsIFileOutputStream)
         705                 :
         706                 : NS_IMETHODIMP
         707            1505 : nsSafeFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm,
         708                 :                              PRInt32 behaviorFlags)
         709                 : {
         710            1505 :     return nsFileOutputStream::Init(file, ioFlags, perm, behaviorFlags);
         711                 : }
         712                 :
         713                 : nsresult
         714            1500 : nsSafeFileOutputStream::DoOpen()
         715                 : {
         716                 :     // Make sure mOpenParams.localFile will be empty if we bail somewhere in
         717                 :     // this function
         718            3000 :     nsCOMPtr<nsILocalFile> file;
         719            1500 :     file.swap(mOpenParams.localFile);
         720                 :
         721            1500 :     nsresult rv = file->Exists(&mTargetFileExists);
         722            1500 :     if (NS_FAILED(rv)) {
         723               0 :         NS_ERROR("Can't tell if target file exists");
         724               0 :         mTargetFileExists = true; // Safer to assume it exists - we just do more work.
         725                 :     }
         726                 :
         727                 :     // follow symlinks, for two reasons:
         728                 :     // 1) if a user has deliberately set up a profile file as a symlink, we honor it
         729                 :     // 2) to make the MoveToNative() in Finish() an atomic operation (which may not
         730                 :     //    be the case if moving across directories on different filesystems).
         731            3000 :     nsCOMPtr<nsIFile> tempResult;
         732            1500 :     rv = file->Clone(getter_AddRefs(tempResult));
         733            1500 :     if (NS_SUCCEEDED(rv)) {
         734            3000 :         nsCOMPtr<nsILocalFile> tempLocal = do_QueryInterface(tempResult);
         735            1500 :         if (tempLocal)
         736            1500 :             tempLocal->SetFollowLinks(true);
         737                 :
         738                 :         // XP_UNIX ignores SetFollowLinks(), so we have to normalize.
         739            1500 :         tempResult->Normalize();
         740                 :     }
         741                 :
         742            1500 :     if (NS_SUCCEEDED(rv) && mTargetFileExists) {
         743                 :         PRUint32 origPerm;
         744             873 :         if (NS_FAILED(file->GetPermissions(&origPerm))) {
         745               0 :             NS_ERROR("Can't get permissions of target file");
         746               0 :             origPerm = mOpenParams.perm;
         747                 :         }
         748                 :         // XXX What if |perm| is more restrictive then |origPerm|?
         749                 :         // This leaves the user supplied permissions as they were.
         750             873 :         rv = tempResult->CreateUnique(nsIFile::NORMAL_FILE_TYPE, origPerm);
         751                 :     }
         752            1500 :     if (NS_SUCCEEDED(rv)) {
         753                 :         // nsFileOutputStream::DoOpen will work on the temporary file, so we
         754                 :         // prepare it and place it in mOpenParams.localFile.
         755            3000 :         nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(tempResult, &rv);
         756            1500 :         NS_ENSURE_SUCCESS(rv, rv);
         757            1500 :         mOpenParams.localFile = localFile;
         758            1500 :         mTempFile = tempResult;
         759            1500 :         mTargetFile = file;
         760            3000 :         rv = nsFileOutputStream::DoOpen();
         761                 :     }
         762            1500 :     return rv;
         763                 : }
         764                 :
         765                 : NS_IMETHODIMP
         766            1608 : nsSafeFileOutputStream::Close()
         767                 : {
         768            1608 :     nsresult rv = nsFileOutputStream::Close();
         769                 :
         770                 :     // the consumer doesn't want the original file overwritten -
         771                 :     // so clean up by removing the temp file.
         772            1608 :     if (mTempFile) {
         773               6 :         mTempFile->Remove(false);
         774               6 :         mTempFile = nsnull;
         775                 :     }
         776                 :
         777            1608 :     return rv;
         778                 : }
         779                 :
         780                 : NS_IMETHODIMP
         781            1494 : nsSafeFileOutputStream::Finish()
         782                 : {
         783            1494 :     Flush();
         784            1494 :     nsresult rv = nsFileOutputStream::Close();
         785                 :
         786                 :     // if there is no temp file, don't try to move it over the original target.
         787                 :     // It would destroy the targetfile if close() is called twice.
         788            1494 :     if (!mTempFile)
         789               0 :         return rv;
         790                 :
         791                 :     // Only overwrite if everything was ok, and the temp file could be closed.
         792            1494 :     if (NS_SUCCEEDED(mWriteResult) && NS_SUCCEEDED(rv)) {
         793            1494 :         NS_ENSURE_STATE(mTargetFile);
         794                 :
         795            1494 :         if (!mTargetFileExists) {
         796                 :             // If the target file did not exist when we were initialized, then the
         797                 :             // temp file we gave out was actually a reference to the target file.
         798                 :             // since we succeeded in writing to the temp file (and hence succeeded
         799                 :             // in writing to the target file), there is nothing more to do.
         800                 : #ifdef DEBUG
         801                 :             bool equal;
         802             621 :             if (NS_FAILED(mTargetFile->Equals(mTempFile, &equal)) || !equal)
         803               0 :                 NS_ERROR("mTempFile not equal to mTargetFile");
         804                 : #endif
         805                 :         }
         806                 :         else {
         807            1746 :             nsAutoString targetFilename;
         808             873 :             rv = mTargetFile->GetLeafName(targetFilename);
         809             873 :             if (NS_SUCCEEDED(rv)) {
         810                 :                 // This will replace target.
         811             873 :                 rv = mTempFile->MoveTo(nsnull, targetFilename);
         812             873 :                 if (NS_FAILED(rv))
         813               0 :                     mTempFile->Remove(false);
         814                 :             }
         815            1494 :         }
         816                 :     }
         817                 :     else {
         818               0 :         mTempFile->Remove(false);
         819                 :
         820                 :         // if writing failed, propagate the failure code to the caller.
         821               0 :         if (NS_FAILED(mWriteResult))
         822               0 :             rv = mWriteResult;
         823                 :     }
         824            1494 :     mTempFile = nsnull;
         825            1494 :     return rv;
         826                 : }
         827                 :
         828                 : NS_IMETHODIMP
         829            4814 : nsSafeFileOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *result)
         830                 : {
         831            4814 :     nsresult rv = nsFileOutputStream::Write(buf, count, result);
         832            4814 :     if (NS_SUCCEEDED(mWriteResult)) {
         833            4814 :         if (NS_FAILED(rv))
         834               2 :             mWriteResult = rv;
         835            4812 :         else if (count != *result)
         836               0 :             mWriteResult = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
         837                 :
         838            4814 :         if (NS_FAILED(mWriteResult) && count > 0)
         839               2 :             NS_WARNING("writing to output stream failed! data may be lost");
         840                 :     }
         841            4814 :     return rv;
         842                 : }
         843                 :
         844                 : ////////////////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.7