Subversion Repositories HelenOS

Rev

Rev 3500 | Rev 3503 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3500 Rev 3501
Line 847... Line 847...
847
 
847
 
848
    fat_node_put(nodep);
848
    fat_node_put(nodep);
849
    ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
849
    ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
850
}
850
}
851
 
851
 
-
 
852
/** Fill the gap between EOF and a new file position.
-
 
853
 *
-
 
854
 * @param nodep     FAT node with the gap.
-
 
855
 * @param mcl       First cluster in an independent cluster chain that will
-
 
856
 *          be later appended to the end of the node's own cluster
-
 
857
 *          chain. If pos is still in the last allocated cluster,
-
 
858
 *          this argument is ignored.
-
 
859
 * @param pos       Position in the last node block.
-
 
860
 */
852
static void
861
static void
853
fat_fill_gap(fat_node_t *nodep, fat_cluster_t mclst, off_t pos)
862
fat_fill_gap(fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
854
{
863
{
-
 
864
    uint16_t bps;
-
 
865
    unsigned spc;
-
 
866
    block_t *bb, *b;
-
 
867
    off_t o, boundary;
-
 
868
 
-
 
869
    bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE);
-
 
870
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
-
 
871
    spc = FAT_BS(bb)->spc;
-
 
872
    block_put(bb);
-
 
873
   
-
 
874
    boundary = ROUND_UP(nodep->size, bps * spc);
-
 
875
 
-
 
876
    /* zero out already allocated space */
-
 
877
    for (o = nodep->size - 1; o < pos && o < boundary;
-
 
878
        o = ALIGN_DOWN(o + bps, bps)) {
-
 
879
        b = fat_block_get(nodep, o / bps);
-
 
880
        memset(b->data + o % bps, 0, bps - o % bps);
-
 
881
        b->dirty = true;        /* need to sync node */
-
 
882
        block_put(b);
-
 
883
    }
-
 
884
   
855
    /* TODO */
885
    if (o >= pos)
-
 
886
        return;
-
 
887
   
-
 
888
    /* zero out the initial part of the new cluster chain */
-
 
889
    for (o = boundary; o < pos; o += bps) {
-
 
890
        b = _fat_block_get(nodep->idx->dev_handle, mcl,
-
 
891
            (o - boundary) / bps);
-
 
892
        memset(b->data, 0, min(bps, pos - o));
-
 
893
        b->dirty = true;
-
 
894
        block_put(b);
-
 
895
    }
856
}
896
}
857
 
897
 
858
static int
898
static int
859
fat_alloc_clusters(unsigned nclsts, fat_cluster_t *mcl, fat_cluster_t *lcl)
899
fat_alloc_clusters(unsigned nclsts, fat_cluster_t *mcl, fat_cluster_t *lcl)
860
{
900
{
Line 874... Line 914...
874
    fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
914
    fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
875
    size_t bytes;
915
    size_t bytes;
876
    block_t *b, *bb;
916
    block_t *b, *bb;
877
    uint16_t bps;
917
    uint16_t bps;
878
    unsigned spc;
918
    unsigned spc;
879
    off_t clst_boundary;
919
    off_t boundary;
880
   
920
   
881
    if (!nodep) {
921
    if (!nodep) {
882
        ipc_answer_0(rid, ENOENT);
922
        ipc_answer_0(rid, ENOENT);
883
        return;
923
        return;
884
    }
924
    }
Line 911... Line 951...
911
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
951
    bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
912
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
952
    bps = uint16_t_le2host(FAT_BS(bb)->bps);
913
    spc = FAT_BS(bb)->spc;
953
    spc = FAT_BS(bb)->spc;
914
    block_put(bb);
954
    block_put(bb);
915
   
955
   
916
    clst_boundary = ROUND_UP(nodep->size, bps * spc);
956
    boundary = ROUND_UP(nodep->size, bps * spc);
917
    if (pos < clst_boundary) {
957
    if (pos < boundary) {
918
        /*
958
        /*
919
         * This is the easier case - we are either overwriting already
959
         * This is the easier case - we are either overwriting already
920
         * existing contents or writing behind the EOF, but still within
960
         * existing contents or writing behind the EOF, but still within
921
         * the limits of the last cluster. The node size may grow to the
961
         * the limits of the last cluster. The node size may grow to the
922
         * next block size boundary.
962
         * next block size boundary.
Line 941... Line 981...
941
         */
981
         */
942
        int status;
982
        int status;
943
        unsigned nclsts;
983
        unsigned nclsts;
944
        fat_cluster_t mcl, lcl;
984
        fat_cluster_t mcl, lcl;
945
   
985
   
946
        nclsts = (ROUND_UP(pos + bytes, bps * spc) - clst_boundary) /
986
        nclsts = (ROUND_UP(pos + bytes, bps * spc) - boundary) /
947
            bps * spc;
987
            bps * spc;
948
        /* create an independent chain of nclsts clusters in all FATs */
988
        /* create an independent chain of nclsts clusters in all FATs */
949
        status = fat_alloc_clusters(nclsts, &mcl, &lcl);
989
        status = fat_alloc_clusters(nclsts, &mcl, &lcl);
950
        if (status != EOK) {
990
        if (status != EOK) {
951
            /* could not allocate a chain of nclsts clusters */
991
            /* could not allocate a chain of nclsts clusters */
Line 957... Line 997...
957
        /* zero fill any gaps */
997
        /* zero fill any gaps */
958
        fat_fill_gap(nodep, mcl, pos);
998
        fat_fill_gap(nodep, mcl, pos);
959
        b = _fat_block_get(dev_handle, lcl, (pos / bps) % spc);
999
        b = _fat_block_get(dev_handle, lcl, (pos / bps) % spc);
960
        (void) ipc_data_write_finalize(callid, b->data + pos % bps,
1000
        (void) ipc_data_write_finalize(callid, b->data + pos % bps,
961
            bytes);
1001
            bytes);
962
        b->dirty = true;
1002
        b->dirty = true;        /* need to sync block */
963
        block_put(b);
1003
        block_put(b);
964
        /*
1004
        /*
965
         * Append the cluster chain starting in mcl to the end of the
1005
         * Append the cluster chain starting in mcl to the end of the
966
         * node's cluster chain.
1006
         * node's cluster chain.
967
         */
1007
         */
968
        fat_append_clusters(nodep, mcl);
1008
        fat_append_clusters(nodep, mcl);
969
        nodep->size = pos + bytes;
1009
        nodep->size = pos + bytes;
970
        nodep->dirty = true;
1010
        nodep->dirty = true;        /* need to sync node */
971
        fat_node_put(nodep);
1011
        fat_node_put(nodep);
972
        ipc_answer_1(rid, EOK, bytes);
1012
        ipc_answer_1(rid, EOK, bytes);
973
        return;
1013
        return;
974
    }
1014
    }
975
}
1015
}