Logo Search packages:      
Sourcecode: fuse version File versions  Download package

fioc.c
/*
  FUSE fioc: FUSE ioctl example
  Copyright (C) 2008       SUSE Linux Products GmbH
  Copyright (C) 2008       Tejun Heo <teheo@suse.de>

  This program can be distributed under the terms of the GNU GPL.
  See the file COPYING.

  gcc -Wall `pkg-config fuse --cflags --libs` fioc.c -o fioc
*/

#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>

#include "fioc.h"

#define FIOC_NAME "fioc"

enum {
      FIOC_NONE,
      FIOC_ROOT,
      FIOC_FILE,
};

static void *fioc_buf;
static size_t fioc_size;

static int fioc_resize(size_t new_size)
{
      void *new_buf;

      if (new_size == fioc_size)
            return 0;

      new_buf = realloc(fioc_buf, new_size);
      if (!new_buf && new_size)
            return -ENOMEM;

      if (new_size > fioc_size)
            memset(new_buf + fioc_size, 0, new_size - fioc_size);

      fioc_buf = new_buf;
      fioc_size = new_size;

      return 0;
}

static int fioc_expand(size_t new_size)
{
      if (new_size > fioc_size)
            return fioc_resize(new_size);
      return 0;
}

static int fioc_file_type(const char *path)
{
      if (strcmp(path, "/") == 0)
            return FIOC_ROOT;
      if (strcmp(path, "/" FIOC_NAME) == 0)
            return FIOC_FILE;
      return FIOC_NONE;
}

static int fioc_getattr(const char *path, struct stat *stbuf)
{
      stbuf->st_uid = getuid();
      stbuf->st_gid = getgid();
      stbuf->st_atime = stbuf->st_mtime = time(NULL);

      switch (fioc_file_type(path)) {
      case FIOC_ROOT:
            stbuf->st_mode = S_IFDIR | 0755;
            stbuf->st_nlink = 2;
            break;
      case FIOC_FILE:
            stbuf->st_mode = S_IFREG | 0644;
            stbuf->st_nlink = 1;
            stbuf->st_size = fioc_size;
            break;
      case FIOC_NONE:
            return -ENOENT;
      }

      return 0;
}

static int fioc_open(const char *path, struct fuse_file_info *fi)
{
      (void) fi;

      if (fioc_file_type(path) != FIOC_NONE)
            return 0;
      return -ENOENT;
}

static int fioc_do_read(char *buf, size_t size, off_t offset)
{
      if (offset >= fioc_size)
            return 0;

      if (size > fioc_size - offset)
            size = fioc_size - offset;

      memcpy(buf, fioc_buf + offset, size);

      return size;
}

static int fioc_read(const char *path, char *buf, size_t size,
                 off_t offset, struct fuse_file_info *fi)
{
      (void) fi;

      if (fioc_file_type(path) != FIOC_FILE)
            return -EINVAL;

      return fioc_do_read(buf, size, offset);
}

static int fioc_do_write(const char *buf, size_t size, off_t offset)
{
      if (fioc_expand(offset + size))
            return -ENOMEM;

      memcpy(fioc_buf + offset, buf, size);

      return size;
}

static int fioc_write(const char *path, const char *buf, size_t size,
                  off_t offset, struct fuse_file_info *fi)
{
      (void) fi;

      if (fioc_file_type(path) != FIOC_FILE)
            return -EINVAL;

      return fioc_do_write(buf, size, offset);
}

static int fioc_truncate(const char *path, off_t size)
{
      if (fioc_file_type(path) != FIOC_FILE)
            return -EINVAL;

      return fioc_resize(size);
}

static int fioc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                  off_t offset, struct fuse_file_info *fi)
{
      (void) fi;
      (void) offset;

      if (fioc_file_type(path) != FIOC_ROOT)
            return -ENOENT;

      filler(buf, ".", NULL, 0);
      filler(buf, "..", NULL, 0);
      filler(buf, FIOC_NAME, NULL, 0);

      return 0;
}

static int fioc_ioctl(const char *path, int cmd, void *arg,
                  struct fuse_file_info *fi, unsigned int flags, void *data)
{
      (void) arg;
      (void) fi;
      (void) flags;

      if (fioc_file_type(path) != FIOC_FILE)
            return -EINVAL;

      if (flags & FUSE_IOCTL_COMPAT)
            return -ENOSYS;

      switch (cmd) {
      case FIOC_GET_SIZE:
            *(size_t *)data = fioc_size;
            return 0;

      case FIOC_SET_SIZE:
            fioc_resize(*(size_t *)data);
            return 0;
      }

      return -EINVAL;
}

static struct fuse_operations fioc_oper = {
      .getattr    = fioc_getattr,
      .readdir    = fioc_readdir,
      .truncate   = fioc_truncate,
      .open       = fioc_open,
      .read       = fioc_read,
      .write            = fioc_write,
      .ioctl            = fioc_ioctl,
};

int main(int argc, char *argv[])
{
      return fuse_main(argc, argv, &fioc_oper, NULL);
}

Generated by  Doxygen 1.6.0   Back to index