Skip to content

Commit

Permalink
f3probe: implement file device
Browse files Browse the repository at this point in the history
NOT FINISHED
  • Loading branch information
AltraMayor committed Sep 21, 2014
1 parent 28808f3 commit 366e2d9
Showing 1 changed file with 154 additions and 3 deletions.
157 changes: 154 additions & 3 deletions libprobe.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
#define _FILE_OFFSET_BITS 64

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <err.h>

#include "libprobe.h"

Expand All @@ -9,14 +20,153 @@ const char *fake_type_to_name(enum fake_type fake_type)
return ftype_to_name[fake_type];
}

#define BLOCK_SIZE (1 << 9)
#define GIGABYTE (1 << 30)

struct device {
int dummy;
int (*read_block)(struct device *dev, char *buf, uint64_t block);
int (*write_block)(struct device *dev, char *buf, uint64_t block);
int (*get_size_gb)(struct device *dev);
void (*free)(struct device *dev);
};

struct file_device {
/* This must be the first field. See dev_fdev() for details. */
struct device dev;

const char *filename;
int fd;
int file_size_gb;
int fake_size_gb;
enum fake_type fake_type;
/* 3 free bytes. */
};

static inline struct file_device *dev_fdev(struct device *dev)
{
return (struct file_device *)dev;
}

static int fdev_read_block(struct device *dev, char *buf, uint64_t block)
{
struct file_device *fdev = dev_fdev(dev);
off_t offset = block * BLOCK_SIZE;

switch (fdev->fake_type) {
case FKTY_LIMBO:
if (offset >= GIGABYTE * fdev->file_size_gb) {
/* XXX Support different types of LIMBO.
* For example: all zeros, all ones, and random.
*/
memset(buf, 0, BLOCK_SIZE);
return 0;
}
break;

/* XXX Support FKTY_TRUNCATE.
* That is, it drops the highest bits, and addresses the real memory
* with the resulting address.
*
* If @fake_size_gb % @file_size_gb == 0, it's identical to
* FKTY_WRAPAROUND.
*/

case FKTY_WRAPAROUND:
offset %= GIGABYTE * fdev->file_size_gb;
/* Fall through. */

case FKTY_GOOD:
break;

default:
assert(0);
}

assert(lseek(fdev->fd, offset, SEEK_SET) == offset);
read(fdev->fd, buf, BLOCK_SIZE); /* TODO */
return 0;
}

static int fdev_write_block(struct device *dev, char *buf, uint64_t block)
{
struct file_device *fdev = dev_fdev(dev);
off_t offset = block * BLOCK_SIZE;

switch (fdev->fake_type) {
case FKTY_LIMBO:
if (offset >= GIGABYTE * fdev->file_size_gb)
return 0;
break;

case FKTY_WRAPAROUND:
offset %= GIGABYTE * fdev->file_size_gb;
/* Fall through. */

case FKTY_GOOD:
break;

default:
assert(0);
}

assert(lseek(fdev->fd, offset, SEEK_SET) == offset);
write(fdev->fd, buf, BLOCK_SIZE); /* TODO */
return 0;
}

static int fdev_get_size_gb(struct device *dev)
{
return dev_fdev(dev)->fake_size_gb;
}

static void fdev_free(struct device *dev)
{
struct file_device *fdev = dev_fdev(dev);
assert(!close(fdev->fd));
assert(!unlink(fdev->filename));
free((void *)fdev->filename);
fdev->filename = NULL;
}

static char *strdup(const char *str)
{
char *new = malloc(strlen(str) + 1);
if (!new)
return NULL;
return strcpy(new, str);
}

struct device *create_file_device(const char *filename,
int file_size_gb, int fake_size_gb, enum fake_type fake_type)
{
/* TODO */
struct file_device *fdev = malloc(sizeof(*fdev));
assert(fdev);

fdev->filename = strdup(filename);
if (!fdev->filename)
goto error;

fdev->fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fdev->fd < 0) {
err(errno, "Can't create file `%s'", filename);
goto filename;
}

fdev->file_size_gb = file_size_gb;
fdev->fake_size_gb = fake_size_gb;
fdev->fake_type = fake_type;

fdev->dev.read_block = fdev_read_block;
fdev->dev.write_block = fdev_write_block;
fdev->dev.get_size_gb = fdev_get_size_gb;
fdev->dev.free = fdev_free;

return &fdev->dev;

filename:
free((void *)fdev->filename);
fdev->filename = NULL;
error:
return NULL;
}

Expand All @@ -38,7 +188,8 @@ struct device *create_block_device(const char *filename)

void free_device(struct device *dev)
{
/* TODO */
dev->free(dev);
free(dev);
}

/* XXX Don't write at the very beginning of the card to avoid
Expand Down

0 comments on commit 366e2d9

Please sign in to comment.