Пример #1
0
int main()
{
	tree_t *urls = tree_open(cmp_str, del_str);
	/*if(fetch_data(urls) < 0) {
		fprintf(stderr, "cannot fetch data\n");
		exit(1);
	}*/
	int min_len;
	min_len	= load_urls("tree.db", urls);
	printf("min len is: %d\n", min_len);
	char *str = "http://metro.co.uk/2016/08/24/rapists-dad-threatened-to-kill-witness-with-rounders-bat-6087084/";
	printf("%s exists? %s\n", str, tree_find(urls, str)==0 ? "yes":"no");
	if(tree_find(urls, str) == 0) {
		tree_del(urls, str);
	}
		
	printf("%s exists? %s\n", str, tree_find(urls, str)==0 ? "yes":"no");
	printf("tree height is: %d\n", urls->root->height);
	printf("root balance factor: %i", tree_node_bf(urls->root->rgt));
	//save_urls(urls);
	
	tree_close(urls);

	return 0;
}
Пример #2
0
int main(int argc, char **argv)
{
	size_t max_path_len = 0;
	int max_depth = 0;

	system("pwd");
	while (*++argv) {
		struct tree *t = tree_open(*argv);
		while (tree_next(t)) {
			size_t path_len = tree_current_pathlen(t);
			int depth = tree_current_depth(t);
			if (path_len > max_path_len)
				max_path_len = path_len;
			if (depth > max_depth)
				max_depth = depth;
			printf("%s\n", tree_current_path(t));
			if (S_ISDIR(tree_current_lstat(t)->st_mode))
				tree_descend(t); /* Descend into every dir. */
		}
		tree_close(t);
		printf("Max path length: %d\n", max_path_len);
		printf("Max depth: %d\n", max_depth);
		printf("Final open count: %d\n", t->openCount);
		printf("Max open count: %d\n", t->maxOpenCount);
		fflush(stdout);
		system("pwd");
	}
	return (0);
}
Пример #3
0
struct nessdb *db_open(struct env *e, const char *dbname) {
	char dbpath[FILE_NAME_MAXLEN];
	struct nessdb *db;
	struct tree *tree;

	memset(dbpath, 0, FILE_NAME_MAXLEN);
	snprintf(dbpath,
	         FILE_NAME_MAXLEN,
	         "%s/%s",
	         e->dir,
	         dbname);
	ness_file_exist(dbpath);

	static struct tree_callback tree_cb = {
		.fetch_node_cb = tree_fetch_node_callback,
		.flush_node_cb = tree_flush_node_callback,
		.fetch_hdr_cb = tree_fetch_hdr_callback,
		.flush_hdr_cb = tree_flush_hdr_callback,
		.free_node_cb = tree_free_node_callback,
		.cache_put_cb = tree_cache_put_callback,
		.node_is_dirty_cb = tree_node_is_dirty_callback,
		.node_set_nondirty_cb = tree_node_set_nondirty_callback,
	};
	tree = tree_open(dbpath, e, &tree_cb);

	db = xcalloc(1, sizeof(*db));
	db->e = e;

    /* struct hdr *tt = (struct hdr *)e->cache->cf_first->hdr; */
    /* printf("=====%d=====",tt->height); */
	db->tree = tree;

	return db;
}
Пример #4
0
/*
 * Write tree to the archive. If pathname is a symbolic link it will be
 * followed. Other symbolic links are stored as such to the archive.
 */
static int
shar_write_tree(struct archive *a, const char *pathname)
{
	struct tree *t;
	const struct stat *lst, *st;
	int error = 0;
	int tree_ret;
	int first;

	assert(a != NULL);
	assert(pathname != NULL);

	t = tree_open(pathname);
	for (first = 1; (tree_ret = tree_next(t)); first = 0) {
		if (tree_ret == TREE_ERROR_DIR) {
			warnx("%s: %s", tree_current_path(t),
			    strerror(tree_errno(t)));
			error = 1;
			continue;
		} else if (tree_ret != TREE_REGULAR)
			continue;
		if ((lst = tree_current_lstat(t)) == NULL) {
			warn("%s", tree_current_path(t));
			error = 1;
			continue;
		}
		/*
		 * If the symlink was given on command line then
		 * follow it rather than write it as symlink.
		 */
		if (first && S_ISLNK(lst->st_mode)) {
			if ((st = tree_current_stat(t)) == NULL) {
				warn("%s", tree_current_path(t));
				error = 1;
				continue;
			}
		} else
			st = lst;

		if (shar_write_entry(a, tree_current_path(t),
		    tree_current_access_path(t), st) != ARCHIVE_OK)
			error = 1;

		tree_descend(t);
	}

	tree_close(t);

	return ((error != 0) ? ARCHIVE_WARN : ARCHIVE_OK);
}
Пример #5
0
YDB ydb_open(char *top_dir,
	     int overcommit_ratio,
	     unsigned long long min_log_size,
	     int flags) {

	log_info(" **** ");
	log_info("ydb_open(%s, %i, %llu, 0x%x)", top_dir, overcommit_ratio, min_log_size, flags);

	/* no minimal limit, but warn */
	if(min_log_size < (MAX_RECORD_SIZE))
		log_warn("min_log_size is low, are you sure? %llu < %i", min_log_size, MAX_RECORD_SIZE);
	// 2GiB maximum for 32-bit platform, we're mmaping the file on load
	if(sizeof(char*) == 4 && min_log_size >= (1<<31))
		log_warn("min_log_size is greater than 1<<31 on 32 bit machine. That's brave.");
	
	struct db *db = (struct db *)zmalloc(sizeof(struct db));
	db->tree = (struct tree *)zmalloc(sizeof(struct tree));
	db->loglist = (struct loglist *)zmalloc(sizeof(struct loglist));
	db->magic = YDB_STRUCT_MAGIC;
	db->top_dir = strdup(top_dir);
	db->overcommit_ratio = overcommit_ratio;
	db->lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
	db->flags = flags;
	
	int tree_fileno = tree_get_max_fileno(top_dir);
	
	int logno = 0;
	u64 record_offset = 0;
	if(tree_open(db->tree, db, tree_fileno, top_dir, &logno, &record_offset, flags) < 0) {
		if(!(flags & YDB_CREAT)) {
			log_error("Failed to load index file from %s", top_dir);
			/* TODO: memleaks here */
			return(NULL);
		}
	}
	
	int r = loglist_open(db->loglist, db, top_dir, min_log_size, max_descriptors());
	if(r < 0){
		/* TODO: memleaks here */
		return(NULL);
	}
	/* rebuild the original tree in memory */
	int record_sz = END_OF_FILE;
	while(1) {
		if(record_sz == END_OF_FILE) {
			/* find an edge */
			struct log *log = slot_get(db->loglist, logno);
			if(log)
				log_info("Loading metadata from log %i/0x%x, offsets %lli-%lli", logno, logno, record_offset, log->file_size);

		}
		char key[MAX_KEY_SIZE];
		u16 key_sz = MAX_KEY_SIZE-1;
		int flags;
		u64 value_offset;
		u32 value_sz;
	
		record_sz = loglist_get_record(db->loglist,
					logno, record_offset,
					key, &key_sz,
					&value_offset, &value_sz,
					&flags);
		if(record_sz == END_OF_FILE) {
			logno++;
			record_offset = 0;
			continue;
		}
		if(record_sz == NO_MORE_DATA)
			break;
		
		if(FLAG_DELETE & flags) {
			tree_del(db->tree, key, key_sz, logno, record_offset);
		}else{
			tree_add(db->tree, key, key_sz, logno, value_offset, value_sz, record_offset);
		}
		record_offset += record_sz;
	}
	
	/* Compare used logs */
	int start = MIN(rarr_min(db->tree->refcnt), rarr_min(db->loglist->logs));
	int stop  = MAX(rarr_max(db->tree->refcnt), rarr_max(db->loglist->logs));
	for(logno=start; logno<stop; logno++) {
		uint refcnt = refcnt_get(db->tree, logno);
		struct log *log = slot_get(db->loglist, logno);
		if(refcnt == 0 && log == NULL)
			continue;
		if(refcnt && log)
			continue;
		if(refcnt) {
			log_error("Log %i(0x%x) used, but file is not readable!", logno, logno);
			log_error("Sorry to say but you'd lost %i keys.", refcnt);
			log_error("Closing db");
			/*  we're in inconsistent state */
			db_close(db);
			return(NULL);
		}
		if(log)
			continue;
	}
	
	log_info("Memory footprint of a single key: %i+key_sz", sizeof(struct item));
	print_stats(db);
	return(db);
}
Пример #6
0
/*
 * Add the file or dir hierarchy named by 'path' to the archive
 */
static void
write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
{
	struct archive_entry *entry = NULL, *spare_entry = NULL;
	struct tree *tree;
	char symlink_mode = bsdtar->symlink_mode;
	dev_t first_dev = 0;
	int dev_recorded = 0;
	int tree_ret;

	tree = tree_open(path);

	if (!tree) {
		lafe_warnc(errno, "%s: Cannot open", path);
		bsdtar->return_value = 1;
		return;
	}

	while ((tree_ret = tree_next(tree)) != 0) {
		int r;
		const char *name = tree_current_path(tree);
		const struct stat *st = NULL; /* info to use for this entry */
		const struct stat *lst = NULL; /* lstat() information */
		int descend;

		if (tree_ret == TREE_ERROR_FATAL)
			lafe_errc(1, tree_errno(tree),
			    "%s: Unable to continue traversing directory tree",
			    name);
		if (tree_ret == TREE_ERROR_DIR) {
			lafe_warnc(errno,
			    "%s: Couldn't visit directory", name);
			bsdtar->return_value = 1;
		}
		if (tree_ret != TREE_REGULAR)
			continue;

		/*
		 * If this file/dir is excluded by a filename
		 * pattern, skip it.
		 */
		if (lafe_excluded(bsdtar->matching, name))
			continue;

		/*
		 * Get lstat() info from the tree library.
		 */
		lst = tree_current_lstat(tree);
		if (lst == NULL) {
			/* Couldn't lstat(); must not exist. */
			lafe_warnc(errno, "%s: Cannot stat", name);
			/* Return error if files disappear during traverse. */
			bsdtar->return_value = 1;
			continue;
		}

		/*
		 * Distinguish 'L'/'P'/'H' symlink following.
		 */
		switch(symlink_mode) {
		case 'H':
			/* 'H': After the first item, rest like 'P'. */
			symlink_mode = 'P';
			/* 'H': First item (from command line) like 'L'. */
			/* FALLTHROUGH */
		case 'L':
			/* 'L': Do descend through a symlink to dir. */
			descend = tree_current_is_dir(tree);
			/* 'L': Follow symlinks to files. */
			archive_read_disk_set_symlink_logical(bsdtar->diskreader);
			/* 'L': Archive symlinks as targets, if we can. */
			st = tree_current_stat(tree);
			if (st != NULL)
				break;
			/* If stat fails, we have a broken symlink;
			 * in that case, don't follow the link. */
			/* FALLTHROUGH */
		default:
			/* 'P': Don't descend through a symlink to dir. */
			descend = tree_current_is_physical_dir(tree);
			/* 'P': Don't follow symlinks to files. */
			archive_read_disk_set_symlink_physical(bsdtar->diskreader);
			/* 'P': Archive symlinks as symlinks. */
			st = lst;
			break;
		}

		if (bsdtar->option_no_subdirs)
			descend = 0;

		/*
		 * Are we about to cross to a new filesystem?
		 */
		if (!dev_recorded) {
			/* This is the initial file system. */
			first_dev = lst->st_dev;
			dev_recorded = 1;
		} else if (lst->st_dev == first_dev) {
			/* The starting file system is always acceptable. */
		} else if (descend == 0) {
			/* We're not descending, so no need to check. */
		} else if (bsdtar->option_dont_traverse_mounts) {
			descend = 0;
		} else {
			/* We're prepared to cross a mount point. */

			/* XXX TODO: check whether this filesystem is
			 * synthetic and/or local.  Add a new
			 * --local-only option to skip non-local
			 * filesystems.  Skip synthetic filesystems
			 * regardless.
			 *
			 * The results should be cached, since
			 * tree.c doesn't usually visit a directory
			 * and the directory contents together.  A simple
			 * move-to-front list should perform quite well.
			 *
			 * This is going to be heavily OS dependent:
			 * FreeBSD's statfs() in conjunction with getvfsbyname()
			 * provides all of this; NetBSD's statvfs() does
			 * most of it; other systems will vary.
			 */
		}

		/*
		 * In -u mode, check that the file is newer than what's
		 * already in the archive; in all modes, obey --newerXXX flags.
		 */
		if (!new_enough(bsdtar, name, st)) {
			if (!descend)
				continue;
			if (bsdtar->option_interactive &&
			    !yes("add '%s'", name))
				continue;
			tree_descend(tree);
			continue;
		}

		archive_entry_free(entry);
		entry = archive_entry_new();

		archive_entry_set_pathname(entry, name);
		archive_entry_copy_sourcepath(entry,
		    tree_current_access_path(tree));

		/* Populate the archive_entry with metadata from the disk. */
		/* XXX TODO: Arrange to open a regular file before
		 * calling this so we can pass in an fd and shorten
		 * the race to query metadata.  The linkify dance
		 * makes this more complex than it might sound. */
#if defined(_WIN32) && !defined(__CYGWIN__)
		/* TODO: tree.c uses stat(), which is badly broken
		 * on Windows.  To fix this, we should
		 * deprecate tree_current_stat() and provide a new
		 * call tree_populate_entry(t, entry).  This call
		 * would use stat() internally on POSIX and
		 * GetInfoByFileHandle() internally on Windows.
		 * This would be another step towards a tree-walker
		 * that can be integrated deep into libarchive.
		 * For now, just set st to NULL on Windows;
		 * archive_read_disk_entry_from_file() should
		 * be smart enough to use platform-appropriate
		 * ways to probe file information.
		 */
		st = NULL;
#endif
		r = archive_read_disk_entry_from_file(bsdtar->diskreader,
		    entry, -1, st);
		if (bsdtar->uid >= 0) {
			archive_entry_set_uid(entry, bsdtar->uid);
			if (!bsdtar->uname)
				archive_entry_set_uname(entry,
				    archive_read_disk_uname(bsdtar->diskreader,
					bsdtar->uid));
		}
		if (bsdtar->gid >= 0) {
			archive_entry_set_gid(entry, bsdtar->gid);
			if (!bsdtar->gname)
				archive_entry_set_gname(entry,
				    archive_read_disk_gname(bsdtar->diskreader,
					bsdtar->gid));
		}
		if (bsdtar->uname)
			archive_entry_set_uname(entry, bsdtar->uname);
		if (bsdtar->gname)
			archive_entry_set_gname(entry, bsdtar->gname);
		if (r != ARCHIVE_OK)
			lafe_warnc(archive_errno(bsdtar->diskreader),
			    "%s", archive_error_string(bsdtar->diskreader));
		if (r < ARCHIVE_WARN)
			continue;

		/* XXX TODO: Just use flag data from entry; avoid the
		 * duplicate check here. */

		/*
		 * If this file/dir is flagged "nodump" and we're
		 * honoring such flags, skip this file/dir.
		 */
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
		/* BSD systems store flags in struct stat */
		if (bsdtar->option_honor_nodump &&
		    (lst->st_flags & UF_NODUMP))
			continue;
#endif

#if defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL)
		/* Linux uses ioctl to read flags. */
		if (bsdtar->option_honor_nodump) {
			int fd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY);
			if (fd >= 0) {
				unsigned long fflags;
				int r = ioctl(fd, EXT2_IOC_GETFLAGS, &fflags);
				close(fd);
				if (r >= 0 && (fflags & EXT2_NODUMP_FL))
					continue;
			}
		}
#endif

#ifdef __APPLE__
		if (bsdtar->enable_copyfile) {
			/* If we're using copyfile(), ignore "._XXX" files. */
			const char *bname = strrchr(name, '/');
			if (bname == NULL)
				bname = name;
			else
				++bname;
			if (bname[0] == '.' && bname[1] == '_')
				continue;
		} else {
			/* If not, drop the copyfile() data. */
			archive_entry_copy_mac_metadata(entry, NULL, 0);
		}
#endif

		/*
		 * If the user vetoes this file/directory, skip it.
		 * We want this to be fairly late; if some other
		 * check would veto this file, we shouldn't bother
		 * the user with it.
		 */
		if (bsdtar->option_interactive &&
		    !yes("add '%s'", name))
			continue;

		if (descend)
			tree_descend(tree);

		/*
		 * Rewrite the pathname to be archived.  If rewrite
		 * fails, skip the entry.
		 */
		if (edit_pathname(bsdtar, entry))
			continue;

		/* Display entry as we process it.
		 * This format is required by SUSv2. */
		if (bsdtar->verbose)
			safe_fprintf(stderr, "a %s",
			    archive_entry_pathname(entry));

		/* Non-regular files get archived with zero size. */
		if (archive_entry_filetype(entry) != AE_IFREG)
			archive_entry_set_size(entry, 0);

		archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry);

		while (entry != NULL) {
			write_file(bsdtar, a, entry);
			archive_entry_free(entry);
			entry = spare_entry;
			spare_entry = NULL;
		}

		if (bsdtar->verbose)
			fprintf(stderr, "\n");
	}
	archive_entry_free(entry);
	tree_close(tree);
}
Пример #7
0
/*
 * Add the file or dir hierarchy named by 'path' to the archive
 */
static void
write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
{
	struct archive_entry *entry = NULL, *spare_entry = NULL;
	struct tree *tree;
	char symlink_mode = bsdtar->symlink_mode;
	dev_t first_dev = 0;
	int dev_recorded = 0;
	int tree_ret;
	dev_t last_dev = 0;
	char * fstype;

	tree = tree_open(path);

	if (!tree) {
		bsdtar_warnc(bsdtar, errno, "%s: Cannot open", path);
		bsdtar->return_value = 1;
		return;
	}

	while ((tree_ret = tree_next(tree))) {
		int r;
		const char *name = tree_current_path(tree);
		const struct stat *st = NULL; /* info to use for this entry */
		const struct stat *lst = NULL; /* lstat() information */
		int descend;

		if (truncate_archive(bsdtar))
			break;
		if (checkpoint_archive(bsdtar, 0))
			exit(1);
		disk_pause(bsdtar);
		if (network_select(0))
			exit(1);

		if (tree_ret == TREE_ERROR_FATAL)
			bsdtar_errc(bsdtar, 1, tree_errno(tree),
			    "%s: Unable to continue traversing directory tree",
			    name);
		if (tree_ret == TREE_ERROR_DIR) {
			bsdtar_warnc(bsdtar, errno,
			    "%s: Couldn't visit directory", name);
			bsdtar->return_value = 1;
		}
		if (tree_ret != TREE_REGULAR)
			continue;

		/*
		 * If this file/dir is excluded by a filename
		 * pattern, skip it.
		 */
		if (excluded(bsdtar, name))
			continue;

		/*
		 * Get lstat() info from the tree library.
		 */
		lst = tree_current_lstat(tree);
		if (lst == NULL) {
			/* Couldn't lstat(); must not exist. */
			bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name);
			/* Return error if files disappear during traverse. */
			bsdtar->return_value = 1;
			continue;
		}

		/*
		 * Distinguish 'L'/'P'/'H' symlink following.
		 */
		switch(symlink_mode) {
		case 'H':
			/* 'H': After the first item, rest like 'P'. */
			symlink_mode = 'P';
			/* 'H': First item (from command line) like 'L'. */
			/* FALLTHROUGH */
		case 'L':
			/* 'L': Do descend through a symlink to dir. */
			descend = tree_current_is_dir(tree);
			/* 'L': Follow symlinks to files. */
			archive_read_disk_set_symlink_logical(bsdtar->diskreader);
			/* 'L': Archive symlinks as targets, if we can. */
			st = tree_current_stat(tree);
			if (st != NULL)
				break;
			/* If stat fails, we have a broken symlink;
			 * in that case, don't follow the link. */
			/* FALLTHROUGH */
		default:
			/* 'P': Don't descend through a symlink to dir. */
			descend = tree_current_is_physical_dir(tree);
			/* 'P': Don't follow symlinks to files. */
			archive_read_disk_set_symlink_physical(bsdtar->diskreader);
			/* 'P': Archive symlinks as symlinks. */
			st = lst;
			break;
		}

		if (bsdtar->option_no_subdirs)
			descend = 0;

		/*
		 * If user has asked us not to cross mount points,
		 * then don't descend into a dir on a different
		 * device.
		 */
		if (!dev_recorded) {
			last_dev = first_dev = lst->st_dev;
			dev_recorded = 1;
		}
		if (bsdtar->option_dont_traverse_mounts) {
			if (lst->st_dev != first_dev)
				descend = 0;
		}

		/*
		 * If the user did not specify --insane-filesystems, do not
		 * cross into a new filesystem which is known to be synthetic.
		 * Note that we will archive synthetic filesystems if we are
		 * explicitly told to do so.
		 */
		if ((bsdtar->option_insane_filesystems == 0) &&
		    (descend != 0) &&
		    (lst->st_dev != last_dev)) {
			fstype = getfstype(tree_current_access_path(tree));
			if (fstype == NULL)
				bsdtar_errc(bsdtar, 1, errno,
				    "%s: Error getting filesystem type",
				    name);
			if (getfstype_issynthetic(fstype)) {
				if (!bsdtar->option_quiet)
					bsdtar_warnc(bsdtar, 0,
					    "Not descending into filesystem of type %s: %s",
					    fstype, name);
				descend = 0;
			} else {
				/* This device is ok to archive. */
				last_dev = lst->st_dev;
			}
			free(fstype);
		}

		/*
		 * In -u mode, check that the file is newer than what's
		 * already in the archive; in all modes, obey --newerXXX flags.
		 */
		if (!new_enough(bsdtar, name, st)) {
			if (!descend)
				continue;
			if (bsdtar->option_interactive &&
			    !yes("add '%s'", name))
				continue;
			tree_descend(tree);
			continue;
		}

		archive_entry_free(entry);
		entry = archive_entry_new();

		archive_entry_set_pathname(entry, name);
		archive_entry_copy_sourcepath(entry,
		    tree_current_access_path(tree));

		/* Populate the archive_entry with metadata from the disk. */
		/* XXX TODO: Arrange to open a regular file before
		 * calling this so we can pass in an fd and shorten
		 * the race to query metadata.  The linkify dance
		 * makes this more complex than it might sound. */
		r = archive_read_disk_entry_from_file(bsdtar->diskreader,
		    entry, -1, st);
		if (r != ARCHIVE_OK)
			bsdtar_warnc(bsdtar, archive_errno(bsdtar->diskreader),
			    "%s", archive_error_string(bsdtar->diskreader));
		if (r < ARCHIVE_WARN)
			continue;

		/* XXX TODO: Just use flag data from entry; avoid the
		 * duplicate check here. */

		/*
		 * If this file/dir is flagged "nodump" and we're
		 * honoring such flags, skip this file/dir.
		 */
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
		/* BSD systems store flags in struct stat */
		if (bsdtar->option_honor_nodump &&
		    (lst->st_flags & UF_NODUMP))
			continue;
#endif

#if defined(EXT2_NODUMP_FL)
		/* Linux uses ioctl to read flags. */
		if (bsdtar->option_honor_nodump) {
			unsigned long fflags, dummy;
			archive_entry_fflags(entry, &fflags, &dummy);
			if (fflags & EXT2_NODUMP_FL)
				continue;
		}
#endif

		/*
		 * Don't back up the cache directory or any files inside it.
		 */
		if ((lst->st_ino == bsdtar->cachedir_ino) &&
		    (lst->st_dev == bsdtar->cachedir_dev)) {
			if (!bsdtar->option_quiet)
				bsdtar_warnc(bsdtar, 0,
				    "Not adding cache directory to archive: %s",
				name);
			continue;
		}

		/*
		 * If the user vetoes this file/directory, skip it.
		 * We want this to be fairly late; if some other
		 * check would veto this file, we shouldn't bother
		 * the user with it.
		 */
		if (bsdtar->option_interactive &&
		    !yes("add '%s'", name))
			continue;

		/* Note: if user vetoes, we won't descend. */
		if (descend)
			tree_descend(tree);

		/*
		 * Rewrite the pathname to be archived.  If rewrite
		 * fails, skip the entry.
		 */
		if (edit_pathname(bsdtar, entry))
			continue;

		/*
		 * If this is a socket, skip the entry: POSIX requires that
		 * pax(1) emit a "diagnostic message" (i.e., warning) that
		 * sockets cannot be archived, but this can make backups of
		 * running systems very noisy.
		 */
		if (S_ISSOCK(st->st_mode))
			continue;

		/* Display entry as we process it.
		 * This format is required by SUSv2. */
		if (bsdtar->verbose)
			safe_fprintf(stderr, "a %s",
			    archive_entry_pathname(entry));

		/*
		 * If the user hasn't specifically asked to have the access
		 * time stored, zero it.  At the moment this usually only
		 * matters for files which have flags set, since the "posix
		 * restricted" format doesn't store access times for most
		 * other files.
		 */
		if (bsdtar->option_store_atime == 0)
			archive_entry_set_atime(entry, 0, 0);

		/* Non-regular files get archived with zero size. */
		if (!S_ISREG(st->st_mode))
			archive_entry_set_size(entry, 0);

		/* Record what we're doing, for SIGINFO / SIGUSR1. */
		siginfo_setinfo(bsdtar, "adding",
		    archive_entry_pathname(entry), archive_entry_size(entry));
		archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry);

		/* Handle SIGINFO / SIGUSR1 request if one was made. */
		siginfo_printinfo(bsdtar, 0);

		while (entry != NULL) {
			write_entry_backend(bsdtar, a, entry, st,
			    tree_current_realpath(tree));
			archive_entry_free(entry);
			entry = spare_entry;
			spare_entry = NULL;
		}

		if (bsdtar->verbose)
			fprintf(stderr, "\n");
	}
	archive_entry_free(entry);
	if (tree_close(tree))
		bsdtar_errc(bsdtar, 1, 0, "Error traversing directory tree");
}
Пример #8
0
static void
create(const char *filename, int compress, const char **argv)
{
    struct archive *a;
    struct archive *disk;
    struct archive_entry *entry;
    ssize_t len;
    int fd;

    a = archive_write_new();
    switch (compress) {
#ifndef NO_BZIP2_CREATE
    case 'j': case 'y':
        archive_write_set_compression_bzip2(a);
        break;
#endif
#ifndef NO_COMPRESS_CREATE
    case 'Z':
        archive_write_set_compression_compress(a);
        break;
#endif
#ifndef NO_GZIP_CREATE
    case 'z':
        archive_write_set_compression_gzip(a);
        break;
#endif
    default:
        archive_write_set_compression_none(a);
        break;
    }
    archive_write_set_format_ustar(a);
    if (strcmp(filename, "-") == 0)
        filename = NULL;
    archive_write_open_file(a, filename);

    disk = archive_read_disk_new();
#ifndef NO_LOOKUP
    archive_read_disk_set_standard_lookup(disk);
#endif
    while (*argv != NULL) {
        struct tree *t = tree_open(*argv);
        while (tree_next(t)) {
            entry = archive_entry_new();
            archive_entry_set_pathname(entry, tree_current_path(t));
            archive_read_disk_entry_from_file(disk, entry, -1,
                tree_current_stat(t));
            if (verbose) {
                msg("a ");
                msg(tree_current_path(t));
            }
            archive_write_header(a, entry);
            fd = open(tree_current_access_path(t), O_RDONLY);
            len = read(fd, buff, sizeof(buff));
            while (len > 0) {
                archive_write_data(a, buff, len);
                len = read(fd, buff, sizeof(buff));
            }
            close(fd);
            archive_entry_free(entry);
            if (verbose)
                msg("\n");
        }
        argv++;
    }
    archive_write_close(a);
    archive_write_finish(a);
}
Пример #9
0
/*
 * Add the file or dir hierarchy named by 'path' to the archive
 */
static void
write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
{
	struct archive_entry *entry = NULL, *spare_entry = NULL;
	struct tree *tree;
	char symlink_mode = bsdtar->symlink_mode;
	dev_t first_dev = 0;
	int dev_recorded = 0;
	int tree_ret;

	tree = tree_open(path);

	if (!tree) {
		bsdtar_warnc(bsdtar, errno, "%s: Cannot open", path);
		bsdtar->return_value = 1;
		return;
	}

	while ((tree_ret = tree_next(tree))) {
		int r;
		const char *name = tree_current_path(tree);
		const struct stat *st = NULL; /* info to use for this entry */
		const struct stat *lst = NULL; /* lstat() information */
		int descend;

		if (tree_ret == TREE_ERROR_FATAL)
			bsdtar_errc(bsdtar, 1, tree_errno(tree),
			    "%s: Unable to continue traversing directory tree",
			    name);
		if (tree_ret == TREE_ERROR_DIR) {
			bsdtar_warnc(bsdtar, errno,
			    "%s: Couldn't visit directory", name);
			bsdtar->return_value = 1;
		}
		if (tree_ret != TREE_REGULAR)
			continue;

		/*
		 * If this file/dir is excluded by a filename
		 * pattern, skip it.
		 */
		if (excluded(bsdtar, name))
			continue;

		/*
		 * Get lstat() info from the tree library.
		 */
		lst = tree_current_lstat(tree);
		if (lst == NULL) {
			/* Couldn't lstat(); must not exist. */
			bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name);
			/* Return error if files disappear during traverse. */
			bsdtar->return_value = 1;
			continue;
		}

		/*
		 * Distinguish 'L'/'P'/'H' symlink following.
		 */
		switch(symlink_mode) {
		case 'H':
			/* 'H': After the first item, rest like 'P'. */
			symlink_mode = 'P';
			/* 'H': First item (from command line) like 'L'. */
			/* FALLTHROUGH */
		case 'L':
			/* 'L': Do descend through a symlink to dir. */
			descend = tree_current_is_dir(tree);
			/* 'L': Follow symlinks to files. */
			archive_read_disk_set_symlink_logical(bsdtar->diskreader);
			/* 'L': Archive symlinks as targets, if we can. */
			st = tree_current_stat(tree);
			if (st != NULL)
				break;
			/* If stat fails, we have a broken symlink;
			 * in that case, don't follow the link. */
			/* FALLTHROUGH */
		default:
			/* 'P': Don't descend through a symlink to dir. */
			descend = tree_current_is_physical_dir(tree);
			/* 'P': Don't follow symlinks to files. */
			archive_read_disk_set_symlink_physical(bsdtar->diskreader);
			/* 'P': Archive symlinks as symlinks. */
			st = lst;
			break;
		}

		/*
		 * If user has asked us not to cross mount points,
		 * then don't descend into into a dir on a different
		 * device.
		 */
		if (!dev_recorded) {
			first_dev = lst->st_dev;
			dev_recorded = 1;
		}
		if (bsdtar->option_dont_traverse_mounts) {
			if (lst->st_dev != first_dev)
				descend = 0;
		}

		/*
		 * In -u mode, check that the file is newer than what's
		 * already in the archive; in all modes, obey --newerXXX flags.
		 */
		if (!new_enough(bsdtar, name, st))
			continue;

		archive_entry_free(entry);
		entry = archive_entry_new();

		archive_entry_set_pathname(entry, name);
		archive_entry_copy_sourcepath(entry,
		    tree_current_access_path(tree));

		/* Populate the archive_entry with metadata from the disk. */
		/* XXX TODO: Arrange to open a regular file before
		 * calling this so we can pass in an fd and shorten
		 * the race to query metadata.  The linkify dance
		 * makes this more complex than it might sound. */
		r = archive_read_disk_entry_from_file(bsdtar->diskreader,
		    entry, -1, st);
		if (r != ARCHIVE_OK)
			bsdtar_warnc(bsdtar, archive_errno(bsdtar->diskreader),
			    archive_error_string(bsdtar->diskreader));
		if (r < ARCHIVE_WARN)
			continue;

		/* XXX TODO: Just use flag data from entry; avoid the
		 * duplicate check here. */

		/*
		 * If this file/dir is flagged "nodump" and we're
		 * honoring such flags, skip this file/dir.
		 */
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
		/* BSD systems store flags in struct stat */
		if (bsdtar->option_honor_nodump &&
		    (lst->st_flags & UF_NODUMP))
			continue;
#endif

#if defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL)
		/* Linux uses ioctl to read flags. */
		if (bsdtar->option_honor_nodump) {
			int fd = open(name, O_RDONLY | O_NONBLOCK);
			if (fd >= 0) {
				unsigned long fflags;
				int r = ioctl(fd, EXT2_IOC_GETFLAGS, &fflags);
				close(fd);
				if (r >= 0 && (fflags & EXT2_NODUMP_FL))
					continue;
			}
		}
#endif

		/*
		 * If the user vetoes this file/directory, skip it.
		 * We want this to be fairly late; if some other
		 * check would veto this file, we shouldn't bother
		 * the user with it.
		 */
		if (bsdtar->option_interactive &&
		    !yes("add '%s'", name))
			continue;

		/* Note: if user vetoes, we won't descend. */
		if (descend && !bsdtar->option_no_subdirs)
			tree_descend(tree);

		/*
		 * Rewrite the pathname to be archived.  If rewrite
		 * fails, skip the entry.
		 */
		if (edit_pathname(bsdtar, entry))
			continue;

		/* Display entry as we process it.
		 * This format is required by SUSv2. */
		if (bsdtar->verbose)
			safe_fprintf(stderr, "a %s",
			    archive_entry_pathname(entry));

		/* Non-regular files get archived with zero size. */
		if (!S_ISREG(st->st_mode))
			archive_entry_set_size(entry, 0);

		/* Record what we're doing, for SIGINFO / SIGUSR1. */
		siginfo_setinfo(bsdtar, "adding",
		    archive_entry_pathname(entry), archive_entry_size(entry));
		archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry);

		/* Handle SIGINFO / SIGUSR1 request if one was made. */
		siginfo_printinfo(bsdtar, 0);

		while (entry != NULL) {
			write_entry_backend(bsdtar, a, entry);
			archive_entry_free(entry);
			entry = spare_entry;
			spare_entry = NULL;
		}

		if (bsdtar->verbose)
			fprintf(stderr, "\n");
	}
	archive_entry_free(entry);
	tree_close(tree);
}