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
00095 #include <compiler.h>
00096
00097 #include <stdlib.h>
00098 #include <string.h>
00099 #include <time.h>
00100 #include <fcntl.h>
00101 #include <dirent.h>
00102 #include <errno.h>
00103 #include <memdebug.h>
00104
00105 #include <sys/stat.h>
00106 #include <sys/file.h>
00107 #include <sys/bankmem.h>
00108
00109 #include <fs/fs.h>
00110 #include <dev/pnut.h>
00111
00116
00123
00128 #ifndef PNUT_BLOCK_SIZE
00129 #define PNUT_BLOCK_SIZE 512
00130 #endif
00131
00138 #ifndef PNUT_DIRENT_SIZE
00139 #define PNUT_DIRENT_SIZE 32
00140 #endif
00141
00154 #ifndef PNUT_BLOCKS_PER_NODE
00155 #define PNUT_BLOCKS_PER_NODE 250
00156 #endif
00157
00158 #ifndef PNUTBANK_COUNT
00159 #ifdef ARTHERNET1
00160
00161 #define PNUTBANK_COUNT 15
00162 #elif MMNET02 || MMNET03 || MMNET04 ||\
00163 MMNET102 || MMNET103 || MMNET104
00164
00165 #define PNUTBANK_COUNT 6
00166 #else
00167
00168 #define PNUTBANK_COUNT 30
00169 #endif
00170 #endif
00171
00175 #ifndef SEEK_SET
00176 # define SEEK_SET 0
00177 # define SEEK_CUR 1
00178 # define SEEK_END 2
00179 #endif
00180
00181 #define NODETYPE_REG 0
00182 #define NODETYPE_DIR 1
00183
00184
00185 typedef short PNUT_BLKNUM;
00186
00205 typedef struct {
00206 uint8_t node_type;
00207 uint8_t node_refs;
00218 uint16_t node_links;
00219 uint32_t node_size;
00220 time_t node_mtime;
00221 PNUT_BLKNUM node_blocks[PNUT_BLOCKS_PER_NODE];
00222 } PNUT_NODE;
00223
00230 #define PNUT_MAX_NAMELEN (PNUT_DIRENT_SIZE - sizeof(PNUT_BLKNUM) - sizeof(uint8_t) - 1)
00231
00240 typedef struct {
00246 PNUT_BLKNUM dir_node;
00252 uint8_t dir_inuse;
00258 char dir_name[PNUT_MAX_NAMELEN + 1];
00259 } PNUT_DIRENTRY;
00260
00267 #define PNUT_MAX_FILESIZE (PNUT_BLOCKS_PER_NODE * PNUT_BLOCK_SIZE)
00268
00272 typedef struct {
00276 PNUT_BLKNUM fr_node;
00277
00281 PNUT_BLKNUM fr_pnode;
00282
00288 CONST char *fr_name;
00289 } PNUT_FINDRESULT;
00290
00294 typedef struct _PNUTFILE PNUTFILE;
00295
00299 struct _PNUTFILE {
00300 PNUT_BLKNUM f_node;
00301 uint32_t f_pos;
00302 unsigned int f_flag;
00303 };
00304
00306 static PNUT_BLKNUM root;
00307
00308
00309
00311 #ifndef NUTBANK_SIZE
00312 #define NUTBANK_SIZE 16384
00313 #endif
00314
00325 #ifndef PNUT_TOTAL_BLOCKS
00326 #define PNUT_TOTAL_BLOCKS (PNUTBANK_COUNT * (NUTBANK_SIZE / PNUT_BLOCK_SIZE))
00327 #endif
00328
00329 #define BLOCKS_PER_BANK (NUTBANK_SIZE / PNUT_BLOCK_SIZE)
00330
00331 #ifndef NUTBANK_SR
00332 #define NUTBANK_SR 0xFF00
00333 #endif
00334
00335 #ifndef NUTBANK_START
00336 #define NUTBANK_START 0x8000
00337 #endif
00338
00339 #define NUTBANK_PTR ((char *)NUTBANK_START)
00340
00352 void BankSelect(PNUT_BLKNUM blk)
00353 {
00354
00355
00356
00357 #if NUTBANK_COUNT
00358 int bank = blk / BLOCKS_PER_BANK;
00359 #endif
00360
00361 NutSegBufEnable(bank);
00362 }
00363
00367 PNUT_NODE *BankNodePointer(PNUT_BLKNUM blk)
00368 {
00369 if (blk < 0) {
00370 return NULL;
00371 }
00372 BankSelect(blk);
00373 return (PNUT_NODE *) & NUTBANK_PTR[(blk % BLOCKS_PER_BANK) * PNUT_BLOCK_SIZE];
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 static PNUT_BLKNUM blockFreeList = -1;
00392
00400 static PNUT_BLKNUM PnutBlockAlloc(void)
00401 {
00402 PNUT_BLKNUM rc = blockFreeList;
00403
00404 if (rc >= 0) {
00405 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blockFreeList);
00406 blockFreeList = *bankptr;
00407
00408 memset(bankptr, 0, PNUT_BLOCK_SIZE);
00409 }
00410 return rc;
00411 }
00412
00420 static void PnutBlockRelease(PNUT_BLKNUM blk)
00421 {
00422 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blk);
00423
00424 *bankptr = blockFreeList;
00425 blockFreeList = blk;
00426 }
00427
00428
00429
00439 static PNUT_BLKNUM PnutNodeAlloc(uint8_t type)
00440 {
00441 PNUT_BLKNUM node = PnutBlockAlloc();
00442
00443 if (node >= 0) {
00444 int i;
00445 PNUT_NODE *np = BankNodePointer(node);
00446
00447
00448 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00449 np->node_blocks[i] = -1;
00450 }
00451
00452
00453 np->node_type = type;
00454 np->node_mtime = time(0);
00455 }
00456 return node;
00457 }
00458
00459
00460
00461
00462 static void PnutNodeDataRelease(PNUT_BLKNUM node)
00463 {
00464 int i;
00465
00466 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00467 if (BankNodePointer(node)->node_blocks[i] >= 0) {
00468 PnutBlockRelease(BankNodePointer(node)->node_blocks[i]);
00469 BankNodePointer(node)->node_blocks[i] = -1;
00470 }
00471 }
00472 BankNodePointer(node)->node_size = 0;
00473 BankNodePointer(node)->node_mtime = time(0);
00474 }
00475
00479 static void PnutNodeRelease(PNUT_BLKNUM node)
00480 {
00481 PnutNodeDataRelease(node);
00482 PnutBlockRelease(node);
00483 }
00484
00501 static int PnutNodeGetDataPtr(PNUT_BLKNUM node, uint32_t pos, uint8_t **buffer, size_t * size, int create)
00502 {
00503 int blkidx;
00504 int rc = EINVAL;
00505
00506 *buffer = NULL;
00507 *size = 0;
00508
00509
00510 if ((blkidx = pos / PNUT_BLOCK_SIZE) < PNUT_BLOCKS_PER_NODE) {
00511 PNUT_BLKNUM blk;
00512
00513
00514 if ((blk = BankNodePointer(node)->node_blocks[blkidx]) < 0 && create) {
00515 if ((blk = PnutBlockAlloc()) < 0) {
00516 rc = ENOSPC;
00517 } else {
00518 BankNodePointer(node)->node_blocks[blkidx] = blk;
00519 }
00520 }
00521
00522
00523
00524
00525
00526 if (blk >= 0) {
00527 uint8_t *blkptr = (uint8_t *) BankNodePointer(blk);
00528 int blkpos = pos % PNUT_BLOCK_SIZE;
00529
00530 *buffer = blkptr + blkpos;
00531 *size = PNUT_BLOCK_SIZE - blkpos;
00532 rc = 0;
00533 }
00534 }
00535 return rc;
00536 }
00537
00538
00539
00540
00544 static int PnutDirIsEmpty(PNUT_BLKNUM node)
00545 {
00546 int rc = 1;
00547 uint32_t pos;
00548 size_t size;
00549 PNUT_DIRENTRY *entry = NULL;
00550
00551
00552 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00553
00554
00555 uint8_t *ptr = (uint8_t *)entry;
00556 if (PnutNodeGetDataPtr(node, pos, &ptr, &size, 0) || size == 0) {
00557
00558 break;
00559 }
00560 entry = (PNUT_DIRENTRY *)ptr;
00561
00562 if (size >= PNUT_DIRENT_SIZE) {
00563 if (entry->dir_inuse && strcmp(entry->dir_name, ".") && strcmp(entry->dir_name, "..")) {
00564
00565 rc = 0;
00566 break;
00567 }
00568 }
00569 }
00570 return rc;
00571 }
00572
00586 static int PnutDirFindEntry(PNUT_BLKNUM node, CONST char *path, size_t len, PNUT_DIRENTRY ** entry)
00587 {
00588 int rc = ENOENT;
00589 uint32_t pos;
00590 size_t size;
00591
00592
00593 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00594
00595
00596 uint8_t *ptr = (uint8_t *)(*entry);
00597 if (PnutNodeGetDataPtr(node, pos, &ptr, &size, 0) || size == 0) {
00598
00599 break;
00600 }
00601 *entry = (PNUT_DIRENTRY *)ptr;
00602
00603
00604 if (size >= PNUT_DIRENT_SIZE) {
00605 if ((*entry)->dir_inuse &&
00606 strlen((*entry)->dir_name) == len &&
00607 strncmp((*entry)->dir_name, path, len) == 0) {
00608
00609 rc = 0;
00610 break;
00611 }
00612 }
00613 }
00614 return rc;
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 static int PnutDirFindPath(PNUT_BLKNUM node, CONST char *path, PNUT_FINDRESULT * result)
00627 {
00628 int rc = 0;
00629 size_t len;
00630 PNUT_DIRENTRY *entry = NULL;
00631
00632 result->fr_pnode = node;
00633 result->fr_node = -1;
00634 result->fr_name = NULL;
00635
00636 while (*path == '/') {
00637 path++;
00638 }
00639
00640 if (*path == 0) {
00641 path = ".";
00642 }
00643
00644
00645
00646
00647 while (*path) {
00648 CONST char *cp;
00649
00650
00651 if (BankNodePointer(node)->node_type != NODETYPE_DIR) {
00652 rc = ENOTDIR;
00653 break;
00654 }
00655
00656
00657 for (len = 0, cp = path; *cp && *cp != '/'; cp++) {
00658 len++;
00659 }
00660
00661
00662
00663
00664
00665 if (*cp == 0) {
00666 result->fr_name = path;
00667 }
00668
00669
00670 if ((rc = PnutDirFindEntry(node, path, len, &entry)) != 0) {
00671 rc = ENOENT;
00672 break;
00673 }
00674
00675
00676 result->fr_node = entry->dir_node;
00677 if (*cp == 0) {
00678 break;
00679 }
00680
00681
00682 result->fr_pnode = result->fr_node;
00683
00684
00685 node = result->fr_node;
00686 path += len;
00687 while (*path == '/') {
00688 path++;
00689 }
00690 }
00691 return rc;
00692 }
00693
00694
00705 static int PnutDirOpen(NUTDEVICE * dev, DIR * dir)
00706 {
00707 PNUTFILE *fp;
00708 PNUT_FINDRESULT found;
00709 int rc;
00710
00711
00712 if ((rc = PnutDirFindPath(root, dir->dd_buf, &found)) != 0) {
00713 errno = rc;
00714 rc = -1;
00715 } else {
00716 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_DIR) {
00717 errno = ENOTDIR;
00718 rc = -1;
00719 }
00720
00721 else if ((fp = malloc(sizeof(PNUTFILE))) == 0) {
00722 rc = -1;
00723 }
00724
00725
00726
00727
00728 else {
00729 fp->f_node = found.fr_node;
00730 fp->f_pos = 0;
00731
00732 if ((dir->dd_fd = malloc(sizeof(NUTFILE))) == 0) {
00733 free(fp);
00734 rc = -1;
00735 }
00736 else {
00737 memset(dir->dd_fd, 0, sizeof(NUTFILE));
00738 dir->dd_fd->nf_dev = dev;
00739 dir->dd_fd->nf_fcb = fp;
00740
00741 BankNodePointer(fp->f_node)->node_refs++;
00742 }
00743 }
00744 }
00745 return rc;
00746 }
00747
00751 static int PnutDirClose(DIR * dir)
00752 {
00753 if (dir && dir->dd_fd) {
00754 if (dir->dd_fd->nf_fcb) {
00755 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00756
00757 BankNodePointer(fp->f_node)->node_refs--;
00758 free(fp);
00759 }
00760 free(dir->dd_fd);
00761 return 0;
00762 }
00763 return EINVAL;
00764 }
00765
00769 static int PnutDirRead(DIR * dir)
00770 {
00771 int rc = -1;
00772 uint32_t pos;
00773 PNUT_DIRENTRY *entry = NULL;
00774 size_t size;
00775 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00776 struct dirent *ent = (struct dirent *) dir->dd_buf;
00777
00778 ent->d_name[0] = 0;
00779 for (pos = fp->f_pos; pos < BankNodePointer(fp->f_node)->node_size; pos += PNUT_DIRENT_SIZE) {
00780 uint8_t *ptr = (uint8_t *)entry;
00781
00782 rc = PnutNodeGetDataPtr(fp->f_node, pos, &ptr, &size, 0);
00783 if (rc || size == 0) {
00784
00785 rc = -1;
00786 break;
00787 }
00788 entry = (PNUT_DIRENTRY *)ptr;
00789 fp->f_pos = pos + PNUT_DIRENT_SIZE;
00790
00791
00792 if (size >= PNUT_DIRENT_SIZE && entry->dir_inuse) {
00793 memset(ent, 0, sizeof(struct dirent));
00794 ent->d_fileno = entry->dir_node;
00795 ent->d_namlen = (uint8_t) strlen(entry->dir_name);
00796 strcpy(ent->d_name, entry->dir_name);
00797 break;
00798 }
00799 }
00800 return rc;
00801 }
00802
00812 static int PnutDirAddEntry(PNUT_BLKNUM dnode, CONST char *name, PNUT_BLKNUM enode)
00813 {
00814 int rc = 0;
00815 uint32_t pos = 0;
00816 size_t size;
00817 PNUT_DIRENTRY *entry = NULL;
00818 PNUT_NODE *np;
00819
00820
00821
00822
00823
00824
00825
00826 for (;;) {
00827
00828
00829
00830
00831 uint8_t *ptr = (uint8_t *)entry;
00832 if ((rc = PnutNodeGetDataPtr(dnode, pos, &ptr, &size, 1)) != 0) {
00833 break;
00834 }
00835 entry = (PNUT_DIRENTRY *)ptr;
00836 pos += PNUT_DIRENT_SIZE;
00837
00838
00839 if (size >= PNUT_DIRENT_SIZE) {
00840
00841 if (entry->dir_inuse == 0) {
00842
00843 entry->dir_node = enode;
00844 entry->dir_inuse = 1;
00845 strcpy(entry->dir_name, name);
00846
00847
00848 np = BankNodePointer(dnode);
00849 np->node_mtime = time(0);
00850 if (pos > np->node_size) {
00851 np->node_size = pos;
00852 }
00853
00854
00855 np = BankNodePointer(enode);
00856 np->node_links++;
00857 break;
00858 }
00859 }
00860 }
00861 return rc;
00862 }
00863
00880 static int PnutDirDelEntry(PNUT_BLKNUM node, CONST char *name)
00881 {
00882 int rc;
00883 PNUT_DIRENTRY *entry = NULL;
00884 PNUT_NODE *rnp;
00885 PNUT_BLKNUM rnode;
00886
00887
00888 if ((rc = PnutDirFindEntry(node, name, strlen(name), &entry)) != 0) {
00889 return rc;
00890 }
00891
00892
00893 rnode = entry->dir_node;
00894 rnp = BankNodePointer(rnode);
00895
00896
00897 if (rnp->node_refs) {
00898 return EACCES;
00899 }
00900
00901
00902 if (rnp->node_type == NODETYPE_DIR) {
00903 if (rnp->node_links > 2 || !PnutDirIsEmpty(rnode)) {
00904 return EACCES;
00905 }
00906 rnp = BankNodePointer(node);
00907 rnp->node_links--;
00908 PnutNodeRelease(rnode);
00909 }
00910
00911
00912 else {
00913 PnutNodeRelease(rnode);
00914 }
00915
00916
00917 PnutDirFindEntry(node, name, strlen(name), &entry);
00918 entry->dir_inuse = 0;
00919
00920 return 0;
00921 }
00922
00930 static int PnutDirCreate(CONST char *path)
00931 {
00932 PNUT_BLKNUM node;
00933 PNUT_FINDRESULT found;
00934 int ec;
00935
00936
00937 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
00938 ec = EEXIST;
00939 }
00940
00941
00942 else if (ec == ENOENT) {
00943
00944 if (found.fr_name) {
00945
00946 if ((node = PnutNodeAlloc(NODETYPE_DIR)) < 0) {
00947 ec = ENOSPC;
00948 }
00949
00950 else if ((ec = PnutDirAddEntry(node, ".", node)) != 0) {
00951 PnutNodeRelease(node);
00952 }
00953
00954 else if ((ec = PnutDirAddEntry(node, "..", found.fr_pnode)) != 0) {
00955 PnutNodeRelease(node);
00956 }
00957
00958 else if ((ec = PnutDirAddEntry(found.fr_pnode, found.fr_name, node)) != 0) {
00959 PnutNodeRelease(node);
00960 }
00961 }
00962 }
00963
00964
00965 if (ec) {
00966 errno = ec;
00967 return -1;
00968 }
00969 return 0;
00970 }
00971
00972
00973
00996 static NUTFILE *PnutFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
00997 {
00998 PNUT_BLKNUM node = -1;
00999 PNUT_FINDRESULT found;
01000 int rc;
01001 PNUTFILE *file;
01002 NUTFILE *nfp = NUTFILE_EOF;
01003
01004
01005 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
01006
01007 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_REG) {
01008 errno = EISDIR;
01009 }
01010
01011
01012
01013
01014
01015 else if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
01016 errno = EEXIST;
01017 } else {
01018 node = found.fr_node;
01019 if (mode & _O_TRUNC) {
01020 PnutNodeDataRelease(node);
01021 }
01022 }
01023 }
01024
01025 else if (rc == ENOENT) {
01026
01027
01028
01029
01030
01031 if (found.fr_name && (mode & _O_CREAT)) {
01032 node = PnutNodeAlloc(NODETYPE_REG);
01033
01034 if (node < 0) {
01035 errno = ENOSPC;
01036 return NUTFILE_EOF;
01037 }
01038
01039 rc = PnutDirAddEntry(found.fr_pnode, found.fr_name, node);
01040
01041 if (rc) {
01042 PnutBlockRelease(node);
01043 }
01044 }
01045 }
01046
01047 if (rc == 0 && node >= 0) {
01048 if ((file = malloc(sizeof(PNUTFILE))) != 0) {
01049 file->f_flag |= mode & (_O_RDONLY | _O_WRONLY | _O_APPEND);
01050 file->f_pos = (mode & _O_APPEND) ? BankNodePointer(node)->node_size : 0;
01051 file->f_node = node;
01052
01053 if ((nfp = malloc(sizeof(NUTFILE))) == 0) {
01054 free(file);
01055 nfp = NUTFILE_EOF;
01056 } else {
01057 nfp->nf_next = 0;
01058 nfp->nf_dev = dev;
01059 nfp->nf_fcb = file;
01060
01061 BankNodePointer(node)->node_refs++;
01062 }
01063 }
01064 }
01065 return nfp;
01066 }
01067
01071 static int PnutFileClose(NUTFILE * nfp)
01072 {
01073 if (nfp != NUTFILE_EOF) {
01074 PNUTFILE *fp = nfp->nf_fcb;
01075
01076 if (fp) {
01077 BankNodePointer(fp->f_node)->node_refs--;
01078 free(fp);
01079 }
01080 free(nfp);
01081
01082 return 0;
01083 }
01084 return EINVAL;
01085 }
01086
01094 static int PnutDelete(char *path)
01095 {
01096 int ec;
01097 PNUT_FINDRESULT found;
01098
01099 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
01100 ec = PnutDirDelEntry(found.fr_pnode, found.fr_name);
01101 }
01102 if (ec) {
01103 errno = ec;
01104 return -1;
01105 }
01106 return 0;
01107 }
01108
01117 static int PnutStatus(CONST char *path, struct stat *status)
01118 {
01119 int rc;
01120 PNUT_FINDRESULT found;
01121
01122 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
01123 status->st_mode = BankNodePointer(found.fr_node)->node_type;
01124 status->st_ino = found.fr_node;
01125 status->st_nlink = BankNodePointer(found.fr_node)->node_links;
01126 status->st_size = BankNodePointer(found.fr_node)->node_size;
01127 status->st_mtime = BankNodePointer(found.fr_node)->node_mtime;
01128 }
01129 return rc;
01130 }
01131
01141 static int PnutFileStatus(PNUTFILE * fp, struct stat *status)
01142 {
01143 status->st_mode = BankNodePointer(fp->f_node)->node_type;
01144 status->st_ino = fp->f_node;
01145 status->st_nlink = BankNodePointer(fp->f_node)->node_links;
01146 status->st_size = BankNodePointer(fp->f_node)->node_size;
01147 status->st_mtime = BankNodePointer(fp->f_node)->node_mtime;
01148
01149 return 0;
01150 }
01151
01164 static int PnutFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
01165 {
01166 PNUTFILE *fp = nfp->nf_fcb;
01167 int ec = 0;
01168 int rc = 0;
01169 PNUT_BLKNUM node = fp->f_node;
01170 uint8_t *blkptr;
01171 size_t blksiz;
01172 CONST char *buf = buffer;
01173
01174 while (len) {
01175 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, &blkptr, &blksiz, 1)) != 0) {
01176 break;
01177 }
01178 if (blksiz >= len) {
01179 blksiz = len;
01180 len = 0;
01181 } else {
01182 len -= blksiz;
01183 }
01184 memcpy(blkptr, buf, blksiz);
01185 rc += blksiz;
01186 buf += blksiz;
01187 fp->f_pos += blksiz;
01188 }
01189 if (ec == 0 || ec == ENOSPC) {
01190 if (BankNodePointer(node)->node_size < fp->f_pos) {
01191 BankNodePointer(node)->node_size = fp->f_pos;
01192 }
01193 BankNodePointer(node)->node_mtime = time(0);
01194 }
01195 return rc;
01196 }
01197
01198 #ifdef __HARVARD_ARCH__
01199 static int PnutFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
01200 {
01201 return -1;
01202 }
01203 #endif
01204
01216 static int PnutFileRead(NUTFILE * nfp, void *buffer, int len)
01217 {
01218 PNUTFILE *fp = nfp->nf_fcb;
01219 int ec = 0;
01220 int rc = 0;
01221 PNUT_BLKNUM node = fp->f_node;
01222 uint8_t *blkptr;
01223 size_t blksiz;
01224 char *buf = buffer;
01225
01226
01227 if (len > BankNodePointer(node)->node_size - fp->f_pos) {
01228 len = (size_t) (BankNodePointer(node)->node_size - fp->f_pos);
01229 }
01230 while (len) {
01231 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, &blkptr, &blksiz, 0)) != 0) {
01232 break;
01233 }
01234 if (blksiz >= len) {
01235 blksiz = len;
01236 len = 0;
01237 } else {
01238 len -= blksiz;
01239 }
01240 memcpy(buf, blkptr, blksiz);
01241 rc += blksiz;
01242 buf += blksiz;
01243 fp->f_pos += blksiz;
01244 }
01245 return rc;
01246 }
01247
01248 static int PnutFileSeek(PNUTFILE * fp, long *pos, int whence)
01249 {
01250 int rc = 0;
01251 long npos = *pos;
01252
01253 switch (whence) {
01254 case SEEK_CUR:
01255 npos += fp->f_pos;
01256 break;
01257 case SEEK_END:
01258 npos += BankNodePointer(fp->f_node)->node_size;
01259 break;
01260 }
01261
01262 if (npos < 0 || npos > (long) BankNodePointer(fp->f_node)->node_size) {
01263 rc = EINVAL;
01264 } else {
01265 fp->f_pos = npos;
01266 *pos = npos;
01267 }
01268 return rc;
01269 }
01270
01271
01272
01276 int PnutIOCtl(NUTDEVICE * dev, int req, void *conf)
01277 {
01278 int rc = -1;
01279
01280 switch (req) {
01281 case FS_STATUS:
01282 {
01283 FSCP_STATUS *par = (FSCP_STATUS *) conf;
01284
01285 rc = PnutStatus(par->par_path, par->par_stp);
01286 }
01287 break;
01288 case FS_DIR_CREATE:
01289 rc = PnutDirCreate((char *) conf);
01290 break;
01291 case FS_DIR_REMOVE:
01292 rc = PnutDelete((char *) conf);
01293 break;
01294 case FS_DIR_OPEN:
01295 rc = PnutDirOpen(dev, (DIR *) conf);
01296 break;
01297 case FS_DIR_CLOSE:
01298 rc = PnutDirClose((DIR *) conf);
01299 break;
01300 case FS_DIR_READ:
01301 rc = PnutDirRead((DIR *) conf);
01302 break;
01303 case FS_FILE_STATUS:
01304 rc = PnutFileStatus((PNUTFILE *) ((IOCTL_ARG2 *) conf)->arg1,
01305 (struct stat *) ((IOCTL_ARG2 *) conf)->arg2);
01306 break;
01307 case FS_FILE_DELETE:
01308 rc = PnutDelete((char *) conf);
01309 break;
01310 case FS_FILE_SEEK:
01311 PnutFileSeek((PNUTFILE *) ((IOCTL_ARG3 *) conf)->arg1,
01312 (long *) ((IOCTL_ARG3 *) conf)->arg2,
01313 (int) ((IOCTL_ARG3 *) conf)->arg3);
01314 break;
01315 }
01316 return rc;
01317 }
01318
01330 static long PnutFileSize(NUTFILE *nfp)
01331 {
01332 PNUTFILE *fp = nfp->nf_fcb;
01333
01334 return BankNodePointer(fp->f_node)->node_size;
01335 }
01336
01337
01338
01350 static int PnutInit(NUTDEVICE * dev)
01351 {
01352 PNUT_BLKNUM i;
01353 int rc;
01354
01355
01356 for (i = 0; i < PNUT_TOTAL_BLOCKS; i++) {
01357 PnutBlockRelease(i);
01358 }
01359
01360
01361 if ((root = PnutNodeAlloc(NODETYPE_DIR)) == -1) {
01362 rc = ENOSPC;
01363 } else {
01364 if ((rc = PnutDirAddEntry(root, ".", root)) == 0) {
01365 rc = PnutDirAddEntry(root, "..", root);
01366 }
01367 if (rc) {
01368 PnutBlockRelease(root);
01369 }
01370 }
01371 return rc;
01372 }
01373
01377 NUTDEVICE devPnut = {
01378 0,
01379 {'P', 'N', 'U', 'T', 0, 0, 0, 0, 0}
01380 ,
01381 IFTYP_RAM,
01382 0,
01383 0,
01384 0,
01385 0,
01386 PnutInit,
01387 PnutIOCtl,
01388 PnutFileRead,
01389 PnutFileWrite,
01390 #ifdef __HARVARD_ARCH__
01391 PnutFileWrite_P,
01392 #endif
01393 PnutFileOpen,
01394 PnutFileClose,
01395 PnutFileSize
01396 };
01397