unify-deunify.c (2595B)
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 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 }