libjf API reference guide

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

jf_utils.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_SYS_STAT_H 00025 # include <sys/stat.h> 00026 #endif /* HAVE_SYS_STAT_H */ 00027 #ifdef HAVE_SYS_TYPES_H 00028 # include <sys/types.h> 00029 #endif /* HAVE_SYS_TYPES_H */ 00030 #ifdef HAVE_UNISTD_H 00031 # include <unistd.h> 00032 #endif /* HAVE_UNISTD_H */ 00033 #ifdef HAVE_STRING_H 00034 # include <string.h> 00035 #endif /* HAVE_STRING_H */ 00036 00037 #include <jf/jf_utils.h> 00038 #include <jf/jf_errors.h> 00039 #include <jf_journal.h> 00040 00041 00042 00043 /* set module trace flag */ 00044 #ifdef JF_TRACE_MODULE 00045 # undef JF_TRACE_MODULE 00046 #endif /* JF_TRACE_MODULE */ 00047 #define JF_TRACE_MODULE JF_TRACE_MOD_LIB_UTILS 00048 00049 00050 00051 const char *jf_feature_debug = "feature/debug = " 00052 JF_FEATURE_DEBUG_ACTIVE; 00053 00054 const char *jf_feature_crash_simul = "feature/crash_simul = " 00055 JF_FEATURE_CRASH_SIMUL_ACTIVE; 00056 00057 const char *jf_feature_cache_stress = "feature/cache_stress = " 00058 JF_FEATURE_CACHE_STRESS_ACTIVE; 00059 00060 const char *jf_feature_extra_check = "feature/extra_check = " 00061 JF_FEATURE_EXTRA_CHECK_ACTIVE; 00062 00063 00064 00065 int jf_translate_NL_CRLF(const byte_t *in_data, jf_word_t in_size, 00066 byte_t **out_data, jf_word_t *out_size) 00067 { 00068 enum Exception { MALLOC_ERROR 00069 , NONE } excp; 00070 int ret_cod = JF_RC_INTERNAL_ERROR; 00071 00072 JF_TRACE(("jf_translate_NL_CRLF\n")); 00073 TRY { 00074 jf_word_t i, count = 0, new_size; 00075 jf_word_t j = 0; 00076 byte_t *new_buffer; 00077 00078 /* count number of substitution */ 00079 for (i = 0; i < in_size; ++i) 00080 if (in_data[i] == '\n') 00081 count++; 00082 00083 /* prepare new buffer for translation result */ 00084 new_size = in_size + count; 00085 if (NULL == (new_buffer = malloc(new_size))) 00086 THROW(MALLOC_ERROR); 00087 00088 /* substitute: '\n' -> "\r\n" */ 00089 for (i = 0; i < in_size; ++i) { 00090 if (in_data[i] == '\n') { 00091 new_buffer[j++] = '\r'; 00092 new_buffer[j++] = '\n'; 00093 } else 00094 new_buffer[j++] = in_data[i]; 00095 } /* for (i = 0; i < b->used; ++i) */ 00096 00097 *out_size = new_size; 00098 *out_data = new_buffer; 00099 00100 THROW(NONE); 00101 } CATCH { 00102 switch (excp) { 00103 case MALLOC_ERROR: 00104 ret_cod = JF_RC_MALLOC_ERROR; 00105 break; 00106 case NONE: 00107 ret_cod = JF_RC_OK; 00108 break; 00109 default: 00110 ret_cod = JF_RC_INTERNAL_ERROR; 00111 } /* switch (excp) */ 00112 } /* TRY-CATCH */ 00113 JF_TRACE(("jf_translate_NL_CRLF/excp=%d/ret_cod=%d/errno=%d\n", 00114 excp, ret_cod, errno)); 00115 return ret_cod; 00116 } 00117 00118 00119 00120 int jf_translate_CRLF_NL(byte_t *data, jf_word_t *size) 00121 { 00122 enum Exception { MALLOC_ERROR 00123 , NONE } excp; 00124 int ret_cod = JF_RC_INTERNAL_ERROR; 00125 00126 JF_TRACE(("jf_translate_CRLF_NL\n")); 00127 TRY { 00128 jf_word_t i = 0, j = 0; 00129 int prev_is_CR = FALSE; 00130 00131 while (i < *size) { 00132 if ('\r' == data[i]) { 00133 prev_is_CR = TRUE; 00134 if (j != i) data[j] = data[i]; 00135 ++i; ++j; 00136 } else if ('\n' == data[i]) { 00137 if (prev_is_CR) { 00138 data[j-1] = data[i]; 00139 ++i; 00140 } else { 00141 if (j != i) data[j] = data[i]; 00142 ++i; ++j; 00143 } /* if (prev_is_CR) */ 00144 prev_is_CR = FALSE; 00145 } else { 00146 if (j != i) data[j] = data[i]; 00147 ++i; ++j; 00148 prev_is_CR = FALSE; 00149 } /* if ('\r' == data[i]) */ 00150 } /* while (i < *size) */ 00151 00152 *size = j; 00153 00154 THROW(NONE); 00155 } CATCH { 00156 switch (excp) { 00157 case NONE: 00158 ret_cod = JF_RC_OK; 00159 break; 00160 default: 00161 ret_cod = JF_RC_INTERNAL_ERROR; 00162 } /* switch (excp) */ 00163 } /* TRY-CATCH */ 00164 JF_TRACE(("jf_translate_CRLF_NL/excp=%d/ret_cod=%d/errno=%d\n", 00165 excp, ret_cod, errno)); 00166 return ret_cod; 00167 } 00168 00169 00170 00171 unsigned long jf_magnitude(unsigned long v) 00172 { 00173 #if (SIZEOF_LONG_INT==4) 00174 const unsigned long masks[] = {0xffff0000, 0xff000000, 00175 0xf0000000, 0xc0000000, 00176 0x80000000}; 00177 const long values[] = {16, 8, 4, 2, 1}; 00178 #elif (SIZEOF_LONG_INT==8) 00179 const unsigned long masks[] = {0xffffffff00000000, 00180 0xffff000000000000, 00181 0xff00000000000000, 00182 0xf000000000000000, 00183 0xc000000000000000, 00184 0x8000000000000000}; 00185 const long values[] = {32, 16, 8, 4, 2, 1}; 00186 #else 00187 # error "Fix this function please!" 00188 #endif /* (SIZEOF_LONG_INT==4) */ 00189 int i; 00190 long r = v > 0 ? 1 : 0; 00191 00192 for (i = 0; i < sizeof(masks)/sizeof(unsigned long); ++i) { 00193 unsigned long v2 = v & masks[i]; 00194 if (v2 > 0) 00195 r += values[i]; 00196 else 00197 v <<= values[i]; 00198 } /* for (i = 0; i < sizeof(masks)/sizeof(unsigned long); ++i) */ 00199 return r; 00200 } 00201 00202 00203 00204 int jf_stream_truncate(FILE *stream, jf_offset_t size) 00205 { 00206 enum Exception { FFLUSH_ERROR 00207 , FILENO_ERROR 00208 , FTRUNCATE_ERROR 00209 , NONE } excp; 00210 int ret_cod = JF_RC_INTERNAL_ERROR; 00211 00212 JF_TRACE(("jf_stream_truncate\n")); 00213 TRY { 00214 int fd; 00215 00216 /* the stream must be flushed to download memory buffers */ 00217 if (0 != fflush(stream)) 00218 THROW(FFLUSH_ERROR); 00219 #if defined(HAVE_FILENO) && defined(HAVE_FTRUNCATE) 00220 if (0 > (fd = fileno(stream))) 00221 THROW(FILENO_ERROR); 00222 if (0 != ftruncate(fd, (off_t)size)) 00223 THROW(FTRUNCATE_ERROR); 00224 #else 00225 # error "Something like ftruncate & fileno is necessary..." 00226 #endif /* HAVE_FILENO */ 00227 THROW(NONE); 00228 } CATCH { 00229 switch (excp) { 00230 case FFLUSH_ERROR: 00231 ret_cod = JF_RC_FFLUSH_ERROR; 00232 break; 00233 case FILENO_ERROR: 00234 ret_cod = JF_RC_FILENO_ERROR; 00235 break; 00236 case FTRUNCATE_ERROR: 00237 ret_cod = JF_RC_FTRUNCATE_ERROR; 00238 break; 00239 case NONE: 00240 ret_cod = JF_RC_OK; 00241 break; 00242 default: 00243 ret_cod = JF_RC_INTERNAL_ERROR; 00244 } /* switch (excp) */ 00245 } /* TRY-CATCH */ 00246 JF_TRACE(("jf_stream_truncate/excp=%d/" 00247 "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); 00248 return ret_cod; 00249 } 00250 00251 00252 00253 int jf_stream_size(FILE *stream, jf_offset_t *size) 00254 { 00255 enum Exception { FFLUSH_ERROR 00256 , FILENO_ERROR 00257 , FSTAT_ERROR 00258 , FTELL_ERROR1 00259 , FSEEK_ERROR1 00260 , FTELL_ERROR2 00261 , FSEEK_ERROR2 00262 , NONE } excp; 00263 int ret_cod = JF_RC_INTERNAL_ERROR; 00264 00265 JF_TRACE(("jf_stream_size\n")); 00266 TRY { 00267 #if defined(HAVE_FILENO) && defined(HAVE_FSTAT) 00268 int fd; 00269 struct stat file_stat; 00270 if (0 != fflush(stream)) 00271 THROW(FFLUSH_ERROR); 00272 if (-1 == (fd = fileno(stream))) 00273 THROW(FILENO_ERROR); 00274 if (0 != fstat(fd, &file_stat)) 00275 THROW(FSTAT_ERROR); 00276 *size = (jf_offset_t)(file_stat.st_size); 00277 #else 00278 jf_offset_t current_pos; 00279 if (0 > (current_pos = ftello(stream))) 00280 THROW(FTELL_ERROR1); 00281 if (0 != fseeko(stream, SEEK_END, 0)) 00282 THROW(FSEEK_ERROR1); 00283 if (0 > (*size = ftello(stream))) 00284 THROW(FTELL_ERROR2); 00285 if (0 != fseeko(stream, SEEK_SET, current_pos)) 00286 THROW(FSEEK_ERROR2); 00287 #endif /* defined(HAVE_FILENO) && defined(HAVE_FSTAT) */ 00288 00289 THROW(NONE); 00290 } CATCH { 00291 switch (excp) { 00292 case FFLUSH_ERROR: 00293 ret_cod = JF_RC_FFLUSH_ERROR; 00294 break; 00295 case FILENO_ERROR: 00296 ret_cod = JF_RC_FILENO_ERROR; 00297 break; 00298 case FSTAT_ERROR: 00299 ret_cod = JF_RC_FSTAT_ERROR; 00300 break; 00301 case FTELL_ERROR1: 00302 case FTELL_ERROR2: 00303 ret_cod = JF_RC_FTELL_ERROR; 00304 break; 00305 case FSEEK_ERROR1: 00306 case FSEEK_ERROR2: 00307 ret_cod = JF_RC_FSEEK_ERROR; 00308 break; 00309 case NONE: 00310 ret_cod = JF_RC_OK; 00311 break; 00312 default: 00313 ret_cod = JF_RC_INTERNAL_ERROR; 00314 } /* switch (excp) */ 00315 } /* TRY-CATCH */ 00316 JF_TRACE(("jf_stream_size/excp=%d/" 00317 "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); 00318 return ret_cod; 00319 } 00320 00321 00322 00323 00324 int jf_stream_sync(FILE *stream, jf_word_t policy) 00325 { 00326 enum Exception { INVALID_STREAM 00327 , FFLUSH_ERROR 00328 , FDATASYNC_ERROR 00329 , FSYNC_ERROR 00330 , NONE } excp; 00331 int ret_cod = JF_RC_INTERNAL_ERROR; 00332 00333 JF_TRACE(("jf_stream_sync: stream = %p\n", stream)); 00334 TRY { 00335 #ifdef _EXTRA_CHECK 00336 if (NULL == stream) 00337 THROW(INVALID_STREAM); 00338 #endif /* _EXTRA_CHECK */ 00339 if (0 != fflush(stream)) 00340 THROW(FFLUSH_ERROR); 00341 if (policy & JF_JOURNAL_PROP_SYNC_SAFE) { 00342 int fd = fileno(stream); 00343 JF_TRACE(("jf_stream_sync: fdatasync/fsync in progress" 00344 " fd = %d\n", fd)); 00345 fflush(stderr); 00346 #ifdef HAVE_FDATASYNC 00347 if (0 > fdatasync(fd)) 00348 THROW(FDATASYNC_ERROR); 00349 #elif defined(HAVE_FSYNC) 00350 if (0 > fsync(fd)) 00351 THROW(FSYNC_ERROR); 00352 #else 00353 # error Something like "fsync/fdatasync" is required to assure disk data sync 00354 #endif 00355 } /* if (policy & JF_JOURNAL_PROP_SYNC_SAFE) */ 00356 00357 THROW(NONE); 00358 } CATCH { 00359 switch (excp) { 00360 case INVALID_STREAM: 00361 ret_cod = JF_RC_NULL_OBJECT; 00362 break; 00363 case FFLUSH_ERROR: 00364 ret_cod = JF_RC_FFLUSH_ERROR; 00365 break; 00366 case FDATASYNC_ERROR: 00367 ret_cod = JF_RC_FDATASYNC_ERROR; 00368 break; 00369 case FSYNC_ERROR: 00370 ret_cod = JF_RC_FSYNC_ERROR; 00371 break; 00372 case NONE: 00373 ret_cod = JF_RC_OK; 00374 break; 00375 default: 00376 ret_cod = JF_RC_INTERNAL_ERROR; 00377 } /* switch (excp) */ 00378 } /* TRY-CATCH */ 00379 JF_TRACE(("jf_stream_sync/excp=%d/" 00380 "ret_cod=%d/errno=%d\n", excp, ret_cod, errno)); 00381 return ret_cod; 00382 } 00383 00384 00385 00386 int jf_path_is_absolute(const char *path) 00387 #ifndef _DOS_FILESYSTEM_SCHEME 00388 { 00389 return *path == JF_PATH_SEPARATOR; 00390 } 00391 #else 00392 { 00393 size_t i, len = strlen(path); 00394 int state = 0; 00395 00396 for (i=0; i<len; ++i) { 00397 char c = path[i]; 00398 switch (state) { 00399 case 0: 00400 if (isalpha(c)) 00401 state = 1; 00402 else if (JF_PATH_SEPARATOR == c) 00403 state = 3; 00404 else 00405 state = 4; 00406 break; 00407 case 1: 00408 if (':' == c) 00409 state = 2; 00410 else 00411 state = 4; 00412 break; 00413 case 2: 00414 if (JF_PATH_SEPARATOR == c) 00415 state = 3; 00416 else 00417 state = 4; 00418 break; 00419 case 3: 00420 return TRUE; 00421 break; 00422 case 4: 00423 return FALSE; 00424 break; 00425 default: 00426 JF_TRACE(("jf_path_is_absolute: invalid state %d\n", 00427 state)); 00428 abort(); 00429 } /* switch (state) */ 00430 } /* for (i=0; i<len; ++i) */ 00431 /* never reached, only to avoid warnings */ 00432 return FALSE; 00433 } 00434 #endif /* _DOS_FILESYSTEM_SCHEME */ 00435 00436

Copyright 2005 © Tiian