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
00082 #include <compiler.h>
00083
00084 #include <stdlib.h>
00085 #include <string.h>
00086 #include <time.h>
00087 #include <fcntl.h>
00088 #include <dirent.h>
00089 #include <errno.h>
00090
00091 #include <sys/stat.h>
00092 #include <sys/file.h>
00093 #include <sys/bankmem.h>
00094
00095 #include <fs/fs.h>
00096 #include <dev/pnut.h>
00097
00102
00109
00114 #ifndef PNUT_BLOCK_SIZE
00115 #define PNUT_BLOCK_SIZE 512
00116 #endif
00117
00124 #ifndef PNUT_DIRENT_SIZE
00125 #define PNUT_DIRENT_SIZE 32
00126 #endif
00127
00140 #ifndef PNUT_BLOCKS_PER_NODE
00141 #define PNUT_BLOCKS_PER_NODE 250
00142 #endif
00143
00144 #ifndef PNUTBANK_COUNT
00145 #ifdef ARTHERNET1
00146
00147 #define PNUTBANK_COUNT 15
00148 #elif MMNET02
00149
00150 #define PNUTBANK_COUNT 6
00151 #else
00152
00153 #define PNUTBANK_COUNT 30
00154 #endif
00155 #endif
00156
00160 #ifndef SEEK_SET
00161 # define SEEK_SET 0
00162 # define SEEK_CUR 1
00163 # define SEEK_END 2
00164 #endif
00165
00166 #define NODETYPE_REG 0
00167 #define NODETYPE_DIR 1
00168
00169
00170 typedef short PNUT_BLKNUM;
00171
00190 typedef struct {
00191 uint8_t node_type;
00192 uint8_t node_refs;
00203 uint16_t node_links;
00204 uint32_t node_size;
00205 time_t node_mtime;
00206 PNUT_BLKNUM node_blocks[PNUT_BLOCKS_PER_NODE];
00207 } PNUT_NODE;
00208
00215 #define PNUT_MAX_NAMELEN (PNUT_DIRENT_SIZE - sizeof(PNUT_BLKNUM) - sizeof(uint8_t) - 1)
00216
00225 typedef struct {
00231 PNUT_BLKNUM dir_node;
00237 uint8_t dir_inuse;
00243 char dir_name[PNUT_MAX_NAMELEN + 1];
00244 } PNUT_DIRENTRY;
00245
00252 #define PNUT_MAX_FILESIZE (PNUT_BLOCKS_PER_NODE * PNUT_BLOCK_SIZE)
00253
00257 typedef struct {
00261 PNUT_BLKNUM fr_node;
00262
00266 PNUT_BLKNUM fr_pnode;
00267
00273 CONST char *fr_name;
00274 } PNUT_FINDRESULT;
00275
00279 typedef struct _PNUTFILE PNUTFILE;
00280
00284 struct _PNUTFILE {
00285 PNUT_BLKNUM f_node;
00286 uint32_t f_pos;
00287 u_int f_flag;
00288 };
00289
00291 static PNUT_BLKNUM root;
00292
00293
00294
00296 #ifndef NUTBANK_SIZE
00297 #define NUTBANK_SIZE 16384
00298 #endif
00299
00310 #ifndef PNUT_TOTAL_BLOCKS
00311 #define PNUT_TOTAL_BLOCKS (PNUTBANK_COUNT * (NUTBANK_SIZE / PNUT_BLOCK_SIZE))
00312 #endif
00313
00314 #define BLOCKS_PER_BANK (NUTBANK_SIZE / PNUT_BLOCK_SIZE)
00315
00316 #ifndef NUTBANK_SR
00317 #define NUTBANK_SR 0xFF00
00318 #endif
00319
00320 #ifndef NUTBANK_START
00321 #define NUTBANK_START 0x8000
00322 #endif
00323
00324 #define NUTBANK_PTR ((char *)NUTBANK_START)
00325
00337 void BankSelect(PNUT_BLKNUM blk)
00338 {
00339
00340
00341
00342 #if NUTBANK_COUNT
00343 int bank = blk / BLOCKS_PER_BANK;
00344 #endif
00345
00346 NutSegBufEnable(bank);
00347 }
00348
00352 PNUT_NODE *BankNodePointer(PNUT_BLKNUM blk)
00353 {
00354 if (blk < 0) {
00355 return NULL;
00356 }
00357 BankSelect(blk);
00358 return (PNUT_NODE *) & NUTBANK_PTR[(blk % BLOCKS_PER_BANK) * PNUT_BLOCK_SIZE];
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 static PNUT_BLKNUM blockFreeList = -1;
00377
00385 static PNUT_BLKNUM PnutBlockAlloc(void)
00386 {
00387 PNUT_BLKNUM rc = blockFreeList;
00388
00389 if (rc >= 0) {
00390 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blockFreeList);
00391 blockFreeList = *bankptr;
00392
00393 memset(bankptr, 0, PNUT_BLOCK_SIZE);
00394 }
00395 return rc;
00396 }
00397
00405 static void PnutBlockRelease(PNUT_BLKNUM blk)
00406 {
00407 PNUT_BLKNUM *bankptr = (PNUT_BLKNUM *) BankNodePointer(blk);
00408
00409 *bankptr = blockFreeList;
00410 blockFreeList = blk;
00411 }
00412
00413
00414
00424 static PNUT_BLKNUM PnutNodeAlloc(uint8_t type)
00425 {
00426 PNUT_BLKNUM node = PnutBlockAlloc();
00427
00428 if (node >= 0) {
00429 int i;
00430 PNUT_NODE *np = BankNodePointer(node);
00431
00432
00433 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00434 np->node_blocks[i] = -1;
00435 }
00436
00437
00438 np->node_type = type;
00439 np->node_mtime = time(0);
00440 }
00441 return node;
00442 }
00443
00444
00445
00446
00447 static void PnutNodeDataRelease(PNUT_BLKNUM node)
00448 {
00449 int i;
00450
00451 for (i = 0; i < PNUT_BLOCKS_PER_NODE; i++) {
00452 if (BankNodePointer(node)->node_blocks[i] >= 0) {
00453 PnutBlockRelease(BankNodePointer(node)->node_blocks[i]);
00454 BankNodePointer(node)->node_blocks[i] = -1;
00455 }
00456 }
00457 BankNodePointer(node)->node_size = 0;
00458 BankNodePointer(node)->node_mtime = time(0);
00459 }
00460
00464 static void PnutNodeRelease(PNUT_BLKNUM node)
00465 {
00466 PnutNodeDataRelease(node);
00467 PnutBlockRelease(node);
00468 }
00469
00486 static int PnutNodeGetDataPtr(PNUT_BLKNUM node, uint32_t pos, void **buffer, size_t * size, int create)
00487 {
00488 int blkidx;
00489 int rc = EINVAL;
00490
00491 *buffer = NULL;
00492 *size = 0;
00493
00494
00495 if ((blkidx = pos / PNUT_BLOCK_SIZE) < PNUT_BLOCKS_PER_NODE) {
00496 PNUT_BLKNUM blk;
00497
00498
00499 if ((blk = BankNodePointer(node)->node_blocks[blkidx]) < 0 && create) {
00500 if ((blk = PnutBlockAlloc()) < 0) {
00501 rc = ENOSPC;
00502 } else {
00503 BankNodePointer(node)->node_blocks[blkidx] = blk;
00504 }
00505 }
00506
00507
00508
00509
00510
00511 if (blk >= 0) {
00512 char *blkptr = (char *) BankNodePointer(blk);
00513 int blkpos = pos % PNUT_BLOCK_SIZE;
00514
00515 *buffer = blkptr + blkpos;
00516 *size = PNUT_BLOCK_SIZE - blkpos;
00517 rc = 0;
00518 }
00519 }
00520 return rc;
00521 }
00522
00523
00524
00525
00529 static int PnutDirIsEmpty(PNUT_BLKNUM node)
00530 {
00531 int rc = 1;
00532 uint32_t pos;
00533 size_t size;
00534 PNUT_DIRENTRY *entry;
00535
00536
00537 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00538
00539
00540 if (PnutNodeGetDataPtr(node, pos, (void *) &entry, &size, 0) || size == 0) {
00541
00542 break;
00543 }
00544
00545 if (size >= PNUT_DIRENT_SIZE) {
00546 if (entry->dir_inuse && strcmp(entry->dir_name, ".") && strcmp(entry->dir_name, "..")) {
00547
00548 rc = 0;
00549 break;
00550 }
00551 }
00552 }
00553 return rc;
00554 }
00555
00569 static int PnutDirFindEntry(PNUT_BLKNUM node, CONST char *path, size_t len, PNUT_DIRENTRY ** entry)
00570 {
00571 int rc = ENOENT;
00572 uint32_t pos;
00573 size_t size;
00574
00575
00576 for (pos = 0; pos < BankNodePointer(node)->node_size; pos += PNUT_DIRENT_SIZE) {
00577
00578
00579 if (PnutNodeGetDataPtr(node, pos, (void **) entry, &size, 0) || size == 0) {
00580
00581 break;
00582 }
00583
00584
00585 if (size >= PNUT_DIRENT_SIZE) {
00586 if ((*entry)->dir_inuse &&
00587 strlen((*entry)->dir_name) == len &&
00588 strncmp((*entry)->dir_name, path, len) == 0) {
00589
00590 rc = 0;
00591 break;
00592 }
00593 }
00594 }
00595 return rc;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 static int PnutDirFindPath(PNUT_BLKNUM node, CONST char *path, PNUT_FINDRESULT * result)
00608 {
00609 int rc = 0;
00610 size_t len;
00611 PNUT_DIRENTRY *entry;
00612
00613 result->fr_pnode = node;
00614 result->fr_node = -1;
00615 result->fr_name = NULL;
00616
00617 while (*path == '/') {
00618 path++;
00619 }
00620
00621 if (*path == 0) {
00622 path = ".";
00623 }
00624
00625
00626
00627
00628 while (*path) {
00629 CONST char *cp;
00630
00631
00632 if (BankNodePointer(node)->node_type != NODETYPE_DIR) {
00633 rc = ENOTDIR;
00634 break;
00635 }
00636
00637
00638 for (len = 0, cp = path; *cp && *cp != '/'; cp++) {
00639 len++;
00640 }
00641
00642
00643
00644
00645
00646 if (*cp == 0) {
00647 result->fr_name = path;
00648 }
00649
00650
00651 if ((rc = PnutDirFindEntry(node, path, len, &entry)) != 0) {
00652 rc = ENOENT;
00653 break;
00654 }
00655
00656
00657 result->fr_node = entry->dir_node;
00658 if (*cp == 0) {
00659 break;
00660 }
00661
00662
00663 result->fr_pnode = result->fr_node;
00664
00665
00666 node = result->fr_node;
00667 path += len;
00668 while (*path == '/') {
00669 path++;
00670 }
00671 }
00672 return rc;
00673 }
00674
00675
00686 static int PnutDirOpen(NUTDEVICE * dev, DIR * dir)
00687 {
00688 PNUTFILE *fp;
00689 PNUT_FINDRESULT found;
00690 int rc;
00691
00692
00693 if ((rc = PnutDirFindPath(root, dir->dd_buf, &found)) != 0) {
00694 errno = rc;
00695 rc = -1;
00696 } else {
00697 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_DIR) {
00698 errno = ENOTDIR;
00699 rc = -1;
00700 }
00701
00702 else if ((fp = malloc(sizeof(PNUTFILE))) == 0) {
00703 rc = -1;
00704 }
00705
00706
00707
00708
00709 else {
00710 fp->f_node = found.fr_node;
00711 fp->f_pos = 0;
00712
00713 if ((dir->dd_fd = malloc(sizeof(NUTFILE))) == 0) {
00714 free(fp);
00715 rc = -1;
00716 }
00717 else {
00718 memset(dir->dd_fd, 0, sizeof(NUTFILE));
00719 dir->dd_fd->nf_dev = dev;
00720 dir->dd_fd->nf_fcb = fp;
00721
00722 BankNodePointer(fp->f_node)->node_refs++;
00723 }
00724 }
00725 }
00726 return rc;
00727 }
00728
00732 static int PnutDirClose(DIR * dir)
00733 {
00734 if (dir && dir->dd_fd) {
00735 if (dir->dd_fd->nf_fcb) {
00736 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00737
00738 BankNodePointer(fp->f_node)->node_refs--;
00739 free(fp);
00740 }
00741 free(dir->dd_fd);
00742 return 0;
00743 }
00744 return EINVAL;
00745 }
00746
00750 static int PnutDirRead(DIR * dir)
00751 {
00752 int rc = -1;
00753 uint32_t pos;
00754 PNUT_DIRENTRY *entry;
00755 size_t size;
00756 PNUTFILE *fp = dir->dd_fd->nf_fcb;
00757 struct dirent *ent = (struct dirent *) dir->dd_buf;
00758
00759 ent->d_name[0] = 0;
00760 for (pos = fp->f_pos; pos < BankNodePointer(fp->f_node)->node_size; pos += PNUT_DIRENT_SIZE) {
00761
00762 rc = PnutNodeGetDataPtr(fp->f_node, pos, (void *) &entry, &size, 0);
00763 if (rc || size == 0) {
00764
00765 rc = -1;
00766 break;
00767 }
00768 fp->f_pos = pos + PNUT_DIRENT_SIZE;
00769
00770
00771 if (size >= PNUT_DIRENT_SIZE && entry->dir_inuse) {
00772 memset(ent, 0, sizeof(struct dirent));
00773 ent->d_fileno = entry->dir_node;
00774 ent->d_namlen = (uint8_t) strlen(entry->dir_name);
00775 strcpy(ent->d_name, entry->dir_name);
00776 break;
00777 }
00778 }
00779 return rc;
00780 }
00781
00791 static int PnutDirAddEntry(PNUT_BLKNUM dnode, CONST char *name, PNUT_BLKNUM enode)
00792 {
00793 int rc = 0;
00794 uint32_t pos = 0;
00795 size_t size;
00796 PNUT_DIRENTRY *entry;
00797 PNUT_NODE *np;
00798
00799
00800
00801
00802
00803
00804
00805 for (;;) {
00806
00807
00808
00809
00810 if ((rc = PnutNodeGetDataPtr(dnode, pos, (void *) &entry, &size, 1)) != 0) {
00811 break;
00812 }
00813 pos += PNUT_DIRENT_SIZE;
00814
00815
00816 if (size >= PNUT_DIRENT_SIZE) {
00817
00818 if (entry->dir_inuse == 0) {
00819
00820 entry->dir_node = enode;
00821 entry->dir_inuse = 1;
00822 strcpy(entry->dir_name, name);
00823
00824
00825 np = BankNodePointer(dnode);
00826 np->node_mtime = time(0);
00827 if (pos > np->node_size) {
00828 np->node_size = pos;
00829 }
00830
00831
00832 np = BankNodePointer(enode);
00833 np->node_links++;
00834 break;
00835 }
00836 }
00837 }
00838 return rc;
00839 }
00840
00857 static int PnutDirDelEntry(PNUT_BLKNUM node, CONST char *name)
00858 {
00859 int rc;
00860 PNUT_DIRENTRY *entry;
00861 PNUT_NODE *rnp;
00862 PNUT_BLKNUM rnode;
00863
00864
00865 if ((rc = PnutDirFindEntry(node, name, strlen(name), &entry)) != 0) {
00866 return rc;
00867 }
00868
00869
00870 rnode = entry->dir_node;
00871 rnp = BankNodePointer(rnode);
00872
00873
00874 if (rnp->node_refs) {
00875 return EACCES;
00876 }
00877
00878
00879 if (rnp->node_type == NODETYPE_DIR) {
00880 if (rnp->node_links > 2 || !PnutDirIsEmpty(rnode)) {
00881 return EACCES;
00882 }
00883 rnp = BankNodePointer(node);
00884 rnp->node_links--;
00885 PnutNodeRelease(rnode);
00886 }
00887
00888
00889 else {
00890 PnutNodeRelease(rnode);
00891 }
00892
00893
00894 PnutDirFindEntry(node, name, strlen(name), &entry);
00895 entry->dir_inuse = 0;
00896
00897 return 0;
00898 }
00899
00907 static int PnutDirCreate(CONST char *path)
00908 {
00909 PNUT_BLKNUM node;
00910 PNUT_FINDRESULT found;
00911 int ec;
00912
00913
00914 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
00915 ec = EEXIST;
00916 }
00917
00918
00919 else if (ec == ENOENT) {
00920
00921 if (found.fr_name) {
00922
00923 if ((node = PnutNodeAlloc(NODETYPE_DIR)) < 0) {
00924 ec = ENOSPC;
00925 }
00926
00927 else if ((ec = PnutDirAddEntry(node, ".", node)) != 0) {
00928 PnutNodeRelease(node);
00929 }
00930
00931 else if ((ec = PnutDirAddEntry(node, "..", found.fr_pnode)) != 0) {
00932 PnutNodeRelease(node);
00933 }
00934
00935 else if ((ec = PnutDirAddEntry(found.fr_pnode, found.fr_name, node)) != 0) {
00936 PnutNodeRelease(node);
00937 }
00938 }
00939 }
00940
00941
00942 if (ec) {
00943 errno = ec;
00944 return -1;
00945 }
00946 return 0;
00947 }
00948
00949
00950
00973 static NUTFILE *PnutFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
00974 {
00975 PNUT_BLKNUM node = -1;
00976 PNUT_FINDRESULT found;
00977 int rc;
00978 PNUTFILE *file;
00979 NUTFILE *nfp = NUTFILE_EOF;
00980
00981
00982 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
00983
00984 if (BankNodePointer(found.fr_node)->node_type != NODETYPE_REG) {
00985 errno = EISDIR;
00986 }
00987
00988
00989
00990
00991
00992 else if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
00993 errno = EEXIST;
00994 } else {
00995 node = found.fr_node;
00996 if (mode & _O_TRUNC) {
00997 PnutNodeDataRelease(node);
00998 }
00999 }
01000 }
01001
01002 else if (rc == ENOENT) {
01003
01004
01005
01006
01007
01008 if (found.fr_name && (mode & _O_CREAT)) {
01009 node = PnutNodeAlloc(NODETYPE_REG);
01010
01011 if (node < 0) {
01012 errno = ENOSPC;
01013 return NUTFILE_EOF;
01014 }
01015
01016 rc = PnutDirAddEntry(found.fr_pnode, found.fr_name, node);
01017
01018 if (rc) {
01019 PnutBlockRelease(node);
01020 }
01021 }
01022 }
01023
01024 if (rc == 0 && node >= 0) {
01025 if ((file = malloc(sizeof(PNUTFILE))) != 0) {
01026 file->f_flag |= mode & (_O_RDONLY | _O_WRONLY | _O_APPEND);
01027 file->f_pos = (mode & _O_APPEND) ? BankNodePointer(node)->node_size : 0;
01028 file->f_node = node;
01029
01030 if ((nfp = malloc(sizeof(NUTFILE))) == 0) {
01031 free(file);
01032 nfp = NUTFILE_EOF;
01033 } else {
01034 nfp->nf_next = 0;
01035 nfp->nf_dev = dev;
01036 nfp->nf_fcb = file;
01037
01038 BankNodePointer(node)->node_refs++;
01039 }
01040 }
01041 }
01042 return nfp;
01043 }
01044
01048 static int PnutFileClose(NUTFILE * nfp)
01049 {
01050 if (nfp != NUTFILE_EOF) {
01051 PNUTFILE *fp = nfp->nf_fcb;
01052
01053 if (fp) {
01054 BankNodePointer(fp->f_node)->node_refs--;
01055 free(fp);
01056 }
01057 free(nfp);
01058
01059 return 0;
01060 }
01061 return EINVAL;
01062 }
01063
01071 static int PnutDelete(char *path)
01072 {
01073 int ec;
01074 PNUT_FINDRESULT found;
01075
01076 if ((ec = PnutDirFindPath(root, path, &found)) == 0) {
01077 ec = PnutDirDelEntry(found.fr_pnode, found.fr_name);
01078 }
01079 if (ec) {
01080 errno = ec;
01081 return -1;
01082 }
01083 return 0;
01084 }
01085
01094 static int PnutStatus(CONST char *path, struct stat *status)
01095 {
01096 int rc;
01097 PNUT_FINDRESULT found;
01098
01099 if ((rc = PnutDirFindPath(root, path, &found)) == 0) {
01100 status->st_mode = BankNodePointer(found.fr_node)->node_type;
01101 status->st_ino = found.fr_node;
01102 status->st_nlink = BankNodePointer(found.fr_node)->node_links;
01103 status->st_size = BankNodePointer(found.fr_node)->node_size;
01104 status->st_mtime = BankNodePointer(found.fr_node)->node_mtime;
01105 }
01106 return rc;
01107 }
01108
01118 static int PnutFileStatus(PNUTFILE * fp, struct stat *status)
01119 {
01120 status->st_mode = BankNodePointer(fp->f_node)->node_type;
01121 status->st_ino = fp->f_node;
01122 status->st_nlink = BankNodePointer(fp->f_node)->node_links;
01123 status->st_size = BankNodePointer(fp->f_node)->node_size;
01124 status->st_mtime = BankNodePointer(fp->f_node)->node_mtime;
01125
01126 return 0;
01127 }
01128
01141 static int PnutFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
01142 {
01143 PNUTFILE *fp = nfp->nf_fcb;
01144 int ec = 0;
01145 int rc = 0;
01146 PNUT_BLKNUM node = fp->f_node;
01147 uint8_t *blkptr;
01148 size_t blksiz;
01149 CONST char *buf = buffer;
01150
01151 while (len) {
01152 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 1)) != 0) {
01153 break;
01154 }
01155 if (blksiz >= len) {
01156 blksiz = len;
01157 len = 0;
01158 } else {
01159 len -= blksiz;
01160 }
01161 memcpy(blkptr, buf, blksiz);
01162 rc += blksiz;
01163 buf += blksiz;
01164 fp->f_pos += blksiz;
01165 }
01166 if (ec == 0 || ec == ENOSPC) {
01167 if (BankNodePointer(node)->node_size < fp->f_pos) {
01168 BankNodePointer(node)->node_size = fp->f_pos;
01169 }
01170 BankNodePointer(node)->node_mtime = time(0);
01171 }
01172 return rc;
01173 }
01174
01175 #ifdef __HARVARD_ARCH__
01176 static int PnutFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
01177 {
01178 return -1;
01179 }
01180 #endif
01181
01193 static int PnutFileRead(NUTFILE * nfp, void *buffer, int len)
01194 {
01195 PNUTFILE *fp = nfp->nf_fcb;
01196 int ec = 0;
01197 int rc = 0;
01198 PNUT_BLKNUM node = fp->f_node;
01199 uint8_t *blkptr;
01200 size_t blksiz;
01201 char *buf = buffer;
01202
01203
01204 if (len > BankNodePointer(node)->node_size - fp->f_pos) {
01205 len = (size_t) (BankNodePointer(node)->node_size - fp->f_pos);
01206 }
01207 while (len) {
01208 if ((ec = PnutNodeGetDataPtr(node, fp->f_pos, (void *) &blkptr, &blksiz, 0)) != 0) {
01209 break;
01210 }
01211 if (blksiz >= len) {
01212 blksiz = len;
01213 len = 0;
01214 } else {
01215 len -= blksiz;
01216 }
01217 memcpy(buf, blkptr, blksiz);
01218 rc += blksiz;
01219 buf += blksiz;
01220 fp->f_pos += blksiz;
01221 }
01222 return rc;
01223 }
01224
01225 static int PnutFileSeek(PNUTFILE * fp, long *pos, int whence)
01226 {
01227 int rc = 0;
01228 long npos = *pos;
01229
01230 switch (whence) {
01231 case SEEK_CUR:
01232 npos += fp->f_pos;
01233 break;
01234 case SEEK_END:
01235 npos += BankNodePointer(fp->f_node)->node_size;
01236 break;
01237 }
01238
01239 if (npos < 0 || npos > (long) BankNodePointer(fp->f_node)->node_size) {
01240 rc = EINVAL;
01241 } else {
01242 fp->f_pos = npos;
01243 *pos = npos;
01244 }
01245 return rc;
01246 }
01247
01248
01249
01253 int PnutIOCtl(NUTDEVICE * dev, int req, void *conf)
01254 {
01255 int rc = -1;
01256
01257 switch (req) {
01258 case FS_STATUS:
01259 {
01260 FSCP_STATUS *par = (FSCP_STATUS *) conf;
01261
01262 rc = PnutStatus(par->par_path, par->par_stp);
01263 }
01264 break;
01265 case FS_DIR_CREATE:
01266 rc = PnutDirCreate((char *) conf);
01267 break;
01268 case FS_DIR_REMOVE:
01269 rc = PnutDelete((char *) conf);
01270 break;
01271 case FS_DIR_OPEN:
01272 rc = PnutDirOpen(dev, (DIR *) conf);
01273 break;
01274 case FS_DIR_CLOSE:
01275 rc = PnutDirClose((DIR *) conf);
01276 break;
01277 case FS_DIR_READ:
01278 rc = PnutDirRead((DIR *) conf);
01279 break;
01280 case FS_FILE_STATUS:
01281 rc = PnutFileStatus((PNUTFILE *) ((IOCTL_ARG2 *) conf)->arg1,
01282 (struct stat *) ((IOCTL_ARG2 *) conf)->arg2);
01283 break;
01284 case FS_FILE_DELETE:
01285 rc = PnutDelete((char *) conf);
01286 break;
01287 case FS_FILE_SEEK:
01288 PnutFileSeek((PNUTFILE *) ((IOCTL_ARG3 *) conf)->arg1,
01289 (long *) ((IOCTL_ARG3 *) conf)->arg2,
01290 (int) ((IOCTL_ARG3 *) conf)->arg3);
01291 break;
01292 }
01293 return rc;
01294 }
01295
01307 static long PnutFileSize(NUTFILE *nfp)
01308 {
01309 PNUTFILE *fp = nfp->nf_fcb;
01310
01311 return BankNodePointer(fp->f_node)->node_size;
01312 }
01313
01314
01315
01327 static int PnutInit(NUTDEVICE * dev)
01328 {
01329 PNUT_BLKNUM i;
01330 int rc;
01331
01332
01333 for (i = 0; i < PNUT_TOTAL_BLOCKS; i++) {
01334 PnutBlockRelease(i);
01335 }
01336
01337
01338 if ((root = PnutNodeAlloc(NODETYPE_DIR)) == -1) {
01339 rc = ENOSPC;
01340 } else {
01341 if ((rc = PnutDirAddEntry(root, ".", root)) == 0) {
01342 rc = PnutDirAddEntry(root, "..", root);
01343 }
01344 if (rc) {
01345 PnutBlockRelease(root);
01346 }
01347 }
01348 return rc;
01349 }
01350
01354 NUTDEVICE devPnut = {
01355 0,
01356 {'P', 'N', 'U', 'T', 0, 0, 0, 0, 0}
01357 ,
01358 IFTYP_RAM,
01359 0,
01360 0,
01361 0,
01362 0,
01363 PnutInit,
01364 PnutIOCtl,
01365 PnutFileRead,
01366 PnutFileWrite,
01367 #ifdef __HARVARD_ARCH__
01368 PnutFileWrite_P,
01369 #endif
01370 PnutFileOpen,
01371 PnutFileClose,
01372 PnutFileSize
01373 };
01374