fixed help message
[util-vserver.git] / util-vserver / src / vunify-doit.ic
1 // $Id$    --*- 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 #include "wrappers-io.h"
19
20 #include <sys/types.h>
21 #include <utime.h>
22
23 static bool
24 doitUnify(char const *src, char const *dst)
25 {
26   size_t        l = strlen(dst);
27   char          tmpfile[l + sizeof(".XXXXXX")];
28   int           fd;
29   int           fd_src;
30   bool          res = false;
31
32   // at first, set the ILI flags on 'src'
33   fd_src = open(src, O_RDONLY);
34   if (fd_src==-1) {
35     perror("open");
36     return false;
37   }
38   if (vc_X_set_ext2flags(fd_src,
39                          VC_IMMUTABLE_FILE_FL|VC_IMMUTABLE_LINK_FL, 0)==-1) {
40     perror("vc_X_set_ext2flags()");
41     close(fd_src);
42     return false;
43   }
44   close(fd_src);
45
46   // now, create a temporary filename
47   memcpy(tmpfile,   dst, l);
48   memcpy(tmpfile+l, ".XXXXXX", 8);
49   fd = mkstemp(tmpfile);
50   close(fd);
51
52   if (fd==-1) {
53     perror("mkstemp()");
54     return false;
55   }
56
57   // and rename the old file to this name
58   if (rename(dst, tmpfile)==-1) {
59     perror("rename()");
60     goto err;
61   }
62
63   // now, link the src-file to dst
64   if (link(src, dst)==-1) {
65     perror("link()");
66
67     unlink(dst);
68     if (rename(tmpfile, dst)==-1) {
69       perror("FATAL error in rename()");
70       _exit(1);
71     }
72     goto err;
73   }
74
75   res = true;
76
77   err:
78   unlink(tmpfile);
79
80   return res;
81 }
82
83 static bool
84 doitDeUnify(char const UNUSED *src, char const *dst)
85 {
86   size_t                l = strlen(dst);
87   char                  tmpfile[l + sizeof(".XXXXXX")];
88   int                   fd_src, fd_tmp;
89   struct stat           st;
90   struct utimbuf        utm;
91
92   fd_src = open(dst, O_RDONLY);
93   if (fd_src==-1) {
94     perror("open()");
95     return false;
96   }
97
98   if (fstat(fd_src, &st)==-1) {
99     perror("fstat()");
100     close(fd_src);
101     return false;
102   }
103   
104   memcpy(tmpfile,   dst, l);
105   memcpy(tmpfile+l, ".XXXXXX", 8);
106   fd_tmp = mkstemp(tmpfile);
107
108   if (fd_tmp==-1) {
109     perror("mkstemp()");
110     tmpfile[0] = '\0';
111     goto err;
112   }
113
114   if (fchown(fd_tmp, st.st_uid, st.st_gid)==-1 ||
115       fchmod(fd_tmp, st.st_mode)==-1) {
116     perror("fchown()/fchmod()");
117     goto err;
118   }
119
120   // todo: acl?
121
122   for (;;) {
123     char        buf[0x4000];
124     ssize_t     len = read(fd_src, buf, sizeof buf);
125     if (len==-1) {
126       perror("read()");
127       goto err;
128     }
129     if (len==0) break;
130
131     if (!WwriteAll(fd_tmp, buf, len)) goto err;
132   }
133
134   if (close(fd_src)==-1) {
135     perror("close()");
136     goto err;
137   }
138   if (close(fd_tmp)==-1) {
139     perror("close()");
140     goto err;
141   }
142   
143   utm.actime  = st.st_atime;
144   utm.modtime = st.st_mtime;
145
146   // ALERT: race !!!
147   if (utime(tmpfile, &utm)==-1) {
148     perror("utime()");
149     goto err1;
150   }
151
152   if (unlink(dst)==-1) {
153     perror("unlink()");
154     goto err1;
155   }
156   
157   // ALERT: race !!!
158   if (rename(tmpfile, dst)==-1) {
159     perror("FATAL error in rename()");
160     _exit(1);
161   }
162
163   return true;
164   
165   err:
166   close(fd_src);
167   close(fd_tmp);
168   err1:
169   if (tmpfile[0]) unlink(tmpfile);
170
171   return false;
172 }