├── LICENSE.txt ├── README.md ├── miniphysfs.h └── test ├── Makefile ├── example.c ├── physfs.c ├── physfs_platform.c └── test_physfs.c /LICENSE.txt: -------------------------------------------------------------------------------- 1 | License for PhysFS: 2 | 3 | zlib license 4 | 5 | Copyright (c) 2001-2020 Ryan C. Gordon and others. 6 | 7 | This software is provided 'as-is', without any express or implied warranty. 8 | In no event will the authors be held liable for any damages arising from 9 | the use of this software. 10 | 11 | Permission is granted to anyone to use this software for any purpose, 12 | including commercial applications, and to alter it and redistribute it 13 | freely, subject to the following restrictions: 14 | 15 | 1. The origin of this software must not be misrepresented; you must not 16 | claim that you wrote the original software. If you use this software in a 17 | product, an acknowledgment in the product documentation would be 18 | appreciated but is not required. 19 | 20 | 2. Altered source versions must be plainly marked as such, and must not be 21 | misrepresented as being the original software. 22 | 23 | 3. This notice may not be removed or altered from any source distribution. 24 | 25 | Ryan C. Gordon 26 | 27 | License for miniphyfs.h: 28 | 29 | zlib license 30 | 31 | Copyright (c) 2020 Eduardo Bart 32 | 33 | This software is provided 'as-is', without any express or implied warranty. 34 | In no event will the authors be held liable for any damages arising from 35 | the use of this software. 36 | 37 | Permission is granted to anyone to use this software for any purpose, 38 | including commercial applications, and to alter it and redistribute it 39 | freely, subject to the following restrictions: 40 | 41 | 1. The origin of this software must not be misrepresented; you must not 42 | claim that you wrote the original software. If you use this software in a 43 | product, an acknowledgment in the product documentation would be 44 | appreciated but is not required. 45 | 46 | 2. Altered source versions must be plainly marked as such, and must not be 47 | misrepresented as being the original software. 48 | 49 | 3. This notice may not be removed or altered from any source distribution. 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MiniPhysFS 2 | 3 | This is the PhysFS contained in a single header to be bundled in C/C++ applications with ease. 4 | [PhysFS](https://icculus.org/physfs/) is a library to provide abstract access to various archives. 5 | 6 | # Example Usage 7 | 8 | ```C 9 | #define PHYSFS_IMPL 10 | #define PHYSFS_PLATFORM_IMPL 11 | #define PHYSFS_SUPPORTS_ONLY_ZIP 12 | #include "miniphysfs.h" 13 | 14 | int main(int argc, char **argv) { 15 | if(!PHYSFS_init(argv[0])) { 16 | printf("PhysFS initialization failed: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); 17 | return -1; 18 | } 19 | /* your PhysFS logic here */ 20 | PHYSFS_deinit(); 21 | return 0; 22 | } 23 | ``` 24 | 25 | # Usage 26 | 27 | MiniPhysFS do very little modification to the original library, the PhysFS sources were concatenated 28 | to a single C header and some defines were added to make easy of use. 29 | 30 | To use the header do this 31 | ```C 32 | #define PHYSFS_IMPL 33 | #define PHYSFS_PLATFORM_IMPL 34 | ``` 35 | before you include this file in *one* C file to create the implementation. 36 | 37 | On MacOS you need to define PHYSFS_PLATFORM_IMPL in a separate a `.m` file. 38 | And on Haiku or WinRT you need to define PHYSFS_PLATFORM_IMPL in a separate `.cpp` file. 39 | 40 | Note that almost no modification was made in the PhysFS implementation code, 41 | thus there are some C variable names that may collide with your code, 42 | therefore it is best to declare the PhysFS implementation in dedicated C file. 43 | 44 | By default all archives are supported, you can disable any of them by defining: 45 | ``` 46 | PHYSFS_SUPPORTS_NO_ZIP 47 | PHYSFS_SUPPORTS_NO_7Z 48 | PHYSFS_SUPPORTS_NO_GRP 49 | PHYSFS_SUPPORTS_NO_WAD 50 | PHYSFS_SUPPORTS_NO_HOG 51 | PHYSFS_SUPPORTS_NO_MVL 52 | PHYSFS_SUPPORTS_NO_QPAK 53 | PHYSFS_SUPPORTS_NO_SLB 54 | PHYSFS_SUPPORTS_NO_ISO9660 55 | PHYSFS_SUPPORTS_NO_VDF 56 | ``` 57 | Or you can request *only* certain archives to be supported by defining one of these: 58 | ``` 59 | PHYSFS_SUPPORTS_ONLY_ZIP 60 | PHYSFS_SUPPORTS_ONLY_7Z 61 | PHYSFS_SUPPORTS_ONLY_GRP 62 | PHYSFS_SUPPORTS_ONLY_WAD 63 | PHYSFS_SUPPORTS_ONLY_HOG 64 | PHYSFS_SUPPORTS_ONLY_MVL 65 | PHYSFS_SUPPORTS_ONLY_QPAK 66 | PHYSFS_SUPPORTS_ONLY_SLB 67 | PHYSFS_SUPPORTS_ONLY_ISO9660 68 | PHYSFS_SUPPORTS_ONLY_VDF 69 | ``` 70 | 71 | Optionally provide the following defines with your own implementations: 72 | - `PHYSFS_DECL` - public function declaration prefix (default: extern) 73 | 74 | 75 | # Documentation 76 | 77 | For documentation on how to use PhysFS read the header or 78 | its [official documentation](https://icculus.org/physfs/docs/). 79 | 80 | # Updates 81 | 82 | - **07-May-2021**: Updated to PhysFS changeset [e0346f434926](https://hg.icculus.org/icculus/physfs/rev/e0346f434926), for better ARM64 support. 83 | - **20-Nov-2020**: Library created, using PhysFS changeset 84 | [acdcf93d1f9b](https://hg.icculus.org/icculus/physfs/rev/acdcf93d1f9b) 85 | 86 | # Notes 87 | 88 | PhysFS 3.1.0 with latest changeset (as 20-Nov-2020) [acdcf93d1f9b](https://hg.icculus.org/icculus/physfs/rev/acdcf93d1f9b) 89 | was used to make this library, the PhysFS 3.1.0 is not officially released yet, 90 | but this changeset was chosen due to the added support for Android. 91 | 92 | # License 93 | 94 | Same license as PhysFS, zlib license, see LICENSE.txt for licensing information. 95 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-O2 -Wall -I.. 3 | 4 | all: test_physfs example 5 | 6 | test_physfs: test_physfs.c physfs.c physfs_platform.c ../miniphysfs.h 7 | $(CC) $(CFLAGS) test_physfs.c physfs_platform.c physfs.c -o test_physfs 8 | 9 | example: example.c ../miniphysfs.h 10 | $(CC) $(CFLAGS) example.c -o example 11 | 12 | clean: 13 | rm -f test_physfs example 14 | -------------------------------------------------------------------------------- /test/example.c: -------------------------------------------------------------------------------- 1 | #define PHYSFS_IMPL 2 | #define PHYSFS_PLATFORM_IMPL 3 | #include "miniphysfs.h" 4 | 5 | int main(int argc, char **argv) { 6 | if(!PHYSFS_init(argv[0])) { 7 | printf("PhysFS initialization failed: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); 8 | return -1; 9 | } 10 | PHYSFS_deinit(); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /test/physfs.c: -------------------------------------------------------------------------------- 1 | #define PHYSFS_IMPL 2 | #include "miniphysfs.h" 3 | -------------------------------------------------------------------------------- /test/physfs_platform.c: -------------------------------------------------------------------------------- 1 | #define PHYSFS_PLATFORM_IMPL 2 | #include "miniphysfs.h" 3 | -------------------------------------------------------------------------------- /test/test_physfs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Test program for PhysicsFS. May only work on Unix. 3 | * 4 | * Please see the file LICENSE.txt in the source's root directory. 5 | * 6 | * This file written by Ryan C. Gordon. 7 | */ 8 | 9 | #define _CRT_SECURE_NO_WARNINGS 1 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if (defined __MWERKS__) 17 | #include 18 | #endif 19 | 20 | #if (defined PHYSFS_HAVE_READLINE) 21 | #include 22 | #include 23 | #include 24 | #endif 25 | 26 | #include 27 | 28 | /* Define this, so the compiler doesn't complain about using old APIs. */ 29 | #define PHYSFS_DEPRECATED 30 | 31 | #include "miniphysfs.h" 32 | 33 | 34 | #define TEST_VERSION_MAJOR 3 35 | #define TEST_VERSION_MINOR 1 36 | #define TEST_VERSION_PATCH 0 37 | 38 | static FILE *history_file = NULL; 39 | static PHYSFS_uint32 do_buffer_size = 0; 40 | 41 | static void output_versions(void) 42 | { 43 | PHYSFS_Version compiled; 44 | PHYSFS_Version linked; 45 | 46 | PHYSFS_VERSION(&compiled); 47 | PHYSFS_getLinkedVersion(&linked); 48 | 49 | printf("test_physfs version %d.%d.%d.\n" 50 | " Compiled against PhysicsFS version %d.%d.%d,\n" 51 | " and linked against %d.%d.%d.\n\n", 52 | TEST_VERSION_MAJOR, TEST_VERSION_MINOR, TEST_VERSION_PATCH, 53 | (int) compiled.major, (int) compiled.minor, (int) compiled.patch, 54 | (int) linked.major, (int) linked.minor, (int) linked.patch); 55 | } /* output_versions */ 56 | 57 | 58 | static void output_archivers(void) 59 | { 60 | const PHYSFS_ArchiveInfo **rc = PHYSFS_supportedArchiveTypes(); 61 | const PHYSFS_ArchiveInfo **i; 62 | 63 | printf("Supported archive types:\n"); 64 | if (*rc == NULL) 65 | printf(" * Apparently, NONE!\n"); 66 | else 67 | { 68 | for (i = rc; *i != NULL; i++) 69 | { 70 | printf(" * %s: %s\n Written by %s.\n %s\n", 71 | (*i)->extension, (*i)->description, 72 | (*i)->author, (*i)->url); 73 | printf(" %s symbolic links.\n", 74 | (*i)->supportsSymlinks ? "Supports" : "Does not support"); 75 | } /* for */ 76 | } /* else */ 77 | 78 | printf("\n"); 79 | } /* output_archivers */ 80 | 81 | 82 | static int cmd_quit(char *args) 83 | { 84 | return 0; 85 | } /* cmd_quit */ 86 | 87 | 88 | static int cmd_init(char *args) 89 | { 90 | if (*args == '\"') 91 | { 92 | args++; 93 | args[strlen(args) - 1] = '\0'; 94 | } /* if */ 95 | 96 | if (PHYSFS_init(args)) 97 | printf("Successful.\n"); 98 | else 99 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 100 | 101 | return 1; 102 | } /* cmd_init */ 103 | 104 | 105 | static int cmd_deinit(char *args) 106 | { 107 | if (PHYSFS_deinit()) 108 | printf("Successful.\n"); 109 | else 110 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 111 | 112 | return 1; 113 | } /* cmd_deinit */ 114 | 115 | 116 | static int cmd_addarchive(char *args) 117 | { 118 | char *ptr = strrchr(args, ' '); 119 | int appending = atoi(ptr + 1); 120 | *ptr = '\0'; 121 | 122 | if (*args == '\"') 123 | { 124 | args++; 125 | *(ptr - 1) = '\0'; 126 | } /* if */ 127 | 128 | /*printf("[%s], [%d]\n", args, appending);*/ 129 | 130 | if (PHYSFS_mount(args, NULL, appending)) 131 | printf("Successful.\n"); 132 | else 133 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 134 | 135 | return 1; 136 | } /* cmd_addarchive */ 137 | 138 | 139 | /* wrap free() to avoid calling convention wankery. */ 140 | static void freeBuf(void *buf) 141 | { 142 | free(buf); 143 | } /* freeBuf */ 144 | 145 | typedef enum 146 | { 147 | MNTTYPE_PATH, 148 | MNTTYPE_MEMORY, 149 | MNTTYPE_HANDLE 150 | } MountType; 151 | 152 | static int cmd_mount_internal(char *args, const MountType mnttype) 153 | { 154 | char *ptr; 155 | char *mntpoint = NULL; 156 | int appending = 0; 157 | int rc = 0; 158 | 159 | if (*args == '\"') 160 | { 161 | args++; 162 | ptr = strchr(args, '\"'); 163 | if (ptr == NULL) 164 | { 165 | printf("missing string terminator in argument.\n"); 166 | return 1; 167 | } /* if */ 168 | *(ptr) = '\0'; 169 | } /* if */ 170 | else 171 | { 172 | ptr = strchr(args, ' '); 173 | *ptr = '\0'; 174 | } /* else */ 175 | 176 | mntpoint = ptr + 1; 177 | if (*mntpoint == '\"') 178 | { 179 | mntpoint++; 180 | ptr = strchr(mntpoint, '\"'); 181 | if (ptr == NULL) 182 | { 183 | printf("missing string terminator in argument.\n"); 184 | return 1; 185 | } /* if */ 186 | *(ptr) = '\0'; 187 | } /* if */ 188 | else 189 | { 190 | ptr = strchr(mntpoint, ' '); 191 | *(ptr) = '\0'; 192 | } /* else */ 193 | appending = atoi(ptr + 1); 194 | 195 | /*printf("[%s], [%s], [%d]\n", args, mntpoint, appending);*/ 196 | 197 | if (mnttype == MNTTYPE_PATH) 198 | rc = PHYSFS_mount(args, mntpoint, appending); 199 | 200 | else if (mnttype == MNTTYPE_HANDLE) 201 | { 202 | PHYSFS_File *f = PHYSFS_openRead(args); 203 | if (f == NULL) 204 | { 205 | printf("PHYSFS_openRead('%s') failed. reason: %s.\n", args, PHYSFS_getLastError()); 206 | return 1; 207 | } /* if */ 208 | 209 | rc = PHYSFS_mountHandle(f, args, mntpoint, appending); 210 | if (!rc) 211 | PHYSFS_close(f); 212 | } /* else if */ 213 | 214 | else if (mnttype == MNTTYPE_MEMORY) 215 | { 216 | FILE *in = fopen(args, "rb"); 217 | void *buf = NULL; 218 | long len = 0; 219 | 220 | if (in == NULL) 221 | { 222 | printf("Failed to open %s to read into memory: %s.\n", args, strerror(errno)); 223 | return 1; 224 | } /* if */ 225 | 226 | if ( (fseek(in, 0, SEEK_END) != 0) || ((len = ftell(in)) < 0) ) 227 | { 228 | printf("Failed to find size of %s to read into memory: %s.\n", args, strerror(errno)); 229 | fclose(in); 230 | return 1; 231 | } /* if */ 232 | 233 | buf = malloc(len); 234 | if (buf == NULL) 235 | { 236 | printf("Failed to allocate space to read %s into memory: %s.\n", args, strerror(errno)); 237 | fclose(in); 238 | return 1; 239 | } /* if */ 240 | 241 | if ((fseek(in, 0, SEEK_SET) != 0) || (fread(buf, len, 1, in) != 1)) 242 | { 243 | printf("Failed to read %s into memory: %s.\n", args, strerror(errno)); 244 | fclose(in); 245 | free(buf); 246 | return 1; 247 | } /* if */ 248 | 249 | fclose(in); 250 | 251 | rc = PHYSFS_mountMemory(buf, len, freeBuf, args, mntpoint, appending); 252 | } /* else */ 253 | 254 | if (rc) 255 | printf("Successful.\n"); 256 | else 257 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 258 | 259 | return 1; 260 | } /* cmd_mount_internal */ 261 | 262 | 263 | static int cmd_mount(char *args) 264 | { 265 | return cmd_mount_internal(args, MNTTYPE_PATH); 266 | } /* cmd_mount */ 267 | 268 | 269 | static int cmd_mount_mem(char *args) 270 | { 271 | return cmd_mount_internal(args, MNTTYPE_MEMORY); 272 | } /* cmd_mount_mem */ 273 | 274 | 275 | static int cmd_mount_handle(char *args) 276 | { 277 | return cmd_mount_internal(args, MNTTYPE_HANDLE); 278 | } /* cmd_mount_handle */ 279 | 280 | static int cmd_getmountpoint(char *args) 281 | { 282 | if (*args == '\"') 283 | { 284 | args++; 285 | args[strlen(args) - 1] = '\0'; 286 | } /* if */ 287 | 288 | printf("Dir [%s] is mounted at [%s].\n", args, PHYSFS_getMountPoint(args)); 289 | return 1; 290 | } /* cmd_getmountpoint */ 291 | 292 | 293 | static int cmd_setroot(char *args) 294 | { 295 | char *archive; 296 | char *subdir; 297 | char *ptr; 298 | 299 | archive = args; 300 | if (*archive == '\"') 301 | { 302 | archive++; 303 | ptr = strchr(archive, '\"'); 304 | if (ptr == NULL) 305 | { 306 | printf("missing string terminator in argument.\n"); 307 | return 1; 308 | } /* if */ 309 | *(ptr) = '\0'; 310 | } /* if */ 311 | else 312 | { 313 | ptr = strchr(archive, ' '); 314 | *ptr = '\0'; 315 | } /* else */ 316 | 317 | subdir = ptr + 1; 318 | if (*subdir == '\"') 319 | { 320 | subdir++; 321 | ptr = strchr(subdir, '\"'); 322 | if (ptr == NULL) 323 | { 324 | printf("missing string terminator in argument.\n"); 325 | return 1; 326 | } /* if */ 327 | *(ptr) = '\0'; 328 | } /* if */ 329 | 330 | if (PHYSFS_setRoot(archive, subdir)) 331 | printf("Successful.\n"); 332 | else 333 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 334 | 335 | return 1; 336 | } /* cmd_setroot */ 337 | 338 | 339 | static int cmd_removearchive(char *args) 340 | { 341 | if (*args == '\"') 342 | { 343 | args++; 344 | args[strlen(args) - 1] = '\0'; 345 | } /* if */ 346 | 347 | if (PHYSFS_unmount(args)) 348 | printf("Successful.\n"); 349 | else 350 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 351 | 352 | return 1; 353 | } /* cmd_removearchive */ 354 | 355 | 356 | static int cmd_enumerate(char *args) 357 | { 358 | char **rc; 359 | 360 | if (*args == '\"') 361 | { 362 | args++; 363 | args[strlen(args) - 1] = '\0'; 364 | } /* if */ 365 | 366 | rc = PHYSFS_enumerateFiles(args); 367 | 368 | if (rc == NULL) 369 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 370 | else 371 | { 372 | int file_count; 373 | char **i; 374 | for (i = rc, file_count = 0; *i != NULL; i++, file_count++) 375 | printf("%s\n", *i); 376 | 377 | printf("\n total (%d) files.\n", file_count); 378 | PHYSFS_freeList(rc); 379 | } /* else */ 380 | 381 | return 1; 382 | } /* cmd_enumerate */ 383 | 384 | 385 | static int cmd_getdirsep(char *args) 386 | { 387 | printf("Directory separator is [%s].\n", PHYSFS_getDirSeparator()); 388 | return 1; 389 | } /* cmd_getdirsep */ 390 | 391 | 392 | static int cmd_getlasterror(char *args) 393 | { 394 | printf("last error is [%s].\n", PHYSFS_getLastError()); 395 | return 1; 396 | } /* cmd_getlasterror */ 397 | 398 | 399 | static int cmd_getcdromdirs(char *args) 400 | { 401 | char **rc = PHYSFS_getCdRomDirs(); 402 | 403 | if (rc == NULL) 404 | printf("Failure. Reason: [%s].\n", PHYSFS_getLastError()); 405 | else 406 | { 407 | int dir_count; 408 | char **i; 409 | for (i = rc, dir_count = 0; *i != NULL; i++, dir_count++) 410 | printf("%s\n", *i); 411 | 412 | printf("\n total (%d) drives.\n", dir_count); 413 | PHYSFS_freeList(rc); 414 | } /* else */ 415 | 416 | return 1; 417 | } /* cmd_getcdromdirs */ 418 | 419 | 420 | static int cmd_getsearchpath(char *args) 421 | { 422 | char **rc = PHYSFS_getSearchPath(); 423 | 424 | if (rc == NULL) 425 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 426 | else 427 | { 428 | int dir_count; 429 | char **i; 430 | for (i = rc, dir_count = 0; *i != NULL; i++, dir_count++) 431 | printf("%s\n", *i); 432 | 433 | printf("\n total (%d) directories.\n", dir_count); 434 | PHYSFS_freeList(rc); 435 | } /* else */ 436 | 437 | return 1; 438 | } /* cmd_getcdromdirs */ 439 | 440 | 441 | static int cmd_getbasedir(char *args) 442 | { 443 | printf("Base dir is [%s].\n", PHYSFS_getBaseDir()); 444 | return 1; 445 | } /* cmd_getbasedir */ 446 | 447 | 448 | static int cmd_getuserdir(char *args) 449 | { 450 | printf("User dir is [%s].\n", PHYSFS_getUserDir()); 451 | return 1; 452 | } /* cmd_getuserdir */ 453 | 454 | 455 | static int cmd_getprefdir(char *args) 456 | { 457 | char *org; 458 | char *appName; 459 | char *ptr = args; 460 | 461 | org = ptr; 462 | ptr = strchr(ptr, ' '); *ptr = '\0'; ptr++; appName = ptr; 463 | printf("Pref dir is [%s].\n", PHYSFS_getPrefDir(org, appName)); 464 | return 1; 465 | } /* cmd_getprefdir */ 466 | 467 | 468 | static int cmd_getwritedir(char *args) 469 | { 470 | printf("Write dir is [%s].\n", PHYSFS_getWriteDir()); 471 | return 1; 472 | } /* cmd_getwritedir */ 473 | 474 | 475 | static int cmd_setwritedir(char *args) 476 | { 477 | if (*args == '\"') 478 | { 479 | args++; 480 | args[strlen(args) - 1] = '\0'; 481 | } /* if */ 482 | 483 | if (PHYSFS_setWriteDir(args)) 484 | printf("Successful.\n"); 485 | else 486 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 487 | 488 | return 1; 489 | } /* cmd_setwritedir */ 490 | 491 | 492 | static int cmd_permitsyms(char *args) 493 | { 494 | int num; 495 | 496 | if (*args == '\"') 497 | { 498 | args++; 499 | args[strlen(args) - 1] = '\0'; 500 | } /* if */ 501 | 502 | num = atoi(args); 503 | PHYSFS_permitSymbolicLinks(num); 504 | printf("Symlinks are now %s.\n", num ? "permitted" : "forbidden"); 505 | return 1; 506 | } /* cmd_permitsyms */ 507 | 508 | 509 | static int cmd_setbuffer(char *args) 510 | { 511 | if (*args == '\"') 512 | { 513 | args++; 514 | args[strlen(args) - 1] = '\0'; 515 | } /* if */ 516 | 517 | do_buffer_size = (unsigned int) atoi(args); 518 | if (do_buffer_size) 519 | { 520 | printf("Further tests will set a (%lu) size buffer.\n", 521 | (unsigned long) do_buffer_size); 522 | } /* if */ 523 | 524 | else 525 | { 526 | printf("Further tests will NOT use a buffer.\n"); 527 | } /* else */ 528 | 529 | return 1; 530 | } /* cmd_setbuffer */ 531 | 532 | 533 | static int cmd_stressbuffer(char *args) 534 | { 535 | int num; 536 | 537 | if (*args == '\"') 538 | { 539 | args++; 540 | args[strlen(args) - 1] = '\0'; 541 | } /* if */ 542 | 543 | num = atoi(args); 544 | if (num < 0) 545 | printf("buffer must be greater than or equal to zero.\n"); 546 | else 547 | { 548 | PHYSFS_File *f; 549 | int rndnum; 550 | 551 | printf("Stress testing with (%d) byte buffer...\n", num); 552 | f = PHYSFS_openWrite("test.txt"); 553 | if (f == NULL) 554 | printf("Couldn't open test.txt for writing: %s.\n", PHYSFS_getLastError()); 555 | else 556 | { 557 | int i, j; 558 | char buf[37]; 559 | char buf2[37]; 560 | 561 | if (!PHYSFS_setBuffer(f, num)) 562 | { 563 | printf("PHYSFS_setBuffer() failed: %s.\n", PHYSFS_getLastError()); 564 | PHYSFS_close(f); 565 | PHYSFS_delete("test.txt"); 566 | return 1; 567 | } /* if */ 568 | 569 | strcpy(buf, "abcdefghijklmnopqrstuvwxyz0123456789"); 570 | srand((unsigned int) time(NULL)); 571 | 572 | for (i = 0; i < 10; i++) 573 | { 574 | for (j = 0; j < 10000; j++) 575 | { 576 | PHYSFS_uint32 right = 1 + (PHYSFS_uint32) (35.0 * rand() / (RAND_MAX + 1.0)); 577 | PHYSFS_uint32 left = 36 - right; 578 | if (PHYSFS_writeBytes(f, buf, left) != left) 579 | { 580 | printf("PHYSFS_writeBytes() failed: %s.\n", PHYSFS_getLastError()); 581 | PHYSFS_close(f); 582 | return 1; 583 | } /* if */ 584 | 585 | rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0)); 586 | if (rndnum == 42) 587 | { 588 | if (!PHYSFS_flush(f)) 589 | { 590 | printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError()); 591 | PHYSFS_close(f); 592 | return 1; 593 | } /* if */ 594 | } /* if */ 595 | 596 | if (PHYSFS_writeBytes(f, buf + left, right) != right) 597 | { 598 | printf("PHYSFS_writeBytes() failed: %s.\n", PHYSFS_getLastError()); 599 | PHYSFS_close(f); 600 | return 1; 601 | } /* if */ 602 | 603 | rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0)); 604 | if (rndnum == 42) 605 | { 606 | if (!PHYSFS_flush(f)) 607 | { 608 | printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError()); 609 | PHYSFS_close(f); 610 | return 1; 611 | } /* if */ 612 | } /* if */ 613 | } /* for */ 614 | 615 | if (!PHYSFS_flush(f)) 616 | { 617 | printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError()); 618 | PHYSFS_close(f); 619 | return 1; 620 | } /* if */ 621 | 622 | } /* for */ 623 | 624 | if (!PHYSFS_close(f)) 625 | { 626 | printf("PHYSFS_close() failed: %s.\n", PHYSFS_getLastError()); 627 | return 1; /* oh well. */ 628 | } /* if */ 629 | 630 | printf(" ... test file written ...\n"); 631 | f = PHYSFS_openRead("test.txt"); 632 | if (f == NULL) 633 | { 634 | printf("Failed to reopen stress file for reading: %s.\n", PHYSFS_getLastError()); 635 | return 1; 636 | } /* if */ 637 | 638 | if (!PHYSFS_setBuffer(f, num)) 639 | { 640 | printf("PHYSFS_setBuffer() failed: %s.\n", PHYSFS_getLastError()); 641 | PHYSFS_close(f); 642 | return 1; 643 | } /* if */ 644 | 645 | for (i = 0; i < 10; i++) 646 | { 647 | for (j = 0; j < 10000; j++) 648 | { 649 | PHYSFS_uint32 right = 1 + (PHYSFS_uint32) (35.0 * rand() / (RAND_MAX + 1.0)); 650 | PHYSFS_uint32 left = 36 - right; 651 | if (PHYSFS_readBytes(f, buf2, left) != left) 652 | { 653 | printf("PHYSFS_readBytes() failed: %s.\n", PHYSFS_getLastError()); 654 | PHYSFS_close(f); 655 | return 1; 656 | } /* if */ 657 | 658 | rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0)); 659 | if (rndnum == 42) 660 | { 661 | if (!PHYSFS_flush(f)) 662 | { 663 | printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError()); 664 | PHYSFS_close(f); 665 | return 1; 666 | } /* if */ 667 | } /* if */ 668 | 669 | if (PHYSFS_readBytes(f, buf2 + left, right) != right) 670 | { 671 | printf("PHYSFS_readBytes() failed: %s.\n", PHYSFS_getLastError()); 672 | PHYSFS_close(f); 673 | return 1; 674 | } /* if */ 675 | 676 | rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0)); 677 | if (rndnum == 42) 678 | { 679 | if (!PHYSFS_flush(f)) 680 | { 681 | printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError()); 682 | PHYSFS_close(f); 683 | return 1; 684 | } /* if */ 685 | } /* if */ 686 | 687 | if (memcmp(buf, buf2, 36) != 0) 688 | { 689 | printf("readback is mismatched on iterations (%d, %d).\n", i, j); 690 | printf("wanted: ["); 691 | for (i = 0; i < 36; i++) 692 | printf("%c", buf[i]); 693 | printf("]\n"); 694 | 695 | printf(" got: ["); 696 | for (i = 0; i < 36; i++) 697 | printf("%c", buf2[i]); 698 | printf("]\n"); 699 | PHYSFS_close(f); 700 | return 1; 701 | } /* if */ 702 | } /* for */ 703 | 704 | if (!PHYSFS_flush(f)) 705 | { 706 | printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError()); 707 | PHYSFS_close(f); 708 | return 1; 709 | } /* if */ 710 | 711 | } /* for */ 712 | 713 | printf(" ... test file read ...\n"); 714 | 715 | if (!PHYSFS_eof(f)) 716 | printf("PHYSFS_eof() returned true! That's wrong.\n"); 717 | 718 | if (!PHYSFS_close(f)) 719 | { 720 | printf("PHYSFS_close() failed: %s.\n", PHYSFS_getLastError()); 721 | return 1; /* oh well. */ 722 | } /* if */ 723 | 724 | PHYSFS_delete("test.txt"); 725 | printf("stress test completed successfully.\n"); 726 | } /* else */ 727 | } /* else */ 728 | 729 | return 1; 730 | } /* cmd_stressbuffer */ 731 | 732 | 733 | static int cmd_setsaneconfig(char *args) 734 | { 735 | char *org; 736 | char *appName; 737 | char *arcExt; 738 | int inclCD; 739 | int arcsFirst; 740 | char *ptr = args; 741 | 742 | /* ugly. */ 743 | org = ptr; 744 | ptr = strchr(ptr, ' '); *ptr = '\0'; ptr++; appName = ptr; 745 | ptr = strchr(ptr, ' '); *ptr = '\0'; ptr++; arcExt = ptr; 746 | ptr = strchr(ptr, ' '); *ptr = '\0'; ptr++; inclCD = atoi(arcExt); 747 | arcsFirst = atoi(ptr); 748 | 749 | if (strcmp(arcExt, "!") == 0) 750 | arcExt = NULL; 751 | 752 | if (PHYSFS_setSaneConfig(org, appName, arcExt, inclCD, arcsFirst)) 753 | printf("Successful.\n"); 754 | else 755 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 756 | 757 | return 1; 758 | } /* cmd_setsaneconfig */ 759 | 760 | 761 | static int cmd_mkdir(char *args) 762 | { 763 | if (*args == '\"') 764 | { 765 | args++; 766 | args[strlen(args) - 1] = '\0'; 767 | } /* if */ 768 | 769 | if (PHYSFS_mkdir(args)) 770 | printf("Successful.\n"); 771 | else 772 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 773 | 774 | return 1; 775 | } /* cmd_mkdir */ 776 | 777 | 778 | static int cmd_delete(char *args) 779 | { 780 | if (*args == '\"') 781 | { 782 | args++; 783 | args[strlen(args) - 1] = '\0'; 784 | } /* if */ 785 | 786 | if (PHYSFS_delete(args)) 787 | printf("Successful.\n"); 788 | else 789 | printf("Failure. reason: %s.\n", PHYSFS_getLastError()); 790 | 791 | return 1; 792 | } /* cmd_delete */ 793 | 794 | 795 | static int cmd_getrealdir(char *args) 796 | { 797 | const char *rc; 798 | 799 | if (*args == '\"') 800 | { 801 | args++; 802 | args[strlen(args) - 1] = '\0'; 803 | } /* if */ 804 | 805 | rc = PHYSFS_getRealDir(args); 806 | if (rc) 807 | printf("Found at [%s].\n", rc); 808 | else 809 | printf("Not found.\n"); 810 | 811 | return 1; 812 | } /* cmd_getrealdir */ 813 | 814 | 815 | static int cmd_exists(char *args) 816 | { 817 | int rc; 818 | 819 | if (*args == '\"') 820 | { 821 | args++; 822 | args[strlen(args) - 1] = '\0'; 823 | } /* if */ 824 | 825 | rc = PHYSFS_exists(args); 826 | printf("File %sexists.\n", rc ? "" : "does not "); 827 | return 1; 828 | } /* cmd_exists */ 829 | 830 | 831 | static int cmd_isdir(char *args) 832 | { 833 | PHYSFS_Stat statbuf; 834 | int rc; 835 | 836 | if (*args == '\"') 837 | { 838 | args++; 839 | args[strlen(args) - 1] = '\0'; 840 | } /* if */ 841 | 842 | rc = PHYSFS_stat(args, &statbuf); 843 | if (rc) 844 | rc = (statbuf.filetype == PHYSFS_FILETYPE_DIRECTORY); 845 | printf("File %s a directory.\n", rc ? "is" : "is NOT"); 846 | return 1; 847 | } /* cmd_isdir */ 848 | 849 | 850 | static int cmd_issymlink(char *args) 851 | { 852 | PHYSFS_Stat statbuf; 853 | int rc; 854 | 855 | if (*args == '\"') 856 | { 857 | args++; 858 | args[strlen(args) - 1] = '\0'; 859 | } /* if */ 860 | 861 | rc = PHYSFS_stat(args, &statbuf); 862 | if (rc) 863 | rc = (statbuf.filetype == PHYSFS_FILETYPE_SYMLINK); 864 | printf("File %s a symlink.\n", rc ? "is" : "is NOT"); 865 | return 1; 866 | } /* cmd_issymlink */ 867 | 868 | 869 | static int cmd_cat(char *args) 870 | { 871 | PHYSFS_File *f; 872 | 873 | if (*args == '\"') 874 | { 875 | args++; 876 | args[strlen(args) - 1] = '\0'; 877 | } /* if */ 878 | 879 | f = PHYSFS_openRead(args); 880 | if (f == NULL) 881 | printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError()); 882 | else 883 | { 884 | if (do_buffer_size) 885 | { 886 | if (!PHYSFS_setBuffer(f, do_buffer_size)) 887 | { 888 | printf("failed to set file buffer. Reason: [%s].\n", 889 | PHYSFS_getLastError()); 890 | PHYSFS_close(f); 891 | return 1; 892 | } /* if */ 893 | } /* if */ 894 | 895 | while (1) 896 | { 897 | char buffer[128]; 898 | PHYSFS_sint64 rc; 899 | PHYSFS_sint64 i; 900 | rc = PHYSFS_readBytes(f, buffer, sizeof (buffer)); 901 | 902 | for (i = 0; i < rc; i++) 903 | fputc((int) buffer[i], stdout); 904 | 905 | if (rc < sizeof (buffer)) 906 | { 907 | printf("\n\n"); 908 | if (!PHYSFS_eof(f)) 909 | { 910 | printf("\n (Error condition in reading. Reason: [%s])\n\n", 911 | PHYSFS_getLastError()); 912 | } /* if */ 913 | PHYSFS_close(f); 914 | return 1; 915 | } /* if */ 916 | } /* while */ 917 | } /* else */ 918 | 919 | return 1; 920 | } /* cmd_cat */ 921 | 922 | static int cmd_cat2(char *args) 923 | { 924 | PHYSFS_File *f1 = NULL; 925 | PHYSFS_File *f2 = NULL; 926 | char *fname1; 927 | char *fname2; 928 | char *ptr; 929 | 930 | fname1 = args; 931 | if (*fname1 == '\"') 932 | { 933 | fname1++; 934 | ptr = strchr(fname1, '\"'); 935 | if (ptr == NULL) 936 | { 937 | printf("missing string terminator in argument.\n"); 938 | return 1; 939 | } /* if */ 940 | *(ptr) = '\0'; 941 | } /* if */ 942 | else 943 | { 944 | ptr = strchr(fname1, ' '); 945 | *ptr = '\0'; 946 | } /* else */ 947 | 948 | fname2 = ptr + 1; 949 | if (*fname2 == '\"') 950 | { 951 | fname2++; 952 | ptr = strchr(fname2, '\"'); 953 | if (ptr == NULL) 954 | { 955 | printf("missing string terminator in argument.\n"); 956 | return 1; 957 | } /* if */ 958 | *(ptr) = '\0'; 959 | } /* if */ 960 | 961 | if ((f1 = PHYSFS_openRead(fname1)) == NULL) 962 | printf("failed to open '%s'. Reason: [%s].\n", fname1, PHYSFS_getLastError()); 963 | else if ((f2 = PHYSFS_openRead(fname2)) == NULL) 964 | printf("failed to open '%s'. Reason: [%s].\n", fname2, PHYSFS_getLastError()); 965 | else 966 | { 967 | char *buffer1 = NULL; 968 | size_t buffer1len = 0; 969 | char *buffer2 = NULL; 970 | size_t buffer2len = 0; 971 | char *ptr = NULL; 972 | size_t i; 973 | 974 | if (do_buffer_size) 975 | { 976 | if (!PHYSFS_setBuffer(f1, do_buffer_size)) 977 | { 978 | printf("failed to set file buffer for '%s'. Reason: [%s].\n", 979 | fname1, PHYSFS_getLastError()); 980 | PHYSFS_close(f1); 981 | PHYSFS_close(f2); 982 | return 1; 983 | } /* if */ 984 | else if (!PHYSFS_setBuffer(f2, do_buffer_size)) 985 | { 986 | printf("failed to set file buffer for '%s'. Reason: [%s].\n", 987 | fname2, PHYSFS_getLastError()); 988 | PHYSFS_close(f1); 989 | PHYSFS_close(f2); 990 | return 1; 991 | } /* if */ 992 | } /* if */ 993 | 994 | 995 | do 996 | { 997 | int readlen = 128; 998 | PHYSFS_sint64 rc; 999 | 1000 | ptr = (char*)realloc(buffer1, buffer1len + readlen); 1001 | if (!ptr) 1002 | { 1003 | printf("(Out of memory.)\n\n"); 1004 | free(buffer1); 1005 | free(buffer2); 1006 | PHYSFS_close(f1); 1007 | PHYSFS_close(f2); 1008 | return 1; 1009 | } /* if */ 1010 | 1011 | buffer1 = ptr; 1012 | rc = PHYSFS_readBytes(f1, buffer1 + buffer1len, readlen); 1013 | if (rc < 0) 1014 | { 1015 | printf("(Error condition in reading '%s'. Reason: [%s])\n\n", 1016 | fname1, PHYSFS_getLastError()); 1017 | free(buffer1); 1018 | free(buffer2); 1019 | PHYSFS_close(f1); 1020 | PHYSFS_close(f2); 1021 | return 1; 1022 | } /* if */ 1023 | buffer1len += (size_t) rc; 1024 | 1025 | ptr = (char*)realloc(buffer2, buffer2len + readlen); 1026 | if (!ptr) 1027 | { 1028 | printf("(Out of memory.)\n\n"); 1029 | free(buffer1); 1030 | free(buffer2); 1031 | PHYSFS_close(f1); 1032 | PHYSFS_close(f2); 1033 | return 1; 1034 | } /* if */ 1035 | 1036 | buffer2 = ptr; 1037 | rc = PHYSFS_readBytes(f2, buffer2 + buffer2len, readlen); 1038 | if (rc < 0) 1039 | { 1040 | printf("(Error condition in reading '%s'. Reason: [%s])\n\n", 1041 | fname2, PHYSFS_getLastError()); 1042 | free(buffer1); 1043 | free(buffer2); 1044 | PHYSFS_close(f1); 1045 | PHYSFS_close(f2); 1046 | return 1; 1047 | } /* if */ 1048 | buffer2len += (size_t) rc; 1049 | } while (!PHYSFS_eof(f1) || !PHYSFS_eof(f2)); 1050 | 1051 | printf("file '%s' ...\n\n", fname1); 1052 | for (i = 0; i < buffer1len; i++) 1053 | fputc((int) buffer1[i], stdout); 1054 | free(buffer1); 1055 | 1056 | printf("\n\nfile '%s' ...\n\n", fname2); 1057 | for (i = 0; i < buffer2len; i++) 1058 | fputc((int) buffer2[i], stdout); 1059 | free(buffer2); 1060 | 1061 | printf("\n\n"); 1062 | } /* else */ 1063 | 1064 | if (f1) 1065 | PHYSFS_close(f1); 1066 | 1067 | if (f2) 1068 | PHYSFS_close(f2); 1069 | 1070 | return 1; 1071 | } /* cmd_cat2 */ 1072 | 1073 | 1074 | #define CRC32_BUFFERSIZE 512 1075 | static int cmd_crc32(char *args) 1076 | { 1077 | PHYSFS_File *f; 1078 | 1079 | if (*args == '\"') 1080 | { 1081 | args++; 1082 | args[strlen(args) - 1] = '\0'; 1083 | } /* if */ 1084 | 1085 | f = PHYSFS_openRead(args); 1086 | if (f == NULL) 1087 | printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError()); 1088 | else 1089 | { 1090 | PHYSFS_uint8 buffer[CRC32_BUFFERSIZE]; 1091 | PHYSFS_uint32 crc = -1; 1092 | PHYSFS_sint64 bytesread; 1093 | 1094 | while ((bytesread = PHYSFS_readBytes(f, buffer, CRC32_BUFFERSIZE)) > 0) 1095 | { 1096 | PHYSFS_uint32 i, bit; 1097 | for (i = 0; i < bytesread; i++) 1098 | { 1099 | for (bit = 0; bit < 8; bit++, buffer[i] >>= 1) 1100 | crc = (crc >> 1) ^ (((crc ^ buffer[i]) & 1) ? 0xEDB88320 : 0); 1101 | } /* for */ 1102 | } /* while */ 1103 | 1104 | if (bytesread < 0) 1105 | { 1106 | printf("error while reading. Reason: [%s].\n", 1107 | PHYSFS_getLastError()); 1108 | return 1; 1109 | } /* if */ 1110 | 1111 | PHYSFS_close(f); 1112 | 1113 | crc ^= -1; 1114 | printf("CRC32 for %s: 0x%08X\n", args, crc); 1115 | } /* else */ 1116 | 1117 | return 1; 1118 | } /* cmd_crc32 */ 1119 | 1120 | 1121 | static int cmd_filelength(char *args) 1122 | { 1123 | PHYSFS_File *f; 1124 | 1125 | if (*args == '\"') 1126 | { 1127 | args++; 1128 | args[strlen(args) - 1] = '\0'; 1129 | } /* if */ 1130 | 1131 | f = PHYSFS_openRead(args); 1132 | if (f == NULL) 1133 | printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError()); 1134 | else 1135 | { 1136 | PHYSFS_sint64 len = PHYSFS_fileLength(f); 1137 | if (len == -1) 1138 | printf("failed to determine length. Reason: [%s].\n", PHYSFS_getLastError()); 1139 | else 1140 | printf(" (cast to int) %d bytes.\n", (int) len); 1141 | 1142 | PHYSFS_close(f); 1143 | } /* else */ 1144 | 1145 | return 1; 1146 | } /* cmd_filelength */ 1147 | 1148 | #define WRITESTR "The cat sat on the mat.\n\n" 1149 | 1150 | static int cmd_append(char *args) 1151 | { 1152 | PHYSFS_File *f; 1153 | 1154 | if (*args == '\"') 1155 | { 1156 | args++; 1157 | args[strlen(args) - 1] = '\0'; 1158 | } /* if */ 1159 | 1160 | f = PHYSFS_openAppend(args); 1161 | if (f == NULL) 1162 | printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError()); 1163 | else 1164 | { 1165 | size_t bw; 1166 | PHYSFS_sint64 rc; 1167 | 1168 | if (do_buffer_size) 1169 | { 1170 | if (!PHYSFS_setBuffer(f, do_buffer_size)) 1171 | { 1172 | printf("failed to set file buffer. Reason: [%s].\n", 1173 | PHYSFS_getLastError()); 1174 | PHYSFS_close(f); 1175 | return 1; 1176 | } /* if */ 1177 | } /* if */ 1178 | 1179 | bw = strlen(WRITESTR); 1180 | rc = PHYSFS_writeBytes(f, WRITESTR, bw); 1181 | if (rc != bw) 1182 | { 1183 | printf("Wrote (%d) of (%d) bytes. Reason: [%s].\n", 1184 | (int) rc, (int) bw, PHYSFS_getLastError()); 1185 | } /* if */ 1186 | else 1187 | { 1188 | printf("Successful.\n"); 1189 | } /* else */ 1190 | 1191 | PHYSFS_close(f); 1192 | } /* else */ 1193 | 1194 | return 1; 1195 | } /* cmd_append */ 1196 | 1197 | 1198 | static int cmd_write(char *args) 1199 | { 1200 | PHYSFS_File *f; 1201 | 1202 | if (*args == '\"') 1203 | { 1204 | args++; 1205 | args[strlen(args) - 1] = '\0'; 1206 | } /* if */ 1207 | 1208 | f = PHYSFS_openWrite(args); 1209 | if (f == NULL) 1210 | printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError()); 1211 | else 1212 | { 1213 | size_t bw; 1214 | PHYSFS_sint64 rc; 1215 | 1216 | if (do_buffer_size) 1217 | { 1218 | if (!PHYSFS_setBuffer(f, do_buffer_size)) 1219 | { 1220 | printf("failed to set file buffer. Reason: [%s].\n", 1221 | PHYSFS_getLastError()); 1222 | PHYSFS_close(f); 1223 | return 1; 1224 | } /* if */ 1225 | } /* if */ 1226 | 1227 | bw = strlen(WRITESTR); 1228 | rc = PHYSFS_writeBytes(f, WRITESTR, bw); 1229 | if (rc != bw) 1230 | { 1231 | printf("Wrote (%d) of (%d) bytes. Reason: [%s].\n", 1232 | (int) rc, (int) bw, PHYSFS_getLastError()); 1233 | } /* if */ 1234 | else 1235 | { 1236 | printf("Successful.\n"); 1237 | } /* else */ 1238 | 1239 | PHYSFS_close(f); 1240 | } /* else */ 1241 | 1242 | return 1; 1243 | } /* cmd_write */ 1244 | 1245 | 1246 | static char* modTimeToStr(PHYSFS_sint64 modtime, char *modstr, size_t strsize) 1247 | { 1248 | if (modtime < 0) 1249 | strncpy(modstr, "Unknown\n", strsize); 1250 | else 1251 | { 1252 | time_t t = (time_t) modtime; 1253 | char *str = ctime(&t); 1254 | strncpy(modstr, str, strsize); 1255 | } /* else */ 1256 | 1257 | modstr[strsize-1] = '\0'; 1258 | return modstr; 1259 | } /* modTimeToStr */ 1260 | 1261 | 1262 | static int cmd_getlastmodtime(char *args) 1263 | { 1264 | PHYSFS_Stat statbuf; 1265 | if (!PHYSFS_stat(args, &statbuf)) 1266 | printf("Failed to determine. Reason: [%s].\n", PHYSFS_getLastError()); 1267 | else 1268 | { 1269 | char modstr[64]; 1270 | modTimeToStr(statbuf.modtime, modstr, sizeof (modstr)); 1271 | printf("Last modified: %s (%ld).\n", modstr, (long) statbuf.modtime); 1272 | } /* else */ 1273 | 1274 | return 1; 1275 | } /* cmd_getLastModTime */ 1276 | 1277 | static int cmd_stat(char *args) 1278 | { 1279 | PHYSFS_Stat stat; 1280 | char timestring[65]; 1281 | 1282 | if (*args == '\"') 1283 | { 1284 | args++; 1285 | args[strlen(args) - 1] = '\0'; 1286 | } /* if */ 1287 | 1288 | if(!PHYSFS_stat(args, &stat)) 1289 | { 1290 | printf("failed to stat. Reason [%s].\n", PHYSFS_getLastError()); 1291 | return 1; 1292 | } /* if */ 1293 | 1294 | printf("Filename: %s\n", args); 1295 | printf("Size %d\n",(int) stat.filesize); 1296 | 1297 | if(stat.filetype == PHYSFS_FILETYPE_REGULAR) 1298 | printf("Type: File\n"); 1299 | else if(stat.filetype == PHYSFS_FILETYPE_DIRECTORY) 1300 | printf("Type: Directory\n"); 1301 | else if(stat.filetype == PHYSFS_FILETYPE_SYMLINK) 1302 | printf("Type: Symlink\n"); 1303 | else 1304 | printf("Type: Unknown\n"); 1305 | 1306 | printf("Created at: %s", modTimeToStr(stat.createtime, timestring, 64)); 1307 | printf("Last modified at: %s", modTimeToStr(stat.modtime, timestring, 64)); 1308 | printf("Last accessed at: %s", modTimeToStr(stat.accesstime, timestring, 64)); 1309 | printf("Readonly: %s\n", stat.readonly ? "true" : "false"); 1310 | 1311 | return 1; 1312 | } /* cmd_filelength */ 1313 | 1314 | 1315 | 1316 | /* must have spaces trimmed prior to this call. */ 1317 | static int count_args(const char *str) 1318 | { 1319 | int retval = 0; 1320 | int in_quotes = 0; 1321 | 1322 | if (str != NULL) 1323 | { 1324 | for (; *str != '\0'; str++) 1325 | { 1326 | if (*str == '\"') 1327 | in_quotes = !in_quotes; 1328 | else if ((*str == ' ') && (!in_quotes)) 1329 | retval++; 1330 | } /* for */ 1331 | retval++; 1332 | } /* if */ 1333 | 1334 | return retval; 1335 | } /* count_args */ 1336 | 1337 | 1338 | static int cmd_help(char *args); 1339 | 1340 | typedef struct 1341 | { 1342 | const char *cmd; 1343 | int (*func)(char *args); 1344 | int argcount; 1345 | const char *usage; 1346 | } command_info; 1347 | 1348 | static const command_info commands[] = 1349 | { 1350 | { "quit", cmd_quit, 0, NULL }, 1351 | { "q", cmd_quit, 0, NULL }, 1352 | { "help", cmd_help, 0, NULL }, 1353 | { "init", cmd_init, 1, "" }, 1354 | { "deinit", cmd_deinit, 0, NULL }, 1355 | { "addarchive", cmd_addarchive, 2, " " }, 1356 | { "mount", cmd_mount, 3, " " }, 1357 | { "mountmem", cmd_mount_mem, 3, " " }, 1358 | { "mounthandle", cmd_mount_handle, 3, " " }, 1359 | { "removearchive", cmd_removearchive, 1, "" }, 1360 | { "unmount", cmd_removearchive, 1, "" }, 1361 | { "enumerate", cmd_enumerate, 1, "" }, 1362 | { "ls", cmd_enumerate, 1, "" }, 1363 | { "getlasterror", cmd_getlasterror, 0, NULL }, 1364 | { "getdirsep", cmd_getdirsep, 0, NULL }, 1365 | { "getcdromdirs", cmd_getcdromdirs, 0, NULL }, 1366 | { "getsearchpath", cmd_getsearchpath, 0, NULL }, 1367 | { "getbasedir", cmd_getbasedir, 0, NULL }, 1368 | { "getuserdir", cmd_getuserdir, 0, NULL }, 1369 | { "getprefdir", cmd_getprefdir, 2, " " }, 1370 | { "getwritedir", cmd_getwritedir, 0, NULL }, 1371 | { "setwritedir", cmd_setwritedir, 1, "" }, 1372 | { "permitsymlinks", cmd_permitsyms, 1, "<1or0>" }, 1373 | { "setsaneconfig", cmd_setsaneconfig, 5, " " }, 1374 | { "mkdir", cmd_mkdir, 1, "" }, 1375 | { "delete", cmd_delete, 1, "" }, 1376 | { "getrealdir", cmd_getrealdir, 1, "" }, 1377 | { "exists", cmd_exists, 1, "" }, 1378 | { "isdir", cmd_isdir, 1, "" }, 1379 | { "issymlink", cmd_issymlink, 1, "" }, 1380 | { "cat", cmd_cat, 1, "" }, 1381 | { "cat2", cmd_cat2, 2, " " }, 1382 | { "filelength", cmd_filelength, 1, "" }, 1383 | { "stat", cmd_stat, 1, "" }, 1384 | { "append", cmd_append, 1, "" }, 1385 | { "write", cmd_write, 1, "" }, 1386 | { "getlastmodtime", cmd_getlastmodtime, 1, "" }, 1387 | { "setbuffer", cmd_setbuffer, 1, "" }, 1388 | { "stressbuffer", cmd_stressbuffer, 1, "" }, 1389 | { "crc32", cmd_crc32, 1, "" }, 1390 | { "getmountpoint", cmd_getmountpoint, 1, "" }, 1391 | { "setroot", cmd_setroot, 2, " " }, 1392 | { NULL, NULL, -1, NULL } 1393 | }; 1394 | 1395 | 1396 | static void output_usage(const char *intro, const command_info *cmdinfo) 1397 | { 1398 | if (cmdinfo->argcount == 0) 1399 | printf("%s \"%s\" (no arguments)\n", intro, cmdinfo->cmd); 1400 | else 1401 | printf("%s \"%s %s\"\n", intro, cmdinfo->cmd, cmdinfo->usage); 1402 | } /* output_usage */ 1403 | 1404 | 1405 | static int cmd_help(char *args) 1406 | { 1407 | const command_info *i; 1408 | 1409 | printf("Commands:\n"); 1410 | for (i = commands; i->cmd != NULL; i++) 1411 | output_usage(" -", i); 1412 | 1413 | return 1; 1414 | } /* output_cmd_help */ 1415 | 1416 | 1417 | static void trim_command(const char *orig, char *copy) 1418 | { 1419 | const char *i; 1420 | char *writeptr = copy; 1421 | int spacecount = 0; 1422 | int have_first = 0; 1423 | 1424 | for (i = orig; *i != '\0'; i++) 1425 | { 1426 | if (*i == ' ') 1427 | { 1428 | if ((*(i + 1) != ' ') && (*(i + 1) != '\0')) 1429 | { 1430 | if ((have_first) && (!spacecount)) 1431 | { 1432 | spacecount++; 1433 | *writeptr = ' '; 1434 | writeptr++; 1435 | } /* if */ 1436 | } /* if */ 1437 | } /* if */ 1438 | else 1439 | { 1440 | have_first = 1; 1441 | spacecount = 0; 1442 | *writeptr = *i; 1443 | writeptr++; 1444 | } /* else */ 1445 | } /* for */ 1446 | 1447 | *writeptr = '\0'; 1448 | 1449 | /* 1450 | printf("\n command is [%s].\n", copy); 1451 | */ 1452 | } /* trim_command */ 1453 | 1454 | 1455 | static int process_command(char *complete_cmd) 1456 | { 1457 | const command_info *i; 1458 | char *cmd_copy; 1459 | char *args; 1460 | int rc = 1; 1461 | 1462 | if (complete_cmd == NULL) /* can happen if user hits CTRL-D, etc. */ 1463 | { 1464 | printf("\n"); 1465 | return 0; 1466 | } /* if */ 1467 | 1468 | cmd_copy = (char *) malloc(strlen(complete_cmd) + 1); 1469 | if (cmd_copy == NULL) 1470 | { 1471 | printf("\n\n\nOUT OF MEMORY!\n\n\n"); 1472 | return 0; 1473 | } /* if */ 1474 | 1475 | trim_command(complete_cmd, cmd_copy); 1476 | args = strchr(cmd_copy, ' '); 1477 | if (args != NULL) 1478 | { 1479 | *args = '\0'; 1480 | args++; 1481 | } /* else */ 1482 | 1483 | if (cmd_copy[0] != '\0') 1484 | { 1485 | for (i = commands; i->cmd != NULL; i++) 1486 | { 1487 | if (strcmp(i->cmd, cmd_copy) == 0) 1488 | { 1489 | if ((i->argcount >= 0) && (count_args(args) != i->argcount)) 1490 | output_usage("usage:", i); 1491 | else 1492 | rc = i->func(args); 1493 | break; 1494 | } /* if */ 1495 | } /* for */ 1496 | 1497 | if (i->cmd == NULL) 1498 | printf("Unknown command. Enter \"help\" for instructions.\n"); 1499 | 1500 | #if (defined PHYSFS_HAVE_READLINE) 1501 | add_history(complete_cmd); 1502 | if (history_file) 1503 | { 1504 | fprintf(history_file, "%s\n", complete_cmd); 1505 | fflush(history_file); 1506 | } /* if */ 1507 | #endif 1508 | 1509 | } /* if */ 1510 | 1511 | free(cmd_copy); 1512 | return rc; 1513 | } /* process_command */ 1514 | 1515 | 1516 | static void open_history_file(void) 1517 | { 1518 | #if (defined PHYSFS_HAVE_READLINE) 1519 | #if 0 1520 | const char *envr = getenv("TESTPHYSFS_HISTORY"); 1521 | if (!envr) 1522 | return; 1523 | #else 1524 | char envr[256]; 1525 | strcpy(envr, PHYSFS_getUserDir()); 1526 | strcat(envr, ".testphys_history"); 1527 | #endif 1528 | 1529 | if (access(envr, F_OK) == 0) 1530 | { 1531 | char buf[512]; 1532 | FILE *f = fopen(envr, "r"); 1533 | if (!f) 1534 | { 1535 | printf("\n\n" 1536 | "Could not open history file [%s] for reading!\n" 1537 | " Will not have past history available.\n\n", 1538 | envr); 1539 | return; 1540 | } /* if */ 1541 | 1542 | do 1543 | { 1544 | if (fgets(buf, sizeof (buf), f) == NULL) 1545 | break; 1546 | 1547 | if (buf[strlen(buf) - 1] == '\n') 1548 | buf[strlen(buf) - 1] = '\0'; 1549 | add_history(buf); 1550 | } while (!feof(f)); 1551 | 1552 | fclose(f); 1553 | } /* if */ 1554 | 1555 | history_file = fopen(envr, "ab"); 1556 | if (!history_file) 1557 | { 1558 | printf("\n\n" 1559 | "Could not open history file [%s] for appending!\n" 1560 | " Will not be able to record this session's history.\n\n", 1561 | envr); 1562 | } /* if */ 1563 | #endif 1564 | } /* open_history_file */ 1565 | 1566 | 1567 | int main(int argc, char **argv) 1568 | { 1569 | char *buf = NULL; 1570 | int rc = 0; 1571 | 1572 | #if (defined __MWERKS__) 1573 | extern tSIOUXSettings SIOUXSettings; 1574 | SIOUXSettings.asktosaveonclose = 0; 1575 | SIOUXSettings.autocloseonquit = 1; 1576 | SIOUXSettings.rows = 40; 1577 | SIOUXSettings.columns = 120; 1578 | #endif 1579 | 1580 | printf("\n"); 1581 | 1582 | if (!PHYSFS_init(argv[0])) 1583 | { 1584 | printf("PHYSFS_init() failed!\n reason: %s.\n", PHYSFS_getLastError()); 1585 | return 1; 1586 | } /* if */ 1587 | 1588 | output_versions(); 1589 | output_archivers(); 1590 | 1591 | open_history_file(); 1592 | 1593 | printf("Enter commands. Enter \"help\" for instructions.\n"); 1594 | fflush(stdout); 1595 | 1596 | do 1597 | { 1598 | #if (defined PHYSFS_HAVE_READLINE) 1599 | buf = readline("> "); 1600 | #else 1601 | int i; 1602 | buf = (char *) malloc(512); 1603 | memset(buf, '\0', 512); 1604 | printf("> "); 1605 | fflush(stdout); 1606 | for (i = 0; i < 511; i++) 1607 | { 1608 | int ch = fgetc(stdin); 1609 | if (ch == EOF) 1610 | { 1611 | strcpy(buf, "quit"); 1612 | break; 1613 | } /* if */ 1614 | else if ((ch == '\n') || (ch == '\r')) 1615 | { 1616 | buf[i] = '\0'; 1617 | break; 1618 | } /* else if */ 1619 | else if (ch == '\b') 1620 | { 1621 | if (i > 0) 1622 | i--; 1623 | } /* else if */ 1624 | else 1625 | { 1626 | buf[i] = (char) ch; 1627 | } /* else */ 1628 | } /* for */ 1629 | #endif 1630 | 1631 | rc = process_command(buf); 1632 | fflush(stdout); 1633 | if (buf != NULL) 1634 | free(buf); 1635 | } while (rc); 1636 | 1637 | if (!PHYSFS_deinit()) 1638 | printf("PHYSFS_deinit() failed!\n reason: %s.\n", PHYSFS_getLastError()); 1639 | 1640 | if (history_file) 1641 | fclose(history_file); 1642 | 1643 | /* 1644 | printf("\n\ntest_physfs written by ryan c. gordon.\n"); 1645 | printf(" it makes you shoot teh railgun bettar.\n"); 1646 | */ 1647 | 1648 | return 0; 1649 | } /* main */ 1650 | 1651 | /* end of test_physfs.c ... */ 1652 | 1653 | --------------------------------------------------------------------------------