3d03249e64c69b8e9d444f9cf4ca45fbe4c8753c
[util-vserver.git] / lib_internal / unify-deunify.c
1 // $Id: unify-deunify.c,v 1.2 2004/02/18 04:48:24 ensc Exp $    --*- 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
23 #include "unify.h"
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <utime.h>
30 #include <fcntl.h>
31 #include <errno.h>
32
33 #define ENSC_WRAPPERS_IO        1
34 #include <wrappers.h>
35
36 bool
37 Unify_deUnify(char const *dst)
38 {
39   size_t                l = strlen(dst);
40   char                  tmpfile[l + sizeof(";XXXXXX")];
41   int                   fd_src, fd_tmp;
42   struct stat           st;
43   struct utimbuf        utm;
44
45   fd_src = open(dst, O_RDONLY);
46   if (fd_src==-1) {
47     perror("open()");
48     return false;
49   }
50
51   if (fstat(fd_src, &st)==-1) {
52     perror("fstat()");
53     close(fd_src);
54     return false;
55   }
56   
57   memcpy(tmpfile,   dst, l);
58   memcpy(tmpfile+l, ";XXXXXX", 8);
59   fd_tmp = mkstemp(tmpfile);
60
61   if (fd_tmp==-1) {
62     perror("mkstemp()");
63     tmpfile[0] = '\0';
64     goto err;
65   }
66
67   if (fchown(fd_tmp, st.st_uid, st.st_gid)==-1 ||
68       fchmod(fd_tmp, st.st_mode)==-1) {
69     perror("fchown()/fchmod()");
70     goto err;
71   }
72
73   // todo: acl?
74
75   for (;;) {
76     char        buf[0x4000];
77     ssize_t     len = read(fd_src, buf, sizeof buf);
78     if (len==-1) {
79       perror("read()");
80       goto err;
81     }
82     if (len==0) break;
83
84     if (!WwriteAll(fd_tmp, buf, len, 0)) goto err;
85   }
86
87   if (close(fd_src)==-1) {
88     perror("close()");
89     goto err;
90   }
91   if (close(fd_tmp)==-1) {
92     perror("close()");
93     goto err;
94   }
95   
96   utm.actime  = st.st_atime;
97   utm.modtime = st.st_mtime;
98
99   // ALERT: race !!!
100   if (utime(tmpfile, &utm)==-1) {
101     perror("utime()");
102     goto err1;
103   }
104
105   if (unlink(dst)==-1) {
106     perror("unlink()");
107     goto err1;
108   }
109   
110   // ALERT: race !!!
111   if (rename(tmpfile, dst)==-1) {
112     perror("FATAL error in rename()");
113     _exit(1);
114   }
115
116   return true;
117   
118   err:
119   close(fd_src);
120   close(fd_tmp);
121   err1:
122   if (tmpfile[0]) unlink(tmpfile);
123
124   return false;
125 }