| 1 | /* 7zMain.c - Test application for 7z Decoder\r |
| 2 | 2016-05-16 : Igor Pavlov : Public domain */\r |
| 3 | \r |
| 4 | #include "Precomp.h"\r |
| 5 | \r |
| 6 | #include <stdio.h>\r |
| 7 | #include <string.h>\r |
| 8 | \r |
| 9 | #include "../../7z.h"\r |
| 10 | #include "../../7zAlloc.h"\r |
| 11 | #include "../../7zBuf.h"\r |
| 12 | #include "../../7zCrc.h"\r |
| 13 | #include "../../7zFile.h"\r |
| 14 | #include "../../7zVersion.h"\r |
| 15 | \r |
| 16 | #ifndef USE_WINDOWS_FILE\r |
| 17 | /* for mkdir */\r |
| 18 | #ifdef _WIN32\r |
| 19 | #include <direct.h>\r |
| 20 | #else\r |
| 21 | #include <sys/stat.h>\r |
| 22 | #include <errno.h>\r |
| 23 | #endif\r |
| 24 | #endif\r |
| 25 | \r |
| 26 | static ISzAlloc g_Alloc = { SzAlloc, SzFree };\r |
| 27 | \r |
| 28 | static int Buf_EnsureSize(CBuf *dest, size_t size)\r |
| 29 | {\r |
| 30 | if (dest->size >= size)\r |
| 31 | return 1;\r |
| 32 | Buf_Free(dest, &g_Alloc);\r |
| 33 | return Buf_Create(dest, size, &g_Alloc);\r |
| 34 | }\r |
| 35 | \r |
| 36 | #ifndef _WIN32\r |
| 37 | #define _USE_UTF8\r |
| 38 | #endif\r |
| 39 | \r |
| 40 | /* #define _USE_UTF8 */\r |
| 41 | \r |
| 42 | #ifdef _USE_UTF8\r |
| 43 | \r |
| 44 | #define _UTF8_START(n) (0x100 - (1 << (7 - (n))))\r |
| 45 | \r |
| 46 | #define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))\r |
| 47 | \r |
| 48 | #define _UTF8_HEAD(n, val) ((Byte)(_UTF8_START(n) + (val >> (6 * (n)))))\r |
| 49 | #define _UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F)))\r |
| 50 | \r |
| 51 | static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim)\r |
| 52 | {\r |
| 53 | size_t size = 0;\r |
| 54 | for (;;)\r |
| 55 | {\r |
| 56 | UInt32 val;\r |
| 57 | if (src == srcLim)\r |
| 58 | return size;\r |
| 59 | \r |
| 60 | size++;\r |
| 61 | val = *src++;\r |
| 62 | \r |
| 63 | if (val < 0x80)\r |
| 64 | continue;\r |
| 65 | \r |
| 66 | if (val < _UTF8_RANGE(1))\r |
| 67 | {\r |
| 68 | size++;\r |
| 69 | continue;\r |
| 70 | }\r |
| 71 | \r |
| 72 | if (val >= 0xD800 && val < 0xDC00 && src != srcLim)\r |
| 73 | {\r |
| 74 | UInt32 c2 = *src;\r |
| 75 | if (c2 >= 0xDC00 && c2 < 0xE000)\r |
| 76 | {\r |
| 77 | src++;\r |
| 78 | size += 3;\r |
| 79 | continue;\r |
| 80 | }\r |
| 81 | }\r |
| 82 | \r |
| 83 | size += 2;\r |
| 84 | }\r |
| 85 | }\r |
| 86 | \r |
| 87 | static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim)\r |
| 88 | {\r |
| 89 | for (;;)\r |
| 90 | {\r |
| 91 | UInt32 val;\r |
| 92 | if (src == srcLim)\r |
| 93 | return dest;\r |
| 94 | \r |
| 95 | val = *src++;\r |
| 96 | \r |
| 97 | if (val < 0x80)\r |
| 98 | {\r |
| 99 | *dest++ = (char)val;\r |
| 100 | continue;\r |
| 101 | }\r |
| 102 | \r |
| 103 | if (val < _UTF8_RANGE(1))\r |
| 104 | {\r |
| 105 | dest[0] = _UTF8_HEAD(1, val);\r |
| 106 | dest[1] = _UTF8_CHAR(0, val);\r |
| 107 | dest += 2;\r |
| 108 | continue;\r |
| 109 | }\r |
| 110 | \r |
| 111 | if (val >= 0xD800 && val < 0xDC00 && src != srcLim)\r |
| 112 | {\r |
| 113 | UInt32 c2 = *src;\r |
| 114 | if (c2 >= 0xDC00 && c2 < 0xE000)\r |
| 115 | {\r |
| 116 | src++;\r |
| 117 | val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;\r |
| 118 | dest[0] = _UTF8_HEAD(3, val);\r |
| 119 | dest[1] = _UTF8_CHAR(2, val);\r |
| 120 | dest[2] = _UTF8_CHAR(1, val);\r |
| 121 | dest[3] = _UTF8_CHAR(0, val);\r |
| 122 | dest += 4;\r |
| 123 | continue;\r |
| 124 | }\r |
| 125 | }\r |
| 126 | \r |
| 127 | dest[0] = _UTF8_HEAD(2, val);\r |
| 128 | dest[1] = _UTF8_CHAR(1, val);\r |
| 129 | dest[2] = _UTF8_CHAR(0, val);\r |
| 130 | dest += 3;\r |
| 131 | }\r |
| 132 | }\r |
| 133 | \r |
| 134 | static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)\r |
| 135 | {\r |
| 136 | size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen);\r |
| 137 | destLen += 1;\r |
| 138 | if (!Buf_EnsureSize(dest, destLen))\r |
| 139 | return SZ_ERROR_MEM;\r |
| 140 | *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0;\r |
| 141 | return SZ_OK;\r |
| 142 | }\r |
| 143 | \r |
| 144 | #endif\r |
| 145 | \r |
| 146 | static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s\r |
| 147 | #ifndef _USE_UTF8\r |
| 148 | , UINT codePage\r |
| 149 | #endif\r |
| 150 | )\r |
| 151 | {\r |
| 152 | unsigned len = 0;\r |
| 153 | for (len = 0; s[len] != 0; len++);\r |
| 154 | \r |
| 155 | #ifndef _USE_UTF8\r |
| 156 | {\r |
| 157 | unsigned size = len * 3 + 100;\r |
| 158 | if (!Buf_EnsureSize(buf, size))\r |
| 159 | return SZ_ERROR_MEM;\r |
| 160 | {\r |
| 161 | buf->data[0] = 0;\r |
| 162 | if (len != 0)\r |
| 163 | {\r |
| 164 | char defaultChar = '_';\r |
| 165 | BOOL defUsed;\r |
| 166 | unsigned numChars = 0;\r |
| 167 | numChars = WideCharToMultiByte(codePage, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);\r |
| 168 | if (numChars == 0 || numChars >= size)\r |
| 169 | return SZ_ERROR_FAIL;\r |
| 170 | buf->data[numChars] = 0;\r |
| 171 | }\r |
| 172 | return SZ_OK;\r |
| 173 | }\r |
| 174 | }\r |
| 175 | #else\r |
| 176 | return Utf16_To_Utf8Buf(buf, s, len);\r |
| 177 | #endif\r |
| 178 | }\r |
| 179 | \r |
| 180 | #ifdef _WIN32\r |
| 181 | #ifndef USE_WINDOWS_FILE\r |
| 182 | static UINT g_FileCodePage = CP_ACP;\r |
| 183 | #endif\r |
| 184 | #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage\r |
| 185 | #else\r |
| 186 | #define MY_FILE_CODE_PAGE_PARAM\r |
| 187 | #endif\r |
| 188 | \r |
| 189 | static WRes MyCreateDir(const UInt16 *name)\r |
| 190 | {\r |
| 191 | #ifdef USE_WINDOWS_FILE\r |
| 192 | \r |
| 193 | return CreateDirectoryW(name, NULL) ? 0 : GetLastError();\r |
| 194 | \r |
| 195 | #else\r |
| 196 | \r |
| 197 | CBuf buf;\r |
| 198 | WRes res;\r |
| 199 | Buf_Init(&buf);\r |
| 200 | RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));\r |
| 201 | \r |
| 202 | res =\r |
| 203 | #ifdef _WIN32\r |
| 204 | _mkdir((const char *)buf.data)\r |
| 205 | #else\r |
| 206 | mkdir((const char *)buf.data, 0777)\r |
| 207 | #endif\r |
| 208 | == 0 ? 0 : errno;\r |
| 209 | Buf_Free(&buf, &g_Alloc);\r |
| 210 | return res;\r |
| 211 | \r |
| 212 | #endif\r |
| 213 | }\r |
| 214 | \r |
| 215 | static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)\r |
| 216 | {\r |
| 217 | #ifdef USE_WINDOWS_FILE\r |
| 218 | return OutFile_OpenW(p, name);\r |
| 219 | #else\r |
| 220 | CBuf buf;\r |
| 221 | WRes res;\r |
| 222 | Buf_Init(&buf);\r |
| 223 | RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));\r |
| 224 | res = OutFile_Open(p, (const char *)buf.data);\r |
| 225 | Buf_Free(&buf, &g_Alloc);\r |
| 226 | return res;\r |
| 227 | #endif\r |
| 228 | }\r |
| 229 | \r |
| 230 | static SRes PrintString(const UInt16 *s)\r |
| 231 | {\r |
| 232 | CBuf buf;\r |
| 233 | SRes res;\r |
| 234 | Buf_Init(&buf);\r |
| 235 | res = Utf16_To_Char(&buf, s\r |
| 236 | #ifndef _USE_UTF8\r |
| 237 | , CP_OEMCP\r |
| 238 | #endif\r |
| 239 | );\r |
| 240 | if (res == SZ_OK)\r |
| 241 | fputs((const char *)buf.data, stdout);\r |
| 242 | Buf_Free(&buf, &g_Alloc);\r |
| 243 | return res;\r |
| 244 | }\r |
| 245 | \r |
| 246 | static void UInt64ToStr(UInt64 value, char *s)\r |
| 247 | {\r |
| 248 | char temp[32];\r |
| 249 | int pos = 0;\r |
| 250 | do\r |
| 251 | {\r |
| 252 | temp[pos++] = (char)('0' + (unsigned)(value % 10));\r |
| 253 | value /= 10;\r |
| 254 | }\r |
| 255 | while (value != 0);\r |
| 256 | do\r |
| 257 | *s++ = temp[--pos];\r |
| 258 | while (pos);\r |
| 259 | *s = '\0';\r |
| 260 | }\r |
| 261 | \r |
| 262 | static char *UIntToStr(char *s, unsigned value, int numDigits)\r |
| 263 | {\r |
| 264 | char temp[16];\r |
| 265 | int pos = 0;\r |
| 266 | do\r |
| 267 | temp[pos++] = (char)('0' + (value % 10));\r |
| 268 | while (value /= 10);\r |
| 269 | for (numDigits -= pos; numDigits > 0; numDigits--)\r |
| 270 | *s++ = '0';\r |
| 271 | do\r |
| 272 | *s++ = temp[--pos];\r |
| 273 | while (pos);\r |
| 274 | *s = '\0';\r |
| 275 | return s;\r |
| 276 | }\r |
| 277 | \r |
| 278 | static void UIntToStr_2(char *s, unsigned value)\r |
| 279 | {\r |
| 280 | s[0] = (char)('0' + (value / 10));\r |
| 281 | s[1] = (char)('0' + (value % 10));\r |
| 282 | }\r |
| 283 | \r |
| 284 | #define PERIOD_4 (4 * 365 + 1)\r |
| 285 | #define PERIOD_100 (PERIOD_4 * 25 - 1)\r |
| 286 | #define PERIOD_400 (PERIOD_100 * 4 + 1)\r |
| 287 | \r |
| 288 | static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)\r |
| 289 | {\r |
| 290 | unsigned year, mon, hour, min, sec;\r |
| 291 | Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r |
| 292 | unsigned t;\r |
| 293 | UInt32 v;\r |
| 294 | UInt64 v64 = nt->Low | ((UInt64)nt->High << 32);\r |
| 295 | v64 /= 10000000;\r |
| 296 | sec = (unsigned)(v64 % 60); v64 /= 60;\r |
| 297 | min = (unsigned)(v64 % 60); v64 /= 60;\r |
| 298 | hour = (unsigned)(v64 % 24); v64 /= 24;\r |
| 299 | \r |
| 300 | v = (UInt32)v64;\r |
| 301 | \r |
| 302 | year = (unsigned)(1601 + v / PERIOD_400 * 400);\r |
| 303 | v %= PERIOD_400;\r |
| 304 | \r |
| 305 | t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100;\r |
| 306 | t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4;\r |
| 307 | t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365;\r |
| 308 | \r |
| 309 | if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))\r |
| 310 | ms[1] = 29;\r |
| 311 | for (mon = 0;; mon++)\r |
| 312 | {\r |
| 313 | unsigned d = ms[mon];\r |
| 314 | if (v < d)\r |
| 315 | break;\r |
| 316 | v -= d;\r |
| 317 | }\r |
| 318 | s = UIntToStr(s, year, 4); *s++ = '-';\r |
| 319 | UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3;\r |
| 320 | UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3;\r |
| 321 | UIntToStr_2(s, hour); s[2] = ':'; s += 3;\r |
| 322 | UIntToStr_2(s, min); s[2] = ':'; s += 3;\r |
| 323 | UIntToStr_2(s, sec); s[2] = 0;\r |
| 324 | }\r |
| 325 | \r |
| 326 | void PrintError(char *sz)\r |
| 327 | {\r |
| 328 | printf("\nERROR: %s\n", sz);\r |
| 329 | }\r |
| 330 | \r |
| 331 | static void GetAttribString(UInt32 wa, Bool isDir, char *s)\r |
| 332 | {\r |
| 333 | #ifdef USE_WINDOWS_FILE\r |
| 334 | s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');\r |
| 335 | s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');\r |
| 336 | s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.');\r |
| 337 | s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.');\r |
| 338 | s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.');\r |
| 339 | s[5] = 0;\r |
| 340 | #else\r |
| 341 | s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.');\r |
| 342 | s[1] = 0;\r |
| 343 | #endif\r |
| 344 | }\r |
| 345 | \r |
| 346 | // #define NUM_PARENTS_MAX 128\r |
| 347 | \r |
| 348 | int MY_CDECL main(int numargs, char *args[])\r |
| 349 | {\r |
| 350 | CFileInStream archiveStream;\r |
| 351 | CLookToRead lookStream;\r |
| 352 | CSzArEx db;\r |
| 353 | SRes res;\r |
| 354 | ISzAlloc allocImp;\r |
| 355 | ISzAlloc allocTempImp;\r |
| 356 | UInt16 *temp = NULL;\r |
| 357 | size_t tempSize = 0;\r |
| 358 | // UInt32 parents[NUM_PARENTS_MAX];\r |
| 359 | \r |
| 360 | printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");\r |
| 361 | \r |
| 362 | if (numargs == 1)\r |
| 363 | {\r |
| 364 | printf(\r |
| 365 | "Usage: 7zDec <command> <archive_name>\n\n"\r |
| 366 | "<Commands>\n"\r |
| 367 | " e: Extract files from archive (without using directory names)\n"\r |
| 368 | " l: List contents of archive\n"\r |
| 369 | " t: Test integrity of archive\n"\r |
| 370 | " x: eXtract files with full paths\n");\r |
| 371 | return 0;\r |
| 372 | }\r |
| 373 | \r |
| 374 | if (numargs < 3)\r |
| 375 | {\r |
| 376 | PrintError("incorrect command");\r |
| 377 | return 1;\r |
| 378 | }\r |
| 379 | \r |
| 380 | #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE)\r |
| 381 | g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;\r |
| 382 | #endif\r |
| 383 | \r |
| 384 | allocImp.Alloc = SzAlloc;\r |
| 385 | allocImp.Free = SzFree;\r |
| 386 | \r |
| 387 | allocTempImp.Alloc = SzAllocTemp;\r |
| 388 | allocTempImp.Free = SzFreeTemp;\r |
| 389 | \r |
| 390 | #ifdef UNDER_CE\r |
| 391 | if (InFile_OpenW(&archiveStream.file, L"\test.7z"))\r |
| 392 | #else\r |
| 393 | if (InFile_Open(&archiveStream.file, args[2]))\r |
| 394 | #endif\r |
| 395 | {\r |
| 396 | PrintError("can not open input file");\r |
| 397 | return 1;\r |
| 398 | }\r |
| 399 | \r |
| 400 | FileInStream_CreateVTable(&archiveStream);\r |
| 401 | LookToRead_CreateVTable(&lookStream, False);\r |
| 402 | \r |
| 403 | lookStream.realStream = &archiveStream.s;\r |
| 404 | LookToRead_Init(&lookStream);\r |
| 405 | \r |
| 406 | CrcGenerateTable();\r |
| 407 | \r |
| 408 | SzArEx_Init(&db);\r |
| 409 | \r |
| 410 | res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);\r |
| 411 | \r |
| 412 | if (res == SZ_OK)\r |
| 413 | {\r |
| 414 | char *command = args[1];\r |
| 415 | int listCommand = 0, testCommand = 0, fullPaths = 0;\r |
| 416 | \r |
| 417 | if (strcmp(command, "l") == 0) listCommand = 1;\r |
| 418 | else if (strcmp(command, "t") == 0) testCommand = 1;\r |
| 419 | else if (strcmp(command, "e") == 0) { }\r |
| 420 | else if (strcmp(command, "x") == 0) { fullPaths = 1; }\r |
| 421 | else\r |
| 422 | {\r |
| 423 | PrintError("incorrect command");\r |
| 424 | res = SZ_ERROR_FAIL;\r |
| 425 | }\r |
| 426 | \r |
| 427 | if (res == SZ_OK)\r |
| 428 | {\r |
| 429 | UInt32 i;\r |
| 430 | \r |
| 431 | /*\r |
| 432 | if you need cache, use these 3 variables.\r |
| 433 | if you use external function, you can make these variable as static.\r |
| 434 | */\r |
| 435 | UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */\r |
| 436 | Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */\r |
| 437 | size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */\r |
| 438 | \r |
| 439 | for (i = 0; i < db.NumFiles; i++)\r |
| 440 | {\r |
| 441 | size_t offset = 0;\r |
| 442 | size_t outSizeProcessed = 0;\r |
| 443 | // const CSzFileItem *f = db.Files + i;\r |
| 444 | size_t len;\r |
| 445 | unsigned isDir = SzArEx_IsDir(&db, i);\r |
| 446 | if (listCommand == 0 && isDir && !fullPaths)\r |
| 447 | continue;\r |
| 448 | len = SzArEx_GetFileNameUtf16(&db, i, NULL);\r |
| 449 | // len = SzArEx_GetFullNameLen(&db, i);\r |
| 450 | \r |
| 451 | if (len > tempSize)\r |
| 452 | {\r |
| 453 | SzFree(NULL, temp);\r |
| 454 | tempSize = len;\r |
| 455 | temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));\r |
| 456 | if (!temp)\r |
| 457 | {\r |
| 458 | res = SZ_ERROR_MEM;\r |
| 459 | break;\r |
| 460 | }\r |
| 461 | }\r |
| 462 | \r |
| 463 | SzArEx_GetFileNameUtf16(&db, i, temp);\r |
| 464 | /*\r |
| 465 | if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp)\r |
| 466 | {\r |
| 467 | res = SZ_ERROR_FAIL;\r |
| 468 | break;\r |
| 469 | }\r |
| 470 | */\r |
| 471 | \r |
| 472 | if (listCommand)\r |
| 473 | {\r |
| 474 | char attr[8], s[32], t[32];\r |
| 475 | UInt64 fileSize;\r |
| 476 | \r |
| 477 | GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);\r |
| 478 | \r |
| 479 | fileSize = SzArEx_GetFileSize(&db, i);\r |
| 480 | UInt64ToStr(fileSize, s);\r |
| 481 | \r |
| 482 | if (SzBitWithVals_Check(&db.MTime, i))\r |
| 483 | ConvertFileTimeToString(&db.MTime.Vals[i], t);\r |
| 484 | else\r |
| 485 | {\r |
| 486 | size_t j;\r |
| 487 | for (j = 0; j < 19; j++)\r |
| 488 | t[j] = ' ';\r |
| 489 | t[j] = '\0';\r |
| 490 | }\r |
| 491 | \r |
| 492 | printf("%s %s %10s ", t, attr, s);\r |
| 493 | res = PrintString(temp);\r |
| 494 | if (res != SZ_OK)\r |
| 495 | break;\r |
| 496 | if (isDir)\r |
| 497 | printf("/");\r |
| 498 | printf("\n");\r |
| 499 | continue;\r |
| 500 | }\r |
| 501 | \r |
| 502 | fputs(testCommand ?\r |
| 503 | "Testing ":\r |
| 504 | "Extracting ",\r |
| 505 | stdout);\r |
| 506 | res = PrintString(temp);\r |
| 507 | if (res != SZ_OK)\r |
| 508 | break;\r |
| 509 | \r |
| 510 | if (isDir)\r |
| 511 | printf("/");\r |
| 512 | else\r |
| 513 | {\r |
| 514 | res = SzArEx_Extract(&db, &lookStream.s, i,\r |
| 515 | &blockIndex, &outBuffer, &outBufferSize,\r |
| 516 | &offset, &outSizeProcessed,\r |
| 517 | &allocImp, &allocTempImp);\r |
| 518 | if (res != SZ_OK)\r |
| 519 | break;\r |
| 520 | }\r |
| 521 | \r |
| 522 | if (!testCommand)\r |
| 523 | {\r |
| 524 | CSzFile outFile;\r |
| 525 | size_t processedSize;\r |
| 526 | size_t j;\r |
| 527 | UInt16 *name = (UInt16 *)temp;\r |
| 528 | const UInt16 *destPath = (const UInt16 *)name;\r |
| 529 | \r |
| 530 | for (j = 0; name[j] != 0; j++)\r |
| 531 | if (name[j] == '/')\r |
| 532 | {\r |
| 533 | if (fullPaths)\r |
| 534 | {\r |
| 535 | name[j] = 0;\r |
| 536 | MyCreateDir(name);\r |
| 537 | name[j] = CHAR_PATH_SEPARATOR;\r |
| 538 | }\r |
| 539 | else\r |
| 540 | destPath = name + j + 1;\r |
| 541 | }\r |
| 542 | \r |
| 543 | if (isDir)\r |
| 544 | {\r |
| 545 | MyCreateDir(destPath);\r |
| 546 | printf("\n");\r |
| 547 | continue;\r |
| 548 | }\r |
| 549 | else if (OutFile_OpenUtf16(&outFile, destPath))\r |
| 550 | {\r |
| 551 | PrintError("can not open output file");\r |
| 552 | res = SZ_ERROR_FAIL;\r |
| 553 | break;\r |
| 554 | }\r |
| 555 | \r |
| 556 | processedSize = outSizeProcessed;\r |
| 557 | \r |
| 558 | if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)\r |
| 559 | {\r |
| 560 | PrintError("can not write output file");\r |
| 561 | res = SZ_ERROR_FAIL;\r |
| 562 | break;\r |
| 563 | }\r |
| 564 | \r |
| 565 | if (File_Close(&outFile))\r |
| 566 | {\r |
| 567 | PrintError("can not close output file");\r |
| 568 | res = SZ_ERROR_FAIL;\r |
| 569 | break;\r |
| 570 | }\r |
| 571 | \r |
| 572 | #ifdef USE_WINDOWS_FILE\r |
| 573 | if (SzBitWithVals_Check(&db.Attribs, i))\r |
| 574 | SetFileAttributesW(destPath, db.Attribs.Vals[i]);\r |
| 575 | #endif\r |
| 576 | }\r |
| 577 | printf("\n");\r |
| 578 | }\r |
| 579 | IAlloc_Free(&allocImp, outBuffer);\r |
| 580 | }\r |
| 581 | }\r |
| 582 | \r |
| 583 | SzArEx_Free(&db, &allocImp);\r |
| 584 | SzFree(NULL, temp);\r |
| 585 | \r |
| 586 | File_Close(&archiveStream.file);\r |
| 587 | \r |
| 588 | if (res == SZ_OK)\r |
| 589 | {\r |
| 590 | printf("\nEverything is Ok\n");\r |
| 591 | return 0;\r |
| 592 | }\r |
| 593 | \r |
| 594 | if (res == SZ_ERROR_UNSUPPORTED)\r |
| 595 | PrintError("decoder doesn't support this archive");\r |
| 596 | else if (res == SZ_ERROR_MEM)\r |
| 597 | PrintError("can not allocate memory");\r |
| 598 | else if (res == SZ_ERROR_CRC)\r |
| 599 | PrintError("CRC error");\r |
| 600 | else\r |
| 601 | printf("\nERROR #%d\n", res);\r |
| 602 | \r |
| 603 | return 1;\r |
| 604 | }\r |