コード例 #1
0
ファイル: fs-sis.c プロジェクト: via/dovecot-clouddb
static void fs_sis_replace_hash_file(struct sis_fs_file *file)
{
	const char *hash_fname, *path = fs_file_path(&file->file);
	struct fs *super_fs = file->super->fs;
	string_t *temp_path;
	int ret;

	if (file->hash_input == NULL) {
		/* hash file didn't exist previously. we should be able to
		   create it with link() */
		if (fs_link(super_fs, path, file->hash_path) < 0) {
			if (errno == EEXIST) {
				/* the file was just created. it's probably
				   a duplicate, but it's too much trouble
				   trying to deduplicate it anymore */
			} else {
				i_error("fs-sis: %s", fs_last_error(super_fs));
			}
		}
		return;
	}

	temp_path = t_str_new(256);
	hash_fname = strrchr(file->hash_path, '/');
	if (hash_fname == NULL)
		hash_fname = file->hash_path;
	else {
		str_append_n(temp_path, file->hash_path,
			     (hash_fname-file->hash_path) + 1);
		hash_fname++;
	}
	str_printfa(temp_path, "%s%s.tmp",
		    super_fs->set.temp_file_prefix, hash_fname);

	/* replace existing hash file atomically */
	ret = fs_link(super_fs, path, str_c(temp_path));
	if (ret < 0 && errno == EEXIST) {
		/* either someone's racing us or it's a stale file.
		   try to continue. */
		if (fs_unlink(super_fs, str_c(temp_path)) < 0 &&
		    errno != ENOENT)
			i_error("fs-sis: %s", fs_last_error(super_fs));
		ret = fs_link(super_fs, path, str_c(temp_path));
	}
	if (ret < 0) {
		i_error("fs-sis: %s", fs_last_error(super_fs));
		return;
	}
	if (fs_rename(super_fs, str_c(temp_path), file->hash_path) < 0) {
		if (errno == ENOENT) {
			/* apparently someone else just renamed it. ignore. */
		} else {
			i_error("fs-sis: %s", fs_last_error(super_fs));
		}
		(void)fs_unlink(super_fs, str_c(temp_path));
	}
}
コード例 #2
0
ファイル: fs-sis.c プロジェクト: via/dovecot-clouddb
static bool fs_sis_try_link(struct sis_fs_file *file)
{
	const char *path = fs_file_path(&file->file);
	const struct stat *st;
	struct stat st2;

	st = i_stream_stat(file->hash_input, FALSE);

	/* we can use the existing file */
	if (fs_link(file->super->fs, file->hash_path, path) < 0) {
		if (errno != ENOENT && errno != EMLINK)
			i_error("fs-sis: %s", fs_last_error(file->super->fs));
		/* failed to use link(), continue as if it hadn't been equal */
		return FALSE;
	}
	if (fs_stat(file->super->fs, path, &st2) < 0) {
		i_error("fs-sis: %s", fs_last_error(file->super->fs));
		if (fs_unlink(file->super->fs, path) < 0)
			i_error("fs-sis: %s", fs_last_error(file->super->fs));
		return FALSE;
	}
	if (st->st_ino != st2.st_ino) {
		/* the hashes/ file was already replaced with something else */
		if (fs_unlink(file->super->fs, path) < 0)
			i_error("fs-sis: %s", fs_last_error(file->super->fs));
		return FALSE;
	}
	return TRUE;
}
コード例 #3
0
ファイル: restore.c プロジェクト: bhohbaum/moosefs
int do_link(const char *filename,uint64_t lv,uint32_t ts,char *ptr) {
	uint32_t inode,parent;
	uint8_t name[256];
	EAT(ptr,filename,lv,'(');
	GETU32(inode,ptr);
	EAT(ptr,filename,lv,',');
	GETU32(parent,ptr);
	EAT(ptr,filename,lv,',');
	GETNAME(name,ptr,filename,lv,')');
	EAT(ptr,filename,lv,')');
	return fs_link(ts,inode,parent,strlen((char*)name),name);
}
コード例 #4
0
ファイル: main.c プロジェクト: asegid/rhombus
int main(int argc, char **argv) {
	
	if (argc < 3) {
		fprintf(stderr, "%s: missing operand\n", argv[0]);
		return 1;
	}

	if (argc == 4) {
		if (fs_slink(argv[3], argv[2])) {
			fprintf(stderr, "%s: error: ", argv[0]);
			perror(NULL);
		}
	}
	else {
		if (fs_link(argv[2], argv[1])) {
			fprintf(stderr, "%s: error: ", argv[0]);
			perror(NULL);
		}
	}

	return 0;
}
コード例 #5
0
ファイル: path.c プロジェクト: Dennisbonke/DB-OS
/* This is possibly the lengthiest function in the VFS (possibly in the entire kernel!).
 * It resolves a path until the last name in the path string, and then tries to create
 * a new file with that name. It requires a lot of in-sequence checks for permission,
 * existance, is-a-directory, and so forth. */
struct inode *fs_path_resolve_create_get(const char *path, int flags, mode_t mode, int *result, struct dirent **dirent)
{
	// Step 1: Split the path up into directory to create in, and name of new file.
	int len = strlen(path) + 1;
	char tmp[len];
	memcpy(tmp, path, len);
	char *del = strrchr(tmp, '/');
	if(del)
		*del = 0;
	char *dirpath = del ? tmp : ".";
	char *name = del ? del + 1 : tmp;
	if(dirpath[0] == 0)
		dirpath = "/";
	if(dirent)
		*dirent = 0;
	if(result)
		*result = 0;

	// Step 2: Resolve the target directory.
	struct inode *dir = fs_path_resolve_inode(dirpath, flags, result);
	if(!dir)
		return 0;
	if(!S_ISDIR(dir->mode)) {
		if(result) *result = -ENOTDIR;
		return 0;
	}

	// Step 3: Try to look up the file that we're trying to create.
	struct dirent *test = fs_dirent_lookup(dir, name, strlen(name));
	if(test) {
		// If it was found, return it and its inode.
		if(dirent)
			*dirent = test;
		struct inode *ret = fs_dirent_readinode(test, true);
		if(ret)	
			ret = fs_resolve_mount(ret);
		if(!ret) {
			if(dirent)
				*dirent = 0;
			if(result)
				*result = -EIO;
			vfs_dirent_release(test);
		} else {
			if(!dirent)
				vfs_dirent_release(test);
			if(result)
				*result = 0;
		}
		vfs_icache_put(dir);
		return ret;
	}
	
	// Didn't find the entry. Step 4: Create one.
	if(!vfs_inode_check_permissions(dir, MAY_WRITE, 0)) {
		if(result) *result = -EACCES;
		vfs_icache_put(dir);
		return 0;
	}
	if(dir->nlink == 1) {
		if(result) *result = -ENOSPC;
		vfs_icache_put(dir);
		return 0;
	}

	uint32_t id;
	// Step 4a: Allocate an inode.
	int r = fs_callback_fs_alloc_inode(dir->filesystem, &id);
	if(r) {
		if(result) *result = r;
		vfs_icache_put(dir);
		return 0;
	}

	// Step 4b: Read in that inode, and set some initial values (like creation time).
	struct inode *node = vfs_icache_get(dir->filesystem, id);
	if(!node) {
		vfs_icache_put(dir);
		if(result) *result = -EIO;
		return 0;
	}
	node->mode = mode;
	node->length = 0;
	node->ctime = node->mtime = time_get_epoch();
	vfs_inode_set_dirty(node);
	
	// If we're making a directory, create the . and .. entries.
	if(S_ISDIR(mode)) {
		// Create . and ..
		if(fs_link(node, node, ".", 1, true))
			r = -EPERM;
		if(fs_link(node, dir, "..", 2, true))
			r = -EMLINK;
	}

	// Step 4c: Create the link for the directory entry to the inode.
	r = fs_link(dir, node, name, strlen(name), false);

	if(result)
		*result = !r ? 1 : r;
	if(dirent && !r) {
		*dirent = fs_dirent_lookup(dir, name, strlen(name));
		if(!*dirent && node) {
			vfs_icache_put(node);
			vfs_icache_put(dir);
			if(result)
				*result = -EIO;
			return 0;
		}
	}
	vfs_icache_put(dir);
	return r ? 0 : node;
}