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-async-ops.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gnome-vfs-async-ops.c - Asynchronous operations supported by the
3    GNOME Virtual File System (version for POSIX threads).
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 #include <config.h>
25
26 #include "gnome-vfs-async-ops.h"
27 #include "gnome-vfs-async-job-map.h"
28 #include "gnome-vfs-job.h"
29 #include "gnome-vfs-job-queue.h"
30 #include "gnome-vfs-job-limit.h"
31 #include <glib/gmessages.h>
32 #include <glib/gstrfuncs.h>
33 #include <unistd.h>
34
35 /**
36  * gnome_vfs_async_cancel:
37  * @handle: handle of the async operation to be cancelled
38  *
39  * Cancel an asynchronous operation and close all its callbacks.
40  * Its possible to still receive another call or two on the callback.
41  **/
42 void
43 gnome_vfs_async_cancel (GnomeVFSAsyncHandle *handle)
44 {
45         GnomeVFSJob *job;
46         
47         _gnome_vfs_async_job_map_lock ();
48
49         job = _gnome_vfs_async_job_map_get_job (handle);
50         if (job == NULL) {
51                 JOB_DEBUG (("job %u - job no longer exists", GPOINTER_TO_UINT (handle)));
52                 /* have to cancel the callbacks because they still can be pending */
53                 _gnome_vfs_async_job_cancel_job_and_callbacks (handle, NULL);
54         } else {
55                 /* Cancel the job in progress. OK to do outside of job->job_lock,
56                  * job lifetime is protected by _gnome_vfs_async_job_map_lock.
57                  */
58                 _gnome_vfs_job_module_cancel (job);
59                 _gnome_vfs_async_job_cancel_job_and_callbacks (handle, job);
60         }
61
62         _gnome_vfs_async_job_map_unlock ();
63 }
64
65 static GnomeVFSAsyncHandle *
66 async_open (GnomeVFSURI *uri,
67             GnomeVFSOpenMode open_mode,
68             int priority,
69             GnomeVFSAsyncOpenCallback callback,
70             gpointer callback_data)
71 {
72         GnomeVFSJob *job;
73         GnomeVFSOpenOp *open_op;
74         GnomeVFSAsyncHandle *result;
75
76         job = _gnome_vfs_job_new (GNOME_VFS_OP_OPEN, priority, (GFunc) callback, callback_data);
77         
78         open_op = &job->op->specifics.open;
79         
80         open_op->uri = uri == NULL ? NULL : gnome_vfs_uri_ref (uri);
81         open_op->open_mode = open_mode;
82
83         result = job->job_handle;
84         _gnome_vfs_job_go (job);
85
86         return result;
87 }
88
89 /**
90  * gnome_vfs_async_open_uri:
91  * @handle_return: A pointer to a pointer to a GnomeVFSHandle object
92  * @uri: URI to open
93  * @open_mode: Open mode
94  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
95  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
96  * in allocating threads from the thread pool.
97  * @callback: function to be called when the operation is complete
98  * @callback_data: data to pass @callback
99  * 
100  * Open @uri according to mode @open_mode.  On return, @handle_return will
101  * contain a pointer to the operation. Once the file has been successfully opened,
102  * @callback will be called with the GnomeVFSResult.
103  * 
104  **/
105 void
106 gnome_vfs_async_open_uri (GnomeVFSAsyncHandle **handle_return,
107                           GnomeVFSURI *uri,
108                           GnomeVFSOpenMode open_mode,
109                           int priority,
110                           GnomeVFSAsyncOpenCallback callback,
111                           gpointer callback_data)
112 {
113         g_return_if_fail (handle_return != NULL);
114         g_return_if_fail (uri != NULL);
115         g_return_if_fail (callback != NULL);
116         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
117         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
118
119         *handle_return = async_open (uri, open_mode, priority,
120                                      callback, callback_data);
121 }
122
123 /**
124  * gnome_vfs_async_open:
125  * @handle_return: A pointer to a pointer to a GnomeVFSHandle object
126  * @text_uri: string of the URI to open
127  * @open_mode: Open mode
128  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
129  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
130  * in allocating threads from the thread pool.
131  * @callback: function to be called when the operation is complete
132  * @callback_data: data to pass @callback
133  * 
134  * Open @text_uri according to mode @open_mode.  On return, @handle_return will
135  * contain a pointer to the operation. Once the file has been successfully opened,
136  * @callback will be called with the GnomeVFSResult.
137  * 
138  **/
139 void
140 gnome_vfs_async_open (GnomeVFSAsyncHandle **handle_return,
141                       const gchar *text_uri,
142                       GnomeVFSOpenMode open_mode,
143                       int priority,
144                       GnomeVFSAsyncOpenCallback callback,
145                       gpointer callback_data)
146 {
147         GnomeVFSURI *uri;
148
149         g_return_if_fail (handle_return != NULL);
150         g_return_if_fail (text_uri != NULL);
151         g_return_if_fail (callback != NULL);
152         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
153         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
154
155         uri = gnome_vfs_uri_new (text_uri);
156         *handle_return = async_open (uri, open_mode, priority,
157                                      callback, callback_data);
158         if (uri != NULL) {
159                 gnome_vfs_uri_unref (uri);
160         }
161 }
162
163 static GnomeVFSAsyncHandle *
164 async_open_as_channel (GnomeVFSURI *uri,
165                        GnomeVFSOpenMode open_mode,
166                        guint advised_block_size,
167                        int priority,
168                        GnomeVFSAsyncOpenAsChannelCallback callback,
169                        gpointer callback_data)
170 {
171         GnomeVFSJob *job;
172         GnomeVFSOpenAsChannelOp *open_as_channel_op;
173         GnomeVFSAsyncHandle *result;
174
175         job = _gnome_vfs_job_new (GNOME_VFS_OP_OPEN_AS_CHANNEL, priority, (GFunc) callback, callback_data);
176
177         open_as_channel_op = &job->op->specifics.open_as_channel;
178         open_as_channel_op->uri = uri == NULL ? NULL : gnome_vfs_uri_ref (uri);
179         open_as_channel_op->open_mode = open_mode;
180         open_as_channel_op->advised_block_size = advised_block_size;
181
182         result = job->job_handle;
183         _gnome_vfs_job_go (job);
184
185         return result;
186 }
187
188 /**
189  * gnome_vfs_async_open_uri_as_channel:
190  * @handle_return: A pointer to a pointer to a GnomeVFSHandle object
191  * @uri: URI to open as a #GIOChannel
192  * @open_mode: open for reading, writing, random, etc
193  * @advised_block_size: the preferred block size for #GIOChannel to read
194  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
195  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
196  * in allocating threads from the thread pool.
197  * @callback: function to be called when the operation is complete
198  * @callback_data: data to pass @callback
199  *
200  * Open @uri as a #GIOChannel. Once the channel has been established
201  * @callback will be called with @callback_data, the result of the operation,
202  * and if the result was %GNOME_VFS_OK, a reference to a #GIOChannel pointing
203  * at @uri in @open_mode.
204  **/
205 void
206 gnome_vfs_async_open_uri_as_channel (GnomeVFSAsyncHandle **handle_return,
207                                      GnomeVFSURI *uri,
208                                      GnomeVFSOpenMode open_mode,
209                                      guint advised_block_size,
210                                      int priority,
211                                      GnomeVFSAsyncOpenAsChannelCallback callback,
212                                      gpointer callback_data)
213 {
214         g_return_if_fail (handle_return != NULL);
215         g_return_if_fail (uri != NULL);
216         g_return_if_fail (callback != NULL);
217         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
218         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
219
220         *handle_return = async_open_as_channel (uri, open_mode, advised_block_size,
221                                                 priority, callback, callback_data);
222 }
223
224 /**
225  * gnome_vfs_async_open_as_channel:
226  * @handle_return: A pointer to a pointer to a GnomeVFSHandle object
227  * @text_uri: string of the URI to open as a #GIOChannel
228  * @open_mode: open for reading, writing, random, etc
229  * @advised_block_size: the preferred block size for #GIOChannel to read
230  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
231  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
232  * in allocating threads from the thread pool.
233  * @callback: function to be called when the operation is complete
234  * @callback_data: data to pass @callback
235  *
236  * Open @text_uri as a #GIOChannel. Once the channel has been established
237  * @callback will be called with @callback_data, the result of the operation,
238  * and if the result was %GNOME_VFS_OK, a reference to a #GIOChannel pointing
239  * at @text_uri in @open_mode.
240  **/
241 void
242 gnome_vfs_async_open_as_channel (GnomeVFSAsyncHandle **handle_return,
243                                  const gchar *text_uri,
244                                  GnomeVFSOpenMode open_mode,
245                                  guint advised_block_size,
246                                  int priority,
247                                  GnomeVFSAsyncOpenAsChannelCallback callback,
248                                  gpointer callback_data)
249 {
250         GnomeVFSURI *uri;
251
252         g_return_if_fail (handle_return != NULL);
253         g_return_if_fail (text_uri != NULL);
254         g_return_if_fail (callback != NULL);
255         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
256         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
257
258         uri = gnome_vfs_uri_new (text_uri);
259         *handle_return = async_open_as_channel (uri, open_mode, advised_block_size,
260                                                 priority, callback, callback_data);
261         if (uri != NULL) {
262                 gnome_vfs_uri_unref (uri);
263         }
264 }
265
266 static GnomeVFSAsyncHandle *
267 async_create (GnomeVFSURI *uri,
268               GnomeVFSOpenMode open_mode,
269               gboolean exclusive,
270               guint perm,
271               int priority,
272               GnomeVFSAsyncOpenCallback callback,
273               gpointer callback_data)
274 {
275         GnomeVFSJob *job;
276         GnomeVFSCreateOp *create_op;
277         GnomeVFSAsyncHandle *result;
278
279         job = _gnome_vfs_job_new (GNOME_VFS_OP_CREATE, priority, (GFunc) callback, callback_data);
280
281         create_op = &job->op->specifics.create;
282         create_op->uri = uri == NULL ? NULL : gnome_vfs_uri_ref (uri);
283         create_op->open_mode = open_mode;
284         create_op->exclusive = exclusive;
285         create_op->perm = perm;
286
287         result = job->job_handle;
288         _gnome_vfs_job_go (job);
289
290         return result;
291 }
292
293 /**
294  * gnome_vfs_async_create_uri:
295  * @handle_return: A pointer to a pointer to a GnomeVFSHandle object
296  * @uri: the URI to create a file at
297  * @open_mode: mode to leave the file opened in after creation (or %GNOME_VFS_OPEN_MODE_NONE
298  * to leave the file closed after creation)
299  * @exclusive: Whether the file should be created in "exclusive" mode:
300  * i.e. if this flag is nonzero, operation will fail if a file with the
301  * same name already exists.
302  * @perm: Bitmap representing the permissions for the newly created file
303  * (Unix style).
304  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
305  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
306  * in allocating threads from the thread pool.
307  * @callback: function to be called when the operation is complete
308  * @callback_data: data to pass @callback
309  * 
310  * Create a file at @uri according to mode @open_mode, with permissions @perm (in
311  * the standard UNIX packed bit permissions format). When the create has been completed
312  * @callback will be called with the result code and @callback_data.
313  **/
314 void
315 gnome_vfs_async_create_uri (GnomeVFSAsyncHandle **handle_return,
316                             GnomeVFSURI *uri,
317                             GnomeVFSOpenMode open_mode,
318                             gboolean exclusive,
319                             guint perm,
320                             int priority,
321                             GnomeVFSAsyncOpenCallback callback,
322                             gpointer callback_data)
323 {
324         g_return_if_fail (handle_return != NULL);
325         g_return_if_fail (uri != NULL);
326         g_return_if_fail (callback != NULL);
327         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
328         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
329
330         *handle_return = async_create (uri, open_mode, exclusive, perm,
331                                        priority, callback, callback_data);
332 }
333
334 /**
335  * gnome_vfs_async_create:
336  * @handle_return: A pointer to a pointer to a GnomeVFSHandle object
337  * @text_uri: String representing the URI to create
338  * @open_mode: mode to leave the file opened in after creation (or %GNOME_VFS_OPEN_MODE_NONE
339  * to leave the file closed after creation)
340  * @exclusive: Whether the file should be created in "exclusive" mode:
341  * i.e. if this flag is nonzero, operation will fail if a file with the
342  * same name already exists.
343  * @perm: Bitmap representing the permissions for the newly created file
344  * (Unix style).
345  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
346  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
347  * in allocating threads from the thread pool.
348  * @callback: function to be called when the operation is complete
349  * @callback_data: data to pass @callback
350  * 
351  * Create a file at @uri according to mode @open_mode, with permissions @perm (in
352  * the standard UNIX packed bit permissions format). When the create has been completed
353  * @callback will be called with the result code and @callback_data.
354  **/
355 void
356 gnome_vfs_async_create (GnomeVFSAsyncHandle **handle_return,
357                         const gchar *text_uri,
358                         GnomeVFSOpenMode open_mode,
359                         gboolean exclusive,
360                         guint perm,
361                         int priority,
362                         GnomeVFSAsyncOpenCallback callback,
363                         gpointer callback_data)
364 {
365         GnomeVFSURI *uri;
366
367         g_return_if_fail (handle_return != NULL);
368         g_return_if_fail (text_uri != NULL);
369         g_return_if_fail (callback != NULL);
370         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
371         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
372
373         uri = gnome_vfs_uri_new (text_uri);
374         *handle_return = async_create (uri, open_mode, exclusive, perm,
375                                        priority, callback, callback_data);
376         if (uri != NULL) {
377                 gnome_vfs_uri_unref (uri);
378         }
379 }
380
381 /**
382  * gnome_vfs_async_create_as_channel:
383  * @handle_return: A pointer to a pointer to a GnomeVFSHandle object
384  * @text_uri: string of the URI to open as a #GIOChannel, creating it as necessary
385  * @open_mode: open for reading, writing, random, etc
386  * @exclusive: replace the file if it already exists
387  * @perm: standard POSIX-style permissions bitmask, permissions of created file
388  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
389  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
390  * in allocating threads from the thread pool.
391  * @callback: function to be called when the operation is complete
392  * @callback_data: data to pass @callback
393  *
394  * Open @text_uri as a #GIOChannel, creating it as necessary. Once the channel has 
395  * been established @callback will be called with @callback_data, the result of the 
396  * operation, and if the result was %GNOME_VFS_OK, a reference to a #GIOChannel pointing
397  * at @text_uri in @open_mode.
398  **/
399 void
400 gnome_vfs_async_create_as_channel (GnomeVFSAsyncHandle **handle_return,
401                                    const gchar *text_uri,
402                                    GnomeVFSOpenMode open_mode,
403                                    gboolean exclusive,
404                                    guint perm,
405                                    int priority,
406                                    GnomeVFSAsyncOpenAsChannelCallback callback,
407                                    gpointer callback_data)
408 {
409         GnomeVFSJob *job;
410         GnomeVFSCreateAsChannelOp *create_as_channel_op;
411         GnomeVFSAsyncHandle *result;
412
413         g_return_if_fail (handle_return != NULL);
414         g_return_if_fail (text_uri != NULL);
415         g_return_if_fail (callback != NULL);
416         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
417         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
418
419         job = _gnome_vfs_job_new (GNOME_VFS_OP_CREATE_AS_CHANNEL, priority, (GFunc) callback, callback_data);
420
421
422         create_as_channel_op = &job->op->specifics.create_as_channel;
423         create_as_channel_op->uri = gnome_vfs_uri_new (text_uri);
424         create_as_channel_op->open_mode = open_mode;
425         create_as_channel_op->exclusive = exclusive;
426         create_as_channel_op->perm = perm;
427
428         result = job->job_handle;
429         _gnome_vfs_job_go (job);
430 }
431
432 /**
433  * gnome_vfs_async_close:
434  * @handle: async handle to close
435  * @callback: function to be called when the operation is complete
436  * @callback_data: data to pass @callback
437  *
438  * Close a handle opened with gnome_vfs_async_open(). When the close
439  * has completed, @callback will be called with @callback_data and
440  * the result of the operation.
441  **/
442 void
443 gnome_vfs_async_close (GnomeVFSAsyncHandle *handle,
444                        GnomeVFSAsyncCloseCallback callback,
445                        gpointer callback_data)
446 {
447         GnomeVFSJob *job;
448
449         g_return_if_fail (handle != NULL);
450         g_return_if_fail (callback != NULL);
451
452         for (;;) {
453                 _gnome_vfs_async_job_map_lock ();
454                 job = _gnome_vfs_async_job_map_get_job (handle);
455                 if (job == NULL) {
456                         g_warning ("trying to read a non-existing handle");
457                         _gnome_vfs_async_job_map_unlock ();
458                         return;
459                 }
460
461                 if (job->op->type != GNOME_VFS_OP_READ &&
462                     job->op->type != GNOME_VFS_OP_WRITE) {
463                         _gnome_vfs_job_set (job, GNOME_VFS_OP_CLOSE,
464                                            (GFunc) callback, callback_data);
465                         _gnome_vfs_job_go (job);
466                         _gnome_vfs_async_job_map_unlock ();
467                         return;
468                 }
469                 /* Still reading, wait a bit, cancel should be pending.
470                  * This mostly handles a race condition that can happen
471                  * on a dual CPU machine where a cancel stops a read before
472                  * the read thread picks up and a close then gets scheduled
473                  * on a new thread. Without this the job op type would be
474                  * close for both threads and two closes would get executed
475                  */
476                 _gnome_vfs_async_job_map_unlock ();
477                 usleep (100);
478         }
479 }
480
481 /**
482  * gnome_vfs_async_read:
483  * @handle: handle for the file to be read
484  * @buffer: allocated block of memory to read into
485  * @bytes: number of bytes to read
486  * @callback: function to be called when the operation is complete
487  * @callback_data: data to pass @callback
488  * 
489  * Read @bytes bytes from the file pointed to be @handle into @buffer.
490  * When the operation is complete, @callback will be called with the
491  * result of the operation and @callback_data.
492  **/
493 void
494 gnome_vfs_async_read (GnomeVFSAsyncHandle *handle,
495                       gpointer buffer,
496                       guint bytes,
497                       GnomeVFSAsyncReadCallback callback,
498                       gpointer callback_data)
499 {
500         GnomeVFSJob *job;
501         GnomeVFSReadOp *read_op;
502
503         g_return_if_fail (handle != NULL);
504         g_return_if_fail (buffer != NULL);
505         g_return_if_fail (callback != NULL);
506
507         _gnome_vfs_async_job_map_lock ();
508         job = _gnome_vfs_async_job_map_get_job (handle);
509         if (job == NULL) {
510                 g_warning ("trying to read from a non-existing handle");
511                 _gnome_vfs_async_job_map_unlock ();
512                 return;
513         }
514
515         _gnome_vfs_job_set (job, GNOME_VFS_OP_READ,
516                            (GFunc) callback, callback_data);
517
518         read_op = &job->op->specifics.read;
519         read_op->buffer = buffer;
520         read_op->num_bytes = bytes;
521
522         _gnome_vfs_job_go (job);
523         _gnome_vfs_async_job_map_unlock ();
524 }
525
526 /**
527  * gnome_vfs_async_write:
528  * @handle: handle for the file to be written
529  * @buffer: block of memory containing data to be written
530  * @bytes: number of bytes to write
531  * @callback: function to be called when the operation is complete
532  * @callback_data: data to pass @callback
533  * 
534  * Write @bytes bytes from @buffer into the file pointed to be @handle.
535  * When the operation is complete, @callback will be called with the
536  * result of the operation and @callback_data.
537  **/
538 void
539 gnome_vfs_async_write (GnomeVFSAsyncHandle *handle,
540                        gconstpointer buffer,
541                        guint bytes,
542                        GnomeVFSAsyncWriteCallback callback,
543                        gpointer callback_data)
544 {
545         GnomeVFSJob *job;
546         GnomeVFSWriteOp *write_op;
547
548         g_return_if_fail (handle != NULL);
549         g_return_if_fail (buffer != NULL);
550         g_return_if_fail (callback != NULL);
551
552         _gnome_vfs_async_job_map_lock ();
553         job = _gnome_vfs_async_job_map_get_job (handle);
554         if (job == NULL) {
555                 g_warning ("trying to write to a non-existing handle");
556                 _gnome_vfs_async_job_map_unlock ();
557                 return;
558         }
559
560         _gnome_vfs_job_set (job, GNOME_VFS_OP_WRITE,
561                            (GFunc) callback, callback_data);
562
563         write_op = &job->op->specifics.write;
564         write_op->buffer = buffer;
565         write_op->num_bytes = bytes;
566
567         _gnome_vfs_job_go (job);
568         _gnome_vfs_async_job_map_unlock ();
569 }
570
571 /**
572  * gnome_vfs_async_create_symbolic_link:
573  * @handle_return: when the function returns will point to a handle for
574  * the async operation.
575  * @uri: location to create the link at
576  * @uri_reference: location to point @uri to (can be a URI fragment, i.e. relative)
577  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
578  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
579  * in allocating threads from the thread pool.
580  * @callback: function to be called when the operation is complete
581  * @callback_data: data to pass @callback
582  * 
583  * Create a symbolic link at @uri pointing to @uri_reference. When the operation
584  * has complete @callback will be called with the result of the operation and
585  * @callback_data.
586  **/
587 void
588 gnome_vfs_async_create_symbolic_link (GnomeVFSAsyncHandle **handle_return,
589                                       GnomeVFSURI *uri,
590                                       const gchar *uri_reference,
591                                       int priority,
592                                       GnomeVFSAsyncOpenCallback callback,
593                                       gpointer callback_data)
594 {
595         GnomeVFSJob *job;
596         GnomeVFSCreateLinkOp *create_op;
597
598         g_return_if_fail (handle_return != NULL);
599         g_return_if_fail (uri != NULL);
600         g_return_if_fail (callback != NULL);
601         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
602         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
603
604         job = _gnome_vfs_job_new (GNOME_VFS_OP_CREATE_SYMBOLIC_LINK, priority, (GFunc) callback, callback_data);
605
606         create_op = &job->op->specifics.create_symbolic_link;
607         create_op->uri = gnome_vfs_uri_ref (uri);
608         create_op->uri_reference = g_strdup (uri_reference);
609
610         *handle_return = job->job_handle;
611         _gnome_vfs_job_go (job);
612 }
613
614 /**
615  * gnome_vfs_async_get_file_info:
616  * @handle_return: when the function returns will point to a handle for
617  * the async operation.
618  * @uri_list: a GList of GnomeVFSURIs to fetch information about
619  * @options: packed boolean type providing control over various details
620  * of the get_file_info operation.
621  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
622  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
623  * in allocating threads from the thread pool.
624  * @callback: function to be called when the operation is complete
625  * @callback_data: data to pass @callback
626  * 
627  * Fetch information about the files indicated in @uris and return the
628  * information progressively to @callback.
629  **/
630 void
631 gnome_vfs_async_get_file_info (GnomeVFSAsyncHandle **handle_return,
632                                GList *uri_list,
633                                GnomeVFSFileInfoOptions options,
634                                int priority,
635                                GnomeVFSAsyncGetFileInfoCallback callback,
636                                gpointer callback_data)
637 {
638         GnomeVFSJob *job;
639         GnomeVFSGetFileInfoOp *get_info_op;
640
641         g_return_if_fail (handle_return != NULL);
642         g_return_if_fail (callback != NULL);
643         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
644         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
645
646         job = _gnome_vfs_job_new (GNOME_VFS_OP_GET_FILE_INFO, priority, (GFunc) callback, callback_data);
647
648         get_info_op = &job->op->specifics.get_file_info;
649
650         get_info_op->uris = gnome_vfs_uri_list_copy (uri_list);
651         get_info_op->options = options;
652
653         *handle_return = job->job_handle;
654         _gnome_vfs_job_go (job);
655 }
656
657 /**
658  * gnome_vfs_async_set_file_info:
659  * @handle_return: when the function returns will point to a handle for
660  * the async operation.
661  * @uri: the URI to set the file info of
662  * @info: the struct containing new information about the file
663  * @mask: control which fields of @info are changed about the file at @uri
664  * @options: packed boolean type providing control over various details
665  * of the set_file_info operation.
666  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
667  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
668  * in allocating threads from the thread pool.
669  * @callback: function to be called when the operation is complete
670  * @callback_data: data to pass @callback
671  * 
672  * Set "file info" details about the file at @uri, such as permissions, name,
673  * owner, and modification time.
674  **/
675 void
676 gnome_vfs_async_set_file_info (GnomeVFSAsyncHandle **handle_return,
677                                GnomeVFSURI *uri,
678                                GnomeVFSFileInfo *info,
679                                GnomeVFSSetFileInfoMask mask,
680                                GnomeVFSFileInfoOptions options,
681                                int priority,
682                                GnomeVFSAsyncSetFileInfoCallback callback,
683                                gpointer callback_data)
684 {
685         GnomeVFSJob *job;
686         GnomeVFSSetFileInfoOp *op;
687
688         g_return_if_fail (handle_return != NULL);
689         g_return_if_fail (uri != NULL);
690         g_return_if_fail (info != NULL);
691         g_return_if_fail (callback != NULL);
692         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
693         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
694
695         job = _gnome_vfs_job_new (GNOME_VFS_OP_SET_FILE_INFO, priority, (GFunc) callback, callback_data);
696
697         op = &job->op->specifics.set_file_info;
698
699         op->uri = gnome_vfs_uri_ref (uri);
700         op->info = gnome_vfs_file_info_new ();
701         gnome_vfs_file_info_copy (op->info, info);
702         op->mask = mask;
703         op->options = options;
704
705         *handle_return = job->job_handle;
706         _gnome_vfs_job_go (job);
707 }
708
709 /**
710  * gnome_vfs_async_find_directory:
711  * @handle_return: when the function returns will point to a handle for
712  * @near_uri_list: a GList of GnomeVFSURIs, find a special directory on the same 
713  * volume as @uris
714  * @kind: kind of special directory
715  * @create_if_needed: If directory we are looking for does not exist, try to create it
716  * @find_if_needed: If we don't know where the directory is yet, look for it.
717  * @permissions: If creating, use these permissions
718  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
719  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
720  * in allocating threads from the thread pool.
721  * @callback: function to be called when the operation is complete
722  * @user_data: data to pass @callback * 
723  * Used to return special directories such as Trash and Desktop from different
724  * file systems.
725  * 
726  * There is quite a complicated logic behind finding/creating a Trash directory
727  * and you need to be aware of some implications:
728  * Finding the Trash the first time when using the file method may be pretty 
729  * expensive. A cache file is used to store the location of that Trash file
730  * for next time.
731  * If @ceate_if_needed is specified without @find_if_needed, you may end up
732  * creating a Trash file when there already is one. Your app should start out
733  * by doing a gnome_vfs_find_directory with the @find_if_needed to avoid this
734  * and then use the @create_if_needed flag to create Trash lazily when it is
735  * needed for throwing away an item on a given disk.
736  * 
737  * When the operation has completed, @callback will be called with the result
738  * of the operation and @user_data.
739  **/
740 void
741 gnome_vfs_async_find_directory (GnomeVFSAsyncHandle **handle_return,
742                                 GList *near_uri_list,
743                                 GnomeVFSFindDirectoryKind kind,
744                                 gboolean create_if_needed,
745                                 gboolean find_if_needed,
746                                 guint permissions,
747                                 int priority,
748                                 GnomeVFSAsyncFindDirectoryCallback callback,
749                                 gpointer user_data)
750 {
751         GnomeVFSJob *job;
752         GnomeVFSFindDirectoryOp *get_info_op;
753
754         g_return_if_fail (handle_return != NULL);
755         g_return_if_fail (callback != NULL);
756         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
757         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
758
759         job = _gnome_vfs_job_new (GNOME_VFS_OP_FIND_DIRECTORY, priority, (GFunc) callback, user_data);
760
761         get_info_op = &job->op->specifics.find_directory;
762
763         get_info_op->uris = gnome_vfs_uri_list_copy (near_uri_list);
764         get_info_op->kind = kind;
765         get_info_op->create_if_needed = create_if_needed;
766         get_info_op->find_if_needed = find_if_needed;
767         get_info_op->permissions = permissions;
768
769         *handle_return = job->job_handle;
770         _gnome_vfs_job_go (job);
771 }
772
773 static GnomeVFSAsyncHandle *
774 async_load_directory (GnomeVFSURI *uri,
775                       GnomeVFSFileInfoOptions options,
776                       guint items_per_notification,
777                       int priority,
778                       GnomeVFSAsyncDirectoryLoadCallback callback,
779                       gpointer callback_data)
780 {
781         GnomeVFSJob *job;
782         GnomeVFSLoadDirectoryOp *load_directory_op;
783         GnomeVFSAsyncHandle *result;
784
785         job = _gnome_vfs_job_new (GNOME_VFS_OP_LOAD_DIRECTORY, priority, (GFunc) callback, callback_data);
786
787         load_directory_op = &job->op->specifics.load_directory;
788         load_directory_op->uri = uri == NULL ? NULL : gnome_vfs_uri_ref (uri);
789         load_directory_op->options = options;
790         load_directory_op->items_per_notification = items_per_notification;
791
792         result = job->job_handle;
793         _gnome_vfs_job_go (job);
794
795         return result;
796 }
797
798
799
800 /**
801  * gnome_vfs_async_load_directory:
802  * @handle_return: when the function returns will point to a handle for
803  * the async operation.
804  * @text_uri: string representing the URI of the directory to be loaded
805  * @options: packed boolean type providing control over various details
806  * of the get_file_info operation.
807  * @items_per_notification: number of files to process in a row before calling @callback
808  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
809  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
810  * in allocating threads from the thread pool.
811  * @callback: function to be called when the operation is complete
812  * @callback_data: data to pass @callback
813  * 
814  * Read the contents of the directory at @text_uri, passing back GnomeVFSFileInfo 
815  * structs about each file in the directory to @callback. @items_per_notification
816  * files will be processed between each call to @callback.
817  **/
818 void
819 gnome_vfs_async_load_directory (GnomeVFSAsyncHandle **handle_return,
820                                 const gchar *text_uri,
821                                 GnomeVFSFileInfoOptions options,
822                                 guint items_per_notification,
823                                 int priority,
824                                 GnomeVFSAsyncDirectoryLoadCallback callback,
825                                 gpointer callback_data)
826 {
827         GnomeVFSURI *uri;
828
829         g_return_if_fail (handle_return != NULL);
830         g_return_if_fail (text_uri != NULL);
831         g_return_if_fail (callback != NULL);
832         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
833         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
834
835         uri = gnome_vfs_uri_new (text_uri);
836         *handle_return = async_load_directory (uri, options,
837                                                items_per_notification,
838                                                priority,
839                                                callback, callback_data);
840         if (uri != NULL) {
841                 gnome_vfs_uri_unref (uri);
842         }
843 }
844
845 /**
846  * gnome_vfs_async_load_directory_uri:
847  * @handle_return: when the function returns will point to a handle for
848  * the async operation.
849  * @uri: string representing the URI of the directory to be loaded
850  * @options: packed boolean type providing control over various details
851  * of the get_file_info operation.
852  * @items_per_notification: number of files to process in a row before calling @callback
853  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
854  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
855  * in allocating threads from the thread pool.
856  * @callback: function to be called when the operation is complete
857  * @callback_data: data to pass @callback
858  * 
859  * Read the contents of the directory at @uri, passing back GnomeVFSFileInfo structs
860  * about each file in the directory to @callback. @items_per_notification
861  * files will be processed between each call to @callback.
862  **/
863 void
864 gnome_vfs_async_load_directory_uri (GnomeVFSAsyncHandle **handle_return,
865                                     GnomeVFSURI *uri,
866                                     GnomeVFSFileInfoOptions options,
867                                     guint items_per_notification,
868                                     int priority,
869                                     GnomeVFSAsyncDirectoryLoadCallback callback,
870                                     gpointer callback_data)
871 {
872         g_return_if_fail (handle_return != NULL);
873         g_return_if_fail (uri != NULL);
874         g_return_if_fail (callback != NULL);
875         g_return_if_fail (priority >= GNOME_VFS_PRIORITY_MIN);
876         g_return_if_fail (priority <= GNOME_VFS_PRIORITY_MAX);
877
878         *handle_return = async_load_directory (uri, options,
879                                                items_per_notification,
880                                                priority,
881                                                callback, callback_data);
882 }
883
884 /**
885  * gnome_vfs_async_xfer:
886  * @handle_return: when the function returns will point to a handle for
887  * @source_uri_list: #GList of #GnomeVFSURI representing the files to be transferred
888  * @target_uri_list: #GList of #GnomeVFSURI, the target locations for the elements
889  * in @source_uri_list
890  * @xfer_options: various options controlling the details of the transfer. 
891  * Use %GNOME_VFS_XFER_REMOUVESOURCE to make the operation a move rather than a copy.
892  * @error_mode: report errors to the @progress_sync_callback, or simply abort
893  * @overwrite_mode: controls whether the xfer engine will overwrite automatically, 
894  * skip the file, abort the operation, or query @progress_sync_callback
895  * @priority: a value from %GNOME_VFS_PRIORITY_MIN to %GNOME_VFS_PRIORITY_MAX (normally
896  * should be %GNOME_VFS_PRIORITY_DEFAULT) indicating the priority to assign this job
897  * in allocating threads from the thread pool.
898  * @progress_update_callback: called periodically to keep the client appraised of progress
899  * in completing the XFer operation, and the current phase of operation.
900  * @update_callback_data: user data passed to @progress_update_callback
901  * @progress_sync_callback: called when the program requires responses to interactive queries
902  * (e.g. overwriting files, handling errors, etc)
903  * @sync_callback_data: user data passed to @progress_sync_callback
904  *
905  * Perform a copy operation in a seperate thread. @progress_update_callback will be periodically
906  * polled with status of the operation (percent done, the current phase of operation, the
907  * current file being operated upon). If the xfer engine needs to query the caller to make
908  * a decision or report on important error it will do so on @progress_sync_callback.
909  *
910  * Return value: %GNOME_VFS_OK if the paramaters were in order, 
911  * or %GNOME_VFS_ERROR_BAD_PARAMETERS if something was wrong in the passed in arguments.
912  **/
913 GnomeVFSResult
914 gnome_vfs_async_xfer (GnomeVFSAsyncHandle **handle_return,
915                       GList *source_uri_list,
916                       GList *target_uri_list,
917                       GnomeVFSXferOptions xfer_options,
918                       GnomeVFSXferErrorMode error_mode,
919                       GnomeVFSXferOverwriteMode overwrite_mode,
920                       int priority,
921                       GnomeVFSAsyncXferProgressCallback progress_update_callback,
922                       gpointer update_callback_data,
923                       GnomeVFSXferProgressCallback progress_sync_callback,
924                       gpointer sync_callback_data)
925 {
926         GnomeVFSJob *job;
927         GnomeVFSXferOp *xfer_op;
928
929         g_return_val_if_fail (handle_return != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
930         g_return_val_if_fail (progress_update_callback != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
931         g_return_val_if_fail (priority >= GNOME_VFS_PRIORITY_MIN, GNOME_VFS_ERROR_BAD_PARAMETERS);
932         g_return_val_if_fail (priority <= GNOME_VFS_PRIORITY_MAX, GNOME_VFS_ERROR_BAD_PARAMETERS);
933
934         job = _gnome_vfs_job_new (GNOME_VFS_OP_XFER,
935                                  priority, 
936                                  (GFunc) progress_update_callback,
937                                  update_callback_data);
938
939
940         xfer_op = &job->op->specifics.xfer;
941         xfer_op->source_uri_list = gnome_vfs_uri_list_copy (source_uri_list);
942         xfer_op->target_uri_list = gnome_vfs_uri_list_copy (target_uri_list);
943         xfer_op->xfer_options = xfer_options;
944         xfer_op->error_mode = error_mode;
945         xfer_op->overwrite_mode = overwrite_mode;
946         xfer_op->progress_sync_callback = progress_sync_callback;
947         xfer_op->sync_callback_data = sync_callback_data;
948
949         *handle_return = job->job_handle;
950         _gnome_vfs_job_go (job);
951
952         return GNOME_VFS_OK;
953 }
954
955 /**
956  * gnome_vfs_async_file_control:
957  * @handle: handle of the file to affect
958  * @operation: The operation to execute
959  * @operation_data: The data needed to execute the operation
960  * @operation_data_destroy_func: Called to destroy operation_data when its no longer needed
961  * @callback: function to be called when the operation is complete
962  * @callback_data: data to pass @callback
963  * 
964  * Execute a backend dependent operation specified by the string @operation.
965  * This is typically used for specialized vfs backends that need additional
966  * operations that gnome-vfs doesn't have. Compare it to the unix call ioctl().
967  * The format of @operation_data depends on the operation. Operation that are
968  * backend specific are normally namespaced by their module name.
969  *
970  * When the operation is complete, @callback will be called with the
971  * result of the operation, @operation_data and @callback_data.
972  *
973  * Since: 2.2
974  **/
975 void
976 gnome_vfs_async_file_control (GnomeVFSAsyncHandle *handle,
977                               const char *operation,
978                               gpointer operation_data,
979                               GDestroyNotify operation_data_destroy_func,
980                               GnomeVFSAsyncFileControlCallback callback,
981                               gpointer callback_data)
982 {
983         GnomeVFSJob *job;
984         GnomeVFSFileControlOp *file_control_op;
985
986         g_return_if_fail (handle != NULL);
987         g_return_if_fail (operation != NULL);
988         g_return_if_fail (callback != NULL);
989
990         _gnome_vfs_async_job_map_lock ();
991         job = _gnome_vfs_async_job_map_get_job (handle);
992         if (job == NULL) {
993                 g_warning ("trying to call file_control on a non-existing handle");
994                 _gnome_vfs_async_job_map_unlock ();
995                 return;
996         }
997
998         _gnome_vfs_job_set (job, GNOME_VFS_OP_FILE_CONTROL,
999                            (GFunc) callback, callback_data);
1000
1001         file_control_op = &job->op->specifics.file_control;
1002         file_control_op->operation = g_strdup (operation);
1003         file_control_op->operation_data = operation_data;
1004         file_control_op->operation_data_destroy_func = operation_data_destroy_func;
1005
1006         _gnome_vfs_job_go (job);
1007         _gnome_vfs_async_job_map_unlock ();
1008 }
1009
1010 #ifdef OLD_CONTEXT_DEPRECATED
1011
1012 guint
1013 gnome_vfs_async_add_status_callback (GnomeVFSAsyncHandle *handle,
1014                                      GnomeVFSStatusCallback callback,
1015                                      gpointer user_data)
1016 {
1017         GnomeVFSJob *job;
1018         guint result;
1019         
1020         g_return_val_if_fail (handle != NULL, 0);
1021         g_return_val_if_fail (callback != NULL, 0);
1022
1023         _gnome_vfs_async_job_map_lock ();
1024         job = _gnome_vfs_async_job_map_get_job (handle);
1025
1026         if (job->op != NULL || job->op->context != NULL) {
1027                 g_warning ("job or context not found");
1028                 _gnome_vfs_async_job_map_unlock ();
1029                 return 0;
1030         }
1031
1032         result = gnome_vfs_message_callbacks_add
1033                 (gnome_vfs_context_get_message_callbacks (job->op->context),
1034                  callback, user_data);
1035         _gnome_vfs_async_job_map_unlock ();
1036         
1037         return result;
1038 }
1039
1040 void
1041 gnome_vfs_async_remove_status_callback (GnomeVFSAsyncHandle *handle,
1042                                         guint callback_id)
1043 {
1044         GnomeVFSJob *job;
1045
1046         g_return_if_fail (handle != NULL);
1047         g_return_if_fail (callback_id > 0);
1048
1049         _gnome_vfs_async_job_map_lock ();
1050         job = _gnome_vfs_async_job_map_get_job (handle);
1051
1052         if (job->op != NULL || job->op->context != NULL) {
1053                 g_warning ("job or context not found");
1054                 _gnome_vfs_async_job_map_unlock ();
1055                 return;
1056         }
1057
1058         gnome_vfs_message_callbacks_remove
1059                 (gnome_vfs_context_get_message_callbacks (job->op->context),
1060                  callback_id);
1061
1062         _gnome_vfs_async_job_map_unlock ();
1063 }
1064
1065 #endif /* OLD_CONTEXT_DEPRECATED */