Bug 1919083 - [ci] Enable os-integration variant for more suites, r=jmaher
[gecko.git] / xpcom / build / FileLocation.cpp
blob5162546f1d49435bfbd32d74b46bea8b198d2b52
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"
13 namespace mozilla {
15 FileLocation::FileLocation() = default;
17 FileLocation::~FileLocation() = default;
19 FileLocation::FileLocation(nsIFile* aFile) { Init(aFile); }
21 FileLocation::FileLocation(nsIFile* aFile, const char* aPath) {
22 Init(aFile, aPath);
25 FileLocation::FileLocation(nsZipArchive* aZip, const char* aPath) {
26 Init(aZip, aPath);
29 FileLocation::FileLocation(const FileLocation& aOther)
31 = default;
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) {
41 if (aFile.IsZip()) {
42 if (aFile.mBaseFile) {
43 Init(aFile.mBaseFile, aFile.mPath.get());
44 } else {
45 Init(aFile.mBaseZip, aFile.mPath.get());
47 if (aPath) {
48 int32_t i = mPath.RFindChar('/');
49 if (kNotFound == i) {
50 mPath.Truncate(0);
51 } else {
52 mPath.Truncate(i + 1);
54 mPath += aPath;
56 } else {
57 if (aPath) {
58 nsCOMPtr<nsIFile> cfile;
59 aFile.mBaseFile->GetParent(getter_AddRefs(cfile));
61 #if defined(XP_WIN)
62 nsAutoCString pathStr(aPath);
63 char* p;
64 uint32_t len = pathStr.GetMutableData(&p);
65 for (; len; ++p, --len) {
66 if ('/' == *p) {
67 *p = '\\';
70 cfile->AppendRelativeNativePath(pathStr);
71 #else
72 cfile->AppendRelativeNativePath(nsDependentCString(aPath));
73 #endif
74 Init(cfile);
75 } else {
76 Init(aFile.mBaseFile);
81 void FileLocation::Init(nsIFile* aFile) {
82 mBaseZip = nullptr;
83 mBaseFile = aFile;
84 mPath.Truncate();
87 void FileLocation::Init(nsIFile* aFile, const char* aPath) {
88 mBaseZip = nullptr;
89 mBaseFile = aFile;
90 mPath = aPath;
93 void FileLocation::Init(nsZipArchive* aZip, const char* aPath) {
94 mBaseZip = aZip;
95 mBaseFile = nullptr;
96 mPath = aPath;
99 void FileLocation::GetURIString(nsACString& aResult) const {
100 if (mBaseFile) {
101 net_GetURLSpecFromActualFile(mBaseFile, aResult);
102 } else if (mBaseZip) {
103 RefPtr<nsZipHandle> handler = mBaseZip->GetFD();
104 handler->mFile.GetURIString(aResult);
106 if (IsZip()) {
107 aResult.InsertLiteral("jar:", 0);
108 aResult += "!/";
109 aResult += mPath;
113 already_AddRefed<nsIFile> FileLocation::GetBaseFile() {
114 if (IsZip() && mBaseZip) {
115 RefPtr<nsZipHandle> handler = mBaseZip->GetFD();
116 if (handler) {
117 return handler->mFile.GetBaseFile();
119 return nullptr;
122 nsCOMPtr<nsIFile> file = mBaseFile;
123 return file.forget();
126 bool FileLocation::Equals(const FileLocation& aFile) const {
127 if (mPath != aFile.mPath) {
128 return false;
131 if (mBaseFile && aFile.mBaseFile) {
132 bool eq;
133 return NS_SUCCEEDED(mBaseFile->Equals(aFile.mBaseFile, &eq)) && eq;
136 const FileLocation* a = this;
137 const FileLocation* b = &aFile;
138 if (a->mBaseZip) {
139 RefPtr<nsZipHandle> handler = a->mBaseZip->GetFD();
140 a = &handler->mFile;
142 if (b->mBaseZip) {
143 RefPtr<nsZipHandle> handler = b->mBaseZip->GetFD();
144 b = &handler->mFile;
147 return a->Equals(*b);
150 nsresult FileLocation::GetData(Data& aData) {
151 if (!IsZip()) {
152 return mBaseFile->OpenNSPRFileDesc(PR_RDONLY, 0444,
153 getter_Transfers(aData.mFd));
155 aData.mZip = mBaseZip;
156 if (!aData.mZip) {
157 // this can return nullptr
158 aData.mZip = nsZipArchive::OpenArchive(mBaseFile);
160 if (aData.mZip) {
161 aData.mItem = aData.mZip->GetItem(mPath.get());
162 if (aData.mItem) {
163 return NS_OK;
166 return NS_ERROR_FILE_UNRECOGNIZED_PATH;
169 nsresult FileLocation::Data::GetSize(uint32_t* aResult) {
170 if (mFd) {
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;
181 return NS_OK;
183 if (mItem) {
184 *aResult = mItem->RealSize();
185 return NS_OK;
187 return NS_ERROR_NOT_INITIALIZED;
190 nsresult FileLocation::Data::Copy(char* aBuf, uint32_t aLen) {
191 if (mFd) {
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)));
195 if (read < 0) {
196 return NS_ErrorAccordingToNSPR();
198 totalRead += read;
200 return NS_OK;
202 if (mItem) {
203 nsZipCursor cursor(mItem, mZip, reinterpret_cast<uint8_t*>(aBuf), aLen,
204 true);
205 uint32_t readLen;
206 cursor.Copy(&readLen);
207 if (readLen != aLen) {
208 return NS_ERROR_FILE_CORRUPTED;
210 return NS_OK;
212 return NS_ERROR_NOT_INITIALIZED;
215 } /* namespace mozilla */