-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathfileops.c
146 lines (124 loc) · 3.56 KB
/
fileops.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fileops.h"
#include <sys/stat.h>
#if defined(_MSC_VER)
# include <sys/utime.h>
#else
# include <utime.h>
#endif
#if !defined(_WIN32)
# include <unistd.h>
#else
# include <io.h>
#endif
#if !defined(S_ISLNK)
# define lstat (stat)
# define S_ISLNK(m) (0)
#endif
/*
copyright (c) 2003, 2005, 2006 squell <info@squell.net>
use, modification, copying and distribution of this software is permitted
under the conditions described in the file 'COPYING'.
*/
int fcopy(FILE *dest, FILE *src)
{
char buffer[0x4000]; /* 16kb buffer */
size_t r, w;
do {
r = fread (buffer, 1, sizeof buffer, src);
w = fwrite(buffer, 1, r, dest);
if(w != r) return 0;
} while(r == sizeof buffer);
return feof(src);
}
size_t fpadd(char c, size_t len, FILE *dest)
{
char buffer[0x4000]; /* 16kb buffer */
size_t w = len;
memset(buffer, c, sizeof buffer);
while(w > sizeof buffer) {
size_t n = fwrite(buffer, sizeof buffer, 1, dest);
if(n!=1) return 0;
w -= sizeof buffer;
}
return (len - w) + fwrite(buffer, 1, w, dest);
}
FILE *ftemp(char *templ, const char *mode)
{
FILE *f;
#if defined(__DJGPP__) || defined(_WIN32)
FILE *fc;
if(mktemp(templ) && (fc = fopen(templ, "wb+"))) {
if(f = freopen(templ, mode, fc)) return f;
fclose(fc);
#else
int fd = mkstemp(templ);
if(fd >= 0) {
FILE* fdopen(); /* in case -ansi is used */
if(f = fdopen(fd, mode)) return f;
close(fd);
#endif
unlink(templ);
}
return 0;
}
FILE *opentemp(const char *hint, char **name) /* free() name! */
{
static const char template[] = "idXXXXXX";
char *buf, *dirsep = strrchr(hint, '/');
size_t prefix = dirsep? dirsep-hint+1 : 0;
FILE *f;
if(buf = malloc(prefix + sizeof template)) {
strncpy(buf, hint, prefix);
strncpy(buf+prefix, template, sizeof template);
if(f = ftemp(buf, "wb")) {
if(name) *name = buf;
else free(buf);
return f;
}
free(buf);
}
return 0;
}
/* ==================================================== */
int cpfile(const char *srcnam, const char *dstnam)
{
FILE *src, *dst;
int result = 0;
if(src = fopen(srcnam, "rb")) {
if(dst = fopen(dstnam, "wb")) {
result = fcopy(dst, src);
if(fclose(dst) != 0) result = 0;
}
fclose(src);
}
return result;
}
int mvfile(const char *srcnam, const char *dstnam)
{
struct stat fs;
int file = 0, slow = 0;
if(lstat(dstnam, &fs) == 0) {
file = !S_ISLNK(fs.st_mode);
slow = fs.st_nlink > 1 || !file; /* honour links */
slow = slow || remove(dstnam) != 0;
}
if(slow || rename(srcnam, dstnam) != 0) {
struct utimbuf buf, *stamp = 0;
struct stat ss;
if(stat(srcnam, &ss) == 0) {
stamp = &buf; /* preserve file time */
buf.actime = ss.st_atime;
buf.modtime = ss.st_mtime;
}
if(!cpfile(srcnam, dstnam))
return 0; /* could not rename, could not copy - give up */
(void) remove(srcnam); /* dont check result */
(void) utime(dstnam, stamp);
}
if(file)
(void) chmod(dstnam, fs.st_mode);
return 1; /* successful rename (or copy) */
}