xref: /haiku/src/servers/package/FSUtils.h (revision 23733521a7b2d6c16027654c606c6069ef026357)
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
7 
8 
9 #include <new>
10 
11 #include <String.h>
12 
13 #include <EntryOperationEngineBase.h>
14 
15 
16 class BDirectory;
17 class BFile;
18 class BPositionIO;
19 class BSymLink;
20 
21 
22 class FSUtils {
23 public:
24 	typedef ::BPrivate::BEntryOperationEngineBase::Entry Entry;
25 
26 public:
27 	struct RelativePath {
28 		RelativePath(const char* component1 = NULL,
29 			const char* component2 = NULL, const char* component3 = NULL)
30 			:
31 			fComponentCount(kMaxComponentCount)
32 		{
33 			fComponents[0] = component1;
34 			fComponents[1] = component2;
35 			fComponents[2] = component3;
36 
37 			for (size_t i = 0; i < kMaxComponentCount; i++) {
38 				if (fComponents[i] == NULL) {
39 					fComponentCount = i;
40 					break;
41 				}
42 			}
43 		}
44 
45 		bool IsEmpty() const
46 		{
47 			return fComponentCount == 0;
48 		}
49 
50 		RelativePath HeadPath(size_t componentsToDropCount = 1)
51 		{
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];
58 			}
59 
60 			return result;
61 		}
62 
63 		const char* LastComponent() const
64 		{
65 			return fComponentCount > 0
66 				? fComponents[fComponentCount - 1] : NULL;
67 		}
68 
69 		BString ToString() const
70 		{
71 			if (fComponentCount == 0)
72 				return BString();
73 
74 			size_t length = fComponentCount - 1;
75 			for (size_t i = 0; i < fComponentCount; i++)
76 				length += strlen(fComponents[i]);
77 
78 			BString result;
79 			char* buffer = result.LockBuffer(length + 1);
80 			if (buffer == NULL)
81 				return BString();
82 
83 			for (size_t i = 0; i < fComponentCount; i++) {
84 				if (i > 0) {
85 					*buffer = '/';
86 					buffer++;
87 				}
88 				strcpy(buffer, fComponents[i]);
89 				buffer += strlen(buffer);
90 			}
91 
92 			return result.UnlockBuffer();
93 		}
94 
95 	private:
96 		static const size_t	kMaxComponentCount = 3;
97 
98 		const char*	fComponents[kMaxComponentCount];
99 		size_t		fComponentCount;
100 	};
101 
102 	// throwing std::bad_alloc()
103 	class Path {
104 	public:
105 		Path(const char* path)
106 			:
107 			fPath(path)
108 		{
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];
120 				}
121 
122 				// remove trailing '/'
123 				if (k > 1 && buffer[k - 1] == '/')
124 					k--;
125 
126 				fPath.LockBuffer(k);
127 			}
128 		}
129 
130 		Path& AppendComponent(const char* component)
131 		{
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();
142 				}
143 
144 				fPath += component;
145 				if (fPath.Length() <= length)
146 					throw std::bad_alloc();
147 			}
148 
149 			return *this;
150 		}
151 
152 		Path& RemoveLastComponent()
153 		{
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 - 1);
161 			return *this;
162 		}
163 
164 		const char* Leaf() const
165 		{
166 			int32 index = fPath.FindLast('/');
167 			if (index < 0 || (index == 0 && fPath.Length() == 1))
168 				return fPath.String();
169 			return fPath.String() + index + 1;
170 		}
171 
172 		const BString ToString() const
173 		{
174 			return fPath;
175 		}
176 
177 		const char* ToCString() const
178 		{
179 			return fPath.String();
180 		}
181 
182 		operator const BString&() const
183 		{
184 			return fPath;
185 		}
186 
187 		operator const char*() const
188 		{
189 			return fPath;
190 		}
191 
192 	private:
193 		BString	fPath;
194 	};
195 
196 public:
197 	static	BString				ShellEscapeString(const BString& string);
198 									// throw std::bad_alloc
199 
200 	static	status_t			OpenSubDirectory(BDirectory& baseDirectory,
201 									const RelativePath& path, bool create,
202 									BDirectory& _directory);
203 
204 	static	status_t			CompareFileContent(const Entry& entry1,
205 									const Entry& entry2, bool& _equal);
206 	static	status_t			CompareFileContent(BPositionIO& content1,
207 									BPositionIO& content2, bool& _equal);
208 
209 	static	status_t			CompareSymLinks(const Entry& entry1,
210 									const Entry& entry2, bool& _equal);
211 	static	status_t			CompareSymLinks(BSymLink& symLink1,
212 									BSymLink& symLink2, bool& _equal);
213 
214 	static	status_t			ExtractPackageContent(const Entry& packageEntry,
215 									const char* contentPath,
216 									const Entry& targetDirectoryEntry);
217 	static	status_t			ExtractPackageContent(const char* packagePath,
218 									const char* contentPath,
219 									const char* targetDirectoryPath);
220 
221 private:
222 	static	status_t			_OpenFile(const Entry& entry, BFile& file);
223 	static	status_t			_OpenSymLink(const Entry& entry,
224 									BSymLink& symLink);
225 };
226 
227 
228 
229 #endif	// FS_UTILS_H
230