vfs: check userland buffers before reading them.
[haiku.git] / src / servers / package / FSUtils.h
blob004d3cdb1eaa191ac22b48ddf5f1a3609604a786
1 /*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5 #ifndef FS_UTILS_H
6 #define FS_UTILS_H
9 #include <new>
11 #include <String.h>
13 #include <EntryOperationEngineBase.h>
16 class BDirectory;
17 class BFile;
18 class BPositionIO;
19 class BSymLink;
22 class FSUtils {
23 public:
24 typedef ::BPrivate::BEntryOperationEngineBase::Entry Entry;
26 public:
27 struct RelativePath {
28 RelativePath(const char* component1 = NULL,
29 const char* component2 = NULL, const char* component3 = NULL)
31 fComponentCount(kMaxComponentCount)
33 fComponents[0] = component1;
34 fComponents[1] = component2;
35 fComponents[2] = component3;
37 for (size_t i = 0; i < kMaxComponentCount; i++) {
38 if (fComponents[i] == NULL) {
39 fComponentCount = i;
40 break;
45 bool IsEmpty() const
47 return fComponentCount == 0;
50 RelativePath HeadPath(size_t componentsToDropCount = 1)
52 RelativePath result;
53 if (componentsToDropCount < fComponentCount) {
54 result.fComponentCount
55 = fComponentCount - componentsToDropCount;
56 for (size_t i = 0; i < result.fComponentCount; i++)
57 result.fComponents[i] = fComponents[i];
60 return result;
63 const char* LastComponent() const
65 return fComponentCount > 0
66 ? fComponents[fComponentCount - 1] : NULL;
69 BString ToString() const
71 if (fComponentCount == 0)
72 return BString();
74 size_t length = fComponentCount - 1;
75 for (size_t i = 0; i < fComponentCount; i++)
76 length += strlen(fComponents[i]);
78 BString result;
79 char* buffer = result.LockBuffer(length + 1);
80 if (buffer == NULL)
81 return BString();
83 for (size_t i = 0; i < fComponentCount; i++) {
84 if (i > 0) {
85 *buffer = '/';
86 buffer++;
88 strcpy(buffer, fComponents[i]);
89 buffer += strlen(buffer);
92 return result.UnlockBuffer();
95 private:
96 static const size_t kMaxComponentCount = 3;
98 const char* fComponents[kMaxComponentCount];
99 size_t fComponentCount;
102 // throwing std::bad_alloc()
103 class Path {
104 public:
105 Path(const char* path)
107 fPath(path)
109 if (fPath.IsEmpty()) {
110 if (path[0] != '\0')
111 throw std::bad_alloc();
112 } else {
113 // remove duplicate '/'s
114 char* buffer = fPath.LockBuffer(fPath.Length());
115 int32 k = 0;
116 for (int32 i = 0; buffer[i] != '\0'; i++) {
117 if (buffer[i] == '/' && k > 0 && buffer[k - 1] == '/')
118 continue;
119 buffer[k++] = buffer[i];
122 // remove trailing '/'
123 if (k > 1 && buffer[k - 1] == '/')
124 k--;
126 fPath.LockBuffer(k);
130 Path& AppendComponent(const char* component)
132 if (fPath.IsEmpty()) {
133 fPath = component;
134 if (fPath.IsEmpty() && component[0] != '\0')
135 throw std::bad_alloc();
136 } else {
137 int32 length = fPath.Length();
138 if (fPath[length - 1] != '/') {
139 fPath += '/';
140 if (++length != fPath.Length())
141 throw std::bad_alloc();
144 fPath += component;
145 if (fPath.Length() <= length)
146 throw std::bad_alloc();
149 return *this;
152 Path& RemoveLastComponent()
154 int32 index = fPath.FindLast('/');
155 if (index < 0 || (index == 0 && fPath.Length() == 1))
156 fPath.Truncate(0);
157 else if (index == 0)
158 fPath.Truncate(1);
159 else
160 fPath.Truncate(index);
161 return *this;
164 const char* Leaf() const
166 int32 index = fPath.FindLast('/');
167 if (index < 0 || (index == 0 && fPath.Length() == 1))
168 return fPath.String();
169 return fPath.String() + index + 1;
172 const BString ToString() const
174 return fPath;
177 const char* ToCString() const
179 return fPath.String();
182 operator const BString&() const
184 return fPath;
187 operator const char*() const
189 return fPath;
192 private:
193 BString fPath;
196 public:
197 static BString ShellEscapeString(const BString& string);
198 // throw std::bad_alloc
200 static status_t OpenSubDirectory(
201 const BDirectory& baseDirectory,
202 const RelativePath& path, bool create,
203 BDirectory& _directory);
205 static status_t CompareFileContent(const Entry& entry1,
206 const Entry& entry2, bool& _equal);
207 static status_t CompareFileContent(BPositionIO& content1,
208 BPositionIO& content2, bool& _equal);
210 static status_t CompareSymLinks(const Entry& entry1,
211 const Entry& entry2, bool& _equal);
212 static status_t CompareSymLinks(BSymLink& symLink1,
213 BSymLink& symLink2, bool& _equal);
215 static status_t ExtractPackageContent(const Entry& packageEntry,
216 const char* contentPath,
217 const Entry& targetDirectoryEntry);
218 static status_t ExtractPackageContent(const char* packagePath,
219 const char* contentPath,
220 const char* targetDirectoryPath);
222 private:
223 static status_t _OpenFile(const Entry& entry, BFile& file);
224 static status_t _OpenSymLink(const Entry& entry,
225 BSymLink& symLink);
230 #endif // FS_UTILS_H