SDDSlib
Loading...
Searching...
No Matches
unpack.c
Go to the documentation of this file.
1/**
2 * @file unpack.c
3 * @brief Provides functions for determining unpacking types and opening unpacked files.
4 *
5 * @copyright
6 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
7 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
8 *
9 * @license
10 * This file is distributed under the terms of the Software License Agreement
11 * found in the file LICENSE included with this distribution.
12 *
13 * @author M. Borland, C Saunders, R. Soliday
14 */
15
16#include "mdb.h"
17#include "scan.h"
18
19#if defined(_WIN32) && !defined(__MINGW32__)
20# define popen(x, y) _popen(x, y)
21#endif
22
23#define UNPACK_TYPES 3
24static char *unpackSuffix[UNPACK_TYPES] = {
25 "gz",
26 "F",
27 "Z",
28};
29static char *unpackCommand[UNPACK_TYPES] = {
30 "gzip -dcn %s 2> /dev/null ",
31 "freeze -dc %s ",
32 "uncompress -c %s ",
33};
34
35/**
36 * @brief Determines the unpacking type based on the file extension.
37 *
38 * This function checks the file extension of the given filename to determine the type of unpacking required.
39 * It can optionally provide the unpacked filename without its extension and verify if the file conforms
40 * to the SDDS format if the UNPACK_REQUIRE_SDDS flag is set in the mode.
41 *
42 * @param filename The name of the file to check.
43 * @param unpackedName Pointer to store the unpacked filename without extension (optional).
44 * @param mode Flags indicating unpacking requirements and options.
45 * @return The index of the unpacking type if the extension matches, or -1 if no matching type is found or an error occurs.
46 */
47long PackSuffixType(char *filename, char **unpackedName, unsigned long mode) {
48 char *extension, buffer[10];
49 FILE *fp;
50 long i;
51
52 if (!(extension = strrchr(filename, '.')))
53 return -1;
54
55 extension++;
56 for (i = 0; i < UNPACK_TYPES; i++)
57 if (strcmp(extension, unpackSuffix[i]) == 0) {
58 if (unpackedName) {
59 cp_str(unpackedName, filename);
60 extension = strrchr(*unpackedName, '.');
61 *extension = 0;
62 }
63 break;
64 }
65 if (i == UNPACK_TYPES)
66 return -1;
67
68 if (mode & UNPACK_REQUIRE_SDDS) {
69 if (!(fp = fopen(filename, FOPEN_READ_MODE)))
70 return -1;
71 if (fread(buffer, sizeof(*buffer), 4, fp) == 4 && strncmp(buffer, "SDDS", 4) == 0) {
72 fclose(fp);
73 return -1;
74 }
75 fclose(fp);
76 }
77 return i;
78}
79
80/**
81 * @brief Opens a file, potentially unpacking it based on its extension and mode.
82 *
83 * This function attempts to open a file, determining whether it needs to be unpacked based on its extension.
84 * If unpacking is required and specified by the mode, it either uses a pipe or creates a temporary file
85 * to access the unpacked data.
86 *
87 * @param filename The name of the file to open.
88 * @param mode Flags indicating unpacking requirements and options.
89 * @param popenUsed Pointer to a short that will be set to 1 if popen is used, otherwise 0 (optional).
90 * @param tmpFileUsed Pointer to store the name of the temporary file used for unpacking (optional).
91 * @return A FILE pointer to the opened file, or NULL if the file could not be opened or an error occurred.
92 */
93FILE *UnpackFopen(char *filename, unsigned long mode, short *popenUsed, char **tmpFileUsed) {
94 static char *command = NULL;
95 long type;
96 char *tmpName;
97
98 if (popenUsed)
99 *popenUsed = 0;
100 if (tmpFileUsed)
101 *tmpFileUsed = NULL;
102 if (!filename)
103 return NULL;
104 if ((type = PackSuffixType(filename, NULL, mode)) < 0)
105 return fopen(filename, FOPEN_READ_MODE);
106
107 if (!(command = trealloc(command, sizeof(*command) * (strlen(filename) + 100))))
108 return NULL;
109 if (mode & UNPACK_USE_PIPE) {
110 sprintf(command, unpackCommand[type], filename);
111 if (popenUsed)
112 *popenUsed = 1;
113#if defined(vxWorks)
114 fprintf(stderr, "popen is not supported in vxWorks\n");
115 exit(1);
116 return NULL;
117#else
118 return popen(command, FOPEN_READ_MODE);
119#endif
120 } else {
121 sprintf(command, unpackCommand[type], filename);
122 tmpName = tmpname(NULL);
123 strcat(command, "> /tmp/");
124 strcat(command, tmpName);
125 system(command);
126
127 sprintf(command, "/tmp/%s", tmpName);
128 if (tmpFileUsed)
129 cp_str(tmpFileUsed, command);
130
131 return fopen(command, FOPEN_READ_MODE);
132 }
133}
134
135#if defined(zLib)
136/**
137 * @brief Opens a gzip-compressed file.
138 *
139 * This function opens a gzip-compressed file for reading in binary mode using the zlib library.
140 *
141 * @param filename The name of the gzip file to open.
142 * @return A gzFile pointer to the opened gzip file, or NULL if the file could not be opened.
143 */
144gzFile UnpackGZipOpen(char *filename) {
145 if (!filename)
146 return NULL;
147 return gzopen(filename, "rb");
148}
149#endif
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
char * tmpname(char *s)
Supplies a unique temporary filename.
Definition tmpname.c:34
FILE * UnpackFopen(char *filename, unsigned long mode, short *popenUsed, char **tmpFileUsed)
Opens a file, potentially unpacking it based on its extension and mode.
Definition unpack.c:93
long PackSuffixType(char *filename, char **unpackedName, unsigned long mode)
Determines the unpacking type based on the file extension.
Definition unpack.c:47