Coverage Report

Created: 2018-09-25 14:53

/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 */