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, void **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 char *blkptr = (char *) 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;
00550
00551
00552 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00553
00554
00555 if (PnutNodeGetDataPtr(node, pos, (void *) &entry, &size, 0) || size == 0) {
00556
00557 break;
00558 }
00559
00560 if (size >= PNUT_DIRENT_SIZE) {
00561 if (entry->dir_inuse && strcmp(entry->dir_name, ".") && strcmp(entry->dir_name, "..")) {
00562
00563 rc = 0;
00564 break;
00565 }
00566 }
00567 }
00568 return rc;
00569 }
00570
00584 static int PnutDirFindEntry(PNUT_BLKNUM node, CONST char *path, size_t len, PNUT_DIRENTRY ** entry)
00585 {
00586 int rc = ENOENT;
00587 uint32_t pos;
00588 size_t size;
00589
00590
00591 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00592
00593
00594 if (PnutNodeGetDataPtr(node, pos, (void **) entry, &size, 0) || size == 0) {
00595
00596 break;
00597 }
00598
00599
00600 if (size >= PNUT_DIRENT_SIZE) {
00601 if ((*entry)->dir_inuse &&
00602 strlen((*entry)->dir_name) == len &&
00603 strncmp((*entry)->dir_name, path, len) == 0) {
00604
00605 rc = 0;
00606 break;
00607 }
00608 }
00609 }
00610 return rc;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 static int PnutDirFindPath(PNUT_BLKNUM node, CONST char *path, PNUT_FINDRESULT * result)
00623 {
00624 int rc = 0;
00625 size_t len;
00626 PNUT_DIRENTRY *entry;
00627
00628 result->fr_pnode = node;
00629 result->fr_node = -1;
00630 result->fr_name = NULL;
00631
00632 while (*path == '/') {
00633 path++;
00634 }
00635
00636 if (*path == 0) {
00637 path = ".";
00638 }
00639
00640
00641
00642
00643 while (*path) {
00644 CONST char *cp;
00645
00646
00647 if (BankNodePointer(node)->node_type != NODETYPE_DIR) {
00648 rc = ENOTDIR;
00649 break;
00650 }
00651
00652
00653 for (len = 0, cp = path; *cp && *cp != '/'; cp++) {
00654 len++;
00655 }
00656
00657
00658
00659
00660
00661 if (*cp == 0) {
00662 result->fr_name = path;
00663 }
00664
00665
00666 if ((rc = PnutDirFindEntry(node, path, len, &entry)) != 0) {
00667 rc = ENOENT;
00668 break;
00669 }
00670
00671
00672 result->fr_node = entry->dir_node;
00673 if (*cp == 0) {
00674 break;
00675 }
00676
00677
00678 result->fr_pnode = result->fr_node;
00679
00680
00681 node = result->fr_node;
00682 path += len;
00683 while (*path == '/') {
00684 path++;
00685 }
00686 }
00687 return rc;
00688 }
00689
00690
00701 static int PnutDirOpen(NUTDEVICE * dev, DIR * dir)
00702 {
00703 PNUTFILE *fp;
00704 PNUT_FINDRESULT found;
00705 int rc;
00706
00707
00708 if ((rc = PnutDirFindPath(root, dir->dd_buf, &found)) != 0) {
00709 errno = rc;
00710 rc = -1;
00711 } else {
00712 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_DIR) {
00713 errno = ENOTDIR;
00714 rc = -1;
00715 }
00716
00717 else if ((fp = malloc(sizeof(PNUTFILE))) == 0) {
00718 rc = -1;
00719 }
00720
00721
00722
00723
00724 else {
00725 fp->f_node = found.fr_node;
00726 fp->f_pos = 0;
00727
00728 if ((dir->dd_fd = malloc(sizeof(NUTFILE))) == 0) {
00729 free(fp);
00730 rc = -1;
00731 }
00732 else {
00733 memset(dir->dd_fd, 0, sizeof(NUTFILE));
00734 dir->dd_fd->nf_dev = dev;
00735 dir->dd_fd->nf_fcb = fp;
00736
00737 BankNodePointer(fp->f_node)->node_refs++;
00738 }
00739 }
00740 }
00741 return rc;
00742 }
00743
00747 static int PnutDirClose(DIR * dir)
00748 {
00749 if (dir && dir->dd_fd) {
00750 if (dir->dd_fd->nf_fcb) {
00751 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00752
00753 BankNodePointer(fp->f_node)->node_refs--;
00754 free(fp);
00755 }
00756 free(dir->dd_fd);
00757 return 0;
00758 }
00759 return EINVAL;
00760 }
00761
00765 static int PnutDirRead(DIR * dir)
00766 {
00767 int rc = -1;
00768 uint32_t pos;
00769 PNUT_DIRENTRY *entry;
00770 size_t size;
00771 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00772 struct dirent *ent = (struct dirent *) dir->dd_buf;
00773
00774 ent->d_name[0] = 0;
00775 for (pos = fp->f_pos; pos < BankNodePointer(fp->f_node)->node_size; pos += PNUT_DIRENT_SIZE) {
00776
00777 rc = PnutNodeGetDataPtr(fp->f_node, pos, (void *) &entry, &size, 0);
00778 if (rc || size == 0) {
00779
00780 rc = -1;
00781 break;
00782 }
00783 fp->f_pos = pos + PNUT_DIRENT_SIZE;
00784
00785
00786 if (size >= PNUT_DIRENT_SIZE && entry->dir_inuse) {
00787 memset(ent, 0, sizeof(struct dirent));
00788 ent->d_fileno = entry->dir_node;
00789 ent->d_namlen = (uint8_t) strlen(entry->dir_name);
00790 strcpy(ent->d_name, entry->dir_name);
00791 break;
00792 }
00793 }
00794 return rc;
00795 }
00796
00806 static int PnutDirAddEntry(PNUT_BLKNUM dnode, CONST char *name, PNUT_BLKNUM enode)
00807 {
00808 int rc = 0;
00809 uint32_t pos = 0;
00810 size_t size;
00811 PNUT_DIRENTRY *entry;
00812 PNUT_NODE *np;
00813
00814
00815
00816
00817
00818
00819
00820 for (;;) {
00821
00822
00823
00824
00825 if ((rc = PnutNodeGetDataPtr(dnode, pos, (void *) &entry, &size, 1)) != 0) {
00826 break;
00827 }
00828 pos += PNUT_DIRENT_SIZE;
00829
00830
00831 if (size >= PNUT_DIRENT_SIZE) {
00832
00833 if (entry->dir_inuse == 0) {
00834
00835 entry->dir_node = enode;
00836 entry->dir_inuse = 1;
00837 strcpy(entry->dir_name, name);
00838
00839
00840 np = BankNodePointer(dnode);
00841 np->node_mtime = time(0);
00842 if (pos > np->node_size) {
00843 np->node_size = pos;
00844 }
00845
00846
00847 np = BankNodePointer(enode);
00848 np->node_links++;
00849 break;
00850 }
00851 }
00852 }
00853 return rc;
00854 }
00855
00872 static int PnutDirDelEntry(PNUT_BLKNUM node, CONST char *name)
00873 {
00874 int rc;
00875 PNUT_DIRENTRY *entry;
00876 PNUT_NODE *rnp;
00877 PNUT_BLKNUM rnode;
00878
00879
00880 if ((rc = PnutDirFindEntry(node, name, strlen(name), &entry)) != 0) {
00881 return rc;
00882 }
00883
00884
00885 rnode = entry->dir_node;
00886 rnp = BankNodePointer(rnode);
00887
00888
00889 if (rnp->node_refs) {
00890 return EACCES;
00891 }
00892
00893
00894 if (rnp->node_type == NODETYPE_DIR) {
00895 if (rnp->node_links > 2 || !PnutDirIsEmpty(rnode)) {
00896 return EACCES;
00897 }
00898 rnp = BankNodePointer(node);
00899 rnp->node_links--;
00900 PnutNodeRelease(rnode);
00901 }
00902
00903
00904 else {
00905 PnutNodeRelease(rnode);
00906 }
00907
00908
00909 PnutDirFindEntry(node, name, strlen(name), &entry);
00910 entry->dir_inuse = 0;
00911
00912 return 0;
00913 }
00914
00922 static int PnutDirCreate(CONST char *path)
00923 {
00924 PNUT_BLKNUM node;
00925 PNUT_FINDRESULT found;
00926 int ec;
00927
00928
00929 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
00930 ec = EEXIST;
00931 }
00932
00933
00934 else if (ec == ENOENT) {
00935
00936 if (found.fr_name) {
00937
00938 if ((node = PnutNodeAlloc(NODETYPE_DIR)) < 0) {
00939 ec = ENOSPC;
00940 }
00941
00942 else if ((ec = PnutDirAddEntry(node, ".", node)) != 0) {
00943 PnutNodeRelease(node);
00944 }
00945
00946 else if ((ec = PnutDirAddEntry(node, "..", found.fr_pnode)) != 0) {
00947 PnutNodeRelease(node);
00948 }
00949
00950 else if ((ec = PnutDirAddEntry(found.fr_pnode, found.fr_name, node)) != 0) {
00951 PnutNodeRelease(node);
00952 }
00953 }
00954 }
00955
00956
00957 if (ec) {
00958 errno = ec;
00959 return -1;
00960 }
00961 return 0;
00962 }
00963
00964
00965
00988 static NUTFILE *PnutFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
00989 {
00990 PNUT_BLKNUM node = -1;
00991 PNUT_FINDRESULT found;
00992 int rc;
00993 PNUTFILE *file;
00994 NUTFILE *nfp = NUTFILE_EOF;
00995
00996
00997 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
00998
00999 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_REG) {
01000 errno = EISDIR;
01001 }
01002
01003
01004
01005
01006
01007 else if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
01008 errno = EEXIST;
01009 } else {
01010 node = found.fr_node;
01011 if (mode & _O_TRUNC) {
01012 PnutNodeDataRelease(node);
01013 }
01014 }
01015 }
01016
01017 else if (rc == ENOENT) {
01018
01019
01020
01021
01022
01023 if (found.fr_name && (mode & _O_CREAT)) {
01024 node = PnutNodeAlloc(NODETYPE_REG);
01025
01026 if (node < 0) {
01027 errno = ENOSPC;
01028 return NUTFILE_EOF;
01029 }
01030
01031 rc = PnutDirAddEntry(found.fr_pnode, found.fr_name, node);
01032
01033 if (rc) {
01034 PnutBlockRelease(node);
01035 }
01036 }
01037 }
01038
01039 if (rc == 0 && node >= 0) {
01040 if ((file = malloc(sizeof(PNUTFILE))) != 0) {
01041 file->f_flag |= mode & (_O_RDONLY | _O_WRONLY | _O_APPEND);
01042 file->f_pos = (mode & _O_APPEND) ? BankNodePointer(node)->node_size : 0;
01043 file->f_node = node;
01044
01045 if ((nfp = malloc(sizeof(NUTFILE))) == 0) {
01046 free(file);
01047 nfp = NUTFILE_EOF;
01048 } else {
01049 nfp->nf_next = 0;
01050 nfp->nf_dev = dev;
01051 nfp->nf_fcb = file;
01052
01053 BankNodePointer(node)->node_refs++;
01054 }
01055 }
01056 }
01057 return nfp;
01058 }
01059
01063 static int PnutFileClose(NUTFILE * nfp)
01064 {
01065 if (nfp != NUTFILE_EOF) {
01066 PNUTFILE *fp = nfp->nf_fcb;
01067
01068 if (fp) {
01069 BankNodePointer(fp->f_node)->node_refs--;
01070 free(fp);
01071 }
01072 free(nfp);
01073
01074 return 0;
01075 }
01076 return EINVAL;
01077 }
01078
01086 static int PnutDelete(char *path)
01087 {
01088 int ec;
01089 PNUT_FINDRESULT found;
01090
01091 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
01092 ec = PnutDirDelEntry(found.fr_pnode, found.fr_name);
01093 }
01094 if (ec) {
01095 errno = ec;
01096 return -1;
01097 }
01098 return 0;
01099 }
01100
01109 static int PnutStatus(CONST char *path, struct stat *status)
01110 {
01111 int rc;
01112 PNUT_FINDRESULT found;
01113
01114 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
01115 status->st_mode = BankNodePointer(found.fr_node)->node_type;
01116 status->st_ino = found.fr_node;
01117 status->st_nlink = BankNodePointer(found.fr_node)->node_links;
01118 status->st_size = BankNodePointer(found.fr_node)->node_size;
01119 status->st_mtime = BankNodePointer(found.fr_node)->node_mtime;
01120 }
01121 return rc;
01122 }
01123
01133 static int PnutFileStatus(PNUTFILE * fp, struct stat *status)
01134 {
01135 status->st_mode = BankNodePointer(fp->f_node)->node_type;
01136 status->st_ino = fp->f_node;
01137 status->st_nlink = BankNodePointer(fp->f_node)->node_links;
01138 status->st_size = BankNodePointer(fp->f_node)->node_size;
01139 status->st_mtime = BankNodePointer(fp->f_node)->node_mtime;
01140
01141 return 0;
01142 }
01143
01156 static int PnutFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
01157 {
01158 PNUTFILE *fp = nfp->nf_fcb;
01159 int ec = 0;
01160 int rc = 0;
01161 PNUT_BLKNUM node = fp->f_node;
01162 uint8_t *blkptr;
01163 size_t blksiz;
01164 CONST char *buf = buffer;
01165
01166 while (len) {
01167 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 1)) != 0) {
01168 break;
01169 }
01170 if (blksiz >= len) {
01171 blksiz = len;
01172 len = 0;
01173 } else {
01174 len -= blksiz;
01175 }
01176 memcpy(blkptr, buf, blksiz);
01177 rc += blksiz;
01178 buf += blksiz;
01179 fp->f_pos += blksiz;
01180 }
01181 if (ec == 0 || ec == ENOSPC) {
01182 if (BankNodePointer(node)->node_size < fp->f_pos) {
01183 BankNodePointer(node)->node_size = fp->f_pos;
01184 }
01185 BankNodePointer(node)->node_mtime = time(0);
01186 }
01187 return rc;
01188 }
01189
01190 #ifdef __HARVARD_ARCH__
01191 static int PnutFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
01192 {
01193 return -1;
01194 }
01195 #endif
01196
01208 static int PnutFileRead(NUTFILE * nfp, void *buffer, int len)
01209 {
01210 PNUTFILE *fp = nfp->nf_fcb;
01211 int ec = 0;
01212 int rc = 0;
01213 PNUT_BLKNUM node = fp->f_node;
01214 uint8_t *blkptr;
01215 size_t blksiz;
01216 char *buf = buffer;
01217
01218
01219 if (len > BankNodePointer(node)->node_size - fp->f_pos) {
01220 len = (size_t) (BankNodePointer(node)->node_size - fp->f_pos);
01221 }
01222 while (len) {
01223 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 0)) != 0) {
01224 break;
01225 }
01226 if (blksiz >= len) {
01227 blksiz = len;
01228 len = 0;
01229 } else {
01230 len -= blksiz;
01231 }
01232 memcpy(buf, blkptr, blksiz);
01233 rc += blksiz;
01234 buf += blksiz;
01235 fp->f_pos += blksiz;
01236 }
01237 return rc;
01238 }
01239
01240 static int PnutFileSeek(PNUTFILE * fp, long *pos, int whence)
01241 {
01242 int rc = 0;
01243 long npos = *pos;
01244
01245 switch (whence) {
01246 case SEEK_CUR:
01247 npos += fp->f_pos;
01248 break;
01249 case SEEK_END:
01250 npos += BankNodePointer(fp->f_node)->node_size;
01251 break;
01252 }
01253
01254 if (npos < 0 || npos > (long) BankNodePointer(fp->f_node)->node_size) {
01255 rc = EINVAL;
01256 } else {
01257 fp->f_pos = npos;
01258 *pos = npos;
01259 }
01260 return rc;
01261 }
01262
01263
01264
01268 int PnutIOCtl(NUTDEVICE * dev, int req, void *conf)
01269 {
01270 int rc = -1;
01271
01272 switch (req) {
01273 case FS_STATUS:
01274 {
01275 FSCP_STATUS *par = (FSCP_STATUS *) conf;
01276
01277 rc = PnutStatus(par->par_path, par->par_stp);
01278 }
01279 break;
01280 case FS_DIR_CREATE:
01281 rc = PnutDirCreate((char *) conf);
01282 break;
01283 case FS_DIR_REMOVE:
01284 rc = PnutDelete((char *) conf);
01285 break;
01286 case FS_DIR_OPEN:
01287 rc = PnutDirOpen(dev, (DIR *) conf);
01288 break;
01289 case FS_DIR_CLOSE:
01290 rc = PnutDirClose((DIR *) conf);
01291 break;
01292 case FS_DIR_READ:
01293 rc = PnutDirRead((DIR *) conf);
01294 break;
01295 case FS_FILE_STATUS:
01296 rc = PnutFileStatus((PNUTFILE *) ((IOCTL_ARG2 *) conf)->arg1,
01297 (struct stat *) ((IOCTL_ARG2 *) conf)->arg2);
01298 break;
01299 case FS_FILE_DELETE:
01300 rc = PnutDelete((char *) conf);
01301 break;
01302 case FS_FILE_SEEK:
01303 PnutFileSeek((PNUTFILE *) ((IOCTL_ARG3 *) conf)->arg1,
01304 (long *) ((IOCTL_ARG3 *) conf)->arg2,
01305 (int) ((IOCTL_ARG3 *) conf)->arg3);
01306 break;
01307 }
01308 return rc;
01309 }
01310
01322 static long PnutFileSize(NUTFILE *nfp)
01323 {
01324 PNUTFILE *fp = nfp->nf_fcb;
01325
01326 return BankNodePointer(fp->f_node)->node_size;
01327 }
01328
01329
01330
01342 static int PnutInit(NUTDEVICE * dev)
01343 {
01344 PNUT_BLKNUM i;
01345 int rc;
01346
01347
01348 for (i = 0; i < PNUT_TOTAL_BLOCKS; i++) {
01349 PnutBlockRelease(i);
01350 }
01351
01352
01353 if ((root = PnutNodeAlloc(NODETYPE_DIR)) == -1) {
01354 rc = ENOSPC;
01355 } else {
01356 if ((rc = PnutDirAddEntry(root, ".", root)) == 0) {
01357 rc = PnutDirAddEntry(root, "..", root);
01358 }
01359 if (rc) {
01360 PnutBlockRelease(root);
01361 }
01362 }
01363 return rc;
01364 }
01365
01369 NUTDEVICE devPnut = {
01370 0,
01371 {'P', 'N', 'U', 'T', 0, 0, 0, 0, 0}
01372 ,
01373 IFTYP_RAM,
01374 0,
01375 0,
01376 0,
01377 0,
01378 PnutInit,
01379 PnutIOCtl,
01380 PnutFileRead,
01381 PnutFileWrite,
01382 #ifdef __HARVARD_ARCH__
01383 PnutFileWrite_P,
01384 #endif
01385 PnutFileOpen,
01386 PnutFileClose,
01387 PnutFileSize
01388 };
01389