Coverage Report

Created: 2025-06-20 06:13

/src/c-blosc2/blosc/sframe.c
Line
Count
Source (jump to first uncovered line)
1
/*********************************************************************
2
  Blosc - Blocked Shuffling and Compression Library
3
4
  Copyright (c) 2021  Blosc Development Team <blosc@blosc.org>
5
  https://blosc.org
6
  License: BSD 3-Clause (see LICENSE.txt)
7
8
  See LICENSE.txt for details about copyright and rights to use.
9
**********************************************************************/
10
11
#include "frame.h"
12
#include "blosc2.h"
13
14
#include <stdio.h>
15
#include <stdint.h>
16
#include <stdlib.h>
17
#include <string.h>
18
19
20
/* If C11 is supported, use it's built-in aligned allocation. */
21
#if __STDC_VERSION__ >= 201112L
22
#include <stdalign.h>
23
#endif
24
25
26
/* Open sparse frame index chunk */
27
0
void* sframe_open_index(const char* urlpath, const char* mode, const blosc2_io *io) {
28
0
  void* fp = NULL;
29
0
  char* index_path = malloc(strlen(urlpath) + strlen("/chunks.b2frame") + 1);
30
0
  if (index_path) {
31
0
    sprintf(index_path, "%s/chunks.b2frame", urlpath);
32
0
    blosc2_io_cb *io_cb = blosc2_get_io_cb(io->id);
33
0
    if (io_cb == NULL) {
34
0
      BLOSC_TRACE_ERROR("Error getting the input/output API");
35
0
      return NULL;
36
0
    }
37
0
    fp = io_cb->open(index_path, mode, io->params);
38
0
    if (fp == NULL)
39
0
      BLOSC_TRACE_ERROR("Error creating index path in: %s", index_path);
40
0
    free(index_path);
41
0
  }
42
0
  return fp;
43
0
}
44
45
/* Open directory/nchunk.chunk with 8 zeros of padding */
46
0
void* sframe_open_chunk(const char* urlpath, int64_t nchunk, const char* mode, const blosc2_io *io) {
47
0
  void* fp = NULL;
48
0
  char* chunk_path = malloc(strlen(urlpath) + 1 + 8 + strlen(".chunk") + 1);
49
0
  if (chunk_path) {
50
0
    sprintf(chunk_path, "%s/%08X.chunk", urlpath, (unsigned int)nchunk);
51
0
    blosc2_io_cb *io_cb = blosc2_get_io_cb(io->id);
52
0
    if (io_cb == NULL) {
53
0
      BLOSC_TRACE_ERROR("Error getting the input/output API");
54
0
      return NULL;
55
0
    }
56
0
    fp = io_cb->open(chunk_path, mode, io->params);
57
0
    if (fp == NULL)
58
0
      BLOSC_TRACE_ERROR("Error opening chunk path in: %s", chunk_path);
59
0
    free(chunk_path);
60
0
  }
61
0
  return fp;
62
0
}
63
64
/* Append an existing chunk into a sparse frame. */
65
0
void* sframe_create_chunk(blosc2_frame_s* frame, uint8_t* chunk, int64_t nchunk, int64_t cbytes) {
66
0
  void* fpc = sframe_open_chunk(frame->urlpath, nchunk, "wb", frame->schunk->storage->io);
67
0
  if (fpc == NULL) {
68
0
    BLOSC_TRACE_ERROR("Cannot open the chunkfile.");
69
0
    return NULL;
70
0
  }
71
0
  blosc2_io_cb *io_cb = blosc2_get_io_cb(frame->schunk->storage->io->id);
72
0
  if (io_cb == NULL) {
73
0
    BLOSC_TRACE_ERROR("Error getting the input/output API");
74
0
    return NULL;
75
0
  }
76
0
  int64_t io_pos = 0;
77
0
  int64_t wbytes = io_cb->write(chunk, 1, cbytes, io_pos, fpc);
78
0
  io_cb->close(fpc);
79
0
  if (wbytes != cbytes) {
80
0
    BLOSC_TRACE_ERROR("Cannot write the full chunk.");
81
0
    return NULL;
82
0
  }
83
84
0
  return frame;
85
0
}
86
87
/* Append an existing chunk into a sparse frame. */
88
0
int sframe_delete_chunk(const char *urlpath, int64_t nchunk) {
89
0
  char* chunk_path = malloc(strlen(urlpath) + 1 + 8 + strlen(".chunk") + 1);
90
0
  if (chunk_path) {
91
0
    sprintf(chunk_path, "%s/%08X.chunk", urlpath, (unsigned int)nchunk);
92
0
    int rc = remove(chunk_path);
93
0
    free(chunk_path);
94
0
    return rc;
95
0
  }
96
0
  return BLOSC2_ERROR_FILE_REMOVE;
97
0
}
98
99
/* Get chunk from sparse frame. */
100
0
int32_t sframe_get_chunk(blosc2_frame_s* frame, int64_t nchunk, uint8_t** chunk, bool* needs_free){
101
0
  void *fpc = sframe_open_chunk(frame->urlpath, nchunk, "rb", frame->schunk->storage->io);
102
0
  if(fpc == NULL){
103
0
    BLOSC_TRACE_ERROR("Cannot open the chunkfile.");
104
0
    return BLOSC2_ERROR_FILE_OPEN;
105
0
  }
106
107
0
  blosc2_io_cb *io_cb = blosc2_get_io_cb(frame->schunk->storage->io->id);
108
0
  if (io_cb == NULL) {
109
0
    BLOSC_TRACE_ERROR("Error getting the input/output API");
110
0
    return BLOSC2_ERROR_PLUGIN_IO;
111
0
  }
112
113
0
  int64_t chunk_cbytes = io_cb->size(fpc);
114
115
0
  if (io_cb->is_allocation_necessary) {
116
0
    *chunk = malloc((size_t)chunk_cbytes);
117
0
    *needs_free = true;
118
0
  }
119
0
  else {
120
0
    *needs_free = false;
121
0
  }
122
123
0
  int64_t io_pos = 0;
124
0
  int64_t rbytes = io_cb->read((void**)chunk, 1, chunk_cbytes, io_pos, fpc);
125
0
  io_cb->close(fpc);
126
0
  if (rbytes != chunk_cbytes) {
127
0
    BLOSC_TRACE_ERROR("Cannot read the chunk out of the chunkfile.");
128
0
    return BLOSC2_ERROR_FILE_READ;
129
0
  }
130
131
0
  return (int32_t)chunk_cbytes;
132
0
}