SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
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#define UNPACK_TYPES 3
20static char *unpackSuffix[UNPACK_TYPES] = {
21 "gz",
22 "F",
23 "Z",
24};
25static char *unpackCommand[UNPACK_TYPES] = {
26 "gzip -dcn %s 2> /dev/null ",
27 "freeze -dc %s ",
28 "uncompress -c %s ",
29};
30
31/**
32 * @brief Determines the unpacking type based on the file extension.
33 *
34 * This function checks the file extension of the given filename to determine the type of unpacking required.
35 * It can optionally provide the unpacked filename without its extension and verify if the file conforms
36 * to the SDDS format if the UNPACK_REQUIRE_SDDS flag is set in the mode.
37 *
38 * @param filename The name of the file to check.
39 * @param unpackedName Pointer to store the unpacked filename without extension (optional).
40 * @param mode Flags indicating unpacking requirements and options.
41 * @return The index of the unpacking type if the extension matches, or -1 if no matching type is found or an error occurs.
42 */
43long PackSuffixType(char *filename, char **unpackedName, unsigned long mode) {
44 char *extension, buffer[10];
45 FILE *fp;
46 long i;
47
48 if (!(extension = strrchr(filename, '.')))
49 return -1;
50
51 extension++;
52 for (i = 0; i < UNPACK_TYPES; i++)
53 if (strcmp(extension, unpackSuffix[i]) == 0) {
54 if (unpackedName) {
55 cp_str(unpackedName, filename);
56 extension = strrchr(*unpackedName, '.');
57 *extension = 0;
58 }
59 break;
60 }
61 if (i == UNPACK_TYPES)
62 return -1;
63
64 if (mode & UNPACK_REQUIRE_SDDS) {
65 if (!(fp = fopen(filename, FOPEN_READ_MODE)))
66 return -1;
67 if (fread(buffer, sizeof(*buffer), 4, fp) == 4 && strncmp(buffer, "SDDS", 4) == 0) {
68 fclose(fp);
69 return -1;
70 }
71 fclose(fp);
72 }
73 return i;
74}
75
76/**
77 * @brief Opens a file, potentially unpacking it based on its extension and mode.
78 *
79 * This function attempts to open a file, determining whether it needs to be unpacked based on its extension.
80 * If unpacking is required and specified by the mode, it either uses a pipe or creates a temporary file
81 * to access the unpacked data.
82 *
83 * @param filename The name of the file to open.
84 * @param mode Flags indicating unpacking requirements and options.
85 * @param popenUsed Pointer to a short that will be set to 1 if popen is used, otherwise 0 (optional).
86 * @param tmpFileUsed Pointer to store the name of the temporary file used for unpacking (optional).
87 * @return A FILE pointer to the opened file, or NULL if the file could not be opened or an error occurred.
88 */
89FILE *UnpackFopen(char *filename, unsigned long mode, short *popenUsed, char **tmpFileUsed) {
90 static char *command = NULL;
91 long type;
92 char *tmpName;
93
94 if (popenUsed)
95 *popenUsed = 0;
96 if (tmpFileUsed)
97 *tmpFileUsed = NULL;
98 if (!filename)
99 return NULL;
100 if ((type = PackSuffixType(filename, NULL, mode)) < 0)
101 return fopen(filename, FOPEN_READ_MODE);
102
103 if (!(command = trealloc(command, sizeof(*command) * (strlen(filename) + 100))))
104 return NULL;
105 if (mode & UNPACK_USE_PIPE) {
106 sprintf(command, unpackCommand[type], filename);
107 if (popenUsed)
108 *popenUsed = 1;
109#if defined(vxWorks)
110 fprintf(stderr, "popen is not supported in vxWorks\n");
111 exit(1);
112 return NULL;
113#else
114 return popen(command, FOPEN_READ_MODE);
115#endif
116 } else {
117 sprintf(command, unpackCommand[type], filename);
118 tmpName = tmpname(NULL);
119 strcat(command, "> /tmp/");
120 strcat(command, tmpName);
121 system(command);
122
123 sprintf(command, "/tmp/%s", tmpName);
124 if (tmpFileUsed)
125 cp_str(tmpFileUsed, command);
126
127 return fopen(command, FOPEN_READ_MODE);
128 }
129}
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:89
long PackSuffixType(char *filename, char **unpackedName, unsigned long mode)
Determines the unpacking type based on the file extension.
Definition unpack.c:43