updated on Mon Jan 23 16:10:15 UTC 2012
[aur-mirror.git] / qmail / syncdir.c
blob4bf688dcdb2fc230c9c2dbed281455d94f69b6be
1 /* syncdir -- emulate synchronous directories
2 Copyright (C) 1998 Bruce Guenter
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 You can reach me at bruce.guenter@qcc.sk.ca
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #define open XXX_open
24 #include <fcntl.h>
25 #undef open
26 #include <unistd.h>
27 #include <string.h>
28 #include <syscall.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <bits/syscall.h>
33 #define SYS_OPEN(FILE,FLAG,MODE) syscall(SYS_open, FILE, FLAG, MODE)
34 #define SYS_CLOSE(FD) syscall(SYS_close, FD)
35 #define SYS_LINK(OLD,NEW) syscall(SYS_link, OLD, NEW)
36 #define SYS_UNLINK(PATH) syscall(SYS_unlink, PATH)
37 #define SYS_RENAME(OLD,NEW) syscall(SYS_rename, OLD, NEW)
38 #define SYS_FSYNC(FD) syscall(SYS_fsync, FD)
40 static int fdirsync(const char* filename, unsigned length)
42 char dirname[length+1];
43 /* This could also be:
44 * char* dirname = alloca(length+1); */
45 int dirfd;
46 int retval;
47 memcpy(dirname, filename, length);
48 dirname[length] = 0;
49 if((dirfd = SYS_OPEN(dirname,O_RDONLY,0)) == -1)
50 return -1;
51 retval = (SYS_FSYNC(dirfd) == -1 && errno == EIO) ? -1 : 0;
52 SYS_CLOSE(dirfd);
53 return retval;
56 static int fdirsyncfn(const char *filename)
58 const char *slash = filename+strlen(filename)-1;
60 /* Skip over trailing slashes, which would be ignored by some
61 * operations */
62 while(slash > filename && *slash == '/')
63 --slash;
65 /* Skip back to the next slash */
66 while(slash > filename && *slash != '/')
67 --slash;
69 /* slash now either points to a '/' character, or no slash was found */
70 if(*slash == '/')
71 return fdirsync(filename,
72 (slash == filename) ? 1 : slash-filename);
73 else
74 return fdirsync(".", 1);
77 int open(const char *file,int oflag,mode_t mode)
79 int fd = SYS_OPEN(file, oflag, mode);
80 if(fd == -1)
81 return fd;
82 if (oflag & O_CREAT)
83 if (fdirsyncfn(file) == -1) {
84 SYS_CLOSE(fd);
85 return -1;
87 return fd;
90 int link(const char *oldpath,const char *newpath)
92 if(SYS_LINK(oldpath,newpath) == -1)
93 return -1;
94 return fdirsyncfn(newpath);
97 int unlink(const char *path)
99 if(SYS_UNLINK(path) == -1)
100 return -1;
101 return fdirsyncfn(path);
104 int rename(const char *oldpath,const char *newpath)
106 if (SYS_RENAME(oldpath,newpath) == -1)
107 return -1;
108 if (fdirsyncfn(newpath) == -1)
109 return -1;
110 return fdirsyncfn(oldpath);