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
00088 #include <compiler.h>
00089
00090 #include <stdlib.h>
00091 #include <string.h>
00092 #include <time.h>
00093 #include <fcntl.h>
00094 #include <dirent.h>
00095 #include <errno.h>
00096
00097 #include <sys/stat.h>
00098 #include <sys/file.h>
00099 #include <sys/bankmem.h>
00100
00101 #include <fs/fs.h>
00102 #include <dev/pnut.h>
00103
00108
00115
00120 #ifndef PNUT_BLOCK_SIZE
00121 #define PNUT_BLOCK_SIZE 512
00122 #endif
00123
00130 #ifndef PNUT_DIRENT_SIZE
00131 #define PNUT_DIRENT_SIZE 32
00132 #endif
00133
00146 #ifndef PNUT_BLOCKS_PER_NODE
00147 #define PNUT_BLOCKS_PER_NODE 250
00148 #endif
00149
00150 #ifndef PNUTBANK_COUNT
00151 #ifdef ARTHERNET1
00152
00153 #define PNUTBANK_COUNT 15
00154 #elif MMNET02 || MMNET03 || MMNET04 ||\
00155 MMNET102 || MMNET103 || MMNET104
00156
00157 #define PNUTBANK_COUNT 6
00158 #else
00159
00160 #define PNUTBANK_COUNT 30
00161 #endif
00162 #endif
00163
00167 #ifndef SEEK_SET
00168 # define SEEK_SET 0
00169 # define SEEK_CUR 1
00170 # define SEEK_END 2
00171 #endif
00172
00173 #define NODETYPE_REG 0
00174 #define NODETYPE_DIR 1
00175
00176
00177 typedef short PNUT_BLKNUM;
00178
00197 typedef struct {
00198 uint8_t node_type;
00199 uint8_t node_refs;
00210 uint16_t node_links;
00211 uint32_t node_size;
00212 time_t node_mtime;
00213 PNUT_BLKNUM node_blocks[PNUT_BLOCKS_PER_NODE];
00214 } PNUT_NODE;
00215
00222 #define PNUT_MAX_NAMELEN (PNUT_DIRENT_SIZE - sizeof(PNUT_BLKNUM) - sizeof(uint8_t) - 1)
00223
00232 typedef struct {
00238 PNUT_BLKNUM dir_node;
00244 uint8_t dir_inuse;
00250 char dir_name[PNUT_MAX_NAMELEN + 1];
00251 } PNUT_DIRENTRY;
00252
00259 #define PNUT_MAX_FILESIZE (PNUT_BLOCKS_PER_NODE * PNUT_BLOCK_SIZE)
00260
00264 typedef struct {
00268 PNUT_BLKNUM fr_node;
00269
00273 PNUT_BLKNUM fr_pnode;
00274
00280 CONST char *fr_name;
00281 } PNUT_FINDRESULT;
00282
00286 typedef struct _PNUTFILE PNUTFILE;
00287
00291 struct _PNUTFILE {
00292 PNUT_BLKNUM f_node;
00293 uint32_t f_pos;
00294 u_int f_flag;
00295 };
00296
00298 static PNUT_BLKNUM root;
00299
00300
00301
00303 #ifndef NUTBANK_SIZE
00304 #define NUTBANK_SIZE 16384
00305 #endif
00306
00317 #ifndef PNUT_TOTAL_BLOCKS
00318 #define PNUT_TOTAL_BLOCKS (PNUTBANK_COUNT * (NUTBANK_SIZE / PNUT_BLOCK_SIZE))
00319 #endif
00320
00321 #define BLOCKS_PER_BANK (NUTBANK_SIZE / PNUT_BLOCK_SIZE)
00322
00323 #ifndef NUTBANK_SR
00324 #define NUTBANK_SR 0xFF00
00325 #endif
00326
00327 #ifndef NUTBANK_START
00328 #define NUTBANK_START 0x8000
00329 #endif
00330
00331 #define NUTBANK_PTR ((char *)NUTBANK_START)
00332
00344 void BankSelect(PNUT_BLKNUM blk)
00345 {
00346
00347
00348
00349 #if NUTBANK_COUNT
00350 int bank = blk / BLOCKS_PER_BANK;
00351 #endif
00352
00353 NutSegBufEnable(bank);
00354 }
00355
00359 PNUT_NODE *BankNodePointer(PNUT_BLKNUM blk)
00360 {
00361 if (blk < 0) {
00362 return NULL;
00363 }
00364 BankSelect(blk);
00365 return (PNUT_NODE *) & NUTBANK_PTR[(blk % BLOCKS_PER_BANK) * PNUT_BLOCK_SIZE];
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 static PNUT_BLKNUM blockFreeList = -1;
00384
00392 static PNUT_BLKNUM PnutBlockAlloc(void)
00393 {
00394 PNUT_BLKNUM rc = blockFreeList;
00395
00396 if (rc >= 0) {
00397 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blockFreeList);
00398 blockFreeList = *bankptr;
00399
00400 memset(bankptr, 0, PNUT_BLOCK_SIZE);
00401 }
00402 return rc;
00403 }
00404
00412 static void PnutBlockRelease(PNUT_BLKNUM blk)
00413 {
00414 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blk);
00415
00416 *bankptr = blockFreeList;
00417 blockFreeList = blk;
00418 }
00419
00420
00421
00431 static PNUT_BLKNUM PnutNodeAlloc(uint8_t type)
00432 {
00433 PNUT_BLKNUM node = PnutBlockAlloc();
00434
00435 if (node >= 0) {
00436 int i;
00437 PNUT_NODE *np = BankNodePointer(node);
00438
00439
00440 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00441 np->node_blocks[i] = -1;
00442 }
00443
00444
00445 np->node_type = type;
00446 np->node_mtime = time(0);
00447 }
00448 return node;
00449 }
00450
00451
00452
00453
00454 static void PnutNodeDataRelease(PNUT_BLKNUM node)
00455 {
00456 int i;
00457
00458 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00459 if (BankNodePointer(node)->node_blocks[i] >= 0) {
00460 PnutBlockRelease(BankNodePointer(node)->node_blocks[i]);
00461 BankNodePointer(node)->node_blocks[i] = -1;
00462 }
00463 }
00464 BankNodePointer(node)->node_size = 0;
00465 BankNodePointer(node)->node_mtime = time(0);
00466 }
00467
00471 static void PnutNodeRelease(PNUT_BLKNUM node)
00472 {
00473 PnutNodeDataRelease(node);
00474 PnutBlockRelease(node);
00475 }
00476
00493 static int PnutNodeGetDataPtr(PNUT_BLKNUM node, uint32_t pos, void **buffer, size_t * size, int create)
00494 {
00495 int blkidx;
00496 int rc = EINVAL;
00497
00498 *buffer = NULL;
00499 *size = 0;
00500
00501
00502 if ((blkidx = pos / PNUT_BLOCK_SIZE) < PNUT_BLOCKS_PER_NODE) {
00503 PNUT_BLKNUM blk;
00504
00505
00506 if ((blk = BankNodePointer(node)->node_blocks[blkidx]) < 0 && create) {
00507 if ((blk = PnutBlockAlloc()) < 0) {
00508 rc = ENOSPC;
00509 } else {
00510 BankNodePointer(node)->node_blocks[blkidx] = blk;
00511 }
00512 }
00513
00514
00515
00516
00517
00518 if (blk >= 0) {
00519 char *blkptr = (char *) BankNodePointer(blk);
00520 int blkpos = pos % PNUT_BLOCK_SIZE;
00521
00522 *buffer = blkptr + blkpos;
00523 *size = PNUT_BLOCK_SIZE - blkpos;
00524 rc = 0;
00525 }
00526 }
00527 return rc;
00528 }
00529
00530
00531
00532
00536 static int PnutDirIsEmpty(PNUT_BLKNUM node)
00537 {
00538 int rc = 1;
00539 uint32_t pos;
00540 size_t size;
00541 PNUT_DIRENTRY *entry;
00542
00543
00544 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00545
00546
00547 if (PnutNodeGetDataPtr(node, pos, (void *) &entry, &size, 0) || size == 0) {
00548
00549 break;
00550 }
00551
00552 if (size >= PNUT_DIRENT_SIZE) {
00553 if (entry->dir_inuse && strcmp(entry->dir_name, ".") && strcmp(entry->dir_name, "..")) {
00554
00555 rc = 0;
00556 break;
00557 }
00558 }
00559 }
00560 return rc;
00561 }
00562
00576 static int PnutDirFindEntry(PNUT_BLKNUM node, CONST char *path, size_t len, PNUT_DIRENTRY ** entry)
00577 {
00578 int rc = ENOENT;
00579 uint32_t pos;
00580 size_t size;
00581
00582
00583 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00584
00585
00586 if (PnutNodeGetDataPtr(node, pos, (void **) entry, &size, 0) || size == 0) {
00587
00588 break;
00589 }
00590
00591
00592 if (size >= PNUT_DIRENT_SIZE) {
00593 if ((*entry)->dir_inuse &&
00594 strlen((*entry)->dir_name) == len &&
00595 strncmp((*entry)->dir_name, path, len) == 0) {
00596
00597 rc = 0;
00598 break;
00599 }
00600 }
00601 }
00602 return rc;
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static int PnutDirFindPath(PNUT_BLKNUM node, CONST char *path, PNUT_FINDRESULT * result)
00615 {
00616 int rc = 0;
00617 size_t len;
00618 PNUT_DIRENTRY *entry;
00619
00620 result->fr_pnode = node;
00621 result->fr_node = -1;
00622 result->fr_name = NULL;
00623
00624 while (*path == '/') {
00625 path++;
00626 }
00627
00628 if (*path == 0) {
00629 path = ".";
00630 }
00631
00632
00633
00634
00635 while (*path) {
00636 CONST char *cp;
00637
00638
00639 if (BankNodePointer(node)->node_type != NODETYPE_DIR) {
00640 rc = ENOTDIR;
00641 break;
00642 }
00643
00644
00645 for (len = 0, cp = path; *cp && *cp != '/'; cp++) {
00646 len++;
00647 }
00648
00649
00650
00651
00652
00653 if (*cp == 0) {
00654 result->fr_name = path;
00655 }
00656
00657
00658 if ((rc = PnutDirFindEntry(node, path, len, &entry)) != 0) {
00659 rc = ENOENT;
00660 break;
00661 }
00662
00663
00664 result->fr_node = entry->dir_node;
00665 if (*cp == 0) {
00666 break;
00667 }
00668
00669
00670 result->fr_pnode = result->fr_node;
00671
00672
00673 node = result->fr_node;
00674 path += len;
00675 while (*path == '/') {
00676 path++;
00677 }
00678 }
00679 return rc;
00680 }
00681
00682
00693 static int PnutDirOpen(NUTDEVICE * dev, DIR * dir)
00694 {
00695 PNUTFILE *fp;
00696 PNUT_FINDRESULT found;
00697 int rc;
00698
00699
00700 if ((rc = PnutDirFindPath(root, dir->dd_buf, &found)) != 0) {
00701 errno = rc;
00702 rc = -1;
00703 } else {
00704 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_DIR) {
00705 errno = ENOTDIR;
00706 rc = -1;
00707 }
00708
00709 else if ((fp = malloc(sizeof(PNUTFILE))) == 0) {
00710 rc = -1;
00711 }
00712
00713
00714
00715
00716 else {
00717 fp->f_node = found.fr_node;
00718 fp->f_pos = 0;
00719
00720 if ((dir->dd_fd = malloc(sizeof(NUTFILE))) == 0) {
00721 free(fp);
00722 rc = -1;
00723 }
00724 else {
00725 memset(dir->dd_fd, 0, sizeof(NUTFILE));
00726 dir->dd_fd->nf_dev = dev;
00727 dir->dd_fd->nf_fcb = fp;
00728
00729 BankNodePointer(fp->f_node)->node_refs++;
00730 }
00731 }
00732 }
00733 return rc;
00734 }
00735
00739 static int PnutDirClose(DIR * dir)
00740 {
00741 if (dir && dir->dd_fd) {
00742 if (dir->dd_fd->nf_fcb) {
00743 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00744
00745 BankNodePointer(fp->f_node)->node_refs--;
00746 free(fp);
00747 }
00748 free(dir->dd_fd);
00749 return 0;
00750 }
00751 return EINVAL;
00752 }
00753
00757 static int PnutDirRead(DIR * dir)
00758 {
00759 int rc = -1;
00760 uint32_t pos;
00761 PNUT_DIRENTRY *entry;
00762 size_t size;
00763 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00764 struct dirent *ent = (struct dirent *) dir->dd_buf;
00765
00766 ent->d_name[0] = 0;
00767 for (pos = fp->f_pos; pos < BankNodePointer(fp->f_node)->node_size; pos += PNUT_DIRENT_SIZE) {
00768
00769 rc = PnutNodeGetDataPtr(fp->f_node, pos, (void *) &entry, &size, 0);
00770 if (rc || size == 0) {
00771
00772 rc = -1;
00773 break;
00774 }
00775 fp->f_pos = pos + PNUT_DIRENT_SIZE;
00776
00777
00778 if (size >= PNUT_DIRENT_SIZE && entry->dir_inuse) {
00779 memset(ent, 0, sizeof(struct dirent));
00780 ent->d_fileno = entry->dir_node;
00781 ent->d_namlen = (uint8_t) strlen(entry->dir_name);
00782 strcpy(ent->d_name, entry->dir_name);
00783 break;
00784 }
00785 }
00786 return rc;
00787 }
00788
00798 static int PnutDirAddEntry(PNUT_BLKNUM dnode, CONST char *name, PNUT_BLKNUM enode)
00799 {
00800 int rc = 0;
00801 uint32_t pos = 0;
00802 size_t size;
00803 PNUT_DIRENTRY *entry;
00804 PNUT_NODE *np;
00805
00806
00807
00808
00809
00810
00811
00812 for (;;) {
00813
00814
00815
00816
00817 if ((rc = PnutNodeGetDataPtr(dnode, pos, (void *) &entry, &size, 1)) != 0) {
00818 break;
00819 }
00820 pos += PNUT_DIRENT_SIZE;
00821
00822
00823 if (size >= PNUT_DIRENT_SIZE) {
00824
00825 if (entry->dir_inuse == 0) {
00826
00827 entry->dir_node = enode;
00828 entry->dir_inuse = 1;
00829 strcpy(entry->dir_name, name);
00830
00831
00832 np = BankNodePointer(dnode);
00833 np->node_mtime = time(0);
00834 if (pos > np->node_size) {
00835 np->node_size = pos;
00836 }
00837
00838
00839 np = BankNodePointer(enode);
00840 np->node_links++;
00841 break;
00842 }
00843 }
00844 }
00845 return rc;
00846 }
00847
00864 static int PnutDirDelEntry(PNUT_BLKNUM node, CONST char *name)
00865 {
00866 int rc;
00867 PNUT_DIRENTRY *entry;
00868 PNUT_NODE *rnp;
00869 PNUT_BLKNUM rnode;
00870
00871
00872 if ((rc = PnutDirFindEntry(node, name, strlen(name), &entry)) != 0) {
00873 return rc;
00874 }
00875
00876
00877 rnode = entry->dir_node;
00878 rnp = BankNodePointer(rnode);
00879
00880
00881 if (rnp->node_refs) {
00882 return EACCES;
00883 }
00884
00885
00886 if (rnp->node_type == NODETYPE_DIR) {
00887 if (rnp->node_links > 2 || !PnutDirIsEmpty(rnode)) {
00888 return EACCES;
00889 }
00890 rnp = BankNodePointer(node);
00891 rnp->node_links--;
00892 PnutNodeRelease(rnode);
00893 }
00894
00895
00896 else {
00897 PnutNodeRelease(rnode);
00898 }
00899
00900
00901 PnutDirFindEntry(node, name, strlen(name), &entry);
00902 entry->dir_inuse = 0;
00903
00904 return 0;
00905 }
00906
00914 static int PnutDirCreate(CONST char *path)
00915 {
00916 PNUT_BLKNUM node;
00917 PNUT_FINDRESULT found;
00918 int ec;
00919
00920
00921 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
00922 ec = EEXIST;
00923 }
00924
00925
00926 else if (ec == ENOENT) {
00927
00928 if (found.fr_name) {
00929
00930 if ((node = PnutNodeAlloc(NODETYPE_DIR)) < 0) {
00931 ec = ENOSPC;
00932 }
00933
00934 else if ((ec = PnutDirAddEntry(node, ".", node)) != 0) {
00935 PnutNodeRelease(node);
00936 }
00937
00938 else if ((ec = PnutDirAddEntry(node, "..", found.fr_pnode)) != 0) {
00939 PnutNodeRelease(node);
00940 }
00941
00942 else if ((ec = PnutDirAddEntry(found.fr_pnode, found.fr_name, node)) != 0) {
00943 PnutNodeRelease(node);
00944 }
00945 }
00946 }
00947
00948
00949 if (ec) {
00950 errno = ec;
00951 return -1;
00952 }
00953 return 0;
00954 }
00955
00956
00957
00980 static NUTFILE *PnutFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
00981 {
00982 PNUT_BLKNUM node = -1;
00983 PNUT_FINDRESULT found;
00984 int rc;
00985 PNUTFILE *file;
00986 NUTFILE *nfp = NUTFILE_EOF;
00987
00988
00989 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
00990
00991 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_REG) {
00992 errno = EISDIR;
00993 }
00994
00995
00996
00997
00998
00999 else if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
01000 errno = EEXIST;
01001 } else {
01002 node = found.fr_node;
01003 if (mode & _O_TRUNC) {
01004 PnutNodeDataRelease(node);
01005 }
01006 }
01007 }
01008
01009 else if (rc == ENOENT) {
01010
01011
01012
01013
01014
01015 if (found.fr_name && (mode & _O_CREAT)) {
01016 node = PnutNodeAlloc(NODETYPE_REG);
01017
01018 if (node < 0) {
01019 errno = ENOSPC;
01020 return NUTFILE_EOF;
01021 }
01022
01023 rc = PnutDirAddEntry(found.fr_pnode, found.fr_name, node);
01024
01025 if (rc) {
01026 PnutBlockRelease(node);
01027 }
01028 }
01029 }
01030
01031 if (rc == 0 && node >= 0) {
01032 if ((file = malloc(sizeof(PNUTFILE))) != 0) {
01033 file->f_flag |= mode & (_O_RDONLY | _O_WRONLY | _O_APPEND);
01034 file->f_pos = (mode & _O_APPEND) ? BankNodePointer(node)->node_size : 0;
01035 file->f_node = node;
01036
01037 if ((nfp = malloc(sizeof(NUTFILE))) == 0) {
01038 free(file);
01039 nfp = NUTFILE_EOF;
01040 } else {
01041 nfp->nf_next = 0;
01042 nfp->nf_dev = dev;
01043 nfp->nf_fcb = file;
01044
01045 BankNodePointer(node)->node_refs++;
01046 }
01047 }
01048 }
01049 return nfp;
01050 }
01051
01055 static int PnutFileClose(NUTFILE * nfp)
01056 {
01057 if (nfp != NUTFILE_EOF) {
01058 PNUTFILE *fp = nfp->nf_fcb;
01059
01060 if (fp) {
01061 BankNodePointer(fp->f_node)->node_refs--;
01062 free(fp);
01063 }
01064 free(nfp);
01065
01066 return 0;
01067 }
01068 return EINVAL;
01069 }
01070
01078 static int PnutDelete(char *path)
01079 {
01080 int ec;
01081 PNUT_FINDRESULT found;
01082
01083 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
01084 ec = PnutDirDelEntry(found.fr_pnode, found.fr_name);
01085 }
01086 if (ec) {
01087 errno = ec;
01088 return -1;
01089 }
01090 return 0;
01091 }
01092
01101 static int PnutStatus(CONST char *path, struct stat *status)
01102 {
01103 int rc;
01104 PNUT_FINDRESULT found;
01105
01106 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
01107 status->st_mode = BankNodePointer(found.fr_node)->node_type;
01108 status->st_ino = found.fr_node;
01109 status->st_nlink = BankNodePointer(found.fr_node)->node_links;
01110 status->st_size = BankNodePointer(found.fr_node)->node_size;
01111 status->st_mtime = BankNodePointer(found.fr_node)->node_mtime;
01112 }
01113 return rc;
01114 }
01115
01125 static int PnutFileStatus(PNUTFILE * fp, struct stat *status)
01126 {
01127 status->st_mode = BankNodePointer(fp->f_node)->node_type;
01128 status->st_ino = fp->f_node;
01129 status->st_nlink = BankNodePointer(fp->f_node)->node_links;
01130 status->st_size = BankNodePointer(fp->f_node)->node_size;
01131 status->st_mtime = BankNodePointer(fp->f_node)->node_mtime;
01132
01133 return 0;
01134 }
01135
01148 static int PnutFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
01149 {
01150 PNUTFILE *fp = nfp->nf_fcb;
01151 int ec = 0;
01152 int rc = 0;
01153 PNUT_BLKNUM node = fp->f_node;
01154 uint8_t *blkptr;
01155 size_t blksiz;
01156 CONST char *buf = buffer;
01157
01158 while (len) {
01159 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 1)) != 0) {
01160 break;
01161 }
01162 if (blksiz >= len) {
01163 blksiz = len;
01164 len = 0;
01165 } else {
01166 len -= blksiz;
01167 }
01168 memcpy(blkptr, buf, blksiz);
01169 rc += blksiz;
01170 buf += blksiz;
01171 fp->f_pos += blksiz;
01172 }
01173 if (ec == 0 || ec == ENOSPC) {
01174 if (BankNodePointer(node)->node_size < fp->f_pos) {
01175 BankNodePointer(node)->node_size = fp->f_pos;
01176 }
01177 BankNodePointer(node)->node_mtime = time(0);
01178 }
01179 return rc;
01180 }
01181
01182 #ifdef __HARVARD_ARCH__
01183 static int PnutFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
01184 {
01185 return -1;
01186 }
01187 #endif
01188
01200 static int PnutFileRead(NUTFILE * nfp, void *buffer, int len)
01201 {
01202 PNUTFILE *fp = nfp->nf_fcb;
01203 int ec = 0;
01204 int rc = 0;
01205 PNUT_BLKNUM node = fp->f_node;
01206 uint8_t *blkptr;
01207 size_t blksiz;
01208 char *buf = buffer;
01209
01210
01211 if (len > BankNodePointer(node)->node_size - fp->f_pos) {
01212 len = (size_t) (BankNodePointer(node)->node_size - fp->f_pos);
01213 }
01214 while (len) {
01215 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 0)) != 0) {
01216 break;
01217 }
01218 if (blksiz >= len) {
01219 blksiz = len;
01220 len = 0;
01221 } else {
01222 len -= blksiz;
01223 }
01224 memcpy(buf, blkptr, blksiz);
01225 rc += blksiz;
01226 buf += blksiz;
01227 fp->f_pos += blksiz;
01228 }
01229 return rc;
01230 }
01231
01232 static int PnutFileSeek(PNUTFILE * fp, long *pos, int whence)
01233 {
01234 int rc = 0;
01235 long npos = *pos;
01236
01237 switch (whence) {
01238 case SEEK_CUR:
01239 npos += fp->f_pos;
01240 break;
01241 case SEEK_END:
01242 npos += BankNodePointer(fp->f_node)->node_size;
01243 break;
01244 }
01245
01246 if (npos < 0 || npos > (long) BankNodePointer(fp->f_node)->node_size) {
01247 rc = EINVAL;
01248 } else {
01249 fp->f_pos = npos;
01250 *pos = npos;
01251 }
01252 return rc;
01253 }
01254
01255
01256
01260 int PnutIOCtl(NUTDEVICE * dev, int req, void *conf)
01261 {
01262 int rc = -1;
01263
01264 switch (req) {
01265 case FS_STATUS:
01266 {
01267 FSCP_STATUS *par = (FSCP_STATUS *) conf;
01268
01269 rc = PnutStatus(par->par_path, par->par_stp);
01270 }
01271 break;
01272 case FS_DIR_CREATE:
01273 rc = PnutDirCreate((char *) conf);
01274 break;
01275 case FS_DIR_REMOVE:
01276 rc = PnutDelete((char *) conf);
01277 break;
01278 case FS_DIR_OPEN:
01279 rc = PnutDirOpen(dev, (DIR *) conf);
01280 break;
01281 case FS_DIR_CLOSE:
01282 rc = PnutDirClose((DIR *) conf);
01283 break;
01284 case FS_DIR_READ:
01285 rc = PnutDirRead((DIR *) conf);
01286 break;
01287 case FS_FILE_STATUS:
01288 rc = PnutFileStatus((PNUTFILE *) ((IOCTL_ARG2 *) conf)->arg1,
01289 (struct stat *) ((IOCTL_ARG2 *) conf)->arg2);
01290 break;
01291 case FS_FILE_DELETE:
01292 rc = PnutDelete((char *) conf);
01293 break;
01294 case FS_FILE_SEEK:
01295 PnutFileSeek((PNUTFILE *) ((IOCTL_ARG3 *) conf)->arg1,
01296 (long *) ((IOCTL_ARG3 *) conf)->arg2,
01297 (int) ((IOCTL_ARG3 *) conf)->arg3);
01298 break;
01299 }
01300 return rc;
01301 }
01302
01314 static long PnutFileSize(NUTFILE *nfp)
01315 {
01316 PNUTFILE *fp = nfp->nf_fcb;
01317
01318 return BankNodePointer(fp->f_node)->node_size;
01319 }
01320
01321
01322
01334 static int PnutInit(NUTDEVICE * dev)
01335 {
01336 PNUT_BLKNUM i;
01337 int rc;
01338
01339
01340 for (i = 0; i < PNUT_TOTAL_BLOCKS; i++) {
01341 PnutBlockRelease(i);
01342 }
01343
01344
01345 if ((root = PnutNodeAlloc(NODETYPE_DIR)) == -1) {
01346 rc = ENOSPC;
01347 } else {
01348 if ((rc = PnutDirAddEntry(root, ".", root)) == 0) {
01349 rc = PnutDirAddEntry(root, "..", root);
01350 }
01351 if (rc) {
01352 PnutBlockRelease(root);
01353 }
01354 }
01355 return rc;
01356 }
01357
01361 NUTDEVICE devPnut = {
01362 0,
01363 {'P', 'N', 'U', 'T', 0, 0, 0, 0, 0}
01364 ,
01365 IFTYP_RAM,
01366 0,
01367 0,
01368 0,
01369 0,
01370 PnutInit,
01371 PnutIOCtl,
01372 PnutFileRead,
01373 PnutFileWrite,
01374 #ifdef __HARVARD_ARCH__
01375 PnutFileWrite_P,
01376 #endif
01377 PnutFileOpen,
01378 PnutFileClose,
01379 PnutFileSize
01380 };
01381