kvisc/vm/dv/diskdev.c

275 lines
4.7 KiB
C
Raw Normal View History

2019-06-26 21:25:59 +02:00
// The OS/K Team licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include <pc/device.h>
2019-07-01 13:16:17 +02:00
#include <sys/stat.h>
2019-06-26 21:25:59 +02:00
#include <dirent.h>
2019-07-10 17:17:45 +02:00
#include <unistd.h>
#include <fcntl.h>
2019-06-26 21:25:59 +02:00
#define MAXOPEN 4096
2019-07-10 17:17:45 +02:00
#define MAXRW 0x800000 // 8MB
2019-06-26 21:25:59 +02:00
typedef struct disk_t disk_t;
typedef struct dirent dirent_t;
struct disk_t
{
// disk directory
DIR *dir;
2019-07-10 17:17:45 +02:00
// opened files
int table[MAXOPEN];
2019-06-26 21:25:59 +02:00
uint opened;
};
#define GETDISK() \
disk_t *disk = (disk_t *)dev->data
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long diskdev_findnext(dev_t *dev)
2019-06-26 21:25:59 +02:00
{
2019-07-01 13:16:17 +02:00
struct stat st;
char name[NAME_MAX+4];
2019-06-26 21:25:59 +02:00
dirent_t *ent;
GETDISK();
for (;;)
{
ent = readdir(disk->dir);
if (ent == NULL)
{
2019-07-24 16:52:26 +02:00
R(RAX) = 0;
2019-06-26 21:25:59 +02:00
return 0;
}
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
break;
}
2019-08-03 19:01:12 +02:00
R(RAX) = writestr(R(AX0), R(AX1), ent->d_name);
2019-06-26 21:25:59 +02:00
2019-07-01 13:16:17 +02:00
snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name);
2019-08-05 14:56:22 +02:00
if (lstat(name, &st) < 0)
2019-07-01 13:16:17 +02:00
{
2019-08-21 16:57:32 +02:00
//perror("diskdev: couldn't stat file in directory: ");
2019-08-05 14:56:22 +02:00
R(RCX) = -1;
2019-07-24 16:52:26 +02:00
R(RDX) = -1;
2019-07-01 13:16:17 +02:00
}
else
2019-08-05 14:56:22 +02:00
{
R(RCX) = st.st_size;
R(RDX) = !S_ISREG(st.st_mode);
}
2019-07-01 13:16:17 +02:00
2019-06-26 21:25:59 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long diskdev_findfirst(dev_t *dev)
2019-06-26 21:25:59 +02:00
{
GETDISK();
rewinddir(disk->dir);
2019-08-03 19:01:12 +02:00
return diskdev_findnext(dev);
2019-06-26 21:25:59 +02:00
}
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long diskdev_open(dev_t *dev)
2019-07-10 17:17:45 +02:00
{
GETDISK();
int fd, tmp;
char buf[NAME_MAX+4] = { 'f', 's', '/', 0 };
2019-08-03 19:01:12 +02:00
readstr(R(AX0), NAME_MAX, buf+3);
2019-07-10 17:17:45 +02:00
for (fd = 0; fd < MAXOPEN; fd++)
if (disk->table[fd] == 0)
break;
if (fd == MAXOPEN)
return -1;
2019-08-05 14:56:22 +02:00
tmp = open(buf, O_RDWR|O_NOFOLLOW);
2019-07-10 17:17:45 +02:00
if (tmp < 0)
2019-07-11 18:34:21 +02:00
{
2019-08-21 16:57:32 +02:00
//perror("diskdev: open");
2019-07-10 17:17:45 +02:00
return -1;
2019-07-11 18:34:21 +02:00
}
2019-07-10 17:17:45 +02:00
disk->table[fd] = tmp;
2019-07-24 16:52:26 +02:00
R(RAX) = fd;
2019-07-10 17:17:45 +02:00
return 0;
}
2019-08-05 15:55:46 +02:00
long diskdev_close(dev_t *dev)
{
GETDISK();
if (R(AX0) >= MAXOPEN)
return -1;
if (disk->table[R(AX0)] <= 0)
return -1;
close(disk->table[R(AX0)]);
return 0;
}
//----------------------------------------------------------------------------//
2019-08-05 14:56:22 +02:00
long diskdev_create(dev_t *dev)
{
int tmp;
char buf[NAME_MAX+4] = { 'f', 's', '/', 0 };
readstr(R(AX0), NAME_MAX, buf+3);
tmp = creat(buf, 0);
if (tmp < 0)
{
perror("diskdev: create");
return -1;
}
close(tmp);
R(RAX) = 0;
return 0;
}
2019-08-05 15:55:46 +02:00
long diskdev_remove(dev_t *dev)
2019-07-10 17:17:45 +02:00
{
2019-08-05 15:55:46 +02:00
int tmp;
char buf[NAME_MAX+4] = { 'f', 's', '/', 0 };
2019-07-10 17:17:45 +02:00
2019-08-05 15:55:46 +02:00
readstr(R(AX0), NAME_MAX, buf+3);
2019-07-10 17:17:45 +02:00
2019-08-05 15:55:46 +02:00
tmp = remove(buf);
2019-07-10 17:17:45 +02:00
2019-08-05 15:55:46 +02:00
if (tmp < 0)
{
perror("diskdev: remove");
return -1;
}
2019-07-10 17:17:45 +02:00
2019-08-05 15:55:46 +02:00
R(RAX) = 0;
2019-07-10 17:17:45 +02:00
return 0;
}
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long diskdev_read(dev_t *dev)
2019-07-10 17:17:45 +02:00
{
GETDISK();
2019-07-24 16:52:26 +02:00
if (R(AX0) >= MAXOPEN || disk->table[R(AX0)] <= 0 || R(AX2) >= MAXRW)
2019-07-10 17:17:45 +02:00
return -1;
int ret;
char *buf = malloc(MAXRW);
if (buf == NULL)
return -1;
2019-07-24 16:52:26 +02:00
ret = read(disk->table[R(AX0)], buf, R(AX2));
2019-07-10 17:17:45 +02:00
if (ret < 0)
{
free(buf);
return -1;
}
2019-07-24 16:52:26 +02:00
R(RAX) = ret;
2019-07-10 17:17:45 +02:00
// Xxx dedicated function & faster copy
2019-07-24 16:52:26 +02:00
for (; ret; ret--, R(AX1)++, buf++)
2019-08-03 19:01:12 +02:00
writemem(*buf, R(AX1), 1);
2019-07-10 17:17:45 +02:00
return 0;
}
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long diskdev_poweron(dev_t *dev)
2019-06-26 21:25:59 +02:00
{
disk_t *disk = calloc(1, sizeof(disk_t));
disk->dir = opendir("fs");
if (disk->dir == NULL)
{
logerr("diskdev: couldn't open fs directory\n");
return -1;
}
dev->data = (void *)disk;
dev->fslots[16] = diskdev_findfirst;
dev->fslots[17] = diskdev_findnext;
2019-07-10 17:17:45 +02:00
dev->fslots[25] = diskdev_open;
dev->fslots[26] = diskdev_close;
2019-08-05 14:56:22 +02:00
dev->fslots[27] = diskdev_create;
2019-08-05 15:55:46 +02:00
dev->fslots[28] = diskdev_remove;
2019-07-10 17:17:45 +02:00
dev->fslots[32] = diskdev_read;
2019-06-26 21:25:59 +02:00
dev->state = DEVGOOD;
return 0;
}
2019-08-03 19:01:12 +02:00
long diskdev_poweroff(dev_t *dev)
2019-06-26 21:25:59 +02:00
{
GETDISK();
2019-07-10 17:17:45 +02:00
int fd;
2019-06-26 21:25:59 +02:00
if (disk)
2019-07-10 17:17:45 +02:00
{
if (disk->dir)
closedir(disk->dir);
for (fd = 0; fd < MAXOPEN; fd++)
if (disk->table[fd] > 0)
close(disk->table[fd]);
2019-06-26 21:25:59 +02:00
free(disk);
2019-07-10 17:17:45 +02:00
}
2019-06-26 21:25:59 +02:00
dev->data = NULL;
dev->state = DEVPWOF;
return 0;
}
//----------------------------------------------------------------------------//
dev_t diskdev =
{
.type = "disk",
.name = "disk",
.modl = "",
.vend = "The OS/K Team",
.major = KARCH_MAJOR,
.minor = KARCH_MINOR,
.revis = KARCH_REVIS,
.fpwon = diskdev_poweron,
.fpwoff = diskdev_poweroff,
};