merge with 0.30.213
[util-vserver.git] / lib_internal / matchlist-initmanually.c
1 // $Id: matchlist-initmanually.c 1954 2005-03-22 14:59:46Z ensc $    --*- c -*--
2
3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22 #include "pathconfig.h"
23
24 #include "matchlist.h"
25 #include "util-io.h"
26
27 #include <wait.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <string.h>
33
34 #define ENSC_WRAPPERS_UNISTD    1
35 #define ENSC_WRAPPERS_STDLIB    1
36 #define ENSC_WRAPPERS_IO        1
37 #include <wrappers.h>
38
39
40 extern int      Global_getVerbosity() PURE CONST;
41 extern bool     Global_doRenew() PURE CONST;
42
43 static void
44 readExcludeListFD(int fd,
45                   char ***files,  size_t *size,
46                   char **buf)
47 {
48   off_t         len;
49   size_t        lines = 0;
50   char          *ptr;
51   
52   if (fd==-1) return; // todo: message on verbose?
53
54   len = Elseek(fd, 0, SEEK_END);
55   Elseek(fd, 0, SEEK_SET);
56
57   *buf = Emalloc(sizeof(*buf) * (len+1));
58   EreadAll(fd, *buf, len);
59   (*buf)[len] = '\0';
60
61   ptr = *buf;
62   while ((ptr=strchr(ptr, '\n'))) {
63     ++lines;
64     ++ptr;
65   }
66
67   ++lines;
68   *files = Emalloc(sizeof(**files) * lines);
69
70   *size = 0;
71   ptr   = *buf;
72   while (*ptr) {
73     char        *end_ptr = strchr(ptr, '\n');
74
75     assert(*size<lines);
76     if (end_ptr==0) break;
77
78     if (*ptr!='#') {
79       char      *tmp = end_ptr;
80       do {
81         *tmp-- = '\0';
82       } while (tmp>ptr && *tmp==' ');
83       
84       if (tmp>ptr) (*files)[(*size)++] = ptr;
85     }
86
87     ptr = end_ptr+1;
88   }
89 }
90
91 static void
92 readExcludeList(char const *filename,
93                 char ***files,  size_t *size,
94                 char **buf)
95 {
96   int           fd = open(filename, O_RDONLY);
97   if (fd==-1) return; // todo: message on verbose?
98
99   readExcludeListFD(fd, files, size, buf);
100   Eclose(fd);
101 }
102
103 static void
104 getConfigfileList(char const *vserver,
105                   char ***files, size_t *size,
106                   char **buf)
107 {
108   char          tmpname[] = "/tmp/vunify.XXXXXX";
109   pid_t         pid;
110   int           fd = Emkstemp(tmpname);
111
112   Eunlink(tmpname);
113   pid = Efork();
114
115   if (pid==0) {
116     char        *args[10];
117     char const  **ptr = (char const **)(args)+0;
118     
119     Edup2(fd, 1);
120     //Eclose(0);
121     if (fd!=1) Eclose(fd);
122
123     *ptr++  = VPKG_PROG;
124     *ptr++  = vserver;
125     *ptr++  = "get-conffiles";
126     *ptr    = 0;
127
128     Eexecv(args[0], args);
129   }
130   else {
131     int         status;
132     
133     if (TEMP_FAILURE_RETRY(wait4(pid, &status, 0,0))==-1) {
134       perror("wait4()");
135       exit(1);
136     }
137
138     if (!WIFEXITED(status) || WEXITSTATUS(status)!=0) {
139       WRITE_MSG(2, "failed to determine configfiles\n");
140       exit(1);
141     }
142
143     readExcludeListFD(fd, files, size, buf);
144     Eclose(fd);
145   }
146 }
147
148 void
149 MatchList_initManually(struct MatchList *list,
150                        struct MatchVserverInfo const *vserver,
151                        char const *vdir, char const *exclude_file)
152 {
153   char                  *buf[2] = { 0,0 };
154   
155   char                  **fixed_files = 0;
156   size_t                fixed_count   = 0;
157
158   char                  **expr_files  = 0;
159   size_t                expr_count    = 0;
160   size_t                len;
161
162   assert((vdir==0 && vserver!=0) || (vdir!=0 && vserver==0));
163
164   if (vserver) {
165     vdir = vserver->vdir.d;
166     len  = vserver->vdir.l;
167   }
168   else
169     len  = strlen(vdir);
170   
171   if (Global_getVerbosity()>=1) {
172     WRITE_MSG(1, "Initializing exclude-list for ");
173     Vwrite(1, vdir, len);
174     if (vserver!=0) {
175       WRITE_MSG(1, " (");
176       WRITE_STR(1, vserver->name);
177       WRITE_MSG(1, ")");
178     }
179     WRITE_MSG(1, "\n");
180   }
181   if (vserver && vserver->use_pkgmgmt && Global_doRenew()) {
182     if (Global_getVerbosity()>=2)
183       WRITE_MSG(1, "  Fetching configuration-file list from packagemanagement\n");
184     getConfigfileList(vserver->name, &fixed_files, &fixed_count, buf+0);
185   }
186
187   // abuse special values (NULL, empty string) to skip the next step
188   if (exclude_file && *exclude_file) {
189     if (Global_getVerbosity()>=6) WRITE_MSG(1, "  Reading exclude file\n");
190     readExcludeList(exclude_file,
191                     &expr_files,  &expr_count,
192                     buf+1);
193   }
194
195   MatchList_init(list, strdup(vdir), fixed_count + expr_count);
196   list->buf       = Emalloc(sizeof(void *) * 3);
197   list->buf[0]    = buf[0];
198   list->buf[1]    = buf[1];
199   list->buf[2]    = list->root.d;
200   list->buf_count = 3;
201
202   MatchList_appendFiles(list, 0,           fixed_files, fixed_count, false);
203   MatchList_appendFiles(list, fixed_count, expr_files,  expr_count,  true);
204
205   free(expr_files);
206   free(fixed_files);
207 }