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