Moved 1.9 branch to trunk
[gnupg.git] / g10 / progress.c
1 /* progress.c - emit progress status lines
2  * Copyright (C) 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24
25 #include "gpg.h"
26 #include "iobuf.h"
27 #include "filter.h"
28 #include "status.h"
29 #include "util.h"
30 #include "options.h"
31
32 /****************
33  * The filter is used to report progress to the user.
34  */
35 int
36 progress_filter (void *opaque, int control,
37                  IOBUF a, byte *buf, size_t *ret_len)
38 {
39   int rc = 0;
40   progress_filter_context_t *pfx = opaque;
41
42   if (control == IOBUFCTRL_INIT)
43     {
44       char buffer[50];
45
46       pfx->last = 0;
47       pfx->offset = 0;
48       pfx->last_time = make_timestamp ();
49
50       sprintf (buffer, "%.20s ? %lu %lu",
51                pfx->what? pfx->what : "?",
52                pfx->offset,
53                pfx->total);
54       write_status_text (STATUS_PROGRESS, buffer);
55     }
56   else if (control == IOBUFCTRL_UNDERFLOW)
57     {
58       u32 timestamp = make_timestamp ();
59       int len = iobuf_read (a, buf, *ret_len);
60
61       if (len >= 0)
62         {
63           pfx->offset += len;
64           *ret_len = len;
65         }
66       else
67         {
68           *ret_len = 0;
69           rc = -1;
70         }
71       if ((len == -1 && pfx->offset != pfx->last)
72           || timestamp - pfx->last_time > 0)
73         {
74           char buffer[50];
75           
76           sprintf (buffer, "%.20s ? %lu %lu",
77                    pfx->what? pfx->what : "?", 
78                    pfx->offset,
79                    pfx->total);
80           write_status_text (STATUS_PROGRESS, buffer);
81
82           pfx->last = pfx->offset;
83           pfx->last_time = timestamp;
84         }
85     }
86   else if (control == IOBUFCTRL_FREE)
87     {
88       /* Note, that we must always dealloc resources of a filter
89          within the filter handler and not anywhere else.  (We set it
90          to NULL and check all uses just in case.) */
91       xfree (pfx->what);
92       pfx->what = NULL;
93     }
94   else if (control == IOBUFCTRL_DESC)
95     *(char**)buf = "progress_filter";
96   return rc;
97 }
98
99 void
100 handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
101 {
102   off_t filesize = 0;
103
104   if (!opt.enable_progress_filter)
105     return;
106
107   if (!is_status_enabled ())
108     return;
109
110   if ( !iobuf_is_pipe_filename (name) && *name )
111     filesize = iobuf_get_filelength (inp, NULL);
112   else if (opt.set_filesize)
113     filesize = opt.set_filesize;
114
115   /* register the progress filter */
116   pfx->what = xstrdup (name ? name : "stdin");
117   pfx->total = filesize;
118   iobuf_push_filter (inp, progress_filter, pfx);
119 }