- Timestamp:
- 2009-12-03T19:25:17Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9510be2
- Parents:
- cb3d641a (diff), 22e6802 (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. - Location:
- uspace
- Files:
-
- 1 added
- 28 edited
-
app/bdsh/input.c (modified) (4 diffs)
-
app/bdsh/input.h (modified) (1 diff)
-
app/bdsh/scli.c (modified) (1 diff)
-
app/edit/edit.c (modified) (10 diffs)
-
lib/libc/arch/amd64/include/atomic.h (modified) (1 diff)
-
lib/libc/arch/arm32/include/atomic.h (modified) (2 diffs)
-
lib/libc/arch/ia32/Makefile.inc (modified) (1 diff)
-
lib/libc/arch/ia32/include/atomic.h (modified) (1 diff)
-
lib/libc/arch/ia64/include/atomic.h (modified) (1 diff)
-
lib/libc/arch/mips32/include/atomic.h (modified) (1 diff)
-
lib/libc/arch/ppc32/include/atomic.h (modified) (1 diff)
-
lib/libc/arch/sparc64/include/atomic.h (modified) (1 diff)
-
lib/libc/generic/async.c (modified) (2 diffs)
-
lib/libc/generic/futex.c (modified) (3 diffs)
-
lib/libc/generic/io/console.c (modified) (1 diff)
-
lib/libc/generic/io/klog.c (modified) (1 diff)
-
lib/libc/generic/string.c (modified) (4 diffs)
-
lib/libc/generic/time.c (modified) (3 diffs)
-
lib/libc/generic/vfs/canonify.c (modified) (2 diffs)
-
lib/libc/include/atomic.h (modified) (2 diffs)
-
lib/libc/include/atomicdflt.h (added)
-
lib/libc/include/futex.h (modified) (1 diff)
-
lib/libc/include/io/console.h (modified) (1 diff)
-
lib/libc/include/ipc/console.h (modified) (1 diff)
-
lib/libc/include/string.h (modified) (1 diff)
-
lib/libc/include/unistd.h (modified) (2 diffs)
-
srv/console/console.c (modified) (1 diff)
-
srv/fs/fat/fat_ops.c (modified) (12 diffs)
-
srv/vfs/vfs_file.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/input.c
rcb3d641a rfbcfc4da 38 38 #include <vfs/vfs.h> 39 39 #include <errno.h> 40 #include <assert.h> 40 41 #include <bool.h> 41 42 … … 47 48 #include "exec.h" 48 49 49 static void read_line(char *, int); 50 #define HISTORY_LEN 10 51 52 typedef struct { 53 wchar_t buffer[INPUT_MAX]; 54 int col0, row0; 55 int con_cols, con_rows; 56 int nc; 57 int pos; 58 59 char *history[1 + HISTORY_LEN]; 60 int hnum; 61 int hpos; 62 } tinput_t; 63 64 typedef enum { 65 seek_backward = -1, 66 seek_forward = 1 67 } seek_dir_t; 68 69 static tinput_t tinput; 70 71 static char *tinput_read(tinput_t *ti); 50 72 51 73 /* Tokenizes input from console, sees if the first word is a built-in, if so … … 99 121 } 100 122 101 static void read_line(char *buffer, int n) 123 static void tinput_display_tail(tinput_t *ti, int start, int pad) 124 { 125 int i; 126 127 console_goto(fphone(stdout), (ti->col0 + start) % ti->con_cols, 128 ti->row0 + (ti->col0 + start) / ti->con_cols); 129 printf("%ls", ti->buffer + start); 130 for (i = 0; i < pad; ++i) 131 putchar(' '); 132 fflush(stdout); 133 } 134 135 static char *tinput_get_str(tinput_t *ti) 136 { 137 return wstr_to_astr(ti->buffer); 138 } 139 140 static void tinput_position_caret(tinput_t *ti) 141 { 142 console_goto(fphone(stdout), (ti->col0 + ti->pos) % ti->con_cols, 143 ti->row0 + (ti->col0 + ti->pos) / ti->con_cols); 144 } 145 146 /** Update row0 in case the screen could have scrolled. */ 147 static void tinput_update_origin(tinput_t *ti) 148 { 149 int width, rows; 150 151 width = ti->col0 + ti->nc; 152 rows = (width / ti->con_cols) + 1; 153 154 /* Update row0 if the screen scrolled. */ 155 if (ti->row0 + rows > ti->con_rows) 156 ti->row0 = ti->con_rows - rows; 157 } 158 159 static void tinput_insert_char(tinput_t *ti, wchar_t c) 160 { 161 int i; 162 int new_width, new_height; 163 164 if (ti->nc == INPUT_MAX) 165 return; 166 167 new_width = ti->col0 + ti->nc + 1; 168 if (new_width % ti->con_cols == 0) { 169 /* Advancing to new line. */ 170 new_height = (new_width / ti->con_cols) + 1; 171 if (new_height >= ti->con_rows) 172 return; /* Disallow text longer than 1 page for now. */ 173 } 174 175 for (i = ti->nc; i > ti->pos; --i) 176 ti->buffer[i] = ti->buffer[i - 1]; 177 178 ti->buffer[ti->pos] = c; 179 ti->pos += 1; 180 ti->nc += 1; 181 ti->buffer[ti->nc] = '\0'; 182 183 tinput_display_tail(ti, ti->pos - 1, 0); 184 tinput_update_origin(ti); 185 tinput_position_caret(ti); 186 } 187 188 static void tinput_backspace(tinput_t *ti) 189 { 190 int i; 191 192 if (ti->pos == 0) 193 return; 194 195 for (i = ti->pos; i < ti->nc; ++i) 196 ti->buffer[i - 1] = ti->buffer[i]; 197 ti->pos -= 1; 198 ti->nc -= 1; 199 ti->buffer[ti->nc] = '\0'; 200 201 tinput_display_tail(ti, ti->pos, 1); 202 tinput_position_caret(ti); 203 } 204 205 static void tinput_delete(tinput_t *ti) 206 { 207 if (ti->pos == ti->nc) 208 return; 209 210 ti->pos += 1; 211 tinput_backspace(ti); 212 } 213 214 static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir) 215 { 216 if (dir == seek_forward) { 217 if (ti->pos < ti->nc) 218 ti->pos += 1; 219 } else { 220 if (ti->pos > 0) 221 ti->pos -= 1; 222 } 223 224 tinput_position_caret(ti); 225 } 226 227 static void tinput_seek_word(tinput_t *ti, seek_dir_t dir) 228 { 229 if (dir == seek_forward) { 230 if (ti->pos == ti->nc) 231 return; 232 233 while (1) { 234 ti->pos += 1; 235 236 if (ti->pos == ti->nc) 237 break; 238 239 if (ti->buffer[ti->pos - 1] == ' ' && 240 ti->buffer[ti->pos] != ' ') 241 break; 242 } 243 } else { 244 if (ti->pos == 0) 245 return; 246 247 while (1) { 248 ti->pos -= 1; 249 250 if (ti->pos == 0) 251 break; 252 253 if (ti->buffer[ti->pos - 1] == ' ' && 254 ti->buffer[ti->pos] != ' ') 255 break; 256 } 257 258 } 259 260 tinput_position_caret(ti); 261 } 262 263 static void tinput_seek_vertical(tinput_t *ti, seek_dir_t dir) 264 { 265 if (dir == seek_forward) { 266 if (ti->pos + ti->con_cols <= ti->nc) 267 ti->pos = ti->pos + ti->con_cols; 268 } else { 269 if (ti->pos - ti->con_cols >= 0) 270 ti->pos = ti->pos - ti->con_cols; 271 } 272 273 tinput_position_caret(ti); 274 } 275 276 static void tinput_seek_max(tinput_t *ti, seek_dir_t dir) 277 { 278 if (dir == seek_backward) 279 ti->pos = 0; 280 else 281 ti->pos = ti->nc; 282 283 tinput_position_caret(ti); 284 } 285 286 static void tinput_history_insert(tinput_t *ti, char *str) 287 { 288 int i; 289 290 if (ti->hnum < HISTORY_LEN) { 291 ti->hnum += 1; 292 } else { 293 if (ti->history[HISTORY_LEN] != NULL) 294 free(ti->history[HISTORY_LEN]); 295 } 296 297 for (i = ti->hnum; i > 1; --i) 298 ti->history[i] = ti->history[i - 1]; 299 300 ti->history[1] = str_dup(str); 301 302 if (ti->history[0] != NULL) { 303 free(ti->history[0]); 304 ti->history[0] = NULL; 305 } 306 } 307 308 static void tinput_set_str(tinput_t *ti, char *str) 309 { 310 str_to_wstr(ti->buffer, INPUT_MAX, str); 311 ti->nc = wstr_length(ti->buffer); 312 ti->pos = ti->nc; 313 } 314 315 static void tinput_history_seek(tinput_t *ti, int offs) 316 { 317 int pad; 318 319 if (ti->hpos + offs < 0 || ti->hpos + offs > ti->hnum) 320 return; 321 322 if (ti->history[ti->hpos] != NULL) { 323 free(ti->history[ti->hpos]); 324 ti->history[ti->hpos] = NULL; 325 } 326 327 ti->history[ti->hpos] = tinput_get_str(ti); 328 ti->hpos += offs; 329 330 pad = ti->nc - str_length(ti->history[ti->hpos]); 331 if (pad < 0) pad = 0; 332 333 tinput_set_str(ti, ti->history[ti->hpos]); 334 tinput_display_tail(ti, 0, pad); 335 tinput_update_origin(ti); 336 tinput_position_caret(ti); 337 } 338 339 static void tinput_init(tinput_t *ti) 340 { 341 ti->hnum = 0; 342 ti->hpos = 0; 343 ti->history[0] = NULL; 344 } 345 346 static char *tinput_read(tinput_t *ti) 102 347 { 103 348 console_event_t ev; 104 size_t offs, otmp; 105 wchar_t dec; 106 107 offs = 0; 349 char *str; 350 351 fflush(stdout); 352 353 if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK) 354 return NULL; 355 if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK) 356 return NULL; 357 358 ti->pos = 0; 359 ti->nc = 0; 360 ti->buffer[0] = '\0'; 361 108 362 while (true) { 109 363 fflush(stdout); 110 364 if (!console_get_event(fphone(stdin), &ev)) 111 return ;365 return NULL; 112 366 113 367 if (ev.type != KEY_PRESS) 114 368 continue; 115 116 if ( ev.key == KC_ENTER || ev.key == KC_NENTER)117 break;118 if (ev.key == KC_BACKSPACE) {119 if (offs > 0) {120 /*121 * Back up until we reach valid start of122 * character.123 */124 while (offs > 0) {125 --offs; otmp = offs;126 dec = str_decode(buffer, &otmp, n);127 if (dec != U_SPECIAL)128 break;129 }130 putchar('\b');369 370 if ((ev.mods & KM_CTRL) != 0 && 371 (ev.mods & (KM_ALT | KM_SHIFT)) == 0) { 372 switch (ev.key) { 373 case KC_LEFT: 374 tinput_seek_word(ti, seek_backward); 375 break; 376 case KC_RIGHT: 377 tinput_seek_word(ti, seek_forward); 378 break; 379 case KC_UP: 380 tinput_seek_vertical(ti, seek_backward); 381 break; 382 case KC_DOWN: 383 tinput_seek_vertical(ti, seek_forward); 384 break; 131 385 } 132 continue;133 386 } 387 388 if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) { 389 switch (ev.key) { 390 case KC_ENTER: 391 case KC_NENTER: 392 goto done; 393 case KC_BACKSPACE: 394 tinput_backspace(ti); 395 break; 396 case KC_DELETE: 397 tinput_delete(ti); 398 break; 399 case KC_LEFT: 400 tinput_seek_cell(ti, seek_backward); 401 break; 402 case KC_RIGHT: 403 tinput_seek_cell(ti, seek_forward); 404 break; 405 case KC_HOME: 406 tinput_seek_max(ti, seek_backward); 407 break; 408 case KC_END: 409 tinput_seek_max(ti, seek_forward); 410 break; 411 case KC_UP: 412 tinput_history_seek(ti, +1); 413 break; 414 case KC_DOWN: 415 tinput_history_seek(ti, -1); 416 break; 417 } 418 } 419 134 420 if (ev.c >= ' ') { 135 if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK) 136 putchar(ev.c); 421 tinput_insert_char(ti, ev.c); 137 422 } 138 423 } 424 425 done: 426 ti->pos = ti->nc; 427 tinput_position_caret(ti); 139 428 putchar('\n'); 140 buffer[offs] = '\0'; 141 } 142 143 /* TODO: 144 * Implement something like editline() / readline(), if even 145 * just for command history and making arrows work. */ 429 430 str = tinput_get_str(ti); 431 if (str_cmp(str, "") != 0) 432 tinput_history_insert(ti, str); 433 434 ti->hpos = 0; 435 436 return str; 437 } 438 146 439 void get_input(cliuser_t *usr) 147 440 { 148 char line[INPUT_MAX];441 char *str; 149 442 150 443 fflush(stdout); … … 154 447 console_set_style(fphone(stdout), STYLE_NORMAL); 155 448 156 read_line(line, INPUT_MAX); 157 /* Make sure we don't have rubbish or a C/R happy user */ 158 if (str_cmp(line, "") == 0 || str_cmp(line, "\n") == 0) 449 str = tinput_read(&tinput); 450 451 /* Check for empty input. */ 452 if (str_cmp(str, "") == 0) { 453 free(str); 159 454 return; 160 usr->line = str_dup(line); 161 455 } 456 457 usr->line = str; 162 458 return; 163 459 } 164 460 461 void input_init(void) 462 { 463 tinput_init(&tinput); 464 } -
uspace/app/bdsh/input.h
rcb3d641a rfbcfc4da 8 8 extern void get_input(cliuser_t *); 9 9 extern int tok_input(cliuser_t *); 10 extern void input_init(void); 10 11 11 12 #endif -
uspace/app/bdsh/scli.c
rcb3d641a rfbcfc4da 64 64 usr->prompt = (char *) NULL; 65 65 usr->lasterr = 0; 66 67 input_init(); 68 66 69 return (int) cli_set_prompt(usr); 67 70 } -
uspace/app/edit/edit.c
rcb3d641a rfbcfc4da 36 36 37 37 #include <stdio.h> 38 #include <stdlib.h> 38 39 #include <sys/types.h> 39 40 #include <vfs/vfs.h> … … 101 102 #define ED_INFTY 65536 102 103 104 /** Maximum filename length that can be entered. */ 105 #define INFNAME_MAX_LEN 128 106 103 107 static void key_handle_unmod(console_event_t const *ev); 104 108 static void key_handle_ctrl(console_event_t const *ev); 105 109 static int file_save(char const *fname); 110 static void file_save_as(void); 106 111 static int file_insert(char *fname); 107 112 static int file_save_range(char const *fname, spt_t const *spos, 108 113 spt_t const *epos); 114 static char *filename_prompt(char const *prompt, char const *init_value); 109 115 static void pane_text_display(void); 110 116 static void pane_row_display(void); … … 150 156 151 157 if (argc == 2) { 152 doc.file_name = argv[1];158 doc.file_name = str_dup(argv[1]); 153 159 } else if (argc > 1) { 154 160 printf("Invalid arguments.\n"); 155 161 return -2; 156 162 } else { 157 doc.file_name = "/edit.txt";163 doc.file_name = NULL; 158 164 } 159 165 160 166 new_file = false; 161 167 162 if ( file_insert(doc.file_name) != EOK)168 if (doc.file_name == NULL || file_insert(doc.file_name) != EOK) 163 169 new_file = true; 164 170 … … 170 176 pane_text_display(); 171 177 pane_status_display(); 172 if (new_file )173 status_display("File not found. Createdempty file.");178 if (new_file && doc.file_name != NULL) 179 status_display("File not found. Starting empty file."); 174 180 pane_caret_display(); 175 181 … … 266 272 break; 267 273 case KC_S: 268 (void) file_save(doc.file_name); 274 if (doc.file_name != NULL) 275 file_save(doc.file_name); 276 else 277 file_save_as(); 278 break; 279 case KC_E: 280 file_save_as(); 269 281 break; 270 282 default: … … 272 284 } 273 285 } 274 275 286 276 287 /** Save the document. */ … … 285 296 286 297 rc = file_save_range(fname, &sp, &ep); 287 status_display("File saved."); 298 299 switch (rc) { 300 case EINVAL: 301 status_display("Error opening file!"); 302 break; 303 case EIO: 304 status_display("Error writing data!"); 305 break; 306 default: 307 status_display("File saved."); 308 break; 309 } 288 310 289 311 return rc; 312 } 313 314 /** Change document name and save. */ 315 static void file_save_as(void) 316 { 317 char *old_fname, *fname; 318 int rc; 319 320 old_fname = (doc.file_name != NULL) ? doc.file_name : ""; 321 fname = filename_prompt("Save As", old_fname); 322 if (fname == NULL) { 323 status_display("Save cancelled."); 324 return; 325 } 326 327 rc = file_save(fname); 328 if (rc != EOK) 329 return; 330 331 if (doc.file_name != NULL) 332 free(doc.file_name); 333 doc.file_name = fname; 334 } 335 336 /** Ask for a file name. */ 337 static char *filename_prompt(char const *prompt, char const *init_value) 338 { 339 console_event_t ev; 340 char *str; 341 wchar_t buffer[INFNAME_MAX_LEN + 1]; 342 int max_len; 343 int nc; 344 bool done; 345 346 asprintf(&str, "%s: %s", prompt, init_value); 347 status_display(str); 348 console_goto(con, 1 + str_length(str), scr_rows - 1); 349 free(str); 350 351 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0); 352 353 max_len = min(INFNAME_MAX_LEN, scr_columns - 4 - str_length(prompt)); 354 str_to_wstr(buffer, max_len + 1, init_value); 355 nc = wstr_length(buffer); 356 done = false; 357 358 while (!done) { 359 console_get_event(con, &ev); 360 361 if (ev.type == KEY_PRESS) { 362 /* Handle key press. */ 363 if (((ev.mods & KM_ALT) == 0) && 364 (ev.mods & KM_CTRL) != 0) { 365 ; 366 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) { 367 switch (ev.key) { 368 case KC_ESCAPE: 369 return NULL; 370 case KC_BACKSPACE: 371 if (nc > 0) { 372 putchar('\b'); 373 fflush(stdout); 374 --nc; 375 } 376 break; 377 case KC_ENTER: 378 done = true; 379 break; 380 default: 381 if (ev.c >= 32 && nc < max_len) { 382 putchar(ev.c); 383 fflush(stdout); 384 buffer[nc++] = ev.c; 385 } 386 break; 387 } 388 } 389 } 390 } 391 392 buffer[nc] = '\0'; 393 str = wstr_to_astr(buffer); 394 395 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0); 396 397 return str; 290 398 } 291 399 … … 359 467 } while (!spt_equal(&bep, epos)); 360 468 361 fclose(f); 469 if (fclose(f) != EOK) 470 return EIO; 362 471 363 472 return EOK; … … 473 582 spt_t caret_pt; 474 583 coord_t coord; 584 char *fname; 475 585 int n; 476 586 … … 478 588 spt_get_coord(&caret_pt, &coord); 479 589 590 fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>"; 591 480 592 console_goto(con, 0, scr_rows - 1); 481 593 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0); 482 n = printf(" %d, %d: File '%s'. Ctrl- S Save Ctrl-Q Quit",483 coord.row, coord.column, doc.file_name);594 n = printf(" %d, %d: File '%s'. Ctrl-Q Quit Ctrl-S Save " 595 "Ctrl-E Save As", coord.row, coord.column, fname); 484 596 printf("%*s", scr_columns - 1 - n, ""); 485 597 fflush(stdout); -
uspace/lib/libc/arch/amd64/include/atomic.h
rcb3d641a rfbcfc4da 37 37 #ifndef LIBC_amd64_ATOMIC_H_ 38 38 #define LIBC_amd64_ATOMIC_H_ 39 40 #define LIBC_ARCH_ATOMIC_H_ 41 42 #include <atomicdflt.h> 39 43 40 44 static inline void atomic_inc(atomic_t *val) { -
uspace/lib/libc/arch/arm32/include/atomic.h
rcb3d641a rfbcfc4da 37 37 #define LIBC_arm32_ATOMIC_H_ 38 38 39 #include <bool.h> 40 41 typedef struct atomic { 42 volatile long count; 43 } atomic_t; 44 45 static inline void atomic_set(atomic_t *val, long i) 46 { 47 val->count = i; 48 } 49 50 static inline long atomic_get(atomic_t *val) 51 { 52 return val->count; 53 } 54 55 static inline bool cas(atomic_t *val, long ov, long nv) 56 { 57 /* FIXME: is not atomic */ 58 if (val->count == ov) { 59 val->count = nv; 60 return true; 61 } 62 return false; 63 } 64 39 65 /** Atomic addition. 40 66 * … … 49 75 volatile long * mem = &(val->count); 50 76 77 /* FIXME: is not atomic, is broken */ 51 78 asm volatile ( 52 79 "1:\n" -
uspace/lib/libc/arch/ia32/Makefile.inc
rcb3d641a rfbcfc4da 39 39 arch/$(UARCH)/src/setjmp.S 40 40 41 GCC_CFLAGS += -march=pentium 41 42 LFLAGS += -N 42 43 -
uspace/lib/libc/arch/ia32/include/atomic.h
rcb3d641a rfbcfc4da 35 35 #ifndef LIBC_ia32_ATOMIC_H_ 36 36 #define LIBC_ia32_ATOMIC_H_ 37 38 #define LIBC_ARCH_ATOMIC_H_ 39 40 #include <atomicdflt.h> 37 41 38 42 static inline void atomic_inc(atomic_t *val) { -
uspace/lib/libc/arch/ia64/include/atomic.h
rcb3d641a rfbcfc4da 35 35 #ifndef LIBC_ia64_ATOMIC_H_ 36 36 #define LIBC_ia64_ATOMIC_H_ 37 38 #define LIBC_ARCH_ATOMIC_H_ 39 40 #include <atomicdflt.h> 37 41 38 42 static inline void atomic_inc(atomic_t *val) -
uspace/lib/libc/arch/mips32/include/atomic.h
rcb3d641a rfbcfc4da 36 36 #ifndef LIBC_mips32_ATOMIC_H_ 37 37 #define LIBC_mips32_ATOMIC_H_ 38 39 #define LIBC_ARCH_ATOMIC_H_ 40 41 #include <atomicdflt.h> 38 42 39 43 #define atomic_inc(x) ((void) atomic_add(x, 1)) -
uspace/lib/libc/arch/ppc32/include/atomic.h
rcb3d641a rfbcfc4da 35 35 #ifndef LIBC_ppc32_ATOMIC_H_ 36 36 #define LIBC_ppc32_ATOMIC_H_ 37 38 #define LIBC_ARCH_ATOMIC_H_ 39 40 #include <atomicdflt.h> 37 41 38 42 static inline void atomic_inc(atomic_t *val) -
uspace/lib/libc/arch/sparc64/include/atomic.h
rcb3d641a rfbcfc4da 36 36 #define LIBC_sparc64_ATOMIC_H_ 37 37 38 #define LIBC_ARCH_ATOMIC_H_ 39 40 #include <atomicdflt.h> 38 41 #include <sys/types.h> 39 42 -
uspace/lib/libc/generic/async.c
rcb3d641a rfbcfc4da 392 392 /* If nothing in queue, wait until something arrives */ 393 393 while (list_empty(&conn->msg_queue)) { 394 if (conn->close_callid) { 395 /* 396 * Handle the case when the connection was already 397 * closed by the client but the server did not notice 398 * the first IPC_M_PHONE_HUNGUP call and continues to 399 * call async_get_call_timeout(). Repeat 400 * IPC_M_PHONE_HUNGUP until the caller notices. 401 */ 402 memset(call, 0, sizeof(ipc_call_t)); 403 IPC_SET_METHOD(*call, IPC_M_PHONE_HUNGUP); 404 futex_up(&async_futex); 405 return conn->close_callid; 406 } 407 394 408 if (usecs) 395 409 async_insert_timeout(&conn->wdata); … … 528 542 list_initialize(&conn->msg_queue); 529 543 conn->callid = callid; 530 conn->close_callid = false;544 conn->close_callid = 0; 531 545 532 546 if (call) -
uspace/lib/libc/generic/futex.c
rcb3d641a rfbcfc4da 36 36 #include <atomic.h> 37 37 #include <libc.h> 38 #include <stdio.h>39 38 #include <sys/types.h> 40 #include <kernel/synch/synch.h>41 42 /*43 * Note about race conditions.44 * Because of non-atomic nature of operations performed sequentially on the45 * futex counter and the futex wait queue, there is a race condition:46 *47 * (wq->missed_wakeups == 1) && (futex->count = 1)48 *49 * Scenario 1 (wait queue timeout vs. futex_up()):50 * 1. assume wq->missed_wakeups == 0 && futex->count == -151 * (ie. thread A sleeping, thread B in the critical section)52 * 2. A receives timeout and gets removed from the wait queue53 * 3. B wants to leave the critical section and calls futex_up()54 * 4. B thus changes futex->count from -1 to 055 * 5. B has to call SYS_FUTEX_WAKEUP syscall to wake up the sleeping thread56 * 6. B finds the wait queue empty and changes wq->missed_wakeups from 0 to 157 * 7. A fixes futex->count (i.e. the number of waiting threads) by changing it58 * from 0 to 159 *60 * Scenario 2 (conditional down operation vs. futex_up)61 * 1. assume wq->missed_wakeups == 0 && futex->count == 062 * (i.e. thread A is in the critical section)63 * 2. thread B performs futex_trydown() operation and changes futex->count from64 * 0 to -165 * B is now obliged to call SYS_FUTEX_SLEEP syscall66 * 3. A wants to leave the critical section and does futex_up()67 * 4. A thus changes futex->count from -1 to 0 and must call SYS_FUTEX_WAKEUP68 * syscall69 * 5. B finds the wait queue empty and immediatelly aborts the conditional sleep70 * 6. No thread is queueing in the wait queue so wq->missed_wakeups changes from71 * 0 to 172 * 6. B fixes futex->count (i.e. the number of waiting threads) by changing it73 * from 0 to 174 *75 * Both scenarios allow two threads to be in the critical section76 * simultaneously. One without kernel intervention and the other through77 * wq->missed_wakeups being 1.78 *79 * To mitigate this problem, futex_down_timeout() detects that the syscall80 * didn't sleep in the wait queue, fixes the futex counter and RETRIES the81 * whole operation again.82 */83 39 84 40 /** Initialize futex counter. … … 92 48 } 93 49 94 int futex_down(futex_t *futex)95 {96 return futex_down_timeout(futex, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);97 }98 99 int futex_trydown(futex_t *futex)100 {101 return futex_down_timeout(futex, SYNCH_NO_TIMEOUT,102 SYNCH_FLAGS_NON_BLOCKING);103 }104 105 50 /** Try to down the futex. 106 51 * 107 52 * @param futex Futex. 108 * @param usec Microseconds to wait. Zero value means sleep without 109 * timeout. 110 * @param flags Select mode of operation. See comment for 111 * waitq_sleep_timeout(). 53 * @return Non-zero if the futex was acquired. 54 * @return Zero if the futex was not acquired. 55 */ 56 int futex_trydown(futex_t *futex) 57 { 58 return cas(futex, 1, 0); 59 } 60 61 /** Down the futex. 112 62 * 113 * @return ENOENT if there is no such virtual address. One of 114 * ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED on success or 115 * ESYNCH_TIMEOUT if the lock was not acquired because of 116 * a timeout or ESYNCH_WOULD_BLOCK if the operation could 117 * not be carried out atomically (if requested so). 63 * @param futex Futex. 64 * @return ENOENT if there is no such virtual address. 65 * @return Zero in the uncontended case. 66 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED. 118 67 */ 119 int futex_down _timeout(futex_t *futex, uint32_t usec, int flags)68 int futex_down(futex_t *futex) 120 69 { 121 int rc; 122 123 while (atomic_predec(futex) < 0) { 124 rc = __SYSCALL3(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count, 125 (sysarg_t) usec, (sysarg_t) flags); 126 127 switch (rc) { 128 case ESYNCH_OK_ATOMIC: 129 /* 130 * Because of a race condition between timeout and 131 * futex_up() and between conditional 132 * futex_down_timeout() and futex_up(), we have to give 133 * up and try again in this special case. 134 */ 135 atomic_inc(futex); 136 break; 70 if (atomic_predec(futex) < 0) 71 return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count); 137 72 138 case ESYNCH_TIMEOUT: 139 atomic_inc(futex); 140 return ESYNCH_TIMEOUT; 141 break; 142 143 case ESYNCH_WOULD_BLOCK: 144 /* 145 * The conditional down operation should be implemented 146 * this way. The userspace-only variant tends to 147 * accumulate missed wakeups in the kernel futex wait 148 * queue. 149 */ 150 atomic_inc(futex); 151 return ESYNCH_WOULD_BLOCK; 152 break; 153 154 case ESYNCH_OK_BLOCKED: 155 /* 156 * Enter the critical section. 157 * The futex counter has already been incremented for 158 * us. 159 */ 160 return ESYNCH_OK_BLOCKED; 161 break; 162 default: 163 return rc; 164 } 165 } 166 167 /* 168 * Enter the critical section. 169 */ 170 return ESYNCH_OK_ATOMIC; 73 return 0; 171 74 } 172 75 … … 174 77 * 175 78 * @param futex Futex. 176 * 177 * @return ENOENT if there is no such virtual address. Otherwise 178 * zero. 79 * @return ENOENT if there is no such virtual address. 80 * @return Zero in the uncontended case. 179 81 */ 180 82 int futex_up(futex_t *futex) 181 83 { 182 long val; 183 184 val = atomic_postinc(futex); 185 if (val < 0) 84 if (atomic_postinc(futex) < 0) 186 85 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count); 187 86 -
uspace/lib/libc/generic/io/console.c
rcb3d641a rfbcfc4da 94 94 } 95 95 96 int console_get_pos(int phone, int *col, int *row) 97 { 98 ipcarg_t col_v; 99 ipcarg_t row_v; 100 int rc; 101 102 rc = async_req_0_2(phone, CONSOLE_GET_POS, &col_v, &row_v); 103 104 *col = (int) col_v; 105 *row = (int) row_v; 106 return rc; 107 } 108 96 109 void console_goto(int phone, int col, int row) 97 110 { -
uspace/lib/libc/generic/io/klog.c
rcb3d641a rfbcfc4da 42 42 size_t klog_write(const void *buf, size_t size) 43 43 { 44 return (size_t) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size); 44 ssize_t ret = (ssize_t) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size); 45 46 if (ret >= 0) 47 return (size_t) ret; 48 49 return 0; 45 50 } 46 51 -
uspace/lib/libc/generic/string.c
rcb3d641a rfbcfc4da 471 471 * null-terminated and containing only complete characters. 472 472 * 473 * @param d st Destination buffer.473 * @param dest Destination buffer. 474 474 * @param count Size of the destination buffer (must be > 0). 475 475 * @param src Source string. … … 505 505 * have to be null-terminated. 506 506 * 507 * @param d st Destination buffer.507 * @param dest Destination buffer. 508 508 * @param count Size of the destination buffer (must be > 0). 509 509 * @param src Source string. … … 537 537 * null-terminated and containing only complete characters. 538 538 * 539 * @param d st Destination buffer.539 * @param dest Destination buffer. 540 540 * @param count Size of the destination buffer. 541 541 * @param src Source string. … … 549 549 } 550 550 551 /** Copy NULL-terminated wide string to string 552 * 553 * Copy source wide string @a src to destination buffer @a dst. 554 * No more than @a size bytes are written. NULL-terminator is always 555 * written after the last succesfully copied character (i.e. if the 556 * destination buffer is has at least 1 byte, it will be always 557 * NULL-terminated). 558 * 559 * @param src Source wide string. 560 * @param dst Destination buffer. 561 * @param count Size of the destination buffer. 562 * 563 */ 564 void wstr_nstr(char *dst, const wchar_t *src, size_t size) 565 { 566 /* No space for the NULL-terminator in the buffer */ 567 if (size == 0) 568 return; 569 551 /** Convert wide string to string. 552 * 553 * Convert wide string @a src to string. The output is written to the buffer 554 * specified by @a dest and @a size. @a size must be non-zero and the string 555 * written will always be well-formed. 556 * 557 * @param dest Destination buffer. 558 * @param size Size of the destination buffer. 559 * @param src Source wide string. 560 */ 561 void wstr_to_str(char *dest, size_t size, const wchar_t *src) 562 { 570 563 wchar_t ch; 571 size_t src_idx = 0; 572 size_t dst_off = 0; 573 564 size_t src_idx; 565 size_t dest_off; 566 567 /* There must be space for a null terminator in the buffer. */ 568 assert(size > 0); 569 570 src_idx = 0; 571 dest_off = 0; 572 574 573 while ((ch = src[src_idx++]) != 0) { 575 if (chr_encode(ch, d st, &dst_off, size) != EOK)574 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 576 575 break; 577 576 } 578 579 if (dst_off >= size) 580 dst[size - 1] = 0; 581 else 582 dst[dst_off] = 0; 577 578 dest[dest_off] = '\0'; 579 } 580 581 /** Convert wide string to new string. 582 * 583 * Convert wide string @a src to string. Space for the new string is allocated 584 * on the heap. 585 * 586 * @param src Source wide string. 587 * @return New string. 588 */ 589 char *wstr_to_astr(const wchar_t *src) 590 { 591 char dbuf[STR_BOUNDS(1)]; 592 char *str; 593 wchar_t ch; 594 595 size_t src_idx; 596 size_t dest_off; 597 size_t dest_size; 598 599 /* Compute size of encoded string. */ 600 601 src_idx = 0; 602 dest_size = 0; 603 604 while ((ch = src[src_idx++]) != 0) { 605 dest_off = 0; 606 if (chr_encode(ch, dbuf, &dest_off, STR_BOUNDS(1)) != EOK) 607 break; 608 dest_size += dest_off; 609 } 610 611 str = malloc(dest_size + 1); 612 if (str == NULL) 613 return NULL; 614 615 /* Encode string. */ 616 617 src_idx = 0; 618 dest_off = 0; 619 620 while ((ch = src[src_idx++]) != 0) { 621 if (chr_encode(ch, str, &dest_off, dest_size) != EOK) 622 break; 623 } 624 625 str[dest_size] = '\0'; 626 return str; 627 } 628 629 630 /** Convert string to wide string. 631 * 632 * Convert string @a src to wide string. The output is written to the 633 * buffer specified by @a dest and @a dlen. @a dlen must be non-zero 634 * and the wide string written will always be null-terminated. 635 * 636 * @param dest Destination buffer. 637 * @param dlen Length of destination buffer (number of wchars). 638 * @param src Source string. 639 */ 640 void str_to_wstr(wchar_t *dest, size_t dlen, const char *src) 641 { 642 size_t offset; 643 size_t di; 644 wchar_t c; 645 646 assert(dlen > 0); 647 648 offset = 0; 649 di = 0; 650 651 do { 652 if (di >= dlen - 1) 653 break; 654 655 c = str_decode(src, &offset, STR_NO_LIMIT); 656 dest[di++] = c; 657 } while (c != '\0'); 658 659 dest[dlen - 1] = '\0'; 583 660 } 584 661 -
uspace/lib/libc/generic/time.c
rcb3d641a rfbcfc4da 31 31 */ 32 32 /** @file 33 */ 33 */ 34 34 35 35 #include <sys/time.h> … … 40 40 #include <unistd.h> 41 41 #include <atomic.h> 42 #include <futex.h>43 42 #include <sysinfo.h> 44 43 #include <ipc/services.h> 44 #include <libc.h> 45 45 46 46 #include <sysinfo.h> … … 189 189 190 190 /** Wait unconditionally for specified number of microseconds */ 191 int usleep(unsigned long usec) 192 { 193 atomic_t futex = FUTEX_INITIALIZER; 194 195 futex_initialize(&futex, 0); 196 futex_down_timeout(&futex, usec, 0); 191 int usleep(useconds_t usec) 192 { 193 (void) __SYSCALL1(SYS_THREAD_USLEEP, usec); 197 194 return 0; 198 195 } 199 196 200 197 /** Wait unconditionally for specified number of seconds */ 201 unsigned int sleep(unsigned int seconds) 202 { 203 atomic_t futex = FUTEX_INITIALIZER; 204 205 futex_initialize(&futex, 0); 206 198 unsigned int sleep(unsigned int sec) 199 { 207 200 /* Sleep in 1000 second steps to support 208 201 full argument range */ 209 while (sec onds> 0) {210 unsigned int period = (sec onds > 1000) ? 1000 : seconds;202 while (sec > 0) { 203 unsigned int period = (sec > 1000) ? 1000 : sec; 211 204 212 futex_down_timeout(&futex, period * 1000000,0);213 sec onds-= period;205 usleep(period * 1000000); 206 sec -= period; 214 207 } 215 208 return 0; -
uspace/lib/libc/generic/vfs/canonify.c
rcb3d641a rfbcfc4da 142 142 t->start[-1] = '\0'; 143 143 } 144 /** Eat the extra '/'. .144 /** Eat the extra '/'. 145 145 * 146 146 * @param t The current TK_SLASH token. … … 288 288 * 289 289 * A file system path is canonical, if the following holds: 290 * 1) the path is absolute (i.e. a/b/c is not canonical) 291 * 2) there is no trailing slash in the path (i.e. /a/b/c is not canonical) 292 * 3) there is no extra slash in the path (i.e. /a//b/c is not canonical) 293 * 4) there is no '.' component in the path (i.e. /a/./b/c is not canonical) 294 * 5) there is no '..' component in the path (i.e. /a/b/../c is not canonical) 290 * 291 * 1) the path is absolute 292 * (i.e. a/b/c is not canonical) 293 * 2) there is no trailing slash in the path if it has components 294 * (i.e. /a/b/c/ is not canonical) 295 * 3) there is no extra slash in the path 296 * (i.e. /a//b/c is not canonical) 297 * 4) there is no '.' component in the path 298 * (i.e. /a/./b/c is not canonical) 299 * 5) there is no '..' component in the path 300 * (i.e. /a/b/../c is not canonical) 295 301 * 296 302 * This function makes a potentially non-canonical file system path canonical. -
uspace/lib/libc/include/atomic.h
rcb3d641a rfbcfc4da 1 1 /* 2 * Copyright (c) 200 6Jakub Jermar2 * Copyright (c) 2009 Jakub Jermar 3 3 * All rights reserved. 4 4 * … … 36 36 #define LIBC_ATOMIC_H_ 37 37 38 typedef struct atomic {39 volatile long count;40 } atomic_t;41 42 38 #include <libarch/atomic.h> 43 44 static inline void atomic_set(atomic_t *val, long i)45 {46 val->count = i;47 }48 49 static inline long atomic_get(atomic_t *val)50 {51 return val->count;52 }53 39 54 40 #endif -
uspace/lib/libc/include/futex.h
rcb3d641a rfbcfc4da 46 46 extern int futex_down(futex_t *futex); 47 47 extern int futex_trydown(futex_t *futex); 48 extern int futex_down_timeout(futex_t *futex, uint32_t usec, int flags);49 48 extern int futex_up(futex_t *futex); 50 49 -
uspace/lib/libc/include/io/console.h
rcb3d641a rfbcfc4da 69 69 70 70 extern int console_get_size(int phone, int *cols, int *rows); 71 extern int console_get_pos(int phone, int *col, int *row); 71 72 extern void console_goto(int phone, int col, int row); 72 73 -
uspace/lib/libc/include/ipc/console.h
rcb3d641a rfbcfc4da 43 43 CONSOLE_GET_COLOR_CAP, 44 44 CONSOLE_GET_EVENT, 45 CONSOLE_GET_POS, 45 46 CONSOLE_GOTO, 46 47 CONSOLE_CLEAR, -
uspace/lib/libc/include/string.h
rcb3d641a rfbcfc4da 73 73 extern void str_append(char *dest, size_t size, const char *src); 74 74 75 extern void wstr_nstr(char *dst, const wchar_t *src, size_t size); 75 extern void wstr_to_str(char *dest, size_t size, const wchar_t *src); 76 extern char *wstr_to_astr(const wchar_t *src); 77 extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src); 76 78 77 79 extern char *str_chr(const char *str, wchar_t ch); -
uspace/lib/libc/include/unistd.h
rcb3d641a rfbcfc4da 51 51 #endif 52 52 53 typedef uint32_t useconds_t; 54 53 55 extern int dup2(int oldfd, int newfd); 54 56 … … 68 70 69 71 extern void _exit(int status) __attribute__ ((noreturn)); 70 extern int usleep(u nsigned long usec);71 extern unsigned int sleep(unsigned int se conds);72 extern int usleep(useconds_t uses); 73 extern unsigned int sleep(unsigned int se); 72 74 73 75 #endif -
uspace/srv/console/console.c
rcb3d641a rfbcfc4da 601 601 IPC_GET_ARG2(call)); 602 602 break; 603 case CONSOLE_GET_POS: 604 arg1 = cons->scr.position_x; 605 arg2 = cons->scr.position_y; 606 break; 603 607 case CONSOLE_GET_SIZE: 604 608 arg1 = fb_info.cols; -
uspace/srv/fs/fat/fat_ops.c
rcb3d641a rfbcfc4da 363 363 } 364 364 rc = fat_node_get_core(&nodep, idx); 365 assert(rc == EOK);366 365 fibril_mutex_unlock(&idx->lock); 367 (void) block_put(b); 366 if (rc != EOK) { 367 (void) block_put(b); 368 return rc; 369 } 368 370 *rfn = FS_NODE(nodep); 369 return EOK; 371 rc = block_put(b); 372 if (rc != EOK) 373 (void) fat_node_put(*rfn); 374 return rc; 370 375 } 371 376 } … … 1072 1077 rc = fat_block_get(&b, bs, nodep, pos / bps, 1073 1078 BLOCK_FLAGS_NONE); 1074 assert(rc == EOK); 1079 if (rc != EOK) { 1080 fat_node_put(fn); 1081 ipc_answer_0(callid, rc); 1082 ipc_answer_0(rid, rc); 1083 return; 1084 } 1075 1085 (void) async_data_read_finalize(callid, b->data + pos % bps, 1076 1086 bytes); 1077 1087 rc = block_put(b); 1078 assert(rc == EOK); 1088 if (rc != EOK) { 1089 fat_node_put(fn); 1090 ipc_answer_0(rid, rc); 1091 return; 1092 } 1079 1093 } 1080 1094 } else { … … 1100 1114 rc = fat_block_get(&b, bs, nodep, bnum, 1101 1115 BLOCK_FLAGS_NONE); 1102 assert(rc == EOK); 1116 if (rc != EOK) 1117 goto err; 1103 1118 for (o = pos % (bps / sizeof(fat_dentry_t)); 1104 1119 o < bps / sizeof(fat_dentry_t); … … 1111 1126 case FAT_DENTRY_LAST: 1112 1127 rc = block_put(b); 1113 assert(rc == EOK); 1128 if (rc != EOK) 1129 goto err; 1114 1130 goto miss; 1115 1131 default: … … 1117 1133 fat_dentry_name_get(d, name); 1118 1134 rc = block_put(b); 1119 assert(rc == EOK); 1135 if (rc != EOK) 1136 goto err; 1120 1137 goto hit; 1121 1138 } 1122 1139 } 1123 1140 rc = block_put(b); 1124 assert(rc == EOK); 1141 if (rc != EOK) 1142 goto err; 1125 1143 bnum++; 1126 1144 } 1127 1145 miss: 1128 fat_node_put(fn); 1129 ipc_answer_0(callid, ENOENT); 1130 ipc_answer_1(rid, ENOENT, 0); 1131 return; 1146 rc = fat_node_put(fn); 1147 ipc_answer_0(callid, rc != EOK ? rc : ENOENT); 1148 ipc_answer_1(rid, rc != EOK ? rc : ENOENT, 0); 1149 return; 1150 1151 err: 1152 (void) fat_node_put(fn); 1153 ipc_answer_0(callid, rc); 1154 ipc_answer_0(rid, rc); 1155 return; 1156 1132 1157 hit: 1133 1158 (void) async_data_read_finalize(callid, name, str_size(name) + 1); … … 1135 1160 } 1136 1161 1137 fat_node_put(fn);1138 ipc_answer_1(rid, EOK, (ipcarg_t)bytes);1162 rc = fat_node_put(fn); 1163 ipc_answer_1(rid, rc, (ipcarg_t)bytes); 1139 1164 } 1140 1165 … … 1147 1172 fat_node_t *nodep; 1148 1173 fat_bs_t *bs; 1149 size_t bytes ;1174 size_t bytes, size; 1150 1175 block_t *b; 1151 1176 uint16_t bps; … … 1170 1195 size_t len; 1171 1196 if (!async_data_write_receive(&callid, &len)) { 1172 fat_node_put(fn);1197 (void) fat_node_put(fn); 1173 1198 ipc_answer_0(callid, EINVAL); 1174 1199 ipc_answer_0(rid, EINVAL); … … 1201 1226 */ 1202 1227 rc = fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); 1203 assert(rc == EOK); 1228 if (rc != EOK) { 1229 (void) fat_node_put(fn); 1230 ipc_answer_0(callid, rc); 1231 ipc_answer_0(rid, rc); 1232 return; 1233 } 1204 1234 rc = fat_block_get(&b, bs, nodep, pos / bps, flags); 1205 assert(rc == EOK); 1235 if (rc != EOK) { 1236 (void) fat_node_put(fn); 1237 ipc_answer_0(callid, rc); 1238 ipc_answer_0(rid, rc); 1239 return; 1240 } 1206 1241 (void) async_data_write_finalize(callid, b->data + pos % bps, 1207 1242 bytes); 1208 1243 b->dirty = true; /* need to sync block */ 1209 1244 rc = block_put(b); 1210 assert(rc == EOK); 1245 if (rc != EOK) { 1246 (void) fat_node_put(fn); 1247 ipc_answer_0(rid, rc); 1248 return; 1249 } 1211 1250 if (pos + bytes > nodep->size) { 1212 1251 nodep->size = pos + bytes; 1213 1252 nodep->dirty = true; /* need to sync node */ 1214 1253 } 1215 ipc_answer_2(rid, EOK, bytes, nodep->size); 1216 fat_node_put(fn); 1254 size = nodep->size; 1255 rc = fat_node_put(fn); 1256 ipc_answer_2(rid, rc, bytes, nodep->size); 1217 1257 return; 1218 1258 } else { … … 1221 1261 * clusters for the node and zero them out. 1222 1262 */ 1223 int status;1224 1263 unsigned nclsts; 1225 1264 fat_cluster_t mcl, lcl; … … 1227 1266 nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc; 1228 1267 /* create an independent chain of nclsts clusters in all FATs */ 1229 status= fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);1230 if ( status!= EOK) {1268 rc = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); 1269 if (rc != EOK) { 1231 1270 /* could not allocate a chain of nclsts clusters */ 1232 fat_node_put(fn);1233 ipc_answer_0(callid, status);1234 ipc_answer_0(rid, status);1271 (void) fat_node_put(fn); 1272 ipc_answer_0(callid, rc); 1273 ipc_answer_0(rid, rc); 1235 1274 return; 1236 1275 } 1237 1276 /* zero fill any gaps */ 1238 1277 rc = fat_fill_gap(bs, nodep, mcl, pos); 1239 assert(rc == EOK); 1278 if (rc != EOK) { 1279 (void) fat_free_clusters(bs, dev_handle, mcl); 1280 (void) fat_node_put(fn); 1281 ipc_answer_0(callid, rc); 1282 ipc_answer_0(rid, rc); 1283 return; 1284 } 1240 1285 rc = _fat_block_get(&b, bs, dev_handle, lcl, (pos / bps) % spc, 1241 1286 flags); 1242 assert(rc == EOK); 1287 if (rc != EOK) { 1288 (void) fat_free_clusters(bs, dev_handle, mcl); 1289 (void) fat_node_put(fn); 1290 ipc_answer_0(callid, rc); 1291 ipc_answer_0(rid, rc); 1292 return; 1293 } 1243 1294 (void) async_data_write_finalize(callid, b->data + pos % bps, 1244 1295 bytes); 1245 1296 b->dirty = true; /* need to sync block */ 1246 1297 rc = block_put(b); 1247 assert(rc == EOK); 1298 if (rc != EOK) { 1299 (void) fat_free_clusters(bs, dev_handle, mcl); 1300 (void) fat_node_put(fn); 1301 ipc_answer_0(rid, rc); 1302 return; 1303 } 1248 1304 /* 1249 1305 * Append the cluster chain starting in mcl to the end of the … … 1251 1307 */ 1252 1308 rc = fat_append_clusters(bs, nodep, mcl); 1253 assert(rc == EOK); 1254 nodep->size = pos + bytes; 1309 if (rc != EOK) { 1310 (void) fat_free_clusters(bs, dev_handle, mcl); 1311 (void) fat_node_put(fn); 1312 ipc_answer_0(rid, rc); 1313 return; 1314 } 1315 nodep->size = size = pos + bytes; 1255 1316 nodep->dirty = true; /* need to sync node */ 1256 ipc_answer_2(rid, EOK, bytes, nodep->size);1257 fat_node_put(fn);1317 rc = fat_node_put(fn); 1318 ipc_answer_2(rid, rc, bytes, size); 1258 1319 return; 1259 1320 } -
uspace/srv/vfs/vfs_file.c
rcb3d641a rfbcfc4da 89 89 unsigned int i; 90 90 if (desc) 91 i = MAX_OPEN_FILES ;91 i = MAX_OPEN_FILES - 1; 92 92 else 93 93 i = 0; … … 111 111 i--; 112 112 } else { 113 if (i == MAX_OPEN_FILES )113 if (i == MAX_OPEN_FILES - 1) 114 114 break; 115 115
Note:
See TracChangeset
for help on using the changeset viewer.
