// 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 #include #include #include #include #define MAXOPEN 4096 #define MAXRW 0x800000 // 8MB typedef struct disk_t disk_t; typedef struct dirent dirent_t; struct disk_t { // disk directory DIR *dir; // opened files int table[MAXOPEN]; uint opened; }; #define GETDISK() \ disk_t *disk = (disk_t *)dev->data //----------------------------------------------------------------------------// long diskdev_findnext(ctx_t *ctx, dev_t *dev) { struct stat st; char name[NAME_MAX+4]; dirent_t *ent; GETDISK(); for (;;) { ent = readdir(disk->dir); if (ent == NULL) { R(RAX) = 0; return 0; } if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; break; } R(RAX) = writestr(ctx, R(AX0), R(AX1), ent->d_name); snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name); if (stat(name, &st) < 0) { perror("diskdev: couldn't stat file in directory: "); R(RDX) = -1; } else R(RDX) = st.st_size; return 0; } long diskdev_findfirst(ctx_t *ctx, dev_t *dev) { GETDISK(); rewinddir(disk->dir); return diskdev_findnext(ctx, dev); } //----------------------------------------------------------------------------// long diskdev_open(ctx_t *ctx, dev_t *dev) { GETDISK(); int fd, tmp; char buf[NAME_MAX+4] = { 'f', 's', '/', 0 }; readstr(ctx, R(AX0), NAME_MAX, buf+3); for (fd = 0; fd < MAXOPEN; fd++) if (disk->table[fd] == 0) break; if (fd == MAXOPEN) return -1; tmp = open(buf, O_RDWR); if (tmp < 0) { perror("diskdev: open"); return -1; } disk->table[fd] = tmp; R(RAX) = fd; return 0; } long diskdev_close(ctx_t *ctx, 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; } //----------------------------------------------------------------------------// long diskdev_read(ctx_t *ctx, dev_t *dev) { GETDISK(); if (R(AX0) >= MAXOPEN || disk->table[R(AX0)] <= 0 || R(AX2) >= MAXRW) return -1; int ret; char *buf = malloc(MAXRW); if (buf == NULL) return -1; ret = read(disk->table[R(AX0)], buf, R(AX2)); if (ret < 0) { free(buf); return -1; } R(RAX) = ret; // Xxx dedicated function & faster copy for (; ret; ret--, R(AX1)++, buf++) writemem(ctx, *buf, R(AX1), 1); return 0; } //----------------------------------------------------------------------------// long diskdev_poweron(ctx_t *ctx, dev_t *dev) { 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; dev->fslots[25] = diskdev_open; dev->fslots[26] = diskdev_close; dev->fslots[32] = diskdev_read; dev->state = DEVGOOD; return 0; } long diskdev_poweroff(ctx_t *ctx, dev_t *dev) { GETDISK(); int fd; if (disk) { if (disk->dir) closedir(disk->dir); for (fd = 0; fd < MAXOPEN; fd++) if (disk->table[fd] > 0) close(disk->table[fd]); free(disk); } 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, };