/src/mozilla-central/xpcom/build/FileLocation.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #include "FileLocation.h" |
8 | | #include "nsZipArchive.h" |
9 | | #include "nsURLHelper.h" |
10 | | |
11 | | namespace mozilla { |
12 | | |
13 | 216 | FileLocation::FileLocation() = default; |
14 | | |
15 | 480 | FileLocation::~FileLocation() = default; |
16 | | |
17 | | FileLocation::FileLocation(nsIFile* aFile) |
18 | 6 | { |
19 | 6 | Init(aFile); |
20 | 6 | } |
21 | | |
22 | | FileLocation::FileLocation(nsIFile* aFile, const char* aPath) |
23 | 0 | { |
24 | 0 | Init(aFile, aPath); |
25 | 0 | } |
26 | | |
27 | | FileLocation::FileLocation(nsZipArchive* aZip, const char* aPath) |
28 | 18 | { |
29 | 18 | Init(aZip, aPath); |
30 | 18 | } |
31 | | |
32 | | FileLocation::FileLocation(const FileLocation& aOther) |
33 | | : mBaseFile(aOther.mBaseFile) |
34 | | , mBaseZip(aOther.mBaseZip) |
35 | | , mPath(aOther.mPath) |
36 | 336 | { |
37 | 336 | } |
38 | | |
39 | | FileLocation::FileLocation(FileLocation&& aOther) |
40 | | : mBaseFile(std::move(aOther.mBaseFile)) |
41 | | , mBaseZip(std::move(aOther.mBaseZip)) |
42 | | , mPath(std::move(aOther.mPath)) |
43 | 0 | { |
44 | 0 | aOther.mPath.Truncate(); |
45 | 0 | } |
46 | | |
47 | | FileLocation::FileLocation(const FileLocation& aFile, const char* aPath) |
48 | 333 | { |
49 | 333 | if (aFile.IsZip()) { |
50 | 333 | if (aFile.mBaseFile) { |
51 | 0 | Init(aFile.mBaseFile, aFile.mPath.get()); |
52 | 0 | } |
53 | 333 | else { |
54 | 333 | Init(aFile.mBaseZip, aFile.mPath.get()); |
55 | 333 | } |
56 | 333 | if (aPath) { |
57 | 333 | int32_t i = mPath.RFindChar('/'); |
58 | 333 | if (kNotFound == i) { |
59 | 6 | mPath.Truncate(0); |
60 | 327 | } else { |
61 | 327 | mPath.Truncate(i + 1); |
62 | 327 | } |
63 | 333 | mPath += aPath; |
64 | 333 | } |
65 | 333 | } else { |
66 | 0 | if (aPath) { |
67 | 0 | nsCOMPtr<nsIFile> cfile; |
68 | 0 | aFile.mBaseFile->GetParent(getter_AddRefs(cfile)); |
69 | 0 |
|
70 | | #if defined(XP_WIN) |
71 | | nsAutoCString pathStr(aPath); |
72 | | char* p; |
73 | | uint32_t len = pathStr.GetMutableData(&p); |
74 | | for (; len; ++p, --len) { |
75 | | if ('/' == *p) { |
76 | | *p = '\\'; |
77 | | } |
78 | | } |
79 | | cfile->AppendRelativeNativePath(pathStr); |
80 | | #else |
81 | | cfile->AppendRelativeNativePath(nsDependentCString(aPath)); |
82 | 0 | #endif |
83 | 0 | Init(cfile); |
84 | 0 | } else { |
85 | 0 | Init(aFile.mBaseFile); |
86 | 0 | } |
87 | 0 | } |
88 | 333 | } |
89 | | |
90 | | void |
91 | | FileLocation::Init(nsIFile* aFile) |
92 | 12 | { |
93 | 12 | mBaseZip = nullptr; |
94 | 12 | mBaseFile = aFile; |
95 | 12 | mPath.Truncate(); |
96 | 12 | } |
97 | | |
98 | | void |
99 | | FileLocation::Init(nsIFile* aFile, const char* aPath) |
100 | 0 | { |
101 | 0 | mBaseZip = nullptr; |
102 | 0 | mBaseFile = aFile; |
103 | 0 | mPath = aPath; |
104 | 0 | } |
105 | | |
106 | | void |
107 | | FileLocation::Init(nsZipArchive* aZip, const char* aPath) |
108 | 354 | { |
109 | 354 | mBaseZip = aZip; |
110 | 354 | mBaseFile = nullptr; |
111 | 354 | mPath = aPath; |
112 | 354 | } |
113 | | |
114 | | void |
115 | | FileLocation::GetURIString(nsACString& aResult) const |
116 | 673 | { |
117 | 673 | if (mBaseFile) { |
118 | 338 | net_GetURLSpecFromActualFile(mBaseFile, aResult); |
119 | 338 | } else if (mBaseZip) { |
120 | 335 | RefPtr<nsZipHandle> handler = mBaseZip->GetFD(); |
121 | 335 | handler->mFile.GetURIString(aResult); |
122 | 335 | } |
123 | 673 | if (IsZip()) { |
124 | 335 | aResult.InsertLiteral("jar:", 0); |
125 | 335 | aResult += "!/"; |
126 | 335 | aResult += mPath; |
127 | 335 | } |
128 | 673 | } |
129 | | |
130 | | already_AddRefed<nsIFile> |
131 | | FileLocation::GetBaseFile() |
132 | 5 | { |
133 | 5 | if (IsZip() && mBaseZip) { |
134 | 1 | RefPtr<nsZipHandle> handler = mBaseZip->GetFD(); |
135 | 1 | if (handler) { |
136 | 1 | return handler->mFile.GetBaseFile(); |
137 | 1 | } |
138 | 0 | return nullptr; |
139 | 0 | } |
140 | 4 | |
141 | 4 | nsCOMPtr<nsIFile> file = mBaseFile; |
142 | 4 | return file.forget(); |
143 | 4 | } |
144 | | |
145 | | bool |
146 | | FileLocation::Equals(const FileLocation& aFile) const |
147 | 0 | { |
148 | 0 | if (mPath != aFile.mPath) { |
149 | 0 | return false; |
150 | 0 | } |
151 | 0 | |
152 | 0 | if (mBaseFile && aFile.mBaseFile) { |
153 | 0 | bool eq; |
154 | 0 | return NS_SUCCEEDED(mBaseFile->Equals(aFile.mBaseFile, &eq)) && eq; |
155 | 0 | } |
156 | 0 |
|
157 | 0 | const FileLocation* a = this; |
158 | 0 | const FileLocation* b = &aFile; |
159 | 0 | if (a->mBaseZip) { |
160 | 0 | RefPtr<nsZipHandle> handler = a->mBaseZip->GetFD(); |
161 | 0 | a = &handler->mFile; |
162 | 0 | } |
163 | 0 | if (b->mBaseZip) { |
164 | 0 | RefPtr<nsZipHandle> handler = b->mBaseZip->GetFD(); |
165 | 0 | b = &handler->mFile; |
166 | 0 | } |
167 | 0 |
|
168 | 0 | return a->Equals(*b); |
169 | 0 | } |
170 | | |
171 | | nsresult |
172 | | FileLocation::GetData(Data& aData) |
173 | 24 | { |
174 | 24 | if (!IsZip()) { |
175 | 6 | return mBaseFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &aData.mFd.rwget()); |
176 | 6 | } |
177 | 18 | aData.mZip = mBaseZip; |
178 | 18 | if (!aData.mZip) { |
179 | 0 | aData.mZip = new nsZipArchive(); |
180 | 0 | aData.mZip->OpenArchive(mBaseFile); |
181 | 0 | } |
182 | 18 | aData.mItem = aData.mZip->GetItem(mPath.get()); |
183 | 18 | if (aData.mItem) { |
184 | 18 | return NS_OK; |
185 | 18 | } |
186 | 0 | return NS_ERROR_FILE_UNRECOGNIZED_PATH; |
187 | 0 | } |
188 | | |
189 | | nsresult |
190 | | FileLocation::Data::GetSize(uint32_t* aResult) |
191 | 24 | { |
192 | 24 | if (mFd) { |
193 | 6 | PRFileInfo64 fileInfo; |
194 | 6 | if (PR_SUCCESS != PR_GetOpenFileInfo64(mFd, &fileInfo)) { |
195 | 0 | return NS_ErrorAccordingToNSPR(); |
196 | 0 | } |
197 | 6 | |
198 | 6 | if (fileInfo.size > int64_t(UINT32_MAX)) { |
199 | 0 | return NS_ERROR_FILE_TOO_BIG; |
200 | 0 | } |
201 | 6 | |
202 | 6 | *aResult = fileInfo.size; |
203 | 6 | return NS_OK; |
204 | 6 | } |
205 | 18 | if (mItem) { |
206 | 18 | *aResult = mItem->RealSize(); |
207 | 18 | return NS_OK; |
208 | 18 | } |
209 | 0 | return NS_ERROR_NOT_INITIALIZED; |
210 | 0 | } |
211 | | |
212 | | nsresult |
213 | | FileLocation::Data::Copy(char* aBuf, uint32_t aLen) |
214 | 24 | { |
215 | 24 | if (mFd) { |
216 | 9 | for (uint32_t totalRead = 0; totalRead < aLen;) { |
217 | 3 | int32_t read = PR_Read(mFd, aBuf + totalRead, |
218 | 3 | XPCOM_MIN(aLen - totalRead, uint32_t(INT32_MAX))); |
219 | 3 | if (read < 0) { |
220 | 0 | return NS_ErrorAccordingToNSPR(); |
221 | 0 | } |
222 | 3 | totalRead += read; |
223 | 3 | } |
224 | 6 | return NS_OK; |
225 | 18 | } |
226 | 18 | if (mItem) { |
227 | 18 | nsZipCursor cursor(mItem, mZip, reinterpret_cast<uint8_t*>(aBuf), |
228 | 18 | aLen, true); |
229 | 18 | uint32_t readLen; |
230 | 18 | cursor.Copy(&readLen); |
231 | 18 | if (readLen != aLen) { |
232 | 0 | nsZipArchive::sFileCorruptedReason = "FileLocation::Data: insufficient data"; |
233 | 0 | return NS_ERROR_FILE_CORRUPTED; |
234 | 0 | } |
235 | 18 | return NS_OK; |
236 | 18 | } |
237 | 0 | return NS_ERROR_NOT_INITIALIZED; |
238 | 0 | } |
239 | | |
240 | | } /* namespace mozilla */ |