Try another fix for wvlinkerhack and static libraries.
[wvstreams.git] / streams / fileutils.cc
blobe3a861bca2bfc77515917e4a552c7de105e14e8f
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Various useful file utilities.
7 */
8 #include "fileutils.h"
9 #include "wvfile.h"
10 #include "wvdiriter.h"
11 #include <string.h>
12 #include <sys/stat.h>
13 #ifndef _WIN32
14 #include <fnmatch.h>
15 #endif
16 #ifndef _MSC_VER
17 #include <unistd.h>
18 #include <utime.h>
19 #endif
21 int wvmkdir(WvStringParm _dir, int create_mode)
23 #ifdef _WIN32
24 return mkdir(_dir);
25 #else
26 return mkdir(_dir, create_mode);
27 #endif
30 int mkdirp(WvStringParm _dir, int create_mode)
32 if (!access(_dir, X_OK))
33 return 0;
35 // You're trying to make a nothing directory eh?
36 assert(!!_dir);
38 WvString dir(_dir);
39 char *p = dir.edit();
41 while ((p = strchr(++p, '/')))
43 *p = '\0';
44 if (access(dir, X_OK) && wvmkdir(dir, create_mode))
45 return -1;
46 *p = '/';
49 // You're probably creating the directory to write to it? Maybe this should
50 // look for R_OK&X_OK instead of X_OK&W_OK...
51 return (access(dir, X_OK&W_OK) && wvmkdir(dir, create_mode)) ? -1 : 0;
55 void rm_rf(WvStringParm dir)
57 WvDirIter i(dir, false, false); // non-recursive, don't skip_mounts
58 for (i.rewind(); i.next(); )
60 if (i.isdir())
61 rm_rf(i->fullname);
62 else
63 ::unlink(i->fullname);
65 ::rmdir(dir);
66 ::unlink(dir);
70 bool fcopy(WvStringParm src, WvStringParm dst)
72 struct stat buf;
73 if (stat(src, &buf))
74 return false;
76 WvFile in(src, O_RDONLY);
77 unlink(dst);
79 int oldmode = umask(0);
80 WvFile out(dst, O_CREAT|O_WRONLY, buf.st_mode & 007777);
81 umask(oldmode);
83 in.autoforward(out);
84 while (in.isok() && out.isok())
86 /* This used to be a select(0), but really, if select() returns
87 * false, it'll keep doing it until the end of time. If you're
88 * going into an infinite loop, better save the CPU a bit, since
89 * you can still find out about it with strace... */
90 if (in.select(-1, true, false))
91 in.callback();
93 if (!out.isok())
94 return false;
96 struct utimbuf utim;
97 utim.actime = utim.modtime = buf.st_mtime;
98 if (utime(dst, &utim))
99 return false;
101 return true;
105 bool fcopy(WvStringParm srcdir, WvStringParm dstdir, WvStringParm relname)
107 return fcopy(WvString("%s/%s", srcdir, relname),
108 WvString("%s/%s", dstdir, relname));
112 bool ftouch(WvStringParm file, time_t mtime)
114 if (!WvFile(file, O_WRONLY|O_CREAT).isok())
115 return false;
117 struct utimbuf *buf = NULL;
118 if (mtime != 0)
120 buf = (struct utimbuf *)malloc(sizeof(struct utimbuf));
121 buf->actime = time(NULL);
122 buf->modtime = mtime;
125 if (utime(file, buf) == 0)
127 free(buf);
128 return true;
131 free(buf);
132 return false;
136 bool samedate(WvStringParm file1, WvStringParm file2)
138 struct stat buf;
139 struct stat buf2;
141 if (stat(file1, &buf) || stat(file2, &buf2))
142 return false;
144 if (buf.st_mtime == buf2.st_mtime || buf.st_ctime == buf2.st_ctime)
145 return true;
147 return false;
151 bool samedate(WvStringParm dir1, WvStringParm dir2, WvStringParm relname)
153 return samedate(WvString("%s/%s", dir1, relname),
154 WvString("%s/%s", dir2, relname));
158 #ifndef _WIN32
159 // runs fnmatch against everything in patterns. We also interpret
160 // CVS-style '!' patterns, which makes us very fancy.
161 bool wvfnmatch(WvStringList& patterns, WvStringParm name, int flags)
163 WvStringList::Iter i(patterns);
164 bool match = false;
166 for (i.rewind(); i.next(); )
168 // if we hit JUST a '!', reset any matches found so far.
169 if (*i == "!") {
170 match = false;
171 continue;
174 // if we hit something that starts with '!', we unmatch anything
175 // found so far.
176 if (i->cstr()[0] == '!')
178 if (!match)
179 continue; // nothing to unmatch, so why try?
180 if (fnmatch(*i+1, name, flags) == 0) // matches
181 match = false; // unmatch it.
183 else
185 // just a straightforward matching case.
186 if (fnmatch(*i, name, flags) == 0) // matches
187 match = true;
191 return match;
193 #endif
195 #ifndef _WIN32 // file permissions are too screwy in win32
196 int wvchmod(const char *path, mode_t mode)
198 struct stat st;
199 if (lstat(path, &st) == -1) {
200 return -1;
203 int filedes = open(path, O_RDONLY);
204 if (filedes == -1) {
205 // if we're not running as root, this file/dir may have 0
206 // perms and open() fails, so let's try again
208 // NOTE: This is not as secure as the proper way, since
209 // it's conceivable that someone swaps out the dir/file
210 // for a symlink between our check and the chmod() call
212 struct stat sst;
213 if (getuid() != 0)
214 if (stat(path, &sst) != -1)
215 if (st.st_ino == sst.st_ino)
216 return chmod(path, mode);
218 return -1;
221 struct stat fst;
222 if (fstat(filedes, &fst) == -1) {
223 close(filedes);
224 return -1;
227 if (st.st_ino != fst.st_ino) {
228 close(filedes);
229 return -1;
232 #ifndef _WIN32
233 // we're definitely chmod'ing the open file here, which is good,
234 // because the filename itself might have been moved around between
235 // our stat'ing and chmod'ing it.
236 int retval = fchmod(filedes, mode);
237 #else
238 // this is guaranteed to be the same file as filedes, because in
239 // Windows, open files can't be changed on the filesystem (unlike in
240 // Unix).
241 int retval = chmod(path, mode);
242 #endif
243 close(filedes);
245 return retval;
247 #endif // !_WIN32
250 FILE *wvtmpfile()
252 #ifndef _WIN32 // tmpfile() is really the best choice, when it works
253 return tmpfile();
254 #else
255 // in win32, tmpfile() creates files in c:\...
256 // and that directory isn't always writable! Idiots.
257 char *name = _tempnam("c:\\temp", "wvtmp");
258 FILE *f = fopen(name, "wb+");
259 free(name);
260 return f;
261 #endif
265 WvString wvtmpfilename(WvStringParm prefix)
267 #ifndef _WIN32 // tmpfile() is really the best choice, when it works
268 WvString tmpname("/tmp/%sXXXXXX", prefix);
269 int fd;
270 if ((fd = mkstemp(tmpname.edit())) == (-1))
271 return WvString();
272 close(fd);
273 #else
274 WvString tmpname(_tempnam("c:\\temp", prefix.cstr()));
275 int fd;
276 fd = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, 0777);
277 if (fd < 0)
278 return WvString::null; // weird
279 _close(fd);
280 #endif
282 return tmpname;
286 mode_t get_umask()
288 mode_t rv = umask(0);
289 umask(rv);
291 return rv;
295 void wvdelay(int msec_delay)
297 #ifdef _WIN32
298 Sleep(msec_delay);
299 #else
300 usleep(msec_delay * 1000);
301 #endif