2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2004 Net Integration Technologies, Inc.
5 * See wvsyncfile.h for details.
15 #include <wvstringlist.h>
16 #include <wvfileutils.h>
18 #include "wvsyncfile.h"
20 WvSyncFile::WvSyncFile(WvStringParm name
, WvStringParm _rootdir
)
21 : WvSyncObj(name
), rootdir(_rootdir
)
31 bool WvSyncFile::getdata(WvBuf
&out
, off_t ofs
, size_t _size
)
35 // it's a directory. no contents, so we should obviously return
36 // true... but we also have to check if it exists.
38 if (lstat(realname(), &st
) != 0)
43 // if the file is actually a symlink we need to treat that separately.
47 char *buf
= (char *) out
.alloc(size
);
48 if (readlink(realname(), buf
, size
) < 0)
51 err("%s: %s\n", name
, strerror(errno
));
58 // do we need to open the file?
61 fd
= open(realname(), O_RDONLY
);
64 err("%s: %s\n", name
, strerror(errno
));
71 // do we need to seek?
74 lseek(fd
, ofs
, SEEK_SET
);
79 char *b
= (char *) out
.alloc(_size
);
80 assert(b
); // come on, now.
81 size_t bytes
= read(fd
, b
, _size
);
86 out
.unalloc(_size
-bytes
);
88 // ONLY done if end of file!
93 off_t
WvSyncFile::approxsize() const
99 time_t WvSyncFile::findlastmodtime() const
103 if (lstat(realname(), &st
) < 0)
110 WvString
WvSyncFile::findmeta()
114 if (lstat(realname(), &st
) == 0)
127 WvString
uidname(uid
), gidname(gid
);
129 struct passwd
*pw
= getpwuid(uid
);
132 uidname
= pw
->pw_name
;
135 struct group
*gr
= getgrgid(gid
);
138 gidname
= gr
->gr_name
;
142 return WvString("%s:%s:%s:%s:%s", mode
, uidname
, uid
, gidname
, gid
);
146 void WvSyncFile::applymeta(WvStringParm newmeta
, time_t newmtime
)
148 // parse the new meta information
150 l
.split(newmeta
, ":");
151 WvStringList::Iter
i(l
);
156 mode_t newmode
= i
->num();
157 if (!S_ISLNK(mode
) && !S_ISLNK(newmode
))
159 chmod(realname(), newmode
);
164 goto applymeta_error
;
169 WvString uidname
= *i
;
171 if (i
.next()) // we have a uid
174 // if we can get a uid from the uidname given, that's better than
175 // just using the number.
176 struct passwd
*pw
= getpwnam(uidname
);
181 lchown(realname(), uid
, gid
);
184 goto applymeta_error
;
189 WvString gidname
= *i
;
191 if (i
.next()) // we have a gid
194 // if we can get a gid from the gidname given, that's better than
195 // just using the number.
196 struct group
*gr
= getgrnam(gidname
);
201 lchown(realname(), uid
, gid
);
206 goto applymeta_error
;
208 // apply the new mtime
212 utim
.actime
= newmtime
;
213 utim
.modtime
= newmtime
;
214 utime(realname(), &utim
);
220 err("Incomplete metadata received for %s\n", name
);
224 bool WvSyncFile::isunchanged(time_t sometime
, WvStringParm somemeta
) const
226 if (S_ISLNK(mode
) || S_ISDIR(mode
))
227 return somemeta
== getmeta();
229 return somemeta
== getmeta() && sometime
== getlastmodtime();
233 void WvSyncFile::makecopy(WvStringParm newname
) const
235 fcopy(realname(), WvString("%s/%s", rootdir
, newname
));
239 bool WvSyncFile::isdir() const
241 return S_ISDIR(mode
);
245 bool WvSyncFile::isdir(WvStringParm somemeta
) const
248 l
.split(somemeta
, ":");
249 WvStringList::Iter
i(l
);
253 mode_t somemode
= i
->num();
254 return S_ISDIR(somemode
);
257 return WvSyncObj::isdir(somemeta
);
261 bool WvSyncFile::installnew(WvStringParm fname
, WvStringParm newmeta
,
264 // make sure it's safe
265 if (hasbeenmodified())
268 // out with the old...
269 ::unlink(realname());
271 // ...and in with the new.
272 // we need the new mode to do that. It's the thing before the first :
273 mode_t newmode
= atoi(newmeta
);
275 if (S_ISDIR(newmode
))
277 mkdir(realname(), 0700);
279 else if (S_ISLNK(newmode
))
281 WvFile
f(fname
, O_RDONLY
);
285 if (f
.select(-1, true, false))
292 if (symlink((const char *) buf
.get(buf
.used()), realname()))
297 log(WvLog::Debug4
, "Copying from %s to %s\n", fname
, name
);
298 fcopy(fname
, realname());
301 applymeta(newmeta
, newmtime
);