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"
11 #include "mozilla/UniquePtrExtensions.h"
15 FileLocation::FileLocation() = default;
17 FileLocation::~FileLocation() = default;
19 FileLocation::FileLocation(nsIFile
* aFile
) { Init(aFile
); }
21 FileLocation::FileLocation(nsIFile
* aFile
, const char* aPath
) {
25 FileLocation::FileLocation(nsZipArchive
* aZip
, const char* aPath
) {
29 FileLocation::FileLocation(const FileLocation
& aOther
)
33 FileLocation::FileLocation(FileLocation
&& aOther
)
34 : mBaseFile(std::move(aOther
.mBaseFile
)),
35 mBaseZip(std::move(aOther
.mBaseZip
)),
36 mPath(std::move(aOther
.mPath
)) {
37 aOther
.mPath
.Truncate();
40 FileLocation::FileLocation(const FileLocation
& aFile
, const char* aPath
) {
42 if (aFile
.mBaseFile
) {
43 Init(aFile
.mBaseFile
, aFile
.mPath
.get());
45 Init(aFile
.mBaseZip
, aFile
.mPath
.get());
48 int32_t i
= mPath
.RFindChar('/');
52 mPath
.Truncate(i
+ 1);
58 nsCOMPtr
<nsIFile
> cfile
;
59 aFile
.mBaseFile
->GetParent(getter_AddRefs(cfile
));
62 nsAutoCString
pathStr(aPath
);
64 uint32_t len
= pathStr
.GetMutableData(&p
);
65 for (; len
; ++p
, --len
) {
70 cfile
->AppendRelativeNativePath(pathStr
);
72 cfile
->AppendRelativeNativePath(nsDependentCString(aPath
));
76 Init(aFile
.mBaseFile
);
81 void FileLocation::Init(nsIFile
* aFile
) {
87 void FileLocation::Init(nsIFile
* aFile
, const char* aPath
) {
93 void FileLocation::Init(nsZipArchive
* aZip
, const char* aPath
) {
99 void FileLocation::GetURIString(nsACString
& aResult
) const {
101 net_GetURLSpecFromActualFile(mBaseFile
, aResult
);
102 } else if (mBaseZip
) {
103 RefPtr
<nsZipHandle
> handler
= mBaseZip
->GetFD();
104 handler
->mFile
.GetURIString(aResult
);
107 aResult
.InsertLiteral("jar:", 0);
113 already_AddRefed
<nsIFile
> FileLocation::GetBaseFile() {
114 if (IsZip() && mBaseZip
) {
115 RefPtr
<nsZipHandle
> handler
= mBaseZip
->GetFD();
117 return handler
->mFile
.GetBaseFile();
122 nsCOMPtr
<nsIFile
> file
= mBaseFile
;
123 return file
.forget();
126 bool FileLocation::Equals(const FileLocation
& aFile
) const {
127 if (mPath
!= aFile
.mPath
) {
131 if (mBaseFile
&& aFile
.mBaseFile
) {
133 return NS_SUCCEEDED(mBaseFile
->Equals(aFile
.mBaseFile
, &eq
)) && eq
;
136 const FileLocation
* a
= this;
137 const FileLocation
* b
= &aFile
;
139 RefPtr
<nsZipHandle
> handler
= a
->mBaseZip
->GetFD();
143 RefPtr
<nsZipHandle
> handler
= b
->mBaseZip
->GetFD();
147 return a
->Equals(*b
);
150 nsresult
FileLocation::GetData(Data
& aData
) {
152 return mBaseFile
->OpenNSPRFileDesc(PR_RDONLY
, 0444,
153 getter_Transfers(aData
.mFd
));
155 aData
.mZip
= mBaseZip
;
157 // this can return nullptr
158 aData
.mZip
= nsZipArchive::OpenArchive(mBaseFile
);
161 aData
.mItem
= aData
.mZip
->GetItem(mPath
.get());
166 return NS_ERROR_FILE_UNRECOGNIZED_PATH
;
169 nsresult
FileLocation::Data::GetSize(uint32_t* aResult
) {
171 PRFileInfo64 fileInfo
;
172 if (PR_SUCCESS
!= PR_GetOpenFileInfo64(mFd
.get(), &fileInfo
)) {
173 return NS_ErrorAccordingToNSPR();
176 if (fileInfo
.size
> int64_t(UINT32_MAX
)) {
177 return NS_ERROR_FILE_TOO_BIG
;
180 *aResult
= fileInfo
.size
;
184 *aResult
= mItem
->RealSize();
187 return NS_ERROR_NOT_INITIALIZED
;
190 nsresult
FileLocation::Data::Copy(char* aBuf
, uint32_t aLen
) {
192 for (uint32_t totalRead
= 0; totalRead
< aLen
;) {
193 int32_t read
= PR_Read(mFd
.get(), aBuf
+ totalRead
,
194 XPCOM_MIN(aLen
- totalRead
, uint32_t(INT32_MAX
)));
196 return NS_ErrorAccordingToNSPR();
203 nsZipCursor
cursor(mItem
, mZip
, reinterpret_cast<uint8_t*>(aBuf
), aLen
,
206 cursor
.Copy(&readLen
);
207 if (readLen
!= aLen
) {
208 return NS_ERROR_FILE_CORRUPTED
;
212 return NS_ERROR_NOT_INITIALIZED
;
215 } /* namespace mozilla */