ftp://ftp.redhat.com/pub/redhat/linux/rawhide/SRPMS/SRPMS/gnome-vfs2-2.3.8-1.src.rpm
[gnome-vfs-httpcaptive.git] / libgnomevfs / gnome-vfs-file-info.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gnome-vfs-file-info.c - Handling of file information for the GNOME
3    Virtual File System.
4
5    Copyright (C) 1999 Free Software Foundation
6
7    The Gnome Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    The Gnome Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public
18    License along with the Gnome Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.
21
22    Author: Ettore Perazzoli <ettore@comm2000.it>
23 */
24
25 #include <config.h>
26 #include "gnome-vfs-file-info.h"
27
28 #include <glib/gmessages.h>
29 #include <glib/gstrfuncs.h>
30 #include <glib/gthread.h>
31 #include <string.h>
32
33 /* Mutex for making GnomeVFSFileInfo ref's/unref's atomic */
34 /* Note that an atomic increment function (such as is present in NSPR) is preferable */
35 /* FIXME: This mutex is probably not needed and might be causing performance issues */
36 static GStaticMutex file_info_ref_lock = G_STATIC_MUTEX_INIT;
37
38
39 /**
40  * gnome_vfs_file_info_new
41  * 
42  * Allocate and initialize a new file information struct.
43  * 
44  * Returns: A pointer to the new file information struct.
45  **/
46 GnomeVFSFileInfo *
47 gnome_vfs_file_info_new (void)
48 {
49         GnomeVFSFileInfo *new;
50
51         new = g_new0 (GnomeVFSFileInfo, 1);
52
53         /* `g_new0()' is enough to initialize everything (we just want
54            all the members to be set to zero).  */
55
56         new->refcount = 1;
57         
58         return new;
59 }
60
61
62 /**
63  * gnome_vfs_file_info_ref
64  * @info: Pointer to a file information struct
65  * 
66  * Increment reference count
67  **/
68 void
69 gnome_vfs_file_info_ref (GnomeVFSFileInfo *info)
70 {
71         g_return_if_fail (info != NULL);
72         g_return_if_fail (info->refcount > 0);
73
74         g_static_mutex_lock (&file_info_ref_lock);
75         info->refcount += 1;
76         g_static_mutex_unlock (&file_info_ref_lock);
77         
78 }
79
80 /**
81  * gnome_vfs_file_info_unref
82  * @info: Pointer to a file information struct
83  * 
84  * Destroy @info
85  **/
86 void
87 gnome_vfs_file_info_unref (GnomeVFSFileInfo *info)
88 {
89         g_return_if_fail (info != NULL);
90         g_return_if_fail (info->refcount > 0);
91
92         g_static_mutex_lock (&file_info_ref_lock);
93         info->refcount -= 1;
94         g_static_mutex_unlock (&file_info_ref_lock);
95
96         if (info->refcount == 0) {
97                 gnome_vfs_file_info_clear (info);
98                 g_free (info);
99         }
100 }
101
102
103 /**
104  * gnome_vfs_file_info_clear
105  * @info: Pointer to a file information struct
106  * 
107  * Clear @info so that it's ready to accept new data. This is
108  * supposed to be used when @info already contains meaningful information which
109  * we want to replace.
110  **/
111 void
112 gnome_vfs_file_info_clear (GnomeVFSFileInfo *info)
113 {
114         guint old_refcount;
115         
116         g_return_if_fail (info != NULL);
117
118         g_free (info->name);
119         g_free (info->symlink_name);
120         g_free (info->mime_type);
121
122         /* Ensure the ref count is maintained correctly */
123         g_static_mutex_lock (&file_info_ref_lock);
124
125         old_refcount = info->refcount;
126         memset (info, 0, sizeof (*info));
127         info->refcount = old_refcount;
128
129         g_static_mutex_unlock (&file_info_ref_lock);
130 }
131
132
133 /**
134  * gnome_vfs_file_info_get_mime_type
135  * @info: A pointer to a file information struct
136  * 
137  * Retrieve MIME type from @info. There is no need to free the return
138  * value.
139  * 
140  * Returns: A pointer to a string representing the MIME type.
141  **/
142 const gchar *
143 gnome_vfs_file_info_get_mime_type (GnomeVFSFileInfo *info)
144 {
145         g_return_val_if_fail (info != NULL, NULL);
146
147         return info->mime_type;
148 }
149
150 /**
151  * gnome_vfs_file_info_copy
152  * @dest: Pointer to a struct to copy @src's information into
153  * @src: Pointer to the information to be copied into @dest
154  * 
155  * Copy information from @src into @dest.
156  **/
157 void
158 gnome_vfs_file_info_copy (GnomeVFSFileInfo *dest,
159                           const GnomeVFSFileInfo *src)
160 {
161         guint old_refcount;
162
163         g_return_if_fail (dest != NULL);
164         g_return_if_fail (src != NULL);
165
166         /* The primary purpose of this lock is to guarentee that the
167          * refcount is correctly maintained, not to make the copy
168          * atomic.  If you want to make the copy atomic, you probably
169          * want serialize access differently (or perhaps you shouldn't
170          * use copy)
171          */
172         g_static_mutex_lock (&file_info_ref_lock);
173
174         old_refcount = dest->refcount;
175
176         /* Copy basic information all at once; we will fix pointers later.  */
177
178         memcpy (dest, src, sizeof (*src));
179
180         /* Duplicate dynamically allocated strings.  */
181
182         dest->name = g_strdup (src->name);
183         dest->symlink_name = g_strdup (src->symlink_name);
184         dest->mime_type = g_strdup (src->mime_type);
185
186         dest->refcount = old_refcount;
187
188         g_static_mutex_unlock (&file_info_ref_lock);
189
190 }
191
192 /**
193  * gnome_vfs_file_info_dup:
194  * @orig: Pointer to a file information structure to duplicate
195  * 
196  * Duplicates @orig and returns it.
197  * 
198  * Returns: a new file information struct that duplicates the information in @orig.
199  **/
200 GnomeVFSFileInfo *
201 gnome_vfs_file_info_dup (const GnomeVFSFileInfo *orig)
202 {
203         GnomeVFSFileInfo * ret;
204
205         g_return_val_if_fail (orig != NULL, NULL);
206
207         ret = gnome_vfs_file_info_new();
208
209         gnome_vfs_file_info_copy (ret, orig);
210
211         return ret;
212 }
213
214
215 /**
216  * gnome_vfs_file_info_matches
217  * @a: first GnomeVFSFileInfo struct to compare
218  * @b: second GnomeVFSFileInfo struct to compare
219  *
220  * Compare the two file info structs, return TRUE if they match.
221  *
222  * Returns: TRUE if the two GnomeVFSFileInfos match, otherwise return FALSE.
223  **/
224 gboolean
225 gnome_vfs_file_info_matches (const GnomeVFSFileInfo *a,
226                              const GnomeVFSFileInfo *b)
227 {
228         g_return_val_if_fail (a != NULL, FALSE);
229         g_return_val_if_fail (b != NULL, FALSE);
230         g_return_val_if_fail (a->name != NULL, FALSE);
231         g_return_val_if_fail (b->name != NULL, FALSE);
232
233         if (a->type != b->type
234             || a->size != b->size
235             || a->block_count != b->block_count
236             || a->atime != b->atime
237             || a->mtime != b->mtime
238             || a->ctime != b->ctime
239             || strcmp (a->name, b->name) != 0) {
240                 return FALSE;
241         }
242
243         if (a->mime_type == NULL || b->mime_type == NULL) {
244                 return a->mime_type == b->mime_type;
245         }
246
247         g_assert (a->mime_type != NULL && b->mime_type != NULL);
248         return g_ascii_strcasecmp (a->mime_type, b->mime_type) == 0;
249 }
250
251 /**
252  * gnome_vfs_file_info_list_ref:
253  * @list: list of GnomeVFSFileInfo elements
254  *
255  * Increments the reference count of the items in @list by one.
256  *
257  * Return value: @list
258  **/
259 GList *
260 gnome_vfs_file_info_list_ref (GList *list)
261 {
262         g_list_foreach (list, (GFunc) gnome_vfs_file_info_ref, NULL);
263         return list;
264 }
265
266 /**
267  * gnome_vfs_file_info_list_unref:
268  * @list: list of GnomeVFSFileInfo elements
269  *
270  * Decrements the reference count of the items in @list by one.
271  * Note that the list is *not freed* even if each member of the list
272  * is freed.
273  *
274  * Return value: @list
275  **/
276 GList *
277 gnome_vfs_file_info_list_unref (GList *list)
278 {
279         g_list_foreach (list, (GFunc) gnome_vfs_file_info_unref, NULL);
280         return list;
281 }
282
283 /**
284  * gnome_vfs_file_info_list_copy:
285  * @list: list of GnomeVFSFileInfo elements
286  *
287  * Creates a duplicate of @list, and references each member of
288  * that list.
289  *
290  * Return value: a newly referenced duplicate of @list
291  **/
292 GList *
293 gnome_vfs_file_info_list_copy (GList *list)
294 {
295         return g_list_copy (gnome_vfs_file_info_list_ref (list));
296 }
297
298 /**
299  * gnome_vfs_file_info_list_free:
300  * @list: list of GnomeVFSFileInfo elements
301  *
302  * Decrements the reference count of each member of @list by one,
303  * and frees the list itself.
304  **/
305 void
306 gnome_vfs_file_info_list_free (GList *list)
307 {
308         g_list_free (gnome_vfs_file_info_list_unref (list));
309 }