made it work...
[util-vserver.git] / util-vserver / src / vhashify-init.hc
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2005 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 #include "pathconfig.h"
19 #include "lib_internal/util-dotfile.h"
20
21 #include <sys/param.h>
22
23 static UNUSED void
24 freeHashList(HashDirCollection *hash_vec)
25 {
26   for (struct HashDirInfo *itm = Vector_begin(hash_vec);
27        itm!=Vector_end(hash_vec);
28        ++itm) {
29     free(const_cast(char *)(itm->path.d));
30   }
31
32   Vector_free(hash_vec);
33 }
34
35 static size_t
36 initHashList(HashDirCollection *hash_vec, char const *hashdir)
37 {
38   int           cur_dir = Eopen(".", O_RDONLY|O_DIRECTORY, 0);
39   Echdir(hashdir);
40   
41   DIR           *d      = Eopendir(".");
42   struct dirent *ep;
43   size_t        l   = strlen(hashdir);
44   size_t        res = 0;
45
46   while ((ep=readdir(d)) != 0) {
47     struct stat         st;
48
49     if (isDotfile(ep->d_name) ||
50         stat(ep->d_name, &st)==-1 || !S_ISDIR(st.st_mode))
51       continue;
52
53     if (HashDirInfo_findDevice(hash_vec, st.st_dev)!=0) {
54       WRITE_MSG(2, "Duplicate hash-dir entry '");
55       WRITE_STR(2, ep->d_name);
56       WRITE_MSG(2, "' found\n");
57       continue;
58     }
59
60     char                *full_path = Emalloc(l + strlen(ep->d_name) + 3);
61     char                *ptr       = full_path + l;
62
63     memcpy(full_path, hashdir, l);
64     while (ptr>full_path && ptr[-1]=='/') --ptr;
65     *ptr++ = '/';
66     strcpy(ptr, ep->d_name);
67     strcat(ptr, "/");   // append a trailing '/'
68
69
70     struct HashDirInfo  tmp = {
71       .device  = st.st_dev,
72       .path    = { full_path, strlen(full_path) },
73     };
74
75     res = MAX(res, tmp.path.l);
76     
77     memcpy(Vector_pushback(hash_vec), &tmp, sizeof tmp);
78   }
79
80   if (Vector_count(hash_vec)==0) {
81     WRITE_MSG(2, "Could not find a place for the hashified files at '");
82     WRITE_STR(2, hashdir);
83     WRITE_MSG(2, "'.\n");
84     exit(wrapper_exit_code);
85   }
86
87   Eclosedir(d);
88   Efchdir(cur_dir);
89   Eclose(cur_dir);
90
91   return res;
92 }
93
94 static char *
95 searchHashdir(char const *lhs, char const *rhs)
96 {
97   size_t        l1  = strlen(lhs);
98   size_t        l2  = rhs ? strlen(rhs) : 0;
99   char *        res = Emalloc(l1 + l2 + 1);
100   struct stat   st;
101
102   strcpy(res, lhs);
103   if (rhs) strcat(res, rhs);
104
105   if (stat(res, &st)==-1 || !S_ISDIR(st.st_mode)) {
106     free(res);
107     res = 0;
108   }
109
110   return res;
111 }
112
113 static void
114 initModeManually(struct Arguments const UNUSED *args, int argc, char *argv[])
115 {
116   assert(args->hash_dir!=0);
117   
118   if (argc<2) {
119     WRITE_MSG(2, "No exclude list specified\n");
120     exit(1);
121   }
122
123   global_info.hash_dirs_max_size = initHashList(&global_info.hash_dirs,
124                                                 args->hash_dir);
125   MatchList_initManually(&global_info.dst_list, 0, strdup(argv[0]), argv[1]);
126 }
127
128 static void
129 initModeVserver(struct Arguments const UNUSED *args, int argc, char *argv[])
130 {
131   char const                            *hashdir   = args->hash_dir;
132   struct MatchVserverInfo               vserver = {
133     .name        = argv[0],
134     .use_pkgmgmt = true
135   };
136
137   if (!MatchVserverInfo_init(&vserver)) {
138     WRITE_MSG(2, "Failed to initialize unification for vserver\n");
139     exit(1);
140   }
141
142   if (argc!=1) {
143     WRITE_MSG(2, "More than one vserver is not supported\n");
144     exit(1);
145   }
146
147   if (!MatchList_initByVserver(&global_info.dst_list, &vserver)) {
148     WRITE_MSG(2, "unification not configured for this vserver\n");
149     exit(1);
150   }
151
152   if (hashdir==0) hashdir = searchHashdir(vserver.appdir.d, "/hash");
153   if (hashdir==0) hashdir = searchHashdir(CONFDIR "/.defaults/apps/vunify/hash", 0);
154
155   if (hashdir==0) {
156     WRITE_MSG(2, "no hash-directory configured for this vserver.\n");
157     exit(1);
158   }
159
160   global_info.hash_dirs_max_size = initHashList(&global_info.hash_dirs, hashdir);
161
162   free(const_cast(char *)(hashdir));
163   MatchVserverInfo_free(&vserver);
164 }
165