fs-api.c revision fdef08644ba66b9db8fe4fc041ecc31a1ec9524b
/* Copyright (c) 2010-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "module-dir.h"
#include "llist.h"
#include "str.h"
#include "hash-method.h"
#include "istream.h"
#include "istream-seekable.h"
#include "ostream.h"
#include "timing.h"
#include "time-util.h"
#include "istream-fs-stats.h"
#include "fs-api-private.h"
struct fs_api_module_register fs_api_module_register = { 0 };
static void fs_classes_init(void);
static int
{
int ret;
T_BEGIN {
} T_END;
if (ret < 0) {
/* a bit kludgy way to allow data stack frame usage in normal
conditions but still be able to return error message from
data stack. */
fs_last_error(fs));
return -1;
}
return 0;
}
{
if (!array_is_created(&fs_classes))
}
static void fs_classes_deinit(void)
{
}
static void fs_classes_init(void)
{
}
{
if (!array_is_created(&fs_classes))
return *classp;
}
return NULL;
}
static void fs_class_deinit_modules(void)
{
}
static const char *fs_driver_module_name(const char *driver)
{
}
static void fs_class_try_load_plugin(const char *driver)
{
const char *module_name =
struct module_dir_load_settings mod_set;
module_name, &mod_set);
}
const struct fs_settings *set,
{
const char *temp_file_prefix;
unsigned int i;
T_BEGIN {
} T_END;
}
return -1;
}
return -1;
for (i = 0; i < FS_OP_COUNT; i++)
else
return 0;
}
{
}
{
}
{
unsigned int i;
return;
if (fs->files_open_count > 0) {
i_panic("fs-%s: %u files still open (first = %s)",
}
for (i = 0; i < FS_OP_COUNT; i++)
T_BEGIN {
} T_END;
}
{
}
{
}
{
}
{
(mode_flags & FS_OPEN_FLAG_ASYNC) != 0);
T_BEGIN {
} T_END;
fs->files_open_count++;
return file;
}
{
T_BEGIN {
} T_END;
if (metadata_pool != NULL)
}
{
}
} T_END;
/* check this only after closing, because some of the fs backends keep
the istream internally open and don't call the destroy-callback
until after file_close() */
}
{
}
{
}
}
{
else T_BEGIN {
const struct fs_metadata *md;
strlen(FS_METADATA_INTERNAL_PREFIX)) == 0)
}
} T_END;
}
{
struct fs_metadata *metadata;
}
{
} T_END;
}
{
return;
i_fatal("gettimeofday() failed: %m");
}
}
static void
{
long long diff;
i_fatal("gettimeofday() failed: %m");
if (diff > 0)
}
{
return;
/* don't count this again */
}
{
int ret;
return -1;
}
if (!file->read_or_prefetch_counted &&
}
T_BEGIN {
} T_END;
return ret;
}
const char **value_r)
{
const struct fs_metadata *md;
return -1;
return 1;
}
}
return 0;
}
{
}
{
}
static void ATTR_FORMAT(2, 0)
{
/* the error is always kept in the parentmost fs */
else {
}
}
{
/* the error is always kept in the parentmost fs */
return "BUG: Unknown fs error";
}
{
}
{
bool ret;
if (!file->read_or_prefetch_counted) {
}
T_BEGIN {
} T_END;
return ret;
}
{
const unsigned char *data;
if (ret == 0) {
return -1;
}
} else {
}
return ret;
}
{
int ret;
if (!file->read_or_prefetch_counted) {
}
T_BEGIN {
} T_END;
return ret;
}
/* backend didn't bother to implement read(), but we can do it with
streams. */
}
{
}
{
const unsigned char *data;
bool want_seekable = FALSE;
if (!file->read_or_prefetch_counted) {
}
/* allow multiple open streams, each in a different position */
i_stream_seek(input, 0);
return input;
}
T_BEGIN {
} T_END;
if (input->stream_errno != 0) {
/* read failed already */
return input;
}
}
/* need to make the stream seekable */
i_stream_unref(&inputs[0]);
}
/* read the whole input stream before returning */
if (ret == 0)
}
i_stream_seek(input, 0);
}
return input;
}
{
int err;
if (!file->write_pending) {
return -1;
}
} else {
}
if (ret == 0) {
return -1;
}
return ret < 0 ? -1 : 0;
}
{
int ret;
T_BEGIN {
} T_END;
}
return ret;
}
/* backend didn't bother to implement write(), but we can do it with
streams. */
}
{
T_BEGIN {
} T_END;
}
{
int ret;
T_BEGIN {
} T_END;
if (ret != 0) {
} else {
/* write didn't finish yet. this shouldn't happen if we
indicated a failure. */
}
if (ret != 0) {
}
return ret;
}
{
}
}
}
{
}
{
int ret;
/* make sure we don't have an old error lying around */
}
void fs_write_stream_abort_error(struct fs_file *file, struct ostream **output, const char *error_fmt, ...)
{
}
{
}
const void *digest)
{
}
void *context)
{
else
}
{
/* recursion not allowed */
} T_END;
}
{
T_BEGIN {
} T_END;
}
return ret;
}
{
int ret;
T_BEGIN {
} T_END;
return ret;
}
{
T_BEGIN {
} T_END;
}
{
int ret;
/* fallback to stat() */
return 1;
else
}
T_BEGIN {
} T_END;
}
return ret;
}
{
int ret;
return -1;
}
if (!file->read_or_prefetch_counted &&
}
T_BEGIN {
} T_END;
return ret;
}
{
int ret;
return -1;
return 0;
}
if (!file->read_or_prefetch_counted &&
}
T_BEGIN {
} T_END;
return ret;
}
{
int tmp_errno;
/* we're going to be counting this as read+write, so remove the
copy_count we just added */
if (fs_write_stream_finish_async(dest) <= 0)
return -1;
return 0;
}
} else {
}
break;
return -1;
"read(%s) failed: %s",
return -1;
/* errno might not survive abort error */
"write(%s) failed: %s",
return -1;
}
return -1;
return 0;
}
{
int ret;
return -1;
}
T_BEGIN {
} T_END;
}
return ret;
}
{
int ret;
T_BEGIN {
} T_END;
}
return ret;
}
{
int ret;
T_BEGIN {
} T_END;
}
return ret;
}
{
int ret;
T_BEGIN {
} T_END;
}
return ret;
}
struct fs_iter *
{
i_fatal("gettimeofday() failed: %m");
}
} else T_BEGIN {
} T_END;
return iter;
}
{
int ret;
ret = -1;
} else T_BEGIN {
} T_END;
return ret;
}
{
const char *ret;
return NULL;
T_BEGIN {
} T_END;
/* first result returned - count this as the finish time, since
we don't want to count the time caller spends on this
iteration. */
/* don't count this again */
}
return ret;
}
void *context)
{
}
{
return iter->async_have_more;
}
{
}
{
}
{
}
{
}
{
}
{
}