Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

zip: implement zip extraction support

This adds code sufficient to extract files to available storage given a
suitable root directory to extract to. It works on an already open zip
handle and also supports chain-loading a secondary callback in the event
that integration into the process is desired.

Change-Id: Id200d8f20d84a0cbd22906470de8bbd21d4525ef

+182
+178
firmware/common/zip.c
··· 22 22 #include "zip.h" 23 23 #include <string.h> 24 24 #include "file.h" 25 + #include "dir.h" 25 26 #include "system.h" 27 + #include "errno.h" 26 28 #include "core_alloc.h" 27 29 #include "timefuncs.h" 30 + #include "pathfuncs.h" 28 31 #include "crc32.h" 29 32 #include "rbendian.h" 30 33 ··· 155 158 const uint8_t* mem; 156 159 off_t mem_offset; 157 160 off_t mem_size; 161 + }; 162 + 163 + struct zip_extract { 164 + zip_callback cb; 165 + void* ctx; 166 + size_t name_offset; 167 + size_t name_size; 168 + char* name; 169 + int file; 170 + char path[MAX_PATH]; 158 171 }; 159 172 160 173 static int zip_read_ed(struct zip* z) { ··· 606 619 z->mem_size = mem_size; 607 620 } 608 621 622 + static int zip_extract_start(const struct zip_args* args, struct zip_extract* ze) { 623 + size_t name_length; 624 + const char* dir; 625 + size_t dir_length; 626 + 627 + if ((name_length = strlcpy(ze->name, args->name, ze->name_size)) >= ze->name_size) 628 + return 5; 629 + 630 + if ((dir_length = path_dirname(ze->name, &dir)) > 0) { 631 + char c = ze->name[dir_length]; 632 + 633 + ze->name[dir_length] = '\0'; 634 + 635 + if (!dir_exists(ze->path)) { 636 + const char* path = ze->name; 637 + const char* name; 638 + 639 + while (parse_path_component(&path, &name) > 0) { 640 + size_t offset = path - ze->name; 641 + char c = ze->name[offset]; 642 + 643 + ze->name[offset] = '\0'; 644 + 645 + if (mkdir(ze->path) < 0 && errno != EEXIST) 646 + return 6; 647 + 648 + ze->name[offset] = c; 649 + } 650 + } 651 + 652 + ze->name[dir_length] = c; 653 + } 654 + 655 + if (ze->name[name_length - 1] == PATH_SEPCH) { 656 + if (mkdir(ze->path) < 0 && errno != EEXIST) 657 + return 7; 658 + 659 + return 0; 660 + } 661 + 662 + if ((ze->file = creat(ze->path, 0666)) < 0) 663 + return 8; 664 + 665 + return 0; 666 + } 667 + 668 + static int zip_extract_data(const struct zip_args* args, struct zip_extract* ze) { 669 + if (write(ze->file, args->block, args->block_size) != (ssize_t) args->block_size) { 670 + return 9; 671 + } 672 + 673 + return 0; 674 + } 675 + 676 + static int zip_extract_end(const struct zip_args* args, struct zip_extract* ze) { 677 + int rv; 678 + 679 + if (ze->file >= 0) { 680 + rv = close(ze->file); 681 + 682 + ze->file = -1; 683 + 684 + if (rv < 0) 685 + return 10; 686 + } 687 + 688 + if (modtime(ze->path, args->mtime) < 0) 689 + return 11; 690 + 691 + return 0; 692 + } 693 + 694 + static int zip_extract_callback(const struct zip_args* args, int pass, void* ctx) { 695 + struct zip_extract* ze = ctx; 696 + int rv; 697 + 698 + if (ze->cb != NULL && (rv = ze->cb(args, pass, ze->ctx)) != 0) 699 + return rv; 700 + 701 + switch (pass) { 702 + case ZIP_PASS_START: 703 + return zip_extract_start(args, ze); 704 + 705 + case ZIP_PASS_DATA: 706 + return zip_extract_data(args, ze); 707 + 708 + case ZIP_PASS_END: 709 + return zip_extract_end(args, ze); 710 + 711 + default: 712 + return 1; 713 + } 714 + } 715 + 609 716 struct zip* zip_open(const char* name, bool try_mem) { 610 717 int file = -1; 611 718 int mem_handle = -1; ··· 690 797 691 798 read_entries: 692 799 return zip_read_entries(z); 800 + } 801 + 802 + int zip_extract(struct zip* z, const char* root, zip_callback cb, void* ctx) { 803 + int rv; 804 + int ze_handle = -1; 805 + struct zip_extract* ze; 806 + char* path; 807 + size_t size; 808 + size_t length; 809 + 810 + if (root == NULL || root[0] == '\0') 811 + root = PATH_ROOTSTR; 812 + 813 + if (root[0] != PATH_SEPCH) { 814 + rv = -1; 815 + goto bail; 816 + } 817 + 818 + if (!dir_exists(root)) { 819 + rv = 1; 820 + goto bail; 821 + } 822 + 823 + if ((ze_handle = zip_core_alloc(sizeof(struct zip_extract))) < 0) { 824 + rv = 2; 825 + goto bail; 826 + } 827 + 828 + ze = core_get_data(ze_handle); 829 + ze->cb = cb; 830 + ze->ctx = ctx; 831 + ze->file = -1; 832 + 833 + path = ze->path; 834 + size = sizeof(ze->path); 835 + length = strlcpy(path, root, size); 836 + 837 + if (length >= size) { 838 + rv = 3; 839 + goto bail; 840 + } 841 + 842 + path += length; 843 + size -= length; 844 + 845 + if (path[-1] != PATH_SEPCH) { 846 + length = strlcpy(path, PATH_SEPSTR, size); 847 + 848 + if (length >= size) { 849 + rv = 4; 850 + goto bail; 851 + } 852 + 853 + path += length; 854 + size -= length; 855 + } 856 + 857 + ze->name_offset = path - ze->path; 858 + ze->name_size = size; 859 + ze->name = path; 860 + 861 + rv = zip_read_deep(z, zip_extract_callback, ze); 862 + 863 + bail: 864 + if (ze_handle >= 0) { 865 + if (ze->file >= 0) 866 + close(ze->file); 867 + 868 + core_free(ze_handle); 869 + } 870 + return rv; 693 871 } 694 872 695 873 void zip_close(struct zip* z) {
+4
firmware/include/zip.h
··· 58 58 // this can also pickup where a successful shallow read leftoff 59 59 int zip_read_deep(struct zip* z, zip_callback cb, void* ctx); 60 60 61 + // extract the contents to an existing directory 62 + // this can also pickup where a successful shallow read leftoff 63 + int zip_extract(struct zip* z, const char* root, zip_callback cb, void* ctx); 64 + 61 65 // returns system resources 62 66 void zip_close(struct zip* z); 63 67