1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 
15 #include "H5private.h"
16 #include "h5tools.h"
17 #include "h5tools_utils.h"
18 
19 /* Name of tool */
20 #define PROGRAMNAME "h5mkgrp"
21 
22 /* Exit status for tools library routines */
23 int d_status = EXIT_SUCCESS;
24 
25 /* command-line options: short and long-named parameters */
26 static const char *s_opts = "hlpvV";
27 static struct long_options l_opts[] = {
28     { "help", no_arg, 'h' },
29     { "latest", no_arg, 'l' },
30     { "parents", no_arg, 'p' },
31     { "verbose", no_arg, 'v' },
32     { "version", no_arg, 'V' },
33     { NULL, 0, '\0' }
34 };
35 
36 /* Command line parameter settings */
37 typedef struct {
38     char *fname;                /* File name to operate on */
39     hbool_t latest;             /* Whether file should use latest format versions */
40     hbool_t verbose;            /* Whether output should be verbose */
41     hbool_t parents;            /* Whether to create intermediate groups */
42     size_t ngroups;             /* Number of groups to create */
43     char **groups;              /* Pointer to array of group names */
44 } param_t;
45 param_t params;             /* Command line parameter settings */
46 
47 
48 /*-------------------------------------------------------------------------
49  * Function:    leave
50  *
51  * Purpose:     Shutdown MPI and/or HDF5 and call exit()
52  *
53  * Return:      Does not return
54  *
55  * Programmer: Quincey Koziol, 2/13/2007
56  *
57  *-------------------------------------------------------------------------
58  */
59 static void
leave(int ret)60 leave(int ret)
61 {
62     size_t curr_group;
63 
64     if (params.fname)
65         HDfree (params.fname);
66     if (params.ngroups) {
67         for(curr_group = 0; curr_group < params.ngroups; curr_group++)
68             HDfree (params.groups[curr_group]);
69         HDfree (params.groups);
70     }
71     h5tools_close();
72     HDexit(ret);
73 } /* end leave() */
74 
75 
76 /*-------------------------------------------------------------------------
77  * Function: usage
78  *
79  * Purpose: Prints a usage message on stderr and then returns.
80  *
81  * Return: void
82  *
83  * Programmer: Quincey Koziol, 2/13/2007
84  *
85  *-------------------------------------------------------------------------
86  */
87 static void
usage(void)88 usage(void)
89 {
90     HDfprintf(stdout, "\
91 usage: h5mkgrp [OPTIONS] FILE GROUP...\n\
92    OPTIONS\n\
93       -h, --help         Print a usage message and exit\n\
94       -l, --latest       Use latest version of file format to create groups\n\
95       -p, --parents      No error if existing, make parent groups as needed\n\
96       -v, --verbose      Print information about OBJECTS and OPTIONS\n\
97       -V, --version      Print version number and exit\n");
98 } /* end usage() */
99 
100 
101 /*-------------------------------------------------------------------------
102  * Function: parse_command_line
103  *
104  * Purpose: Parses command line and sets up global variable to control output
105  *
106  * Return:  Success: 0
107  *    Failure: -1
108  *
109  * Programmer: Quincey Koziol, 2/13/2007
110  *
111  *-------------------------------------------------------------------------
112  */
113 static int
parse_command_line(int argc,const char * argv[],param_t * parms)114 parse_command_line(int argc, const char *argv[], param_t *parms)
115 {
116     int opt;            /* Option from command line */
117     size_t curr_group;  /* Current group name to copy */
118 
119     /* Check for empty command line */
120     if(argc == 1) {
121         usage();
122         leave(EXIT_SUCCESS);
123     } /* end if */
124 
125     /* Parse command line options */
126     while((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) {
127         switch((char)opt) {
128             /* Display 'help' */
129             case 'h':
130                 usage();
131                 leave(EXIT_SUCCESS);
132                 break;
133 
134             /* Create objects with the latest version of the format */
135             case 'l':
136                 parms->latest = TRUE;
137                 break;
138 
139             /* Create parent groups */
140             case 'p':
141                 parms->parents = TRUE;
142                 break;
143 
144             /* Verbose output */
145             case 'v':
146                 parms->verbose = TRUE;
147                 break;
148 
149             /* Display version */
150             case 'V':
151                 print_version(h5tools_getprogname());
152                 leave(EXIT_SUCCESS);
153                 break;
154 
155             /* Bad command line argument */
156             default:
157                 usage();
158                 leave(EXIT_FAILURE);
159         } /* end switch */
160     } /* end while */
161 
162     /* Check for file name to be processed */
163     if(argc <= opt_ind) {
164         error_msg("missing file name\n");
165         usage();
166         leave(EXIT_FAILURE);
167     } /* end if */
168 
169     /* Retrieve file name */
170     parms->fname = HDstrdup(argv[opt_ind]);
171     opt_ind++;
172 
173     /* Check for group(s) to be created */
174     if(argc <= opt_ind) {
175         error_msg("missing group name(s)\n");
176         usage();
177         leave(EXIT_FAILURE);
178     } /* end if */
179 
180     /* Allocate space for the group name pointers */
181     parms->ngroups = (size_t)(argc - opt_ind);
182     parms->groups = (char **)HDmalloc(parms->ngroups * sizeof(char *));
183 
184     /* Retrieve the group names */
185     curr_group = 0;
186     while(opt_ind < argc) {
187         parms->groups[curr_group] = HDstrdup(argv[opt_ind]);
188         curr_group++;
189         opt_ind++;
190     } /* end while */
191 
192 #ifdef QAK
193 HDfprintf(stderr, "parms->parents = %t\n", parms->parents);
194 HDfprintf(stderr, "parms->verbose = %t\n", parms->verbose);
195 HDfprintf(stderr, "parms->fname = '%s'\n", parms->fname);
196 HDfprintf(stderr, "parms->ngroups = %Zu\n", parms->ngroups);
197 for(curr_group = 0; curr_group < parms->ngroups; curr_group++)
198     HDfprintf(stderr, "parms->group[%Zu] = '%s'\n", curr_group, parms->groups[curr_group]);
199 #endif /* QAK */
200 
201     return(0);
202 } /* parse_command_line() */
203 
204 
205 /*-------------------------------------------------------------------------
206  * Function: main
207  *
208  * Purpose: Create group(s) in an HDF5 file
209  *
210  * Programmer: Quincey Koziol, 2/13/2007
211  *
212  *-------------------------------------------------------------------------
213  */
214 int
main(int argc,const char * argv[])215 main(int argc, const char *argv[])
216 {
217     hid_t fid;                  /* HDF5 file ID */
218     hid_t fapl_id;              /* File access property list ID */
219     hid_t lcpl_id;              /* Link creation property list ID */
220     size_t curr_group;          /* Current group to create */
221 
222     h5tools_setprogname(PROGRAMNAME);
223     h5tools_setstatus(EXIT_SUCCESS);
224 
225     /* Disable the HDF5 library's error reporting */
226     H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
227 
228     /* Initialize h5tools lib */
229     h5tools_init();
230 
231     /* Parse command line */
232     HDmemset(&params, 0, sizeof(params));
233     if(parse_command_line(argc, argv, &params) < 0) {
234         error_msg("unable to parse command line arguments\n");
235         leave(EXIT_FAILURE);
236     } /* end if */
237 
238     /* Create file access property list */
239     if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) {
240         error_msg("Could not create file access property list\n");
241         leave(EXIT_FAILURE);
242     } /* end if */
243 
244     /* Check for creating groups with new format version */
245     if(params.latest) {
246         /* Set the "use the latest version of the format" bounds */
247         if(H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) {
248             error_msg("Could not set property for using latest version of the format\n");
249             leave(EXIT_FAILURE);
250         } /* end if */
251 
252         /* Display some output if requested */
253         if(params.verbose)
254             HDprintf("%s: Creating groups with latest version of the format\n", h5tools_getprogname());
255     } /* end if */
256 
257     /* Attempt to open an existing HDF5 file first */
258     fid = h5tools_fopen(params.fname, H5F_ACC_RDWR, fapl_id, NULL, NULL, 0);
259 
260     /* If we couldn't open an existing file, try creating file */
261     /* (use "EXCL" instead of "TRUNC", so we don't blow away existing non-HDF5 file) */
262     if(fid < 0)
263         fid = H5Fcreate(params.fname, H5F_ACC_EXCL, H5P_DEFAULT, fapl_id);
264 
265     /* Test for error in opening file */
266     if(fid < 0) {
267         error_msg("Could not open output file '%s'\n", params.fname);
268         leave(EXIT_FAILURE);
269     } /* end if */
270 
271     /* Create link creation property list */
272     if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) {
273         error_msg("Could not create link creation property list\n");
274         leave(EXIT_FAILURE);
275     } /* end if */
276 
277     /* Check for creating intermediate groups */
278     if(params.parents) {
279         /* Set the intermediate group creation property */
280         if(H5Pset_create_intermediate_group(lcpl_id, TRUE) < 0) {
281             error_msg("Could not set property for creating parent groups\n");
282             leave(EXIT_FAILURE);
283         } /* end if */
284 
285         /* Display some output if requested */
286         if(params.verbose)
287             HDprintf("%s: Creating parent groups\n", h5tools_getprogname());
288     } /* end if */
289 
290     /* Loop over creating requested groups */
291     for(curr_group = 0; curr_group < params.ngroups; curr_group++) {
292         hid_t gid;              /* Group ID */
293 
294         /* Attempt to create a group */
295         if((gid = H5Gcreate2(fid, params.groups[curr_group], lcpl_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) {
296             error_msg("Could not create group '%s'\n", params.groups[curr_group]);
297             leave(EXIT_FAILURE);
298         } /* end if */
299 
300         /* Close the group */
301         if(H5Gclose(gid) < 0) {
302             error_msg("Could not close group '%s'??\n", params.groups[curr_group]);
303             leave(EXIT_FAILURE);
304         } /* end if */
305 
306         /* Display some output if requested */
307         if(params.verbose)
308             HDprintf("%s: created group '%s'\n", h5tools_getprogname(), params.groups[curr_group]);
309     } /* end for */
310 
311     /* Close link creation property list */
312     if(H5Pclose(lcpl_id) < 0) {
313         error_msg("Could not close link creation property list\n");
314         leave(EXIT_FAILURE);
315     } /* end if */
316 
317     /* Close file */
318     if(H5Fclose(fid) < 0) {
319         error_msg("Could not close output file '%s'??\n", params.fname);
320         leave(EXIT_FAILURE);
321     } /* end if */
322 
323     /* Close file access property list */
324     if(H5Pclose(fapl_id) < 0) {
325         error_msg("Could not close file access property list\n");
326         leave(EXIT_FAILURE);
327     } /* end if */
328 
329     leave(EXIT_SUCCESS);
330 } /* end main() */
331 
332