1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "FileLocation.h"
8 #include "nsZipArchive.h"
9 #include "nsURLHelper.h"
13 FileLocation::FileLocation() = default;
15 FileLocation::~FileLocation() = default;
17 FileLocation::FileLocation(nsIFile
* aFile
) { Init(aFile
); }
19 FileLocation::FileLocation(nsIFile
* aFile
, const char* aPath
) {
23 FileLocation::FileLocation(nsZipArchive
* aZip
, const char* aPath
) {
27 FileLocation::FileLocation(const FileLocation
& aOther
)
31 FileLocation::FileLocation(FileLocation
&& aOther
)
32 : mBaseFile(std::move(aOther
.mBaseFile
)),
33 mBaseZip(std::move(aOther
.mBaseZip
)),
34 mPath(std::move(aOther
.mPath
)) {
35 aOther
.mPath
.Truncate();
38 FileLocation::FileLocation(const FileLocation
& aFile
, const char* aPath
) {
40 if (aFile
.mBaseFile
) {
41 Init(aFile
.mBaseFile
, aFile
.mPath
.get());
43 Init(aFile
.mBaseZip
, aFile
.mPath
.get());
46 int32_t i
= mPath
.RFindChar('/');
50 mPath
.Truncate(i
+ 1);
56 nsCOMPtr
<nsIFile
> cfile
;
57 aFile
.mBaseFile
->GetParent(getter_AddRefs(cfile
));
60 nsAutoCString
pathStr(aPath
);
62 uint32_t len
= pathStr
.GetMutableData(&p
);
63 for (; len
; ++p
, --len
) {
68 cfile
->AppendRelativeNativePath(pathStr
);
70 cfile
->AppendRelativeNativePath(nsDependentCString(aPath
));
74 Init(aFile
.mBaseFile
);
79 void FileLocation::Init(nsIFile
* aFile
) {
85 void FileLocation::Init(nsIFile
* aFile
, const char* aPath
) {
91 void FileLocation::Init(nsZipArchive
* aZip
, const char* aPath
) {
97 void FileLocation::GetURIString(nsACString
& aResult
) const {
99 net_GetURLSpecFromActualFile(mBaseFile
, aResult
);
100 } else if (mBaseZip
) {
101 RefPtr
<nsZipHandle
> handler
= mBaseZip
->GetFD();
102 handler
->mFile
.GetURIString(aResult
);
105 aResult
.InsertLiteral("jar:", 0);
111 already_AddRefed
<nsIFile
> FileLocation::GetBaseFile() {
112 if (IsZip() && mBaseZip
) {
113 RefPtr
<nsZipHandle
> handler
= mBaseZip
->GetFD();
115 return handler
->mFile
.GetBaseFile();
120 nsCOMPtr
<nsIFile
> file
= mBaseFile
;
121 return file
.forget();
124 bool FileLocation::Equals(const FileLocation
& aFile
) const {
125 if (mPath
!= aFile
.mPath
) {
129 if (mBaseFile
&& aFile
.mBaseFile
) {
131 return NS_SUCCEEDED(mBaseFile
->Equals(aFile
.mBaseFile
, &eq
)) && eq
;
134 const FileLocation
* a
= this;
135 const FileLocation
* b
= &aFile
;
137 RefPtr
<nsZipHandle
> handler
= a
->mBaseZip
->GetFD();
141 RefPtr
<nsZipHandle
> handler
= b
->mBaseZip
->GetFD();
145 return a
->Equals(*b
);
148 nsresult
FileLocation::GetData(Data
& aData
) {
150 return mBaseFile
->OpenNSPRFileDesc(PR_RDONLY
, 0444, &aData
.mFd
.rwget());
152 aData
.mZip
= mBaseZip
;
154 // this can return nullptr
155 aData
.mZip
= nsZipArchive::OpenArchive(mBaseFile
);
158 aData
.mItem
= aData
.mZip
->GetItem(mPath
.get());
163 return NS_ERROR_FILE_UNRECOGNIZED_PATH
;
166 nsresult
FileLocation::Data::GetSize(uint32_t* aResult
) {
168 PRFileInfo64 fileInfo
;
169 if (PR_SUCCESS
!= PR_GetOpenFileInfo64(mFd
, &fileInfo
)) {
170 return NS_ErrorAccordingToNSPR();
173 if (fileInfo
.size
> int64_t(UINT32_MAX
)) {
174 return NS_ERROR_FILE_TOO_BIG
;
177 *aResult
= fileInfo
.size
;
181 *aResult
= mItem
->RealSize();
184 return NS_ERROR_NOT_INITIALIZED
;
187 nsresult
FileLocation::Data::Copy(char* aBuf
, uint32_t aLen
) {
189 for (uint32_t totalRead
= 0; totalRead
< aLen
;) {
190 int32_t read
= PR_Read(mFd
, aBuf
+ totalRead
,
191 XPCOM_MIN(aLen
- totalRead
, uint32_t(INT32_MAX
)));
193 return NS_ErrorAccordingToNSPR();
200 nsZipCursor
cursor(mItem
, mZip
, reinterpret_cast<uint8_t*>(aBuf
), aLen
,
203 cursor
.Copy(&readLen
);
204 if (readLen
!= aLen
) {
205 return NS_ERROR_FILE_CORRUPTED
;
209 return NS_ERROR_NOT_INITIALIZED
;
212 } /* namespace mozilla */