+ inode_type = 'f';
+
+ file_size = dumpfile(fd, file_info, path, stat_buf);
+ file_info["size"] = encode_int(file_size);
+
+ if (file_size < 0)
+ return; // error occurred; do not dump file
+
+ if (file_size != stat_buf.st_size) {
+ fprintf(stderr, "Warning: Size of %s changed during reading\n",
+ path.c_str());
+ file_info["volatile"] = "1";
+ }
+
+ break;
+ case S_IFDIR:
+ inode_type = 'd';
+ break;
+
+ default:
+ fprintf(stderr, "Unknown inode type: mode=%x\n", stat_buf.st_mode);
+ return;
+ }
+
+ file_info["type"] = string(1, inode_type);
+
+ metawriter->add(file_info);
+}
+
+void scanfile(const string& path, bool include)
+{
+ int fd = -1;
+ long flags;
+ struct stat stat_buf;
+ list<string> refs;
+
+ string true_path;
+ if (relative_paths)
+ true_path = path;
+ else
+ true_path = "/" + path;
+
+ // Set to true if we should scan through the contents of this directory,
+ // but not actually back files up
+ bool scan_only = false;
+
+ // Check this file against the include/exclude list to see if it should be
+ // considered
+ for (list<string>::iterator i = includes.begin();
+ i != includes.end(); ++i) {
+ if (path == *i) {
+ include = true;
+ }
+ }
+
+ for (list<string>::iterator i = excludes.begin();
+ i != excludes.end(); ++i) {
+ if (path == *i) {
+ include = false;
+ }
+ }
+
+ if (excluded_names.size() > 0) {
+ std::string name = path;
+ std::string::size_type last_slash = name.rfind('/');
+ if (last_slash != std::string::npos) {
+ name.replace(0, last_slash + 1, "");
+ }
+
+ for (list<string>::iterator i = excluded_names.begin();
+ i != excluded_names.end(); ++i) {
+ if (name == *i) {
+ include = false;
+ }
+ }
+ }
+
+ for (list<string>::iterator i = searches.begin();
+ i != searches.end(); ++i) {
+ if (path == *i) {
+ scan_only = true;
+ }
+ }
+
+ if (!include && !scan_only)
+ return;
+
+ if (lstat(true_path.c_str(), &stat_buf) < 0) {
+ fprintf(stderr, "lstat(%s): %m\n", path.c_str());
+ return;
+ }