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