00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00079 #include <compiler.h>
00080
00081 #include <stdlib.h>
00082 #include <string.h>
00083 #include <time.h>
00084 #include <fcntl.h>
00085 #include <dirent.h>
00086 #include <errno.h>
00087
00088 #include <sys/stat.h>
00089 #include <sys/file.h>
00090 #include <sys/bankmem.h>
00091
00092 #include <fs/fs.h>
00093 #include <dev/pnut.h>
00094
00099
00106
00111 #ifndef PNUT_BLOCK_SIZE
00112 #define PNUT_BLOCK_SIZE 512
00113 #endif
00114
00121 #ifndef PNUT_DIRENT_SIZE
00122 #define PNUT_DIRENT_SIZE 32
00123 #endif
00124
00137 #ifndef PNUT_BLOCKS_PER_NODE
00138 #define PNUT_BLOCKS_PER_NODE 250
00139 #endif
00140
00141 #ifndef PNUTBANK_COUNT
00142 #ifdef ARTHERNET1
00143
00144 #define PNUTBANK_COUNT 15
00145 #elif MMNET02
00146
00147 #define PNUTBANK_COUNT 6
00148 #else
00149
00150 #define PNUTBANK_COUNT 30
00151 #endif
00152 #endif
00153
00157 #ifndef SEEK_SET
00158 # define SEEK_SET 0
00159 # define SEEK_CUR 1
00160 # define SEEK_END 2
00161 #endif
00162
00163 #define NODETYPE_REG 0
00164 #define NODETYPE_DIR 1
00165
00166
00167 typedef short PNUT_BLKNUM;
00168
00187 typedef struct {
00188 u_char node_type;
00189 u_char node_refs;
00200 u_short node_links;
00201 u_long node_size;
00202 time_t node_mtime;
00203 PNUT_BLKNUM node_blocks[PNUT_BLOCKS_PER_NODE];
00204 } PNUT_NODE;
00205
00212 #define PNUT_MAX_NAMELEN (PNUT_DIRENT_SIZE - sizeof(PNUT_BLKNUM) - sizeof(u_char) - 1)
00213
00222 typedef struct {
00228 PNUT_BLKNUM dir_node;
00234 u_char dir_inuse;
00240 char dir_name[PNUT_MAX_NAMELEN + 1];
00241 } PNUT_DIRENTRY;
00242
00249 #define PNUT_MAX_FILESIZE (PNUT_BLOCKS_PER_NODE * PNUT_BLOCK_SIZE)
00250
00254 typedef struct {
00258 PNUT_BLKNUM fr_node;
00259
00263 PNUT_BLKNUM fr_pnode;
00264
00270 CONST char *fr_name;
00271 } PNUT_FINDRESULT;
00272
00276 typedef struct _PNUTFILE PNUTFILE;
00277
00281 struct _PNUTFILE {
00282 PNUT_BLKNUM f_node;
00283 u_long f_pos;
00284 u_int f_flag;
00285 };
00286
00288 static PNUT_BLKNUM root;
00289
00290
00291
00293 #ifndef NUTBANK_SIZE
00294 #define NUTBANK_SIZE 16384
00295 #endif
00296
00307 #ifndef PNUT_TOTAL_BLOCKS
00308 #define PNUT_TOTAL_BLOCKS (PNUTBANK_COUNT * (NUTBANK_SIZE / PNUT_BLOCK_SIZE))
00309 #endif
00310
00311 #define BLOCKS_PER_BANK (NUTBANK_SIZE / PNUT_BLOCK_SIZE)
00312
00313 #ifndef NUTBANK_SR
00314 #define NUTBANK_SR 0xFF00
00315 #endif
00316
00317 #ifndef NUTBANK_START
00318 #define NUTBANK_START 0x8000
00319 #endif
00320
00321 #define NUTBANK_PTR ((char *)NUTBANK_START)
00322
00334 void BankSelect(PNUT_BLKNUM blk)
00335 {
00336
00337
00338
00339 #if NUTBANK_COUNT
00340 int bank = blk / BLOCKS_PER_BANK;
00341 #endif
00342
00343 NutSegBufEnable(bank);
00344 }
00345
00349 PNUT_NODE *BankNodePointer(PNUT_BLKNUM blk)
00350 {
00351 if (blk < 0) {
00352 return NULL;
00353 }
00354 BankSelect(blk);
00355 return (PNUT_NODE *) & NUTBANK_PTR[(blk % BLOCKS_PER_BANK) * PNUT_BLOCK_SIZE];
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 static PNUT_BLKNUM blockFreeList = -1;
00374
00382 static PNUT_BLKNUM PnutBlockAlloc(void)
00383 {
00384 PNUT_BLKNUM rc = blockFreeList;
00385
00386 if (rc >= 0) {
00387 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blockFreeList);
00388 blockFreeList = *bankptr;
00389
00390 memset(bankptr, 0, PNUT_BLOCK_SIZE);
00391 }
00392 return rc;
00393 }
00394
00402 static void PnutBlockRelease(PNUT_BLKNUM blk)
00403 {
00404 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blk);
00405
00406 *bankptr = blockFreeList;
00407 blockFreeList = blk;
00408 }
00409
00410
00411
00421 static PNUT_BLKNUM PnutNodeAlloc(u_char type)
00422 {
00423 PNUT_BLKNUM node = PnutBlockAlloc();
00424
00425 if (node >= 0) {
00426 int i;
00427 PNUT_NODE *np = BankNodePointer(node);
00428
00429
00430 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00431 np->node_blocks[i] = -1;
00432 }
00433
00434
00435 np->node_type = type;
00436 np->node_mtime = time(0);
00437 }
00438 return node;
00439 }
00440
00441
00442
00443
00444 static void PnutNodeDataRelease(PNUT_BLKNUM node)
00445 {
00446 int i;
00447
00448 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00449 if (BankNodePointer(node)->node_blocks[i] >= 0) {
00450 PnutBlockRelease(BankNodePointer(node)->node_blocks[i]);
00451 BankNodePointer(node)->node_blocks[i] = -1;
00452 }
00453 }
00454 BankNodePointer(node)->node_size = 0;
00455 BankNodePointer(node)->node_mtime = time(0);
00456 }
00457
00461 static void PnutNodeRelease(PNUT_BLKNUM node)
00462 {
00463 PnutNodeDataRelease(node);
00464 PnutBlockRelease(node);
00465 }
00466
00483 static int PnutNodeGetDataPtr(PNUT_BLKNUM node, u_long pos, void **buffer, size_t * size, int create)
00484 {
00485 int blkidx;
00486 int rc = EINVAL;
00487
00488 *buffer = NULL;
00489 *size = 0;
00490
00491
00492 if ((blkidx = pos / PNUT_BLOCK_SIZE) < PNUT_BLOCKS_PER_NODE) {
00493 PNUT_BLKNUM blk;
00494
00495
00496 if ((blk = BankNodePointer(node)->node_blocks[blkidx]) < 0 && create) {
00497 if ((blk = PnutBlockAlloc()) < 0) {
00498 rc = ENOSPC;
00499 } else {
00500 BankNodePointer(node)->node_blocks[blkidx] = blk;
00501 }
00502 }
00503
00504
00505
00506
00507
00508 if (blk >= 0) {
00509 char *blkptr = (char *) BankNodePointer(blk);
00510 int blkpos = pos % PNUT_BLOCK_SIZE;
00511
00512 *buffer = blkptr + blkpos;
00513 *size = PNUT_BLOCK_SIZE - blkpos;
00514 rc = 0;
00515 }
00516 }
00517 return rc;
00518 }
00519
00520
00521
00522
00526 static int PnutDirIsEmpty(PNUT_BLKNUM node)
00527 {
00528 int rc = 1;
00529 u_long pos;
00530 size_t size;
00531 PNUT_DIRENTRY *entry;
00532
00533
00534 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00535
00536
00537 if (PnutNodeGetDataPtr(node, pos, (void *) &entry, &size, 0) || size == 0) {
00538
00539 break;
00540 }
00541
00542 if (size >= PNUT_DIRENT_SIZE) {
00543 if (entry->dir_inuse && strcmp(entry->dir_name, ".") && strcmp(entry->dir_name, "..")) {
00544
00545 rc = 0;
00546 break;
00547 }
00548 }
00549 }
00550 return rc;
00551 }
00552
00566 static int PnutDirFindEntry(PNUT_BLKNUM node, CONST char *path, size_t len, PNUT_DIRENTRY ** entry)
00567 {
00568 int rc = ENOENT;
00569 u_long pos;
00570 size_t size;
00571
00572
00573 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00574
00575
00576 if (PnutNodeGetDataPtr(node, pos, (void **) entry, &size, 0) || size == 0) {
00577
00578 break;
00579 }
00580
00581
00582 if (size >= PNUT_DIRENT_SIZE) {
00583 if ((*entry)->dir_inuse &&
00584 strlen((*entry)->dir_name) == len &&
00585 strncmp((*entry)->dir_name, path, len) == 0) {
00586
00587 rc = 0;
00588 break;
00589 }
00590 }
00591 }
00592 return rc;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 static int PnutDirFindPath(PNUT_BLKNUM node, CONST char *path, PNUT_FINDRESULT * result)
00605 {
00606 int rc = 0;
00607 size_t len;
00608 PNUT_DIRENTRY *entry;
00609
00610 result->fr_pnode = node;
00611 result->fr_node = -1;
00612 result->fr_name = NULL;
00613
00614 while (*path == '/') {
00615 path++;
00616 }
00617
00618 if (*path == 0) {
00619 path = ".";
00620 }
00621
00622
00623
00624
00625 while (*path) {
00626 CONST char *cp;
00627
00628
00629 if (BankNodePointer(node)->node_type != NODETYPE_DIR) {
00630 rc = ENOTDIR;
00631 break;
00632 }
00633
00634
00635 for (len = 0, cp = path; *cp && *cp != '/'; cp++) {
00636 len++;
00637 }
00638
00639
00640
00641
00642
00643 if (*cp == 0) {
00644 result->fr_name = path;
00645 }
00646
00647
00648 if ((rc = PnutDirFindEntry(node, path, len, &entry)) != 0) {
00649 rc = ENOENT;
00650 break;
00651 }
00652
00653
00654 result->fr_node = entry->dir_node;
00655 if (*cp == 0) {
00656 break;
00657 }
00658
00659
00660 result->fr_pnode = result->fr_node;
00661
00662
00663 node = result->fr_node;
00664 path += len;
00665 while (*path == '/') {
00666 path++;
00667 }
00668 }
00669 return rc;
00670 }
00671
00672
00683 static int PnutDirOpen(NUTDEVICE * dev, DIR * dir)
00684 {
00685 PNUTFILE *fp;
00686 PNUT_FINDRESULT found;
00687 int rc;
00688
00689
00690 if ((rc = PnutDirFindPath(root, dir->dd_buf, &found)) != 0) {
00691 errno = rc;
00692 rc = -1;
00693 } else {
00694 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_DIR) {
00695 errno = ENOTDIR;
00696 rc = -1;
00697 }
00698
00699 else if ((fp = malloc(sizeof(PNUTFILE))) == 0) {
00700 rc = -1;
00701 }
00702
00703
00704
00705
00706 else {
00707 fp->f_node = found.fr_node;
00708 fp->f_pos = 0;
00709
00710 if ((dir->dd_fd = malloc(sizeof(NUTFILE))) == 0) {
00711 free(fp);
00712 rc = -1;
00713 }
00714 else {
00715 memset(dir->dd_fd, 0, sizeof(NUTFILE));
00716 dir->dd_fd->nf_dev = dev;
00717 dir->dd_fd->nf_fcb = fp;
00718
00719 BankNodePointer(fp->f_node)->node_refs++;
00720 }
00721 }
00722 }
00723 return rc;
00724 }
00725
00729 static int PnutDirClose(DIR * dir)
00730 {
00731 if (dir && dir->dd_fd) {
00732 if (dir->dd_fd->nf_fcb) {
00733 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00734
00735 BankNodePointer(fp->f_node)->node_refs--;
00736 free(fp);
00737 }
00738 free(dir->dd_fd);
00739 return 0;
00740 }
00741 return EINVAL;
00742 }
00743
00747 static int PnutDirRead(DIR * dir)
00748 {
00749 int rc = -1;
00750 u_long pos;
00751 PNUT_DIRENTRY *entry;
00752 size_t size;
00753 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00754 struct dirent *ent = (struct dirent *) dir->dd_buf;
00755
00756 ent->d_name[0] = 0;
00757 for (pos = fp->f_pos; pos < BankNodePointer(fp->f_node)->node_size; pos += PNUT_DIRENT_SIZE) {
00758
00759 rc = PnutNodeGetDataPtr(fp->f_node, pos, (void *) &entry, &size, 0);
00760 if (rc || size == 0) {
00761
00762 rc = -1;
00763 break;
00764 }
00765 fp->f_pos = pos + PNUT_DIRENT_SIZE;
00766
00767
00768 if (size >= PNUT_DIRENT_SIZE && entry->dir_inuse) {
00769 memset(ent, 0, sizeof(struct dirent));
00770 ent->d_fileno = entry->dir_node;
00771 ent->d_namlen = (u_char) strlen(entry->dir_name);
00772 strcpy(ent->d_name, entry->dir_name);
00773 break;
00774 }
00775 }
00776 return rc;
00777 }
00778
00788 static int PnutDirAddEntry(PNUT_BLKNUM dnode, CONST char *name, PNUT_BLKNUM enode)
00789 {
00790 int rc = 0;
00791 u_long pos = 0;
00792 size_t size;
00793 PNUT_DIRENTRY *entry;
00794 PNUT_NODE *np;
00795
00796
00797
00798
00799
00800
00801
00802 for (;;) {
00803
00804
00805
00806
00807 if ((rc = PnutNodeGetDataPtr(dnode, pos, (void *) &entry, &size, 1)) != 0) {
00808 break;
00809 }
00810 pos += PNUT_DIRENT_SIZE;
00811
00812
00813 if (size >= PNUT_DIRENT_SIZE) {
00814
00815 if (entry->dir_inuse == 0) {
00816
00817 entry->dir_node = enode;
00818 entry->dir_inuse = 1;
00819 strcpy(entry->dir_name, name);
00820
00821
00822 np = BankNodePointer(dnode);
00823 np->node_mtime = time(0);
00824 if (pos > np->node_size) {
00825 np->node_size = pos;
00826 }
00827
00828
00829 np = BankNodePointer(enode);
00830 np->node_links++;
00831 break;
00832 }
00833 }
00834 }
00835 return rc;
00836 }
00837
00854 static int PnutDirDelEntry(PNUT_BLKNUM node, CONST char *name)
00855 {
00856 int rc;
00857 PNUT_DIRENTRY *entry;
00858 PNUT_NODE *rnp;
00859 PNUT_BLKNUM rnode;
00860
00861
00862 if ((rc = PnutDirFindEntry(node, name, strlen(name), &entry)) != 0) {
00863 return rc;
00864 }
00865
00866
00867 rnode = entry->dir_node;
00868 rnp = BankNodePointer(rnode);
00869
00870
00871 if (rnp->node_refs) {
00872 return EACCES;
00873 }
00874
00875
00876 if (rnp->node_type == NODETYPE_DIR) {
00877 if (rnp->node_links > 2 || !PnutDirIsEmpty(rnode)) {
00878 return EACCES;
00879 }
00880 rnp = BankNodePointer(node);
00881 rnp->node_links--;
00882 PnutNodeRelease(rnode);
00883 }
00884
00885
00886 else {
00887 PnutNodeRelease(rnode);
00888 }
00889
00890
00891 PnutDirFindEntry(node, name, strlen(name), &entry);
00892 entry->dir_inuse = 0;
00893
00894 return 0;
00895 }
00896
00904 static int PnutDirCreate(CONST char *path)
00905 {
00906 PNUT_BLKNUM node;
00907 PNUT_FINDRESULT found;
00908 int ec;
00909
00910
00911 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
00912 ec = EEXIST;
00913 }
00914
00915
00916 else if (ec == ENOENT) {
00917
00918 if (found.fr_name) {
00919
00920 if ((node = PnutNodeAlloc(NODETYPE_DIR)) < 0) {
00921 ec = ENOSPC;
00922 }
00923
00924 else if ((ec = PnutDirAddEntry(node, ".", node)) != 0) {
00925 PnutNodeRelease(node);
00926 }
00927
00928 else if ((ec = PnutDirAddEntry(node, "..", found.fr_pnode)) != 0) {
00929 PnutNodeRelease(node);
00930 }
00931
00932 else if ((ec = PnutDirAddEntry(found.fr_pnode, found.fr_name, node)) != 0) {
00933 PnutNodeRelease(node);
00934 }
00935 }
00936 }
00937
00938
00939 if (ec) {
00940 errno = ec;
00941 return -1;
00942 }
00943 return 0;
00944 }
00945
00946
00947
00970 static NUTFILE *PnutFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
00971 {
00972 PNUT_BLKNUM node = -1;
00973 PNUT_FINDRESULT found;
00974 int rc;
00975 PNUTFILE *file;
00976 NUTFILE *nfp = NUTFILE_EOF;
00977
00978
00979 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
00980
00981 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_REG) {
00982 errno = EISDIR;
00983 }
00984
00985
00986
00987
00988
00989 else if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
00990 errno = EEXIST;
00991 } else {
00992 node = found.fr_node;
00993 if (mode & _O_TRUNC) {
00994 PnutNodeDataRelease(node);
00995 }
00996 }
00997 }
00998
00999 else if (rc == ENOENT) {
01000
01001
01002
01003
01004
01005 if (found.fr_name && (mode & _O_CREAT)) {
01006 node = PnutNodeAlloc(NODETYPE_REG);
01007
01008 if (node < 0) {
01009 errno = ENOSPC;
01010 return NUTFILE_EOF;
01011 }
01012
01013 rc = PnutDirAddEntry(found.fr_pnode, found.fr_name, node);
01014
01015 if (rc) {
01016 PnutBlockRelease(node);
01017 }
01018 }
01019 }
01020
01021 if (rc == 0 && node >= 0) {
01022 if ((file = malloc(sizeof(PNUTFILE))) != 0) {
01023 file->f_flag |= mode & (_O_RDONLY | _O_WRONLY | _O_APPEND);
01024 file->f_pos = (mode & _O_APPEND) ? BankNodePointer(node)->node_size : 0;
01025 file->f_node = node;
01026
01027 if ((nfp = malloc(sizeof(NUTFILE))) == 0) {
01028 free(file);
01029 nfp = NUTFILE_EOF;
01030 } else {
01031 nfp->nf_next = 0;
01032 nfp->nf_dev = dev;
01033 nfp->nf_fcb = file;
01034
01035 BankNodePointer(node)->node_refs++;
01036 }
01037 }
01038 }
01039 return nfp;
01040 }
01041
01045 static int PnutFileClose(NUTFILE * nfp)
01046 {
01047 if (nfp != NUTFILE_EOF) {
01048 PNUTFILE *fp = nfp->nf_fcb;
01049
01050 if (fp) {
01051 BankNodePointer(fp->f_node)->node_refs--;
01052 free(fp);
01053 }
01054 free(nfp);
01055
01056 return 0;
01057 }
01058 return EINVAL;
01059 }
01060
01068 static int PnutDelete(char *path)
01069 {
01070 int ec;
01071 PNUT_FINDRESULT found;
01072
01073 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
01074 ec = PnutDirDelEntry(found.fr_pnode, found.fr_name);
01075 }
01076 if (ec) {
01077 errno = ec;
01078 return -1;
01079 }
01080 return 0;
01081 }
01082
01091 static int PnutStatus(CONST char *path, struct stat *status)
01092 {
01093 int rc;
01094 PNUT_FINDRESULT found;
01095
01096 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
01097 status->st_mode = BankNodePointer(found.fr_node)->node_type;
01098 status->st_ino = found.fr_node;
01099 status->st_nlink = BankNodePointer(found.fr_node)->node_links;
01100 status->st_size = BankNodePointer(found.fr_node)->node_size;
01101 status->st_mtime = BankNodePointer(found.fr_node)->node_mtime;
01102 }
01103 return rc;
01104 }
01105
01115 static int PnutFileStatus(PNUTFILE * fp, struct stat *status)
01116 {
01117 status->st_mode = BankNodePointer(fp->f_node)->node_type;
01118 status->st_ino = fp->f_node;
01119 status->st_nlink = BankNodePointer(fp->f_node)->node_links;
01120 status->st_size = BankNodePointer(fp->f_node)->node_size;
01121 status->st_mtime = BankNodePointer(fp->f_node)->node_mtime;
01122
01123 return 0;
01124 }
01125
01138 static int PnutFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
01139 {
01140 PNUTFILE *fp = nfp->nf_fcb;
01141 int ec = 0;
01142 int rc = 0;
01143 PNUT_BLKNUM node = fp->f_node;
01144 u_char *blkptr;
01145 size_t blksiz;
01146 CONST char *buf = buffer;
01147
01148 while (len) {
01149 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 1)) != 0) {
01150 break;
01151 }
01152 if (blksiz >= len) {
01153 blksiz = len;
01154 len = 0;
01155 } else {
01156 len -= blksiz;
01157 }
01158 memcpy(blkptr, buf, blksiz);
01159 rc += blksiz;
01160 buf += blksiz;
01161 fp->f_pos += blksiz;
01162 }
01163 if (ec == 0 || ec == ENOSPC) {
01164 if (BankNodePointer(node)->node_size < fp->f_pos) {
01165 BankNodePointer(node)->node_size = fp->f_pos;
01166 }
01167 BankNodePointer(node)->node_mtime = time(0);
01168 }
01169 return rc;
01170 }
01171
01172 #ifdef __HARVARD_ARCH__
01173 static int PnutFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
01174 {
01175 return -1;
01176 }
01177 #endif
01178
01190 static int PnutFileRead(NUTFILE * nfp, void *buffer, int len)
01191 {
01192 PNUTFILE *fp = nfp->nf_fcb;
01193 int ec = 0;
01194 int rc = 0;
01195 PNUT_BLKNUM node = fp->f_node;
01196 u_char *blkptr;
01197 size_t blksiz;
01198 char *buf = buffer;
01199
01200
01201 if (len > BankNodePointer(node)->node_size - fp->f_pos) {
01202 len = (size_t) (BankNodePointer(node)->node_size - fp->f_pos);
01203 }
01204 while (len) {
01205 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 0)) != 0) {
01206 break;
01207 }
01208 if (blksiz >= len) {
01209 blksiz = len;
01210 len = 0;
01211 } else {
01212 len -= blksiz;
01213 }
01214 memcpy(buf, blkptr, blksiz);
01215 rc += blksiz;
01216 buf += blksiz;
01217 fp->f_pos += blksiz;
01218 }
01219 return rc;
01220 }
01221
01222 static int PnutFileSeek(PNUTFILE * fp, long *pos, int whence)
01223 {
01224 int rc = 0;
01225 long npos = *pos;
01226
01227 switch (whence) {
01228 case SEEK_CUR:
01229 npos += fp->f_pos;
01230 break;
01231 case SEEK_END:
01232 npos += BankNodePointer(fp->f_node)->node_size;
01233 break;
01234 }
01235
01236 if (npos < 0 || npos > (long) BankNodePointer(fp->f_node)->node_size) {
01237 rc = EINVAL;
01238 } else {
01239 fp->f_pos = npos;
01240 *pos = npos;
01241 }
01242 return rc;
01243 }
01244
01245
01246
01250 int PnutIOCtl(NUTDEVICE * dev, int req, void *conf)
01251 {
01252 int rc = -1;
01253
01254 switch (req) {
01255 case FS_STATUS:
01256 {
01257 FSCP_STATUS *par = (FSCP_STATUS *) conf;
01258
01259 rc = PnutStatus(par->par_path, par->par_stp);
01260 }
01261 break;
01262 case FS_DIR_CREATE:
01263 rc = PnutDirCreate((char *) conf);
01264 break;
01265 case FS_DIR_REMOVE:
01266 rc = PnutDelete((char *) conf);
01267 break;
01268 case FS_DIR_OPEN:
01269 rc = PnutDirOpen(dev, (DIR *) conf);
01270 break;
01271 case FS_DIR_CLOSE:
01272 rc = PnutDirClose((DIR *) conf);
01273 break;
01274 case FS_DIR_READ:
01275 rc = PnutDirRead((DIR *) conf);
01276 break;
01277 case FS_FILE_STATUS:
01278 rc = PnutFileStatus((PNUTFILE *) ((IOCTL_ARG2 *) conf)->arg1,
01279 (struct stat *) ((IOCTL_ARG2 *) conf)->arg2);
01280 break;
01281 case FS_FILE_DELETE:
01282 rc = PnutDelete((char *) conf);
01283 break;
01284 case FS_FILE_SEEK:
01285 PnutFileSeek((PNUTFILE *) ((IOCTL_ARG3 *) conf)->arg1,
01286 (long *) ((IOCTL_ARG3 *) conf)->arg2,
01287 (int) ((IOCTL_ARG3 *) conf)->arg3);
01288 break;
01289 }
01290 return rc;
01291 }
01292
01304 static long PnutFileSize(NUTFILE *nfp)
01305 {
01306 PNUTFILE *fp = nfp->nf_fcb;
01307
01308 return BankNodePointer(fp->f_node)->node_size;
01309 }
01310
01311
01312
01324 static int PnutInit(NUTDEVICE * dev)
01325 {
01326 PNUT_BLKNUM i;
01327 int rc;
01328
01329
01330 for (i = 0; i < PNUT_TOTAL_BLOCKS; i++) {
01331 PnutBlockRelease(i);
01332 }
01333
01334
01335 if ((root = PnutNodeAlloc(NODETYPE_DIR)) == -1) {
01336 rc = ENOSPC;
01337 } else {
01338 if ((rc = PnutDirAddEntry(root, ".", root)) == 0) {
01339 rc = PnutDirAddEntry(root, "..", root);
01340 }
01341 if (rc) {
01342 PnutBlockRelease(root);
01343 }
01344 }
01345 return rc;
01346 }
01347
01351 NUTDEVICE devPnut = {
01352 0,
01353 {'P', 'N', 'U', 'T', 0, 0, 0, 0, 0}
01354 ,
01355 IFTYP_RAM,
01356 0,
01357 0,
01358 0,
01359 0,
01360 PnutInit,
01361 PnutIOCtl,
01362 PnutFileRead,
01363 PnutFileWrite,
01364 #ifdef __HARVARD_ARCH__
01365 PnutFileWrite_P,
01366 #endif
01367 PnutFileOpen,
01368 PnutFileClose,
01369 PnutFileSize
01370 };
01371