1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "py/mpconfig.h"
5 #include "py/misc.h"
6 #include "memzip.h"
7 
8 extern uint8_t memzip_data[];
9 
memzip_find_file_header(const char * filename)10 const MEMZIP_FILE_HDR *memzip_find_file_header(const char *filename) {
11 
12     const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)memzip_data;
13     uint8_t *mem_data;
14 
15     /* Zip file filenames don't have a leading /, so we strip it off */
16 
17     if (*filename == '/') {
18         filename++;
19     }
20     while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) {
21         const char *file_hdr_filename = (const char *)&file_hdr[1];
22         mem_data = (uint8_t *)file_hdr_filename;
23         mem_data += file_hdr->filename_len;
24         mem_data += file_hdr->extra_len;
25         if (!strncmp(file_hdr_filename, filename, file_hdr->filename_len)) {
26             /* We found a match */
27             return file_hdr;
28         }
29         mem_data += file_hdr->uncompressed_size;
30         file_hdr = (const MEMZIP_FILE_HDR *)mem_data;
31     }
32     return NULL;
33 }
34 
memzip_is_dir(const char * filename)35 bool memzip_is_dir(const char *filename) {
36     const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)memzip_data;
37     uint8_t *mem_data;
38 
39     if (strcmp(filename, "/") == 0) {
40         // The root directory is a directory.
41         return true;
42     }
43 
44     // Zip filenames don't have a leading /, so we strip it off
45     if (*filename == '/') {
46         filename++;
47     }
48     size_t filename_len = strlen(filename);
49 
50     while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) {
51         const char *file_hdr_filename = (const char *)&file_hdr[1];
52         if (filename_len < file_hdr->filename_len &&
53             strncmp(file_hdr_filename, filename, filename_len) == 0 &&
54             file_hdr_filename[filename_len] == '/') {
55             return true;
56         }
57 
58         mem_data = (uint8_t *)file_hdr_filename;
59         mem_data += file_hdr->filename_len;
60         mem_data += file_hdr->extra_len;
61         mem_data += file_hdr->uncompressed_size;
62         file_hdr = (const MEMZIP_FILE_HDR *)mem_data;
63     }
64     return NULL;
65 
66 }
67 
memzip_locate(const char * filename,void ** data,size_t * len)68 MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len)
69 {
70     const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(filename);
71     if (file_hdr == NULL) {
72         return MZ_NO_FILE;
73     }
74     if (file_hdr->compression_method != 0) {
75         return MZ_FILE_COMPRESSED;
76     }
77 
78     uint8_t *mem_data;
79     mem_data = (uint8_t *)&file_hdr[1];
80     mem_data += file_hdr->filename_len;
81     mem_data += file_hdr->extra_len;
82 
83     *data = mem_data;
84     *len = file_hdr->uncompressed_size;
85     return MZ_OK;
86 }
87 
memzip_stat(const char * path,MEMZIP_FILE_INFO * info)88 MEMZIP_RESULT memzip_stat(const char *path, MEMZIP_FILE_INFO *info) {
89     const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(path);
90     if (file_hdr == NULL) {
91         if (memzip_is_dir(path)) {
92             info->file_size = 0;
93             info->last_mod_date = 0;
94             info->last_mod_time = 0;
95             info->is_dir = 1;
96             return MZ_OK;
97         }
98         return MZ_NO_FILE;
99     }
100     info->file_size = file_hdr->uncompressed_size;
101     info->last_mod_date = file_hdr->last_mod_date;
102     info->last_mod_time = file_hdr->last_mod_time;
103     info->is_dir = 0;
104 
105     return MZ_OK;
106 }
107