94957a33732da06a1c4555ba1632d869009c54bd
[util-vserver.git] / util-vserver / src / vutil.cc
1 // $Id$
2
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 // based on vutil.cc by Jacques Gelinas
5 //  
6 // This program 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, or (at your option)
9 // any later version.
10 //  
11 // This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 #pragma implementation
21 #include <stdio.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/wait.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <utime.h>
29 #include "vutil.h"
30 #include <sys/ioctl.h>
31 #include <linux/ext2_fs.h>
32
33 bool testmode;
34 int debug;
35
36 int file_copy (const char *src, const char *dst, struct stat &st)
37 {
38         int ret = -1;
39         FILE *fin = fopen (src,"r");
40         if (fin == NULL){
41                 fprintf (stderr,"Can't open file %s (%s)\n",src,strerror(errno));
42         }else{
43                 FILE *fout = fopen (dst,"w");
44                 if (fout == NULL){
45                         fprintf (stderr,"Can't open file %s (%s)\n",dst,strerror(errno));
46                 }else{
47                         char buf[8192];
48                         int len;
49                         while ((len=fread(buf,1,sizeof(buf),fin))>0){
50                                 fwrite (buf,1,len,fout);
51                         }
52                         fflush (fout);
53                         ret = 0;
54                         if (fchown (fileno(fout),st.st_uid,st.st_gid)==-1){
55                                 fprintf (stderr,"Can't chown file %s (%s)\n"
56                                         ,dst,strerror(errno));
57                                 ret = -1;
58                         }else if (fchmod (fileno(fout),st.st_mode)==-1){
59                                 fprintf (stderr,"Can't chmod file %s (%s)\n"
60                                         ,dst,strerror(errno));
61                                 ret = -1;
62                         }
63                         fclose(fout);
64                         struct utimbuf timbuf;
65                         timbuf.modtime = st.st_mtime;
66                         timbuf.actime = st.st_atime;
67                         if (utime (dst,&timbuf)==-1){
68                                 fprintf (stderr,"Can't set time stamp on file %s (%s)\n"
69                                         ,dst,strerror(errno));
70                         }
71                 }
72                 fclose (fin);
73         }
74         return ret;
75 }
76
77 /*
78         Set the immutable flag on a file
79 */
80 int setext2flag (const char *fname, bool set, int ext2flags)
81 {
82         int ret = -1;
83         if (testmode){
84                 ret = 0;
85         }else{
86                 int fd = open (fname,O_RDONLY);
87                 if (fd == -1){
88                         fprintf (stderr,"Can't open file %s (%s)\n",fname 
89                                 ,strerror(errno));
90                 }else{
91                         int flags = set ? ext2flags : 0;
92                         ret = ioctl (fd,EXT2_IOC_SETFLAGS,&flags);
93                         close (fd);
94                         if (ret == -1){
95                                 fprintf (stderr,"Can't %s immutable flag on file %s (^s)\n"
96                                         ,(set ? "set" : "unset")
97                                         ,fname
98                                         ,strerror(errno));
99                         }
100                 }
101         }
102         return ret;
103 }
104
105 int vbuild_mkdir (const char *path, mode_t mode)
106 {
107         int ret = -1;
108         if (testmode){
109                 printf ("mkdir %s; chmod %o %s\n",path,mode,path);
110                 ret = 0;
111         }else{
112                 ret = mkdir (path,mode);
113                 if (ret == -1 && errno == EEXIST){
114                         struct stat st;
115                         if (lstat(path,&st)!=-1 && S_ISDIR(st.st_mode)){
116                                 ret = chmod (path,mode);
117                         }
118                 }
119         }
120         return ret;
121 }
122
123 int vbuild_mknod(const char *path, mode_t mode, dev_t dev)
124 {
125         int ret = -1;
126         if (testmode){
127                 printf ("mknod %s %o %02x:%02x\n",path,mode,major(dev),minor(dev));
128                 ret = 0;
129         }else{
130                 ret = mknod (path,mode,dev);
131                 if (ret == -1 && errno == EEXIST){
132                         struct stat st;
133                         lstat(path,&st);
134                         if (lstat(path,&st)!=-1
135                                 && (st.st_mode & S_IFMT) == (mode & S_IFMT)
136                                 && st.st_rdev == dev){
137                                 ret = chmod (path,mode);
138                         }
139                 }
140         }
141         return ret;
142 }
143 int vbuild_symlink(const char *src, const char *dst)
144 {
145         int ret = -1;
146         if (testmode){
147                 printf ("ln -s %s %s\n",src,dst);
148                 ret = 0;
149         }else{
150                 ret = symlink (src,dst);
151         }
152         return ret;
153 }
154
155 int vbuild_link(const char *src, const char *dst)
156 {
157         int ret = -1;
158         if (testmode){
159                 printf ("ln %s %s\n",src,dst);
160                 ret = 0;
161         }else{
162                 ret = link (src,dst);
163         }
164         return ret;
165 }
166
167 int vbuild_unlink(const char *path)
168 {
169         int ret = -1;
170         if (testmode){
171                 printf ("unlink %s\n",path);
172                 ret = 0;
173         }else{
174                 ret = unlink (path);
175         }
176         return ret;
177 }
178
179 int vbuild_chown(const char *path, uid_t uid, gid_t gid)
180 {
181         int ret = -1;
182         if (testmode){
183                 printf ("chown %d.%d %s\n",uid,gid,path);
184                 ret = 0;
185         }else{
186                 ret = chown (path,uid,gid);
187         }
188         return ret;
189 }
190
191 int vbuild_file_copy(
192         const char *src,
193         const char *dst,
194         struct stat &st)
195 {
196         int ret = -1;
197         if (testmode){
198                 printf ("cp -a %s %s\n",src,dst);
199                 ret = 0;
200         }else{
201                 ret = file_copy (src,dst,st);
202         }
203         return ret;
204 }
205
206 /*
207         Load the list of all packages in a vserver
208 */
209 void vutil_loadallpkg (string &refserver, list<PACKAGE> &packages)
210 {
211         FILE *fin = vutil_execdistcmd (K_PKGVERSION,refserver,NULL);
212         if (fin != NULL){
213                 char line[1000];
214                 while (fgets(line,sizeof(line)-1,fin)!=NULL){
215                         int last = strlen(line)-1;
216                         if (last >= 0 && line[last] == '\n') line[last] = '\0';
217                         packages.push_back (PACKAGE(line));
218                 }
219                 pclose (fin);
220         }
221 }
222
223 int vutil_lstat (string path, struct stat &st)
224 {
225         int ret = 0;
226         if (lstat(path.c_str(),&st) == -1){
227                 fprintf (stderr,"Can't lstat file %s (%s)\n"
228                         ,path.c_str(),strerror(errno));
229                 ret = -1;
230         }
231         return ret;
232 }
233
234 const char K_PKGVERSION[]="pkgversion";
235 const char K_DUMPFILES[]="dumpfiles";
236 const char K_UNIFILES[]="unifiles";
237
238 FILE *vutil_execdistcmd (const char *key, const string &vserver, const char *args)
239 {
240         string cmd = PKGLIBDIR "/distrib-info ";
241         cmd += vserver;
242         cmd += " ";
243         cmd += key;
244         if (args != NULL){
245                 cmd += " ";
246                 cmd += args;
247         }
248         FILE *ret = popen (cmd.c_str(),"r");
249         if (ret == NULL){
250                 fprintf (stderr,"Can't execute command %s\n",cmd.c_str());
251         }else{
252                 #if 0
253                 char buf[1000];
254                 while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
255                         int last = strlen(buf)-1;
256                         if (last >= 0) buf[last] = '\0';
257                         ret = buf;
258                         break;
259                 }
260                 pclose (fin);
261                 #endif
262         }
263         return ret;
264 }
265