1. Paweł Wieczorek
  2. Impala

Commits

Paweł Wieczorek  committed 4986c5f

* fatfs
* przepisywanie jakichkolwiek katalogów
* w pełni działający truncate
* zapis do plików

  • Participants
  • Parent commits b803a99
  • Branches impala-fatfs

Comments (0)

Files changed (4)

File sys/fs/fatfs/fat_dirent.c

View file
 fatfs_node_t *
 fatfs_dir_create(fatfs_dir_t *dir, const char *name, int type, blkno_t clu)
 {
-    
     KASSERT(type == FATFS_DIR || type == FATFS_REG);
     fatfs_node_t *node = fatfs_node_alloc(dir->node->fatfs, type);
     fatfs_dirent_t *dirent = kmem_zalloc( sizeof(*dirent), KM_SLEEP );
     node->dir->node = node;
     LIST_CREATE(&node->dir->dirents, fatfs_dirent_t, L_dirents, FALSE);
 
+
+
     if (node->type == FATFS_ROOT) {
         err = load_from_root(node->dir);
     } else {
 
 
 /*============================================================================
- * Pomocnicze procedury
+ * Obsługa zapisu i odczytu katalogów z nośnika
  */
 
 int
 rewrite_whole_dir(fatfs_dir_t *dir)
 {
+    int err;
     uio_t u;
     iovec_t iov;
     fatfs_dirent_t *dirent;
     size_t size = list_length(&dir->dirents);
+
+    err = fatfs_node_truncate(dir->node, size*32);
+    if (err) return err;
+
     fatfs_dentry_t *table = kmem_zalloc(size*32, KM_SLEEP);
     if (table == NULL) {
         DEBUGF("cannot allocate buffer for %u bytes", size);
     for (int i = 0; i < 11; i++) {
         sum = (((sum & 1) << 7) | ((sum & 0xFE) >> 1)) + helper[i];
     }
-    
+
     copy.attr =  (dirent->type == FATFS_REG)? 0 : FATFS_SUBDIR;
     FATFS_D_SET_INDEX(&copy, dirent->firstclu);
     FATFS_D_SET_SIZE(&copy, dirent->size);
     if (dentry->attr == 0 || ISSET(dentry->attr, FATFS_SKIP)) return;
     if ( mem_cmp(dentry->name, ".       ", 8) == 0) return;
     if ( mem_cmp(dentry->name, "..      ", 8) == 0) return;
-    
+
     if (dentry->name[0] != 0xe5) {
         fatfs_dirent_t *dirent = kmem_zalloc(sizeof(*dirent), KM_SLEEP);
         fatfs_node_t *node;

File sys/fs/fatfs/fat_main.c

View file
 }
 
 /*************************************************************************
- * Procedury obsługi VFS.
+ * Procedury zarządzające miejscem na nośniku.
  */
 
-
-
 /**
  *
  */
     do {
         clu = nclu;
         nclu = fatfs_fatget(fatfs, clu);
-        kprintf("%u<%u> ", clu, nclu);
+        kprintf("%u<%u>[%u] ", clu, nclu, fatfs->clu_used);
         fatfs_fatset(fatfs, clu, fatfs->free_first);
         fatfs->free_first = clu;
         fatfs->free_count++;
-    } while ( clu <= fatfs->clu_used );
+    } while ( nclu <= fatfs->clu_used );
     kprintf("\n");
 }
 
+/*************************************************************************
+ *
+ */
+
 
 /**
  * sprawdza pierwszy sektor nośnika

File sys/fs/fatfs/fat_node.c

View file
 {
     ssize_t r;
     fatfs_node_t *node = VTOFATFSN(v);
+    if (node->size < u->offset + u->size) {
+        r = fatfs_node_truncate(node, u->offset + u->size);
+        if (r) return r;
+    }
     r = fatfs_node_write(node, u, flags);
     return r;
 }
 int
 fatfs_truncate(vnode_t *v, off_t len)
 {
+    int err = 0;
     fatfs_node_t *node = v->v_private;
+    size_t oldsize = node->size;
     if (node->type != FATFS_REG || v->v_type != VNODE_TYPE_REG)
         return -EISDIR;
     fatfs_node_truncate(node, len);
     if (node->dirent) {
         fatfs_dir_sync(node->dirent->dirnode->dir);
     }
-    return 0;
+    if (oldsize < node->size) {
+        uio_t u;
+        iovec_t iov;
+        u.iovs = &iov;
+        u.iovcnt = 1;
+        u.space = UIO_SYSSPACE;
+        u.size = node->size - oldsize;
+        u.resid = u.size;
+        u.completed = 0;
+        iov.iov_len = u.resid;
+        iov.iov_base = kmem_zalloc(u.resid, KM_SLEEP);
+        err = fatfs_node_write(node, &u, 0);
+        err = (err < 0)? err : 0;
+    }
+    VFS_SYNC(node->fatfs->vfs);
+    return err;
 }
 
 int
         attr->va_type = v->v_type;
     if ( ISSET(attr->va_mask, VATTR_NLINK) )
         attr->va_nlink = 1;
-    if ( ISSET(attr->va_mask, VATTR_INO) )
+    if ( ISSET(attr->va_mask, VATTR_INO) ) {
         attr->va_ino = node->firstclu;
+    }
     if ( ISSET(attr->va_mask, VATTR_BLK) ) {
         attr->va_blksize = fatfs->clusize;
         attr->va_blocks = (node->size+fatfs->clusize-1)/fatfs->clusize;
 int
 fatfs_node_write(fatfs_node_t *node, uio_t *u, int flags)
 {
-    return 0;
+    iobuf_t *bp;
+    blkno_t blk;
+    off_t off = u->offset % node->fatfs->clusize;
+    size_t cont = 1;
+    u->resid = MIN(u->resid, MAX(0, node->size - u->offset));
+    u->completed = 0;
+    while ((blk=fatfs_bmap(node,u->offset,u->resid,&cont)) != -1 && u->resid) {
+        size_t size = cont*node->fatfs->clusize;
+        bp = bio_getblk(node->fatfs->dev, blk, cont*node->fatfs->clusize);
+        size -= off;
+        uio_move(bp->addr + off, MIN(size, u->resid), u);
+        off = 0;
+        bio_write(bp);
+        bio_wait(bp);
+        if ( ISSET(bp->flags, BIO_ERROR) ) {
+            int err = bp->errno;
+            bio_release(bp);
+            return -err;
+        }
+        bio_release(bp);
+    }
+    return u->completed;
 }
 
 
     }
 }
 
+void
+fatfs_dirent_sync(fatfs_node_t *node)
+{
+    if (!node->dirent) return;
+    node->dirent->size = node->size;
+    node->dirent->firstclu = node->firstclu;
+
+}
+
 fatfs_node_t *
 fatfs_node_alloc(fatfs_t *fatfs, int type)
 {
 int
 fatfs_node_truncate(fatfs_node_t *node, off_t off)
 {
-//     blkno_t alloc;
     fatfs_t *fatfs = node->fatfs;
     size_t need = (off+fatfs->clusize-1) / fatfs->clusize;
     size_t have = node->csize;
-
-    if (need == have) return 0;
-    if (need < have) {
-        DEBUGF("need=%u have=%u clu=%u", need, have, node->firstclu);
-        blkno_t clu = node->firstclu;
-        blkno_t xclu = node->firstclu;
-        for (int i = 0; i < need; i++) {
-            xclu = clu;
-            clu = fatfs_fatget(fatfs, clu);
-        }
-        DEBUGF("freeing %u", clu);
-        fatfs_space_free(fatfs, clu);
-        fatfs_fatset(fatfs, xclu, 0xfff);
-        if (need == 0) node->firstclu = 0;
-    } else {
-        panic("not supported");
-    }
+    blkno_t clu = node->firstclu;
+    blkno_t xclu = node->firstclu;
     node->size = off;
     node->csize = need;
+
+    if (need == have) {
+        DEBUGF("no cluster-chain changes");
+        fatfs_dirent_sync(node);
+
+        return 0;
+    } else
+    if (need == 0) {
+        DEBUGF("zero");
+        if (node->firstclu) {
+            DEBUGF("freeing chain");
+            fatfs_space_free(fatfs, node->firstclu);
+            node->firstclu = 0;
+        }
+        fatfs_dirent_sync(node);
+        return 0;
+    } else
+    if (have == 0) {
+        node->firstclu = fatfs_space_alloc(fatfs, need);
+        fatfs_dirent_sync(node);
+        return 0;
+    }
+
+    // jedziemy na koniec mniejszego łańcucha
+    for (int i = 0; i < need && i < have; i++) {
+        xclu = clu;
+        clu = fatfs_fatget(fatfs, clu);
+    }
+    if (need < have) {
+        fatfs_space_free(fatfs, clu);
+        fatfs_fatset(fatfs, xclu, fatfs->clu_last);
+    } else {
+        blkno_t blk = fatfs_space_alloc(fatfs, need-have);
+        fatfs_fatset(fatfs, xclu, blk);
+    }
+    fatfs_dirent_sync(node);
     return 0;
 }
 

File sys/fs/fatfs/fatfs.h

View file
     FAT12_CLU_FREE      = 0x000,
     FAT12_CLU_USED      = 0xfef,
     FAT12_CLU_BAD       = 0xff7,
-    FAT12_CLU_LAST      = 0xff8
+    FAT12_CLU_LAST      = 0xfff
 };
 
 enum FATFS_ATTR {
 
 int fatfs_node_getdir(fatfs_node_t *, fatfs_dir_t **);
 vnode_t * fatfs_node_getv(fatfs_node_t *node);
-int fatfs_node_truncate(fatfs_node_t *node, off_t );
+int fatfs_node_truncate(fatfs_node_t *node, off_t);
 int fatfs_node_read(fatfs_node_t *, uio_t *, int);
 int fatfs_node_write(fatfs_node_t *, uio_t *, int);
+void fatfs_dirent_sync(fatfs_node_t *node);
 
 int fatfs_dir_load(fatfs_node_t *);
 void fatfs_dir_free(fatfs_dir_t *);
 void fatfs_dir_sync(fatfs_dir_t *);
 void fatfs_dir_release(fatfs_dir_t *, fatfs_node_t *n);
 int fatfs_dir_getdents(fatfs_dir_t *, dirent_t *, int first, int n);
-/// pomocnicze makro rzutujące v_private
+
 #define VTOFATFSN(v) ((fatfs_node_t*)(v)->v_private)
 #define VTOFATFS(v) ((fatfs_t*)(v)->vfs_private)