Imported Upstream version 2.5.2p1
[debian/amanda] / server-src / amcleanupdisk.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 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: amcleanupdisk.c,v 1.22 2006/07/25 18:27:57 martinea Exp $
28  */
29 #include "amanda.h"
30
31 #include "conffile.h"
32 #include "diskfile.h"
33 #include "clock.h"
34 #include "version.h"
35 #include "holding.h"
36 #include "infofile.h"
37 #include "server_util.h"
38
39 sl_t *holding_list;
40 char *datestamp;
41
42 /* local functions */
43 int main(int argc, char **argv);
44 void check_holdingdisk(char *diskdir, char *datestamp);
45 void check_disks(void);
46
47 int
48 main(
49     int         main_argc,
50     char **     main_argv)
51 {
52     struct passwd *pw;
53     char *dumpuser;
54     disklist_t diskq;
55     char *conffile;
56     char *conf_diskfile;
57     char *conf_infofile;
58
59     safe_fd(-1, 0);
60     safe_cd();
61
62     set_pname("amcleanupdisk");
63
64     dbopen(DBG_SUBDIR_SERVER);
65
66     /* Don't die when child closes pipe */
67     signal(SIGPIPE, SIG_IGN);
68
69     if(main_argc < 2) {
70         error("Usage: amcleanupdisk%s <config>", versionsuffix());
71         /*NOTREACHED*/
72     }
73
74     config_name = main_argv[1];
75
76     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
77
78     conffile = stralloc2(config_dir, CONFFILE_NAME);
79     if(read_conffile(conffile)) {
80         error("errors processing config file \"%s\"", conffile);
81         /*NOTREACHED*/
82     }
83     amfree(conffile);
84
85     dbrename(config_name, DBG_SUBDIR_SERVER);
86
87     conf_diskfile = getconf_str(CNF_DISKFILE);
88     if (*conf_diskfile == '/') {
89         conf_diskfile = stralloc(conf_diskfile);
90     } else {
91         conf_diskfile = stralloc2(config_dir, conf_diskfile);
92     }
93     if (read_diskfile(conf_diskfile, &diskq) < 0) {
94         error("could not load disklist %s", conf_diskfile);
95         /*NOTREACHED*/
96     }
97     amfree(conf_diskfile);
98
99     conf_infofile = getconf_str(CNF_INFOFILE);
100     if (*conf_infofile == '/') {
101         conf_infofile = stralloc(conf_infofile);
102     } else {
103         conf_infofile = stralloc2(config_dir, conf_infofile);
104     }
105     if (open_infofile(conf_infofile) < 0) {
106         error("could not open info db \"%s\"", conf_infofile);
107         /*NOTREACHED*/
108     }
109     amfree(conf_infofile);
110
111     datestamp = construct_datestamp(NULL);
112
113     dumpuser = getconf_str(CNF_DUMPUSER);
114     if((pw = getpwnam(dumpuser)) == NULL) {
115         error("dumpuser %s not found in password file", dumpuser);
116         /*NOTREACHED*/
117     }
118
119     if(pw->pw_uid != getuid()) {
120         error("must run amcleanupdisk as user %s", dumpuser);
121         /*NOTREACHED*/
122     }
123
124     holding_list = pick_all_datestamp(1);
125
126     check_disks();
127
128     close_infofile();
129
130     free_sl(holding_list);
131     holding_list = NULL;
132     amfree(config_dir);
133     return 0;
134 }
135
136
137 void
138 check_holdingdisk(
139     char *      diskdir,
140     char *      datestamp)
141 {
142     DIR *workdir;
143     struct dirent *entry;
144     char *dirname = NULL;
145     char *tmpname = NULL;
146     char *destname = NULL;
147     char *hostname = NULL;
148     char *diskname = NULL;
149     disk_t *dp;
150     filetype_t filetype;
151     info_t info;
152     int level;
153     size_t dl, l;
154
155     dirname = vstralloc(diskdir, "/", datestamp, NULL);
156     dl = strlen(dirname);
157
158     if((workdir = opendir(dirname)) == NULL) {
159         amfree(dirname);
160         return;
161     }
162
163     while((entry = readdir(workdir)) != NULL) {
164         if(is_dot_or_dotdot(entry->d_name)) {
165             continue;
166         }
167
168         if((l = strlen(entry->d_name)) < 7 ) {
169             continue;
170         }
171
172         if(strncmp(&entry->d_name[l-4],".tmp",4) != 0) {
173             continue;
174         }
175
176         tmpname = newvstralloc(tmpname,
177                                dirname, "/", entry->d_name,
178                                NULL);
179
180         destname = newstralloc(destname, tmpname);
181         destname[dl + 1 + l - 4] = '\0';
182
183         amfree(hostname);
184         amfree(diskname);
185         filetype = holding_file_read_header(tmpname, &hostname, &diskname, &level, NULL);
186         amfree(tmpname);
187         if(filetype != F_DUMPFILE) {
188             continue;
189         }
190
191         dp = lookup_disk(hostname, diskname);
192
193         if (dp == NULL) {
194             continue;
195         }
196
197         if(level < 0 || level > 9) {
198             continue;
199         }
200
201         if(rename_tmp_holding(destname, 0)) {
202             get_info(dp->host->hostname, dp->name, &info);
203             info.command &= ~FORCE_BUMP;
204             info.command |= FORCE_NO_BUMP;
205             if(put_info(dp->host->hostname, dp->name, &info)) {
206                 error("could not put info record for %s:%s: %s",
207                       dp->host->hostname, dp->name, strerror(errno));
208                 /*NOTREACHED*/
209             }
210         } else {
211             fprintf(stderr,"rename_tmp_holding(%s) failed\n", destname);
212         }
213     }
214     closedir(workdir);
215
216     /* try to zap the potentially empty working dir */
217     /* ignore any errors -- it either works or it doesn't */
218     (void) rmdir(dirname);
219
220     amfree(diskname);
221     amfree(hostname);
222     amfree(destname);
223     amfree(dirname);
224 }
225
226
227 void
228 check_disks(void)
229 {
230     holdingdisk_t *hdisk;
231     sle_t *dir;
232
233     for(dir = holding_list->first; dir !=NULL; dir = dir->next) {
234         for(hdisk = getconf_holdingdisks(); hdisk != NULL; hdisk = hdisk->next)
235             check_holdingdisk(holdingdisk_get_diskdir(hdisk), dir->name);
236     }
237 }