Example #1
0
void fs_sis_try_unlink_hash_file(struct fs *fs, struct fs *super,
                                 const char *path)
{
    struct stat st1, st2;
    const char *dir, *hash, *hash_path, *hash_dir;

    if (fs_sis_path_parse(fs, path, &dir, &hash) == 0 &&
            fs_stat(super, path, &st1) == 0 && st1.st_nlink == 2) {
        /* this may be the last link. if hashes/ file is the same,
           delete it. */
        hash_path = t_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
        if (fs_stat(super, hash_path, &st2) == 0 &&
                st1.st_ino == st2.st_ino &&
                CMP_DEV_T(st1.st_dev, st2.st_dev)) {
            if (fs_unlink(super, hash_path) < 0)
                i_error("%s", fs_last_error(super));
            else {
                /* try to rmdir the hashes/ directory */
                hash_dir = t_strdup_printf("%s/"HASH_DIR_NAME,
                                           dir);
                (void)fs_rmdir(super, hash_dir);
            }
        }
    }
}
Example #2
0
static int
fs_sis_open(struct fs *_fs, const char *path, enum fs_open_mode mode,
	    enum fs_open_flags flags, struct fs_file **file_r)
{
	struct sis_fs *fs = (struct sis_fs *)_fs;
	struct sis_fs_file *file;
	struct fs_file *super;
	const char *dir, *hash;

	if (mode == FS_OPEN_MODE_APPEND) {
		fs_set_error(_fs, "APPEND mode not supported");
		return -1;
	}

	if (fs_open(fs->super, path, mode | flags, &super) < 0) {
		fs_sis_copy_error(fs);
		return -1;
	}

	switch (mode) {
	case FS_OPEN_MODE_RDONLY:
		*file_r = super;
		return 0;
	case FS_OPEN_MODE_CREATE:
	case FS_OPEN_MODE_REPLACE:
		break;
	case FS_OPEN_MODE_APPEND:
		i_unreached();
	}

	if (fs_sis_path_parse(_fs, path, &dir, &hash) < 0)
		return -1;

	file = i_new(struct sis_fs_file, 1);
	file->file.fs = _fs;
	file->file.path = i_strdup(fs_file_path(super));
	file->super = super;
	file->open_mode = mode;
	file->hash = i_strdup(hash);

	/* if hashes/<hash> already exists, open it */
	file->hash_path = i_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
	if (fs_open(fs->super, file->hash_path, FS_OPEN_MODE_RDONLY,
		    &file->hash_file) < 0 && errno != ENOENT) {
		i_error("fs-sis: Couldn't open hash file: %s",
			fs_last_error(fs->super));
	}
	if (file->hash_file != NULL) {
		file->hash_input =
			fs_read_stream(file->hash_file, IO_BLOCK_SIZE);
	}

	*file_r = &file->file;
	return 0;
}
Example #3
0
static struct fs_file *
fs_sis_file_init(struct fs *_fs, const char *path,
		 enum fs_open_mode mode, enum fs_open_flags flags)
{
	struct sis_fs *fs = (struct sis_fs *)_fs;
	struct sis_fs_file *file;
	const char *dir, *hash;

	file = i_new(struct sis_fs_file, 1);
	file->file.fs = _fs;
	file->file.path = i_strdup(path);
	file->fs = fs;
	file->open_mode = mode;
	if (mode == FS_OPEN_MODE_APPEND) {
		fs_set_error(_fs, "APPEND mode not supported");
		return &file->file;
	}

	if (fs_sis_path_parse(_fs, path, &dir, &hash) < 0) {
		fs_set_error(_fs, "Invalid path");
		return &file->file;
	}

	/* if hashes/<hash> already exists, open it */
	file->hash_path = i_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
	file->hash_file = fs_file_init(_fs->parent, file->hash_path,
				       FS_OPEN_MODE_READONLY);

	file->hash_input = fs_read_stream(file->hash_file, IO_BLOCK_SIZE);
	if (i_stream_read(file->hash_input) == -1) {
		/* doesn't exist */
		if (errno != ENOENT) {
			i_error("fs-sis: Couldn't read hash file %s: %m",
				file->hash_path);
		}
		i_stream_destroy(&file->hash_input);
	}

	file->super = fs_file_init(_fs->parent, path, mode | flags);
	return &file->file;
}
void fs_sis_try_unlink_hash_file(struct fs *sis_fs, struct fs_file *super_file)
{
	struct fs_file *hash_file;
	struct stat st1, st2;
	const char *dir, *hash, *hash_path;

	if (fs_sis_path_parse(sis_fs, super_file->path, &dir, &hash) == 0 &&
	    fs_stat(super_file, &st1) == 0 && st1.st_nlink == 2) {
		/* this may be the last link. if hashes/ file is the same,
		   delete it. */
		hash_path = t_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
		hash_file = fs_file_init(super_file->fs, hash_path,
					 FS_OPEN_MODE_READONLY);
		if (fs_stat(hash_file, &st2) == 0 &&
		    st1.st_ino == st2.st_ino &&
		    CMP_DEV_T(st1.st_dev, st2.st_dev)) {
			if (fs_delete(hash_file) < 0)
				i_error("%s", fs_last_error(hash_file->fs));
		}
		fs_file_deinit(&hash_file);
	}
}