Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 8cc4ddb in mainline


Ignore:
Timestamp:
2011-08-28T21:16:54Z (10 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
0f0f8bc
Parents:
1a5b252 (diff), 36e2b55 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

Files:
21 added
46 edited
1 moved

Legend:

Unmodified
Added
Removed
  • abi/include/syscall.h

    r1a5b252 r8cc4ddb  
    8989        SYS_UNREGISTER_IRQ,
    9090       
    91         SYS_SYSINFO_GET_TAG,
     91        SYS_SYSINFO_GET_VAL_TYPE,
    9292        SYS_SYSINFO_GET_VALUE,
    9393        SYS_SYSINFO_GET_DATA_SIZE,
  • abi/include/sysinfo.h

    r1a5b252 r8cc4ddb  
    3737#define ABI_SYSINFO_H_
    3838
     39#include <abi/proc/task.h>
     40#include <abi/proc/thread.h>
     41
    3942/** Number of load components */
    4043#define LOAD_STEPS  3
     
    4447#define EXC_NAME_BUFLEN   20
    4548
    46 /** Thread states */
     49/** Item value type
     50 *
     51 */
    4752typedef enum {
    48         /** It is an error, if thread is found in this state. */
    49         Invalid,
    50         /** State of a thread that is currently executing on some CPU. */
    51         Running,
    52         /** Thread in this state is waiting for an event. */
    53         Sleeping,
    54         /** State of threads in a run queue. */
    55         Ready,
    56         /** Threads are in this state before they are first readied. */
    57         Entering,
    58         /** After a thread calls thread_exit(), it is put into Exiting state. */
    59         Exiting,
    60         /** Threads that were not detached but exited are Lingering. */
    61         Lingering
    62 } state_t;
     53        SYSINFO_VAL_UNDEFINED = 0,     /**< Undefined value */
     54        SYSINFO_VAL_VAL = 1,           /**< Constant numeric value */
     55        SYSINFO_VAL_DATA = 2,          /**< Constant binary data */
     56        SYSINFO_VAL_FUNCTION_VAL = 3,  /**< Generated numeric value */
     57        SYSINFO_VAL_FUNCTION_DATA = 4  /**< Generated binary data */
     58} sysinfo_item_val_type_t;
    6359
    6460/** Statistics about a single CPU
  • boot/Makefile.common

    r1a5b252 r8cc4ddb  
    102102        $(USPACE_PATH)/srv/fs/tmpfs/tmpfs \
    103103        $(USPACE_PATH)/srv/fs/fat/fat \
     104        $(USPACE_PATH)/srv/fs/exfat/exfat \
    104105        $(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
    105106        $(USPACE_PATH)/srv/taskmon/taskmon \
  • boot/generic/src/printf_core.c

    r1a5b252 r8cc4ddb  
    7070 */
    7171#define PRINT_NUMBER_BUFFER_SIZE  (64 + 5)
     72
     73/** Get signed or unsigned integer argument */
     74#define PRINTF_GET_INT_ARGUMENT(type, ap, flags) \
     75        ({ \
     76                unsigned type res; \
     77                \
     78                if ((flags) & __PRINTF_FLAG_SIGNED) { \
     79                        signed type arg = va_arg((ap), signed type); \
     80                        \
     81                        if (arg < 0) { \
     82                                res = -arg; \
     83                                (flags) |= __PRINTF_FLAG_NEGATIVE; \
     84                        } else \
     85                                res = arg; \
     86                } else \
     87                        res = va_arg((ap), unsigned type); \
     88                \
     89                res; \
     90        })
    7291
    7392/** Enumeration of possible arguments types.
     
    171190        }
    172191       
    173         return (int) (counter + 1);
     192        return (int) (counter);
    174193}
    175194
     
    698717                        size_t size;
    699718                        uint64_t number;
     719                       
    700720                        switch (qualifier) {
    701721                        case PrintfQualifierByte:
    702722                                size = sizeof(unsigned char);
    703                                 number = (uint64_t) va_arg(ap, unsigned int);
     723                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    704724                                break;
    705725                        case PrintfQualifierShort:
    706726                                size = sizeof(unsigned short);
    707                                 number = (uint64_t) va_arg(ap, unsigned int);
     727                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    708728                                break;
    709729                        case PrintfQualifierInt:
    710730                                size = sizeof(unsigned int);
    711                                 number = (uint64_t) va_arg(ap, unsigned int);
     731                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    712732                                break;
    713733                        case PrintfQualifierLong:
    714734                                size = sizeof(unsigned long);
    715                                 number = (uint64_t) va_arg(ap, unsigned long);
     735                                number = PRINTF_GET_INT_ARGUMENT(long, ap, flags);
    716736                                break;
    717737                        case PrintfQualifierLongLong:
    718738                                size = sizeof(unsigned long long);
    719                                 number = (uint64_t) va_arg(ap, unsigned long long);
     739                                number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags);
    720740                                break;
    721741                        case PrintfQualifierPointer:
     
    732752                                counter = -counter;
    733753                                goto out;
    734                         }
    735                        
    736                         if (flags & __PRINTF_FLAG_SIGNED) {
    737                                 if (number & (0x1 << (size * 8 - 1))) {
    738                                         flags |= __PRINTF_FLAG_NEGATIVE;
    739                                        
    740                                         if (size == sizeof(uint64_t)) {
    741                                                 number = -((int64_t) number);
    742                                         } else {
    743                                                 number = ~number;
    744                                                 number &=
    745                                                     ~(0xFFFFFFFFFFFFFFFFll <<
    746                                                     (size * 8));
    747                                                 number++;
    748                                         }
    749                                 }
    750754                        }
    751755                       
  • kernel/arch/amd64/include/asm.h

    r1a5b252 r8cc4ddb  
    4141#include <trace.h>
    4242
     43#define IO_SPACE_BOUNDARY       ((void *) (64 * 1024))
     44
    4345/** Return base address of current stack.
    4446 *
     
    7779}
    7880
    79 #define IO_SPACE_BOUNDARY       ((void *) (64 * 1024))
    80 
    8181/** Byte from port
    8282 *
     
    9191        if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
    9292                uint8_t val;
     93               
    9394                asm volatile (
    9495                        "inb %w[port], %b[val]\n"
     
    9697                        : [port] "d" (port)
    9798                );
     99               
    98100                return val;
    99         } else {
     101        } else
    100102                return (uint8_t) *port;
    101         }
    102103}
    103104
     
    114115        if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
    115116                uint16_t val;
     117               
    116118                asm volatile (
    117119                        "inw %w[port], %w[val]\n"
     
    119121                        : [port] "d" (port)
    120122                );
     123               
    121124                return val;
    122         } else {
     125        } else
    123126                return (uint16_t) *port;
    124         }
    125127}
    126128
     
    137139        if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
    138140                uint32_t val;
     141               
    139142                asm volatile (
    140143                        "inl %w[port], %[val]\n"
     
    142145                        : [port] "d" (port)
    143146                );
     147               
    144148                return val;
    145         } else {
     149        } else
    146150                return (uint32_t) *port;
    147         }
    148151}
    149152
     
    163166                        :: [val] "a" (val), [port] "d" (port)
    164167                );     
    165         } else {
     168        } else
    166169                *port = val;
    167         }
    168170}
    169171
     
    183185                        :: [val] "a" (val), [port] "d" (port)
    184186                );
    185         } else {
     187        } else
    186188                *port = val;
    187         }
    188189}
    189190
     
    203204                        :: [val] "a" (val), [port] "d" (port)
    204205                );
    205         } else {
     206        } else
    206207                *port = val;
    207         }
    208208}
    209209
  • kernel/arch/ia32/include/asm.h

    r1a5b252 r8cc4ddb  
    118118                        :: [val] "a" (val), [port] "d" (port)
    119119                );     
    120         } else {
     120        } else
    121121                *port = val;
    122         }
    123122}
    124123
     
    138137                        :: [val] "a" (val), [port] "d" (port)
    139138                );
    140         } else {
     139        } else
    141140                *port = val;
    142         }
    143141}
    144142
     
    158156                        :: [val] "a" (val), [port] "d" (port)
    159157                );
    160         } else {
     158        } else
    161159                *port = val;
    162         }
    163160}
    164161
     
    175172        if (((void *)port) < IO_SPACE_BOUNDARY) {
    176173                uint8_t val;
     174               
    177175                asm volatile (
    178176                        "inb %w[port], %b[val]\n"
     
    180178                        : [port] "d" (port)
    181179                );
     180               
    182181                return val;
    183         } else {
     182        } else
    184183                return (uint8_t) *port;
    185         }
    186184}
    187185
     
    198196        if (((void *)port) < IO_SPACE_BOUNDARY) {
    199197                uint16_t val;
     198               
    200199                asm volatile (
    201200                        "inw %w[port], %w[val]\n"
     
    203202                        : [port] "d" (port)
    204203                );
     204               
    205205                return val;
    206         } else {
     206        } else
    207207                return (uint16_t) *port;
    208         }
    209208}
    210209
     
    221220        if (((void *)port) < IO_SPACE_BOUNDARY) {
    222221                uint32_t val;
     222               
    223223                asm volatile (
    224224                        "inl %w[port], %[val]\n"
     
    226226                        : [port] "d" (port)
    227227                );
     228               
    228229                return val;
    229         } else {
     230        } else
    230231                return (uint32_t) *port;
    231         }
    232232}
    233233
  • kernel/generic/include/ipc/ipc.h

    r1a5b252 r8cc4ddb  
    3636#define KERN_IPC_H_
    3737
    38 #include <abi/ipc/ipc.h>
    3938#include <synch/spinlock.h>
    4039#include <synch/mutex.h>
    4140#include <synch/waitq.h>
     41#include <abi/ipc/ipc.h>
     42#include <abi/proc/task.h>
    4243#include <typedefs.h>
    4344
    44 #define IPC_MAX_PHONES  32
     45#define IPC_MAX_PHONES  64
    4546
    4647struct answerbox;
  • kernel/generic/include/sysinfo/sysinfo.h

    r1a5b252 r8cc4ddb  
    3838#include <typedefs.h>
    3939#include <str.h>
     40#include <abi/sysinfo.h>
    4041
    4142/** Framebuffer info exported flags */
    4243extern bool fb_exported;
    43 
    44 /** Item value type
    45  *
    46  */
    47 typedef enum {
    48         SYSINFO_VAL_UNDEFINED = 0,     /**< Undefined value */
    49         SYSINFO_VAL_VAL = 1,           /**< Constant numeric value */
    50         SYSINFO_VAL_DATA = 2,          /**< Constant binary data */
    51         SYSINFO_VAL_FUNCTION_VAL = 3,  /**< Generated numeric value */
    52         SYSINFO_VAL_FUNCTION_DATA = 4  /**< Generated binary data */
    53 } sysinfo_item_val_type_t;
    5444
    5545/** Subtree type
     
    145135extern void sysinfo_dump(sysinfo_item_t *);
    146136
    147 extern sysarg_t sys_sysinfo_get_tag(void *, size_t);
     137extern sysarg_t sys_sysinfo_get_val_type(void *, size_t);
    148138extern sysarg_t sys_sysinfo_get_value(void *, size_t, void *);
    149139extern sysarg_t sys_sysinfo_get_data_size(void *, size_t, void *);
  • kernel/generic/include/typedefs.h

    r1a5b252 r8cc4ddb  
    3939#include <arch/common.h>
    4040#include <arch/types.h>
     41#include <abi/bool.h>
    4142
    4243#define NULL  ((void *) 0)
     
    6162typedef void (* function)();
    6263
    63 typedef uint8_t bool;
    64 typedef uint64_t thread_id_t;
    65 typedef uint64_t task_id_t;
    6664typedef uint32_t container_id_t;
    6765
  • kernel/generic/src/mm/slab.c

    r1a5b252 r8cc4ddb  
    180180    unsigned int flags)
    181181{
    182        
    183        
    184182        size_t zone = 0;
    185183       
  • kernel/generic/src/printf/printf_core.c

    r1a5b252 r8cc4ddb  
    7575#define PRINT_NUMBER_BUFFER_SIZE  (64 + 5)
    7676
     77/** Get signed or unsigned integer argument */
     78#define PRINTF_GET_INT_ARGUMENT(type, ap, flags) \
     79        ({ \
     80                unsigned type res; \
     81                \
     82                if ((flags) & __PRINTF_FLAG_SIGNED) { \
     83                        signed type arg = va_arg((ap), signed type); \
     84                        \
     85                        if (arg < 0) { \
     86                                res = -arg; \
     87                                (flags) |= __PRINTF_FLAG_NEGATIVE; \
     88                        } else \
     89                                res = arg; \
     90                } else \
     91                        res = va_arg((ap), unsigned type); \
     92                \
     93                res; \
     94        })
     95
    7796/** Enumeration of possible arguments types.
    7897 */
     
    207226        }
    208227       
    209         return (int) (counter + 1);
     228        return (int) (counter);
    210229}
    211230
     
    245264        }
    246265       
    247         return (int) (counter + 1);
     266        return (int) (counter);
    248267}
    249268
     
    832851                        size_t size;
    833852                        uint64_t number;
     853                       
    834854                        switch (qualifier) {
    835855                        case PrintfQualifierByte:
    836856                                size = sizeof(unsigned char);
    837                                 number = (uint64_t) va_arg(ap, unsigned int);
     857                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    838858                                break;
    839859                        case PrintfQualifierShort:
    840860                                size = sizeof(unsigned short);
    841                                 number = (uint64_t) va_arg(ap, unsigned int);
     861                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    842862                                break;
    843863                        case PrintfQualifierInt:
    844864                                size = sizeof(unsigned int);
    845                                 number = (uint64_t) va_arg(ap, unsigned int);
     865                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    846866                                break;
    847867                        case PrintfQualifierLong:
    848868                                size = sizeof(unsigned long);
    849                                 number = (uint64_t) va_arg(ap, unsigned long);
     869                                number = PRINTF_GET_INT_ARGUMENT(long, ap, flags);
    850870                                break;
    851871                        case PrintfQualifierLongLong:
    852872                                size = sizeof(unsigned long long);
    853                                 number = (uint64_t) va_arg(ap, unsigned long long);
     873                                number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags);
    854874                                break;
    855875                        case PrintfQualifierPointer:
     
    866886                                counter = -counter;
    867887                                goto out;
    868                         }
    869                        
    870                         if (flags & __PRINTF_FLAG_SIGNED) {
    871                                 if (number & (0x1 << (size * 8 - 1))) {
    872                                         flags |= __PRINTF_FLAG_NEGATIVE;
    873                                        
    874                                         if (size == sizeof(uint64_t)) {
    875                                                 number = -((int64_t) number);
    876                                         } else {
    877                                                 number = ~number;
    878                                                 number &=
    879                                                     ~(0xFFFFFFFFFFFFFFFFll <<
    880                                                     (size * 8));
    881                                                 number++;
    882                                         }
    883                                 }
    884888                        }
    885889                       
  • kernel/generic/src/syscall/syscall.c

    r1a5b252 r8cc4ddb  
    181181       
    182182        /* Sysinfo syscalls. */
    183         (syshandler_t) sys_sysinfo_get_tag,
     183        (syshandler_t) sys_sysinfo_get_val_type,
    184184        (syshandler_t) sys_sysinfo_get_value,
    185185        (syshandler_t) sys_sysinfo_get_data_size,
  • kernel/generic/src/sysinfo/sysinfo.c

    r1a5b252 r8cc4ddb  
    661661 *
    662662 */
    663 sysarg_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
     663sysarg_t sys_sysinfo_get_val_type(void *path_ptr, size_t path_size)
    664664{
    665665        /*
  • kernel/test/print/print2.c

    r1a5b252 r8cc4ddb  
    4444        TPRINTF("Real output:     [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5);
    4545       
     46        TPRINTF("Testing printf(\"%%lld %%3.2lld %%-3.2lld %%2.3lld %%-2.3lld\", (long long) -1, (long long) -2, (long long) -3, (long long) -4, (long long) -5):\n");
     47        TPRINTF("Expected output: [-1] [-02] [-03] [-004] [-005]\n");
     48        TPRINTF("Real output:     [%lld] [%3.2lld] [%-3.2lld] [%2.3lld] [%-2.3lld]\n\n", (long long) -1, (long long) -2, (long long) -3, (long long) -4, (long long) -5);
     49       
    4650        TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n");
    4751        TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n");
  • uspace/Makefile

    r1a5b252 r8cc4ddb  
    7979        srv/bd/part/guid_part \
    8080        srv/bd/part/mbr_part \
     81        srv/fs/exfat \
    8182        srv/fs/fat \
    8283        srv/fs/tmpfs \
     
    163164        lib/block \
    164165        lib/clui \
     166        lib/fmtutil \
    165167        lib/scsi \
    166168        lib/softint \
  • uspace/Makefile.common

    r1a5b252 r8cc4ddb  
    108108LIBIMGMAP_PREFIX = $(LIB_PREFIX)/imgmap
    109109LIBCLUI_PREFIX = $(LIB_PREFIX)/clui
     110LIBFMTUTIL_PREFIX = $(LIB_PREFIX)/fmtutil
    110111
    111112LIBEXT2_PREFIX = $(LIB_PREFIX)/ext2
  • uspace/app/bdsh/Makefile

    r1a5b252 r8cc4ddb  
    2929
    3030USPACE_PREFIX = ../..
    31 LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBCLUI_PREFIX)/libclui.a
    32 EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBCLUI_PREFIX) -I. -Icmds/ \
    33         -Icmds/builtins -Icmds/modules
     31LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBCLUI_PREFIX)/libclui.a \
     32        $(LIBFMTUTIL_PREFIX)/libfmtutil.a
     33EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBCLUI_PREFIX) \
     34        -I$(LIBFMTUTIL_PREFIX) -I. -Icmds/ -Icmds/builtins -Icmds/modules
    3435BINARY = bdsh
    3536
  • uspace/app/bdsh/cmds/modules/help/help.c

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2008 Tim Post
     3 * Copyright (c) 2011 Martin Sucha
    34 * All rights reserved.
    45 *
     
    3031#include <stdlib.h>
    3132#include <str.h>
     33#include <fmtutil.h>
    3234
    3335#include "config.h"
     
    128130static void help_survival(void)
    129131{
    130         printf("Don't panic!\n\n");
    131 
    132         printf("This is Bdsh, the Brain dead shell, currently "
     132        print_wrapped_console(
     133            "Don't panic!\n\n"
     134
     135            "This is Bdsh, the Brain dead shell, currently "
    133136            "the primary user interface to HelenOS. Bdsh allows you to enter "
    134137            "commands and supports history (Up, Down arrow keys), "
    135138            "line editing (Left Arrow, Right Arrow, Home, End, Backspace), "
    136139            "selection (Shift + movement keys), copy and paste (Ctrl-C, "
    137             "Ctrl-V), similar to common desktop environments.\n\n");
    138 
    139         printf("The most basic filesystem commands are Bdsh builtins. Type "
     140            "Ctrl-V), similar to common desktop environments.\n\n"
     141
     142            "The most basic filesystem commands are Bdsh builtins. Type "
    140143            "'help commands' [Enter] to see the list of Bdsh builtin commands. "
    141144            "Other commands are external executables located in the /app and "
    142145            "/srv directories. Type 'ls /app' [Enter] and 'ls /srv' [Enter] "
    143146            "to see their list. You can execute an external command simply "
    144             "by entering its name (e.g. type 'tetris' [Enter]).\n\n");
    145 
    146         printf("HelenOS has virtual consoles (VCs). You can switch between "
    147             "these using the F1-F11 keys.\n\n");
    148 
    149         printf("This is but a small glimpse of what you can do with HelenOS. "
     147            "by entering its name (e.g. type 'tetris' [Enter]).\n\n"
     148
     149            "HelenOS has virtual consoles (VCs). You can switch between "
     150            "these using the F1-F11 keys.\n\n"
     151
     152            "This is but a small glimpse of what you can do with HelenOS. "
    150153            "To learn more please point your browser to the HelenOS User's "
    151             "Guide: http://trac.helenos.org/trac.fcgi/wiki/UsersGuide\n\n");
     154            "Guide: http://trac.helenos.org/wiki/UsersGuide\n\n",
     155            ALIGN_LEFT);
    152156}
    153157
  • uspace/app/bdsh/compl.c

    r1a5b252 r8cc4ddb  
    9090{
    9191        compl_t *cs = NULL;
    92         size_t pref_size;
    9392        char *stext = NULL;
    9493        char *prefix = NULL;
    9594        char *dirname = NULL;
     95        int retval;
     96       
     97        token_t *tokens = calloc(WORD_MAX, sizeof(token_t));
     98        if (tokens == NULL) {
     99                retval = ENOMEM;
     100                goto error;
     101        }
     102       
     103        size_t pref_size;
    96104        char *rpath_sep;
    97105        static const char *dirlist_arg[] = { ".", NULL };
    98         int retval;
    99106        tokenizer_t tok;
    100         token_t tokens[WORD_MAX];
    101         unsigned int current_token;
     107        ssize_t current_token;
    102108        size_t tokens_length;
    103 
     109       
    104110        cs = calloc(1, sizeof(compl_t));
    105111        if (!cs) {
     
    107113                goto error;
    108114        }
    109 
     115       
    110116        /* Convert text buffer to string */
    111117        stext = wstr_to_astr(text);
     
    127133       
    128134        /* Find the current token */
    129         for (current_token = 0; current_token < tokens_length; current_token++) {
     135        for (current_token = 0; current_token < (ssize_t) tokens_length;
     136            current_token++) {
    130137                token_t *t = &tokens[current_token];
    131138                size_t end = t->char_start + t->char_length;
    132                 /* Check if the caret lies inside the token or immediately
     139               
     140                /*
     141                 * Check if the caret lies inside the token or immediately
    133142                 * after it
    134143                 */
     
    138147        }
    139148       
    140         if (tokens[current_token].type != TOKTYPE_SPACE) {
     149        if (tokens_length == 0)
     150                current_token = -1;
     151       
     152        if ((current_token >= 0) && (tokens[current_token].type != TOKTYPE_SPACE))
    141153                *cstart = tokens[current_token].char_start;
    142         }
    143         else {
     154        else
    144155                *cstart = pos;
    145         }
    146        
    147         /* Extract the prefix being completed
     156       
     157        /*
     158         * Extract the prefix being completed
    148159         * XXX: handle strings, etc.
    149160         */
     
    154165                goto error;
    155166        }
    156 
    157         str_ncpy(prefix, pref_size + 1, stext +
    158             tokens[current_token].byte_start, pref_size);
     167        prefix[pref_size] = 0;
     168
     169        if (current_token >= 0) {
     170                str_ncpy(prefix, pref_size + 1, stext +
     171                    tokens[current_token].byte_start, pref_size);
     172        }
    159173
    160174        /*
     
    165179
    166180        /* Skip any whitespace before current token */
    167         int prev_token = current_token - 1;
    168         if (prev_token != -1 && tokens[prev_token].type == TOKTYPE_SPACE) {
     181        ssize_t prev_token = current_token - 1;
     182        if ((prev_token >= 0) && (tokens[prev_token].type == TOKTYPE_SPACE))
    169183                prev_token--;
    170         }
    171 
     184       
    172185        /*
    173186         * It is a command if it is the first token or if it immediately
    174187         * follows a pipe token.
    175188         */
    176         if (prev_token == -1 || tokens[prev_token].type == TOKTYPE_SPACE)
     189        if ((prev_token < 0) || (tokens[prev_token].type == TOKTYPE_SPACE))
    177190                cs->is_command = true;
    178191        else
     
    249262        if (cs != NULL)
    250263                free(cs);
     264        if (tokens != NULL)
     265                free(tokens);
    251266
    252267        return retval;
  • uspace/app/bdsh/input.c

    r1a5b252 r8cc4ddb  
    6767int process_input(cliuser_t *usr)
    6868{
     69        token_t *tokens = calloc(WORD_MAX, sizeof(token_t));
     70        if (tokens == NULL)
     71                return ENOMEM;
     72       
    6973        char *cmd[WORD_MAX];
    70         token_t tokens_space[WORD_MAX];
    71         token_t *tokens = tokens_space;
    7274        int rc = 0;
    7375        tokenizer_t tok;
     
    7779        char *redir_to = NULL;
    7880
    79         if (NULL == usr->line)
     81        if (usr->line == NULL) {
     82                free(tokens);
    8083                return CL_EFAIL;
     84        }
    8185
    8286        rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
     
    209213        }
    210214        tok_fini(&tok);
     215        free(tokens);
    211216
    212217        return rc;
  • uspace/app/mkfat/fat.h

    r1a5b252 r8cc4ddb  
    3838#define BS_BLOCK                0
    3939#define BS_SIZE                 512
     40#define DIRENT_SIZE             32
    4041
    41 #define DIRENT_SIZE             32
     42#define FAT12_CLST_MAX    4085
     43#define FAT16_CLST_MAX    65525
     44
     45#define FAT12   12
     46#define FAT16   16
     47#define FAT32   32
     48
     49#define FAT_CLUSTER_DOUBLE_SIZE(a) ((a) / 4)
    4250
    4351typedef struct fat_bs {
  • uspace/app/mkfat/mkfat.c

    r1a5b252 r8cc4ddb  
    3535 * @brief       Tool for creating new FAT file systems.
    3636 *
    37  * Currently we can only create 16-bit FAT.
     37 * Currently we can create 12/16/32-bit FAT.
    3838 */
    3939
     
    5555#define div_round_up(a, b) (((a) + (b) - 1) / (b))
    5656
    57 /** Predefined file-system parameters */
     57/** Default file-system parameters */
    5858enum {
    59         sector_size             = 512,
    60         sectors_per_cluster     = 8,
    61         fat_count               = 2,
    62         reserved_clusters       = 2,
    63         media_descriptor        = 0xF8 /**< fixed disk */
     59        default_sector_size             = 512,
     60        default_sectors_per_cluster     = 4,
     61        default_fat_count               = 2,
     62        default_reserved_clusters       = 2,
     63        default_media_descriptor        = 0xF8 /**< fixed disk */
    6464};
    6565
    6666/** Configurable file-system parameters */
    6767typedef struct fat_cfg {
     68        int fat_type; /* FAT12 = 12, FAT16 = 16, FAT32 = 32 */
     69        size_t sector_size;
    6870        uint32_t total_sectors;
    6971        uint16_t root_ent_max;
    70         uint16_t addt_res_sectors;
     72        uint32_t addt_res_sectors;
     73        uint8_t sectors_per_cluster;
     74
     75        uint16_t reserved_sectors;
     76        uint32_t rootdir_sectors;
     77        uint32_t fat_sectors;
     78        uint32_t total_clusters;
     79        uint8_t fat_count;
    7180} fat_cfg_t;
    7281
    73 /** Derived file-system parameters */
    74 typedef struct fat_params {
    75         struct fat_cfg cfg;
    76         uint16_t reserved_sectors;
    77         uint16_t rootdir_sectors;
    78         uint32_t fat_sectors;
    79         uint16_t total_clusters;
    80 } fat_params_t;
    81 
    8282static void syntax_print(void);
    8383
    84 static int fat_params_compute(struct fat_cfg const *cfg,
    85     struct fat_params *par);
    86 static int fat_blocks_write(struct fat_params const *par,
    87     service_id_t service_id);
    88 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs);
     84static int fat_params_compute(struct fat_cfg *cfg);
     85static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id);
     86static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs);
    8987
    9088int main(int argc, char **argv)
    9189{
    92         struct fat_params par;
    9390        struct fat_cfg cfg;
    9491
     
    9693        char *dev_path;
    9794        service_id_t service_id;
    98         size_t block_size;
    9995        char *endptr;
    10096        aoff64_t dev_nblocks;
    10197
     98        cfg.sector_size = default_sector_size;
     99        cfg.sectors_per_cluster = default_sectors_per_cluster;
     100        cfg.fat_count = default_fat_count;
    102101        cfg.total_sectors = 0;
    103102        cfg.addt_res_sectors = 0;
    104103        cfg.root_ent_max = 128;
     104        cfg.fat_type = FAT16;
    105105
    106106        if (argc < 2) {
     
    111111
    112112        --argc; ++argv;
    113 
    114113        if (str_cmp(*argv, "--size") == 0) {
    115114                --argc; ++argv;
     
    130129        }
    131130
     131        if (str_cmp(*argv, "--type") == 0) {
     132                --argc; ++argv;
     133                if (*argv == NULL) {
     134                        printf(NAME ": Error, argument missing.\n");
     135                        syntax_print();
     136                        return 1;
     137                }
     138
     139                cfg.fat_type = strtol(*argv, &endptr, 10);
     140                if (*endptr != '\0') {
     141                        printf(NAME ": Error, invalid argument.\n");
     142                        syntax_print();
     143                        return 1;
     144                }
     145
     146                --argc; ++argv;
     147        }
     148
    132149        if (argc != 1) {
    133150                printf(NAME ": Error, unexpected argument.\n");
     
    137154
    138155        dev_path = *argv;
     156        printf("Device: %s\n", dev_path);
    139157
    140158        rc = loc_service_get_id(dev_path, &service_id, 0);
     
    150168        }
    151169
    152         rc = block_get_bsize(service_id, &block_size);
     170        rc = block_get_bsize(service_id, &cfg.sector_size);
    153171        if (rc != EOK) {
    154172                printf(NAME ": Error determining device block size.\n");
     
    162180                printf(NAME ": Block device has %" PRIuOFF64 " blocks.\n",
    163181                    dev_nblocks);
    164                 cfg.total_sectors = dev_nblocks;
    165         }
    166 
    167         if (block_size != 512) {
    168                 printf(NAME ": Error. Device block size is not 512 bytes.\n");
    169                 return 2;
     182                if (!cfg.total_sectors || dev_nblocks < cfg.total_sectors)
     183                        cfg.total_sectors = dev_nblocks;
    170184        }
    171185
     
    175189        }
    176190
    177         printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
    178 
    179         rc = fat_params_compute(&cfg, &par);
     191        if (cfg.fat_type != FAT12 && cfg.fat_type != FAT16 && cfg.fat_type != FAT32) {
     192                printf(NAME ": Error. Unknown FAT type.\n");
     193                return 2;
     194        }
     195
     196        printf(NAME ": Creating FAT%d filesystem on device %s.\n", cfg.fat_type, dev_path);
     197
     198        rc = fat_params_compute(&cfg);
    180199        if (rc != EOK) {
    181200                printf(NAME ": Invalid file-system parameters.\n");
     
    183202        }
    184203
    185         rc = fat_blocks_write(&par, service_id);
     204        rc = fat_blocks_write(&cfg, service_id);
    186205        if (rc != EOK) {
    187206                printf(NAME ": Error writing device.\n");
     
    197216static void syntax_print(void)
    198217{
    199         printf("syntax: mkfat [--size <num_blocks>] <device_name>\n");
     218        printf("syntax: mkfat [--size <sectors>] [--type 12|16|32] <device_name>\n");
    200219}
    201220
     
    205224 * file system params.
    206225 */
    207 static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)
     226static int fat_params_compute(struct fat_cfg *cfg)
    208227{
    209228        uint32_t fat_bytes;
     
    211230
    212231        /*
    213          * Make a conservative guess on the FAT size needed for the file
    214          * system. The optimum could be potentially smaller since we
    215          * do not subtract size of the FAT itself when computing the
    216          * size of the data region.
    217          */
    218 
    219         par->reserved_sectors = 1 + cfg->addt_res_sectors;
    220         par->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
    221             sector_size);
    222         non_data_sectors_lb = par->reserved_sectors + par->rootdir_sectors;
    223 
    224         par->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
    225             sectors_per_cluster);
    226 
    227         fat_bytes = (par->total_clusters + 2) * 2;
    228         par->fat_sectors = div_round_up(fat_bytes, sector_size);
    229 
    230         par->cfg = *cfg;
     232         * Make a conservative guess on the FAT size needed for the file
     233         * system. The optimum could be potentially smaller since we
     234         * do not subtract size of the FAT itself when computing the
     235         * size of the data region.
     236         */
     237
     238        cfg->reserved_sectors = 1 + cfg->addt_res_sectors;
     239        if (cfg->fat_type != FAT32) {
     240                cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
     241                        cfg->sector_size);
     242        } else
     243                cfg->rootdir_sectors = 0;
     244        non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
     245
     246        cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
     247            cfg->sectors_per_cluster);
     248
     249        if ((cfg->fat_type == FAT12 && cfg->total_clusters > FAT12_CLST_MAX) ||
     250            (cfg->fat_type == FAT16 && (cfg->total_clusters <= FAT12_CLST_MAX ||
     251            cfg->total_clusters > FAT16_CLST_MAX)) ||
     252            (cfg->fat_type == FAT32 && cfg->total_clusters <= FAT16_CLST_MAX))
     253                return ENOSPC;
     254
     255        fat_bytes = div_round_up((cfg->total_clusters + 2) *
     256            FAT_CLUSTER_DOUBLE_SIZE(cfg->fat_type), 2);
     257        cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size);
    231258
    232259        return EOK;
     
    234261
    235262/** Create file system with the given parameters. */
    236 static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
     263static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id)
    237264{
    238265        aoff64_t addr;
     
    243270        struct fat_bs bs;
    244271
    245         fat_bootsec_create(par, &bs);
     272        fat_bootsec_create(cfg, &bs);
    246273
    247274        rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
     
    251278        addr = BS_BLOCK + 1;
    252279
    253         buffer = calloc(sector_size, 1);
     280        buffer = calloc(cfg->sector_size, 1);
    254281        if (buffer == NULL)
    255282                return ENOMEM;
     283        memset(buffer, 0, cfg->sector_size);
    256284
    257285        /* Reserved sectors */
    258         for (i = 0; i < par->reserved_sectors - 1; ++i) {
     286        for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
    259287                rc = block_write_direct(service_id, addr, 1, buffer);
    260288                if (rc != EOK)
     
    265293
    266294        /* File allocation tables */
    267         for (i = 0; i < fat_count; ++i) {
     295        for (i = 0; i < cfg->fat_count; ++i) {
    268296                printf("Writing allocation table %d.\n", i + 1);
    269297
    270                 for (j = 0; j < par->fat_sectors; ++j) {
    271                         memset(buffer, 0, sector_size);
     298                for (j = 0; j < cfg->fat_sectors; ++j) {
     299                        memset(buffer, 0, cfg->sector_size);
    272300                        if (j == 0) {
    273                                 buffer[0] = media_descriptor;
     301                                buffer[0] = default_media_descriptor;
    274302                                buffer[1] = 0xFF;
    275303                                buffer[2] = 0xFF;
    276                                 buffer[3] = 0xFF;
     304                                if (cfg->fat_type == FAT16) {
     305                                        buffer[3] = 0xFF;
     306                                } else if (cfg->fat_type == FAT32) {
     307                                        buffer[3] = 0x0F;
     308                                        buffer[4] = 0xFF;
     309                                        buffer[5] = 0xFF;
     310                                        buffer[6] = 0xFF;
     311                                        buffer[7] = 0x0F;
     312                                        buffer[8] = 0xF8;
     313                                        buffer[9] = 0xFF;
     314                                        buffer[10] = 0xFF;
     315                                        buffer[11] = 0x0F;
     316                                }
    277317                        }
    278318
     
    285325        }
    286326
     327        /* Root directory */
    287328        printf("Writing root directory.\n");
    288 
    289         memset(buffer, 0, sector_size);
    290 
    291         /* Root directory */
    292         for (i = 0; i < par->rootdir_sectors; ++i) {
    293                 rc = block_write_direct(service_id, addr, 1, buffer);
    294                 if (rc != EOK)
    295                         return EIO;
    296 
    297                 ++addr;
     329        memset(buffer, 0, cfg->sector_size);
     330        if (cfg->fat_type != FAT32) {
     331                size_t idx;
     332                for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
     333                        rc = block_write_direct(service_id, addr, 1, buffer);
     334                        if (rc != EOK)
     335                                return EIO;
     336
     337                        ++addr;
     338                }
     339        } else {
     340                for (i = 0; i < cfg->sectors_per_cluster; i++) {
     341                        rc = block_write_direct(service_id, addr, 1, buffer);
     342                        if (rc != EOK)
     343                                return EIO;
     344
     345                        ++addr;
     346                }       
    298347        }
    299348
     
    304353
    305354/** Construct boot sector with the given parameters. */
    306 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs)
     355static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
    307356{
    308357        memset(bs, 0, sizeof(*bs));
     
    315364
    316365        /* BIOS Parameter Block */
    317         bs->bps = host2uint16_t_le(sector_size);
    318         bs->spc = sectors_per_cluster;
    319         bs->rscnt = host2uint16_t_le(par->reserved_sectors);
    320         bs->fatcnt = fat_count;
    321         bs->root_ent_max = host2uint16_t_le(par->cfg.root_ent_max);
    322 
    323         if (par->cfg.total_sectors < 0x10000)
    324                 bs->totsec16 = host2uint16_t_le(par->cfg.total_sectors);
    325         else
    326                 bs->totsec16 = host2uint16_t_le(0);
    327 
    328         bs->mdesc = media_descriptor;
    329         bs->sec_per_fat = host2uint16_t_le(par->fat_sectors);
     366        bs->bps = host2uint16_t_le(cfg->sector_size);
     367        bs->spc = cfg->sectors_per_cluster;
     368        bs->rscnt = host2uint16_t_le(cfg->reserved_sectors);
     369        bs->fatcnt = cfg->fat_count;
     370        bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max);
     371
     372        if (cfg->total_sectors < 0x10000) {
     373                bs->totsec16 = host2uint16_t_le(cfg->total_sectors);
     374                bs->totsec32 = 0;
     375        } else {
     376                bs->totsec16 = 0;
     377                bs->totsec32 = host2uint32_t_le(cfg->total_sectors);
     378        }
     379
     380        bs->mdesc = default_media_descriptor;
    330381        bs->sec_per_track = host2uint16_t_le(63);
     382        bs->signature = host2uint16_t_be(0x55AA);
    331383        bs->headcnt = host2uint16_t_le(6);
    332384        bs->hidden_sec = host2uint32_t_le(0);
    333385
    334         if (par->cfg.total_sectors >= 0x10000)
    335                 bs->totsec32 = host2uint32_t_le(par->cfg.total_sectors);
    336         else
    337                 bs->totsec32 = host2uint32_t_le(0);
    338 
    339         /* Extended BPB */
    340         bs->pdn = 0x80;
    341         bs->ebs = 0x29;
    342         bs->id = host2uint32_t_be(0x12345678);
    343 
    344         memcpy(bs->label, "HELENOS_NEW", 11);
    345         memcpy(bs->type, "FAT16   ", 8);
    346         bs->signature = host2uint16_t_be(0x55AA);
     386        if (cfg->fat_type == FAT32) {
     387                bs->sec_per_fat = 0;
     388                bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors);
     389
     390                bs->fat32.pdn = 0x80;
     391                bs->fat32.ebs = 0x29;
     392                bs->fat32.id = host2uint32_t_be(0x12345678);
     393                bs->fat32.root_cluster = 2;
     394
     395                memcpy(bs->fat32.label, "HELENOS_NEW", 11);
     396                memcpy(bs->fat32.type, "FAT32   ", 8);
     397        } else {
     398                bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors);
     399                bs->pdn = 0x80;
     400                bs->ebs = 0x29;
     401                bs->id = host2uint32_t_be(0x12345678);
     402
     403                memcpy(bs->label, "HELENOS_NEW", 11);
     404                memcpy(bs->type, "FAT   ", 8);
     405        }
    347406}
    348407
  • uspace/app/sysinfo/sysinfo.c

    r1a5b252 r8cc4ddb  
    5151        int rc;
    5252        char *ipath;
    53         sysinfo_item_tag_t tag;
     53        sysinfo_item_val_type_t tag;
    5454
    5555        if (argc != 2) {
     
    6060        ipath = argv[1];
    6161
    62         tag = sysinfo_get_tag(ipath);
     62        tag = sysinfo_get_val_type(ipath);
    6363
    6464        /* Silence warning */
     
    7575        case SYSINFO_VAL_DATA:
    7676                rc = print_item_data(ipath);
     77                break;
     78        default:
     79                printf("Error: Sysinfo item '%s' with unknown value type.\n",
     80                    ipath);
     81                rc = 2;
    7782                break;
    7883        }
  • uspace/app/tester/print/print2.c

    r1a5b252 r8cc4ddb  
    4545        TPRINTF("Real output:     [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5);
    4646       
     47        TPRINTF("Testing printf(\"%%lld %%3.2lld %%-3.2lld %%2.3lld %%-2.3lld\", (long long) -1, (long long) -2, (long long) -3, (long long) -4, (long long) -5):\n");
     48        TPRINTF("Expected output: [-1] [-02] [-03] [-004] [-005]\n");
     49        TPRINTF("Real output:     [%lld] [%3.2lld] [%-3.2lld] [%2.3lld] [%-2.3lld]\n\n", (long long) -1, (long long) -2, (long long) -3, (long long) -4, (long long) -5);
     50       
    4751        TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n");
    4852        TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n");
  • uspace/app/tester/stdio/stdio1.c

    r1a5b252 r8cc4ddb  
    3939{
    4040        FILE *file;
    41         const char *file_name = "/readme";
     41        const char *file_name = "/textdemo";
    4242       
    4343        TPRINTF("Open file \"%s\"...", file_name);
  • uspace/app/trace/syscalls.c

    r1a5b252 r8cc4ddb  
    7575    [SYS_UNREGISTER_IRQ] = { "unregister_irq",  2,      V_ERRNO },
    7676
    77     [SYS_SYSINFO_GET_TAG] = { "sysinfo_get_tag",                2,      V_INTEGER },
     77    [SYS_SYSINFO_GET_VAL_TYPE] = { "sysinfo_get_val_type",              2,      V_INTEGER },
    7878    [SYS_SYSINFO_GET_VALUE] = { "sysinfo_get_value",            3,      V_ERRNO },
    7979    [SYS_SYSINFO_GET_DATA_SIZE] = { "sysinfo_get_data_size",    3,      V_ERRNO },
  • uspace/dist/src/sysel/demos/htxtfile.sy

    r1a5b252 r8cc4ddb  
    3535                var out_file : TextFile;
    3636
    37                 name = "/readme";
     37                name = "/textdemo";
    3838
    3939                in_file = new TextFile();
  • uspace/lib/c/arch/ia32/include/ddi.h

    r1a5b252 r8cc4ddb  
    4343        if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
    4444                uint8_t val;
     45               
    4546                asm volatile (
    4647                        "inb %w[port], %b[val]\n"
     
    4849                        : [port] "d" (port)
    4950                );
     51               
    5052                return val;
    51         } else {
     53        } else
    5254                return (uint8_t) *port;
    53         }
    5455}
    5556
     
    5859        if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
    5960                uint16_t val;
     61               
    6062                asm volatile (
    6163                        "inw %w[port], %w[val]\n"
     
    6365                        : [port] "d" (port)
    6466                );
     67               
    6568                return val;
    66         } else {
     69        } else
    6770                return (uint16_t) *port;
    68         }
    6971}
    7072
     
    7375        if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
    7476                uint32_t val;
     77               
    7578                asm volatile (
    7679                        "inl %w[port], %[val]\n"
     
    7881                        : [port] "d" (port)
    7982                );
     83               
    8084                return val;
    81         } else {
     85        } else
    8286                return (uint32_t) *port;
    83         }
    8487}
    8588
     
    9194                        :: [val] "a" (val), [port] "d" (port)
    9295                );     
    93         } else {
     96        } else
    9497                *port = val;
    95         }
    9698}
    9799
     
    103105                        :: [val] "a" (val), [port] "d" (port)
    104106                );
    105         } else {
     107        } else
    106108                *port = val;
    107         }
    108109}
    109110
     
    115116                        :: [val] "a" (val), [port] "d" (port)
    116117                );
    117         } else {
     118        } else
    118119                *port = val;
    119         }
    120120}
    121121
  • uspace/lib/c/generic/async.c

    r1a5b252 r8cc4ddb  
    17771777int async_hangup(async_sess_t *sess)
    17781778{
     1779        async_exch_t *exch;
     1780       
    17791781        assert(sess);
    17801782       
    17811783        if (atomic_get(&sess->refcnt) > 0)
    17821784                return EBUSY;
     1785       
     1786        fibril_mutex_lock(&async_sess_mutex);
    17831787       
    17841788        int rc = async_hangup_internal(sess->phone);
    17851789        if (rc == EOK)
    17861790                free(sess);
     1791       
     1792        while (!list_empty(&sess->exch_list)) {
     1793                exch = (async_exch_t *)
     1794                    list_get_instance(list_first(&sess->exch_list),
     1795                    async_exch_t, sess_link);
     1796               
     1797                list_remove(&exch->sess_link);
     1798                list_remove(&exch->global_link);
     1799                async_hangup_internal(exch->phone);
     1800                free(exch);
     1801        }
     1802       
     1803        fibril_mutex_unlock(&async_sess_mutex);
    17871804       
    17881805        return rc;
  • uspace/lib/c/generic/io/printf_core.c

    r1a5b252 r8cc4ddb  
    7373 */
    7474#define PRINT_NUMBER_BUFFER_SIZE  (64 + 5)
     75
     76/** Get signed or unsigned integer argument */
     77#define PRINTF_GET_INT_ARGUMENT(type, ap, flags) \
     78        ({ \
     79                unsigned type res; \
     80                \
     81                if ((flags) & __PRINTF_FLAG_SIGNED) { \
     82                        signed type arg = va_arg((ap), signed type); \
     83                        \
     84                        if (arg < 0) { \
     85                                res = -arg; \
     86                                (flags) |= __PRINTF_FLAG_NEGATIVE; \
     87                        } else \
     88                                res = arg; \
     89                } else \
     90                        res = va_arg((ap), unsigned type); \
     91                \
     92                res; \
     93        })
    7594
    7695/** Enumeration of possible arguments types.
     
    831850                        size_t size;
    832851                        uint64_t number;
     852                       
    833853                        switch (qualifier) {
    834854                        case PrintfQualifierByte:
    835855                                size = sizeof(unsigned char);
    836                                 number = (uint64_t) va_arg(ap, unsigned int);
     856                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    837857                                break;
    838858                        case PrintfQualifierShort:
    839859                                size = sizeof(unsigned short);
    840                                 number = (uint64_t) va_arg(ap, unsigned int);
     860                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    841861                                break;
    842862                        case PrintfQualifierInt:
    843863                                size = sizeof(unsigned int);
    844                                 number = (uint64_t) va_arg(ap, unsigned int);
     864                                number = PRINTF_GET_INT_ARGUMENT(int, ap, flags);
    845865                                break;
    846866                        case PrintfQualifierLong:
    847867                                size = sizeof(unsigned long);
    848                                 number = (uint64_t) va_arg(ap, unsigned long);
     868                                number = PRINTF_GET_INT_ARGUMENT(long, ap, flags);
    849869                                break;
    850870                        case PrintfQualifierLongLong:
    851871                                size = sizeof(unsigned long long);
    852                                 number = (uint64_t) va_arg(ap, unsigned long long);
     872                                number = PRINTF_GET_INT_ARGUMENT(long long, ap, flags);
    853873                                break;
    854874                        case PrintfQualifierPointer:
     
    865885                                counter = -counter;
    866886                                goto out;
    867                         }
    868                        
    869                         if (flags & __PRINTF_FLAG_SIGNED) {
    870                                 if (number & (0x1 << (size * 8 - 1))) {
    871                                         flags |= __PRINTF_FLAG_NEGATIVE;
    872                                        
    873                                         if (size == sizeof(uint64_t)) {
    874                                                 number = -((int64_t) number);
    875                                         } else {
    876                                                 number = ~number;
    877                                                 number &=
    878                                                     ~(0xFFFFFFFFFFFFFFFFll <<
    879                                                     (size * 8));
    880                                                 number++;
    881                                         }
    882                                 }
    883887                        }
    884888                       
  • uspace/lib/c/generic/str.c

    r1a5b252 r8cc4ddb  
    22 * Copyright (c) 2005 Martin Decky
    33 * Copyright (c) 2008 Jiri Svoboda
     4 * Copyright (c) 2011 Martin Sucha
     5 * Copyright (c) 2011 Oleg Romanenko
    46 * All rights reserved.
    57 *
     
    639641}
    640642
     643/** Convert UTF16 string to string.
     644 *
     645 * Convert utf16 string @a src to string. The output is written to the buffer
     646 * specified by @a dest and @a size. @a size must be non-zero and the string
     647 * written will always be well-formed. Surrogate pairs also supported.
     648 *
     649 * @param dest  Destination buffer.
     650 * @param size  Size of the destination buffer.
     651 * @param src   Source utf16 string.
     652 *
     653 * @return EOK, if success, negative otherwise.
     654 */
     655int utf16_to_str(char *dest, size_t size, const uint16_t *src)
     656{
     657        size_t idx = 0, dest_off = 0;
     658        wchar_t ch;
     659        int rc = EOK;
     660
     661        /* There must be space for a null terminator in the buffer. */
     662        assert(size > 0);
     663
     664        while (src[idx]) {
     665                if ((src[idx] & 0xfc00) == 0xd800) {
     666                        if (src[idx + 1] && (src[idx + 1] & 0xfc00) == 0xdc00) {
     667                                ch = 0x10000;
     668                                ch += (src[idx] & 0x03FF) << 10;
     669                                ch += (src[idx + 1] & 0x03FF);
     670                                idx += 2;
     671                        }
     672                        else
     673                                break;
     674                } else {
     675                        ch = src[idx];
     676                        idx++;
     677                }
     678                rc = chr_encode(ch, dest, &dest_off, size - 1);
     679                if (rc != EOK)
     680                        break;
     681        }
     682        dest[dest_off] = '\0';
     683        return rc;
     684}
     685
     686int str_to_utf16(uint16_t *dest, size_t size, const char *src)
     687{
     688        int rc = EOK;
     689        size_t offset = 0;
     690        size_t idx = 0;
     691        wchar_t c;
     692
     693        assert(size > 0);
     694       
     695        while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) {
     696                if (c > 0x10000) {
     697                        if (idx + 2 >= size - 1) {
     698                                rc = EOVERFLOW;
     699                                break;
     700                        }
     701                        c = (c - 0x10000);
     702                        dest[idx] = 0xD800 | (c >> 10);
     703                        dest[idx + 1] = 0xDC00 | (c & 0x3FF);
     704                        idx++;
     705                } else {
     706                         dest[idx] = c;
     707                }
     708
     709                idx++;
     710                if (idx >= size - 1) {
     711                        rc = EOVERFLOW;
     712                        break;
     713                }
     714        }
     715
     716        dest[idx] = '\0';
     717        return rc;
     718}
     719
     720
    641721/** Convert wide string to new string.
    642722 *
     
    718798
    719799        dest[dlen - 1] = '\0';
     800}
     801
     802/** Convert string to wide string.
     803 *
     804 * Convert string @a src to wide string. A new wide NULL-terminated
     805 * string will be allocated on the heap.
     806 *
     807 * @param src   Source string.
     808 */
     809wchar_t *str_to_awstr(const char *str)
     810{
     811        size_t len = str_length(str);
     812       
     813        wchar_t *wstr = calloc(len+1, sizeof(wchar_t));
     814        if (wstr == NULL)
     815                return NULL;
     816       
     817        str_to_wstr(wstr, len + 1, str);
     818        return wstr;
    720819}
    721820
     
    10161115        return dest;
    10171116}
    1018 
    10191117
    10201118/** Convert initial part of string to unsigned long according to given base.
  • uspace/lib/c/generic/sysinfo.c

    r1a5b252 r8cc4ddb  
    4747 *
    4848 */
    49 sysinfo_item_tag_t sysinfo_get_tag(const char *path)
     49sysinfo_item_val_type_t sysinfo_get_val_type(const char *path)
    5050{
    51         return (sysinfo_item_tag_t) __SYSCALL2(SYS_SYSINFO_GET_TAG,
     51        return (sysinfo_item_val_type_t) __SYSCALL2(SYS_SYSINFO_GET_VAL_TYPE,
    5252            (sysarg_t) path, (sysarg_t) str_size(path));
    5353}
  • uspace/lib/c/include/bool.h

    r1a5b252 r8cc4ddb  
    3737
    3838#include <libarch/types.h>
     39#include <abi/bool.h>
    3940
    4041#define false  0
    4142#define true   1
    42 
    43 typedef uint8_t bool;
    4443
    4544#endif
  • uspace/lib/c/include/str.h

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2005 Martin Decky
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    8384extern char *wstr_to_astr(const wchar_t *src);
    8485extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
     86extern wchar_t *str_to_awstr(const char *src);
     87extern int utf16_to_str(char *dest, size_t size, const uint16_t *src);
     88extern int str_to_utf16(uint16_t *dest, size_t size, const char *src);
    8589
    8690extern char *str_chr(const char *str, wchar_t ch);
  • uspace/lib/c/include/sysinfo.h

    r1a5b252 r8cc4ddb  
    3636#define LIBC_SYSINFO_H_
    3737
    38 #include <libc.h>
     38#include <sys/types.h>
     39#include <bool.h>
     40#include <abi/sysinfo.h>
    3941
    40 /** Sysinfo value types
    41  *
    42  */
    43 typedef enum {
    44         SYSINFO_VAL_UNDEFINED = 0,
    45         SYSINFO_VAL_VAL = 1,
    46         SYSINFO_VAL_DATA = 2
    47 } sysinfo_item_tag_t;
    48 
    49 extern sysinfo_item_tag_t sysinfo_get_tag(const char *);
     42extern sysinfo_item_val_type_t sysinfo_get_val_type(const char *);
    5043extern int sysinfo_get_value(const char *, sysarg_t *);
    5144extern void *sysinfo_get_data(const char *, size_t *);
  • uspace/lib/c/include/task.h

    r1a5b252 r8cc4ddb  
    3737
    3838#include <sys/types.h>
    39 
    40 typedef uint64_t task_id_t;
     39#include <abi/proc/task.h>
    4140
    4241typedef enum {
  • uspace/lib/c/include/thread.h

    r1a5b252 r8cc4ddb  
    3838#include <libarch/thread.h>
    3939#include <sys/types.h>
    40 
    41 typedef uint64_t thread_id_t;
     40#include <abi/proc/thread.h>
    4241
    4342extern int thread_create(void (*)(void *), void *, const char *, thread_id_t *);
  • uspace/srv/fs/fat/Makefile

    r1a5b252 r8cc4ddb  
    3939        fat_idx.c \
    4040        fat_dentry.c \
     41        fat_directory.c \
    4142        fat_fat.c
    4243
  • uspace/srv/fs/fat/fat.c

    r1a5b252 r8cc4ddb  
    22 * Copyright (c) 2006 Martin Decky
    33 * Copyright (c) 2008 Jakub Jermar
     4 * Copyright (c) 2011 Oleg Romanenko
    45 * All rights reserved.
    56 *
  • uspace/srv/fs/fat/fat.h

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    4647#endif
    4748
    48 #define min(a, b)               ((a) < (b) ? (a) : (b))
     49#define min(a, b)       ((a) < (b) ? (a) : (b))
    4950
    5051/*
     
    5556#define RSCNT(bs)       uint16_t_le2host((bs)->rscnt)
    5657#define FATCNT(bs)      (bs)->fatcnt
    57 #define SF(bs)          uint16_t_le2host((bs)->sec_per_fat)
     58
     59#define SF(bs)          (uint16_t_le2host((bs)->sec_per_fat) ? \
     60    uint16_t_le2host((bs)->sec_per_fat) : \
     61    uint32_t_le2host(bs->fat32.sectors_per_fat))
     62
    5863#define RDE(bs)         uint16_t_le2host((bs)->root_ent_max)
    59 #define TS(bs)          (uint16_t_le2host((bs)->totsec16) != 0 ? \
    60                         uint16_t_le2host((bs)->totsec16) : \
    61                         uint32_t_le2host(bs->totsec32))
    62 
    63 #define BS_BLOCK                0
    64 #define BS_SIZE                 512
     64
     65#define TS(bs)          (uint16_t_le2host((bs)->totsec16) ? \
     66    uint16_t_le2host((bs)->totsec16) : \
     67    uint32_t_le2host(bs->totsec32))
     68
     69#define BS_BLOCK        0
     70#define BS_SIZE         512
    6571
    6672typedef struct fat_bs {
  • uspace/srv/fs/fat/fat_dentry.c

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3940#include <ctype.h>
    4041#include <str.h>
    41 
    42 static bool is_d_char(const char ch)
    43 {
    44         if (isalnum(ch) || ch == '_')
    45                 return true;
    46         else
    47                 return false;
    48 }
     42#include <errno.h>
     43#include <byteorder.h>
     44#include <assert.h>
    4945
    5046/** Compare path component with the name read from the dentry.
     
    8076}
    8177
    82 bool fat_dentry_name_verify(const char *name)
     78void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
     79{
     80        unsigned int i;
     81       
     82        for (i = 0; i < FAT_NAME_LEN; i++) {
     83                if (d->name[i] == FAT_PAD)
     84                        break;
     85               
     86                if (d->name[i] == FAT_DENTRY_E5_ESC)
     87                        *buf++ = 0xe5;
     88                else {
     89                        if (d->lcase & FAT_LCASE_LOWER_NAME)
     90                                *buf++ = tolower(d->name[i]);
     91                        else
     92                                *buf++ = d->name[i];
     93                }
     94        }
     95       
     96        if (d->ext[0] != FAT_PAD)
     97                *buf++ = '.';
     98       
     99        for (i = 0; i < FAT_EXT_LEN; i++) {
     100                if (d->ext[i] == FAT_PAD) {
     101                        *buf = '\0';
     102                        return;
     103                }
     104               
     105                if (d->ext[i] == FAT_DENTRY_E5_ESC)
     106                        *buf++ = 0xe5;
     107                else {
     108                        if (d->lcase & FAT_LCASE_LOWER_EXT)
     109                                *buf++ = tolower(d->ext[i]);
     110                        else
     111                                *buf++ = d->ext[i];
     112                }
     113        }
     114       
     115        *buf = '\0';
     116}
     117
     118void fat_dentry_name_set(fat_dentry_t *d, const char *name)
     119{
     120        unsigned int i;
     121        const char fake_ext[] = "   ";
     122        bool lower_name = true;
     123        bool lower_ext = true;
     124       
     125        for (i = 0; i < FAT_NAME_LEN; i++) {
     126                switch ((uint8_t) *name) {
     127                case 0xe5:
     128                        d->name[i] = FAT_DENTRY_E5_ESC;
     129                        name++;
     130                        break;
     131                case '\0':
     132                case '.':
     133                        d->name[i] = FAT_PAD;
     134                        break;
     135                default:
     136                        if (isalpha(*name)) {
     137                                if (!islower(*name))
     138                                        lower_name = false;
     139                        }
     140                       
     141                        d->name[i] = toupper(*name++);
     142                        break;
     143                }
     144        }
     145       
     146        if (*name++ != '.')
     147                name = fake_ext;
     148       
     149        for (i = 0; i < FAT_EXT_LEN; i++) {
     150                switch ((uint8_t) *name) {
     151                case 0xe5:
     152                        d->ext[i] = FAT_DENTRY_E5_ESC;
     153                        name++;
     154                        break;
     155                case '\0':
     156                        d->ext[i] = FAT_PAD;
     157                        break;
     158                default:
     159                        if (isalpha(*name)) {
     160                                if (!islower(*name))
     161                                        lower_ext = false;
     162                        }
     163                       
     164                        d->ext[i] = toupper(*name++);
     165                        break;
     166                }
     167        }
     168       
     169        if (lower_name)
     170                d->lcase |= FAT_LCASE_LOWER_NAME;
     171        else
     172                d->lcase &= ~FAT_LCASE_LOWER_NAME;
     173       
     174        if (lower_ext)
     175                d->lcase |= FAT_LCASE_LOWER_EXT;
     176        else
     177                d->lcase &= ~FAT_LCASE_LOWER_EXT;
     178}
     179
     180fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
     181{
     182        if (d->attr == FAT_ATTR_LFN) {
     183                /* long name entry */
     184                if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED)
     185                        return FAT_DENTRY_FREE;
     186                else
     187                        return FAT_DENTRY_LFN;
     188        }
     189        if (d->attr & FAT_ATTR_VOLLABEL) {
     190                /* volume label entry */
     191                return FAT_DENTRY_SKIP;
     192        }
     193        if (d->name[0] == FAT_DENTRY_ERASED) {
     194                /* not-currently-used entry */
     195                return FAT_DENTRY_FREE;
     196        }
     197        if (d->name[0] == FAT_DENTRY_UNUSED) {
     198                /* never used entry */
     199                return FAT_DENTRY_LAST;
     200        }
     201        if (d->name[0] == FAT_DENTRY_DOT) {
     202                /*
     203                 * Most likely '.' or '..'.
     204                 * It cannot occur in a regular file name.
     205                 */
     206                return FAT_DENTRY_SKIP;
     207        }
     208        return FAT_DENTRY_VALID;
     209}
     210
     211/** Compute checksum of Node name.
     212 *
     213 * Returns an unsigned byte checksum computed on an unsigned byte
     214 * array. The array must be 11 bytes long and is assumed to contain
     215 * a name stored in the format of a MS-DOS directory entry.
     216 *
     217 * @param name          Node name read from the dentry.
     218 *
     219 * @return              An 8-bit unsigned checksum of the name.
     220 */
     221uint8_t fat_dentry_chksum(uint8_t *name)
     222{
     223        uint8_t i, sum = 0;
     224
     225        for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++)
     226                sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
     227
     228        return sum;
     229}
     230
     231/** Get number of bytes in a string with size limit.
     232 *
     233 * @param str  NULL-terminated (or not) string.
     234 * @param size Maximum number of bytes to consider.
     235 *
     236 * @return Number of bytes in string (without 0 and ff).
     237 *
     238 */
     239size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
     240{
     241        size_t offset = 0;
     242
     243        while (offset < size) {
     244                if (str[offset] == 0 || str[offset] == FAT_LFN_PAD)
     245                        break;
     246                offset++;
     247        }
     248        return offset;
     249}
     250
     251/** Get number of bytes in a FAT long entry occuped by characters.
     252 *
     253 * @param d FAT long entry.
     254 *
     255 * @return Number of bytes.
     256 *
     257 */
     258size_t fat_lfn_size(const fat_dentry_t *d)
     259{
     260        size_t size = 0;
     261       
     262        size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
     263        size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
     264        size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);     
     265       
     266        return size;
     267}
     268
     269size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
     270{
     271        int i;
     272        for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) {
     273                if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
     274                        continue;
     275                (*offset)--;
     276                dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
     277        }
     278        for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) {
     279                if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
     280                        continue;
     281                (*offset)--;
     282                dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
     283        }
     284        for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) {
     285                if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
     286                        continue;
     287                (*offset)--;
     288                dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
     289        }
     290        return *offset;
     291}
     292
     293size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size,
     294    fat_dentry_t *d)
     295{
     296        size_t idx;
     297        for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) {
     298                if (*offset < size) {
     299                        d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
     300                        (*offset)++;
     301                } else
     302                        d->lfn.part1[idx] = FAT_LFN_PAD;
     303        }
     304        for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) {
     305                if (*offset < size) {
     306                        d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
     307                        (*offset)++;
     308                } else
     309                        d->lfn.part2[idx] = FAT_LFN_PAD;
     310        }
     311        for (idx = 0; idx < FAT_LFN_PART3_SIZE; idx++) {
     312                if (*offset < size) {
     313                        d->lfn.part3[idx] = host2uint16_t_le(src[*offset]);
     314                        (*offset)++;
     315                } else
     316                        d->lfn.part3[idx] = FAT_LFN_PAD;
     317        }
     318
     319        if (src[*offset] == 0)
     320                offset++;
     321        FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
     322        d->lfn.type = 0;
     323        d->lfn.firstc_lo = 0;
     324       
     325        return *offset;
     326}
     327
     328void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
     329{
     330        wchar_t ch;
     331        size_t off = 0;
     332        size_t i = 0;
     333       
     334        while (i < count) {
     335                if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
     336                        if (ascii_check(ch) & IS_D_CHAR(ch))
     337                                *dst = toupper(ch);
     338                        else
     339                                *dst = pad;
     340                } else
     341                        break;
     342
     343                dst++;
     344                i++;
     345        }
     346        *dst = '\0';
     347}
     348
     349bool fat_valid_name(const char *name)
     350{
     351        wchar_t ch;
     352        size_t offset=0;
     353        bool result = true;
     354       
     355        while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
     356                if (str_chr(FAT_STOP_CHARS, ch) != NULL) {
     357                        result = false;
     358                        break;
     359                }
     360        }
     361        return result;
     362}
     363
     364bool fat_valid_short_name(const char *name)
    83365{
    84366        unsigned int i;
    85367        unsigned int dot = 0;
    86368        bool dot_found = false;
    87        
    88369
    89370        for (i = 0; name[i]; i++) {
     
    96377                        }
    97378                } else {
    98                         if (!is_d_char(name[i]))
     379                        if (!IS_D_CHAR(name[i]))
    99380                                return false;
    100381                }
     
    114395}
    115396
    116 void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
    117 {
    118         unsigned int i;
    119        
    120         for (i = 0; i < FAT_NAME_LEN; i++) {
    121                 if (d->name[i] == FAT_PAD)
    122                         break;
    123                
    124                 if (d->name[i] == FAT_DENTRY_E5_ESC)
    125                         *buf++ = 0xe5;
    126                 else {
    127                         if (d->lcase & FAT_LCASE_LOWER_NAME)
    128                                 *buf++ = tolower(d->name[i]);
    129                         else
    130                                 *buf++ = d->name[i];
    131                 }
    132         }
    133        
    134         if (d->ext[0] != FAT_PAD)
    135                 *buf++ = '.';
    136        
    137         for (i = 0; i < FAT_EXT_LEN; i++) {
    138                 if (d->ext[i] == FAT_PAD) {
    139                         *buf = '\0';
    140                         return;
    141                 }
    142                
    143                 if (d->ext[i] == FAT_DENTRY_E5_ESC)
    144                         *buf++ = 0xe5;
    145                 else {
    146                         if (d->lcase & FAT_LCASE_LOWER_EXT)
    147                                 *buf++ = tolower(d->ext[i]);
    148                         else
    149                                 *buf++ = d->ext[i];
    150                 }
    151         }
    152        
    153         *buf = '\0';
    154 }
    155 
    156 void fat_dentry_name_set(fat_dentry_t *d, const char *name)
    157 {
    158         unsigned int i;
    159         const char fake_ext[] = "   ";
    160         bool lower_name = true;
    161         bool lower_ext = true;
    162        
    163         for (i = 0; i < FAT_NAME_LEN; i++) {
    164                 switch ((uint8_t) *name) {
    165                 case 0xe5:
    166                         d->name[i] = FAT_DENTRY_E5_ESC;
    167                         name++;
    168                         break;
    169                 case '\0':
    170                 case '.':
    171                         d->name[i] = FAT_PAD;
    172                         break;
    173                 default:
    174                         if (isalpha(*name)) {
    175                                 if (!islower(*name))
    176                                         lower_name = false;
    177                         }
    178                        
    179                         d->name[i] = toupper(*name++);
    180                         break;
    181                 }
    182         }
    183        
    184         if (*name++ != '.')
    185                 name = fake_ext;
    186        
    187         for (i = 0; i < FAT_EXT_LEN; i++) {
    188                 switch ((uint8_t) *name) {
    189                 case 0xe5:
    190                         d->ext[i] = FAT_DENTRY_E5_ESC;
    191                         name++;
    192                         break;
    193                 case '\0':
    194                         d->ext[i] = FAT_PAD;
    195                         break;
    196                 default:
    197                         if (isalpha(*name)) {
    198                                 if (!islower(*name))
    199                                         lower_ext = false;
    200                         }
    201                        
    202                         d->ext[i] = toupper(*name++);
    203                         break;
    204                 }
    205         }
    206        
    207         if (lower_name)
    208                 d->lcase |= FAT_LCASE_LOWER_NAME;
    209         else
    210                 d->lcase &= ~FAT_LCASE_LOWER_NAME;
    211        
    212         if (lower_ext)
    213                 d->lcase |= FAT_LCASE_LOWER_EXT;
    214         else
    215                 d->lcase &= ~FAT_LCASE_LOWER_EXT;
    216 }
    217 
    218 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
    219 {
    220         if (d->attr & FAT_ATTR_VOLLABEL) {
    221                 /* volume label entry */
    222                 return FAT_DENTRY_SKIP;
    223         }
    224         if (d->name[0] == FAT_DENTRY_ERASED) {
    225                 /* not-currently-used entry */
    226                 return FAT_DENTRY_FREE;
    227         }
    228         if (d->name[0] == FAT_DENTRY_UNUSED) {
    229                 /* never used entry */
    230                 return FAT_DENTRY_LAST;
    231         }
    232         if (d->name[0] == FAT_DENTRY_DOT) {
    233                 /*
    234                  * Most likely '.' or '..'.
    235                  * It cannot occur in a regular file name.
    236                  */
    237                 return FAT_DENTRY_SKIP;
    238         }
    239         return FAT_DENTRY_VALID;
     397size_t utf16_length(const uint16_t *wstr)
     398{
     399        size_t len = 0;
     400       
     401        while (*wstr++ != 0)
     402                len++;
     403       
     404        return len;
    240405}
    241406
  • uspace/srv/fs/fat/fat_dentry.h

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3738#include <bool.h>
    3839
     40#define IS_D_CHAR(ch) (isalnum(ch) || ch == '_')
     41#define FAT_STOP_CHARS "*?/\\\n\t|'"
     42
    3943#define FAT_NAME_LEN            8
    4044#define FAT_EXT_LEN             3
     
    4448#define FAT_EXT_PAD             "   "
    4549
    46 #define FAT_ATTR_RDONLY         (1 << 0)
    47 #define FAT_ATTR_VOLLABEL       (1 << 3)
    48 #define FAT_ATTR_SUBDIR         (1 << 4)
    49 
     50#define FAT_ATTR_RDONLY   0x01
     51#define FAT_ATTR_HIDDEN   0x02
     52#define FAT_ATTR_SYSTEM   0x04
     53#define FAT_ATTR_VOLLABEL 0x08
     54#define FAT_ATTR_SUBDIR   0x10
     55#define FAT_ATTR_ARCHIVE  0x20
     56#define FAT_ATTR_LFN \
     57    (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL)
     58   
    5059#define FAT_LCASE_LOWER_NAME    0x08
    5160#define FAT_LCASE_LOWER_EXT     0x10
    5261
    53 #define FAT_PAD                 ' '
     62#define FAT_PAD                 ' '
     63#define FAT_LFN_PAD     0xffff
     64#define FAT_SFN_CHAR '_'
    5465
    5566#define FAT_DENTRY_UNUSED       0x00
     
    5768#define FAT_DENTRY_DOT          0x2e
    5869#define FAT_DENTRY_ERASED       0xe5
     70#define FAT_LFN_LAST            0x40
     71#define FAT_LFN_ERASED          0x80
     72
     73#define FAT_LFN_ORDER(d) ((d)->lfn.order)
     74#define FAT_IS_LFN(d) \
     75    ((FAT_LFN_ORDER((d)) & FAT_LFN_LAST) == FAT_LFN_LAST)
     76#define FAT_LFN_COUNT(d) \
     77    (FAT_LFN_ORDER((d)) ^ FAT_LFN_LAST)
     78#define FAT_LFN_PART1(d) ((d)->lfn.part1)
     79#define FAT_LFN_PART2(d) ((d)->lfn.part2)
     80#define FAT_LFN_PART3(d) ((d)->lfn.part3)
     81#define FAT_LFN_ATTR(d) ((d)->lfn.attr)
     82#define FAT_LFN_CHKSUM(d) ((d)->lfn.check_sum)
     83
     84#define FAT_LFN_NAME_SIZE   260
     85#define FAT_LFN_MAX_COUNT   20
     86#define FAT_LFN_PART1_SIZE  5
     87#define FAT_LFN_PART2_SIZE  6
     88#define FAT_LFN_PART3_SIZE  2
     89#define FAT_LFN_ENTRY_SIZE \
     90    (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)
    5991
    6092typedef enum {
     
    6294        FAT_DENTRY_LAST,
    6395        FAT_DENTRY_FREE,
    64         FAT_DENTRY_VALID
     96        FAT_DENTRY_VALID,
     97        FAT_DENTRY_LFN
    6598} fat_dentry_clsf_t;
    6699
    67 typedef struct {
    68         uint8_t         name[8];
    69         uint8_t         ext[3];
    70         uint8_t         attr;
    71         uint8_t         lcase;
    72         uint8_t         ctime_fine;
    73         uint16_t        ctime;
    74         uint16_t        cdate;
    75         uint16_t        adate;
    76         union {
    77                 uint16_t        eaidx;          /* FAT12/FAT16 */
    78                 uint16_t        firstc_hi;      /* FAT32 */
     100typedef union {
     101        struct {
     102                uint8_t         name[8];
     103                uint8_t         ext[3];
     104                uint8_t         attr;
     105                uint8_t         lcase;
     106                uint8_t         ctime_fine;
     107                uint16_t        ctime;
     108                uint16_t        cdate;
     109                uint16_t        adate;
     110                union {
     111                        uint16_t        eaidx;          /* FAT12/FAT16 */
     112                        uint16_t        firstc_hi;      /* FAT32 */
     113                } __attribute__ ((packed));
     114                uint16_t        mtime;
     115                uint16_t        mdate;
     116                union {
     117                        uint16_t        firstc;         /* FAT12/FAT16 */
     118                        uint16_t        firstc_lo;      /* FAT32 */
     119                } __attribute__ ((packed));
     120                uint32_t        size;
    79121        } __attribute__ ((packed));
    80         uint16_t        mtime;
    81         uint16_t        mdate;
    82         union {
    83                 uint16_t        firstc;         /* FAT12/FAT16 */
    84                 uint16_t        firstc_lo;      /* FAT32 */
    85         } __attribute__ ((packed));
    86         uint32_t        size;
     122        struct {
     123                uint8_t         order;
     124                uint16_t        part1[FAT_LFN_PART1_SIZE];
     125                uint8_t         attr;
     126                uint8_t         type;
     127                uint8_t         check_sum;
     128                uint16_t        part2[FAT_LFN_PART2_SIZE];
     129                uint16_t        firstc_lo; /* MUST be 0 */
     130                uint16_t        part3[FAT_LFN_PART3_SIZE];
     131        } __attribute__ ((packed)) lfn;
    87132} __attribute__ ((packed)) fat_dentry_t;
    88133
     134
    89135extern int fat_dentry_namecmp(char *, const char *);
    90 extern bool fat_dentry_name_verify(const char *);
    91136extern void fat_dentry_name_get(const fat_dentry_t *, char *);
    92137extern void fat_dentry_name_set(fat_dentry_t *, const char *);
    93138extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
     139extern uint8_t fat_dentry_chksum(uint8_t *);
     140
     141extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);
     142extern size_t fat_lfn_size(const fat_dentry_t *);
     143extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *);
     144extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t,
     145    fat_dentry_t *);
     146
     147extern void str_to_ascii(char *, const char *, size_t, uint8_t);
     148extern size_t utf16_length(const uint16_t *);
     149
     150extern bool fat_valid_name(const char *);
     151extern bool fat_valid_short_name(const char *);
    94152
    95153#endif
  • uspace/srv/fs/fat/fat_fat.c

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    5051#include <mem.h>
    5152
    52 /*
    53  * Convenience macros for computing some frequently used values from the
    54  * primitive boot sector members.
    55  */
    56 #define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    57                         (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    58 #define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    59 
    60 #define CLBN2PBN(bs, cl, bn) \
    61         (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     53#define IS_ODD(number)  (number & 0x1)
    6254
    6355/**
     
    6557 * during allocation of clusters. The lock does not have to be held durring
    6658 * deallocation of clusters.
    67  */ 
     59 */
    6860static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6961
     
    7769 * @param numc          If non-NULL, output argument holding the number of
    7870 *                      clusters seen during the walk.
    79  * @param max_clusters  Maximum number of clusters to visit.   
     71 * @param max_clusters  Maximum number of clusters to visit.
    8072 *
    8173 * @return              EOK on success or a negative error code.
    8274 */
    83 int 
     75int
    8476fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
    85     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    86 {
    87         block_t *b;
    88         uint16_t clusters = 0;
    89         fat_cluster_t clst = firstc;
     77    fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
     78{
     79        uint32_t clusters = 0;
     80        fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
     81        fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
    9082        int rc;
    9183
     
    9991        }
    10092
    101         while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
    102                 aoff64_t fsec;  /* sector offset relative to FAT1 */
    103                 unsigned fidx;  /* FAT1 entry index */
    104 
     93        while (clst < clst_last1 && clusters < max_clusters) {
    10594                assert(clst >= FAT_CLST_FIRST);
    10695                if (lastc)
    10796                        *lastc = clst;  /* remember the last cluster number */
    108                 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    109                 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     97
    11098                /* read FAT1 */
    111                 rc = block_get(&b, service_id, RSCNT(bs) + fsec,
    112                     BLOCK_FLAGS_NONE);
    113                 if (rc != EOK)
    114                         return rc;
    115                 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    116                 assert(clst != FAT_CLST_BAD);
    117                 rc = block_put(b);
    118                 if (rc != EOK)
    119                         return rc;
     99                rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
     100                if (rc != EOK)
     101                        return rc;
     102
     103                assert(clst != clst_bad);
    120104                clusters++;
    121105        }
    122106
    123         if (lastc && clst < FAT_CLST_LAST1)
     107        if (lastc && clst < clst_last1)
    124108                *lastc = clst;
    125109        if (numc)
     
    151135                return ELIMIT;
    152136
    153         if (nodep->firstc == FAT_CLST_ROOT)
     137        if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
    154138                goto fall_through;
    155139
     
    178162        if (rc != EOK)
    179163                return rc;
    180        
     164
    181165        /*
    182166         * Update the "current" cluster cache.
     
    198182 * @param clp           If not NULL, address where the cluster containing bn
    199183 *                      will be stored.
    200  *                      stored 
     184 *                      stored
    201185 * @param bn            Block number.
    202186 * @param flags         Flags passed to libblock.
     
    208192    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    209193{
    210         uint16_t clusters;
    211         unsigned max_clusters;
     194        uint32_t clusters;
     195        uint32_t max_clusters;
    212196        fat_cluster_t c;
    213197        int rc;
     
    219203                return ELIMIT;
    220204
    221         if (fcl == FAT_CLST_ROOT) {
     205        if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
    222206                /* root directory special case */
    223207                assert(bn < RDS(bs));
     
    253237 * @return              EOK on success or a negative error code.
    254238 */
    255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
     239int
     240fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
    256241{
    257242        block_t *b;
     
    275260                        return rc;
    276261        }
    277        
     262
    278263        if (o >= pos)
    279264                return EOK;
    280        
     265
    281266        /* zero out the initial part of the new cluster chain */
    282267        for (o = boundary; o < pos; o += BPS(bs)) {
     
    304289 * @return              EOK or a negative error code.
    305290 */
     291static int
     292fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     293    fat_cluster_t clst, fat_cluster_t *value)
     294{
     295        block_t *b, *b1;
     296        uint16_t byte1, byte2;
     297        aoff64_t offset;
     298        int rc;
     299
     300        offset = (clst + clst / 2);
     301        if (offset / BPS(bs) >= SF(bs))
     302                return ERANGE;
     303
     304        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     305            offset / BPS(bs), BLOCK_FLAGS_NONE);
     306        if (rc != EOK)
     307                return rc;
     308
     309        byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
     310        /* This cluster access spans a sector boundary. Check only for FAT12 */
     311        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     312                /* Is this the last sector of FAT? */
     313                if (offset / BPS(bs) < SF(bs)) {
     314                        /* No, read the next sector */
     315                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     316                            SF(bs) * fatno + offset / BPS(bs),
     317                            BLOCK_FLAGS_NONE);
     318                        if (rc != EOK) {
     319                                block_put(b);
     320                                return rc;
     321                        }
     322                        /*
     323                        * Combining value with last byte of current sector and
     324                        * first byte of next sector
     325                        */
     326                        byte2 = ((uint8_t*) b1->data)[0];
     327
     328                        rc = block_put(b1);
     329                        if (rc != EOK) {
     330                                block_put(b);
     331                                return rc;
     332                        }
     333                } else {
     334                        /* Yes. This is the last sector of FAT */
     335                        block_put(b);
     336                        return ERANGE;
     337                }
     338        } else
     339                byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];
     340
     341        *value = uint16_t_le2host(byte1 | (byte2 << 8));
     342        if (IS_ODD(clst))
     343                *value = (*value) >> 4;
     344        else
     345                *value = (*value) & FAT12_MASK;
     346       
     347        rc = block_put(b);
     348
     349        return rc;
     350}
     351
     352/** Get cluster from the first FAT.
     353 *
     354 * @param bs            Buffer holding the boot sector for the file system.
     355 * @param service_id    Service ID for the file system.
     356 * @param clst          Cluster which to get.
     357 * @param value         Output argument holding the value of the cluster.
     358 *
     359 * @return              EOK or a negative error code.
     360 */
     361static int
     362fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     363    fat_cluster_t clst, fat_cluster_t *value)
     364{
     365        block_t *b;
     366        aoff64_t offset;
     367        int rc;
     368
     369        offset = (clst * FAT16_CLST_SIZE);
     370
     371        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     372            offset / BPS(bs), BLOCK_FLAGS_NONE);
     373        if (rc != EOK)
     374                return rc;
     375
     376        *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
     377
     378        rc = block_put(b);
     379
     380        return rc;
     381}
     382
     383/** Get cluster from the first FAT.
     384 *
     385 * @param bs            Buffer holding the boot sector for the file system.
     386 * @param service_id    Service ID for the file system.
     387 * @param clst          Cluster which to get.
     388 * @param value         Output argument holding the value of the cluster.
     389 *
     390 * @return              EOK or a negative error code.
     391 */
     392static int
     393fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     394    fat_cluster_t clst, fat_cluster_t *value)
     395{
     396        block_t *b;
     397        aoff64_t offset;
     398        int rc;
     399
     400        offset = (clst * FAT32_CLST_SIZE);
     401
     402        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     403            offset / BPS(bs), BLOCK_FLAGS_NONE);
     404        if (rc != EOK)
     405                return rc;
     406
     407        *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) &
     408            FAT32_MASK;
     409
     410        rc = block_put(b);
     411
     412        return rc;
     413}
     414
     415
     416/** Get cluster from the first FAT.
     417 *
     418 * @param bs            Buffer holding the boot sector for the file system.
     419 * @param service_id    Service ID for the file system.
     420 * @param clst          Cluster which to get.
     421 * @param value         Output argument holding the value of the cluster.
     422 *
     423 * @return              EOK or a negative error code.
     424 */
    306425int
    307426fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    308427    fat_cluster_t clst, fat_cluster_t *value)
    309428{
    310         block_t *b;
    311         fat_cluster_t *cp;
    312         int rc;
    313 
     429        int rc;
     430
     431        assert(fatno < FATCNT(bs));
     432
     433        if (FAT_IS_FAT12(bs))
     434                rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);
     435        else if (FAT_IS_FAT16(bs))
     436                rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);
     437        else
     438                rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);
     439
     440        return rc;
     441}
     442
     443/** Set cluster in one instance of FAT.
     444 *
     445 * @param bs            Buffer holding the boot sector for the file system.
     446 * @param service_id    Service ID for the file system.
     447 * @param fatno         Number of the FAT instance where to make the change.
     448 * @param clst          Cluster which is to be set.
     449 * @param value         Value to set the cluster with.
     450 *
     451 * @return              EOK on success or a negative error code.
     452 */
     453static int
     454fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     455    fat_cluster_t clst, fat_cluster_t value)
     456{
     457        block_t *b, *b1 = NULL;
     458        aoff64_t offset;
     459        uint16_t byte1, byte2;
     460        int rc;
     461
     462        offset = (clst + clst / 2);
     463        if (offset / BPS(bs) >= SF(bs))
     464                return ERANGE;
     465       
    314466        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    315             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     467            offset / BPS(bs), BLOCK_FLAGS_NONE);
    316468        if (rc != EOK)
    317469                return rc;
    318         cp = (fat_cluster_t *)b->data +
    319             clst % (BPS(bs) / sizeof(fat_cluster_t));
    320         *value = uint16_t_le2host(*cp);
     470
     471        byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
     472        bool border = false;
     473        /* This cluster access spans a sector boundary. */
     474        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     475                /* Is it the last sector of FAT? */
     476                if (offset / BPS(bs) < SF(bs)) {
     477                        /* No, read the next sector */
     478                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     479                            SF(bs) * fatno + offset / BPS(bs),
     480                            BLOCK_FLAGS_NONE);
     481                        if (rc != EOK) {
     482                                block_put(b);
     483                                return rc;
     484                        }
     485                        /*
     486                         * Combining value with last byte of current sector and
     487                         * first byte of next sector
     488                         */
     489                        byte2 = ((uint8_t *) b1->data)[0];
     490                        border = true;
     491                } else {
     492                        /* Yes. This is the last sector of FAT */
     493                        block_put(b);
     494                        return ERANGE;
     495                }
     496        } else
     497                byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1];
     498
     499        if (IS_ODD(clst)) {
     500                byte1 &= 0x0f;
     501                byte2 = 0;
     502                value = (value << 4);
     503        } else {
     504                byte1 = 0;
     505                byte2 &= 0xf0;
     506                value &= FAT12_MASK;
     507        }
     508
     509        byte1 = byte1 | (value & 0xff);
     510        byte2 = byte2 | (value >> 8);
     511
     512        ((uint8_t *) b->data)[(offset % BPS(bs))] = byte1;
     513        if (border) {
     514                ((uint8_t *) b1->data)[0] = byte2;
     515
     516                b1->dirty = true;
     517                rc = block_put(b1);
     518                if (rc != EOK) {
     519                        block_put(b);
     520                        return rc;
     521                }
     522        } else
     523                ((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2;
     524
     525        b->dirty = true;        /* need to sync block */
    321526        rc = block_put(b);
    322        
     527
     528        return rc;
     529}
     530
     531/** Set cluster in one instance of FAT.
     532 *
     533 * @param bs            Buffer holding the boot sector for the file system.
     534 * @param service_id    Service ID for the file system.
     535 * @param fatno         Number of the FAT instance where to make the change.
     536 * @param clst          Cluster which is to be set.
     537 * @param value         Value to set the cluster with.
     538 *
     539 * @return              EOK on success or a negative error code.
     540 */
     541static int
     542fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     543    fat_cluster_t clst, fat_cluster_t value)
     544{
     545        block_t *b;
     546        aoff64_t offset;
     547        int rc;
     548
     549        offset = (clst * FAT16_CLST_SIZE);
     550
     551        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     552            offset / BPS(bs), BLOCK_FLAGS_NONE);
     553        if (rc != EOK)
     554                return rc;
     555
     556        *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
     557
     558        b->dirty = true;        /* need to sync block */
     559        rc = block_put(b);
     560
     561        return rc;
     562}
     563
     564/** Set cluster in one instance of FAT.
     565 *
     566 * @param bs            Buffer holding the boot sector for the file system.
     567 * @param service_id    Service ID for the file system.
     568 * @param fatno         Number of the FAT instance where to make the change.
     569 * @param clst          Cluster which is to be set.
     570 * @param value         Value to set the cluster with.
     571 *
     572 * @return              EOK on success or a negative error code.
     573 */
     574static int
     575fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     576    fat_cluster_t clst, fat_cluster_t value)
     577{
     578        block_t *b;
     579        aoff64_t offset;
     580        int rc;
     581        fat_cluster_t temp;
     582
     583        offset = (clst * FAT32_CLST_SIZE);
     584
     585        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     586            offset / BPS(bs), BLOCK_FLAGS_NONE);
     587        if (rc != EOK)
     588                return rc;
     589
     590        temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
     591        temp &= 0xf0000000;
     592        temp |= (value & FAT32_MASK);
     593        *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
     594
     595        b->dirty = true;        /* need to sync block */
     596        rc = block_put(b);
     597
    323598        return rc;
    324599}
     
    338613    fat_cluster_t clst, fat_cluster_t value)
    339614{
    340         block_t *b;
    341         fat_cluster_t *cp;
    342615        int rc;
    343616
    344617        assert(fatno < FATCNT(bs));
    345         rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
    346             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    347         if (rc != EOK)
    348                 return rc;
    349         cp = (fat_cluster_t *)b->data +
    350             clst % (BPS(bs) / sizeof(fat_cluster_t));
    351         *cp = host2uint16_t_le(value);
    352         b->dirty = true;                /* need to sync block */
    353         rc = block_put(b);
     618
     619        if (FAT_IS_FAT12(bs))
     620                rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value);
     621        else if (FAT_IS_FAT16(bs))
     622                rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value);
     623        else
     624                rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);
     625
    354626        return rc;
    355627}
     
    369641        uint8_t fatno;
    370642        unsigned c;
    371         int rc;
    372 
    373         for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
     643        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
     644        int rc;
     645
     646        for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
    374647                for (c = 0; c < nclsts; c++) {
    375648                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
    376                             c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     649                            c == 0 ? clst_last1 : lifo[c - 1]);
    377650                        if (rc != EOK)
    378651                                return rc;
     
    404677    fat_cluster_t *mcl, fat_cluster_t *lcl)
    405678{
    406         block_t *blk;
    407         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    408         unsigned found = 0;     /* top of the free cluster number stack */
    409         unsigned b, c, cl;
    410         int rc;
     679        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     680        unsigned found = 0;     /* top of the free cluster number stack */
     681        fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
     682        int rc = EOK;
    411683
    412684        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    418690         */
    419691        fibril_mutex_lock(&fat_alloc_lock);
    420         for (b = 0, cl = 0; b < SF(bs); b++) {
    421                 rc = block_get(&blk, service_id, RSCNT(bs) + b,
    422                     BLOCK_FLAGS_NONE);
    423                 if (rc != EOK)
    424                         goto error;
    425                 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
     692        for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts;
     693            clst++) {
     694                rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
     695                if (rc != EOK)
     696                        break;
     697
     698                if (value == FAT_CLST_RES0) {
    426699                        /*
    427                          * Check if the entire cluster is physically there.
    428                          * This check becomes necessary when the file system is
    429                          * created with fewer total sectors than how many is
    430                          * inferred from the size of the file allocation table
    431                          * or when the last cluster ends beyond the end of the
    432                          * device.
     700                         * The cluster is free. Put it into our stack
     701                         * of found clusters and mark it as non-free.
    433702                         */
    434                         if ((cl >= FAT_CLST_FIRST) &&
    435                             CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
    436                                 rc = block_put(blk);
    437                                 if (rc != EOK)
    438                                         goto error;
    439                                 goto out;
    440                         }
    441 
    442                         fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    443                         if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
    444                                 /*
    445                                  * The cluster is free. Put it into our stack
    446                                  * of found clusters and mark it as non-free.
    447                                  */
    448                                 lifo[found] = cl;
    449                                 *clst = (found == 0) ?
    450                                     host2uint16_t_le(FAT_CLST_LAST1) :
    451                                     host2uint16_t_le(lifo[found - 1]);
    452                                 blk->dirty = true;      /* need to sync block */
    453                                 if (++found == nclsts) {
    454                                         /* we are almost done */
    455                                         rc = block_put(blk);
    456                                         if (rc != EOK)
    457                                                 goto error;
    458                                         /* update the shadow copies of FAT */
    459                                         rc = fat_alloc_shadow_clusters(bs,
    460                                             service_id, lifo, nclsts);
    461                                         if (rc != EOK)
    462                                                 goto error;
    463                                         *mcl = lifo[found - 1];
    464                                         *lcl = lifo[0];
    465                                         free(lifo);
    466                                         fibril_mutex_unlock(&fat_alloc_lock);
    467                                         return EOK;
    468                                 }
    469                         }
     703                        lifo[found] = clst;
     704                        rc = fat_set_cluster(bs, service_id, FAT1, clst,
     705                            (found == 0) ?  clst_last1 : lifo[found - 1]);
     706                        if (rc != EOK)
     707                                break;
     708
     709                        found++;
    470710                }
    471                 rc = block_put(blk);
    472                 if (rc != EOK) {
    473 error:
     711        }
     712
     713        if (rc == EOK && found == nclsts) {
     714                rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
     715                if (rc == EOK) {
     716                        *mcl = lifo[found - 1];
     717                        *lcl = lifo[0];
     718                        free(lifo);
    474719                        fibril_mutex_unlock(&fat_alloc_lock);
    475                         free(lifo);
    476                         return rc;
     720                        return EOK;
    477721                }
    478722        }
    479 out:
     723
     724        /* If something wrong - free the clusters */
     725        while (found--) {
     726                (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
     727                    FAT_CLST_RES0);
     728        }
     729
     730        free(lifo);
    480731        fibril_mutex_unlock(&fat_alloc_lock);
    481732
    482         /*
    483          * We could not find enough clusters. Now we need to free the clusters
    484          * we have allocated so far.
    485          */
    486         while (found--) {
    487                 rc = fat_set_cluster(bs, service_id, FAT1, lifo[found],
    488                     FAT_CLST_RES0);
    489                 if (rc != EOK) {
    490                         free(lifo);
    491                         return rc;
    492                 }
    493         }
    494        
    495         free(lifo);
    496733        return ENOSPC;
    497734}
     
    509746{
    510747        unsigned fatno;
    511         fat_cluster_t nextc;
     748        fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
    512749        int rc;
    513750
    514751        /* Mark all clusters in the chain as free in all copies of FAT. */
    515         while (firstc < FAT_CLST_LAST1) {
    516                 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
     752        while (firstc < FAT_CLST_LAST1(bs)) {
     753                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
     754
    517755                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
    518756                if (rc != EOK)
    519757                        return rc;
    520                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     758
     759                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    521760                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
    522761                            FAT_CLST_RES0);
     
    540779 * @return              EOK on success or a negative error code.
    541780 */
    542 int
    543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
     781int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
    544782    fat_cluster_t lcl)
    545783{
     
    559797                } else {
    560798                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
    561                             &lastc, NULL, (uint16_t) -1);
     799                            &lastc, NULL, (uint32_t) -1);
    562800                        if (rc != EOK)
    563801                                return rc;
    564802                }
    565803
    566                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    567                         rc = fat_set_cluster(bs, nodep->idx->service_id, fatno,
    568                             lastc, mcl);
     804                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     805                        rc = fat_set_cluster(bs, nodep->idx->service_id,
     806                            fatno, lastc, mcl);
    569807                        if (rc != EOK)
    570808                                return rc;
     
    590828int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    591829{
     830        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    592831        int rc;
    593832        service_id_t service_id = nodep->idx->service_id;
     
    616855
    617856                /* Terminate the cluster chain in all copies of FAT. */
    618                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     857                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    619858                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
    620                             FAT_CLST_LAST1);
     859                            clst_last1);
    621860                        if (rc != EOK)
    622861                                return rc;
     
    673912
    674913        /* Check number of FATs. */
    675         if (bs->fatcnt == 0)
     914        if (FATCNT(bs) == 0)
    676915                return ENOTSUP;
    677916
    678917        /* Check total number of sectors. */
    679 
    680         if (bs->totsec16 == 0 && bs->totsec32 == 0)
     918        if (TS(bs) == 0)
    681919                return ENOTSUP;
    682920
    683921        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    684             bs->totsec16 != bs->totsec32) 
     922            bs->totsec16 != bs->totsec32)
    685923                return ENOTSUP;
    686924
     
    690928
    691929        /* Check number of sectors per FAT. */
    692         if (bs->sec_per_fat == 0)
     930        if (SF(bs) == 0)
    693931                return ENOTSUP;
    694932
     
    700938         * sanitized to support file systems with this property.
    701939         */
    702         if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
    703             uint16_t_le2host(bs->bps) != 0)
     940        if (!FAT_IS_FAT32(bs) &&
     941            (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
    704942                return ENOTSUP;
    705943
    706944        /* Check signature of each FAT. */
    707 
    708         for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
     945        for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
    709946                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
    710947                if (rc != EOK)
     
    715952                        return EIO;
    716953
    717                 /* Check that first byte of FAT contains the media descriptor. */
     954                /*
     955                 * Check that first byte of FAT contains the media descriptor.
     956                 */
    718957                if ((e0 & 0xff) != bs->mdesc)
    719958                        return ENOTSUP;
     
    723962                 * set to one.
    724963                 */
    725                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     964                if (!FAT_IS_FAT12(bs) &&
     965                    ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
    726966                        return ENOTSUP;
    727967        }
     
    732972/**
    733973 * @}
    734  */ 
     974 */
  • uspace/srv/fs/fat/fat_fat.h

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334#ifndef FAT_FAT_FAT_H_
     
    4041#define FAT1            0
    4142
    42 #define FAT_CLST_RES0   0x0000
    43 #define FAT_CLST_RES1   0x0001
    44 #define FAT_CLST_FIRST  0x0002
    45 #define FAT_CLST_BAD    0xfff7
    46 #define FAT_CLST_LAST1  0xfff8
    47 #define FAT_CLST_LAST8  0xffff
     43#define FAT_CLST_RES0     0
     44#define FAT_CLST_RES1     1
     45#define FAT_CLST_FIRST    2
     46
     47#define FAT32_CLST_BAD    0x0ffffff7
     48#define FAT32_CLST_LAST1  0x0ffffff8
     49#define FAT32_CLST_LAST8  0x0fffffff
     50
     51#define FAT12_MASK        0x0fff
     52#define FAT16_MASK        0xffff
     53#define FAT32_MASK        0x0fffffff
     54
     55#define FAT12_CLST_MAX    4085
     56#define FAT16_CLST_MAX    65525
     57
     58/* Size in bytes for cluster value of FAT */
     59#define FAT12_CLST_SIZE   2
     60#define FAT16_CLST_SIZE   2
     61#define FAT32_CLST_SIZE   4
    4862
    4963/* internally used to mark root directory's parent */
     
    5266#define FAT_CLST_ROOT           FAT_CLST_RES1
    5367
     68/*
     69 * Convenience macros for computing some frequently used values from the
     70 * primitive boot sector members.
     71 */
     72#define RDS(bs)   ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
     73                   (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
     74#define SSA(bs)   (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
     75#define DS(bs)    (TS(bs) - SSA(bs))
     76#define CC(bs)    (DS(bs) / SPC(bs))
     77
     78#define CLBN2PBN(bs, cl, bn) \
     79        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     80
     81#define FAT_IS_FAT12(bs)        (CC(bs) < FAT12_CLST_MAX)
     82#define FAT_IS_FAT16(bs) \
     83    ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX))
     84#define FAT_IS_FAT32(bs)        (CC(bs) >= FAT16_CLST_MAX)
     85
     86#define FAT_CLST_SIZE(bs) \
     87    (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE)
     88
     89#define FAT_MASK(bs) \
     90    (FAT_IS_FAT12(bs) ? FAT12_MASK : \
     91    (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK))
     92
     93#define FAT_CLST_LAST1(bs)      (FAT32_CLST_LAST1 & FAT_MASK((bs)))
     94#define FAT_CLST_LAST8(bs)      (FAT32_CLST_LAST8 & FAT_MASK((bs)))
     95#define FAT_CLST_BAD(bs)        (FAT32_CLST_BAD & FAT_MASK((bs)))
     96
     97#define FAT_ROOT_CLST(bs) \
     98    (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \
     99    FAT_CLST_ROOT)
     100
    54101/* forward declarations */
    55102struct block;
     
    57104struct fat_bs;
    58105
    59 typedef uint16_t fat_cluster_t;
     106typedef uint32_t fat_cluster_t;
    60107
    61 #define fat_clusters_get(numc, bs, dh, fc) \
    62     fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
     108#define fat_clusters_get(numc, bs, sid, fc) \
     109    fat_cluster_walk((bs), (sid), (fc), NULL, (numc), (uint32_t) -1)
    63110extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t,
    64     fat_cluster_t *, uint16_t *, uint16_t);
     111    fat_cluster_t *, uint32_t *, uint32_t);
    65112
    66113extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
  • uspace/srv/fs/fat/fat_idx.c

    r1a5b252 r8cc4ddb  
    116116#define UPH_BUCKETS     (1 << UPH_BUCKETS_LOG)
    117117
    118 #define UPH_DH_KEY      0
     118#define UPH_SID_KEY     0
    119119#define UPH_PFC_KEY     1
    120120#define UPH_PDI_KEY     2
     
    122122static hash_index_t pos_hash(unsigned long key[])
    123123{
    124         service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
     124        service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
    125125        fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
    126126        unsigned pdi = (unsigned)key[UPH_PDI_KEY];
     
    150150static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
    151151{
    152         service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
     152        service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
    153153        fat_cluster_t pfc;
    154154        unsigned pdi;
     
    190190#define UIH_BUCKETS     (1 << UIH_BUCKETS_LOG)
    191191
    192 #define UIH_DH_KEY      0
     192#define UIH_SID_KEY     0
    193193#define UIH_INDEX_KEY   1
    194194
    195195static hash_index_t idx_hash(unsigned long key[])
    196196{
    197         service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
     197        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
    198198        fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
    199199
     
    209209static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
    210210{
    211         service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
     211        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
    212212        fs_index_t index;
    213213        fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
     
    402402               
    403403        unsigned long ikey[] = {
    404                 [UIH_DH_KEY] = service_id,
     404                [UIH_SID_KEY] = service_id,
    405405                [UIH_INDEX_KEY] = fidx->index,
    406406        };
     
    420420        link_t *l;
    421421        unsigned long pkey[] = {
    422                 [UPH_DH_KEY] = service_id,
     422                [UPH_SID_KEY] = service_id,
    423423                [UPH_PFC_KEY] = pfc,
    424424                [UPH_PDI_KEY] = pdi,
     
    439439               
    440440                unsigned long ikey[] = {
    441                         [UIH_DH_KEY] = service_id,
     441                        [UIH_SID_KEY] = service_id,
    442442                        [UIH_INDEX_KEY] = fidx->index,
    443443                };
     
    458458{
    459459        unsigned long pkey[] = {
    460                 [UPH_DH_KEY] = idx->service_id,
     460                [UPH_SID_KEY] = idx->service_id,
    461461                [UPH_PFC_KEY] = idx->pfc,
    462462                [UPH_PDI_KEY] = idx->pdi,
     
    471471{
    472472        unsigned long pkey[] = {
    473                 [UPH_DH_KEY] = idx->service_id,
     473                [UPH_SID_KEY] = idx->service_id,
    474474                [UPH_PFC_KEY] = idx->pfc,
    475475                [UPH_PDI_KEY] = idx->pdi,
     
    487487        link_t *l;
    488488        unsigned long ikey[] = {
    489                 [UIH_DH_KEY] = service_id,
     489                [UIH_SID_KEY] = service_id,
    490490                [UIH_INDEX_KEY] = index,
    491491        };
     
    509509{
    510510        unsigned long ikey[] = {
    511                 [UIH_DH_KEY] = idx->service_id,
     511                [UIH_SID_KEY] = idx->service_id,
    512512                [UIH_INDEX_KEY] = idx->index,
    513513        };
     
    571571{
    572572        unsigned long ikey[] = {
    573                 [UIH_DH_KEY] = service_id
     573                [UIH_SID_KEY] = service_id
    574574        };
    575575        unsigned long pkey[] = {
    576                 [UPH_DH_KEY] = service_id
     576                [UPH_SID_KEY] = service_id
    577577        };
    578578
  • uspace/srv/fs/fat/fat_ops.c

    r1a5b252 r8cc4ddb  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    3940#include "fat_dentry.h"
    4041#include "fat_fat.h"
     42#include "fat_directory.h"
    4143#include "../../vfs/vfs.h"
    4244#include <libfs.h>
     
    5658#include <align.h>
    5759#include <malloc.h>
     60#include <str.h>
    5861
    5962#define FAT_NODE(node)  ((node) ? (fat_node_t *) (node)->data : NULL)
     
    104107        node->dirty = false;
    105108        node->lastc_cached_valid = false;
    106         node->lastc_cached_value = FAT_CLST_LAST1;
     109        node->lastc_cached_value = 0;
    107110        node->currc_cached_valid = false;
    108111        node->currc_cached_bn = 0;
    109         node->currc_cached_value = FAT_CLST_LAST1;
     112        node->currc_cached_value = 0;
    110113}
    111114
     
    116119        fat_dentry_t *d;
    117120        int rc;
    118        
     121
    119122        assert(node->dirty);
    120123
    121124        bs = block_bb_get(node->idx->service_id);
    122        
     125
    123126        /* Read the block that contains the dentry of interest. */
    124127        rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
     
    136139                d->attr = FAT_ATTR_SUBDIR;
    137140        }
    138        
     141
    139142        /* TODO: update other fields? (e.g time fields) */
    140        
     143
    141144        b->dirty = true;                /* need to sync block */
    142145        rc = block_put(b);
     
    255258        fn->data = nodep;
    256259        nodep->bp = fn;
    257        
     260
    258261        *nodepp = nodep;
    259262        return EOK;
     
    291294         * We must instantiate the node from the file system.
    292295         */
    293        
     296
    294297        assert(idxp->pfc);
    295298
     
    309312
    310313        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
     314        if (FAT_IS_FAT32(bs)) {
     315                nodep->firstc = uint16_t_le2host(d->firstc_lo) |
     316                    (uint16_t_le2host(d->firstc_hi) << 16);
     317        } else
     318                nodep->firstc = uint16_t_le2host(d->firstc);
     319
    311320        if (d->attr & FAT_ATTR_SUBDIR) {
    312                 /* 
     321                /*
    313322                 * The only directory which does not have this bit set is the
    314323                 * root directory itself. The root directory node is handled
     
    316325                 */
    317326                nodep->type = FAT_DIRECTORY;
     327
    318328                /*
    319329                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    321331                 * size of the directory by walking the FAT.
    322332                 */
    323                 uint16_t clusters;
     333                uint32_t clusters;
    324334                rc = fat_clusters_get(&clusters, bs, idxp->service_id,
    325                     uint16_t_le2host(d->firstc));
     335                    nodep->firstc);
    326336                if (rc != EOK) {
    327337                        (void) block_put(b);
     
    334344                nodep->size = uint32_t_le2host(d->size);
    335345        }
    336         nodep->firstc = uint16_t_le2host(d->firstc);
     346
    337347        nodep->lnkcnt = 1;
    338348        nodep->refcnt = 1;
     
    363373int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    364374{
    365         fat_bs_t *bs;
    366375        fat_node_t *parentp = FAT_NODE(pfn);
    367         char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    368         unsigned i, j;
    369         unsigned blocks;
     376        char name[FAT_LFN_NAME_SIZE];
    370377        fat_dentry_t *d;
    371378        service_id_t service_id;
    372         block_t *b;
    373379        int rc;
    374380
     
    376382        service_id = parentp->idx->service_id;
    377383        fibril_mutex_unlock(&parentp->idx->lock);
    378 
    379         bs = block_bb_get(service_id);
    380         blocks = parentp->size / BPS(bs);
    381         for (i = 0; i < blocks; i++) {
    382                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    383                 if (rc != EOK)
    384                         return rc;
    385                 for (j = 0; j < DPS(bs); j++) {
    386                         d = ((fat_dentry_t *)b->data) + j;
    387                         switch (fat_classify_dentry(d)) {
    388                         case FAT_DENTRY_SKIP:
    389                         case FAT_DENTRY_FREE:
    390                                 continue;
    391                         case FAT_DENTRY_LAST:
    392                                 /* miss */
    393                                 rc = block_put(b);
    394                                 *rfn = NULL;
    395                                 return rc;
    396                         default:
    397                         case FAT_DENTRY_VALID:
    398                                 fat_dentry_name_get(d, name);
    399                                 break;
     384       
     385        fat_directory_t di;
     386        rc = fat_directory_open(parentp, &di);
     387        if (rc != EOK)
     388                return rc;
     389
     390        while (fat_directory_read(&di, name, &d) == EOK) {
     391                if (fat_dentry_namecmp(name, component) == 0) {
     392                        /* hit */
     393                        fat_node_t *nodep;
     394                        aoff64_t o = di.pos %
     395                            (BPS(di.bs) / sizeof(fat_dentry_t));
     396                        fat_idx_t *idx = fat_idx_get_by_pos(service_id,
     397                            parentp->firstc, di.bnum * DPS(di.bs) + o);
     398                        if (!idx) {
     399                                /*
     400                                 * Can happen if memory is low or if we
     401                                 * run out of 32-bit indices.
     402                                 */
     403                                rc = fat_directory_close(&di);
     404                                return (rc == EOK) ? ENOMEM : rc;
    400405                        }
    401                         if (fat_dentry_namecmp(name, component) == 0) {
    402                                 /* hit */
    403                                 fat_node_t *nodep;
    404                                 fat_idx_t *idx = fat_idx_get_by_pos(service_id,
    405                                     parentp->firstc, i * DPS(bs) + j);
    406                                 if (!idx) {
    407                                         /*
    408                                          * Can happen if memory is low or if we
    409                                          * run out of 32-bit indices.
    410                                          */
    411                                         rc = block_put(b);
    412                                         return (rc == EOK) ? ENOMEM : rc;
    413                                 }
    414                                 rc = fat_node_get_core(&nodep, idx);
    415                                 fibril_mutex_unlock(&idx->lock);
    416                                 if (rc != EOK) {
    417                                         (void) block_put(b);
    418                                         return rc;
    419                                 }
    420                                 *rfn = FS_NODE(nodep);
    421                                 rc = block_put(b);
    422                                 if (rc != EOK)
    423                                         (void) fat_node_put(*rfn);
     406                        rc = fat_node_get_core(&nodep, idx);
     407                        fibril_mutex_unlock(&idx->lock);
     408                        if (rc != EOK) {
     409                                (void) fat_directory_close(&di);
    424410                                return rc;
    425411                        }
    426                 }
    427                 rc = block_put(b);
    428                 if (rc != EOK)
     412                        *rfn = FS_NODE(nodep);
     413                        rc = fat_directory_close(&di);
     414                        if (rc != EOK)
     415                                (void) fat_node_put(*rfn);
    429416                        return rc;
    430         }
    431 
     417                } else {
     418                        rc = fat_directory_next(&di);
     419                        if (rc != EOK)
     420                                break;
     421                }
     422        }
     423        (void) fat_directory_close(&di);
    432424        *rfn = NULL;
    433425        return EOK;
     
    591583        fat_bs_t *bs;
    592584        block_t *b;
    593         unsigned i, j;
    594         unsigned blocks;
    595         fat_cluster_t mcl, lcl;
     585        fat_directory_t di;
     586        fat_dentry_t de;
    596587        int rc;
    597588
     
    607598        fibril_mutex_unlock(&childp->lock);
    608599
    609         if (!fat_dentry_name_verify(name)) {
    610                 /*
    611                  * Attempt to create unsupported name.
    612                  */
     600        if (!fat_valid_name(name))
    613601                return ENOTSUP;
    614         }
    615 
    616         /*
    617          * Get us an unused parent node's dentry or grow the parent and allocate
    618          * a new one.
    619          */
    620        
     602
    621603        fibril_mutex_lock(&parentp->idx->lock);
    622604        bs = block_bb_get(parentp->idx->service_id);
    623 
    624         blocks = parentp->size / BPS(bs);
    625 
    626         for (i = 0; i < blocks; i++) {
    627                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    628                 if (rc != EOK) {
    629                         fibril_mutex_unlock(&parentp->idx->lock);
    630                         return rc;
    631                 }
    632                 for (j = 0; j < DPS(bs); j++) {
    633                         d = ((fat_dentry_t *)b->data) + j;
    634                         switch (fat_classify_dentry(d)) {
    635                         case FAT_DENTRY_SKIP:
    636                         case FAT_DENTRY_VALID:
    637                                 /* skipping used and meta entries */
    638                                 continue;
    639                         case FAT_DENTRY_FREE:
    640                         case FAT_DENTRY_LAST:
    641                                 /* found an empty slot */
    642                                 goto hit;
    643                         }
    644                 }
    645                 rc = block_put(b);
    646                 if (rc != EOK) {
    647                         fibril_mutex_unlock(&parentp->idx->lock);
    648                         return rc;
    649                 }
    650         }
    651         j = 0;
    652        
    653         /*
    654          * We need to grow the parent in order to create a new unused dentry.
    655          */
    656         if (parentp->firstc == FAT_CLST_ROOT) {
    657                 /* Can't grow the root directory. */
    658                 fibril_mutex_unlock(&parentp->idx->lock);
    659                 return ENOSPC;
    660         }
    661         rc = fat_alloc_clusters(bs, parentp->idx->service_id, 1, &mcl, &lcl);
     605        rc = fat_directory_open(parentp, &di);
    662606        if (rc != EOK) {
    663607                fibril_mutex_unlock(&parentp->idx->lock);
    664608                return rc;
    665609        }
    666         rc = fat_zero_cluster(bs, parentp->idx->service_id, mcl);
    667         if (rc != EOK) {
    668                 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
    669                 fibril_mutex_unlock(&parentp->idx->lock);
    670                 return rc;
    671         }
    672         rc = fat_append_clusters(bs, parentp, mcl, lcl);
    673         if (rc != EOK) {
    674                 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
    675                 fibril_mutex_unlock(&parentp->idx->lock);
    676                 return rc;
    677         }
    678         parentp->size += BPS(bs) * SPC(bs);
    679         parentp->dirty = true;          /* need to sync node */
    680         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    681         if (rc != EOK) {
    682                 fibril_mutex_unlock(&parentp->idx->lock);
    683                 return rc;
    684         }
    685         d = (fat_dentry_t *)b->data;
    686 
    687 hit:
     610
    688611        /*
    689612         * At this point we only establish the link between the parent and the
     
    692615         * dentry data is kept in the child node structure.
    693616         */
    694         memset(d, 0, sizeof(fat_dentry_t));
    695         fat_dentry_name_set(d, name);
    696         b->dirty = true;                /* need to sync block */
    697         rc = block_put(b);
     617        memset(&de, 0, sizeof(fat_dentry_t));
     618
     619        rc = fat_directory_write(&di, name, &de);
     620        if (rc != EOK) {
     621                (void) fat_directory_close(&di);
     622                fibril_mutex_unlock(&parentp->idx->lock);
     623                return rc;
     624        }
     625        rc = fat_directory_close(&di);
     626        if (rc != EOK) {
     627                fibril_mutex_unlock(&parentp->idx->lock);
     628                return rc;
     629        }
     630
    698631        fibril_mutex_unlock(&parentp->idx->lock);
    699         if (rc != EOK)
    700                 return rc;
    701632
    702633        fibril_mutex_lock(&childp->idx->lock);
    703        
     634
    704635        if (childp->type == FAT_DIRECTORY) {
    705636                /*
     
    720651                d = (fat_dentry_t *) b->data;
    721652                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    722                     (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
     653                    (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
    723654                        memset(d, 0, sizeof(fat_dentry_t));
    724655                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    730661                d++;
    731662                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    732                     (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
     663                    (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
    733664                        memset(d, 0, sizeof(fat_dentry_t));
    734665                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    735666                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    736667                        d->attr = FAT_ATTR_SUBDIR;
    737                         d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    738                             host2uint16_t_le(FAT_CLST_RES0) :
     668                        d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
     669                            host2uint16_t_le(FAT_CLST_ROOTPAR) :
    739670                            host2uint16_t_le(parentp->firstc);
    740671                        /* TODO: initialize also the date/time members. */
     
    750681
    751682        childp->idx->pfc = parentp->firstc;
    752         childp->idx->pdi = i * DPS(bs) + j;
     683        childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
    753684        fibril_mutex_unlock(&childp->idx->lock);
    754685
     
    770701        fat_node_t *parentp = FAT_NODE(pfn);
    771702        fat_node_t *childp = FAT_NODE(cfn);
    772         fat_bs_t *bs;
    773         fat_dentry_t *d;
    774         block_t *b;
    775703        bool has_children;
    776704        int rc;
     
    778706        if (!parentp)
    779707                return EBUSY;
    780        
     708
    781709        rc = fat_has_children(&has_children, cfn);
    782710        if (rc != EOK)
     
    789717        assert(childp->lnkcnt == 1);
    790718        fibril_mutex_lock(&childp->idx->lock);
    791         bs = block_bb_get(childp->idx->service_id);
    792 
    793         rc = _fat_block_get(&b, bs, childp->idx->service_id, childp->idx->pfc,
    794             NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    795             BLOCK_FLAGS_NONE);
    796         if (rc != EOK)
     719       
     720        fat_directory_t di;
     721        rc = fat_directory_open(parentp, &di);
     722        if (rc != EOK)
    797723                goto error;
    798         d = (fat_dentry_t *)b->data +
    799             (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t)));
    800         /* mark the dentry as not-currently-used */
    801         d->name[0] = FAT_DENTRY_ERASED;
    802         b->dirty = true;                /* need to sync block */
    803         rc = block_put(b);
     724        rc = fat_directory_seek(&di, childp->idx->pdi);
     725        if (rc != EOK)
     726                goto error;
     727        rc = fat_directory_erase(&di);
     728        if (rc != EOK)
     729                goto error;
     730        rc = fat_directory_close(&di);
    804731        if (rc != EOK)
    805732                goto error;
     
    820747
    821748error:
    822         fibril_mutex_unlock(&parentp->idx->lock);
     749        (void) fat_directory_close(&di);
     750        fibril_mutex_unlock(&childp->idx->lock);
    823751        fibril_mutex_unlock(&childp->lock);
    824         fibril_mutex_unlock(&childp->idx->lock);
     752        fibril_mutex_unlock(&parentp->lock);
    825753        return rc;
    826754}
     
    839767                return EOK;
    840768        }
    841        
     769
    842770        fibril_mutex_lock(&nodep->idx->lock);
    843771        bs = block_bb_get(nodep->idx->service_id);
     
    847775        for (i = 0; i < blocks; i++) {
    848776                fat_dentry_t *d;
    849        
     777
    850778                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    851779                if (rc != EOK) {
     
    875803                if (rc != EOK) {
    876804                        fibril_mutex_unlock(&nodep->idx->lock);
    877                         return rc;     
     805                        return rc;
    878806                }
    879807        }
     
    946874        fat_bs_t *bs;
    947875        int rc;
    948        
     876
    949877        /* Check for option enabling write through. */
    950878        if (str_cmp(opts, "wtcache") == 0)
     
    1003931                return ENOMEM;
    1004932        }
     933
    1005934        fs_node_initialize(rfn);
    1006935        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     
    1027956
    1028957        rootp->type = FAT_DIRECTORY;
    1029         rootp->firstc = FAT_CLST_ROOT;
     958        rootp->firstc = FAT_ROOT_CLST(bs);
    1030959        rootp->refcnt = 1;
    1031960        rootp->lnkcnt = 0;      /* FS root is not linked */
    1032         rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     961
     962        if (FAT_IS_FAT32(bs)) {
     963                uint32_t clusters;
     964                rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
     965                if (rc != EOK) {
     966                        free(rfn);
     967                        free(rootp);
     968                        (void) block_cache_fini(service_id);
     969                        block_fini(service_id);
     970                        fat_idx_fini_by_service_id(service_id);
     971                        return ENOTSUP;
     972                }
     973                rootp->size = BPS(bs) * SPC(bs) * clusters;
     974        } else
     975                rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     976
    1033977        rootp->idx = ridxp;
    1034978        ridxp->nodep = rootp;
    1035979        rootp->bp = rfn;
    1036980        rfn->data = rootp;
    1037        
     981
    1038982        fibril_mutex_unlock(&ridxp->lock);
    1039983
     
    10641008                return EBUSY;
    10651009        }
    1066        
     1010
    10671011        /*
    10681012         * Put the root node and force it to the FAT free node list.
     
    11411085                }
    11421086        } else {
    1143                 unsigned bnum;
    11441087                aoff64_t spos = pos;
    1145                 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     1088                char name[FAT_LFN_NAME_SIZE];
    11461089                fat_dentry_t *d;
    11471090
     
    11501093                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    11511094
    1152                 /*
    1153                  * Our strategy for readdir() is to use the position pointer as
    1154                  * an index into the array of all dentries. On entry, it points
    1155                  * to the first unread dentry. If we skip any dentries, we bump
    1156                  * the position pointer accordingly.
    1157                  */
    1158                 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs);
    1159                 while (bnum < nodep->size / BPS(bs)) {
    1160                         aoff64_t o;
    1161 
    1162                         rc = fat_block_get(&b, bs, nodep, bnum,
    1163                             BLOCK_FLAGS_NONE);
    1164                         if (rc != EOK)
    1165                                 goto err;
    1166                         for (o = pos % (BPS(bs) / sizeof(fat_dentry_t));
    1167                             o < BPS(bs) / sizeof(fat_dentry_t);
    1168                             o++, pos++) {
    1169                                 d = ((fat_dentry_t *)b->data) + o;
    1170                                 switch (fat_classify_dentry(d)) {
    1171                                 case FAT_DENTRY_SKIP:
    1172                                 case FAT_DENTRY_FREE:
    1173                                         continue;
    1174                                 case FAT_DENTRY_LAST:
    1175                                         rc = block_put(b);
    1176                                         if (rc != EOK)
    1177                                                 goto err;
    1178                                         goto miss;
    1179                                 default:
    1180                                 case FAT_DENTRY_VALID:
    1181                                         fat_dentry_name_get(d, name);
    1182                                         rc = block_put(b);
    1183                                         if (rc != EOK)
    1184                                                 goto err;
    1185                                         goto hit;
    1186                                 }
    1187                         }
    1188                         rc = block_put(b);
    1189                         if (rc != EOK)
    1190                                 goto err;
    1191                         bnum++;
    1192                 }
     1095                fat_directory_t di;
     1096                rc = fat_directory_open(nodep, &di);
     1097                if (rc != EOK)
     1098                        goto err;
     1099                rc = fat_directory_seek(&di, pos);
     1100                if (rc != EOK) {
     1101                        (void) fat_directory_close(&di);
     1102                        goto err;
     1103                }
     1104
     1105                rc = fat_directory_read(&di, name, &d);
     1106                if (rc == EOK)
     1107                        goto hit;
     1108                if (rc == ENOENT)
     1109                        goto miss;
     1110
     1111err:
     1112                (void) fat_node_put(fn);
     1113                async_answer_0(callid, rc);
     1114                return rc;
     1115
    11931116miss:
     1117                rc = fat_directory_close(&di);
     1118                if (rc != EOK)
     1119                        goto err;
    11941120                rc = fat_node_put(fn);
    11951121                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     
    11971123                return rc != EOK ? rc : ENOENT;
    11981124
    1199 err:
    1200                 (void) fat_node_put(fn);
    1201                 async_answer_0(callid, rc);
    1202                 return rc;
    1203 
    12041125hit:
    1205                 (void) async_data_read_finalize(callid, name, str_size(name) + 1);
     1126                pos = di.pos;
     1127                rc = fat_directory_close(&di);
     1128                if (rc != EOK)
     1129                        goto err;
     1130                (void) async_data_read_finalize(callid, name,
     1131                    str_size(name) + 1);
    12061132                bytes = (pos - spos) + 1;
    12071133        }
     
    12311157                return ENOENT;
    12321158        nodep = FAT_NODE(fn);
    1233        
     1159
    12341160        ipc_callid_t callid;
    12351161        size_t len;
     
    12471173         * but this one greatly simplifies fat_write(). Note that we can afford
    12481174         * to do this because the client must be ready to handle the return
    1249          * value signalizing a smaller number of bytes written. 
    1250          */ 
     1175         * value signalizing a smaller number of bytes written.
     1176         */
    12511177        bytes = min(len, BPS(bs) - pos % BPS(bs));
    12521178        if (bytes == BPS(bs))
    12531179                flags |= BLOCK_FLAGS_NOREAD;
    1254        
     1180
    12551181        boundary = ROUND_UP(nodep->size, BPC(bs));
    12561182        if (pos < boundary) {
     
    12951221                 */
    12961222                unsigned nclsts;
    1297                 fat_cluster_t mcl, lcl; 
    1298  
     1223                fat_cluster_t mcl, lcl;
     1224
    12991225                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    13001226                /* create an independent chain of nclsts clusters in all FATs */
     
    13801306                nodep->size = size;
    13811307                nodep->dirty = true;            /* need to sync node */
    1382                 rc = EOK;       
     1308                rc = EOK;
    13831309        } else {
    13841310                /*
     
    14011327                nodep->size = size;
    14021328                nodep->dirty = true;            /* need to sync node */
    1403                 rc = EOK;       
     1329                rc = EOK;
    14041330        }
    14051331out:
     
    14441370        if (!fn)
    14451371                return ENOENT;
    1446        
     1372
    14471373        fat_node_t *nodep = FAT_NODE(fn);
    1448        
     1374
    14491375        nodep->dirty = true;
    14501376        rc = fat_node_sync(nodep);
    1451        
     1377
    14521378        fat_node_put(fn);
    14531379        return rc;
Note: See TracChangeset for help on using the changeset viewer.