Imported Upstream version 2.4.5
[debian/amanda] / client-src / amqde.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1999 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: amqde.c,v 1.1.2.1.2.1 2004/08/05 11:35:35 martinea Exp $
28  *
29  * the central header file included by all amanda sources
30  */
31
32 #include "amanda.h"
33
34 /*
35  * amanda's version of things.
36  */
37 #define emalloc alloc
38 #define estrdup stralloc
39
40 #ifdef USE_STRHASH
41 hash_table *parse_exclude_path(char *, char *);
42 int should_exclude(hash_table * hash, char *path);
43
44 #endif
45
46 typedef struct __dirtrax {
47         char *dirname;
48         struct __dirtrax *next;
49 }         dirtrax_t;
50
51 typedef struct __diretrax_track_ll {
52         dirtrax_t *first, *last;
53 }                   dirtrax_ll_t;
54
55 int
56 main(argc, argv)
57         int argc;
58         char *argv[];
59 {
60         extern char *optarg;
61         extern int optind;
62
63         int ch;
64         char buf[8192];
65         struct stat top, st;
66         char *path;
67         time_t since = 0;
68         DIR *d;
69         struct dirent *de;
70 #ifdef HAVE_UNSIGNED_LONG_LONG
71         unsigned long long total = 0;
72 #else
73         unsigned long total = 0;
74 #endif
75         dirtrax_ll_t ll;
76         dirtrax_t *trax = NULL, *new, *c;
77         char *exclude_path = NULL;
78         int havesince = 0;
79
80 #ifdef USE_STRHASH
81         hash_table *hash = NULL;
82
83 #endif
84
85         while ((ch = getopt(argc, argv, "s:x:")) != EOF) {
86                 switch (ch) {
87                 case 's':
88                         since = atoi(optarg);
89                         havesince = 1;
90                         break;
91                 case 'x':
92                         exit(0);
93                         exclude_path = (optarg);
94                         break;
95                 default:
96                         fprintf(stderr, "unknown argument \'%c\'", ch);
97                         exit(1);
98                 }
99         }
100
101         argc -= optind;
102         argv += optind;
103
104         if (argc == 0) {
105                 fprintf(stderr, "must specify a path to dump\n");
106                 exit(1);
107         }
108         if (!havesince) {
109                 fprintf(stderr, "must specify -s\n");
110                 exit(1);
111         }
112         path = argv[0];
113
114 #ifdef USE_STRHASH
115         if (exclude_path)
116                 hash = parse_exclude_path(path, exclude_path);
117 #endif
118
119         if (chdir(path) != 0) {
120                 fprintf(stderr, "could not chdir to %s\n", path);
121                 exit(1);
122         }
123         if (lstat(".", &top) != 0) {
124                 fprintf(stderr, "could not stat %s\n", path);
125                 exit(1);
126         }
127         trax = emalloc(sizeof(*trax));
128         trax->dirname = estrdup(".");
129         trax->next = NULL;
130
131         ll.first = ll.last = trax;
132
133         for (new = ll.first; new; new = ll.first) {
134                 if (!(d = opendir(new->dirname))) {
135                         goto forcleanup;        /* basically continue; */
136                 }
137                 /*
138                  * skip directories if we cross a device
139                  */
140                 if (lstat(new->dirname, &st) != 0)
141                         goto forwclosedircleanup;
142                 if (top.st_dev != st.st_dev || top.st_rdev != st.st_rdev)
143                         goto forwclosedircleanup;
144
145                 while ((de = readdir(d))) {
146                         total += 505;
147                         if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
148                                 continue;
149
150                         ap_snprintf(buf, sizeof(buf) - 1, "%s/%s", new->dirname, de->d_name);
151
152 #ifdef USE_STRHASH
153                         if (should_exclude(hash, buf))
154                                 continue;
155 #endif
156
157                         if (lstat(buf, &st) != 0)
158                                 continue;
159
160                         if (S_ISDIR(st.st_mode)) {
161                                 c = emalloc(sizeof(*c));
162                                 c->dirname = estrdup(buf);
163                                 c->next = NULL;
164                                 ll.last->next = c;
165                                 ll.last = c;
166                         } else {
167                                 if (st.st_mtime < since && st.st_ctime < since)
168                                         continue;
169                                 if ((st.st_blocks * 512) < st.st_size)
170                                         total += (st.st_blocks * 512);
171                                 else
172                                         total += st.st_size;
173                                 /*
174                                  * add in some overhead, these are estimates
175                                  * after all
176                                  */
177                                 total += 505;
178                         }
179                 }
180 forwclosedircleanup:
181                 closedir(d);
182 forcleanup:
183                 ll.first = new->next;
184                 free(new->dirname);
185                 free(new);
186         }
187
188         /*
189          * This is dumped out in k so upstream utilies can handle it without
190          * having to handle unsigned long long.  The theory is that if you
191          * need to use these estimates, then you proably have a system that
192          * uses long long.
193          */
194
195 #ifdef HAVE_UNSIGNED_LONG_LONG
196         fprintf(stderr, "amqde estimate: %llu kb\n", total/1024);
197 #else
198         fprintf(stderr, "amqde estimate: %lu kb\n", total/1024);
199 #endif
200         chdir("/");
201
202         return (0);
203 }
204
205 /*
206  * at the moment, we don't actually parse the include file because it means
207  * implementing globbing, which is a pain in the arse.
208  *
209  * This is quick and dirty, after all.
210  */
211 #ifdef USE_STRHASH
212 hash_table *
213 parse_exclude_path(rootpath, infile)
214         char *rootpath;
215         char *infile;
216 {
217         FILE *f;
218         char buf[4096];
219         hash_table *hash;
220
221         return (NULL);
222 }
223
224 int
225 should_exclude(hash, path)
226         hash_table *hash;
227         char *path;
228 {
229         return (0);
230 }
231
232 #endif