mirror of
https://github.com/AltraMayor/f3.git
synced 2025-09-15 18:17:26 -04:00
f3probe: implement file device
NOT FINISHED
This commit is contained in:
parent
28808f31b5
commit
366e2d94bf
157
libprobe.c
157
libprobe.c
@ -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"
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user