00001
00002
00003
00004
00005
00006
00007
00008 #include "fileutils.h"
00009 #include "wvfile.h"
00010 #include "wvdiriter.h"
00011 #include <string.h>
00012 #include <sys/stat.h>
00013 #ifndef _WIN32
00014 #include <fnmatch.h>
00015 #endif
00016 #ifndef _MSC_VER
00017 #include <unistd.h>
00018 #include <utime.h>
00019 #endif
00020
00021 int wvmkdir(WvStringParm _dir, int create_mode)
00022 {
00023 #ifdef _WIN32
00024 return mkdir(_dir);
00025 #else
00026 return mkdir(_dir, create_mode);
00027 #endif
00028 }
00029
00030 int mkdirp(WvStringParm _dir, int create_mode)
00031 {
00032 if (!access(_dir, X_OK))
00033 return 0;
00034
00035
00036 assert(!!_dir);
00037
00038 WvString dir(_dir);
00039 char *p = dir.edit();
00040
00041 while ((p = strchr(++p, '/')))
00042 {
00043 *p = '\0';
00044 if (access(dir, X_OK) && wvmkdir(dir, create_mode))
00045 return -1;
00046 *p = '/';
00047 }
00048
00049
00050
00051 return (access(dir, X_OK&W_OK) && wvmkdir(dir, create_mode)) ? -1 : 0;
00052 }
00053
00054
00055 void rm_rf(WvStringParm dir)
00056 {
00057 WvDirIter i(dir, false, false);
00058 for (i.rewind(); i.next(); )
00059 {
00060 if (i.isdir())
00061 rm_rf(i->fullname);
00062 else
00063 ::unlink(i->fullname);
00064 }
00065 ::rmdir(dir);
00066 ::unlink(dir);
00067 }
00068
00069
00070 bool fcopy(WvStringParm src, WvStringParm dst)
00071 {
00072 struct stat buf;
00073 if (stat(src, &buf))
00074 return false;
00075
00076 WvFile in(src, O_RDONLY);
00077 unlink(dst);
00078
00079 int oldmode = umask(0);
00080 WvFile out(dst, O_CREAT|O_WRONLY, buf.st_mode & 007777);
00081 umask(oldmode);
00082
00083 in.autoforward(out);
00084 while (in.isok() && out.isok())
00085 {
00086
00087
00088
00089
00090 if (in.select(-1, true, false))
00091 in.callback();
00092 }
00093 if (!out.isok())
00094 return false;
00095
00096 struct utimbuf utim;
00097 utim.actime = utim.modtime = buf.st_mtime;
00098 if (utime(dst, &utim))
00099 return false;
00100
00101 return true;
00102 }
00103
00104
00105 bool fcopy(WvStringParm srcdir, WvStringParm dstdir, WvStringParm relname)
00106 {
00107 return fcopy(WvString("%s/%s", srcdir, relname),
00108 WvString("%s/%s", dstdir, relname));
00109 }
00110
00111
00112 bool ftouch(WvStringParm file, time_t mtime)
00113 {
00114 if (!WvFile(file, O_WRONLY|O_CREAT).isok())
00115 return false;
00116
00117 struct utimbuf *buf = NULL;
00118 if (mtime != 0)
00119 {
00120 buf = (struct utimbuf *)malloc(sizeof(struct utimbuf));
00121 buf->actime = time(NULL);
00122 buf->modtime = mtime;
00123 }
00124
00125 if (utime(file, buf) == 0)
00126 {
00127 free(buf);
00128 return true;
00129 }
00130
00131 free(buf);
00132 return false;
00133 }
00134
00135
00136
00137 WvString wvreadlink(WvStringParm path)
00138 {
00139 #ifdef _WIN32
00140 return WvString::null;
00141 #else
00142 WvString result;
00143 int size = 64;
00144 for (;;)
00145 {
00146 result.setsize(size);
00147 int readlink_result = readlink(path, result.edit(), size);
00148 if (readlink_result == -1)
00149 return WvString::null;
00150 if (readlink_result < size)
00151 {
00152 result.edit()[readlink_result] = '\0';
00153 break;
00154 }
00155 size = 2*size;
00156 }
00157 return result;
00158 #endif
00159 }
00160
00161
00162 bool samedate(WvStringParm file1, WvStringParm file2)
00163 {
00164 struct stat buf;
00165 struct stat buf2;
00166
00167 if (stat(file1, &buf) || stat(file2, &buf2))
00168 return false;
00169
00170 if (buf.st_mtime == buf2.st_mtime || buf.st_ctime == buf2.st_ctime)
00171 return true;
00172
00173 return false;
00174 }
00175
00176
00177 bool samedate(WvStringParm dir1, WvStringParm dir2, WvStringParm relname)
00178 {
00179 return samedate(WvString("%s/%s", dir1, relname),
00180 WvString("%s/%s", dir2, relname));
00181 }
00182
00183
00184 #ifndef _WIN32
00185
00186
00187 bool wvfnmatch(WvStringList& patterns, WvStringParm name, int flags)
00188 {
00189 WvStringList::Iter i(patterns);
00190 bool match = false;
00191
00192 for (i.rewind(); i.next(); )
00193 {
00194
00195 if (*i == "!") {
00196 match = false;
00197 continue;
00198 }
00199
00200
00201
00202 if (i->cstr()[0] == '!')
00203 {
00204 if (!match)
00205 continue;
00206 if (fnmatch(*i+1, name, flags) == 0)
00207 match = false;
00208 }
00209 else
00210 {
00211
00212 if (fnmatch(*i, name, flags) == 0)
00213 match = true;
00214 }
00215 }
00216
00217 return match;
00218 }
00219 #endif
00220
00221 #ifndef _WIN32 // file permissions are too screwy in win32
00222 int wvchmod(const char *path, mode_t mode)
00223 {
00224 struct stat st;
00225 if (lstat(path, &st) == -1) {
00226 return -1;
00227 }
00228
00229 int filedes = open(path, O_RDONLY);
00230 if (filedes == -1) {
00231
00232
00233
00234
00235
00236
00237
00238 struct stat sst;
00239 if (getuid() != 0)
00240 if (stat(path, &sst) != -1)
00241 if (st.st_ino == sst.st_ino)
00242 return chmod(path, mode);
00243
00244 return -1;
00245 }
00246
00247 struct stat fst;
00248 if (fstat(filedes, &fst) == -1) {
00249 close(filedes);
00250 return -1;
00251 }
00252
00253 if (st.st_ino != fst.st_ino) {
00254 close(filedes);
00255 return -1;
00256 }
00257
00258 #ifndef _WIN32
00259
00260
00261
00262 int retval = fchmod(filedes, mode);
00263 #else
00264
00265
00266
00267 int retval = chmod(path, mode);
00268 #endif
00269 close(filedes);
00270
00271 return retval;
00272 }
00273 #endif // !_WIN32
00274
00275
00276 FILE *wvtmpfile()
00277 {
00278 #ifndef _WIN32 // tmpfile() is really the best choice, when it works
00279 return tmpfile();
00280 #else
00281
00282
00283 char *name = _tempnam("c:\\temp", "wvtmp");
00284 FILE *f = fopen(name, "wb+");
00285 free(name);
00286 return f;
00287 #endif
00288 }
00289
00290
00291 WvString wvtmpfilename(WvStringParm prefix)
00292 {
00293 #ifndef _WIN32 // tmpfile() is really the best choice, when it works
00294 WvString tmpname("/tmp/%sXXXXXX", prefix);
00295 int fd;
00296 if ((fd = mkstemp(tmpname.edit())) == (-1))
00297 return WvString();
00298 close(fd);
00299 #else
00300 WvString tmpname(_tempnam("c:\\temp", prefix.cstr()));
00301 int fd;
00302 fd = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, 0777);
00303 if (fd < 0)
00304 return WvString::null;
00305 _close(fd);
00306 #endif
00307
00308 return tmpname;
00309 }
00310
00311
00312 mode_t get_umask()
00313 {
00314 mode_t rv = umask(0);
00315 umask(rv);
00316
00317 return rv;
00318 }
00319