// 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(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(R(AX0), R(AX1), ent->d_name); snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name); if (lstat(name, &st) < 0) { perror("diskdev: couldn't stat file in directory: "); R(RCX) = -1; R(RDX) = -1; } else { R(RCX) = st.st_size; R(RDX) = !S_ISREG(st.st_mode); } return 0; } long diskdev_findfirst(dev_t *dev) { GETDISK(); rewinddir(disk->dir); return diskdev_findnext(dev); } //----------------------------------------------------------------------------// long diskdev_open(dev_t *dev) { GETDISK(); int fd, tmp; char buf[NAME_MAX+4] = { 'f', 's', '/', 0 }; readstr(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|O_NOFOLLOW); if (tmp < 0) { perror("diskdev: open"); return -1; } disk->table[fd] = tmp; R(RAX) = fd; return 0; } 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; } 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; } //----------------------------------------------------------------------------// long diskdev_read(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(*buf, R(AX1), 1); return 0; } //----------------------------------------------------------------------------// long diskdev_poweron(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[27] = diskdev_create; dev->fslots[32] = diskdev_read; dev->state = DEVGOOD; return 0; } long diskdev_poweroff(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, };