vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

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 }