remove libzip, and fix srzip data is empty

This commit is contained in:
dreamsourcelabTAI 2022-07-05 11:01:52 +08:00
parent e36c1372bf
commit 4077e0bf22
11 changed files with 300 additions and 479 deletions

View File

@ -1,37 +0,0 @@
# Finds libzip.
#
# This module defines:
# LIBZIP_INCLUDE_DIR_ZIP
# LIBZIP_INCLUDE_DIR_ZIPCONF
# LIBZIP_LIBRARY
#
find_package(PkgConfig)
pkg_check_modules(PC_LIBZIP QUIET libzip)
find_path(LIBZIP_INCLUDE_DIR_ZIP
NAMES zip.h
HINTS ${PC_LIBZIP_INCLUDE_DIRS})
find_path(LIBZIP_INCLUDE_DIR_ZIPCONF
NAMES zipconf.h
HINTS ${PC_LIBZIP_INCLUDE_DIRS})
find_library(LIBZIP_LIBRARY
NAMES zip)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(
LIBZIP DEFAULT_MSG
LIBZIP_LIBRARY LIBZIP_INCLUDE_DIR_ZIP LIBZIP_INCLUDE_DIR_ZIPCONF)
set(LIBZIP_VERSION 0)
if (LIBZIP_INCLUDE_DIR_ZIPCONF)
FILE(READ "${LIBZIP_INCLUDE_DIR_ZIPCONF}/zipconf.h" _LIBZIP_VERSION_CONTENTS)
if (_LIBZIP_VERSION_CONTENTS)
STRING(REGEX REPLACE ".*#define LIBZIP_VERSION \"([0-9.]+)\".*" "\\1" LIBZIP_VERSION "${_LIBZIP_VERSION_CONTENTS}")
endif ()
endif ()
set(LIBZIP_VERSION ${LIBZIP_VERSION} CACHE STRING "Version number of libzip")

View File

@ -33,7 +33,7 @@ set(DS_DESCRIPTION "A GUI for instruments of DreamSourceLab")
set(DS_VERSION_MAJOR 1) set(DS_VERSION_MAJOR 1)
set(DS_VERSION_MINOR 2) set(DS_VERSION_MINOR 2)
set(DS_VERSION_MICRO 0) set(DS_VERSION_MICRO 0)
set(DS_VERSION_STRING ${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}-RC10 ) set(DS_VERSION_STRING ${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}-RC15 )
configure_file ( configure_file (
${PROJECT_SOURCE_DIR}/DSView/config.h.in ${PROJECT_SOURCE_DIR}/DSView/config.h.in
@ -150,21 +150,6 @@ message(STATUS " includes:" ${ZLIB_INCLUDE_DIRS})
message(STATUS " libraries:" ${ZLIB_LIBRARIES}) message(STATUS " libraries:" ${ZLIB_LIBRARIES})
include_directories(${ZLIB_INCLUDE_DIRS}) include_directories(${ZLIB_INCLUDE_DIRS})
#===============================================================================
#= libzip
#-------------------------------------------------------------------------------
pkg_search_module(LIBZIP libzip)
if(NOT LIBZIP_FOUND)
message(FATAL_ERROR "Please install libzip!")
endif()
message("----- libzip:")
message(STATUS " includes:" ${LIBZIP_INCLUDE_DIRS})
message(STATUS " libraries:" ${LIBZIP_LIBDIR}/lib${LIBZIP_LIBRARIES}.*)
include_directories(${LIBZIP_INCLUDE_DIRS})
link_directories(${LIBZIP_LIBDIR})
#=============================================================================== #===============================================================================
#= Qt5 or Qt6 #= Qt5 or Qt6
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@ -568,6 +553,7 @@ include_directories(
./DSView ./DSView
./libsigrok4DSL ./libsigrok4DSL
./libsigrokdecode4DSL ./libsigrokdecode4DSL
./common
) )
include_directories( include_directories(
@ -606,7 +592,6 @@ set(DSVIEW_LINK_LIBS
${LIBUSB_1_LIBRARIES} ${LIBUSB_1_LIBRARIES}
${FFTW_LIBRARIES} ${FFTW_LIBRARIES}
${Python3_LIBRARIES} ${Python3_LIBRARIES}
${LIBZIP_LIBRARIES}
) )
if(STATIC_PKGDEPS_LIBS) if(STATIC_PKGDEPS_LIBS)

View File

@ -30,6 +30,6 @@
#define DS_VERSION_MAJOR 1 #define DS_VERSION_MAJOR 1
#define DS_VERSION_MINOR 2 #define DS_VERSION_MINOR 2
#define DS_VERSION_MICRO 0 #define DS_VERSION_MICRO 0
#define DS_VERSION_STRING "1.2.0-RC10" #define DS_VERSION_STRING "1.2.0-RC15"
#endif #endif

View File

@ -25,6 +25,7 @@
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
#include <QDebug>
ZipMaker::ZipMaker() : ZipMaker::ZipMaker() :
m_zDoc(NULL) m_zDoc(NULL)
@ -161,3 +162,83 @@ const char *ZipMaker::GetError()
return m_error; return m_error;
return NULL; return NULL;
} }
//-----------------ZipReader
ZipInnerFileData::ZipInnerFileData(char *data, int size)
{
_data = data;
_size = size;
}
ZipInnerFileData::~ZipInnerFileData()
{
if (_data != NULL){
free(_data);
_data = NULL;
}
}
ZipReader::ZipReader(const char *filePath)
{
m_archive = NULL;
m_archive = unzOpen64(filePath);
}
ZipReader::~ZipReader()
{
Close();
}
void ZipReader::Close()
{
if (m_archive != NULL){
unzClose(m_archive);
m_archive = NULL;
}
}
ZipInnerFileData* ZipReader::GetInnterFileData(const char *innerFile)
{
char *metafile = NULL;
char szFilePath[15];
unz_file_info64 fileInfo;
if (m_archive == NULL){
return NULL;
}
// inner file not exists
if (unzLocateFile(m_archive, innerFile, 0) != UNZ_OK){
return NULL;
}
if (unzGetCurrentFileInfo64(m_archive, &fileInfo, szFilePath,
sizeof(szFilePath), NULL, 0, NULL, 0) != UNZ_OK)
{
return NULL;
}
if (unzOpenCurrentFile(m_archive) != UNZ_OK)
{
return NULL;
}
if (fileInfo.uncompressed_size > 0 && (metafile = (char *)malloc(fileInfo.uncompressed_size)))
{
unzReadCurrentFile(m_archive, metafile, fileInfo.uncompressed_size);
unzCloseCurrentFile(m_archive);
ZipInnerFileData *data = new ZipInnerFileData(metafile, fileInfo.uncompressed_size);
return data;
}
return NULL;
}
void ZipReader::ReleaseInnerFileData(ZipInnerFileData *data)
{
if (data){
delete data;
}
}

View File

@ -23,15 +23,8 @@
#pragma once #pragma once
#include "../../common/minizip/zip.h" #include <minizip/zip.h>
#include <minizip/unzip.h>
typedef struct
{
char inFileName[256];
int inFileNameLen;
void *pData;
long long dataLen;
} UnZipFileInfo;
class ZipMaker class ZipMaker
@ -68,3 +61,42 @@ private:
char m_error[500]; char m_error[500];
}; };
//------------------ZipReader
class ZipInnerFileData
{
public:
ZipInnerFileData(char *data, int size);
~ZipInnerFileData();
inline char *data(){
return _data;
}
inline int size(){
return _size;
}
private:
char *_data;
int _size;
};
class ZipReader{
public:
ZipReader(const char *filePath);
~ZipReader();
void Close();
inline bool HaveArchive(){
return m_archive != NULL;
}
ZipInnerFileData* GetInnterFileData(const char *innerFile);
void ReleaseInnerFileData(ZipInnerFileData *data);
private:
unzFile m_archive;
};

View File

@ -24,9 +24,10 @@
#include "sessionfile.h" #include "sessionfile.h"
#include <QFileInfo> #include <QFileInfo>
#include <zip.h>
#include <assert.h> #include <assert.h>
#include "../utility/path.h" #include "../utility/path.h"
#include <stdlib.h>
#include "../ZipMaker.h"
namespace pv { namespace pv {
namespace device { namespace device {
@ -71,33 +72,19 @@ File* File::create(QString name)
QJsonArray File::get_decoders() QJsonArray File::get_decoders()
{ {
struct zip *archive;
struct zip_file *zf;
struct zip_stat zs;
int ret;
char *dec_file;
QJsonArray dec_array; QJsonArray dec_array;
QJsonParseError error; QJsonParseError error;
/* read "decoders" */
auto f_name = path::ConvertPath(_path); auto f_name = path::ConvertPath(_path);
ZipReader rd(f_name.c_str());
auto *data = rd.GetInnterFileData("decoders");
archive = zip_open(f_name.c_str(), 0, &ret); if (data != NULL){
if (archive) { QJsonDocument sessionDoc = QJsonDocument::fromJson(
/* read "decoders" */ QByteArray::fromRawData(data->data(), data->size()), &error);
if (zip_stat(archive, "decoders", 0, &zs) != -1) { dec_array = sessionDoc.array();
dec_file = (char *)g_try_malloc(zs.size); rd.ReleaseInnerFileData(data);
if (dec_file) {
zf = zip_fopen_index(archive, zs.index, 0);
zip_fread(zf, dec_file, zs.size);
zip_fclose(zf);
//QString sessionData = QString::fromUtf8(dec_file);
QJsonDocument sessionDoc = QJsonDocument::fromJson(QByteArray::fromRawData(dec_file, zs.size), &error);
dec_array = sessionDoc.array();
}
}
zip_close(archive);
} }
return dec_array; return dec_array;
@ -105,32 +92,17 @@ QJsonArray File::get_decoders()
QJsonDocument File::get_session() QJsonDocument File::get_session()
{ {
struct zip *archive;
struct zip_file *zf;
struct zip_stat zs;
int ret;
char *dec_file;
QJsonDocument sessionDoc; QJsonDocument sessionDoc;
QJsonParseError error; QJsonParseError error;
auto f_name = path::ConvertPath(_path); auto f_name = path::ConvertPath(_path);
ZipReader rd(f_name.c_str());
auto *data = rd.GetInnterFileData("session");
archive = zip_open(f_name.c_str(), 0, &ret); if (data != NULL){
if (archive) { sessionDoc = QJsonDocument::fromJson(
/* read "decoders" */ QByteArray::fromRawData(data->data(), data->size()), &error);
if (zip_stat(archive, "session", 0, &zs) != -1) { rd.ReleaseInnerFileData(data);
dec_file = (char *)g_try_malloc(zs.size);
if (dec_file) {
zf = zip_fopen_index(archive, zs.index, 0);
zip_fread(zf, dec_file, zs.size);
zip_fclose(zf);
//QString sessionData = QString::fromUtf8(dec_file);
sessionDoc = QJsonDocument::fromJson(QByteArray::fromRawData(dec_file, zs.size), &error);
}
}
zip_close(archive);
} }
return sessionDoc; return sessionDoc;

View File

@ -11,7 +11,6 @@ Requirements
- cmake >= 2.6 - cmake >= 2.6
- Qt >= 5.0 - Qt >= 5.0
- libglib >= 2.32.0 - libglib >= 2.32.0
- libzip >= 0.10
- zlib - zlib
- libusb-1.0 >= 1.0.16 - libusb-1.0 >= 1.0.16
On FreeBSD, this is an integral part of the FreeBSD libc, not an extra package/library. On FreeBSD, this is an integral part of the FreeBSD libc, not an extra package/library.
@ -30,7 +29,7 @@ Step1: Installing the requirements:
please check your respective distro's package manager tool if you use other distros please check your respective distro's package manager tool if you use other distros
Debian/Ubuntu: Debian/Ubuntu:
$ sudo apt install git gcc g++ make cmake qt5-default libglib2.0-dev libzip-dev zlib1g-dev \ $ sudo apt install git gcc g++ make cmake qt5-default libglib2.0-dev zlib1g-dev \
libusb-1.0-0-dev libboost-dev libfftw3-dev python3-dev libudev-dev pkg-config libusb-1.0-0-dev libboost-dev libfftw3-dev python3-dev libudev-dev pkg-config
How to install qt on ubuntu? How to install qt on ubuntu?
@ -39,11 +38,11 @@ Debian/Ubuntu:
Fedora (18, 19): Fedora (18, 19):
$ sudo yum install git gcc g++ make cmake libtool pkgconfig glib2-devel \ $ sudo yum install git gcc g++ make cmake libtool pkgconfig glib2-devel \
libzip-devel libudev-devel libusb1-devel \ zlib-devel libudev-devel libusb1-devel \
python3-devel qt-devel boost-devel libfftw3-devel python3-devel qt-devel boost-devel libfftw3-devel
Arch: Arch:
$ pacman -S base-devel git cmake glib2 libzip libusb $ pacman -S base-devel git cmake glib2 zlib libusb
python boost qt5 fftw python boost qt5 fftw
Mac: Mac:
@ -56,7 +55,6 @@ Mac:
brew install gettext brew install gettext
brew install glib brew install glib
brew install libusb brew install libusb
brew install libzip
brew install zlib brew install zlib
brew install boost brew install boost
brew install fftw brew install fftw

View File

@ -27,7 +27,6 @@
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#include <glib.h> #include <glib.h>
#include <zip.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

495
libsigrok4DSL/output/srzip.c Normal file → Executable file
View File

@ -17,28 +17,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../libsigrok.h" #include "libsigrok.h"
#include "../libsigrok-internal.h" #include "libsigrok-internal.h"
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <glib.h> #include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <zip.h> #include <minizip/zip.h>
#include <time.h>
#include <assert.h>
#define LOG_PREFIX "output/srzip" #define LOG_PREFIX "output/srzip"
#define CHUNK_SIZE (4 * 1024 * 1024)
struct out_context { struct out_context {
gboolean zip_created; uint64_t samplerate;
uint64_t samplerate; char *filename;
char *filename; zipFile zipArchive;
struct logic_buff { int bCreated;
size_t unit_size; zip_fileinfo zi;
size_t alloc_size; GKeyFile *meta;
uint8_t *samples; int chunk_index;
size_t fill_size;
} logic_buff;
}; };
static int init(struct sr_output *o, GHashTable *options) static int init(struct sr_output *o, GHashTable *options)
@ -47,53 +47,123 @@ static int init(struct sr_output *o, GHashTable *options)
outc = g_malloc0(sizeof(struct out_context)); outc = g_malloc0(sizeof(struct out_context));
o->priv = outc; o->priv = outc;
outc->zipArchive = NULL;
outc->bCreated = 0;
outc->meta = NULL;
outc->chunk_index = 0;
outc->filename = g_strdup(g_variant_get_bytestring(g_hash_table_lookup(options, "filename"))); outc->filename = g_strdup(g_variant_get_bytestring(g_hash_table_lookup(options, "filename")));
if (strlen(outc->filename) == 0) if (strlen(outc->filename) == 0)
return SR_ERR_ARG; return SR_ERR_ARG;
return SR_OK; return SR_OK;
} }
static int zip_create(const struct sr_output *o) /*
add zip inner file
*/
static int add_file_from_buffer(zipFile zipArchive, zip_fileinfo *zi, const char *innerFile, const char *buffer, unsigned int buferSize)
{
assert(buffer);
assert(innerFile);
assert(zipArchive);
assert(zi);
int level = Z_BEST_SPEED;
if (level < Z_DEFAULT_COMPRESSION || level > Z_BEST_COMPRESSION){
level = Z_DEFAULT_COMPRESSION;
}
zipOpenNewFileInZip(zipArchive,innerFile,zi,
NULL,0,NULL,0,NULL ,
Z_DEFLATED,
level);
zipWriteInFileInZip(zipArchive, buffer, (unsigned int)buferSize);
zipCloseFileInZip(zipArchive);
return 0;
}
/*
add meta file to archive
*/
static void save_meta_file(const struct sr_output *o)
{ {
struct out_context *outc; struct out_context *outc;
struct zip *zipfile; char *metabuf;
struct zip_source *versrc, *metasrc;
struct sr_channel *ch;
size_t ch_nr;
size_t alloc_size;
GVariant *gvar;
GKeyFile *meta;
GSList *l;
const char *devgroup;
char *s, *metabuf;
gsize metalen; gsize metalen;
guint logic_channels, enabled_logic_channels;
outc = o->priv; outc = o->priv;
if (outc->samplerate == 0 && sr_config_get(o->sdi->driver, o->sdi, NULL, NULL, if (outc->meta != NULL && outc->zipArchive != NULL){
SR_CONF_SAMPLERATE, &gvar) == SR_OK) { metabuf = g_key_file_to_data(outc->meta, &metalen, NULL);
outc->samplerate = g_variant_get_uint64(gvar); add_file_from_buffer(outc->zipArchive, &outc->zi, "metadata", metabuf, metalen);
g_variant_unref(gvar); g_free(metabuf);
g_key_file_free(outc->meta);
outc->meta = NULL;
}
}
/*
create zip archive
*/
static int create_archive(const struct sr_output *o)
{
struct out_context *outc;
struct sr_channel *ch;
GKeyFile *meta;
GVariant *gvar;
GSList *l;
int tmpfile, ret;
const char *devgroup;
size_t ch_nr;
char version[1], metafile[32];
char *s = NULL;
int logic_channels = 0;
int enabled_logic_channels = 0;
outc = o->priv;
outc->zipArchive = NULL;
//zi
time_t rawtime;
time (&rawtime);
struct tm *ti = localtime(&rawtime);
zip_fileinfo *zi = &outc->zi;
zi->tmz_date.tm_year = ti->tm_year;
zi->tmz_date.tm_mon = ti->tm_mon;
zi->tmz_date.tm_mday = ti->tm_mday;
zi->tmz_date.tm_hour = ti->tm_hour;
zi->tmz_date.tm_min = ti->tm_min;
zi->tmz_date.tm_sec = ti->tm_sec;
zi->dosDate = 0;
if (outc->samplerate == 0) {
if (sr_config_get(o->sdi->driver, o->sdi, NULL, NULL, SR_CONF_SAMPLERATE,
&gvar) == SR_OK) {
if (gvar != NULL) {
outc->samplerate = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
}
}
} }
/* Quietly delete it first, libzip wants replace ops otherwise. */ /* Quietly delete it first, libzip wants replace ops otherwise. */
g_unlink(outc->filename); unlink(outc->filename);
zipfile = zip_open(outc->filename, ZIP_CREATE, NULL);
if (!zipfile)
return SR_ERR;
/* "version" */ outc->zipArchive = zipOpen64(outc->filename, FALSE);
versrc = zip_source_buffer(zipfile, "2", 1, FALSE); if (outc->zipArchive == NULL){
if (zip_add(zipfile, "version", versrc) < 0) { sr_err("create srzip archive error.");
sr_err("Error saving version into zipfile: %s",
zip_strerror(zipfile));
zip_source_free(versrc);
zip_discard(zipfile);
return SR_ERR; return SR_ERR;
} }
/* "version" */
version[0] = '2';
add_file_from_buffer(outc->zipArchive, zi, "version", version, 1);
/* init "metadata" */ /* init "metadata" */
meta = g_key_file_new(); meta = g_key_file_new();
@ -101,18 +171,16 @@ static int zip_create(const struct sr_output *o)
sr_package_version_string_get()); sr_package_version_string_get());
devgroup = "device 1"; devgroup = "device 1";
logic_channels = 0; logic_channels = 0;
enabled_logic_channels = 0; enabled_logic_channels = 0;
for (l = o->sdi->channels; l; l = l->next) { for (l = o->sdi->channels; l; l = l->next) {
ch = l->data; ch = l->data;
switch (ch->type) { if (ch->type == SR_CHANNEL_LOGIC){
case SR_CHANNEL_LOGIC:
if (ch->enabled) if (ch->enabled)
enabled_logic_channels++; enabled_logic_channels++;
logic_channels++; logic_channels++;
break;
} }
} }
@ -128,323 +196,50 @@ static int zip_create(const struct sr_output *o)
for (l = o->sdi->channels; l; l = l->next) { for (l = o->sdi->channels; l; l = l->next) {
ch = l->data; ch = l->data;
if (!ch->enabled)
if (!ch->enabled || ch->type != SR_CHANNEL_LOGIC){
continue; continue;
}
s = NULL; s = NULL;
switch (ch->type) { ch_nr = ch->index + 1;
case SR_CHANNEL_LOGIC: s = g_strdup_printf("probe%zu", ch_nr);
ch_nr = ch->index + 1;
s = g_strdup_printf("probe%zu", ch_nr);
break;
}
if (s) { if (s) {
g_key_file_set_string(meta, devgroup, s, ch->name); g_key_file_set_string(meta, devgroup, s, ch->name);
g_free(s); g_free(s);
} }
} }
outc->meta = meta;
/*
* Allocate one samples buffer for all logic channels. Allocate
* buffers of CHUNK_SIZE size (in bytes), and determine the
* sample counts from the respective channel counts and data
* type widths.
*
* These buffers are intended to reduce the number of ZIP
* archive update calls, and decouple the srzip output module
* from implementation details in other acquisition device
* drivers and input modules.
*
* Avoid allocating zero bytes, to not depend on platform
* specific malloc(0) return behaviour. Avoid division by zero,
* holding a local buffer won't harm when no data is seen later
* during execution. This simplifies other locations.
*/
alloc_size = CHUNK_SIZE;
outc->logic_buff.unit_size = logic_channels;
outc->logic_buff.unit_size += 8 - 1;
outc->logic_buff.unit_size /= 8;
outc->logic_buff.samples = g_try_malloc0(alloc_size);
if (!outc->logic_buff.samples)
return SR_ERR_MALLOC;
if (outc->logic_buff.unit_size)
alloc_size /= outc->logic_buff.unit_size;
outc->logic_buff.alloc_size = alloc_size;
outc->logic_buff.fill_size = 0;
metabuf = g_key_file_to_data(meta, &metalen, NULL);
g_key_file_free(meta);
metasrc = zip_source_buffer(zipfile, metabuf, metalen, FALSE);
if (zip_add(zipfile, "metadata", metasrc) < 0) {
sr_err("Error saving metadata into zipfile: %s",
zip_strerror(zipfile));
zip_source_free(metasrc);
zip_discard(zipfile);
g_free(metabuf);
return SR_ERR;
}
if (zip_close(zipfile) < 0) {
sr_err("Error saving zipfile: %s", zip_strerror(zipfile));
zip_discard(zipfile);
g_free(metabuf);
return SR_ERR;
}
g_free(metabuf);
return SR_OK; return SR_OK;
} }
/** /*
* Read metadata entries from a session archive. append data to archive
* */
* @param[in] archive An open ZIP archive. static int append_archive_data(const struct sr_output *o, unsigned char *buf,
* @param[in] entry Stat buffer filled in for the metadata archive member. int unitsize, int length)
*
* @return A new key/value store containing the session metadata.
*
* @private
*/
SR_PRIV GKeyFile *sr_sessionfile_read_metadata(struct zip *archive,
const struct zip_stat *entry)
{
GKeyFile *keyfile;
GError *error;
struct zip_file *zf;
char *metabuf;
int metalen;
if (entry->size > G_MAXINT || !(metabuf = g_try_malloc(entry->size))) {
sr_err("Metadata buffer allocation failed.");
return NULL;
}
zf = zip_fopen_index(archive, entry->index, 0);
if (!zf) {
sr_err("Failed to open metadata: %s", zip_strerror(archive));
g_free(metabuf);
return NULL;
}
metalen = zip_fread(zf, metabuf, entry->size);
if (metalen < 0) {
sr_err("Failed to read metadata: %s", zip_file_strerror(zf));
zip_fclose(zf);
g_free(metabuf);
return NULL;
}
zip_fclose(zf);
keyfile = g_key_file_new();
error = NULL;
g_key_file_load_from_data(keyfile, metabuf, metalen,
G_KEY_FILE_NONE, &error);
g_free(metabuf);
if (error) {
sr_err("Failed to parse metadata: %s", error->message);
g_error_free(error);
g_key_file_free(keyfile);
return NULL;
}
return keyfile;
}
/**
* Append a block of logic data to an srzip archive.
*
* @param[in] o Output module instance.
* @param[in] buf Logic data samples as byte sequence.
* @param[in] unitsize Logic data unit size (bytes per sample).
* @param[in] length Byte sequence length (in bytes, not samples).
*
* @returns SR_OK et al error codes.
*/
static int zip_append(const struct sr_output *o,
uint8_t *buf, size_t unitsize, size_t length)
{ {
struct out_context *outc; struct out_context *outc;
struct zip *archive; char chunkname[20];
struct zip_source *logicsrc;
int64_t i, num_files;
struct zip_stat zs;
struct zip_source *metasrc;
GKeyFile *kf;
GError *error;
uint64_t chunk_num;
const char *entry_name;
char *metabuf;
gsize metalen;
char *chunkname;
unsigned int next_chunk_num;
if (!length)
return SR_OK;
outc = o->priv; outc = o->priv;
if (!(archive = zip_open(outc->filename, 0, NULL)))
return SR_ERR;
if (zip_stat(archive, "metadata", 0, &zs) < 0) {
sr_err("Failed to open metadata: %s", zip_strerror(archive));
zip_discard(archive);
return SR_ERR;
}
kf = sr_sessionfile_read_metadata(archive, &zs);
if (!kf) {
zip_discard(archive);
return SR_ERR;
}
/* /*
* If the file was only initialized but doesn't yet have any * If the file was only initialized but doesn't yet have any
* data it in, it won't have a unitsize field in metadata yet. * data it in, it won't have a unitsize field in metadata yet.
*/ */
error = NULL; if (outc->meta != NULL) {
metabuf = NULL;
if (!g_key_file_has_key(kf, "device 1", "unitsize", &error)) {
if (error && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
sr_err("Failed to check unitsize key: %s", error->message);
g_error_free(error);
g_key_file_free(kf);
zip_discard(archive);
return SR_ERR;
}
g_clear_error(&error);
/* Add unitsize field. */ /* Add unitsize field. */
g_key_file_set_integer(kf, "device 1", "unitsize", unitsize); g_key_file_set_integer(outc->meta, "device 1", "unitsize", unitsize);
metabuf = g_key_file_to_data(kf, &metalen, NULL); save_meta_file(o);
metasrc = zip_source_buffer(archive, metabuf, metalen, FALSE); outc->meta = NULL;
if (zip_replace(archive, zs.index, metasrc) < 0) {
sr_err("Failed to replace metadata: %s",
zip_strerror(archive));
g_key_file_free(kf);
zip_source_free(metasrc);
zip_discard(archive);
g_free(metabuf);
return SR_ERR;
}
}
g_key_file_free(kf);
next_chunk_num = 1;
num_files = zip_get_num_entries(archive, 0);
for (i = 0; i < num_files; i++) {
entry_name = zip_get_name(archive, i, 0);
if (!entry_name || strncmp(entry_name, "logic-1", 7) != 0)
continue;
if (entry_name[7] == '\0') {
/*
* This file has no extra chunks, just a single
* "logic-1". Rename it to "logic-1-1" and continue
* with chunk 2.
*/
if (zip_rename(archive, i, "logic-1-1") < 0) {
sr_err("Failed to rename 'logic-1' to 'logic-1-1': %s",
zip_strerror(archive));
zip_discard(archive);
g_free(metabuf);
return SR_ERR;
}
next_chunk_num = 2;
break;
} else if (entry_name[7] == '-') {
chunk_num = g_ascii_strtoull(entry_name + 8, NULL, 10);
if (chunk_num < G_MAXINT && chunk_num >= next_chunk_num)
next_chunk_num = chunk_num + 1;
}
} }
if (length % unitsize != 0) { outc->chunk_index++;
sr_warn("Chunk size %zu not a multiple of the" snprintf(chunkname, 15, "logic-1-%d", outc->chunk_index);
" unit size %zu.", length, unitsize); add_file_from_buffer(outc->zipArchive, &outc->zi, chunkname, buf, length);
}
logicsrc = zip_source_buffer(archive, buf, length, FALSE);
chunkname = g_strdup_printf("logic-1-%u", next_chunk_num);
i = zip_add(archive, chunkname, logicsrc);
g_free(chunkname);
if (i < 0) {
sr_err("Failed to add chunk 'logic-1-%u': %s",
next_chunk_num, zip_strerror(archive));
zip_source_free(logicsrc);
zip_discard(archive);
g_free(metabuf);
return SR_ERR;
}
if (zip_close(archive) < 0) {
sr_err("Error saving session file: %s", zip_strerror(archive));
zip_discard(archive);
g_free(metabuf);
return SR_ERR;
}
g_free(metabuf);
return SR_OK;
}
/**
* Queue a block of logic data for srzip archive writes.
*
* @param[in] o Output module instance.
* @param[in] buf Logic data samples as byte sequence.
* @param[in] unitsize Logic data unit size (bytes per sample).
* @param[in] length Number of bytes of sample data.
* @param[in] flush Force ZIP archive update (queue by default).
*
* @returns SR_OK et al error codes.
*/
static int zip_append_queue(const struct sr_output *o,
uint8_t *buf, size_t unitsize, size_t length, gboolean flush)
{
struct out_context *outc;
struct logic_buff *buff;
size_t send_size, remain, copy_size;
uint8_t *wrptr, *rdptr;
int ret;
outc = o->priv;
buff = &outc->logic_buff;
if (length && unitsize != buff->unit_size) {
sr_warn("Unexpected unit size, discarding logic data.");
return SR_ERR_ARG;
}
/*
* Queue most recently received samples to the local buffer.
* Flush to the ZIP archive when the buffer space is exhausted.
*/
rdptr = buf;
send_size = buff->unit_size ? length / buff->unit_size : 0;
while (send_size) {
remain = buff->alloc_size - buff->fill_size;
if (remain) {
wrptr = &buff->samples[buff->fill_size * buff->unit_size];
copy_size = MIN(send_size, remain);
send_size -= copy_size;
buff->fill_size += copy_size;
memcpy(wrptr, rdptr, copy_size * buff->unit_size);
rdptr += copy_size * buff->unit_size;
remain -= copy_size;
}
if (send_size && !remain) {
ret = zip_append(o, buff->samples, buff->unit_size,
buff->fill_size * buff->unit_size);
if (ret != SR_OK)
return ret;
buff->fill_size = 0;
remain = buff->alloc_size - buff->fill_size;
}
}
/* Flush to the ZIP archive if the caller wants us to. */
if (flush && buff->fill_size) {
ret = zip_append(o, buff->samples, buff->unit_size,
buff->fill_size * buff->unit_size);
if (ret != SR_OK)
return ret;
buff->fill_size = 0;
}
return SR_OK; return SR_OK;
} }
@ -457,6 +252,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
const struct sr_datafeed_logic *logic; const struct sr_datafeed_logic *logic;
const struct sr_config *src; const struct sr_config *src;
GSList *l; GSList *l;
int ret; int ret;
*out = NULL; *out = NULL;
@ -474,23 +270,13 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
} }
break; break;
case SR_DF_LOGIC: case SR_DF_LOGIC:
if (!outc->zip_created) { if (!outc->bCreated) {
if ((ret = zip_create(o)) != SR_OK) if ((ret = create_archive(o)) != SR_OK)
return ret; return ret;
outc->zip_created = TRUE; outc->bCreated = TRUE;
} }
logic = packet->payload; logic = packet->payload;
ret = zip_append_queue(o, logic->data, ret = append_archive_data(o, logic->data, logic->unitsize, logic->length);
logic->unitsize, logic->length, FALSE);
if (ret != SR_OK)
return ret;
break;
case SR_DF_END:
if (outc->zip_created) {
ret = zip_append_queue(o, NULL, 0, 0, TRUE);
if (ret != SR_OK)
return ret;
}
break; break;
} }
@ -502,8 +288,13 @@ static int cleanup(struct sr_output *o)
struct out_context *outc; struct out_context *outc;
outc = o->priv; outc = o->priv;
if (outc->zipArchive != NULL){
save_meta_file(o);
zipClose(outc->zipArchive, NULL);
}
g_free(outc->filename); g_free(outc->filename);
g_free(outc->logic_buff.samples);
g_free(outc); g_free(outc);
o->priv = NULL; o->priv = NULL;

View File

@ -26,7 +26,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "../common/minizip/unzip.h" #include <minizip/unzip.h>
/* Message logging helpers with subsystem-specific prefix string. */ /* Message logging helpers with subsystem-specific prefix string. */
#define LOG_PREFIX "virtual-session: " #define LOG_PREFIX "virtual-session: "

View File

@ -27,7 +27,7 @@
#include <errno.h> #include <errno.h>
#include <glib.h> #include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include "../common/minizip/unzip.h" #include <minizip/unzip.h>
#include "config.h" /* Needed for PACKAGE_VERSION and others. */ #include "config.h" /* Needed for PACKAGE_VERSION and others. */
/* Message logging helpers with subsystem-specific prefix string. */ /* Message logging helpers with subsystem-specific prefix string. */