1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/build/FileLocation.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,205 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "FileLocation.h" 1.9 +#include "nsZipArchive.h" 1.10 +#include "nsURLHelper.h" 1.11 + 1.12 +namespace mozilla { 1.13 + 1.14 +FileLocation::FileLocation() 1.15 +{ 1.16 +} 1.17 + 1.18 +FileLocation::~FileLocation() 1.19 +{ 1.20 +} 1.21 + 1.22 +FileLocation::FileLocation(nsIFile* file) 1.23 +{ 1.24 + Init(file); 1.25 +} 1.26 + 1.27 +FileLocation::FileLocation(nsIFile* file, const char *path) 1.28 +{ 1.29 + Init(file, path); 1.30 +} 1.31 + 1.32 +FileLocation::FileLocation(const FileLocation &file, const char *path) 1.33 +{ 1.34 + if (file.IsZip()) { 1.35 + if (file.mBaseFile) { 1.36 + Init(file.mBaseFile, file.mPath.get()); 1.37 + } else { 1.38 + Init(file.mBaseZip, file.mPath.get()); 1.39 + } 1.40 + if (path) { 1.41 + int32_t i = mPath.RFindChar('/'); 1.42 + if (kNotFound == i) { 1.43 + mPath.Truncate(0); 1.44 + } else { 1.45 + mPath.Truncate(i + 1); 1.46 + } 1.47 + mPath += path; 1.48 + } 1.49 + } else { 1.50 + if (path) { 1.51 + nsCOMPtr<nsIFile> cfile; 1.52 + file.mBaseFile->GetParent(getter_AddRefs(cfile)); 1.53 + 1.54 +#if defined(XP_WIN) 1.55 + nsAutoCString pathStr(path); 1.56 + char *p; 1.57 + uint32_t len = pathStr.GetMutableData(&p); 1.58 + for (; len; ++p, --len) { 1.59 + if ('/' == *p) { 1.60 + *p = '\\'; 1.61 + } 1.62 + } 1.63 + cfile->AppendRelativeNativePath(pathStr); 1.64 +#else 1.65 + cfile->AppendRelativeNativePath(nsDependentCString(path)); 1.66 +#endif 1.67 + Init(cfile); 1.68 + } else { 1.69 + Init(file.mBaseFile); 1.70 + } 1.71 + } 1.72 +} 1.73 + 1.74 +void 1.75 +FileLocation::Init(nsIFile* file) 1.76 +{ 1.77 + mBaseZip = nullptr; 1.78 + mBaseFile = file; 1.79 + mPath.Truncate(); 1.80 +} 1.81 + 1.82 +void 1.83 +FileLocation::Init(nsIFile* file, const char* path) 1.84 +{ 1.85 + mBaseZip = nullptr; 1.86 + mBaseFile = file; 1.87 + mPath = path; 1.88 +} 1.89 + 1.90 +void 1.91 +FileLocation::Init(nsZipArchive* zip, const char* path) 1.92 +{ 1.93 + mBaseZip = zip; 1.94 + mBaseFile = nullptr; 1.95 + mPath = path; 1.96 +} 1.97 + 1.98 +void 1.99 +FileLocation::GetURIString(nsACString &result) const 1.100 +{ 1.101 + if (mBaseFile) { 1.102 + net_GetURLSpecFromActualFile(mBaseFile, result); 1.103 + } else if (mBaseZip) { 1.104 + nsRefPtr<nsZipHandle> handler = mBaseZip->GetFD(); 1.105 + handler->mFile.GetURIString(result); 1.106 + } 1.107 + if (IsZip()) { 1.108 + result.Insert("jar:", 0); 1.109 + result += "!/"; 1.110 + result += mPath; 1.111 + } 1.112 +} 1.113 + 1.114 +already_AddRefed<nsIFile> 1.115 +FileLocation::GetBaseFile() 1.116 +{ 1.117 + if (IsZip() && mBaseZip) { 1.118 + nsRefPtr<nsZipHandle> handler = mBaseZip->GetFD(); 1.119 + if (handler) 1.120 + return handler->mFile.GetBaseFile(); 1.121 + return nullptr; 1.122 + } 1.123 + 1.124 + nsCOMPtr<nsIFile> file = mBaseFile; 1.125 + return file.forget(); 1.126 +} 1.127 + 1.128 +bool 1.129 +FileLocation::Equals(const FileLocation &file) const 1.130 +{ 1.131 + if (mPath != file.mPath) 1.132 + return false; 1.133 + 1.134 + if (mBaseFile && file.mBaseFile) { 1.135 + bool eq; 1.136 + return NS_SUCCEEDED(mBaseFile->Equals(file.mBaseFile, &eq)) && eq; 1.137 + } 1.138 + 1.139 + const FileLocation *a = this, *b = &file; 1.140 + if (a->mBaseZip) { 1.141 + nsRefPtr<nsZipHandle> handler = a->mBaseZip->GetFD(); 1.142 + a = &handler->mFile; 1.143 + } 1.144 + if (b->mBaseZip) { 1.145 + nsRefPtr<nsZipHandle> handler = b->mBaseZip->GetFD(); 1.146 + b = &handler->mFile; 1.147 + } 1.148 + return a->Equals(*b); 1.149 +} 1.150 + 1.151 +nsresult 1.152 +FileLocation::GetData(Data &data) 1.153 +{ 1.154 + if (!IsZip()) { 1.155 + return mBaseFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &data.mFd.rwget()); 1.156 + } 1.157 + data.mZip = mBaseZip; 1.158 + if (!data.mZip) { 1.159 + data.mZip = new nsZipArchive(); 1.160 + data.mZip->OpenArchive(mBaseFile); 1.161 + } 1.162 + data.mItem = data.mZip->GetItem(mPath.get()); 1.163 + if (data.mItem) 1.164 + return NS_OK; 1.165 + return NS_ERROR_FILE_UNRECOGNIZED_PATH; 1.166 +} 1.167 + 1.168 +nsresult 1.169 +FileLocation::Data::GetSize(uint32_t *result) 1.170 +{ 1.171 + if (mFd) { 1.172 + PRFileInfo64 fileInfo; 1.173 + if (PR_SUCCESS != PR_GetOpenFileInfo64(mFd, &fileInfo)) 1.174 + return NS_ErrorAccordingToNSPR(); 1.175 + 1.176 + if (fileInfo.size > int64_t(UINT32_MAX)) 1.177 + return NS_ERROR_FILE_TOO_BIG; 1.178 + 1.179 + *result = fileInfo.size; 1.180 + return NS_OK; 1.181 + } else if (mItem) { 1.182 + *result = mItem->RealSize(); 1.183 + return NS_OK; 1.184 + } 1.185 + return NS_ERROR_NOT_INITIALIZED; 1.186 +} 1.187 + 1.188 +nsresult 1.189 +FileLocation::Data::Copy(char *buf, uint32_t len) 1.190 +{ 1.191 + if (mFd) { 1.192 + for (uint32_t totalRead = 0; totalRead < len; ) { 1.193 + int32_t read = PR_Read(mFd, buf + totalRead, XPCOM_MIN(len - totalRead, uint32_t(INT32_MAX))); 1.194 + if (read < 0) 1.195 + return NS_ErrorAccordingToNSPR(); 1.196 + totalRead += read; 1.197 + } 1.198 + return NS_OK; 1.199 + } else if (mItem) { 1.200 + nsZipCursor cursor(mItem, mZip, reinterpret_cast<uint8_t *>(buf), len, true); 1.201 + uint32_t readLen; 1.202 + cursor.Copy(&readLen); 1.203 + return (readLen == len) ? NS_OK : NS_ERROR_FILE_CORRUPTED; 1.204 + } 1.205 + return NS_ERROR_NOT_INITIALIZED; 1.206 +} 1.207 + 1.208 +} /* namespace mozilla */