2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * Various useful file utilities.
10 #include "wvdiriter.h"
21 int wvmkdir(WvStringParm _dir
, int create_mode
)
26 return mkdir(_dir
, create_mode
);
30 int mkdirp(WvStringParm _dir
, int create_mode
)
32 if (!access(_dir
, X_OK
))
35 // You're trying to make a nothing directory eh?
41 while ((p
= strchr(++p
, '/')))
44 if (access(dir
, X_OK
) && wvmkdir(dir
, create_mode
))
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(); )
63 ::unlink(i
->fullname
);
70 bool fcopy(WvStringParm src
, WvStringParm dst
)
76 WvFile
in(src
, O_RDONLY
);
79 int oldmode
= umask(0);
80 WvFile
out(dst
, O_CREAT
|O_WRONLY
, buf
.st_mode
& 007777);
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))
97 utim
.actime
= utim
.modtime
= buf
.st_mtime
;
98 if (utime(dst
, &utim
))
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())
117 struct utimbuf
*buf
= NULL
;
120 buf
= (struct utimbuf
*)malloc(sizeof(struct utimbuf
));
121 buf
->actime
= time(NULL
);
122 buf
->modtime
= mtime
;
125 if (utime(file
, buf
) == 0)
136 // Reads the contents of a symlink. Returns WvString::null on error.
137 WvString
wvreadlink(WvStringParm path
)
140 return WvString::null
; // no such thing as a symlink on Windows
146 result
.setsize(size
);
147 int readlink_result
= readlink(path
, result
.edit(), size
);
148 if (readlink_result
== -1)
149 return WvString::null
;
150 if (readlink_result
< size
)
152 result
.edit()[readlink_result
] = '\0';
155 size
= 2*size
; // increase buffer size
162 bool samedate(WvStringParm file1
, WvStringParm file2
)
167 if (stat(file1
, &buf
) || stat(file2
, &buf2
))
170 if (buf
.st_mtime
== buf2
.st_mtime
|| buf
.st_ctime
== buf2
.st_ctime
)
177 bool samedate(WvStringParm dir1
, WvStringParm dir2
, WvStringParm relname
)
179 return samedate(WvString("%s/%s", dir1
, relname
),
180 WvString("%s/%s", dir2
, relname
));
185 // runs fnmatch against everything in patterns. We also interpret
186 // CVS-style '!' patterns, which makes us very fancy.
187 bool wvfnmatch(WvStringList
& patterns
, WvStringParm name
, int flags
)
189 WvStringList::Iter
i(patterns
);
192 for (i
.rewind(); i
.next(); )
194 // if we hit JUST a '!', reset any matches found so far.
200 // if we hit something that starts with '!', we unmatch anything
202 if (i
->cstr()[0] == '!')
205 continue; // nothing to unmatch, so why try?
206 if (fnmatch(*i
+1, name
, flags
) == 0) // matches
207 match
= false; // unmatch it.
211 // just a straightforward matching case.
212 if (fnmatch(*i
, name
, flags
) == 0) // matches
221 #ifndef _WIN32 // file permissions are too screwy in win32
222 int wvchmod(const char *path
, mode_t mode
)
225 if (lstat(path
, &st
) == -1) {
229 int filedes
= open(path
, O_RDONLY
);
231 // if we're not running as root, this file/dir may have 0
232 // perms and open() fails, so let's try again
234 // NOTE: This is not as secure as the proper way, since
235 // it's conceivable that someone swaps out the dir/file
236 // for a symlink between our check and the chmod() call
240 if (stat(path
, &sst
) != -1)
241 if (st
.st_ino
== sst
.st_ino
)
242 return chmod(path
, mode
);
248 if (fstat(filedes
, &fst
) == -1) {
253 if (st
.st_ino
!= fst
.st_ino
) {
259 // we're definitely chmod'ing the open file here, which is good,
260 // because the filename itself might have been moved around between
261 // our stat'ing and chmod'ing it.
262 int retval
= fchmod(filedes
, mode
);
264 // this is guaranteed to be the same file as filedes, because in
265 // Windows, open files can't be changed on the filesystem (unlike in
267 int retval
= chmod(path
, mode
);
278 #ifndef _WIN32 // tmpfile() is really the best choice, when it works
281 // in win32, tmpfile() creates files in c:\...
282 // and that directory isn't always writable! Idiots.
283 char *name
= _tempnam("c:\\temp", "wvtmp");
284 FILE *f
= fopen(name
, "wb+");
291 WvString
wvtmpfilename(WvStringParm prefix
)
293 #ifndef _WIN32 // tmpfile() is really the best choice, when it works
294 WvString
tmpname("/tmp/%sXXXXXX", prefix
);
296 if ((fd
= mkstemp(tmpname
.edit())) == (-1))
300 WvString
tmpname(_tempnam("c:\\temp", prefix
.cstr()));
302 fd
= open(tmpname
, O_WRONLY
|O_CREAT
|O_EXCL
, 0777);
304 return WvString::null
; // weird
314 mode_t rv
= umask(0);