-/**
- * Initialize a saved session file.
- *
- * @param session The session to use. Must not be NULL.
- * @param filename The name of the filename to save the session as.
- * Must not be NULL.
- * @param samplerate The samplerate to store for this session.
- * @param channels A NULL-terminated array of strings containing the names
- * of all the channels active in this session.
- *
- * @retval SR_OK Success
- * @retval SR_ERR_ARG Invalid arguments
- * @retval SR_ERR Other errors
- *
- * @since 0.3.0
- */
-SR_API int sr_session_save_init(struct sr_session *session,
- const char *filename, uint64_t samplerate, char **channels)
-{
- FILE *meta;
- struct zip *zipfile;
- struct zip_source *versrc, *metasrc;
- int tmpfile, cnt, ret, i;
- char version[1], metafile[32], *s;
-
- (void)session;
-
- if (!filename) {
- sr_err("%s: filename was NULL", __func__);
- return SR_ERR_ARG;
- }
-
- /* Quietly delete it first, libzip wants replace ops otherwise. */
- unlink(filename);
- if (!(zipfile = zip_open(filename, ZIP_CREATE, &ret)))
- return SR_ERR;
-
- /* "version" */
- version[0] = '2';
- if (!(versrc = zip_source_buffer(zipfile, version, 1, 0)))
- return SR_ERR;
- if (zip_add(zipfile, "version", versrc) == -1) {
- sr_info("error saving version into zipfile: %s",
- zip_strerror(zipfile));
- return SR_ERR;
- }
-
- /* init "metadata" */
- strcpy(metafile, "sigrok-meta-XXXXXX");
- if ((tmpfile = g_mkstemp(metafile)) == -1)
- return SR_ERR;
- close(tmpfile);
- meta = g_fopen(metafile, "wb");
- fprintf(meta, "[global]\n");
- fprintf(meta, "sigrok version = %s\n", SR_PACKAGE_VERSION_STRING);
-
- /* metadata */
- fprintf(meta, "[device 1]\n");
-
- /* metadata */
- fprintf(meta, "capturefile = logic-1\n");
- cnt = 0;
- for (i = 0; channels[i]; i++)
- cnt++;
- fprintf(meta, "total probes = %d\n", cnt);
- s = sr_samplerate_string(samplerate);
- fprintf(meta, "samplerate = %s\n", s);
- g_free(s);
-
- for (i = 0; channels[i]; i++)
- fprintf(meta, "probe%d = %s\n", i + 1, channels[i]);
-
- fclose(meta);
-
- if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1))) {
- unlink(metafile);
- return SR_ERR;
- }
- if (zip_add(zipfile, "metadata", metasrc) == -1) {
- unlink(metafile);
- return SR_ERR;
- }
-
- if ((ret = zip_close(zipfile)) == -1) {
- sr_info("error saving zipfile: %s", zip_strerror(zipfile));
- unlink(metafile);
- return SR_ERR;
- }
-
- unlink(metafile);
-
- return SR_OK;
-}
-
-/**
- * Append data to an existing session file.
- *
- * The session file must have been created with sr_session_save_init()
- * or sr_session_save() beforehand.
- *
- * @param session The session to use. Must not be NULL.
- * @param filename The name of the filename to append to. Must not be NULL.
- * @param buf The data to be appended.
- * @param unitsize The number of bytes per sample.
- * @param units The number of samples.
- *
- * @retval SR_OK Success
- * @retval SR_ERR_ARG Invalid arguments
- * @retval SR_ERR Other errors
- *
- * @since 0.3.0
- */
-SR_API int sr_session_append(struct sr_session *session, const char *filename,
- unsigned char *buf, int unitsize, int units)
-{
- struct zip *archive;
- struct zip_source *logicsrc;
- zip_int64_t num_files;
- struct zip_file *zf;
- struct zip_stat zs;
- struct zip_source *metasrc;
- GKeyFile *kf;
- GError *error;
- gsize len;
- int chunk_num, next_chunk_num, tmpfile, ret, i;
- const char *entry_name;
- char *metafile, tmpname[32], chunkname[16];
-
- (void)session;
-
- if ((ret = sr_sessionfile_check(filename)) != SR_OK)
- return ret;
-
- if (!(archive = zip_open(filename, 0, &ret)))
- return SR_ERR;
-
- if (zip_stat(archive, "metadata", 0, &zs) == -1)
- return SR_ERR;
-
- metafile = g_malloc(zs.size);
- zf = zip_fopen_index(archive, zs.index, 0);
- zip_fread(zf, metafile, zs.size);
- zip_fclose(zf);
-
- /*
- * 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.
- */
- error = NULL;
- kf = g_key_file_new();
- if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, &error)) {
- sr_err("Failed to parse metadata: %s.", error->message);
- return SR_ERR;
- }
- g_free(metafile);
- tmpname[0] = '\0';
- 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 ? error->message : "?");
- return SR_ERR;
- }
- /* Add unitsize field. */
- g_key_file_set_integer(kf, "device 1", "unitsize", unitsize);
- metafile = g_key_file_to_data(kf, &len, &error);
- strcpy(tmpname, "sigrok-meta-XXXXXX");
- if ((tmpfile = g_mkstemp(tmpname)) == -1)
- return SR_ERR;
- if (write(tmpfile, metafile, len) < 0) {
- sr_dbg("Failed to create new metadata: %s", g_strerror(errno));
- g_free(metafile);
- unlink(tmpname);
- return SR_ERR;
- }
- close(tmpfile);
- if (!(metasrc = zip_source_file(archive, tmpname, 0, -1))) {
- sr_err("Failed to create zip source for metadata.");
- g_free(metafile);
- unlink(tmpname);
- return SR_ERR;
- }
- if (zip_replace(archive, zs.index, metasrc) == -1) {
- sr_err("Failed to replace metadata file.");
- g_free(metafile);
- unlink(tmpname);
- return SR_ERR;
- }
- g_free(metafile);
- }
- 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 (strncmp(entry_name, "logic-1", 7))
- continue;
- if (strlen(entry_name) == 7) {
- /* 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") == -1) {
- sr_err("Failed to rename 'logic-1' to 'logic-1-1'.");
- unlink(tmpname);
- return SR_ERR;
- }
- next_chunk_num = 2;
- break;
- } else if (strlen(entry_name) > 8 && entry_name[7] == '-') {
- chunk_num = strtoull(entry_name + 8, NULL, 10);
- if (chunk_num >= next_chunk_num)
- next_chunk_num = chunk_num + 1;
- }
- }
- snprintf(chunkname, 15, "logic-1-%d", next_chunk_num);
- if (!(logicsrc = zip_source_buffer(archive, buf, units * unitsize, FALSE))) {
- unlink(tmpname);
- return SR_ERR;
- }
- if (zip_add(archive, chunkname, logicsrc) == -1) {
- unlink(tmpname);
- return SR_ERR;
- }
- if ((ret = zip_close(archive)) == -1) {
- sr_info("error saving session file: %s", zip_strerror(archive));
- unlink(tmpname);
- return SR_ERR;
- }
- unlink(tmpname);
-
- return SR_OK;
-}
-