libjf API reference guide

Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

jf_file.c

Go to the documentation of this file.
00001 /* 00002 * Copyright 2005 Tiian 00003 * {In real life Tiian is Christian Ferrari} 00004 * This file is part of "libjf" package. 00005 * 00006 * "libjf" is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2.1 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * "libjf" is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with ; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 */ 00020 #include <jf/jf_config.h> 00021 00022 00023 00024 #ifdef HAVE_STDIO_H 00025 # include <stdio.h> 00026 #endif /* HAVE_STDIO_H */ 00027 #ifdef HAVE_STDLIB_H 00028 # include <stdlib.h> 00029 #endif /* HAVE_STDLIB_H */ 00030 #ifdef HAVE_STRING_H 00031 # include <string.h> 00032 #endif /* HAVE_STRING_H */ 00033 #ifdef HAVE_STDARG_H 00034 # include <stdarg.h> 00035 #endif /* HAVE_STDARG_H */ 00036 #ifdef HAVE_ERRNO_H 00037 # include <errno.h> 00038 #endif /* HAVE_ERRNO_H */ 00039 00040 #include <jf/jf_errors.h> 00041 #include <jf/jf_trace.h> 00042 #include <jf_file.h> 00043 00044 00045 00046 /* set module trace flag */ 00047 #ifdef JF_TRACE_MODULE 00048 # undef JF_TRACE_MODULE 00049 #endif /* JF_TRACE_MODULE */ 00050 #define JF_TRACE_MODULE JF_TRACE_MOD_LIB_FILE 00051 00052 00053 00054 void jf_file_reset(jf_file_t *jf) 00055 { 00056 JF_TRACE(("jf_file_reset\n")); 00057 jf->journal = NULL; 00058 jf->private_journal = FALSE; 00059 jf->id = JF_JOURNAL_GLOBAL_FILE_ID; 00060 jf->char_buffer = NULL; 00061 jf->char_buffer_size = 0; 00062 } 00063 00064 00065 00066 int jf_file_open(jf_file_t *jfile, jf_journal_t *journal, 00067 const char *path, const char *mode, 00068 const struct jf_file_open_opts_s *options) 00069 { 00070 enum Exception { INVALID_PATH 00071 , MALLOC_NAME 00072 , MALLOC_JOURNAL 00073 , JOURNAL_OPEN 00074 , JOURNAL_OPEN_ATTACH_FILE 00075 , NONE } excp; 00076 int ret_cod = JF_RC_INTERNAL_ERROR; 00077 00078 char *journal_path = NULL; 00079 00080 JF_TRACE(("jf_file_open\n")); 00081 TRY { 00082 const struct jf_journal_file_opts_s *journal_file_opts = NULL; 00083 struct jf_file_open_opts_s opts; 00084 int join_the_journal = TRUE; 00085 00086 if (NULL != options) 00087 opts = *options; 00088 else 00089 jf_set_default_file_open_opts(&opts); 00090 00091 if (path == NULL || strlen(path) == 0) 00092 THROW(INVALID_PATH); 00093 00094 /* reset object */ 00095 jf_file_reset(jfile); 00096 00097 if (NULL == journal) { 00098 /* a private journal must be opened, building name */ 00099 if (NULL == (journal_path = (char *)malloc( 00100 strlen(path) + 00101 strlen(JF_JOURNAL_EXTENSION)+1))) 00102 THROW(MALLOC_NAME); 00103 strcpy(journal_path, path); 00104 strcat(journal_path, JF_JOURNAL_EXTENSION); 00105 00106 /* allocate a private journal object */ 00107 jfile->private_journal = TRUE; 00108 if (NULL == (jfile->journal = (jf_journal_t *)malloc( 00109 sizeof(jf_journal_t)))) 00110 THROW(MALLOC_JOURNAL); 00111 00112 opts.journal_opts.flags |= 00113 JF_JOURNAL_PROP_OPEN_O_CREAT; 00114 /* open the journal */ 00115 ret_cod = jf_journal_open( 00116 jfile->journal, journal_path, 1, 00117 &(opts.journal_opts)); 00118 if (JF_RC_OK != ret_cod) 00119 THROW(JOURNAL_OPEN); 00120 } else { 00121 jfile->private_journal = FALSE; 00122 jfile->journal = journal; 00123 } 00124 00125 if (options != NULL) { 00126 join_the_journal = opts.join_the_journal; 00127 } /* if (options != NULL) */ 00128 journal_file_opts = &(opts.journal_opts.journal_file_opts); 00129 00130 /* open file (if not already opened) and attach to journal */ 00131 ret_cod = jf_journal_open_attach_file( 00132 jfile->journal, path, mode, &(jfile->id), 00133 join_the_journal, journal_file_opts); 00134 if (JF_RC_OK != ret_cod) 00135 THROW(JOURNAL_OPEN_ATTACH_FILE); 00136 00137 THROW(NONE); 00138 } CATCH { 00139 switch (excp) { 00140 case INVALID_PATH: 00141 ret_cod = JF_RC_INVALID_PATH_NAME; 00142 break; 00143 case MALLOC_NAME: 00144 ret_cod = JF_RC_MALLOC_ERROR; 00145 break; 00146 case MALLOC_JOURNAL: 00147 ret_cod = JF_RC_MALLOC_ERROR; 00148 break; 00149 case JOURNAL_OPEN: 00150 break; 00151 case JOURNAL_OPEN_ATTACH_FILE: 00152 break; 00153 case NONE: 00154 ret_cod = JF_RC_OK; 00155 break; 00156 default: 00157 ret_cod = JF_RC_INTERNAL_ERROR; 00158 } /* switch (excp) */ 00159 00160 /* release storage */ 00161 if (NULL != journal_path) 00162 free(journal_path); 00163 00164 /* release storage */ 00165 if (excp > MALLOC_JOURNAL && excp < NONE) { 00166 if (journal == NULL && jfile->journal != NULL) 00167 free(jfile->journal); 00168 jfile->journal = NULL; 00169 } /* if (excp > MALLOC_JOURNAL) */ 00170 00171 } /* TRY-CATCH */ 00172 JF_TRACE(("jf_file_open/excp=%d/ret_cod=%d/errno=%d\n", 00173 excp, ret_cod, errno)); 00174 return ret_cod; 00175 } 00176 00177 00178 00179 int jf_file_check_mode(const char *mode, uint32_t *flags) 00180 { 00181 enum Exception { INVALID_POINTER 00182 , INVALID_FIRST 00183 , INVALID_SECOND 00184 , INVALID_THIRD 00185 , NONE } excp; 00186 int ret_cod = JF_RC_INTERNAL_ERROR; 00187 00188 uint32_t tmp_flags = 0; 00189 00190 JF_TRACE(("jf_file_check_mode\n")); 00191 TRY { 00192 if (mode == NULL) 00193 THROW(INVALID_POINTER); 00194 00195 /* check first char, it must be in set [r,R,w,W,a] */ 00196 switch (mode[0]) { 00197 case 'r': 00198 tmp_flags |= JF_FILE_OM_READ; 00199 break; 00200 case 'R': 00201 tmp_flags |= JF_FILE_OM_READ | JF_FILE_OM_RESTART; 00202 break; 00203 case 'w': 00204 tmp_flags |= JF_FILE_OM_WRITE | JF_FILE_OM_TRUNCATE; 00205 break; 00206 case 'W': 00207 tmp_flags |= JF_FILE_OM_WRITE | JF_FILE_OM_RESTART | 00208 JF_FILE_OM_TRUNCATE; 00209 break; 00210 case 'a': 00211 tmp_flags |= JF_FILE_OM_WRITE | JF_FILE_OM_APPEND; 00212 break; 00213 default: 00214 THROW(INVALID_FIRST); 00215 } /* switch mode[0] */ 00216 00217 /* check second char, it can be in set [D,+] */ 00218 switch (mode[1]) { 00219 case '\0': /* break parsing */ 00220 THROW(NONE); 00221 case 'D': 00222 tmp_flags |= JF_FILE_OM_MSDOS; 00223 break; 00224 case '+': 00225 tmp_flags |= JF_FILE_OM_READ | JF_FILE_OM_WRITE; 00226 break; 00227 default: 00228 THROW(INVALID_SECOND); 00229 } /* switch (mode[1]) */ 00230 00231 /* check third char, it can be in set [D,+] */ 00232 switch (mode[2]) { 00233 case '\0': /* break parsing */ 00234 THROW(NONE); 00235 case 'D': 00236 tmp_flags |= JF_FILE_OM_MSDOS; 00237 break; 00238 case '+': 00239 tmp_flags |= JF_FILE_OM_READ | JF_FILE_OM_WRITE; 00240 break; 00241 default: 00242 THROW(INVALID_THIRD); 00243 } /* switch (mode[2]) */ 00244 00245 THROW(NONE); 00246 } CATCH { 00247 switch (excp) { 00248 case INVALID_POINTER: 00249 ret_cod = JF_RC_NULL_OBJECT; 00250 break; 00251 case INVALID_FIRST: 00252 /* intentionally missed break ... */ 00253 case INVALID_SECOND: 00254 /* intentionally missed break ... */ 00255 case INVALID_THIRD: 00256 ret_cod = JF_RC_INVALID_OPTION; 00257 break; 00258 case NONE: 00259 *flags = tmp_flags; 00260 ret_cod = JF_RC_OK; 00261 break; 00262 default: 00263 ret_cod = JF_RC_INTERNAL_ERROR; 00264 } /* switch (excp) */ 00265 } /* TRY-CATCH */ 00266 JF_TRACE(("jf_file_check_mode/excp=%d/ret_cod=%d\n", 00267 excp, ret_cod)); 00268 return ret_cod; 00269 } 00270 00271 00272 00273 int jf_file_build_open_mode(uint32_t flags, char *mode1, char *mode2, 00274 int *repos, int *resize, int *append) 00275 { 00276 enum Exception { UNSUPPORTED_MODE 00277 , NONE } excp; 00278 int ret_cod = JF_RC_INTERNAL_ERROR; 00279 00280 JF_TRACE(("jf_file_build_open_mode\n")); 00281 TRY { 00282 /* keeping only interesting bits */ 00283 uint32_t tmp_flags = flags & 00284 (JF_FILE_OM_MASK & (~JF_FILE_OM_MSDOS)); 00285 00286 /* resetting boolean flags */ 00287 *repos = FALSE; 00288 *resize = FALSE; 00289 *append = FALSE; 00290 00291 /* resetting modes */ 00292 *mode1 = '\0'; 00293 *mode2 = '\0'; 00294 00295 /* building fopen mode associated to flags: note the stream is 00296 * EVER opened as a BINARY stream; MS-DOS new line conversion 00297 * is operated at libjf level */ 00298 switch (tmp_flags) { 00299 case JF_FILE_OM_READ: 00300 /* "r" -> "r" */ 00301 strcpy(mode1, "rb"); 00302 break; 00303 case JF_FILE_OM_READ | JF_FILE_OM_WRITE: 00304 /* "r+" -> "r+" */ 00305 strcpy(mode1, "r+b"); 00306 break; 00307 case JF_FILE_OM_READ | JF_FILE_OM_RESTART: 00308 /* "R" -> "r" */ 00309 *repos = TRUE; 00310 strcpy(mode1, "rb"); 00311 break; 00312 case JF_FILE_OM_READ | JF_FILE_OM_WRITE | 00313 JF_FILE_OM_RESTART: 00314 /* "R+" -> "r+" */ 00315 *repos = TRUE; 00316 strcpy(mode1, "r+b"); 00317 break; 00318 case JF_FILE_OM_WRITE | JF_FILE_OM_TRUNCATE: 00319 /* "w" -> "r+", "w" */ 00320 *resize = TRUE; 00321 strcpy(mode1, "r+b"); 00322 strcpy(mode2, "wb"); 00323 break; 00324 case JF_FILE_OM_WRITE | JF_FILE_OM_READ | 00325 JF_FILE_OM_TRUNCATE: 00326 /* "w+" -> "r+", "w+" */ 00327 *resize = TRUE; 00328 strcpy(mode1, "r+b"); 00329 strcpy(mode2, "w+b"); 00330 break; 00331 case JF_FILE_OM_WRITE | JF_FILE_OM_TRUNCATE | 00332 JF_FILE_OM_RESTART: 00333 /* "W" -> "r+", "w" */ 00334 *repos = TRUE; 00335 *resize = TRUE; 00336 strcpy(mode1, "r+b"); 00337 strcpy(mode2, "wb"); 00338 break; 00339 case JF_FILE_OM_WRITE | JF_FILE_OM_READ | 00340 JF_FILE_OM_TRUNCATE | JF_FILE_OM_RESTART: 00341 /* "W+" -> "r+", "w+" */ 00342 *repos = TRUE; 00343 *resize = TRUE; 00344 strcpy(mode1, "r+b"); 00345 strcpy(mode2, "w+b"); 00346 break; 00347 case JF_FILE_OM_WRITE | JF_FILE_OM_APPEND: 00348 /* "a" -> "r+", "w" */ 00349 *append = TRUE; 00350 strcpy(mode1, "r+b"); 00351 strcpy(mode2, "wb"); 00352 break; 00353 case JF_FILE_OM_WRITE | JF_FILE_OM_READ | 00354 JF_FILE_OM_APPEND: 00355 /* "a+" -> "r+", "w+" */ 00356 *append = TRUE; 00357 strcpy(mode1, "r+b"); 00358 strcpy(mode2, "w+b"); 00359 break; 00360 default: /* unsupported mode */ 00361 THROW(UNSUPPORTED_MODE); 00362 } /* switch (flags) */ 00363 00364 THROW(NONE); 00365 } CATCH { 00366 switch (excp) { 00367 case UNSUPPORTED_MODE: 00368 ret_cod = JF_RC_INVALID_OPTION; 00369 break; 00370 case NONE: 00371 ret_cod = JF_RC_OK; 00372 break; 00373 default: 00374 ret_cod = JF_RC_INTERNAL_ERROR; 00375 } /* switch (excp) */ 00376 } /* TRY-CATCH */ 00377 JF_TRACE(("jf_file_build_open_mode/excp=%d/ret_cod=%d\n", 00378 excp, ret_cod)); 00379 return ret_cod; 00380 } 00381 00382 00383 00384 int jf_file_close(jf_file_t *jfile) 00385 { 00386 enum Exception { NOT_SAFE 00387 , INVALID_BUFFER 00388 , ROLLBACK 00389 , JOURNAL_CLOSE_DETACH_FILE 00390 , JOURNAL_CLOSE 00391 , NONE } excp; 00392 int ret_cod = JF_RC_INTERNAL_ERROR; 00393 00394 JF_TRACE(("jf_file_close\n")); 00395 TRY { 00396 /* check safety */ 00397 if (!jf_file_is_safe(jfile)) 00398 THROW(NOT_SAFE); 00399 00400 #ifdef _EXTRA_CHECK 00401 if ((NULL == jfile->char_buffer && 00402 0 != jfile->char_buffer_size) || 00403 (NULL != jfile->char_buffer && 00404 0 == jfile->char_buffer_size)) 00405 THROW(INVALID_BUFFER); 00406 #endif /* _EXTRA_CHECK */ 00407 00408 if (NULL != jfile->char_buffer) { 00409 free(jfile->char_buffer); 00410 jfile->char_buffer = NULL; 00411 jfile->char_buffer_size = 0; 00412 } /* if (NULL != jfile->char_buffer) */ 00413 00414 /* rollback uncommitted changes (if necessary) */ 00415 if (JF_RC_OK != (ret_cod = jf_file_rollback(jfile))) 00416 THROW(ROLLBACK); 00417 00418 /* close file and detach from journal */ 00419 if (JF_RC_OK != (ret_cod = jf_journal_close_detach_file( 00420 jfile->journal, jfile->id))) 00421 THROW(JOURNAL_CLOSE_DETACH_FILE); 00422 00423 /* close journal file too */ 00424 if (jfile->private_journal && 00425 JF_RC_OK != (ret_cod = jf_journal_close(jfile->journal))) 00426 THROW(JOURNAL_CLOSE); 00427 00428 /* reset journaled file object */ 00429 jf_file_reset(jfile); 00430 00431 THROW(NONE); 00432 } CATCH { 00433 switch (excp) { 00434 case NOT_SAFE: 00435 ret_cod = JF_RC_OBJ_CORRUPTED; 00436 break; 00437 #ifdef _EXTRA_CHECK 00438 case INVALID_BUFFER: 00439 ret_cod = JF_RC_INVALID_STATUS; 00440 break; 00441 #endif /* _EXTRA_CHECK */ 00442 case ROLLBACK: 00443 case JOURNAL_CLOSE_DETACH_FILE: 00444 case JOURNAL_CLOSE: 00445 break; 00446 case NONE: 00447 ret_cod = JF_RC_OK; 00448 break; 00449 default: 00450 ret_cod = JF_RC_INTERNAL_ERROR; 00451 } /* switch (excp) */ 00452 } /* TRY-CATCH */ 00453 JF_TRACE(("jf_file_close/excp=%d/ret_cod=%d/errno=%d\n", 00454 excp, ret_cod, errno)); 00455 return ret_cod; 00456 } 00457 00458 00459 00460 jf_offset_t jf_file_get_cache_limit(const jf_file_t *jfile) 00461 { 00462 jf_journal_file_t *jf; 00463 jf_cache_file_t *cf; 00464 00465 if (!jf_file_is_safe(jfile)) 00466 return -1; 00467 if (NULL == (jf = jf_journal_get_jfile( 00468 jfile->journal, jfile->id))) 00469 return -1; 00470 if (NULL == (cf = jf_journal_file_get_cache_file(jf))) 00471 return -1; 00472 return jf_cache_file_get_limit(cf); 00473 } 00474 00475 00476 00477 int jf_file_seek(jf_file_t *jf, jf_offset_t offset, int whence) 00478 { 00479 enum Exception { OBJ_NOT_SAFE 00480 , NOTHING_TO_DO 00481 , INVALID_WHENCE_VALUE 00482 , INVALID_OFFSET 00483 , SET_LAST_UC_POS 00484 , NONE } excp; 00485 int ret_cod = JF_RC_INTERNAL_ERROR; 00486 00487 JF_TRACE(("jf_file_seek\n")); 00488 TRY { 00489 jf_journal_t *journal; 00490 jf_word_t file_id; 00491 jf_journal_file_t *jfp; 00492 jf_offset_t tmp_off; 00493 uint32_t open_mode; 00494 00495 if (!jf_file_is_safe(jf)) 00496 THROW(OBJ_NOT_SAFE); 00497 00498 journal = jf_file_get_journal(jf); 00499 file_id = jf_file_get_id(jf); 00500 jfp = jf_journal_get_jfile(journal, file_id); 00501 open_mode = jf_journal_file_get_open_mode(jfp); 00502 00503 /* "a" mode can not support "seek" operation */ 00504 if (open_mode & JF_FILE_OM_APPEND && 00505 !(open_mode & JF_FILE_OM_READ)) 00506 THROW(NOTHING_TO_DO); 00507 00508 switch (whence) { 00509 case SEEK_SET: 00510 tmp_off = offset; 00511 break; 00512 case SEEK_CUR: 00513 tmp_off = jf_journal_file_get_last_uc_pos(jfp) + 00514 offset; 00515 break; 00516 case SEEK_END: 00517 tmp_off = jf_journal_file_get_last_uc_size(jfp) + 00518 offset; 00519 break; 00520 default: 00521 THROW(INVALID_WHENCE_VALUE); 00522 } /* switch (whence) */ 00523 00524 /* check new offset value */ 00525 if (tmp_off < 0 || 00526 tmp_off > jf_journal_file_get_last_uc_size(jfp)) 00527 THROW(INVALID_OFFSET); 00528 00529 ret_cod = jf_journal_file_set_last_uc_pos(jfp, tmp_off); 00530 if (JF_RC_OK != ret_cod) 00531 THROW(SET_LAST_UC_POS); 00532 00533 THROW(NONE); 00534 } CATCH { 00535 switch (excp) { 00536 case OBJ_NOT_SAFE: 00537 ret_cod = JF_RC_OBJ_CORRUPTED; 00538 break; 00539 case INVALID_WHENCE_VALUE: 00540 ret_cod = JF_RC_OUT_OF_RANGE; 00541 break; 00542 case INVALID_OFFSET: 00543 ret_cod = JF_RC_INVALID_STREAM_POSITION; 00544 break; 00545 case SET_LAST_UC_POS: 00546 break; 00547 case NOTHING_TO_DO: 00548 case NONE: 00549 ret_cod = JF_RC_OK; 00550 break; 00551 default: 00552 ret_cod = JF_RC_INTERNAL_ERROR; 00553 } /* switch (excp) */ 00554 } /* TRY-CATCH */ 00555 JF_TRACE(("jf_file_seek/excp=%d/ret_cod=%d/errno=%d\n", 00556 excp, ret_cod, errno)); 00557 return ret_cod; 00558 } 00559 00560 00561 00562 int jf_file_size(jf_file_t *jf, jf_offset_t *last_size, 00563 jf_offset_t *last_uc_size) 00564 { 00565 enum Exception { OBJ_NOT_SAFE 00566 , NONE } excp; 00567 int ret_cod = JF_RC_INTERNAL_ERROR; 00568 00569 JF_TRACE(("jf_file_size\n")); 00570 TRY { 00571 jf_journal_t *journal; 00572 jf_word_t file_id; 00573 jf_journal_file_t *jfp; 00574 00575 if (!jf_file_is_safe(jf)) 00576 THROW(OBJ_NOT_SAFE); 00577 00578 journal = jf_file_get_journal(jf); 00579 file_id = jf_file_get_id(jf); 00580 jfp = jf_journal_get_jfile(journal, file_id); 00581 00582 if (NULL != last_size) 00583 *last_size = jf_journal_file_get_last_size(jfp); 00584 if (NULL != last_uc_size) 00585 *last_uc_size = jf_journal_file_get_last_uc_size(jfp); 00586 00587 THROW(NONE); 00588 } CATCH { 00589 switch (excp) { 00590 case OBJ_NOT_SAFE: 00591 ret_cod = JF_RC_OBJ_CORRUPTED; 00592 break; 00593 case NONE: 00594 ret_cod = JF_RC_OK; 00595 break; 00596 default: 00597 ret_cod = JF_RC_INTERNAL_ERROR; 00598 } /* switch (excp) */ 00599 } /* TRY-CATCH */ 00600 JF_TRACE(("jf_file_size/excp=%d/ret_cod=%d/errno=%d\n", 00601 excp, ret_cod, errno)); 00602 return ret_cod; 00603 } 00604 00605 00606 00607 int jf_file_write(jf_file_t *jf, const void *data, 00608 size_t size, size_t *write_number) 00609 { 00610 enum Exception { NOTHING_TO_DO 00611 , JOURNAL_ADD_DATA 00612 , NONE } excp; 00613 int ret_cod = JF_RC_INTERNAL_ERROR; 00614 00615 JF_TRACE(("jf_file_write\n")); 00616 TRY { 00617 jf_journal_t *journal = jf_file_get_journal(jf); 00618 00619 if (size == 0) 00620 THROW(NOTHING_TO_DO); 00621 00622 ret_cod = jf_journal_add_byte_data(journal, jf_file_get_id(jf), 00623 (byte_t *)data, size); 00624 if (JF_RC_OK != ret_cod) 00625 THROW(JOURNAL_ADD_DATA); 00626 00627 *write_number = size; 00628 THROW(NONE); 00629 } CATCH { 00630 switch (excp) { 00631 case JOURNAL_ADD_DATA: 00632 break; 00633 case NOTHING_TO_DO: 00634 case NONE: 00635 ret_cod = JF_RC_OK; 00636 break; 00637 default: 00638 ret_cod = JF_RC_INTERNAL_ERROR; 00639 } /* switch (excp) */ 00640 } /* TRY-CATCH */ 00641 JF_TRACE(("jf_file_write/excp=%d/ret_cod=%d/errno=%d\n", 00642 excp, ret_cod, errno)); 00643 return ret_cod; 00644 } 00645 00646 00647 00648 int jf_file_read(jf_file_t *jf, void *data, size_t size, size_t *read_number) 00649 { 00650 enum Exception { JOURNAL_GET_DATA 00651 , NONE } excp; 00652 int ret_cod = JF_RC_INTERNAL_ERROR; 00653 00654 JF_TRACE(("jf_file_read\n")); 00655 TRY { 00656 jf_journal_t *journal = jf_file_get_journal(jf); 00657 00658 ret_cod = jf_journal_get_byte_data( 00659 journal, jf_file_get_id(jf), 00660 (byte_t *)data, size, read_number); 00661 if (JF_RC_OK != ret_cod) 00662 THROW(JOURNAL_GET_DATA); 00663 00664 THROW(NONE); 00665 } CATCH { 00666 switch (excp) { 00667 case JOURNAL_GET_DATA: 00668 break; 00669 case NONE: 00670 ret_cod = JF_RC_OK; 00671 break; 00672 default: 00673 ret_cod = JF_RC_INTERNAL_ERROR; 00674 } /* switch (excp) */ 00675 } /* TRY-CATCH */ 00676 JF_TRACE(("jf_file_read/excp=%d/ret_cod=%d/errno=%d\n", 00677 excp, ret_cod, errno)); 00678 return ret_cod; 00679 } 00680 00681 00682 00683 int jf_file_putc(jf_file_t *jf, int c) 00684 { 00685 enum Exception { JOURNAL_BUFFER_ADD_C 00686 , NONE } excp; 00687 int ret_cod = JF_RC_INTERNAL_ERROR; 00688 00689 JF_TRACE(("jf_file_putc\n")); 00690 TRY { 00691 jf_journal_t *journal = jf_file_get_journal(jf); 00692 00693 ret_cod = jf_journal_add_c(journal, jf_file_get_id(jf), c); 00694 if (JF_RC_OK != ret_cod) 00695 THROW(JOURNAL_BUFFER_ADD_C); 00696 00697 THROW(NONE); 00698 } CATCH { 00699 switch (excp) { 00700 case JOURNAL_BUFFER_ADD_C: 00701 break; 00702 case NONE: 00703 ret_cod = JF_RC_OK; 00704 break; 00705 default: 00706 ret_cod = JF_RC_INTERNAL_ERROR; 00707 } /* switch (excp) */ 00708 } /* TRY-CATCH */ 00709 JF_TRACE(("jf_file_putc/excp=%d/ret_cod=%d\n", 00710 excp, ret_cod)); 00711 return ret_cod; 00712 } 00713 00714 00715 00716 int jf_file_puts(jf_file_t *jf, const char *s) 00717 { 00718 enum Exception { NOTHING_TO_DO 00719 , JOURNAL_ADD_DATA 00720 , NONE } excp; 00721 int ret_cod = JF_RC_INTERNAL_ERROR; 00722 00723 JF_TRACE(("jf_file_puts\n")); 00724 TRY { 00725 jf_journal_t *journal = jf_file_get_journal(jf); 00726 size_t size = strlen(s); 00727 00728 if (size == 0) 00729 THROW(NOTHING_TO_DO); 00730 00731 ret_cod = jf_journal_add_byte_data(journal, jf_file_get_id(jf), 00732 (byte_t *)s, size); 00733 if (JF_RC_OK != ret_cod) 00734 THROW(JOURNAL_ADD_DATA); 00735 00736 THROW(NONE); 00737 } CATCH { 00738 switch (excp) { 00739 case JOURNAL_ADD_DATA: 00740 break; 00741 case NOTHING_TO_DO: 00742 case NONE: 00743 ret_cod = JF_RC_OK; 00744 break; 00745 default: 00746 ret_cod = JF_RC_INTERNAL_ERROR; 00747 } /* switch (excp) */ 00748 } /* TRY-CATCH */ 00749 JF_TRACE(("jf_file_puts/excp=%d/ret_cod=%d/errno=%d\n", 00750 excp, ret_cod, errno)); 00751 return ret_cod; 00752 } 00753 00754 00755 00756 int jf_file_getc(jf_file_t *jf, int *c) 00757 { 00758 enum Exception { INVALID_OBJECT 00759 , JOURNAL_BUFFER_GET_C 00760 , NONE } excp; 00761 int ret_cod = JF_RC_INTERNAL_ERROR; 00762 00763 JF_TRACE(("jf_file_getc\n")); 00764 TRY { 00765 jf_journal_t *journal; 00766 jf_word_t jf_id; 00767 jf_journal_file_t *jfile; 00768 00769 if (!jf_file_is_safe(jf)) 00770 THROW(INVALID_OBJECT); 00771 00772 jf_id = jf_file_get_id(jf); 00773 journal = jf_file_get_journal(jf); 00774 jfile = jf_journal_get_jfile(journal, jf_id); 00775 00776 ret_cod = jf_journal_get_c(journal, jf_id, c); 00777 if (JF_RC_OK != ret_cod) 00778 THROW(JOURNAL_BUFFER_GET_C); 00779 *c &= 0xff; 00780 00781 THROW(NONE); 00782 } CATCH { 00783 switch (excp) { 00784 case INVALID_OBJECT: 00785 ret_cod = JF_RC_OBJ_CORRUPTED; 00786 break; 00787 case JOURNAL_BUFFER_GET_C: 00788 break; 00789 case NONE: 00790 ret_cod = JF_RC_OK; 00791 break; 00792 default: 00793 ret_cod = JF_RC_INTERNAL_ERROR; 00794 } /* switch (excp) */ 00795 } /* TRY-CATCH */ 00796 JF_TRACE(("jf_file_getc/excp=%d/ret_cod=%d/errno=%d\n", 00797 excp, ret_cod, errno)); 00798 return ret_cod; 00799 } 00800 00801 00802 00803 int jf_file_gets(jf_file_t *jf, size_t size, char *s) 00804 { 00805 enum Exception { INVALID_OBJECT 00806 , JOURNAL_BUFFER_GET_C 00807 , NONE } excp; 00808 int ret_cod = JF_RC_INTERNAL_ERROR; 00809 00810 JF_TRACE(("jf_file_gets\n")); 00811 TRY { 00812 size_t i = 0; 00813 jf_journal_t *journal; 00814 jf_word_t jf_id; 00815 jf_journal_file_t *jfile; 00816 00817 if (!jf_file_is_safe(jf)) 00818 THROW(INVALID_OBJECT); 00819 00820 jf_id = jf_file_get_id(jf); 00821 journal = jf_file_get_journal(jf); 00822 jfile = jf_journal_get_jfile(journal, jf_id); 00823 00824 for (i = 0; i < size - 1; ++i) { 00825 int c; 00826 ret_cod = jf_journal_get_c( 00827 journal, jf_file_get_id(jf), &c); 00828 if (JF_RC_EOF == ret_cod) 00829 break; 00830 if (JF_RC_OK != ret_cod) 00831 THROW(JOURNAL_BUFFER_GET_C); 00832 c &= 0xff; 00833 s[i] = c; 00834 if (c == '\n') 00835 break; 00836 } /* for (i = 0; i < size; ++i) */ 00837 s[++i] = '\0'; 00838 00839 THROW(NONE); 00840 } CATCH { 00841 switch (excp) { 00842 case INVALID_OBJECT: 00843 ret_cod = JF_RC_OBJ_CORRUPTED; 00844 break; 00845 case JOURNAL_BUFFER_GET_C: 00846 break; 00847 case NONE: 00848 ret_cod = JF_RC_OK; 00849 break; 00850 default: 00851 ret_cod = JF_RC_INTERNAL_ERROR; 00852 } /* switch (excp) */ 00853 } /* TRY-CATCH */ 00854 JF_TRACE(("jf_file_gets/excp=%d/" 00855 "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); 00856 return ret_cod; 00857 } 00858 00859 00860 00861 #ifdef HAVE_VSNPRINTF 00862 int jf_file_printf(jf_file_t *jf, size_t *write_number, 00863 const char *format, ...) 00864 { 00865 enum Exception { VPRINTF_ERROR 00866 , NONE } excp; 00867 int ret_cod = JF_RC_INTERNAL_ERROR; 00868 00869 JF_TRACE(("jf_file_printf\n")); 00870 TRY { 00871 va_list ap; 00872 va_start(ap, format); 00873 00874 ret_cod = jf_file_vprintf(jf, write_number, format, ap); 00875 if (JF_RC_OK != ret_cod) 00876 THROW(VPRINTF_ERROR); 00877 00878 va_end(ap); 00879 00880 THROW(NONE); 00881 } CATCH { 00882 switch (excp) { 00883 case VPRINTF_ERROR: 00884 break; 00885 case NONE: 00886 ret_cod = JF_RC_OK; 00887 break; 00888 default: 00889 ret_cod = JF_RC_INTERNAL_ERROR; 00890 } /* switch (excp) */ 00891 } /* TRY-CATCH */ 00892 JF_TRACE(("jf_file_printf/excp=%d/" 00893 "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); 00894 return ret_cod; 00895 } 00896 00897 00898 00899 int jf_file_vprintf(jf_file_t *jf, size_t *write_number, const char *format, 00900 va_list ap) 00901 { 00902 enum Exception { INVALID_BUFFER 00903 , MALLOC_ERROR1 00904 , VSNPRINTF_ERROR 00905 , MALLOC_ERROR2 00906 , FILE_WRITE 00907 , NONE } excp; 00908 int ret_cod = JF_RC_INTERNAL_ERROR; 00909 00910 JF_TRACE(("jf_file_vprintf\n")); 00911 TRY { 00912 int chars; 00913 *write_number = 0; 00914 uint32_t flags; 00915 00916 # ifdef _EXTRA_CHECK 00917 if ((NULL == jf->char_buffer && 0 != jf->char_buffer_size) || 00918 (NULL != jf->char_buffer && 0 == jf->char_buffer_size)) 00919 THROW(INVALID_BUFFER); 00920 # endif /* _EXTRA_CHECK */ 00921 00922 if (NULL == jf->char_buffer) { 00923 jf->char_buffer = (char *)malloc( 00924 JF_FILE_BUFFER_PAGE_SIZE); 00925 if (NULL == jf->char_buffer) 00926 THROW(MALLOC_ERROR1); 00927 jf->char_buffer_size = JF_FILE_BUFFER_PAGE_SIZE; 00928 } /* if (NULL == jf->char_buffer) */ 00929 00930 while (TRUE) { 00931 va_list aq; 00932 # ifdef HAVE_VA_COPY 00933 va_copy(aq, ap); 00934 # else 00935 if (sizeof(aq) == sizeof(ap)) 00936 memcpy(&aq, &ap, sizeof(va_list)); 00937 else 00938 memcpy(&aq, ap, sizeof(va_list)); 00939 # endif /* HAVE_VA_COPY */ 00940 chars = vsnprintf(jf->char_buffer, 00941 jf->char_buffer_size, format, aq); 00942 va_end(aq); 00943 00944 if (chars > 0 && chars < jf->char_buffer_size) 00945 break; 00946 /* detect error or expand buffer */ 00947 if (chars < 0) 00948 THROW(VSNPRINTF_ERROR); 00949 free(jf->char_buffer); 00950 jf->char_buffer_size += JF_FILE_BUFFER_PAGE_SIZE; 00951 jf->char_buffer = (char *)malloc(jf->char_buffer_size); 00952 if (NULL == jf->char_buffer) 00953 THROW(MALLOC_ERROR2); 00954 } /* while (TRUE) */ 00955 00956 ret_cod = jf_file_write(jf, jf->char_buffer, chars, 00957 write_number); 00958 if (JF_RC_OK != ret_cod) 00959 THROW(FILE_WRITE); 00960 00961 flags = jf_journal_get_open_opts_flags( 00962 jf_file_get_journal(jf)); 00963 if ((flags & JF_JOURNAL_PROP_VIRTMEM_LOW) || 00964 ((flags & JF_JOURNAL_PROP_VIRTMEM_MEDIUM) && 00965 (chars + JF_FILE_BUFFER_PAGE_SIZE < 00966 jf->char_buffer_size))) { 00967 /* release storage */ 00968 free(jf->char_buffer); 00969 jf->char_buffer = NULL; 00970 jf->char_buffer_size = 0; 00971 } /* if ((flags & JF_JOURNAL_PROP_STORAGE_LOW) || ... */ 00972 00973 THROW(NONE); 00974 } CATCH { 00975 switch (excp) { 00976 case INVALID_BUFFER: 00977 ret_cod = JF_RC_INVALID_STATUS; 00978 break; 00979 case MALLOC_ERROR1: 00980 case MALLOC_ERROR2: 00981 ret_cod = JF_RC_MALLOC_ERROR; 00982 break; 00983 case VSNPRINTF_ERROR: 00984 ret_cod = JF_RC_VSNPRINTF_ERROR; 00985 break; 00986 case FILE_WRITE: 00987 break; 00988 case NONE: 00989 ret_cod = JF_RC_OK; 00990 break; 00991 default: 00992 ret_cod = JF_RC_INTERNAL_ERROR; 00993 } /* switch (excp) */ 00994 } /* TRY-CATCH */ 00995 JF_TRACE(("jf_file_vprintf/excp=%d/" 00996 "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); 00997 return ret_cod; 00998 } 00999 #endif /* HAVE_VSNPRINTF */ 01000 01001 01002

Copyright 2005 © Tiian