00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <jf/jf_config.h>
00021
00022
00023
00024
#ifdef HAVE_SYS_STAT_H
00025
# include <sys/stat.h>
00026
#endif
00027
#ifdef HAVE_SYS_TYPES_H
00028
# include <sys/types.h>
00029
#endif
00030
#ifdef HAVE_UNISTD_H
00031
# include <unistd.h>
00032
#endif
00033
#ifdef HAVE_STRING_H
00034
# include <string.h>
00035
#endif
00036
00037
#include <jf/jf_utils.h>
00038
#include <jf/jf_errors.h>
00039
#include <jf_journal.h>
00040
00041
00042
00043
00044
#ifdef JF_TRACE_MODULE
00045
# undef JF_TRACE_MODULE
00046
#endif
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
00079
for (i = 0; i < in_size; ++i)
00080
if (in_data[i] ==
'\n')
00081 count++;
00082
00083
00084 new_size = in_size + count;
00085
if (NULL == (new_buffer = malloc(new_size)))
00086
THROW(MALLOC_ERROR);
00087
00088
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 }
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 }
00112 }
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 }
00144 prev_is_CR =
FALSE;
00145 }
else {
00146
if (j != i) data[j] = data[i];
00147 ++i; ++j;
00148 prev_is_CR =
FALSE;
00149 }
00150 }
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 }
00163 }
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
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 }
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
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
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 }
00245 }
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
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 }
00315 }
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
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
}
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 }
00378 }
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 }
00430 }
00431
00432
return FALSE;
00433 }
00434
#endif
00435
00436