h5_attachments.c 7.71 KB
Newer Older
1
/*
gsell's avatar
gsell committed
2
  Copyright (c) 2006-2016, The Regents of the University of California,
3 4 5 6 7 8 9
  through Lawrence Berkeley National Laboratory (subject to receipt of any
  required approvals from the U.S. Dept. of Energy) and the Paul Scherrer
  Institut (Switzerland).  All rights reserved.

  License: see file COPYING in top level of source distribution.
*/

gsell's avatar
gsell committed
10
#include "private/h5_types.h"
11

12
#include "private/h5_err.h"
gsell's avatar
gsell committed
13 14
#include "private/h5_hdf5.h"
#include "private/h5_model.h"
15
#include "h5core/h5_syscall.h"
gsell's avatar
gsell committed
16
#include "private/h5_va_macros.h"
17

18 19
#include "h5core/h5_file.h"

20 21 22 23 24 25 26 27 28 29 30 31 32 33
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

h5_err_t
h5_add_attachment (
	const h5_file_t f_,
	const char* const fname
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p, fname='%s'", f, fname);
	// allowed file modes: O_RDWR, O_WRONLY; O_APPEND
34
	if (f->props->flags & H5_O_RDONLY) {
gsell's avatar
gsell committed
35
		H5_LEAVE (
36
			h5priv_handle_file_mode_error (f->props->flags));
37 38 39 40
	}

	struct stat st;
        if (stat (fname, &st) < 0) {
41 42 43 44
		H5_RETURN_ERROR (
			H5_ERR_HDF5,
			"Cannot stat file '%s'",
			fname);
45 46 47 48 49 50 51 52 53
	}
	hsize_t fsize = st.st_size;
	hsize_t write_length;
	char* buf = NULL;
	if (f->myproc == 0) {
		TRY (buf = h5_calloc (1, fsize));
		write_length = fsize;
		int fd;
		if ((fd = open (fname, O_RDONLY)) < 0) {
54 55 56 57
			H5_RETURN_ERROR (
				H5_ERR_HDF5,
				"Cannot open file '%s' for reading",
				fname);
58 59 60 61 62 63
		}
	again:
		if (read (fd, buf, fsize) < 0) {
			if (errno == EINTR) {
				goto again;
			} else {
64 65 66 67
				H5_RETURN_ERROR (
					H5_ERR_HDF5,
					"Cannot read file '%s'",
					fname);
68 69 70
			}
		}
		if (close (fd) < 0) {
71 72 73 74
			H5_RETURN_ERROR (
				H5_ERR_HDF5,
				"Cannot close file '%s'",
				fname);
75 76 77 78 79 80 81 82 83 84 85
		}

	} else {
		TRY (buf = h5_calloc (1, 1));
		write_length = 0;
	}

	hid_t loc_id;
	TRY (loc_id = h5priv_open_group (1, f->file, H5_ATTACHMENT));
	h5_err_t exists;
	TRY (exists = hdf5_link_exists (loc_id, fname));
86
        if (exists && (f->props->flags & H5_O_APPENDONLY)) {
gsell's avatar
gsell committed
87
		H5_LEAVE (
88
			h5priv_handle_file_mode_error (f->props->flags));
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	}
	hid_t diskspace_id;
	TRY (diskspace_id = hdf5_create_dataspace (1, &fsize, &fsize));
	hid_t dataset_id;
	TRY (dataset_id = hdf5_create_dataset (loc_id,
					       fname,
					       H5T_NATIVE_CHAR,
					       diskspace_id,
					       H5P_DEFAULT));
	hsize_t start = 0;
	TRY (hdf5_select_hyperslab_of_dataspace (
		     diskspace_id,
		     H5S_SELECT_SET,
		     &start,
		     NULL,
		     &write_length,
		     NULL));

	hid_t memspace_id;
	hsize_t max = H5S_UNLIMITED;
	TRY (memspace_id = hdf5_create_dataspace (1, &write_length, &max));
	TRY (hdf5_write_dataset (dataset_id,
				 H5T_NATIVE_CHAR,
				 memspace_id,
				 diskspace_id,
				 f->props->xfer_prop,
				 buf));

	TRY (hdf5_close_dataspace (diskspace_id));
	TRY (hdf5_close_dataspace (memspace_id));
	TRY (hdf5_close_dataset (dataset_id));
	TRY (hdf5_close_group (loc_id));

	TRY (h5_free (buf));

gsell's avatar
gsell committed
124
	H5_RETURN (H5_SUCCESS);
125 126
}

127 128 129
h5_err_t
h5_has_attachments (
	const h5_file_t f_
130
	) {
131 132
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_ssize_t, "f=%p", f);
133
	TRY  (ret_value = hdf5_link_exists (f->file, H5_ATTACHMENT));
gsell's avatar
gsell committed
134
	H5_RETURN (ret_value);
135 136 137 138 139 140 141 142
}

h5_ssize_t
h5_get_num_attachments (
	const h5_file_t f_
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_ssize_t, "f=%p", f);
143 144 145 146
	h5_err_t exists;
	TRY  (exists = hdf5_link_exists (f->file, H5_ATTACHMENT));
	if (exists == 0) {
		return 0;
147
	}
148 149
	hid_t group_id;
	TRY (group_id = hdf5_open_group (f->file, H5_ATTACHMENT));
150
	TRY (ret_value = hdf5_get_num_datasets (group_id));
151
	TRY (hdf5_close_group (group_id));
gsell's avatar
gsell committed
152
	H5_RETURN (ret_value);
153 154 155 156 157 158 159 160 161 162 163 164 165
}

h5_err_t
h5_get_attachment_info_by_idx (
	const h5_file_t f_,
	const h5_size_t idx,		// IN
	char* const fname,		// OUT
	h5_size_t len_fname,		// IN
	h5_size_t* const fsize		// OUT
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t,
			   "f=%p, idx=%llu, fname=%s, len_fname=%llu, fsize=%p",
166 167
			   f, (unsigned long long)idx,
			   fname, (unsigned long long)len_fname,
168 169
			   fsize);
	hid_t loc_id;
170
	TRY (loc_id = hdf5_open_group (f->file, H5_ATTACHMENT));
171 172 173 174 175 176 177 178 179 180 181 182
	TRY (hdf5_get_name_of_dataset_by_idx (
		     loc_id,
		     idx,
		     fname, len_fname));

	if (fsize) {
		// get number of elements, do not change value on error
		h5_ssize_t ssize;
		TRY (ssize = hdf5_get_npoints_of_dataset_by_name (loc_id, fname));
		*fsize = ssize;
	}
	TRY (hdf5_close_group (loc_id));
gsell's avatar
gsell committed
183
	H5_RETURN (H5_SUCCESS);
184 185
}

186 187 188 189 190 191 192 193 194
h5_err_t
h5_has_attachment (
	const h5_file_t f_,		// [in]
	const char* const fname		// [in]
	) {
	h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p, fname='%s'", f, fname);
	hid_t loc_id;
	TRY (loc_id = hdf5_open_group (f->file, H5_ATTACHMENT));
195
        TRY (ret_value = hdf5_link_exists (f->file, fname));
gsell's avatar
gsell committed
196
	H5_RETURN (ret_value);
197 198
}

199 200 201 202 203 204 205 206 207 208
h5_err_t
h5_get_attachment_info_by_name (
	const h5_file_t f_,
	const char* const fname,	// IN
	h5_size_t* const fsize		// OUT
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p, fname='%s', fsize=%p", f, fname, fsize);

	hid_t loc_id;
209
	TRY (loc_id = hdf5_open_group (f->file, H5_ATTACHMENT));
210 211 212 213 214 215 216
	if (fsize) {
		// get number of elements, do not change value on error
		h5_ssize_t ssize;
		TRY (ssize = hdf5_get_npoints_of_dataset_by_name (loc_id, fname));
		*fsize = ssize;
	}
	TRY (hdf5_close_group (loc_id));
gsell's avatar
gsell committed
217
	H5_RETURN (H5_SUCCESS);
218 219 220 221 222 223 224 225 226 227 228
}

h5_err_t
h5_get_attachment (
	const h5_file_t f_,
	const char* const fname
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p, fname='%s'", f, fname);
	// allowed modes: O_RDWR, O_RDONLY; O_APPEND
	// forbidden modes: O_WRONLY
229
	if (f->props->flags & H5_O_WRONLY) {
gsell's avatar
gsell committed
230
		H5_LEAVE (
231
			h5priv_handle_file_mode_error (f->props->flags));
232 233 234 235 236 237 238 239
	}

	hid_t loc_id;
	TRY (loc_id = hdf5_open_group (f->file, H5_ATTACHMENT));

	// read dataset
	hid_t dataset_id, diskspace_id;
	h5_ssize_t fsize;
240
	TRY (dataset_id = hdf5_open_dataset_by_name (loc_id, fname));
241 242 243 244 245 246
	TRY (diskspace_id = hdf5_get_dataset_space (dataset_id));
	TRY (fsize = hdf5_get_npoints_of_dataspace (diskspace_id));

	hsize_t read_length;
	char* buf = NULL;
	if (f->myproc == 0) {
gsell's avatar
gsell committed
247
		buf = h5_calloc (1, fsize);
248 249 250
		read_length = fsize;

	} else {
gsell's avatar
gsell committed
251
		buf = h5_calloc (1, 1);
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
		read_length = 0;
	}

	hsize_t start = 0;
	TRY (hdf5_select_hyperslab_of_dataspace (
		     diskspace_id,
		     H5S_SELECT_SET,
		     &start,
		     NULL,
		     &read_length,
		     NULL));

	hid_t memspace_id;
	hsize_t max = H5S_UNLIMITED;
	TRY (memspace_id = hdf5_create_dataspace (1, &read_length, &max));
	TRY (hdf5_read_dataset (dataset_id,
				 H5T_NATIVE_CHAR,
				 memspace_id,
				 diskspace_id,
				 f->props->xfer_prop,
				 buf));

	TRY (hdf5_close_dataspace (diskspace_id));
	TRY (hdf5_close_dataspace (memspace_id));
	TRY (hdf5_close_dataset (dataset_id));
	TRY (hdf5_close_group (loc_id));

	// write file
	if (f->myproc == 0) {
		int fd;
		if ((fd = open (fname, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
283 284 285 286
			H5_RETURN_ERROR (
				H5_ERR_H5,
				"Error opening file '%s': %s",
				fname, strerror(errno));
287 288
		}
		if (write (fd, buf, fsize) != fsize) {
289 290 291 292
			H5_RETURN_ERROR (
				H5_ERR_H5,
				"Error writing to file '%s': %s",
				fname, strerror(errno));
293 294
		}
		if (close (fd) < 0) {
295 296 297 298
			H5_RETURN_ERROR (
				H5_ERR_H5,
				"Error closing file '%s': %s",
				fname, strerror(errno));
299 300 301 302
		}
	}
	TRY (h5_free (buf));

gsell's avatar
gsell committed
303
	H5_RETURN (H5_SUCCESS);
304 305 306 307 308 309 310 311 312
}

h5_err_t
h5_delete_attachment (
	const h5_file_t f_,
	const char* const fname
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p, fname='%s'", f, fname);
gsell's avatar
gsell committed
313 314 315 316 317
	// allowed file modes: O_RDWR, O_WRONLY; O_APPEND
	if (f->props->flags & H5_O_RDONLY) {
		H5_LEAVE (
			h5priv_handle_file_mode_error (f->props->flags));
	}
318 319 320 321 322

	hid_t loc_id;
	TRY (loc_id = hdf5_open_group (f->file, H5_ATTACHMENT));
	TRY (hdf5_delete_link (loc_id, fname, H5P_DEFAULT));
	TRY (hdf5_close_group (loc_id));
gsell's avatar
gsell committed
323
	H5_RETURN (H5_SUCCESS);
324
}