2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
14 #include <Directory.h>
19 #include <AutoDeleter.h>
21 #include "DebugSupport.h"
24 static const size_t kCompareDataBufferSize
= 64 * 1024;
25 const char* const kShellEscapeCharacters
= " ~`#$&*()\\|[]{};'\"<>?!";
29 FSUtils::ShellEscapeString(const BString
& string
)
31 BString
result(string
);
32 result
.CharacterEscape(kShellEscapeCharacters
, '\\');
34 throw std::bad_alloc();
40 FSUtils::OpenSubDirectory(const BDirectory
& baseDirectory
,
41 const RelativePath
& path
, bool create
, BDirectory
& _directory
)
43 // get a string for the path
44 BString pathString
= path
.ToString();
45 if (pathString
.IsEmpty())
46 RETURN_ERROR(B_NO_MEMORY
);
48 // If creating is not allowed, just try to open it.
50 RETURN_ERROR(_directory
.SetTo(&baseDirectory
, pathString
));
52 // get an absolute path and create the subdirectory
54 status_t error
= absolutePath
.SetTo(&baseDirectory
, pathString
);
56 ERROR("Volume::OpenSubDirectory(): failed to get absolute path "
57 "for subdirectory \"%s\": %s\n", pathString
.String(),
62 error
= create_directory(absolutePath
.Path(),
63 S_IRWXU
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
);
65 ERROR("Volume::OpenSubDirectory(): failed to create "
66 "subdirectory \"%s\": %s\n", pathString
.String(),
71 RETURN_ERROR(_directory
.SetTo(&baseDirectory
, pathString
));
76 FSUtils::CompareFileContent(const Entry
& entry1
, const Entry
& entry2
,
80 status_t error
= _OpenFile(entry1
, file1
);
85 error
= _OpenFile(entry2
, file2
);
89 return CompareFileContent(file1
, file2
, _equal
);
94 FSUtils::CompareFileContent(BPositionIO
& content1
, BPositionIO
& content2
,
97 // get and compare content size
99 status_t error
= content1
.GetSize(&size1
);
104 error
= content2
.GetSize(&size2
);
108 if (size1
!= size2
) {
118 // allocate a data buffer
119 uint8
* buffer1
= new(std::nothrow
) uint8
[2 * kCompareDataBufferSize
];
122 ArrayDeleter
<uint8
> bufferDeleter(buffer1
);
123 uint8
* buffer2
= buffer1
+ kCompareDataBufferSize
;
127 while (offset
< size1
) {
128 size_t toCompare
= std::min(size_t(size1
- offset
),
129 kCompareDataBufferSize
);
130 ssize_t bytesRead
= content1
.ReadAt(offset
, buffer1
, toCompare
);
133 if ((size_t)bytesRead
!= toCompare
)
136 bytesRead
= content2
.ReadAt(offset
, buffer2
, toCompare
);
139 if ((size_t)bytesRead
!= toCompare
)
142 if (memcmp(buffer1
, buffer2
, toCompare
) != 0) {
156 FSUtils::CompareSymLinks(const Entry
& entry1
, const Entry
& entry2
, bool& _equal
)
159 status_t error
= _OpenSymLink(entry1
, symLink1
);
164 error
= _OpenSymLink(entry2
, symLink2
);
168 return CompareSymLinks(symLink1
, symLink2
, _equal
);
173 FSUtils::CompareSymLinks(BSymLink
& symLink1
, BSymLink
& symLink2
, bool& _equal
)
175 char buffer1
[B_PATH_NAME_LENGTH
];
176 ssize_t bytesRead1
= symLink1
.ReadLink(buffer1
, sizeof(buffer1
));
180 char buffer2
[B_PATH_NAME_LENGTH
];
181 ssize_t bytesRead2
= symLink2
.ReadLink(buffer2
, sizeof(buffer2
));
185 _equal
= bytesRead1
== bytesRead2
186 && memcmp(buffer1
, buffer2
, bytesRead1
) == 0;
192 FSUtils::ExtractPackageContent(const Entry
& packageEntry
,
193 const char* contentPath
, const Entry
& targetDirectoryEntry
)
195 BPath packagePathBuffer
;
196 const char* packagePath
;
197 status_t error
= packageEntry
.GetPath(packagePathBuffer
, packagePath
);
201 BPath targetPathBuffer
;
202 const char* targetPath
;
203 error
= targetDirectoryEntry
.GetPath(targetPathBuffer
, targetPath
);
207 return ExtractPackageContent(packagePath
, contentPath
, targetPath
);
212 FSUtils::ExtractPackageContent(const char* packagePath
, const char* contentPath
,
213 const char* targetDirectoryPath
)
215 std::string commandLine
= std::string("package extract -C ")
216 + ShellEscapeString(targetDirectoryPath
).String()
218 + ShellEscapeString(packagePath
).String()
220 + ShellEscapeString(contentPath
).String();
221 if (system(commandLine
.c_str()) != 0)
228 FSUtils::_OpenFile(const Entry
& entry
, BFile
& file
)
232 status_t error
= entry
.GetPath(pathBuffer
, path
);
236 return file
.SetTo(path
, B_READ_ONLY
);
241 FSUtils::_OpenSymLink(const Entry
& entry
, BSymLink
& symLink
)
245 status_t error
= entry
.GetPath(pathBuffer
, path
);
249 return symLink
.SetTo(path
);