int lws_alloc_vfs_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount) { lws_filepos_t len; lws_fop_flags_t flags = LWS_O_RDONLY; lws_fop_fd_t fops_fd = lws_vfs_file_open( lws_get_fops(context), filename, &flags); int ret = 1; if (!fops_fd) return 1; len = lws_vfs_get_length(fops_fd); *buf = lws_malloc((size_t)len, "lws_alloc_vfs_file"); if (!*buf) goto bail; if (lws_vfs_file_read(fops_fd, amount, *buf, len)) goto bail; ret = 0; bail: lws_vfs_file_close(&fops_fd); return ret; }
int lws_fops_zip_scan(lws_fops_zip_t priv, const char *name, int len) { lws_filepos_t amount; uint8_t buf[96]; int i; if (lws_vfs_file_seek_end(priv->zip_fop_fd, -ZE_DIRECTORY_LENGTH) < 0) return LWS_FZ_ERR_SEEK_END_RECORD; if (lws_vfs_file_read(priv->zip_fop_fd, &amount, buf, ZE_DIRECTORY_LENGTH)) return LWS_FZ_ERR_READ_END_RECORD; if (amount != ZE_DIRECTORY_LENGTH) return LWS_FZ_ERR_READ_END_RECORD; /* * We require the zip to have the last record right at the end * Linux zip always does this if no zip comment. */ if (buf[0] != 'P' || buf[1] != 'K' || buf[2] != 5 || buf[3] != 6) return LWS_FZ_ERR_END_RECORD_MAGIC; i = get_u16(buf + ZE_NUM_ENTRIES); if (get_u16(buf + ZE_DESK_NUMBER) || get_u16(buf + ZE_CENTRAL_DIRECTORY_DISK_NUMBER) || i != get_u16(buf + ZE_NUM_ENTRIES_THIS_DISK)) return LWS_FZ_ERR_END_RECORD_SANITY; /* end record is OK... look for our file in the central dir */ if (lws_vfs_file_seek_set(priv->zip_fop_fd, get_u32(buf + ZE_CENTRAL_DIR_OFFSET)) < 0) return LWS_FZ_ERR_CENTRAL_SEEK; while (i--) { priv->content_start = lws_vfs_tell(priv->zip_fop_fd); if (lws_vfs_file_read(priv->zip_fop_fd, &amount, buf, ZC_DIRECTORY_LENGTH)) return LWS_FZ_ERR_CENTRAL_READ; if (amount != ZC_DIRECTORY_LENGTH) return LWS_FZ_ERR_CENTRAL_READ; if (get_u32(buf + ZC_SIGNATURE) != 0x02014B50) return LWS_FZ_ERR_CENTRAL_SANITY; lwsl_debug("cstart 0x%lx\n", (unsigned long)priv->content_start); priv->hdr.filename_len = get_u16(buf + ZC_FILE_NAME_LENGTH); priv->hdr.extra = get_u16(buf + ZC_EXTRA_FIELD_LENGTH); priv->hdr.filename_start = lws_vfs_tell(priv->zip_fop_fd); priv->hdr.method = get_u16(buf + ZC_COMPRESSION_METHOD); priv->hdr.crc32 = get_u32(buf + ZC_CRC32); priv->hdr.comp_size = get_u32(buf + ZC_COMPRESSED_SIZE); priv->hdr.uncomp_size = get_u32(buf + ZC_UNCOMPRESSED_SIZE); priv->hdr.offset = get_u32(buf + ZC_REL_OFFSET_LOCAL_HEADER); priv->hdr.mod_time = get_u32(buf + ZC_LAST_MOD_FILE_TIME); priv->hdr.file_com_len = get_u16(buf + ZC_FILE_COMMENT_LENGTH); if (priv->hdr.filename_len != len) goto next; if (len >= (int)sizeof(buf) - 1) return LWS_FZ_ERR_NAME_TOO_LONG; if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd, &amount, buf, len)) return LWS_FZ_ERR_NAME_READ; if ((int)amount != len) return LWS_FZ_ERR_NAME_READ; buf[len] = '\0'; lwsl_debug("check %s vs %s\n", buf, name); if (strcmp((const char *)buf, name)) goto next; /* we found a match */ if (lws_vfs_file_seek_set(priv->zip_fop_fd, priv->hdr.offset) < 0) return LWS_FZ_ERR_NAME_SEEK; if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd, &amount, buf, ZL_HEADER_LENGTH)) return LWS_FZ_ERR_NAME_READ; if (amount != ZL_HEADER_LENGTH) return LWS_FZ_ERR_NAME_READ; priv->content_start = priv->hdr.offset + ZL_HEADER_LENGTH + priv->hdr.filename_len + get_u16(buf + ZL_REL_OFFSET_CONTENT); lwsl_debug("content supposed to start at 0x%lx\n", (unsigned long)priv->content_start); if (priv->content_start > priv->zip_fop_fd->len) return LWS_FZ_ERR_CONTENT_SANITY; if (lws_vfs_file_seek_set(priv->zip_fop_fd, priv->content_start) < 0) return LWS_FZ_ERR_CONTENT_SEEK; /* we are aligned at the start of the content */ priv->exp_uncomp_pos = 0; return 0; next: if (i && lws_vfs_file_seek_set(priv->zip_fop_fd, priv->content_start + ZC_DIRECTORY_LENGTH + priv->hdr.filename_len + priv->hdr.extra + priv->hdr.file_com_len) < 0) return LWS_FZ_ERR_SCAN_SEEK; } return LWS_FZ_ERR_NOT_FOUND; }