Backed out changeset c3cca6dfcaa7 for landing with the wrong bug number.
[gecko.git] / xpcom / build / FileLocation.cpp
blobca40811efdbece673cc66a2e62bc4f0edbbeae4a
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "FileLocation.h"
6 #include "nsZipArchive.h"
7 #include "nsURLHelper.h"
9 namespace mozilla {
11 FileLocation::FileLocation()
15 FileLocation::~FileLocation()
19 FileLocation::FileLocation(nsIFile* file)
21 Init(file);
24 FileLocation::FileLocation(nsIFile* file, const char *path)
26 Init(file, path);
29 FileLocation::FileLocation(const FileLocation &file, const char *path)
31 if (file.IsZip()) {
32 if (file.mBaseFile) {
33 Init(file.mBaseFile, file.mPath.get());
34 } else {
35 Init(file.mBaseZip, file.mPath.get());
37 if (path) {
38 int32_t i = mPath.RFindChar('/');
39 if (kNotFound == i) {
40 mPath.Truncate(0);
41 } else {
42 mPath.Truncate(i + 1);
44 mPath += path;
46 } else {
47 if (path) {
48 nsCOMPtr<nsIFile> cfile;
49 file.mBaseFile->GetParent(getter_AddRefs(cfile));
51 #if defined(XP_WIN)
52 nsAutoCString pathStr(path);
53 char *p;
54 uint32_t len = pathStr.GetMutableData(&p);
55 for (; len; ++p, --len) {
56 if ('/' == *p) {
57 *p = '\\';
60 cfile->AppendRelativeNativePath(pathStr);
61 #else
62 cfile->AppendRelativeNativePath(nsDependentCString(path));
63 #endif
64 Init(cfile);
65 } else {
66 Init(file.mBaseFile);
71 void
72 FileLocation::Init(nsIFile* file)
74 mBaseZip = nullptr;
75 mBaseFile = file;
76 mPath.Truncate();
79 void
80 FileLocation::Init(nsIFile* file, const char* path)
82 mBaseZip = nullptr;
83 mBaseFile = file;
84 mPath = path;
87 void
88 FileLocation::Init(nsZipArchive* zip, const char* path)
90 mBaseZip = zip;
91 mBaseFile = nullptr;
92 mPath = path;
95 void
96 FileLocation::GetURIString(nsACString &result) const
98 if (mBaseFile) {
99 net_GetURLSpecFromActualFile(mBaseFile, result);
100 } else if (mBaseZip) {
101 nsRefPtr<nsZipHandle> handler = mBaseZip->GetFD();
102 handler->mFile.GetURIString(result);
104 if (IsZip()) {
105 result.Insert("jar:", 0);
106 result += "!/";
107 result += mPath;
111 already_AddRefed<nsIFile>
112 FileLocation::GetBaseFile()
114 if (IsZip() && mBaseZip) {
115 nsRefPtr<nsZipHandle> handler = mBaseZip->GetFD();
116 if (handler)
117 return handler->mFile.GetBaseFile();
118 return nullptr;
121 nsCOMPtr<nsIFile> file = mBaseFile;
122 return file.forget();
125 bool
126 FileLocation::Equals(const FileLocation &file) const
128 if (mPath != file.mPath)
129 return false;
131 if (mBaseFile && file.mBaseFile) {
132 bool eq;
133 return NS_SUCCEEDED(mBaseFile->Equals(file.mBaseFile, &eq)) && eq;
136 const FileLocation *a = this, *b = &file;
137 if (a->mBaseZip) {
138 nsRefPtr<nsZipHandle> handler = a->mBaseZip->GetFD();
139 a = &handler->mFile;
141 if (b->mBaseZip) {
142 nsRefPtr<nsZipHandle> handler = b->mBaseZip->GetFD();
143 b = &handler->mFile;
145 return a->Equals(*b);
148 nsresult
149 FileLocation::GetData(Data &data)
151 if (!IsZip()) {
152 return mBaseFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &data.mFd.rwget());
154 data.mZip = mBaseZip;
155 if (!data.mZip) {
156 data.mZip = new nsZipArchive();
157 data.mZip->OpenArchive(mBaseFile);
159 data.mItem = data.mZip->GetItem(mPath.get());
160 if (data.mItem)
161 return NS_OK;
162 return NS_ERROR_FILE_UNRECOGNIZED_PATH;
165 nsresult
166 FileLocation::Data::GetSize(uint32_t *result)
168 if (mFd) {
169 PRFileInfo64 fileInfo;
170 if (PR_SUCCESS != PR_GetOpenFileInfo64(mFd, &fileInfo))
171 return NS_ErrorAccordingToNSPR();
173 if (fileInfo.size > int64_t(UINT32_MAX))
174 return NS_ERROR_FILE_TOO_BIG;
176 *result = fileInfo.size;
177 return NS_OK;
178 } else if (mItem) {
179 *result = mItem->RealSize();
180 return NS_OK;
182 return NS_ERROR_NOT_INITIALIZED;
185 nsresult
186 FileLocation::Data::Copy(char *buf, uint32_t len)
188 if (mFd) {
189 for (uint32_t totalRead = 0; totalRead < len; ) {
190 int32_t read = PR_Read(mFd, buf + totalRead, XPCOM_MIN(len - totalRead, uint32_t(INT32_MAX)));
191 if (read < 0)
192 return NS_ErrorAccordingToNSPR();
193 totalRead += read;
195 return NS_OK;
196 } else if (mItem) {
197 nsZipCursor cursor(mItem, mZip, reinterpret_cast<uint8_t *>(buf), len, true);
198 uint32_t readLen;
199 cursor.Copy(&readLen);
200 return (readLen == len) ? NS_OK : NS_ERROR_FILE_CORRUPTED;
202 return NS_ERROR_NOT_INITIALIZED;
205 } /* namespace mozilla */