Changeset 2988aec7 in mainline


Ignore:
Timestamp:
2012-08-14T03:17:17Z (12 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
71b0d4d4
Parents:
1b6b76d
Message:

Bithenge: read FAT files/subdirs; self-recursion and more operators

Location:
uspace
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/Makefile.linux

    r1b6b76d r2988aec7  
    5050
    5151$(BINARY): $(OBJECTS)
    52         $(CC) -o $@ $^
     52        $(CC) $(CFLAGS) -o $@ $^
    5353
    5454clean:
  • uspace/app/bithenge/blob.c

    r1b6b76d r2988aec7  
    459459}
    460460
     461typedef struct {
     462        bithenge_blob_t base;
     463        bithenge_blob_t *a, *b;
     464        aoff64_t a_size;
     465} concat_blob_t;
     466
     467static inline concat_blob_t *blob_as_concat(bithenge_blob_t *base)
     468{
     469        return (concat_blob_t *)base;
     470}
     471
     472static inline bithenge_blob_t *concat_as_blob(concat_blob_t *blob)
     473{
     474        return &blob->base;
     475}
     476
     477static int concat_blob_size(bithenge_blob_t *base, aoff64_t *size)
     478{
     479        concat_blob_t *self = blob_as_concat(base);
     480        int rc = bithenge_blob_size(self->b, size);
     481        *size += self->a_size;
     482        return rc;
     483}
     484
     485static int concat_blob_read(bithenge_blob_t *base, aoff64_t offset,
     486    char *buffer, aoff64_t *size)
     487{
     488        int rc = EOK;
     489        concat_blob_t *self = blob_as_concat(base);
     490
     491        aoff64_t a_size = 0, b_size = 0;
     492        if (offset < self->a_size) {
     493                a_size = *size;
     494                rc = bithenge_blob_read(self->a, offset, buffer, &a_size);
     495                if (rc != EOK)
     496                        return rc;
     497        }
     498        if (offset + *size > self->a_size) {
     499                b_size = *size - a_size;
     500                rc = bithenge_blob_read(self->b,
     501                    offset + a_size - self->a_size, buffer + a_size, &b_size);
     502                if (rc != EOK)
     503                        return rc;
     504        }
     505        assert(a_size + b_size <= *size);
     506        *size = a_size + b_size;
     507        return rc;
     508}
     509
     510static int concat_blob_read_bits(bithenge_blob_t *base, aoff64_t offset,
     511    char *buffer, aoff64_t *size, bool little_endian)
     512{
     513        int rc = EOK;
     514        concat_blob_t *self = blob_as_concat(base);
     515
     516        aoff64_t a_size = 0, b_size = 0;
     517        if (offset < self->a_size) {
     518                a_size = *size;
     519                rc = bithenge_blob_read_bits(self->a, offset, buffer, &a_size,
     520                    little_endian);
     521                if (rc != EOK)
     522                        return rc;
     523        }
     524        if (offset + *size > self->a_size) {
     525                b_size = offset + *size - self->a_size;
     526                rc = bithenge_blob_read_bits(self->b,
     527                    offset + a_size - self->a_size, buffer + a_size, &b_size,
     528                    little_endian);
     529                if (rc != EOK)
     530                        return rc;
     531        }
     532        *size = a_size + b_size;
     533        return rc;
     534}
     535
     536static void concat_blob_destroy(bithenge_blob_t *base)
     537{
     538        concat_blob_t *self = blob_as_concat(base);
     539        bithenge_blob_dec_ref(self->a);
     540        bithenge_blob_dec_ref(self->b);
     541        free(self);
     542}
     543
     544static const bithenge_random_access_blob_ops_t concat_blob_ops = {
     545        .size = concat_blob_size,
     546        .read = concat_blob_read,
     547        .read_bits = concat_blob_read_bits,
     548        .destroy = concat_blob_destroy,
     549};
     550
     551/** Create a concatenated blob. Takes references to @a a and @a b.
     552 * @param[out] out Holds the new blob.
     553 * @param a The first blob.
     554 * @param b The second blob.
     555 * @return EOK on success or an error code from errno.h. */
     556int bithenge_concat_blob(bithenge_node_t **out, bithenge_blob_t *a,
     557    bithenge_blob_t *b)
     558{
     559        assert(out);
     560        assert(a);
     561        assert(b);
     562        int rc;
     563        concat_blob_t *self = malloc(sizeof(*self));
     564        if (!self) {
     565                rc = ENOMEM;
     566                goto error;
     567        }
     568
     569        rc = bithenge_blob_size(a, &self->a_size);
     570        if (rc != EOK)
     571                goto error;
     572
     573        rc = bithenge_init_random_access_blob(concat_as_blob(self),
     574            &concat_blob_ops);
     575        if (rc != EOK)
     576                goto error;
     577        self->a = a;
     578        self->b = b;
     579        *out = bithenge_blob_as_node(concat_as_blob(self));
     580        return EOK;
     581
     582error:
     583        bithenge_blob_dec_ref(a);
     584        bithenge_blob_dec_ref(b);
     585        free(self);
     586        return rc;
     587}
     588
    461589/** Check whether the contents of two blobs are equal.
    462590 * @memberof bithenge_blob_t
  • uspace/app/bithenge/blob.h

    r1b6b76d r2988aec7  
    243243int bithenge_new_subblob(bithenge_node_t **, bithenge_blob_t *, aoff64_t,
    244244    aoff64_t);
     245int bithenge_concat_blob(bithenge_node_t **, bithenge_blob_t *,
     246    bithenge_blob_t *);
    245247bool bithenge_blob_equal(bithenge_blob_t *, bithenge_blob_t *);
    246248
  • uspace/app/bithenge/expression.c

    r1b6b76d r2988aec7  
    101101        /* Check types and get values. */
    102102        bithenge_int_t a_int = 0, b_int = 0;
     103        bool a_bool = false, b_bool = false;
    103104        switch (self->op) {
    104105        case BITHENGE_EXPRESSION_ADD: /* fallthrough */
     
    119120                b_int = bithenge_integer_node_value(b);
    120121                break;
     122        case BITHENGE_EXPRESSION_AND: /* fallthrough */
     123        case BITHENGE_EXPRESSION_OR:
     124                rc = EINVAL;
     125                if (bithenge_node_type(a) != BITHENGE_NODE_BOOLEAN)
     126                        goto error;
     127                if (bithenge_node_type(b) != BITHENGE_NODE_BOOLEAN)
     128                        goto error;
     129                a_bool = bithenge_boolean_node_value(a);
     130                b_bool = bithenge_boolean_node_value(b);
     131                break;
     132        case BITHENGE_EXPRESSION_CONCAT:
     133                if (bithenge_node_type(a) != BITHENGE_NODE_BLOB)
     134                        goto error;
     135                if (bithenge_node_type(b) != BITHENGE_NODE_BLOB)
     136                        goto error;
     137                break;
    121138        default:
    122139                break;
     
    135152        case BITHENGE_EXPRESSION_INTEGER_DIVIDE:
    136153                /* Integer division can behave in three major ways when the
    137                  * operands are signed: truncated, floored, or Euclidean. When
     154                  operands are signed: truncated, floored, or Euclidean. When
    138155                 * b > 0, we give the same result as floored and Euclidean;
    139156                 * otherwise, we currently raise an error. See
     
    173190        case BITHENGE_EXPRESSION_NOT_EQUALS:
    174191                rc = bithenge_new_boolean_node(out,
    175                     ~bithenge_node_equal(a, b));
     192                    !bithenge_node_equal(a, b));
     193                break;
     194        case BITHENGE_EXPRESSION_AND:
     195                rc = bithenge_new_boolean_node(out, a_bool && b_bool);
     196                break;
     197        case BITHENGE_EXPRESSION_OR:
     198                rc = bithenge_new_boolean_node(out, a_bool || b_bool);
     199                break;
     200        case BITHENGE_EXPRESSION_MEMBER:
     201                rc = bithenge_node_get(a, b, out);
     202                b = NULL;
     203                break;
     204        case BITHENGE_EXPRESSION_CONCAT:
     205                rc = bithenge_concat_blob(out, bithenge_node_as_blob(a),
     206                    bithenge_node_as_blob(b));
     207                a = NULL;
     208                b = NULL;
    176209                break;
    177210        case BITHENGE_EXPRESSION_INVALID_BINARY_OP:
     
    430463        free(self);
    431464        bithenge_node_dec_ref(node);
    432         return rc;
    433 }
    434 
    435 
    436 
    437 /***************** member_expression                         *****************/
    438 
    439 typedef struct {
    440         bithenge_expression_t base;
    441         bithenge_expression_t *expr;
    442         bithenge_node_t *key;
    443 } member_expression_t;
    444 
    445 static member_expression_t *expression_as_member(bithenge_expression_t *base)
    446 {
    447         return (member_expression_t *)base;
    448 }
    449 
    450 static bithenge_expression_t *member_as_expression(member_expression_t *expr)
    451 {
    452         return &expr->base;
    453 }
    454 
    455 static int member_expression_evaluate(bithenge_expression_t *base,
    456     bithenge_scope_t *scope, bithenge_node_t **out)
    457 {
    458         member_expression_t *self = expression_as_member(base);
    459         bithenge_node_t *node;
    460         int rc = bithenge_expression_evaluate(self->expr, scope, &node);
    461         if (rc != EOK)
    462                 return rc;
    463         bithenge_node_inc_ref(self->key);
    464         rc = bithenge_node_get(node, self->key, out);
    465         bithenge_node_dec_ref(node);
    466         if (rc == ENOENT)
    467                 return bithenge_scope_error(scope, "No member %t", self->key);
    468         return rc;
    469 }
    470 
    471 static void member_expression_destroy(bithenge_expression_t *base)
    472 {
    473         member_expression_t *self = expression_as_member(base);
    474         bithenge_expression_dec_ref(self->expr);
    475         bithenge_node_dec_ref(self->key);
    476         free(self);
    477 }
    478 
    479 static const bithenge_expression_ops_t member_expression_ops = {
    480         .evaluate = member_expression_evaluate,
    481         .destroy = member_expression_destroy,
    482 };
    483 
    484 /** Create an expression that gets a member from a node. Takes references to
    485  * @a expr and @a key.
    486  * @param[out] out Holds the new expression.
    487  * @param expr Calculates the node to get the member of.
    488  * @param key The member to get.
    489  * @return EOK on success or an error code from errno.h. */
    490 int bithenge_member_expression(bithenge_expression_t **out,
    491     bithenge_expression_t *expr, bithenge_node_t *key)
    492 {
    493         int rc;
    494         member_expression_t *self = malloc(sizeof(*self));
    495         if (!self) {
    496                 rc = ENOMEM;
    497                 goto error;
    498         }
    499 
    500         rc = bithenge_init_expression(member_as_expression(self),
    501             &member_expression_ops);
    502         if (rc != EOK)
    503                 goto error;
    504 
    505         self->expr = expr;
    506         self->key = key;
    507         *out = member_as_expression(self);
    508         return EOK;
    509 
    510 error:
    511         bithenge_expression_dec_ref(expr);
    512         bithenge_node_dec_ref(key);
    513         free(self);
    514465        return rc;
    515466}
  • uspace/app/bithenge/expression.h

    r1b6b76d r2988aec7  
    9393typedef enum {
    9494        BITHENGE_EXPRESSION_INVALID_BINARY_OP,
     95
    9596        BITHENGE_EXPRESSION_ADD,
    9697        BITHENGE_EXPRESSION_SUBTRACT,
     
    9899        BITHENGE_EXPRESSION_INTEGER_DIVIDE,
    99100        BITHENGE_EXPRESSION_MODULO,
     101
    100102        BITHENGE_EXPRESSION_LESS_THAN,
    101103        BITHENGE_EXPRESSION_GREATER_THAN,
     
    104106        BITHENGE_EXPRESSION_EQUALS,
    105107        BITHENGE_EXPRESSION_NOT_EQUALS,
     108
     109        BITHENGE_EXPRESSION_AND,
     110        BITHENGE_EXPRESSION_OR,
     111
     112        BITHENGE_EXPRESSION_MEMBER,
     113        BITHENGE_EXPRESSION_CONCAT,
    106114} bithenge_binary_op_t;
    107115
     
    114122int bithenge_param_expression(bithenge_expression_t **, int);
    115123int bithenge_const_expression(bithenge_expression_t **, bithenge_node_t *);
    116 int bithenge_member_expression(bithenge_expression_t **,
    117     bithenge_expression_t *, bithenge_node_t *);
    118124int bithenge_scope_member_expression(bithenge_expression_t **,
    119125    bithenge_node_t *);
  • uspace/app/bithenge/print.c

    r1b6b76d r2988aec7  
    181181        bithenge_blob_t *blob = bithenge_node_as_blob(node);
    182182        aoff64_t pos = 0;
    183         char buffer[1024];
     183        uint8_t buffer[1024];
    184184        aoff64_t size = sizeof(buffer);
    185185        int rc;
     
    187187            state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
    188188        do {
    189                 rc = bithenge_blob_read(blob, pos, buffer, &size);
     189                rc = bithenge_blob_read(blob, pos, (char *)buffer, &size);
    190190                if (rc != EOK)
    191191                        return rc;
    192192                for (aoff64_t i = 0; i < size; i++)
    193193                        state_printf(state, "\\x%02x",
    194                             (unsigned int)(uint8_t)buffer[i]);
     194                            (unsigned int)buffer[i]);
    195195                pos += size;
    196196        } while (size == sizeof(buffer));
  • uspace/app/bithenge/script.c

    r1b6b76d r2988aec7  
    5353 * other token uses one of these values: */
    5454typedef enum {
    55         TOKEN_EQUALS = -128,
    56         TOKEN_ERROR,
     55        TOKEN_ERROR = -128,
     56
     57        TOKEN_AND,
     58        TOKEN_CONCAT,
     59        TOKEN_EQUALS,
    5760        TOKEN_EOF,
    5861        TOKEN_GREATER_THAN_OR_EQUAL,
     
    6366        TOKEN_LESS_THAN_OR_EQUAL,
    6467        TOKEN_NOT_EQUAL,
     68        TOKEN_OR,
    6569
    6670        /* Keywords */
     
    308312                        state->buffer_pos++;
    309313                }
     314        } else if (ch == '&') {
     315                state->token = ch;
     316                state->buffer_pos++;
     317                if (state->buffer[state->buffer_pos] == '&') {
     318                        state->token = TOKEN_AND;
     319                        state->buffer_pos++;
     320                }
     321        } else if (ch == '|') {
     322                state->token = ch;
     323                state->buffer_pos++;
     324                if (state->buffer[state->buffer_pos] == '|') {
     325                        state->token = TOKEN_OR;
     326                        state->buffer_pos++;
     327                }
     328        } else if (ch == '+') {
     329                state->token = ch;
     330                state->buffer_pos++;
     331                if (state->buffer[state->buffer_pos] == '+') {
     332                        state->token = TOKEN_CONCAT;
     333                        state->buffer_pos++;
     334                }
    310335        } else {
    311336                state->token = ch;
     
    415440typedef enum {
    416441        PRECEDENCE_NONE,
     442        PRECEDENCE_AND,
    417443        PRECEDENCE_EQUALS,
    418444        PRECEDENCE_COMPARE,
     
    446472        case TOKEN_NOT_EQUAL:
    447473                return BITHENGE_EXPRESSION_NOT_EQUALS;
     474        case TOKEN_AND:
     475                return BITHENGE_EXPRESSION_AND;
     476        case TOKEN_OR:
     477                return BITHENGE_EXPRESSION_OR;
     478        case TOKEN_CONCAT:
     479                return BITHENGE_EXPRESSION_CONCAT;
    448480        default:
    449481                return BITHENGE_EXPRESSION_INVALID_BINARY_OP;
     
    455487        switch (op) {
    456488        case BITHENGE_EXPRESSION_ADD: /* fallthrough */
    457         case BITHENGE_EXPRESSION_SUBTRACT:
     489        case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
     490        case BITHENGE_EXPRESSION_CONCAT:
    458491                return PRECEDENCE_ADD;
    459492        case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */
     
    469502        case BITHENGE_EXPRESSION_NOT_EQUALS:
    470503                return PRECEDENCE_EQUALS;
     504        case BITHENGE_EXPRESSION_AND: /* fallthrough */
     505        case BITHENGE_EXPRESSION_OR:
     506                return PRECEDENCE_AND;
    471507        default:
    472508                assert(false);
     
    609645                        }
    610646
    611                         rc = bithenge_member_expression(&expr, expr, key);
     647                        bithenge_expression_t *key_expr;
     648                        rc = bithenge_const_expression(&key_expr, key);
     649                        if (rc != EOK) {
     650                                error_errno(state, rc);
     651                                bithenge_expression_dec_ref(expr);
     652                                return NULL;
     653                        }
     654
     655                        rc = bithenge_binary_expression(&expr,
     656                            BITHENGE_EXPRESSION_MEMBER, expr, key_expr);
    612657                        if (rc != EOK) {
    613658                                error_errno(state, rc);
     
    618663                        bithenge_expression_t *start = parse_expression(state);
    619664                        bool absolute_limit = false;
    620                         if (state->token == ',') {
    621                                 absolute_limit = false;
     665                        if (state->token == ',' || state->token == ':') {
     666                                absolute_limit = state->token == ':';
    622667                                next_token(state);
    623                         } else if (state->token == ':') {
    624                                 absolute_limit = true;
     668                                bithenge_expression_t *limit = NULL;
     669                                if (!(state->token == ']' && absolute_limit))
     670                                        limit = parse_expression(state);
     671                                expect(state, ']');
     672
     673                                if (state->error != EOK) {
     674                                        bithenge_expression_dec_ref(expr);
     675                                        bithenge_expression_dec_ref(start);
     676                                        bithenge_expression_dec_ref(limit);
     677                                        return NULL;
     678                                }
     679                                rc = bithenge_subblob_expression(&expr, expr, start,
     680                                    limit, absolute_limit);
     681                                if (rc != EOK) {
     682                                        error_errno(state, rc);
     683                                        return NULL;
     684                                }
     685                        } else if (state->token == ']') {
    625686                                next_token(state);
     687
     688                                if (state->error != EOK) {
     689                                        bithenge_expression_dec_ref(expr);
     690                                        bithenge_expression_dec_ref(start);
     691                                        return NULL;
     692                                }
     693                                rc = bithenge_binary_expression(&expr,
     694                                    BITHENGE_EXPRESSION_MEMBER, expr, start);
     695                                if (rc != EOK) {
     696                                        error_errno(state, rc);
     697                                        return NULL;
     698                                }
    626699                        } else {
    627                                 syntax_error(state, "expected ',' or ':'");
    628                         }
    629                         bithenge_expression_t *limit = NULL;
    630                         if (!(state->token == ']' && absolute_limit))
    631                                 limit = parse_expression(state);
    632                         expect(state, ']');
    633 
    634                         if (state->error != EOK) {
     700                                syntax_error(state, "expected ',', ':', or ']'");
    635701                                bithenge_expression_dec_ref(expr);
    636702                                bithenge_expression_dec_ref(start);
    637                                 bithenge_expression_dec_ref(limit);
    638                                 return NULL;
    639                         }
    640                         rc = bithenge_subblob_expression(&expr, expr, start,
    641                             limit, absolute_limit);
    642                         if (rc != EOK) {
    643                                 error_errno(state, rc);
    644703                                return NULL;
    645704                        }
     
    11731232        }
    11741233
     1234        bithenge_transform_t *barrier = NULL;
     1235        if (state->error == EOK) {
     1236                int rc = bithenge_new_barrier_transform(&barrier,
     1237                    state->num_params);
     1238                if (rc != EOK) {
     1239                        barrier = NULL;
     1240                        error_errno(state, rc);
     1241                }
     1242        }
     1243
     1244        add_named_transform(state, barrier, name);
     1245
    11751246        expect(state, '=');
    11761247        bithenge_transform_t *xform = parse_transform(state);
     
    11781249
    11791250        if (state->error == EOK) {
    1180                 int rc = bithenge_new_barrier_transform(&xform, xform,
    1181                     state->num_params);
    1182                 if (rc != EOK) {
    1183                         xform = NULL;
    1184                         error_errno(state, rc);
    1185                 }
    1186         }
    1187 
    1188         add_named_transform(state, xform, name);
     1251                int rc = bithenge_barrier_transform_set_subtransform(barrier,
     1252                    xform);
     1253                xform = NULL;
     1254                if (rc != EOK)
     1255                        error_errno(state, rc);
     1256        }
     1257
     1258        if (state->error != EOK)
     1259                bithenge_transform_dec_ref(xform);
    11891260
    11901261        for (int i = 0; i < state->num_params; i++)
  • uspace/app/bithenge/sequence.c

    r1b6b76d r2988aec7  
    619619/***************** bithenge_repeat_transform                 *****************/
    620620
     621/* TODO: ignore errors */
     622
    621623typedef struct {
    622624        bithenge_transform_t base;
  • uspace/app/bithenge/transform.c

    r1b6b76d r2988aec7  
    477477};
    478478
     479/** Set the subtransform of a barrier transform. This must be done before the
     480 * barrier transform is used. Takes a reference to @a transform.
     481 * @param base The barrier transform.
     482 * @param transform The subtransform to use for all operations.
     483 * @return EOK on success or an error code from errno.h. */
     484int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *base,
     485    bithenge_transform_t *transform)
     486{
     487        assert(transform);
     488        assert(bithenge_transform_num_params(transform) == 0);
     489
     490        barrier_transform_t *self = transform_as_barrier(base);
     491        assert(!self->transform);
     492        self->transform = transform;
     493        return EOK;
     494}
     495
    479496/** Create a wrapper transform that creates a new scope. This ensures nothing
    480497 * from the outer scope is passed in, other than parameters. The wrapper may
    481  * have a different value for num_params. Takes a reference to @a transform,
    482  * which it will use for all operations.
     498 * have a different value for num_params. The subtransform must be set with @a
     499 * bithenge_barrier_transform_set_subtransform before the result is used.
    483500 * @param[out] out Holds the created transform.
    484  * @param transform The transform to wrap.
    485501 * @param num_params The number of parameters to require, which may be 0.
    486502 * @return EOK on success or an error code from errno.h. */
    487 int bithenge_new_barrier_transform(bithenge_transform_t **out,
    488     bithenge_transform_t *transform, int num_params)
    489 {
    490         assert(transform);
    491         assert(bithenge_transform_num_params(transform) == 0);
    492 
     503int bithenge_new_barrier_transform(bithenge_transform_t **out, int num_params)
     504{
    493505        int rc;
    494506        barrier_transform_t *self = malloc(sizeof(*self));
     
    501513        if (rc != EOK)
    502514                goto error;
    503         self->transform = transform;
     515        self->transform = NULL;
    504516        *out = barrier_as_transform(self);
    505517        return EOK;
    506518error:
    507         bithenge_transform_dec_ref(transform);
    508519        free(self);
    509520        return rc;
  • uspace/app/bithenge/transform.h

    r1b6b76d r2988aec7  
    147147int bithenge_transform_prefix_apply(bithenge_transform_t *, bithenge_scope_t *,
    148148    bithenge_blob_t *, bithenge_node_t **, aoff64_t *);
    149 int bithenge_new_barrier_transform(bithenge_transform_t **,
    150     bithenge_transform_t *, int);
     149int bithenge_new_barrier_transform(bithenge_transform_t **, int);
     150int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *,
     151    bithenge_transform_t *);
    151152
    152153int bithenge_scope_new(bithenge_scope_t **, bithenge_scope_t *);
  • uspace/dist/src/bithenge/fat.bh

    r1b6b76d r2988aec7  
    4444} <- bits_le <- known_length(1);
    4545
    46 transform fat_dir_entry(disk) = struct {
     46transform file_data(data, bits, fat, cluster_size, start) = (in.data) <- struct {
     47        .cluster <- (data[(start-2)*cluster_size, cluster_size]);
     48        .last_cluster_number <- switch (bits) {
     49                12: (488);       # 0x00000ff8
     50                16: (65528);     # 0x0000fff8
     51                32: (268435448); # 0x0ffffff8
     52        };
     53        .next <- (fat[start]);
     54        if (.next == 0 || .next >= .last_cluster_number) {
     55                .data <- (.cluster);
     56        } else {
     57                .rest <- file_data(data, bits, fat, cluster_size, .next);
     58                .data <- (.cluster ++ .rest);
     59        }
     60};
     61
     62transform fat_dir_entry(data, bits, fat, cluster_size, self_start, parent) = struct {
    4763        .filename <- known_length(8);
    4864        .extension <- known_length(3);
     
    5874        .start <- u16;
    5975        .size <- u32;
     76        .size_shown <- if (.size > 32) { (32) } else { (.size) };
     77
     78        if (.start != 0 && .start != self_start && .start != parent) {
     79                .data
     80                    <- if (.attrs.subdirectory) {
     81                        repeat { fat_dir_entry(data, bits, fat, cluster_size, .start, self_start) }
     82                    } else {
     83                        (in[0,.size_shown])
     84                    }
     85                    <- if (.size != 0) { (in[0,.size]) } else { (in) }
     86                    <- file_data(data, bits, fat, cluster_size, .start);
     87        }
    6088};
    6189
     
    112140        };
    113141
     142        .cluster_size <- (.super.sectors_per_cluster * .super.bytes_per_sector);
    114143        .first_root_sector <- (.super.num_reserved_sectors + .super.num_fats * .super.sectors_per_fat);
    115144        .first_data_sector <- (.first_root_sector +
     
    128157
    129158        .root <- partial(.first_root_sector * .super.bytes_per_sector) {
    130                 repeat(.super.num_root_entries) { fat_dir_entry(disk) } } <- (disk);
     159                repeat(.super.num_root_entries) {
     160                        fat_dir_entry(disk[.first_data_sector * .super.bytes_per_sector:],
     161                            .bits, .fats[0], .cluster_size, 0, 0)
     162                }
     163        } <- (disk);
    131164};
    132165
Note: See TracChangeset for help on using the changeset viewer.