fix buildbot reported problems (unix related), part 3, don't use GError with GLib 1.x
[metze/wireshark/wip.git] / fileset.c
1 /* fileset.c
2  * Routines for handling file sets
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_IO_H
30 #include <io.h>
31 #endif
32
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36
37 #ifdef HAVE_DIRENT_H
38 #include <dirent.h>
39 #endif
40
41 #ifdef HAVE_SYS_STAT_H
42 # include <sys/stat.h>
43 #endif
44
45 #ifdef HAVE_SYS_WAIT_H
46 # include <sys/wait.h>
47 #endif
48
49 #include <string.h>
50 #include <ctype.h>
51
52 #include <glib.h>
53
54 #include "globals.h"
55
56 #include <epan/filesystem.h>
57
58 #include "fileset.h"
59
60
61
62 typedef struct _fileset {
63   GList         *entries;
64   const char    *dirname;
65 } fileset;
66
67 /* this is the fileset's global data */
68 fileset set = { NULL, NULL};
69
70
71 /* is this a probable file of a file set (does the naming pattern match)? */
72 gboolean
73 fileset_filename_match_pattern(const char *fname)
74 {
75     char        *pfx;
76     int         baselen;
77     int         minlen = strlen("_00001_20050418010750");
78     char        *filename;
79   
80
81     /* d:\dir1\test_00001_20050418010750.cap */
82     filename = g_strdup(get_basename(fname));
83
84     /* test_00001_20050418010750.cap */
85     pfx = strrchr(filename, '.');
86     if(pfx == NULL) {
87         return FALSE;
88     }
89     /* test_00001_20050418010750 */
90     *pfx = '\0';
91
92     /* filename long enough? */
93     baselen = strlen(filename);
94     if(baselen < minlen) {
95         g_free(filename);
96         return FALSE;
97     }
98
99     /* there must be two underscores at special places */
100     if(filename[baselen-minlen] != '_' || filename[baselen-minlen+6] != '_') {
101         g_free(filename);
102         return FALSE;
103     }
104
105     /* replace the two underscores by digits */
106     filename[baselen-minlen] = '0';
107     filename[baselen-minlen+6] = '0';
108
109     /* we should have only digits now */
110     while(minlen--) {
111         baselen--;
112
113         if(!isdigit( (int) filename[baselen])) {
114             g_free(filename);
115             return FALSE;
116         }
117     }
118
119     g_free(filename);
120
121     /* ok, seems to be good */
122     return TRUE;
123 }
124
125
126 /* test, if both files could be in the same file set */
127 gboolean
128 fileset_is_file_in_set(const char *fname1, const char *fname2)
129 {
130     char        *pfx1;
131     char        *pfx2;
132     char        *dup_f1;
133     char        *dup_f2;
134     int         minlen = strlen("_00001_20050418010750");
135
136
137     dup_f1 = g_strdup(fname1);
138     dup_f2 = g_strdup(fname2);
139
140     pfx1 = strrchr(dup_f1, '.');
141     pfx2 = strrchr(dup_f2, '.');
142
143     if(strcmp(pfx1, pfx2) != 0) {
144         g_free(dup_f1);
145         g_free(dup_f2);
146         return FALSE;
147     }
148
149     *(pfx1-minlen) = '\0';
150     *(pfx2-minlen) = '\0';
151
152     if(strcmp(dup_f1, dup_f2) != 0) {
153         g_free(dup_f1);
154         g_free(dup_f2);
155         return FALSE;
156     }
157
158     g_free(dup_f1);
159     g_free(dup_f2);
160     return TRUE;
161 }
162
163
164 /* we know this file is part of the set, so add it */
165 fileset_entry *
166 fileset_add_file(const char *dirname, const char *fname, gboolean current)
167 {
168     int fh, result;
169     struct stat buf;
170     char *path;
171     fileset_entry *entry = NULL;
172
173
174     path = g_strdup_printf("%s%s", dirname, fname);
175
176     fh = open( path, O_RDONLY );
177     if(fh !=  -1) {
178
179         /* Get statistics */
180         result = fstat( fh, &buf );
181
182         /* Show statistics if they are valid */
183         if( result == 0 ) {
184             entry = g_malloc(sizeof(fileset_entry));
185
186             entry->fullname = g_strdup(path);
187             entry->name     = g_strdup(fname);
188             entry->ctime    = buf.st_ctime;
189             entry->mtime    = buf.st_mtime;
190             entry->size     = buf.st_size;
191             entry->current  = current;
192
193             set.entries = g_list_append(set.entries, entry);
194         }
195
196         close(fh);
197     }
198
199     g_free(path);
200
201     return entry;
202 }
203
204
205 /* compare two list entries by creation date/time */
206 gint
207 fileset_compare_creation(gconstpointer a, gconstpointer b)
208 {
209     const fileset_entry *entry_a = a;
210     const fileset_entry *entry_b = b;
211
212     return entry_a->ctime - entry_b->ctime;
213 }
214
215
216 /* add all file set entries to the dialog */
217 void fileset_update_dlg(void)
218 {
219     GList         *le;
220
221
222     /* add all entires to the dialog */
223     le = g_list_first(set.entries);
224     while(le) {
225         fileset_dlg_add_file(le->data);
226         le = g_list_next(le);
227     }
228 }
229
230
231 /* walk through the directory of the loaded file and add every file matching the current file */
232 void
233 fileset_add_dir(const char *fname)
234 {
235 #if GLIB_MAJOR_VERSION < 2
236     DIR           *dir;             /* scanned directory */
237     struct dirent *file;            /* current file */
238     gchar         *name;
239 #else /* GLIB 2 */
240     GDir          *dir;             /* scanned directory */
241     GError        **dummy;
242     const char    *name;
243 #endif
244     fileset_entry *entry;
245     GString       *dirname;
246     gchar         *fname_dup;
247
248
249     /* get (convert) directory name, but don't touch the given string */
250     fname_dup = get_dirname(g_strdup(fname));
251     dirname = g_string_new(fname_dup);
252     g_free(fname_dup);
253
254     set.dirname = g_strdup(dirname->str);    
255     
256     dirname = g_string_append_c(dirname, G_DIR_SEPARATOR);
257
258     /* if the current file can't be part of any fileset, do nothing */
259     if(!fileset_filename_match_pattern(fname)) {
260         entry = fileset_add_file(dirname->str, get_basename(fname), TRUE /* current */);
261         if(entry) {
262             fileset_dlg_add_file(entry);
263         }
264     }
265
266     /* go through the files in the directory and check if it's part of the current file set */
267 #if GLIB_MAJOR_VERSION < 2
268     if ((dir = opendir(dirname)) != NULL) {
269             while ((file = readdir(dir)) != NULL) {
270                 name = (gchar *)file->d_name;
271 #else
272     dummy = g_malloc(sizeof(GError *));
273     *dummy = NULL;
274
275     if ((dir = g_dir_open(dirname->str, 0, dummy)) != NULL) {
276         while ((name = g_dir_read_name(dir)) != NULL) {
277 #endif
278             if(fileset_filename_match_pattern(name) && fileset_is_file_in_set(name, get_basename(fname))) {
279                 fileset_add_file(dirname->str, name, strcmp(name, get_basename(fname))== 0 /* current */);
280             }
281         }
282     }
283
284     g_free(dummy);
285     g_string_free(dirname, TRUE /* free_segment */);
286
287     /* sort entries by creation time */
288     set.entries = g_list_sort(set.entries, fileset_compare_creation);
289
290     fileset_update_dlg();
291 }
292
293
294 /* get current directory name */
295 const char *
296 fileset_get_dirname(void)
297 {
298     return set.dirname;
299 }
300
301
302 /* get the current list entry, or NULL */
303 GList *
304 fileset_get_current(void)
305 {
306     GList         *le;
307     fileset_entry *entry;
308
309
310     /* add all entires to the dialog */
311     le = g_list_first(set.entries);
312     while(le) {
313         entry = le->data;
314         if(entry->current) {
315             return le;
316         }
317         le = g_list_next(le);
318     }
319
320     return NULL;
321 }
322
323
324 /* get the file set entry after the current one, or NULL */
325 fileset_entry *
326 fileset_get_next(void)
327 {
328     GList         *le;
329
330
331     le = fileset_get_current();
332     if(le == NULL) {
333         return NULL;
334     }
335
336     le = g_list_next(le);
337     if(le == NULL) {
338         return NULL;
339     }
340
341     return le->data;
342 }
343
344
345 /* get the file set entry before the current one, or NULL */
346 fileset_entry *
347 fileset_get_previous(void)
348 {
349     GList         *le;
350
351
352     le = fileset_get_current();
353     if(le == NULL) {
354         return NULL;
355     }
356
357     le = g_list_previous(le);
358     if(le == NULL) {
359         return NULL;
360     }
361
362     return le->data;
363 }
364
365
366 /* delete a single entry */
367 void fileset_entry_delete(gpointer data, gpointer user_data)
368 {
369     fileset_entry *entry = data;
370
371     g_free( (gpointer) entry->fullname);
372     entry->fullname = NULL;
373     g_free( (gpointer) entry->name);
374     entry->name = NULL;
375 }
376
377
378 /* delete the whole file set */
379 void fileset_delete(void)
380 {
381     /* free the entry list */
382     if(set.entries) {
383         g_list_foreach(set.entries, fileset_entry_delete, NULL);
384         g_list_free(set.entries);
385         set.entries = NULL;
386     }
387
388     /* free the rest */
389     if(set.dirname) {
390         g_free( (gpointer) set.dirname);
391         set.dirname = NULL;
392     }
393 }
394
395