Changeset 8cc4ddb in mainline
- Timestamp:
- 2011-08-28T21:16:54Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- 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. - Files:
-
- 21 added
- 46 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
abi/include/syscall.h
r1a5b252 r8cc4ddb 89 89 SYS_UNREGISTER_IRQ, 90 90 91 SYS_SYSINFO_GET_ TAG,91 SYS_SYSINFO_GET_VAL_TYPE, 92 92 SYS_SYSINFO_GET_VALUE, 93 93 SYS_SYSINFO_GET_DATA_SIZE, -
abi/include/sysinfo.h
r1a5b252 r8cc4ddb 37 37 #define ABI_SYSINFO_H_ 38 38 39 #include <abi/proc/task.h> 40 #include <abi/proc/thread.h> 41 39 42 /** Number of load components */ 40 43 #define LOAD_STEPS 3 … … 44 47 #define EXC_NAME_BUFLEN 20 45 48 46 /** Thread states */ 49 /** Item value type 50 * 51 */ 47 52 typedef 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; 63 59 64 60 /** Statistics about a single CPU -
boot/Makefile.common
r1a5b252 r8cc4ddb 102 102 $(USPACE_PATH)/srv/fs/tmpfs/tmpfs \ 103 103 $(USPACE_PATH)/srv/fs/fat/fat \ 104 $(USPACE_PATH)/srv/fs/exfat/exfat \ 104 105 $(USPACE_PATH)/srv/fs/ext2fs/ext2fs \ 105 106 $(USPACE_PATH)/srv/taskmon/taskmon \ -
boot/generic/src/printf_core.c
r1a5b252 r8cc4ddb 70 70 */ 71 71 #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 }) 72 91 73 92 /** Enumeration of possible arguments types. … … 171 190 } 172 191 173 return (int) (counter + 1);192 return (int) (counter); 174 193 } 175 194 … … 698 717 size_t size; 699 718 uint64_t number; 719 700 720 switch (qualifier) { 701 721 case PrintfQualifierByte: 702 722 size = sizeof(unsigned char); 703 number = (uint64_t) va_arg(ap, unsigned int);723 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 704 724 break; 705 725 case PrintfQualifierShort: 706 726 size = sizeof(unsigned short); 707 number = (uint64_t) va_arg(ap, unsigned int);727 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 708 728 break; 709 729 case PrintfQualifierInt: 710 730 size = sizeof(unsigned int); 711 number = (uint64_t) va_arg(ap, unsigned int);731 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 712 732 break; 713 733 case PrintfQualifierLong: 714 734 size = sizeof(unsigned long); 715 number = (uint64_t) va_arg(ap, unsigned long);735 number = PRINTF_GET_INT_ARGUMENT(long, ap, flags); 716 736 break; 717 737 case PrintfQualifierLongLong: 718 738 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); 720 740 break; 721 741 case PrintfQualifierPointer: … … 732 752 counter = -counter; 733 753 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 }750 754 } 751 755 -
kernel/arch/amd64/include/asm.h
r1a5b252 r8cc4ddb 41 41 #include <trace.h> 42 42 43 #define IO_SPACE_BOUNDARY ((void *) (64 * 1024)) 44 43 45 /** Return base address of current stack. 44 46 * … … 77 79 } 78 80 79 #define IO_SPACE_BOUNDARY ((void *) (64 * 1024))80 81 81 /** Byte from port 82 82 * … … 91 91 if (port < (ioport8_t *) IO_SPACE_BOUNDARY) { 92 92 uint8_t val; 93 93 94 asm volatile ( 94 95 "inb %w[port], %b[val]\n" … … 96 97 : [port] "d" (port) 97 98 ); 99 98 100 return val; 99 } else {101 } else 100 102 return (uint8_t) *port; 101 }102 103 } 103 104 … … 114 115 if (port < (ioport16_t *) IO_SPACE_BOUNDARY) { 115 116 uint16_t val; 117 116 118 asm volatile ( 117 119 "inw %w[port], %w[val]\n" … … 119 121 : [port] "d" (port) 120 122 ); 123 121 124 return val; 122 } else {125 } else 123 126 return (uint16_t) *port; 124 }125 127 } 126 128 … … 137 139 if (port < (ioport32_t *) IO_SPACE_BOUNDARY) { 138 140 uint32_t val; 141 139 142 asm volatile ( 140 143 "inl %w[port], %[val]\n" … … 142 145 : [port] "d" (port) 143 146 ); 147 144 148 return val; 145 } else {149 } else 146 150 return (uint32_t) *port; 147 }148 151 } 149 152 … … 163 166 :: [val] "a" (val), [port] "d" (port) 164 167 ); 165 } else {168 } else 166 169 *port = val; 167 }168 170 } 169 171 … … 183 185 :: [val] "a" (val), [port] "d" (port) 184 186 ); 185 } else {187 } else 186 188 *port = val; 187 }188 189 } 189 190 … … 203 204 :: [val] "a" (val), [port] "d" (port) 204 205 ); 205 } else {206 } else 206 207 *port = val; 207 }208 208 } 209 209 -
kernel/arch/ia32/include/asm.h
r1a5b252 r8cc4ddb 118 118 :: [val] "a" (val), [port] "d" (port) 119 119 ); 120 } else {120 } else 121 121 *port = val; 122 }123 122 } 124 123 … … 138 137 :: [val] "a" (val), [port] "d" (port) 139 138 ); 140 } else {139 } else 141 140 *port = val; 142 }143 141 } 144 142 … … 158 156 :: [val] "a" (val), [port] "d" (port) 159 157 ); 160 } else {158 } else 161 159 *port = val; 162 }163 160 } 164 161 … … 175 172 if (((void *)port) < IO_SPACE_BOUNDARY) { 176 173 uint8_t val; 174 177 175 asm volatile ( 178 176 "inb %w[port], %b[val]\n" … … 180 178 : [port] "d" (port) 181 179 ); 180 182 181 return val; 183 } else {182 } else 184 183 return (uint8_t) *port; 185 }186 184 } 187 185 … … 198 196 if (((void *)port) < IO_SPACE_BOUNDARY) { 199 197 uint16_t val; 198 200 199 asm volatile ( 201 200 "inw %w[port], %w[val]\n" … … 203 202 : [port] "d" (port) 204 203 ); 204 205 205 return val; 206 } else {206 } else 207 207 return (uint16_t) *port; 208 }209 208 } 210 209 … … 221 220 if (((void *)port) < IO_SPACE_BOUNDARY) { 222 221 uint32_t val; 222 223 223 asm volatile ( 224 224 "inl %w[port], %[val]\n" … … 226 226 : [port] "d" (port) 227 227 ); 228 228 229 return val; 229 } else {230 } else 230 231 return (uint32_t) *port; 231 }232 232 } 233 233 -
kernel/generic/include/ipc/ipc.h
r1a5b252 r8cc4ddb 36 36 #define KERN_IPC_H_ 37 37 38 #include <abi/ipc/ipc.h>39 38 #include <synch/spinlock.h> 40 39 #include <synch/mutex.h> 41 40 #include <synch/waitq.h> 41 #include <abi/ipc/ipc.h> 42 #include <abi/proc/task.h> 42 43 #include <typedefs.h> 43 44 44 #define IPC_MAX_PHONES 3245 #define IPC_MAX_PHONES 64 45 46 46 47 struct answerbox; -
kernel/generic/include/sysinfo/sysinfo.h
r1a5b252 r8cc4ddb 38 38 #include <typedefs.h> 39 39 #include <str.h> 40 #include <abi/sysinfo.h> 40 41 41 42 /** Framebuffer info exported flags */ 42 43 extern bool fb_exported; 43 44 /** Item value type45 *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;54 44 55 45 /** Subtree type … … 145 135 extern void sysinfo_dump(sysinfo_item_t *); 146 136 147 extern sysarg_t sys_sysinfo_get_ tag(void *, size_t);137 extern sysarg_t sys_sysinfo_get_val_type(void *, size_t); 148 138 extern sysarg_t sys_sysinfo_get_value(void *, size_t, void *); 149 139 extern sysarg_t sys_sysinfo_get_data_size(void *, size_t, void *); -
kernel/generic/include/typedefs.h
r1a5b252 r8cc4ddb 39 39 #include <arch/common.h> 40 40 #include <arch/types.h> 41 #include <abi/bool.h> 41 42 42 43 #define NULL ((void *) 0) … … 61 62 typedef void (* function)(); 62 63 63 typedef uint8_t bool;64 typedef uint64_t thread_id_t;65 typedef uint64_t task_id_t;66 64 typedef uint32_t container_id_t; 67 65 -
kernel/generic/src/mm/slab.c
r1a5b252 r8cc4ddb 180 180 unsigned int flags) 181 181 { 182 183 184 182 size_t zone = 0; 185 183 -
kernel/generic/src/printf/printf_core.c
r1a5b252 r8cc4ddb 75 75 #define PRINT_NUMBER_BUFFER_SIZE (64 + 5) 76 76 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 77 96 /** Enumeration of possible arguments types. 78 97 */ … … 207 226 } 208 227 209 return (int) (counter + 1);228 return (int) (counter); 210 229 } 211 230 … … 245 264 } 246 265 247 return (int) (counter + 1);266 return (int) (counter); 248 267 } 249 268 … … 832 851 size_t size; 833 852 uint64_t number; 853 834 854 switch (qualifier) { 835 855 case PrintfQualifierByte: 836 856 size = sizeof(unsigned char); 837 number = (uint64_t) va_arg(ap, unsigned int);857 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 838 858 break; 839 859 case PrintfQualifierShort: 840 860 size = sizeof(unsigned short); 841 number = (uint64_t) va_arg(ap, unsigned int);861 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 842 862 break; 843 863 case PrintfQualifierInt: 844 864 size = sizeof(unsigned int); 845 number = (uint64_t) va_arg(ap, unsigned int);865 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 846 866 break; 847 867 case PrintfQualifierLong: 848 868 size = sizeof(unsigned long); 849 number = (uint64_t) va_arg(ap, unsigned long);869 number = PRINTF_GET_INT_ARGUMENT(long, ap, flags); 850 870 break; 851 871 case PrintfQualifierLongLong: 852 872 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); 854 874 break; 855 875 case PrintfQualifierPointer: … … 866 886 counter = -counter; 867 887 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 }884 888 } 885 889 -
kernel/generic/src/syscall/syscall.c
r1a5b252 r8cc4ddb 181 181 182 182 /* Sysinfo syscalls. */ 183 (syshandler_t) sys_sysinfo_get_ tag,183 (syshandler_t) sys_sysinfo_get_val_type, 184 184 (syshandler_t) sys_sysinfo_get_value, 185 185 (syshandler_t) sys_sysinfo_get_data_size, -
kernel/generic/src/sysinfo/sysinfo.c
r1a5b252 r8cc4ddb 661 661 * 662 662 */ 663 sysarg_t sys_sysinfo_get_ tag(void *path_ptr, size_t path_size)663 sysarg_t sys_sysinfo_get_val_type(void *path_ptr, size_t path_size) 664 664 { 665 665 /* -
kernel/test/print/print2.c
r1a5b252 r8cc4ddb 44 44 TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5); 45 45 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 46 50 TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n"); 47 51 TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n"); -
uspace/Makefile
r1a5b252 r8cc4ddb 79 79 srv/bd/part/guid_part \ 80 80 srv/bd/part/mbr_part \ 81 srv/fs/exfat \ 81 82 srv/fs/fat \ 82 83 srv/fs/tmpfs \ … … 163 164 lib/block \ 164 165 lib/clui \ 166 lib/fmtutil \ 165 167 lib/scsi \ 166 168 lib/softint \ -
uspace/Makefile.common
r1a5b252 r8cc4ddb 108 108 LIBIMGMAP_PREFIX = $(LIB_PREFIX)/imgmap 109 109 LIBCLUI_PREFIX = $(LIB_PREFIX)/clui 110 LIBFMTUTIL_PREFIX = $(LIB_PREFIX)/fmtutil 110 111 111 112 LIBEXT2_PREFIX = $(LIB_PREFIX)/ext2 -
uspace/app/bdsh/Makefile
r1a5b252 r8cc4ddb 29 29 30 30 USPACE_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 31 LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBCLUI_PREFIX)/libclui.a \ 32 $(LIBFMTUTIL_PREFIX)/libfmtutil.a 33 EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBCLUI_PREFIX) \ 34 -I$(LIBFMTUTIL_PREFIX) -I. -Icmds/ -Icmds/builtins -Icmds/modules 34 35 BINARY = bdsh 35 36 -
uspace/app/bdsh/cmds/modules/help/help.c
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2008 Tim Post 3 * Copyright (c) 2011 Martin Sucha 3 4 * All rights reserved. 4 5 * … … 30 31 #include <stdlib.h> 31 32 #include <str.h> 33 #include <fmtutil.h> 32 34 33 35 #include "config.h" … … 128 130 static void help_survival(void) 129 131 { 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 " 133 136 "the primary user interface to HelenOS. Bdsh allows you to enter " 134 137 "commands and supports history (Up, Down arrow keys), " 135 138 "line editing (Left Arrow, Right Arrow, Home, End, Backspace), " 136 139 "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 " 140 143 "'help commands' [Enter] to see the list of Bdsh builtin commands. " 141 144 "Other commands are external executables located in the /app and " 142 145 "/srv directories. Type 'ls /app' [Enter] and 'ls /srv' [Enter] " 143 146 "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. " 150 153 "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); 152 156 } 153 157 -
uspace/app/bdsh/compl.c
r1a5b252 r8cc4ddb 90 90 { 91 91 compl_t *cs = NULL; 92 size_t pref_size;93 92 char *stext = NULL; 94 93 char *prefix = NULL; 95 94 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; 96 104 char *rpath_sep; 97 105 static const char *dirlist_arg[] = { ".", NULL }; 98 int retval;99 106 tokenizer_t tok; 100 token_t tokens[WORD_MAX]; 101 unsigned int current_token; 107 ssize_t current_token; 102 108 size_t tokens_length; 103 109 104 110 cs = calloc(1, sizeof(compl_t)); 105 111 if (!cs) { … … 107 113 goto error; 108 114 } 109 115 110 116 /* Convert text buffer to string */ 111 117 stext = wstr_to_astr(text); … … 127 133 128 134 /* 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++) { 130 137 token_t *t = &tokens[current_token]; 131 138 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 133 142 * after it 134 143 */ … … 138 147 } 139 148 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)) 141 153 *cstart = tokens[current_token].char_start; 142 } 143 else { 154 else 144 155 *cstart = pos; 145 }146 147 /* Extract the prefix being completed156 157 /* 158 * Extract the prefix being completed 148 159 * XXX: handle strings, etc. 149 160 */ … … 154 165 goto error; 155 166 } 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 } 159 173 160 174 /* … … 165 179 166 180 /* 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)) 169 183 prev_token--; 170 } 171 184 172 185 /* 173 186 * It is a command if it is the first token or if it immediately 174 187 * follows a pipe token. 175 188 */ 176 if ( prev_token == -1 || tokens[prev_token].type == TOKTYPE_SPACE)189 if ((prev_token < 0) || (tokens[prev_token].type == TOKTYPE_SPACE)) 177 190 cs->is_command = true; 178 191 else … … 249 262 if (cs != NULL) 250 263 free(cs); 264 if (tokens != NULL) 265 free(tokens); 251 266 252 267 return retval; -
uspace/app/bdsh/input.c
r1a5b252 r8cc4ddb 67 67 int process_input(cliuser_t *usr) 68 68 { 69 token_t *tokens = calloc(WORD_MAX, sizeof(token_t)); 70 if (tokens == NULL) 71 return ENOMEM; 72 69 73 char *cmd[WORD_MAX]; 70 token_t tokens_space[WORD_MAX];71 token_t *tokens = tokens_space;72 74 int rc = 0; 73 75 tokenizer_t tok; … … 77 79 char *redir_to = NULL; 78 80 79 if (NULL == usr->line) 81 if (usr->line == NULL) { 82 free(tokens); 80 83 return CL_EFAIL; 84 } 81 85 82 86 rc = tok_init(&tok, usr->line, tokens, WORD_MAX); … … 209 213 } 210 214 tok_fini(&tok); 215 free(tokens); 211 216 212 217 return rc; -
uspace/app/mkfat/fat.h
r1a5b252 r8cc4ddb 38 38 #define BS_BLOCK 0 39 39 #define BS_SIZE 512 40 #define DIRENT_SIZE 32 40 41 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) 42 50 43 51 typedef struct fat_bs { -
uspace/app/mkfat/mkfat.c
r1a5b252 r8cc4ddb 35 35 * @brief Tool for creating new FAT file systems. 36 36 * 37 * Currently we can only create 16-bit FAT.37 * Currently we can create 12/16/32-bit FAT. 38 38 */ 39 39 … … 55 55 #define div_round_up(a, b) (((a) + (b) - 1) / (b)) 56 56 57 /** Predefinedfile-system parameters */57 /** Default file-system parameters */ 58 58 enum { 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 */ 64 64 }; 65 65 66 66 /** Configurable file-system parameters */ 67 67 typedef struct fat_cfg { 68 int fat_type; /* FAT12 = 12, FAT16 = 16, FAT32 = 32 */ 69 size_t sector_size; 68 70 uint32_t total_sectors; 69 71 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; 71 80 } fat_cfg_t; 72 81 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 82 82 static void syntax_print(void); 83 83 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); 84 static int fat_params_compute(struct fat_cfg *cfg); 85 static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id); 86 static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs); 89 87 90 88 int main(int argc, char **argv) 91 89 { 92 struct fat_params par;93 90 struct fat_cfg cfg; 94 91 … … 96 93 char *dev_path; 97 94 service_id_t service_id; 98 size_t block_size;99 95 char *endptr; 100 96 aoff64_t dev_nblocks; 101 97 98 cfg.sector_size = default_sector_size; 99 cfg.sectors_per_cluster = default_sectors_per_cluster; 100 cfg.fat_count = default_fat_count; 102 101 cfg.total_sectors = 0; 103 102 cfg.addt_res_sectors = 0; 104 103 cfg.root_ent_max = 128; 104 cfg.fat_type = FAT16; 105 105 106 106 if (argc < 2) { … … 111 111 112 112 --argc; ++argv; 113 114 113 if (str_cmp(*argv, "--size") == 0) { 115 114 --argc; ++argv; … … 130 129 } 131 130 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 132 149 if (argc != 1) { 133 150 printf(NAME ": Error, unexpected argument.\n"); … … 137 154 138 155 dev_path = *argv; 156 printf("Device: %s\n", dev_path); 139 157 140 158 rc = loc_service_get_id(dev_path, &service_id, 0); … … 150 168 } 151 169 152 rc = block_get_bsize(service_id, & block_size);170 rc = block_get_bsize(service_id, &cfg.sector_size); 153 171 if (rc != EOK) { 154 172 printf(NAME ": Error determining device block size.\n"); … … 162 180 printf(NAME ": Block device has %" PRIuOFF64 " blocks.\n", 163 181 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; 170 184 } 171 185 … … 175 189 } 176 190 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); 180 199 if (rc != EOK) { 181 200 printf(NAME ": Invalid file-system parameters.\n"); … … 183 202 } 184 203 185 rc = fat_blocks_write(& par, service_id);204 rc = fat_blocks_write(&cfg, service_id); 186 205 if (rc != EOK) { 187 206 printf(NAME ": Error writing device.\n"); … … 197 216 static void syntax_print(void) 198 217 { 199 printf("syntax: mkfat [--size < num_blocks>] <device_name>\n");218 printf("syntax: mkfat [--size <sectors>] [--type 12|16|32] <device_name>\n"); 200 219 } 201 220 … … 205 224 * file system params. 206 225 */ 207 static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)226 static int fat_params_compute(struct fat_cfg *cfg) 208 227 { 209 228 uint32_t fat_bytes; … … 211 230 212 231 /* 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); 231 258 232 259 return EOK; … … 234 261 235 262 /** Create file system with the given parameters. */ 236 static int fat_blocks_write(struct fat_ params const *par, service_id_t service_id)263 static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id) 237 264 { 238 265 aoff64_t addr; … … 243 270 struct fat_bs bs; 244 271 245 fat_bootsec_create( par, &bs);272 fat_bootsec_create(cfg, &bs); 246 273 247 274 rc = block_write_direct(service_id, BS_BLOCK, 1, &bs); … … 251 278 addr = BS_BLOCK + 1; 252 279 253 buffer = calloc( sector_size, 1);280 buffer = calloc(cfg->sector_size, 1); 254 281 if (buffer == NULL) 255 282 return ENOMEM; 283 memset(buffer, 0, cfg->sector_size); 256 284 257 285 /* Reserved sectors */ 258 for (i = 0; i < par->reserved_sectors - 1; ++i) {286 for (i = 0; i < cfg->reserved_sectors - 1; ++i) { 259 287 rc = block_write_direct(service_id, addr, 1, buffer); 260 288 if (rc != EOK) … … 265 293 266 294 /* File allocation tables */ 267 for (i = 0; i < fat_count; ++i) {295 for (i = 0; i < cfg->fat_count; ++i) { 268 296 printf("Writing allocation table %d.\n", i + 1); 269 297 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); 272 300 if (j == 0) { 273 buffer[0] = media_descriptor;301 buffer[0] = default_media_descriptor; 274 302 buffer[1] = 0xFF; 275 303 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 } 277 317 } 278 318 … … 285 325 } 286 326 327 /* Root directory */ 287 328 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 } 298 347 } 299 348 … … 304 353 305 354 /** Construct boot sector with the given parameters. */ 306 static void fat_bootsec_create(struct fat_ params const *par, struct fat_bs *bs)355 static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs) 307 356 { 308 357 memset(bs, 0, sizeof(*bs)); … … 315 364 316 365 /* 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; 330 381 bs->sec_per_track = host2uint16_t_le(63); 382 bs->signature = host2uint16_t_be(0x55AA); 331 383 bs->headcnt = host2uint16_t_le(6); 332 384 bs->hidden_sec = host2uint32_t_le(0); 333 385 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 } 347 406 } 348 407 -
uspace/app/sysinfo/sysinfo.c
r1a5b252 r8cc4ddb 51 51 int rc; 52 52 char *ipath; 53 sysinfo_item_ tag_t tag;53 sysinfo_item_val_type_t tag; 54 54 55 55 if (argc != 2) { … … 60 60 ipath = argv[1]; 61 61 62 tag = sysinfo_get_ tag(ipath);62 tag = sysinfo_get_val_type(ipath); 63 63 64 64 /* Silence warning */ … … 75 75 case SYSINFO_VAL_DATA: 76 76 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; 77 82 break; 78 83 } -
uspace/app/tester/print/print2.c
r1a5b252 r8cc4ddb 45 45 TPRINTF("Real output: [%d] [%3.2d] [%-3.2d] [%2.3d] [%-2.3d]\n\n", -1, -2, -3, -4, -5); 46 46 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 47 51 TPRINTF("Testing printf(\"%%#x %%5.3#x %%-5.3#x %%3.5#x %%-3.5#x\", 17, 18, 19, 20, 21):\n"); 48 52 TPRINTF("Expected output: [0x11] [0x012] [0x013] [0x00014] [0x00015]\n"); -
uspace/app/tester/stdio/stdio1.c
r1a5b252 r8cc4ddb 39 39 { 40 40 FILE *file; 41 const char *file_name = "/ readme";41 const char *file_name = "/textdemo"; 42 42 43 43 TPRINTF("Open file \"%s\"...", file_name); -
uspace/app/trace/syscalls.c
r1a5b252 r8cc4ddb 75 75 [SYS_UNREGISTER_IRQ] = { "unregister_irq", 2, V_ERRNO }, 76 76 77 [SYS_SYSINFO_GET_ TAG] = { "sysinfo_get_tag", 2, V_INTEGER },77 [SYS_SYSINFO_GET_VAL_TYPE] = { "sysinfo_get_val_type", 2, V_INTEGER }, 78 78 [SYS_SYSINFO_GET_VALUE] = { "sysinfo_get_value", 3, V_ERRNO }, 79 79 [SYS_SYSINFO_GET_DATA_SIZE] = { "sysinfo_get_data_size", 3, V_ERRNO }, -
uspace/dist/src/sysel/demos/htxtfile.sy
r1a5b252 r8cc4ddb 35 35 var out_file : TextFile; 36 36 37 name = "/ readme";37 name = "/textdemo"; 38 38 39 39 in_file = new TextFile(); -
uspace/lib/c/arch/ia32/include/ddi.h
r1a5b252 r8cc4ddb 43 43 if (port < (ioport8_t *) IO_SPACE_BOUNDARY) { 44 44 uint8_t val; 45 45 46 asm volatile ( 46 47 "inb %w[port], %b[val]\n" … … 48 49 : [port] "d" (port) 49 50 ); 51 50 52 return val; 51 } else {53 } else 52 54 return (uint8_t) *port; 53 }54 55 } 55 56 … … 58 59 if (port < (ioport16_t *) IO_SPACE_BOUNDARY) { 59 60 uint16_t val; 61 60 62 asm volatile ( 61 63 "inw %w[port], %w[val]\n" … … 63 65 : [port] "d" (port) 64 66 ); 67 65 68 return val; 66 } else {69 } else 67 70 return (uint16_t) *port; 68 }69 71 } 70 72 … … 73 75 if (port < (ioport32_t *) IO_SPACE_BOUNDARY) { 74 76 uint32_t val; 77 75 78 asm volatile ( 76 79 "inl %w[port], %[val]\n" … … 78 81 : [port] "d" (port) 79 82 ); 83 80 84 return val; 81 } else {85 } else 82 86 return (uint32_t) *port; 83 }84 87 } 85 88 … … 91 94 :: [val] "a" (val), [port] "d" (port) 92 95 ); 93 } else {96 } else 94 97 *port = val; 95 }96 98 } 97 99 … … 103 105 :: [val] "a" (val), [port] "d" (port) 104 106 ); 105 } else {107 } else 106 108 *port = val; 107 }108 109 } 109 110 … … 115 116 :: [val] "a" (val), [port] "d" (port) 116 117 ); 117 } else {118 } else 118 119 *port = val; 119 }120 120 } 121 121 -
uspace/lib/c/generic/async.c
r1a5b252 r8cc4ddb 1777 1777 int async_hangup(async_sess_t *sess) 1778 1778 { 1779 async_exch_t *exch; 1780 1779 1781 assert(sess); 1780 1782 1781 1783 if (atomic_get(&sess->refcnt) > 0) 1782 1784 return EBUSY; 1785 1786 fibril_mutex_lock(&async_sess_mutex); 1783 1787 1784 1788 int rc = async_hangup_internal(sess->phone); 1785 1789 if (rc == EOK) 1786 1790 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); 1787 1804 1788 1805 return rc; -
uspace/lib/c/generic/io/printf_core.c
r1a5b252 r8cc4ddb 73 73 */ 74 74 #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 }) 75 94 76 95 /** Enumeration of possible arguments types. … … 831 850 size_t size; 832 851 uint64_t number; 852 833 853 switch (qualifier) { 834 854 case PrintfQualifierByte: 835 855 size = sizeof(unsigned char); 836 number = (uint64_t) va_arg(ap, unsigned int);856 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 837 857 break; 838 858 case PrintfQualifierShort: 839 859 size = sizeof(unsigned short); 840 number = (uint64_t) va_arg(ap, unsigned int);860 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 841 861 break; 842 862 case PrintfQualifierInt: 843 863 size = sizeof(unsigned int); 844 number = (uint64_t) va_arg(ap, unsigned int);864 number = PRINTF_GET_INT_ARGUMENT(int, ap, flags); 845 865 break; 846 866 case PrintfQualifierLong: 847 867 size = sizeof(unsigned long); 848 number = (uint64_t) va_arg(ap, unsigned long);868 number = PRINTF_GET_INT_ARGUMENT(long, ap, flags); 849 869 break; 850 870 case PrintfQualifierLongLong: 851 871 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); 853 873 break; 854 874 case PrintfQualifierPointer: … … 865 885 counter = -counter; 866 886 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 }883 887 } 884 888 -
uspace/lib/c/generic/str.c
r1a5b252 r8cc4ddb 2 2 * Copyright (c) 2005 Martin Decky 3 3 * Copyright (c) 2008 Jiri Svoboda 4 * Copyright (c) 2011 Martin Sucha 5 * Copyright (c) 2011 Oleg Romanenko 4 6 * All rights reserved. 5 7 * … … 639 641 } 640 642 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 */ 655 int 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 686 int 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 641 721 /** Convert wide string to new string. 642 722 * … … 718 798 719 799 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 */ 809 wchar_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; 720 819 } 721 820 … … 1016 1115 return dest; 1017 1116 } 1018 1019 1117 1020 1118 /** Convert initial part of string to unsigned long according to given base. -
uspace/lib/c/generic/sysinfo.c
r1a5b252 r8cc4ddb 47 47 * 48 48 */ 49 sysinfo_item_ tag_t sysinfo_get_tag(const char *path)49 sysinfo_item_val_type_t sysinfo_get_val_type(const char *path) 50 50 { 51 return (sysinfo_item_ tag_t) __SYSCALL2(SYS_SYSINFO_GET_TAG,51 return (sysinfo_item_val_type_t) __SYSCALL2(SYS_SYSINFO_GET_VAL_TYPE, 52 52 (sysarg_t) path, (sysarg_t) str_size(path)); 53 53 } -
uspace/lib/c/include/bool.h
r1a5b252 r8cc4ddb 37 37 38 38 #include <libarch/types.h> 39 #include <abi/bool.h> 39 40 40 41 #define false 0 41 42 #define true 1 42 43 typedef uint8_t bool;44 43 45 44 #endif -
uspace/lib/c/include/str.h
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2005 Martin Decky 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 83 84 extern char *wstr_to_astr(const wchar_t *src); 84 85 extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src); 86 extern wchar_t *str_to_awstr(const char *src); 87 extern int utf16_to_str(char *dest, size_t size, const uint16_t *src); 88 extern int str_to_utf16(uint16_t *dest, size_t size, const char *src); 85 89 86 90 extern char *str_chr(const char *str, wchar_t ch); -
uspace/lib/c/include/sysinfo.h
r1a5b252 r8cc4ddb 36 36 #define LIBC_SYSINFO_H_ 37 37 38 #include <libc.h> 38 #include <sys/types.h> 39 #include <bool.h> 40 #include <abi/sysinfo.h> 39 41 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 *); 42 extern sysinfo_item_val_type_t sysinfo_get_val_type(const char *); 50 43 extern int sysinfo_get_value(const char *, sysarg_t *); 51 44 extern void *sysinfo_get_data(const char *, size_t *); -
uspace/lib/c/include/task.h
r1a5b252 r8cc4ddb 37 37 38 38 #include <sys/types.h> 39 40 typedef uint64_t task_id_t; 39 #include <abi/proc/task.h> 41 40 42 41 typedef enum { -
uspace/lib/c/include/thread.h
r1a5b252 r8cc4ddb 38 38 #include <libarch/thread.h> 39 39 #include <sys/types.h> 40 41 typedef uint64_t thread_id_t; 40 #include <abi/proc/thread.h> 42 41 43 42 extern int thread_create(void (*)(void *), void *, const char *, thread_id_t *); -
uspace/srv/fs/fat/Makefile
r1a5b252 r8cc4ddb 39 39 fat_idx.c \ 40 40 fat_dentry.c \ 41 fat_directory.c \ 41 42 fat_fat.c 42 43 -
uspace/srv/fs/fat/fat.c
r1a5b252 r8cc4ddb 2 2 * Copyright (c) 2006 Martin Decky 3 3 * Copyright (c) 2008 Jakub Jermar 4 * Copyright (c) 2011 Oleg Romanenko 4 5 * All rights reserved. 5 6 * -
uspace/srv/fs/fat/fat.h
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 46 47 #endif 47 48 48 #define min(a, b) 49 #define min(a, b) ((a) < (b) ? (a) : (b)) 49 50 50 51 /* … … 55 56 #define RSCNT(bs) uint16_t_le2host((bs)->rscnt) 56 57 #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 58 63 #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 65 71 66 72 typedef struct fat_bs { -
uspace/srv/fs/fat/fat_dentry.c
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 39 40 #include <ctype.h> 40 41 #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> 49 45 50 46 /** Compare path component with the name read from the dentry. … … 80 76 } 81 77 82 bool fat_dentry_name_verify(const char *name) 78 void 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 118 void 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 180 fat_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 */ 221 uint8_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 */ 239 size_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 */ 258 size_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 269 size_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 293 size_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 328 void 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 349 bool 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 364 bool fat_valid_short_name(const char *name) 83 365 { 84 366 unsigned int i; 85 367 unsigned int dot = 0; 86 368 bool dot_found = false; 87 88 369 89 370 for (i = 0; name[i]; i++) { … … 96 377 } 97 378 } else { 98 if (! is_d_char(name[i]))379 if (!IS_D_CHAR(name[i])) 99 380 return false; 100 381 } … … 114 395 } 115 396 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; 397 size_t utf16_length(const uint16_t *wstr) 398 { 399 size_t len = 0; 400 401 while (*wstr++ != 0) 402 len++; 403 404 return len; 240 405 } 241 406 -
uspace/srv/fs/fat/fat_dentry.h
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 37 38 #include <bool.h> 38 39 40 #define IS_D_CHAR(ch) (isalnum(ch) || ch == '_') 41 #define FAT_STOP_CHARS "*?/\\\n\t|'" 42 39 43 #define FAT_NAME_LEN 8 40 44 #define FAT_EXT_LEN 3 … … 44 48 #define FAT_EXT_PAD " " 45 49 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 50 59 #define FAT_LCASE_LOWER_NAME 0x08 51 60 #define FAT_LCASE_LOWER_EXT 0x10 52 61 53 #define FAT_PAD ' ' 62 #define FAT_PAD ' ' 63 #define FAT_LFN_PAD 0xffff 64 #define FAT_SFN_CHAR '_' 54 65 55 66 #define FAT_DENTRY_UNUSED 0x00 … … 57 68 #define FAT_DENTRY_DOT 0x2e 58 69 #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) 59 91 60 92 typedef enum { … … 62 94 FAT_DENTRY_LAST, 63 95 FAT_DENTRY_FREE, 64 FAT_DENTRY_VALID 96 FAT_DENTRY_VALID, 97 FAT_DENTRY_LFN 65 98 } fat_dentry_clsf_t; 66 99 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 */ 100 typedef 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; 79 121 } __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; 87 132 } __attribute__ ((packed)) fat_dentry_t; 88 133 134 89 135 extern int fat_dentry_namecmp(char *, const char *); 90 extern bool fat_dentry_name_verify(const char *);91 136 extern void fat_dentry_name_get(const fat_dentry_t *, char *); 92 137 extern void fat_dentry_name_set(fat_dentry_t *, const char *); 93 138 extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *); 139 extern uint8_t fat_dentry_chksum(uint8_t *); 140 141 extern size_t fat_lfn_str_nlength(const uint16_t *, size_t); 142 extern size_t fat_lfn_size(const fat_dentry_t *); 143 extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *); 144 extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t, 145 fat_dentry_t *); 146 147 extern void str_to_ascii(char *, const char *, size_t, uint8_t); 148 extern size_t utf16_length(const uint16_t *); 149 150 extern bool fat_valid_name(const char *); 151 extern bool fat_valid_short_name(const char *); 94 152 95 153 #endif -
uspace/srv/fs/fat/fat_fat.c
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 50 51 #include <mem.h> 51 52 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) 62 54 63 55 /** … … 65 57 * during allocation of clusters. The lock does not have to be held durring 66 58 * deallocation of clusters. 67 */ 59 */ 68 60 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 69 61 … … 77 69 * @param numc If non-NULL, output argument holding the number of 78 70 * 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. 80 72 * 81 73 * @return EOK on success or a negative error code. 82 74 */ 83 int 75 int 84 76 fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc, 85 fat_cluster_t *lastc, uint 16_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); 90 82 int rc; 91 83 … … 99 91 } 100 92 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) { 105 94 assert(clst >= FAT_CLST_FIRST); 106 95 if (lastc) 107 96 *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 110 98 /* 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); 120 104 clusters++; 121 105 } 122 106 123 if (lastc && clst < FAT_CLST_LAST1)107 if (lastc && clst < clst_last1) 124 108 *lastc = clst; 125 109 if (numc) … … 151 135 return ELIMIT; 152 136 153 if ( nodep->firstc == FAT_CLST_ROOT)137 if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT) 154 138 goto fall_through; 155 139 … … 178 162 if (rc != EOK) 179 163 return rc; 180 164 181 165 /* 182 166 * Update the "current" cluster cache. … … 198 182 * @param clp If not NULL, address where the cluster containing bn 199 183 * will be stored. 200 * stored 184 * stored 201 185 * @param bn Block number. 202 186 * @param flags Flags passed to libblock. … … 208 192 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 209 193 { 210 uint 16_t clusters;211 u nsignedmax_clusters;194 uint32_t clusters; 195 uint32_t max_clusters; 212 196 fat_cluster_t c; 213 197 int rc; … … 219 203 return ELIMIT; 220 204 221 if ( fcl == FAT_CLST_ROOT) {205 if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) { 222 206 /* root directory special case */ 223 207 assert(bn < RDS(bs)); … … 253 237 * @return EOK on success or a negative error code. 254 238 */ 255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 239 int 240 fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 256 241 { 257 242 block_t *b; … … 275 260 return rc; 276 261 } 277 262 278 263 if (o >= pos) 279 264 return EOK; 280 265 281 266 /* zero out the initial part of the new cluster chain */ 282 267 for (o = boundary; o < pos; o += BPS(bs)) { … … 304 289 * @return EOK or a negative error code. 305 290 */ 291 static int 292 fat_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 */ 361 static int 362 fat_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 */ 392 static int 393 fat_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 */ 306 425 int 307 426 fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 308 427 fat_cluster_t clst, fat_cluster_t *value) 309 428 { 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 */ 453 static int 454 fat_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 314 466 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); 316 468 if (rc != EOK) 317 469 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 */ 321 526 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 */ 541 static int 542 fat_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 */ 574 static int 575 fat_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 323 598 return rc; 324 599 } … … 338 613 fat_cluster_t clst, fat_cluster_t value) 339 614 { 340 block_t *b;341 fat_cluster_t *cp;342 615 int rc; 343 616 344 617 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 354 626 return rc; 355 627 } … … 369 641 uint8_t fatno; 370 642 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++) { 374 647 for (c = 0; c < nclsts; c++) { 375 648 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]); 377 650 if (rc != EOK) 378 651 return rc; … … 404 677 fat_cluster_t *mcl, fat_cluster_t *lcl) 405 678 { 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; 411 683 412 684 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); … … 418 690 */ 419 691 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) { 426 699 /* 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. 433 702 */ 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++; 470 710 } 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); 474 719 fibril_mutex_unlock(&fat_alloc_lock); 475 free(lifo); 476 return rc; 720 return EOK; 477 721 } 478 722 } 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); 480 731 fibril_mutex_unlock(&fat_alloc_lock); 481 732 482 /*483 * We could not find enough clusters. Now we need to free the clusters484 * 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);496 733 return ENOSPC; 497 734 } … … 509 746 { 510 747 unsigned fatno; 511 fat_cluster_t nextc ;748 fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs); 512 749 int rc; 513 750 514 751 /* 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 517 755 rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc); 518 756 if (rc != EOK) 519 757 return rc; 520 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 758 759 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 521 760 rc = fat_set_cluster(bs, service_id, fatno, firstc, 522 761 FAT_CLST_RES0); … … 540 779 * @return EOK on success or a negative error code. 541 780 */ 542 int 543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 781 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 544 782 fat_cluster_t lcl) 545 783 { … … 559 797 } else { 560 798 rc = fat_cluster_walk(bs, service_id, nodep->firstc, 561 &lastc, NULL, (uint 16_t) -1);799 &lastc, NULL, (uint32_t) -1); 562 800 if (rc != EOK) 563 801 return rc; 564 802 } 565 803 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); 569 807 if (rc != EOK) 570 808 return rc; … … 590 828 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 591 829 { 830 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 592 831 int rc; 593 832 service_id_t service_id = nodep->idx->service_id; … … 616 855 617 856 /* 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++) { 619 858 rc = fat_set_cluster(bs, service_id, fatno, lcl, 620 FAT_CLST_LAST1);859 clst_last1); 621 860 if (rc != EOK) 622 861 return rc; … … 673 912 674 913 /* Check number of FATs. */ 675 if ( bs->fatcnt== 0)914 if (FATCNT(bs) == 0) 676 915 return ENOTSUP; 677 916 678 917 /* Check total number of sectors. */ 679 680 if (bs->totsec16 == 0 && bs->totsec32 == 0) 918 if (TS(bs) == 0) 681 919 return ENOTSUP; 682 920 683 921 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 684 bs->totsec16 != bs->totsec32) 922 bs->totsec16 != bs->totsec32) 685 923 return ENOTSUP; 686 924 … … 690 928 691 929 /* Check number of sectors per FAT. */ 692 if ( bs->sec_per_fat== 0)930 if (SF(bs) == 0) 693 931 return ENOTSUP; 694 932 … … 700 938 * sanitized to support file systems with this property. 701 939 */ 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) 704 942 return ENOTSUP; 705 943 706 944 /* 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++) { 709 946 rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0); 710 947 if (rc != EOK) … … 715 952 return EIO; 716 953 717 /* Check that first byte of FAT contains the media descriptor. */ 954 /* 955 * Check that first byte of FAT contains the media descriptor. 956 */ 718 957 if ((e0 & 0xff) != bs->mdesc) 719 958 return ENOTSUP; … … 723 962 * set to one. 724 963 */ 725 if ((e0 >> 8) != 0xff || e1 != 0xffff) 964 if (!FAT_IS_FAT12(bs) && 965 ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs))) 726 966 return ENOTSUP; 727 967 } … … 732 972 /** 733 973 * @} 734 */ 974 */ -
uspace/srv/fs/fat/fat_fat.h
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 #ifndef FAT_FAT_FAT_H_ … … 40 41 #define FAT1 0 41 42 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 48 62 49 63 /* internally used to mark root directory's parent */ … … 52 66 #define FAT_CLST_ROOT FAT_CLST_RES1 53 67 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 54 101 /* forward declarations */ 55 102 struct block; … … 57 104 struct fat_bs; 58 105 59 typedef uint 16_t fat_cluster_t;106 typedef uint32_t fat_cluster_t; 60 107 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) 63 110 extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t, 64 fat_cluster_t *, uint 16_t *, uint16_t);111 fat_cluster_t *, uint32_t *, uint32_t); 65 112 66 113 extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *, -
uspace/srv/fs/fat/fat_idx.c
r1a5b252 r8cc4ddb 116 116 #define UPH_BUCKETS (1 << UPH_BUCKETS_LOG) 117 117 118 #define UPH_ DH_KEY 0118 #define UPH_SID_KEY 0 119 119 #define UPH_PFC_KEY 1 120 120 #define UPH_PDI_KEY 2 … … 122 122 static hash_index_t pos_hash(unsigned long key[]) 123 123 { 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]; 125 125 fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY]; 126 126 unsigned pdi = (unsigned)key[UPH_PDI_KEY]; … … 150 150 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item) 151 151 { 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]; 153 153 fat_cluster_t pfc; 154 154 unsigned pdi; … … 190 190 #define UIH_BUCKETS (1 << UIH_BUCKETS_LOG) 191 191 192 #define UIH_ DH_KEY 0192 #define UIH_SID_KEY 0 193 193 #define UIH_INDEX_KEY 1 194 194 195 195 static hash_index_t idx_hash(unsigned long key[]) 196 196 { 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]; 198 198 fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY]; 199 199 … … 209 209 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item) 210 210 { 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]; 212 212 fs_index_t index; 213 213 fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link); … … 402 402 403 403 unsigned long ikey[] = { 404 [UIH_ DH_KEY] = service_id,404 [UIH_SID_KEY] = service_id, 405 405 [UIH_INDEX_KEY] = fidx->index, 406 406 }; … … 420 420 link_t *l; 421 421 unsigned long pkey[] = { 422 [UPH_ DH_KEY] = service_id,422 [UPH_SID_KEY] = service_id, 423 423 [UPH_PFC_KEY] = pfc, 424 424 [UPH_PDI_KEY] = pdi, … … 439 439 440 440 unsigned long ikey[] = { 441 [UIH_ DH_KEY] = service_id,441 [UIH_SID_KEY] = service_id, 442 442 [UIH_INDEX_KEY] = fidx->index, 443 443 }; … … 458 458 { 459 459 unsigned long pkey[] = { 460 [UPH_ DH_KEY] = idx->service_id,460 [UPH_SID_KEY] = idx->service_id, 461 461 [UPH_PFC_KEY] = idx->pfc, 462 462 [UPH_PDI_KEY] = idx->pdi, … … 471 471 { 472 472 unsigned long pkey[] = { 473 [UPH_ DH_KEY] = idx->service_id,473 [UPH_SID_KEY] = idx->service_id, 474 474 [UPH_PFC_KEY] = idx->pfc, 475 475 [UPH_PDI_KEY] = idx->pdi, … … 487 487 link_t *l; 488 488 unsigned long ikey[] = { 489 [UIH_ DH_KEY] = service_id,489 [UIH_SID_KEY] = service_id, 490 490 [UIH_INDEX_KEY] = index, 491 491 }; … … 509 509 { 510 510 unsigned long ikey[] = { 511 [UIH_ DH_KEY] = idx->service_id,511 [UIH_SID_KEY] = idx->service_id, 512 512 [UIH_INDEX_KEY] = idx->index, 513 513 }; … … 571 571 { 572 572 unsigned long ikey[] = { 573 [UIH_ DH_KEY] = service_id573 [UIH_SID_KEY] = service_id 574 574 }; 575 575 unsigned long pkey[] = { 576 [UPH_ DH_KEY] = service_id576 [UPH_SID_KEY] = service_id 577 577 }; 578 578 -
uspace/srv/fs/fat/fat_ops.c
r1a5b252 r8cc4ddb 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 39 40 #include "fat_dentry.h" 40 41 #include "fat_fat.h" 42 #include "fat_directory.h" 41 43 #include "../../vfs/vfs.h" 42 44 #include <libfs.h> … … 56 58 #include <align.h> 57 59 #include <malloc.h> 60 #include <str.h> 58 61 59 62 #define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) … … 104 107 node->dirty = false; 105 108 node->lastc_cached_valid = false; 106 node->lastc_cached_value = FAT_CLST_LAST1;109 node->lastc_cached_value = 0; 107 110 node->currc_cached_valid = false; 108 111 node->currc_cached_bn = 0; 109 node->currc_cached_value = FAT_CLST_LAST1;112 node->currc_cached_value = 0; 110 113 } 111 114 … … 116 119 fat_dentry_t *d; 117 120 int rc; 118 121 119 122 assert(node->dirty); 120 123 121 124 bs = block_bb_get(node->idx->service_id); 122 125 123 126 /* Read the block that contains the dentry of interest. */ 124 127 rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc, … … 136 139 d->attr = FAT_ATTR_SUBDIR; 137 140 } 138 141 139 142 /* TODO: update other fields? (e.g time fields) */ 140 143 141 144 b->dirty = true; /* need to sync block */ 142 145 rc = block_put(b); … … 255 258 fn->data = nodep; 256 259 nodep->bp = fn; 257 260 258 261 *nodepp = nodep; 259 262 return EOK; … … 291 294 * We must instantiate the node from the file system. 292 295 */ 293 296 294 297 assert(idxp->pfc); 295 298 … … 309 312 310 313 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 311 320 if (d->attr & FAT_ATTR_SUBDIR) { 312 /* 321 /* 313 322 * The only directory which does not have this bit set is the 314 323 * root directory itself. The root directory node is handled … … 316 325 */ 317 326 nodep->type = FAT_DIRECTORY; 327 318 328 /* 319 329 * Unfortunately, the 'size' field of the FAT dentry is not … … 321 331 * size of the directory by walking the FAT. 322 332 */ 323 uint 16_t clusters;333 uint32_t clusters; 324 334 rc = fat_clusters_get(&clusters, bs, idxp->service_id, 325 uint16_t_le2host(d->firstc));335 nodep->firstc); 326 336 if (rc != EOK) { 327 337 (void) block_put(b); … … 334 344 nodep->size = uint32_t_le2host(d->size); 335 345 } 336 nodep->firstc = uint16_t_le2host(d->firstc); 346 337 347 nodep->lnkcnt = 1; 338 348 nodep->refcnt = 1; … … 363 373 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 364 374 { 365 fat_bs_t *bs;366 375 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]; 370 377 fat_dentry_t *d; 371 378 service_id_t service_id; 372 block_t *b;373 379 int rc; 374 380 … … 376 382 service_id = parentp->idx->service_id; 377 383 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; 400 405 } 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); 424 410 return rc; 425 411 } 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); 429 416 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); 432 424 *rfn = NULL; 433 425 return EOK; … … 591 583 fat_bs_t *bs; 592 584 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; 596 587 int rc; 597 588 … … 607 598 fibril_mutex_unlock(&childp->lock); 608 599 609 if (!fat_dentry_name_verify(name)) { 610 /* 611 * Attempt to create unsupported name. 612 */ 600 if (!fat_valid_name(name)) 613 601 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 621 603 fibril_mutex_lock(&parentp->idx->lock); 622 604 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); 662 606 if (rc != EOK) { 663 607 fibril_mutex_unlock(&parentp->idx->lock); 664 608 return rc; 665 609 } 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 688 611 /* 689 612 * At this point we only establish the link between the parent and the … … 692 615 * dentry data is kept in the child node structure. 693 616 */ 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 698 631 fibril_mutex_unlock(&parentp->idx->lock); 699 if (rc != EOK)700 return rc;701 632 702 633 fibril_mutex_lock(&childp->idx->lock); 703 634 704 635 if (childp->type == FAT_DIRECTORY) { 705 636 /* … … 720 651 d = (fat_dentry_t *) b->data; 721 652 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) { 723 654 memset(d, 0, sizeof(fat_dentry_t)); 724 655 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 730 661 d++; 731 662 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)) { 733 664 memset(d, 0, sizeof(fat_dentry_t)); 734 665 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 735 666 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 736 667 d->attr = FAT_ATTR_SUBDIR; 737 d->firstc = (parentp->firstc == FAT_ CLST_ROOT) ?738 host2uint16_t_le(FAT_CLST_R ES0) :668 d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ? 669 host2uint16_t_le(FAT_CLST_ROOTPAR) : 739 670 host2uint16_t_le(parentp->firstc); 740 671 /* TODO: initialize also the date/time members. */ … … 750 681 751 682 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 */ 753 684 fibril_mutex_unlock(&childp->idx->lock); 754 685 … … 770 701 fat_node_t *parentp = FAT_NODE(pfn); 771 702 fat_node_t *childp = FAT_NODE(cfn); 772 fat_bs_t *bs;773 fat_dentry_t *d;774 block_t *b;775 703 bool has_children; 776 704 int rc; … … 778 706 if (!parentp) 779 707 return EBUSY; 780 708 781 709 rc = fat_has_children(&has_children, cfn); 782 710 if (rc != EOK) … … 789 717 assert(childp->lnkcnt == 1); 790 718 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) 797 723 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); 804 731 if (rc != EOK) 805 732 goto error; … … 820 747 821 748 error: 822 fibril_mutex_unlock(&parentp->idx->lock); 749 (void) fat_directory_close(&di); 750 fibril_mutex_unlock(&childp->idx->lock); 823 751 fibril_mutex_unlock(&childp->lock); 824 fibril_mutex_unlock(& childp->idx->lock);752 fibril_mutex_unlock(&parentp->lock); 825 753 return rc; 826 754 } … … 839 767 return EOK; 840 768 } 841 769 842 770 fibril_mutex_lock(&nodep->idx->lock); 843 771 bs = block_bb_get(nodep->idx->service_id); … … 847 775 for (i = 0; i < blocks; i++) { 848 776 fat_dentry_t *d; 849 777 850 778 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 851 779 if (rc != EOK) { … … 875 803 if (rc != EOK) { 876 804 fibril_mutex_unlock(&nodep->idx->lock); 877 return rc; 805 return rc; 878 806 } 879 807 } … … 946 874 fat_bs_t *bs; 947 875 int rc; 948 876 949 877 /* Check for option enabling write through. */ 950 878 if (str_cmp(opts, "wtcache") == 0) … … 1003 931 return ENOMEM; 1004 932 } 933 1005 934 fs_node_initialize(rfn); 1006 935 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); … … 1027 956 1028 957 rootp->type = FAT_DIRECTORY; 1029 rootp->firstc = FAT_ CLST_ROOT;958 rootp->firstc = FAT_ROOT_CLST(bs); 1030 959 rootp->refcnt = 1; 1031 960 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 1033 977 rootp->idx = ridxp; 1034 978 ridxp->nodep = rootp; 1035 979 rootp->bp = rfn; 1036 980 rfn->data = rootp; 1037 981 1038 982 fibril_mutex_unlock(&ridxp->lock); 1039 983 … … 1064 1008 return EBUSY; 1065 1009 } 1066 1010 1067 1011 /* 1068 1012 * Put the root node and force it to the FAT free node list. … … 1141 1085 } 1142 1086 } else { 1143 unsigned bnum;1144 1087 aoff64_t spos = pos; 1145 char name[FAT_ NAME_LEN + 1 + FAT_EXT_LEN + 1];1088 char name[FAT_LFN_NAME_SIZE]; 1146 1089 fat_dentry_t *d; 1147 1090 … … 1150 1093 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1151 1094 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 1111 err: 1112 (void) fat_node_put(fn); 1113 async_answer_0(callid, rc); 1114 return rc; 1115 1193 1116 miss: 1117 rc = fat_directory_close(&di); 1118 if (rc != EOK) 1119 goto err; 1194 1120 rc = fat_node_put(fn); 1195 1121 async_answer_0(callid, rc != EOK ? rc : ENOENT); … … 1197 1123 return rc != EOK ? rc : ENOENT; 1198 1124 1199 err:1200 (void) fat_node_put(fn);1201 async_answer_0(callid, rc);1202 return rc;1203 1204 1125 hit: 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); 1206 1132 bytes = (pos - spos) + 1; 1207 1133 } … … 1231 1157 return ENOENT; 1232 1158 nodep = FAT_NODE(fn); 1233 1159 1234 1160 ipc_callid_t callid; 1235 1161 size_t len; … … 1247 1173 * but this one greatly simplifies fat_write(). Note that we can afford 1248 1174 * 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 */ 1251 1177 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1252 1178 if (bytes == BPS(bs)) 1253 1179 flags |= BLOCK_FLAGS_NOREAD; 1254 1180 1255 1181 boundary = ROUND_UP(nodep->size, BPC(bs)); 1256 1182 if (pos < boundary) { … … 1295 1221 */ 1296 1222 unsigned nclsts; 1297 fat_cluster_t mcl, lcl; 1298 1223 fat_cluster_t mcl, lcl; 1224 1299 1225 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1300 1226 /* create an independent chain of nclsts clusters in all FATs */ … … 1380 1306 nodep->size = size; 1381 1307 nodep->dirty = true; /* need to sync node */ 1382 rc = EOK; 1308 rc = EOK; 1383 1309 } else { 1384 1310 /* … … 1401 1327 nodep->size = size; 1402 1328 nodep->dirty = true; /* need to sync node */ 1403 rc = EOK; 1329 rc = EOK; 1404 1330 } 1405 1331 out: … … 1444 1370 if (!fn) 1445 1371 return ENOENT; 1446 1372 1447 1373 fat_node_t *nodep = FAT_NODE(fn); 1448 1374 1449 1375 nodep->dirty = true; 1450 1376 rc = fat_node_sync(nodep); 1451 1377 1452 1378 fat_node_put(fn); 1453 1379 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.