.long __lxsys_sys_mmap
.long __lxsys_munmap
.long __lxsys_execve
+ .long __lxsys_fstat /* 55 */
2:
.rept __SYSCALL_MAX - (2b - 1b)/4
.long 0
#define HBA_CLB_SIZE 1024
#define HBA_MY_IE (HBA_PxINTR_DHR | HBA_PxINTR_TFE | HBA_PxINTR_OF)
+#define AHCI_DEVCLASS DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA, 0)
// #define DO_HBA_FULL_RESET
"SATA II (3.0Gbps)",
"SATA III (6.0Gbps)" };
+static struct devclass ahci_class = AHCI_DEVCLASS;
+
extern void
ahci_fsexport(struct block_dev* bdev, void* fs_node);
bdev->end_lba = hbadev->max_lba;
bdev->blk_size = hbadev->block_size;
+ bdev->class = &ahci_class;
block_mount(bdev, ahci_fsexport);
}
}
static int
-pdev_nulldev_init(struct device_def*)
+pdev_nulldev_init(struct device_def* def)
{
- struct device* devnull = device_addseq(NULL, NULL, "null");
+ struct device* devnull = device_addseq(NULL, &def->class, NULL, "null");
devnull->ops.write_page = __null_wr_pg;
devnull->ops.write = __null_wr;
devnull->ops.read_page = __null_rd_pg;
}
static int
-pdev_zerodev_init(struct device_def*)
+pdev_zerodev_init(struct device_def* def)
{
- struct device* devzero = device_addseq(NULL, NULL, "zero");
+ struct device* devzero = device_addseq(NULL, &def->class, NULL, "zero");
devzero->ops.read_page = __zero_rd_pg;
devzero->ops.read = __zero_rd;
kbd_state.translation_table = scancode_set2;
kbd_state.state = KBD_STATE_KWAIT;
- kbd_idev = input_add_device("i8042-kbd");
+ kbd_idev = input_add_device(&devdef->class, devdef->name);
/* FIXME This require systematical rework! */
// acpi_context* acpi_ctx = acpi_get_context();
#define RXBUF_SIZE 512
struct serial_dev*
-serial_create()
+serial_create(struct devclass* class)
{
struct serial_dev* sdev = valloc(sizeof(struct serial_dev));
- struct device* dev = device_addseq(NULL, sdev, "ttyS%d", serial_idx++);
+ struct device* dev =
+ device_addseq(NULL, class, sdev, "ttyS%d", serial_idx++);
dev->ops.read = __serial_read;
dev->ops.read_page = __serial_read_page;
dev->ops.write = __serial_write;
uart_enable_fifo(uart, UART_FIFO8);
llist_append(&com_ports, &uart->local_ports);
- struct serial_dev* sdev = serial_create();
+ struct serial_dev* sdev = serial_create(&def->class);
sdev->backend = uart;
sdev->write = uart_general_tx;
sdev->exec_cmd = uart_general_exec_cmd;
device->cspace_base = pci_base;
device->intr_info = intr;
- device_prepare(&device->dev);
+ device_prepare(&device->dev, &pos->devdef.class);
pci_probe_msi_info(device);
pci_probe_bar_info(device);
int
pdev_randdev_init(struct device_def* devdef)
{
- struct device* devrand = device_addseq(NULL, NULL, "rand");
+ struct device* devrand = device_addseq(NULL, &devdef->class, NULL, "rand");
devrand->ops.read = __rand_rd;
devrand->ops.read_page = __rand_rd_pg;
}
struct hwrtc*
-hwrtc_alloc_new(char* name)
+hwrtc_alloc_new(struct device_def* def, char* name)
{
struct hwrtc* rtc_instance = valloc(sizeof(struct hwrtc));
rtc_instance->name = name;
struct device* rtcdev =
- device_addsys(NULL, rtc_instance, "rtc%d", rtc_count);
+ device_addsys(NULL, &def->class, rtc_instance, "rtc%d", rtc_count);
rtcdev->ops.exec_cmd = hwrtc_ioctl;
rtcdev->ops.read = hwrtc_read;
// Make sure the rtc timer is disabled by default
rtc_disable_timer();
- struct hwrtc* rtc = hwrtc_alloc_new("mc146818");
+ struct hwrtc* rtc = hwrtc_alloc_new(devdef, "mc146818");
struct mc146818* state = valloc(sizeof(struct mc146818));
state->rtc_context = rtc;
apic_hwtimer_context()
{
static struct hwtimer apic_hwt = { .name = "apic_timer",
+ .class = DEVCLASS(
+ DEVIF_SOC, DEVFN_TIME, DEV_TIMER, 0),
.init = apic_timer_init,
.supported = apic_timer_check,
.systicks = apic_get_systicks };
current_timer = hwt_ctx;
- struct device* timerdev = device_addsys(NULL, hwt_ctx, hwt_ctx->name);
+ struct device* timerdev =
+ device_addsys(NULL, &hwt_ctx->class, hwt_ctx, hwt_ctx->name);
timerdev->ops.exec_cmd = __hwtimer_ioctl;
}
\ No newline at end of file
hwrtc_init();
struct hwrtc*
-hwrtc_alloc_new(char* driver_id);
+hwrtc_alloc_new(struct device_def* def, char* name);
void
hwrtc_walltime(datetime_t* dt);
char* name;
void* data;
+ struct devclass class;
struct device* timer_dev;
int (*supported)(struct hwtimer*);
};
struct serial_dev*
-serial_create();
+serial_create(struct devclass* class);
void
serial_readone(struct serial_dev* sdev, u8_t* val);
u64_t end_lba;
u32_t blk_size;
struct block_dev_ops ops;
+ struct devclass* class;
};
// Lunaix Partition Table
#define DEV_IFCAT 0x2 // a device category (as device groupping)
#define DEV_IFSYS 0x3 // a system device
-typedef unsigned int dev_t;
-
struct devclass
{
u32_t meta;
// TODO investigate event polling
struct hstr name;
- struct devclass class;
- dev_t dev_id;
+ struct devclass* class;
+ u32_t dev_uid;
int dev_type;
char name_val[DEVICE_NAME_SIZE];
void* underlay;
~class.meta;
}
+static inline u32_t
+device_id_from_class(struct devclass* class)
+{
+ return ((class->device & 0xffff) << 16) | ((class->variant & 0xffff));
+}
+
void
device_register_all();
void
-device_prepare(struct device* dev);
+device_prepare(struct device* dev, struct devclass* class);
void
device_setname(struct device* dev, char* fmt, ...);
void* underlay,
char* name_fmt,
u32_t type,
+ struct devclass* class,
va_list args);
struct device*
device_add(struct device* parent,
+ struct devclass* class,
void* underlay,
u32_t type,
char* name_fmt,
...);
struct device*
-device_addsys(struct device* parent, void* underlay, char* name_fmt, ...);
+device_addsys(struct device* parent,
+ struct devclass* class,
+ void* underlay,
+ char* name_fmt,
+ ...);
struct device*
-device_addseq(struct device* parent, void* underlay, char* name_fmt, ...);
+device_addseq(struct device* parent,
+ struct devclass* class,
+ void* underlay,
+ char* name_fmt,
+ ...);
struct device*
-device_addvol(struct device* parent, void* underlay, char* name_fmt, ...);
+device_addvol(struct device* parent,
+ struct devclass* class,
+ void* underlay,
+ char* name_fmt,
+ ...);
struct device*
device_addcat(struct device* parent, char* name_fmt, ...);
device_remove(struct device* dev);
struct device*
-device_getbyid(struct llist_header* devlist, dev_t id);
+device_getbyid(struct llist_header* devlist, u32_t id);
struct device*
device_getbyhname(struct device* root_dev, struct hstr* name);
#define DEV_NVME 0x5
#define DEV_BUS 0x6
#define DEV_SERIAL 0x7
+#define DEV_TIMER 0x8
#endif /* __LUNAIX_DEVICE_NUM_H */
#include <lunaix/ds/lru.h>
#include <lunaix/ds/mutex.h>
#include <lunaix/status.h>
+
#include <stdatomic.h>
+#include <usr/lunaix/fstypes.h>
+
#define VFS_NAME_MAXLEN 128
#define VFS_MAX_FD 32
-#define VFS_IFDIR 0x1
-#define VFS_IFFILE 0x2
-#define VFS_IFSEQDEV 0x4
-#define VFS_IFVOLDEV 0x8
-#define VFS_IFSYMLINK 0x10
+#define VFS_IFDIR F_DIR
+#define VFS_IFFILE F_FILE
+#define VFS_IFDEV (F_DEV | F_FILE)
+#define VFS_IFSEQDEV (F_SEQDEV | F_FILE)
+#define VFS_IFVOLDEV (F_VOLDEV | F_FILE)
+#define VFS_IFSYMLINK (F_SYMLINK | F_FILE)
+
+#define VFS_DEVFILE(type) ((type) & F_DEV)
+#define VFS_DEVTYPE(type) ((type) & ((F_SEQDEV | F_VOLDEV) ^ F_DEV))
// Walk, mkdir if component encountered is non-exists.
#define VFS_WALK_MKPARENT 0x1
#define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
-#define EXPORT_FILE_SYSTEM(fs_id, init_fn) \
+#define EXPORT_FILE_SYSTEM(fs_id, init_fn) \
export_ldga_el(fs, fs_id, ptr_t, init_fn)
#define VFS_VALID_CHAR(chr) \
struct filesystem* fs;
struct hbucket* i_cache;
void* data;
+ size_t blksize;
struct
{
u32_t (*read_capacity)(struct v_superblock* vsb);
input_add_listener(input_evt_cb listener);
struct input_device*
-input_add_device(char* name_fmt, ...);
+input_add_device(struct devclass* class, char* name_fmt, ...);
#endif /* __LUNAIX_INPUT_H */
#ifndef __LUNAIX_SYS_FCNTL_DEFS_H
#define __LUNAIX_SYS_FCNTL_DEFS_H
+#include "fstypes.h"
+#include "types.h"
+
#define FO_CREATE 0x1
#define FO_APPEND 0x2
#define FO_DIRECT 0x4
#define FO_RDONLY 0x10
#define FO_RDWR 0x20
+#define FO_NOFOLLOW 0x10000
+
#define FSEEK_SET 0x1
#define FSEEK_CUR 0x2
#define FSEEK_END 0x3
#define MNT_RO 0x1
+struct file_stat
+{
+ dev_t st_dev;
+ ino_t st_ino;
+ unsigned int mode;
+ dev_t st_rdev;
+ off_t st_size;
+ size_t st_blksize;
+ size_t st_ioblksize;
+ size_t st_blocks;
+};
+
#endif /* __LUNAIX_FNCTL_DEFS_H */
--- /dev/null
+#ifndef __LUNAIX_FSTYPES_H
+#define __LUNAIX_FSTYPES_H
+
+#define F_DIR 0x0
+#define F_FILE 0x1
+#define F_DEV 0x2
+#define F_SEQDEV 0x6
+#define F_VOLDEV 0xa
+#define F_SYMLINK 0x10
+
+#define F_MFILE 0b00001
+#define F_MDEV 0b01110
+#define F_MSLNK 0b10000
+
+#endif /* __LUNAIX_FSTYPES_H */
#define __SYSCALL_execve 54
+#define __SYSCALL_fstat 55
+
#define __SYSCALL_MAX 0x100
#endif /* __LUNAIX_SYSCALLID_H */
typedef unsigned long off_t;
+typedef unsigned int ino_t;
+
+typedef struct dev_t
+{
+ unsigned int meta;
+ unsigned int devident;
+ unsigned int dev_uid;
+} dev_t;
+
#endif /* __LUNAIX_TYPES_H */
}
struct device* dev =
- device_addvol(blk_parent_dev, bdev, "sd%c", 'a' + free_slot);
+ device_addvol(blk_parent_dev, bdev->class, bdev, "sd%c", 'a' + free_slot);
dev->ops.write = __block_write;
dev->ops.write_page = __block_write_page;
dev->ops.read = __block_read;
struct block_dev* pbdev = cake_grab(lbd_pile);
memcpy(pbdev, bdev, sizeof(*bdev));
- struct device* dev =
- device_addvol(NULL, pbdev, "%sp%d", bdev->bdev_id, index + 1);
+ struct device* dev = device_addvol(
+ NULL, pbdev->class, pbdev, "%sp%d", bdev->bdev_id, index + 1);
dev->ops.write = __block_write;
dev->ops.write_page = __block_write_page;
dev->ops.read = __block_read;
return NULL;
}
- struct device* dev = device_add(adhoc_devcat, NULL, type, NULL);
+ struct device* dev = device_add(adhoc_devcat, class, NULL, type, NULL);
errno = devdef->init_for(devdef, dev);
if (err_code && !errno) {
class->meta,
class->device,
class->device,
- dev->dev_id);
+ dev->dev_uid);
return dev;
}
itype = VFS_IFDIR;
} else if (dev_if == DEV_IFVOL) {
itype |= VFS_IFVOLDEV;
- } else {
+ } else if (dev_if == DEV_IFSEQ) {
itype |= VFS_IFSEQDEV;
+ } else {
+ itype |= VFS_IFDEV;
}
return itype;
}
{
assert(dev);
- struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_id);
+ struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_uid);
if (!devnod) {
if ((devnod = vfs_i_alloc(dnode->super_block))) {
- devnod->id = dev->dev_id;
+ devnod->id = dev->dev_uid;
devnod->data = dev;
devnod->itype = devfs_get_itype(dev);
static DEFINE_LLIST(root_list);
-static volatile dev_t devid = 0;
+static volatile u32_t devid = 0;
+
+struct devclass default_devclass = {};
void
-device_prepare(struct device* dev)
+device_prepare(struct device* dev, struct devclass* class)
{
dev->magic = DEV_STRUCT_MAGIC;
- dev->dev_id = devid++;
+ dev->dev_uid = devid++;
+ dev->class = class ? class : &default_devclass;
llist_init_head(&dev->children);
}
void* underlay,
char* name_fmt,
u32_t type,
+ struct devclass* class,
va_list args)
{
struct device* dev = vzalloc(sizeof(struct device));
- device_prepare(dev);
+ device_prepare(dev, class);
if (parent) {
assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
struct device*
device_add(struct device* parent,
+ struct devclass* class,
void* underlay,
u32_t type,
char* name_fmt,
va_start(args, name_fmt);
struct device* dev =
- device_add_vargs(parent, underlay, name_fmt, type, args);
+ device_add_vargs(parent, underlay, name_fmt, type, class, args);
va_end(args);
return dev;
}
struct device*
-device_addsys(struct device* parent, void* underlay, char* name_fmt, ...)
+device_addsys(struct device* parent,
+ struct devclass* class,
+ void* underlay,
+ char* name_fmt,
+ ...)
{
va_list args;
va_start(args, name_fmt);
struct device* dev =
- device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, args);
+ device_add_vargs(parent, underlay, name_fmt, DEV_IFSYS, class, args);
va_end(args);
return dev;
}
struct device*
-device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
+device_addseq(struct device* parent,
+ struct devclass* class,
+ void* underlay,
+ char* name_fmt,
+ ...)
{
va_list args;
va_start(args, name_fmt);
struct device* dev =
- device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, args);
+ device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, class, args);
va_end(args);
return dev;
}
struct device*
-device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
+device_addvol(struct device* parent,
+ struct devclass* class,
+ void* underlay,
+ char* name_fmt,
+ ...)
{
va_list args;
va_start(args, name_fmt);
struct device* dev =
- device_add_vargs(parent, underlay, name_fmt, DEV_IFVOL, args);
+ device_add_vargs(parent, underlay, name_fmt, DEV_IFVOL, class, args);
va_end(args);
return dev;
va_start(args, name_fmt);
struct device* dev =
- device_add_vargs(parent, NULL, name_fmt, DEV_IFCAT, args);
+ device_add_vargs(parent, NULL, name_fmt, DEV_IFCAT, NULL, args);
va_end(args);
return dev;
}
struct device*
-device_getbyid(struct llist_header* devlist, dev_t id)
+device_getbyid(struct llist_header* devlist, u32_t id)
{
devlist = devlist ? devlist : &root_list;
struct device *pos, *n;
llist_for_each(pos, n, devlist, siblings)
{
- if (pos->dev_id == id) {
+ if (pos->dev_uid == id) {
return pos;
}
}
static inline void
device_populate_info(struct device* dev, struct dev_info* devinfo)
{
- devinfo->dev_id.meta = dev->class.meta;
- devinfo->dev_id.device = dev->class.device;
- devinfo->dev_id.variant = dev->class.variant;
+ devinfo->dev_id.meta = dev->class->meta;
+ devinfo->dev_id.device = dev->class->device;
+ devinfo->dev_id.variant = dev->class->variant;
if (!devinfo->dev_name.buf) {
return;
}
- struct device_def* def = devdef_byclass(&dev->class);
+ struct device_def* def = devdef_byclass(dev->class);
size_t buflen = devinfo->dev_name.buf_len;
strncpy(devinfo->dev_name.buf, def->name, buflen);
}
struct input_device*
-input_add_device(char* name_fmt, ...)
+input_add_device(struct devclass* class, char* name_fmt, ...)
{
assert(input_devcat);
va_start(args, name_fmt);
struct device* dev =
- device_add_vargs(input_devcat, idev, name_fmt, DEV_IFSEQ, args);
+ device_add_vargs(input_devcat, idev, name_fmt, DEV_IFSEQ, class, args);
idev->dev_if = dev;
dev->ops.read = __input_dev_read;
int
iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode)
{
- if (!(inode->itype & VFS_IFDIR)) {
+ if ((inode->itype & F_FILE)) {
vfs_assign_inode(dnode, inode);
return 0;
}
inode->id = ino;
inode->lb_addr = dir->extent_addr;
+ inode->lb_usage = ICEIL(dir->data_size, fu_len);
inode->ops = &iso_inode_ops;
inode->default_fops = &iso_file_ops;
vsb->data = isovsb;
vsb->ops.init_inode = iso9660_init_inode;
vsb->ops.read_capacity = iso9660_rd_capacity;
+ vsb->blksize = ISO9660_BLKSZ;
struct v_inode* rootino = vfs_i_alloc(vsb);
struct iso_var_mdu* mdu = (struct iso_var_mdu*)vprim->root_record;
return ENOTBLK;
}
- if (mnt_point->inode && !(mnt_point->inode->itype & VFS_IFDIR)) {
+ if (mnt_point->inode && (mnt_point->inode->itype & F_MFILE)) {
return ENOTDIR;
}
current_level = dnode;
current_inode = current_level->inode;
- if ((current_inode->itype & VFS_IFSYMLINK) &&
+ if ((current_inode->itype & F_MSLNK) &&
!(walk_options & VFS_WALK_NOFOLLOW)) {
const char* link;
int errno =
pos->ops.read(pos, (void*)volp, ISO9660_READ_OFF, ISO9660_BLKSZ);
if (errno < 0) {
- kprintf(KWARN "can not probe %x:%s (%d)\n",
- pos->dev_id,
- pos->name.value,
- errno);
+ kprintf(KINFO "failed %x:%d:%d, /dev/%s\n",
+ pos->class->meta,
+ pos->class->device,
+ pos->class->variant,
+ pos->name.value);
pos = NULL;
goto done;
}
}
if (*(u32_t*)volp->sys_id == LUNAIX_ID) {
- kprintf(KINFO "[%x:%s] %s\n",
- pos->dev_id,
+ kprintf(KINFO "%x:%d:%d, /dev/%s, %s\n",
+ pos->class->meta,
+ pos->class->device,
+ pos->class->variant,
pos->name.value,
(char*)volp->vol_id);
break;
rinode->flags = flags;
inode->data = rinode;
- if ((flags & RAMF_DIR)) {
- inode->itype = VFS_IFDIR;
- } else {
+ if (!(flags & RAMF_DIR)) {
inode->itype = VFS_IFFILE;
}
{
struct twifs_node* twi_node = (struct twifs_node*)inode->data;
- if (!(twi_node->itype & VFS_IFDIR)) {
+ if ((twi_node->itype & F_FILE)) {
return ENOTDIR;
}
int
twifs_rm_node(struct twifs_node* node)
{
- if ((node->itype & VFS_IFDIR) && !llist_empty(&node->children)) {
+ if (!(node->itype & F_FILE) && !llist_empty(&node->children)) {
return ENOTEMPTY;
}
llist_delete(&node->siblings);
we can do similar thing in Lunaix? A block device emulation
above the regular file when we mount it on.
10. (device) device number (dev_t) allocation
- [good idea] <class>:<subclass>:<uniq_id> composition
+ [good idea] <class>:<subclass>:<uniq_id> composition (CHECKED)
*/
#include <klibc/string.h>
vfile->ref_count = ATOMIC_VAR_INIT(1);
vfile->ops = inode->default_fops;
- if ((inode->itype & VFS_IFFILE) && !inode->pg_cache) {
+ if ((inode->itype & F_MFILE) && !inode->pg_cache) {
struct pcache* pcache = vzalloc(sizeof(struct pcache));
pcache_init(pcache);
pcache->master = inode;
#define FLOCATE_CREATE_EMPTY 1
#define FLOCATE_CREATE_ONLY 2
+#define FLOCATE_NOFOLLOW 4
int
vfs_getfd(int fd, struct v_fd** fd_s)
{
char name_str[VFS_NAME_MAXLEN];
struct hstr name = HSTR(name_str, 0);
- int errno;
+ int errno, woption = 0;
+
+ if ((options & FLOCATE_NOFOLLOW)) {
+ woption |= VFS_WALK_NOFOLLOW;
+ }
name_str[0] = 0;
- if ((errno = vfs_walk_proc(path, fdir, &name, VFS_WALK_PARENT))) {
+ if ((errno = vfs_walk_proc(path, fdir, &name, woption | VFS_WALK_PARENT))) {
return errno;
}
- errno = vfs_walk(*fdir, name.value, file, NULL, 0);
+ errno = vfs_walk(*fdir, name.value, file, NULL, woption);
if (errno != ENOENT && (options & FLOCATE_CREATE_ONLY)) {
return EEXIST;
int
vfs_do_open(const char* path, int options)
{
- int errno, fd;
+ int errno, fd, loptions = 0;
struct v_dnode *dentry, *file;
struct v_file* ofile = NULL;
- errno = __vfs_try_locate_file(
- path, &dentry, &file, (options & FO_CREATE) ? FLOCATE_CREATE_EMPTY : 0);
+ if ((options & FO_CREATE)) {
+ loptions |= FLOCATE_CREATE_EMPTY;
+ } else if ((options & FO_NOFOLLOW)) {
+ loptions |= FLOCATE_NOFOLLOW;
+ }
+
+ errno = __vfs_try_locate_file(path, &dentry, &file, loptions);
if (!errno && !(errno = vfs_alloc_fdslot(&fd))) {
lock_inode(inode);
- if (!(inode->itype & VFS_IFDIR)) {
+ if ((inode->itype & F_FILE)) {
errno = ENOTDIR;
} else {
struct dir_context dctx =
}
struct v_file* file = fd_s->file;
- if ((file->inode->itype & VFS_IFDIR)) {
+ if (!(file->inode->itype & F_FILE)) {
errno = EISDIR;
goto done;
}
goto done;
}
- if ((file->inode->itype & VFS_IFDIR)) {
+ if (!(file->inode->itype & F_FILE)) {
errno = EISDIR;
goto done;
}
int
vfs_get_dtype(int itype)
{
- switch (itype) {
- case VFS_IFDIR:
- return DT_DIR;
- case VFS_IFSYMLINK:
- return DT_SYMLINK;
- default:
- return DT_PIPE;
+ if ((itype & VFS_IFSYMLINK)) {
+ return DT_SYMLINK;
+ } else if (!(itype & VFS_IFFILE)) {
+ return DT_DIR;
+ } else {
+ return DT_FILE;
}
}
goto done;
}
+ pathname = pathname ? pathname : "";
+
struct v_dnode* dnode;
if (!(errno = vfs_walk(
fd_s->file->dnode, pathname, &dnode, NULL, VFS_WALK_NOFOLLOW))) {
lock_dnode(parent);
lock_inode(parent->inode);
- if ((dnode->inode->itype & VFS_IFDIR)) {
+ if (!(dnode->inode->itype & F_MFILE)) {
errno = parent->inode->ops->rmdir(parent->inode, dnode);
if (!errno) {
vfs_dcache_remove(dnode);
errno = ENOTSUP;
} else if (!parent->inode->ops->mkdir) {
errno = ENOTSUP;
- } else if (!(parent->inode->itype & VFS_IFDIR)) {
+ } else if ((parent->inode->itype & F_FILE)) {
errno = ENOTDIR;
} else if (!(errno = parent->inode->ops->mkdir(parent->inode, dir))) {
vfs_dcache_add(parent, dir);
if (inode->open_count) {
errno = EBUSY;
- } else if (!(inode->itype & VFS_IFDIR)) {
+ } else if ((inode->itype & F_MFILE)) {
errno = inode->ops->unlink(inode);
if (!errno) {
vfs_d_free(dnode);
lock_dnode(dnode);
- if (!(dnode->inode->itype & VFS_IFDIR)) {
+ if ((dnode->inode->itype & F_FILE)) {
errno = ENOTDIR;
goto done;
}
done:
vfree((void*)name.value);
return DO_STATUS(errno);
+}
+
+__DEFINE_LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat)
+{
+ int errno = 0;
+ struct v_fd* fds;
+
+ if ((errno = vfs_getfd(fd, &fds))) {
+ goto done;
+ }
+
+ struct v_inode* vino = fds->file->inode;
+ struct device* fdev = vino->sb->dev;
+
+ *stat = (struct file_stat){ .st_ino = vino->id,
+ .st_blocks = vino->lb_usage,
+ .st_size = vino->fsize,
+ .mode = vino->itype,
+ .st_ioblksize = PG_SIZE,
+ .st_blksize = vino->sb->blksize };
+
+ if (VFS_DEVFILE(vino->itype)) {
+ struct device* rdev = (struct device*)vino->data;
+ if (!rdev || rdev->magic != DEV_STRUCT_MAGIC) {
+ errno = EINVAL;
+ goto done;
+ }
+
+ stat->st_rdev = (dev_t){ .meta = rdev->class->meta,
+ .devident = device_id_from_class(rdev->class),
+ .dev_uid = rdev->dev_uid };
+ }
+
+ if (fdev) {
+ u32_t devident = device_id_from_class(fdev->class);
+ stat->st_dev = (dev_t){ .meta = fdev->class->meta,
+ .devident = devident,
+ .dev_uid = fdev->dev_uid };
+ }
+
+done:
+ return DO_STATUS(errno);
}
\ No newline at end of file
return ENOENT;
}
- return taskfs_mknod(dnode, pid, 0, VFS_IFDIR);
+ return taskfs_mknod(dnode, pid, 0, F_FILE);
}
static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
static int
lxconsole_spawn_ttydev(struct device_def* devdef)
{
- struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
+ struct device* tty_dev =
+ device_addseq(NULL, &devdef->class, &lx_console, "tty");
tty_dev->ops.write = __tty_write;
tty_dev->ops.write_page = __tty_write_pg;
tty_dev->ops.read = __tty_read;
#include <fcntl.h>
__LXSYSCALL2(int, open, const char*, path, int, options)
+
+__LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat)
extern int
open(const char* path, int flags);
+extern int
+fstat(int fd, struct file_stat* stat);
+
#endif /* __LUNAIX_FCNTL_H */
app-list += sh
app-list += cat
app-list += testp
+app-list += stat
mkapp-list := $(addprefix app-, $(app-list))
--- /dev/null
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static char buf[256];
+
+int
+main(int argc, char* argv[])
+{
+ if (argc <= 1) {
+ printf("missing operand\n");
+ return 1;
+ }
+
+ int fd = open(argv[1], FO_RDONLY | FO_NOFOLLOW);
+ if (fd < 0) {
+ printf("fail to open %d\n", fd);
+ return 1;
+ }
+
+ struct file_stat stat;
+ if (fstat(fd, &stat) < 0) {
+ printf("fail to get stat %d\n", errno);
+ return 1;
+ }
+
+ printf("File: %s ", argv[1]);
+
+ char* ftype = "directory";
+ int mode = stat.mode;
+ if ((mode & F_MDEV)) {
+ if (!((mode & F_SEQDEV) ^ F_SEQDEV)) {
+ ftype = "sequential device";
+ } else if (!((mode & F_VOLDEV) ^ F_VOLDEV)) {
+ ftype = "volumetric device";
+ } else {
+ ftype = "regular device";
+ }
+ } else if ((mode & F_MSLNK)) {
+ if (readlinkat(fd, NULL, buf, 256) < 0) {
+ printf("fail to readlink %d\n", errno);
+ } else {
+ printf("-> %s", buf);
+ }
+ ftype = "symbolic link";
+ } else if ((mode & F_MFILE)) {
+ ftype = "regular file";
+ }
+
+ printf("\nType: %s\n", ftype);
+ printf("Size: %d; Blocks: %d; FS Block: %d; IO Blocks: %d\n",
+ stat.st_size,
+ stat.st_blocks,
+ stat.st_blksize,
+ stat.st_ioblksize);
+ printf("Inode: %d; ", stat.st_ino);
+
+ dev_t* dev;
+ if (!(stat.mode & F_MDEV)) {
+ dev = &stat.st_dev;
+ } else {
+ dev = &stat.st_rdev;
+ }
+
+ printf("Device: %xh:%d:%d;\n",
+ dev->meta,
+ dev->devident >> 16,
+ dev->devident & 0xffff);
+
+ close(fd);
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+define src_files
+ main.c
+endef
+
+obj_files := $(addsuffix .o,$(src_files))
+include_opt := $(addprefix -I,$(INCLUDES))
+
+out := $(BUILD_DIR)/bin
+
+%.c.o: %.c
+ $(call status_,CC,$<)
+ @$(CC) $(CFLAGS) $(include_opt) -c $< -o $@
+
+$(out)/$(BUILD_NAME): $(obj_files)
+ $(call status_,LD,$(@F))
+ @$(CC) -T $(LD_SCRIPT) -o $@ $< $(LIBC) $(LDFLAGS)
+
+all: $(out)/$(BUILD_NAME)
+
+clean:
+ @rm -f $(obj_files)
\ No newline at end of file