00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00032 #include <string.h>
00033 #include <sys/stat.h>
00034 #include <unistd.h>
00035 #include <dirent.h>
00036 #include <errno.h>
00037
00038 #ifdef __WIN32__
00039 #include <shlwapi.h>
00040 #endif
00041
00042 #include "splt.h"
00043
00044 static int splt_u_fname_is_directory_parent(char *fname, int fname_size);
00045
00046 int splt_io_input_is_stdin(splt_state *state)
00047 {
00048 char *filename = splt_t_get_filename_to_split(state);
00049
00050 if (filename && filename[0] != '\0')
00051 {
00052 if ((strcmp(filename,"-") == 0) ||
00053 (filename[strlen(filename)-1] == '-'))
00054 {
00055 return SPLT_TRUE;
00056 }
00057 }
00058
00059 return SPLT_FALSE;
00060 }
00061
00062 int splt_io_input_is_stdout(splt_state *state)
00063 {
00064 const char *oformat = splt_of_get_oformat(state);
00065
00066 if (oformat && oformat[0] != '\0')
00067 {
00068 if ((strcmp(oformat,"-") == 0))
00069 {
00070 return SPLT_TRUE;
00071 }
00072 else
00073 {
00074 return SPLT_FALSE;
00075 }
00076 }
00077
00078 return SPLT_FALSE;
00079 }
00080
00081 static int splt_io_file_type_is(const char *fname, int file_type)
00082 {
00083 mode_t st_mode;
00084 int status = splt_io_stat(fname, &st_mode, NULL);
00085 if (status == 0)
00086 {
00087 if ((st_mode & S_IFMT) == file_type)
00088 {
00089 return SPLT_TRUE;
00090 }
00091 }
00092
00093 return SPLT_FALSE;
00094 }
00095
00096 #ifndef __WIN32__
00097 static char *splt_io_readlink(const char *fname)
00098 {
00099 int bufsize = 1024;
00100
00101 while (bufsize < INT_MAX)
00102 {
00103 char *linked_fname = malloc(sizeof(char) * bufsize);
00104 if (linked_fname == NULL)
00105 {
00106 return NULL;
00107 }
00108
00109 ssize_t real_link_size = readlink(fname, linked_fname, bufsize);
00110 if (real_link_size == -1)
00111 {
00112 free(linked_fname);
00113 return NULL;
00114 }
00115
00116 if (real_link_size < bufsize)
00117 {
00118 linked_fname[real_link_size] = '\0';
00119 return linked_fname;
00120 }
00121
00122 free(linked_fname);
00123 bufsize += 1024;
00124 }
00125
00126 return NULL;
00127 }
00128
00129 char *splt_io_get_linked_fname(const char *fname, int *number_of_symlinks)
00130 {
00131 char *previous_linked_fname = NULL;
00132
00133 char *linked_fname = splt_io_readlink(fname);
00134 if (!linked_fname)
00135 {
00136 return NULL;
00137 }
00138
00139 int count = 0;
00140 while (linked_fname != NULL)
00141 {
00142 if (previous_linked_fname)
00143 {
00144 free(previous_linked_fname);
00145 }
00146 previous_linked_fname = linked_fname;
00147 linked_fname = splt_io_readlink(linked_fname);
00148
00149 count++;
00150 if (count > MAX_SYMLINKS)
00151 {
00152 if (previous_linked_fname)
00153 {
00154 free(previous_linked_fname);
00155 previous_linked_fname = NULL;
00156 }
00157 if (linked_fname)
00158 {
00159 free(linked_fname);
00160 }
00161 if (number_of_symlinks)
00162 {
00163 *number_of_symlinks = MAX_SYMLINKS;
00164 }
00165 return NULL;
00166 }
00167 }
00168
00169 if (number_of_symlinks)
00170 {
00171 *number_of_symlinks = count;
00172 }
00173
00174 linked_fname = previous_linked_fname;
00175
00176 if (linked_fname[0] == SPLT_DIRCHAR)
00177 {
00178 return linked_fname;
00179 }
00180
00181 char *slash_ptr = strrchr(fname, SPLT_DIRCHAR);
00182 if (slash_ptr == NULL)
00183 {
00184 return linked_fname;
00185 }
00186
00187 char *linked_fname_with_path = NULL;
00188
00189 size_t path_size = slash_ptr - fname + 1;
00190 int err = splt_su_append(&linked_fname_with_path, fname, path_size, NULL);
00191 if (err != SPLT_OK)
00192 {
00193 free(linked_fname);
00194 return NULL;
00195 }
00196
00197 err = splt_su_append_str(&linked_fname_with_path, linked_fname, NULL);
00198 if (err != SPLT_OK)
00199 {
00200 free(linked_fname);
00201 free(linked_fname_with_path);
00202 return NULL;
00203 }
00204
00205 free(linked_fname);
00206 linked_fname = NULL;
00207
00208 return linked_fname_with_path;
00209 }
00210
00211 static int splt_io_linked_file_type_is(const char *fname, int file_type)
00212 {
00213 int linked_file_is_of_type = SPLT_FALSE;
00214
00215 int number_of_symlinks = 0;
00216 char *linked_fname = splt_io_get_linked_fname(fname, &number_of_symlinks);
00217 if (linked_fname)
00218 {
00219 if (splt_io_file_type_is(linked_fname, file_type))
00220 {
00221 linked_file_is_of_type = SPLT_TRUE;
00222 }
00223
00224 free(linked_fname);
00225 linked_fname = NULL;
00226 }
00227
00228 if (number_of_symlinks == MAX_SYMLINKS)
00229 {
00230 errno = ELOOP;
00231 }
00232
00233 return linked_file_is_of_type;
00234 }
00235 #endif
00236
00237 int splt_io_check_if_directory(const char *fname)
00238 {
00239 #ifdef __WIN32__
00240 int is_file = splt_io_check_if_file(NULL, fname);
00241 if (is_file)
00242 {
00243 return SPLT_FALSE;
00244 }
00245
00246 if (splt_w32_check_if_encoding_is_utf8(fname))
00247 {
00248 wchar_t *wpath = splt_w32_utf8_to_utf16(fname);
00249 if (PathFileExistsW(wpath) == 1)
00250 {
00251 free(wpath);
00252 return SPLT_TRUE;
00253 }
00254
00255 free(wpath);
00256 return SPLT_FALSE;
00257 }
00258 else
00259 {
00260 if (PathFileExistsA(fname) == 1)
00261 {
00262 return SPLT_TRUE;
00263 }
00264
00265 return SPLT_FALSE;
00266 }
00267 #endif
00268
00269 if (fname != NULL)
00270 {
00271 if (splt_io_file_type_is(fname, S_IFDIR))
00272 {
00273 return SPLT_TRUE;
00274 }
00275
00276 #ifndef __WIN32__
00277 int is_link = splt_io_file_type_is(fname, S_IFLNK);
00278 if (is_link && splt_io_linked_file_type_is(fname, S_IFDIR))
00279 {
00280 return SPLT_TRUE;
00281 }
00282 #endif
00283 }
00284
00285 return SPLT_FALSE;
00286 }
00287
00288 int splt_io_check_if_file(splt_state *state, const char *fname)
00289 {
00290 errno = 0;
00291
00292 if (fname != NULL)
00293 {
00294
00295 if (fname[0] != '\0' && fname[strlen(fname)-1] == '-')
00296 {
00297 return SPLT_TRUE;
00298 }
00299
00300 if (splt_io_file_type_is(fname, S_IFREG))
00301 {
00302 return SPLT_TRUE;
00303 }
00304
00305 #ifndef __WIN32__
00306 int is_link = splt_io_file_type_is(fname, S_IFLNK);
00307 if (is_link && splt_io_linked_file_type_is(fname, S_IFREG))
00308 {
00309 return SPLT_TRUE;
00310 }
00311 #endif
00312 }
00313
00314 if (state != NULL)
00315 {
00316 splt_e_set_strerror_msg_with_data(state, fname);
00317 }
00318
00319 return SPLT_FALSE;
00320 }
00321
00322 int splt_io_get_word(FILE *in, off_t offset, int mode, unsigned long *headw)
00323 {
00324 int i;
00325 *headw = 0;
00326
00327 if (fseeko(in, offset, mode)==-1)
00328 {
00329 return -1;
00330 }
00331
00332 for (i=0; i<4; i++)
00333 {
00334 if (feof(in))
00335 {
00336 return -1;
00337 }
00338 *headw = *headw << 8;
00339 *headw |= fgetc(in);
00340 }
00341
00342 return 0;
00343 }
00344
00345 off_t splt_io_get_file_length(splt_state *state, FILE *in, const char *filename, int *error)
00346 {
00347 struct stat info;
00348 if (fstat(fileno(in), &info)==-1)
00349 {
00350 splt_e_set_strerror_msg_with_data(state, filename);
00351 *error = SPLT_ERROR_CANNOT_OPEN_FILE;
00352 return -1;
00353 }
00354 return info.st_size;
00355 }
00356
00357 void splt_io_create_output_dirs_if_necessary(splt_state *state,
00358 const char *output_filename, int *error)
00359 {
00360 if (splt_o_get_int_option(state, SPLT_OPT_CREATE_DIRS_FROM_FILENAMES))
00361 {
00362 char *only_dirs = strdup(output_filename);
00363 if (! only_dirs)
00364 {
00365 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00366 return;
00367 }
00368
00369 char *dir_char = strrchr(only_dirs, SPLT_DIRCHAR);
00370 if (dir_char != NULL)
00371 {
00372 *dir_char = '\0';
00373 #ifdef __WIN32__
00374 if (strlen(only_dirs) == 2 && only_dirs[1] == ':' &&
00375 strlen(output_filename) > 3)
00376 {
00377 *dir_char = SPLT_DIRCHAR;
00378 *(dir_char+1) = '\0';
00379 }
00380 #endif
00381 int err = splt_io_create_directories(state, only_dirs);
00382 if (err < 0) { *error = err; }
00383 }
00384
00385 free(only_dirs);
00386 only_dirs = NULL;
00387 }
00388 }
00389
00390 int splt_io_create_directories(splt_state *state, const char *dir)
00391 {
00392 int result = SPLT_OK;
00393
00394 if (dir == NULL || dir[0] == '\0')
00395 {
00396 return result;
00397 }
00398
00399 char *dir_to_create = malloc(sizeof(char) * (strlen(dir)+100));
00400 if (!dir_to_create)
00401 {
00402 return SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00403 }
00404
00405 splt_d_print_debug(state, "Starting to create directories for _%s_ ...\n", dir);
00406
00407 const char *ptr = dir;
00408
00409 #ifdef __WIN32__
00410 int first_time = SPLT_TRUE;
00411 #endif
00412
00413 while ((ptr = strchr(ptr, SPLT_DIRCHAR)) != NULL)
00414 {
00415
00416 #ifdef __WIN32__
00417 if (first_time && splt_w32_str_starts_with_drive_root_directory(dir))
00418 {
00419 ptr++;
00420 first_time = SPLT_FALSE;
00421 continue;
00422 }
00423 first_time = SPLT_FALSE;
00424 #endif
00425
00426 strncpy(dir_to_create, dir, ptr-dir);
00427 dir_to_create[ptr-dir] = '\0';
00428
00429 if (dir_to_create[0] != '\0')
00430 {
00431 splt_d_print_debug(state,"Checking if _%s_ is a directory ...\n", dir_to_create);
00432
00433 if (! splt_io_check_if_directory(dir_to_create))
00434 {
00435 splt_d_print_debug(state,"Creating directory _%s_ ...\n", dir_to_create);
00436
00437 if ((splt_io_mkdir(state, dir_to_create)) == -1)
00438 {
00439 splt_e_set_strerror_msg_with_data(state, dir_to_create);
00440 result = SPLT_ERROR_CANNOT_CREATE_DIRECTORY;
00441 goto end;
00442 }
00443 }
00444 }
00445
00446 ptr++;
00447 }
00448
00449 strncpy(dir_to_create, dir, strlen(dir) + 1);
00450
00451 if (! splt_io_check_if_directory(dir_to_create))
00452 {
00453 splt_d_print_debug(state,"Creating final directory _%s_ ...\n", dir_to_create);
00454
00455 if ((splt_io_mkdir(state, dir_to_create)) == -1)
00456 {
00457 splt_e_set_strerror_msg_with_data(state, dir_to_create);
00458 result = SPLT_ERROR_CANNOT_CREATE_DIRECTORY;
00459 }
00460 }
00461
00462 end:
00463 if (dir_to_create)
00464 {
00465 free(dir_to_create);
00466 dir_to_create = NULL;
00467 }
00468
00469 return result;
00470 }
00471
00472 FILE *splt_io_fopen(const char *filename, const char *mode)
00473 {
00474 #ifdef __WIN32__
00475 if (splt_w32_check_if_encoding_is_utf8(filename))
00476 {
00477 wchar_t *wfilename = splt_w32_utf8_to_utf16(filename);
00478 wchar_t *wmode = splt_w32_utf8_to_utf16(mode);
00479
00480 FILE *file = _wfopen(wfilename, wmode);
00481
00482 if (wfilename)
00483 {
00484 free(wfilename);
00485 wfilename = NULL;
00486 }
00487
00488 if (wmode)
00489 {
00490 free(wmode);
00491 wmode = NULL;
00492 }
00493
00494 return file;
00495 }
00496 else
00497 #endif
00498 {
00499 return fopen(filename, mode);
00500 }
00501 }
00502
00503 int splt_io_mkdir(splt_state *state, const char *path)
00504 {
00505 if (splt_o_get_int_option(state, SPLT_OPT_PRETEND_TO_SPLIT))
00506 {
00507 return 0;
00508 }
00509
00510 #ifdef __WIN32__
00511 if (splt_w32_check_if_encoding_is_utf8(path))
00512 {
00513 wchar_t *wpath = splt_w32_utf8_to_utf16(path);
00514
00515 int ret = _wmkdir(wpath);
00516
00517 if (wpath)
00518 {
00519 free(wpath);
00520 wpath = NULL;
00521 }
00522
00523 return ret;
00524 }
00525 else
00526 {
00527 return mkdir(path);
00528 }
00529 #else
00530 return mkdir(path, 0755);
00531 #endif
00532 }
00533
00534 int splt_io_stat(const char *path, mode_t *st_mode, off_t *st_size)
00535 {
00536 #ifdef __WIN32__
00537 if (splt_w32_check_if_encoding_is_utf8(path))
00538 {
00539 struct _stat buf;
00540 wchar_t *wpath = splt_w32_utf8_to_utf16(path);
00541
00542 int ret = _wstat(wpath, &buf);
00543
00544 if (wpath)
00545 {
00546 free(wpath);
00547 wpath = NULL;
00548 }
00549
00550 if (st_mode != NULL)
00551 {
00552 *st_mode = buf.st_mode;
00553 }
00554
00555 if (st_size != NULL)
00556 {
00557 *st_size = buf.st_size;
00558 }
00559
00560 return ret;
00561 }
00562 else
00563 #endif
00564 {
00565 struct stat buf;
00566
00567 #ifdef __WIN32__
00568 int ret = stat(path, &buf);
00569 #else
00570 int ret = lstat(path, &buf);
00571 #endif
00572
00573 if (st_mode != NULL)
00574 {
00575 *st_mode = buf.st_mode;
00576 }
00577
00578 if (st_size != NULL)
00579 {
00580 *st_size = buf.st_size;
00581 }
00582
00583 return ret;
00584 }
00585 }
00586
00587 void splt_io_find_filenames(splt_state *state, const char *directory,
00588 char ***found_files, int *number_of_found_files, int *error)
00589 {
00590 #ifdef __WIN32__
00591 struct _wdirent **files = NULL;
00592 #else
00593 struct dirent **files = NULL;
00594 #endif
00595
00596
00597 #ifdef __WIN32__
00598 int num_of_files = wscandir(directory, &files, NULL, walphasort);
00599 #else
00600 int num_of_files = scandir(directory, &files, NULL, alphasort);
00601 #endif
00602
00603 int new_number_of_files = num_of_files;
00604
00605 if (files == NULL) { return; }
00606
00607 while (new_number_of_files-- > 0)
00608 {
00609 #ifdef __WIN32__
00610 char *fname = splt_w32_utf16_to_utf8(files[new_number_of_files]->d_name);
00611 #else
00612 char *fname = files[new_number_of_files]->d_name;
00613 #endif
00614
00615 int fname_size = strlen(fname);
00616
00617 if (*error >= 0)
00618 {
00619 int path_with_fname_size = fname_size + strlen(directory) + 2;
00620 char *path_with_fname = malloc(sizeof(char) * path_with_fname_size);
00621 if (path_with_fname == NULL)
00622 {
00623 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00624 free(files[new_number_of_files]);
00625 files[new_number_of_files] = NULL;
00626 continue;
00627 }
00628
00629 snprintf(path_with_fname, path_with_fname_size, "%s%c%s", directory,
00630 SPLT_DIRCHAR, fname);
00631
00632 if (splt_io_check_if_file(state, path_with_fname))
00633 {
00634 if (splt_p_file_is_supported_by_plugins(state, fname))
00635 {
00636 if (!(*found_files))
00637 {
00638 (*found_files) = malloc(sizeof(char *));
00639 }
00640 else
00641 {
00642 (*found_files) = realloc((*found_files),
00643 sizeof(char *) * ((*number_of_found_files) + 1));
00644 }
00645 if (*found_files == NULL)
00646 {
00647 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00648 goto end;
00649 }
00650
00651 int fname_size = strlen(path_with_fname) + 1;
00652 (*found_files)[(*number_of_found_files)] = malloc(sizeof(char) * fname_size);
00653 if ((*found_files)[(*number_of_found_files)] == NULL)
00654 {
00655 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00656 goto end;
00657 }
00658
00659 memset((*found_files)[(*number_of_found_files)], '\0', fname_size);
00660 strncat((*found_files)[*(number_of_found_files)], path_with_fname, fname_size);
00661 (*number_of_found_files)++;
00662 }
00663 }
00664 else if (splt_io_check_if_directory(path_with_fname))
00665 {
00666 if (! splt_u_fname_is_directory_parent(fname, fname_size))
00667 {
00668 splt_io_find_filenames(state, path_with_fname, found_files,
00669 number_of_found_files, error);
00670 }
00671 }
00672
00673 end:
00674 if (path_with_fname)
00675 {
00676 free(path_with_fname);
00677 path_with_fname = NULL;
00678 }
00679 }
00680
00681 free(files[new_number_of_files]);
00682 files[new_number_of_files] = NULL;
00683 }
00684
00685 if (files)
00686 {
00687 free(files);
00688 files = NULL;
00689 }
00690 }
00691
00692 size_t splt_io_fwrite(splt_state *state, const void *ptr,
00693 size_t size, size_t nmemb, FILE *stream)
00694 {
00695 if (splt_o_get_int_option(state, SPLT_OPT_PRETEND_TO_SPLIT))
00696 {
00697 return size * nmemb;
00698 }
00699 else
00700 {
00701 return fwrite(ptr, size, nmemb, stream);
00702 }
00703 }
00704
00705 char *splt_io_readline(FILE *stream, int *error)
00706 {
00707 if (feof(stream))
00708 {
00709 return NULL;
00710 }
00711
00712 int err = SPLT_OK;
00713 int bufsize = 1024;
00714 char *buffer = malloc(sizeof(char) * bufsize);
00715 buffer[0] = '\0';
00716
00717 char *line = NULL;
00718 while (fgets(buffer, bufsize, stream) != NULL)
00719 {
00720 err = splt_su_append_str(&line, buffer, NULL);
00721 if (err < 0) { *error = err; break; }
00722
00723 if (line != NULL && line[strlen(line)-1] == '\n')
00724 {
00725 free(buffer);
00726 return line;
00727 }
00728
00729 buffer[0] = '\0';
00730 }
00731
00732 free(buffer);
00733
00734 if (*error < 0)
00735 {
00736 free(line);
00737 return NULL;
00738 }
00739
00740 return line;
00741 }
00742
00743 unsigned char *splt_io_fread(FILE *file, int start, size_t size)
00744 {
00745 unsigned char *bytes = malloc(sizeof(unsigned char) * size);
00746
00747 if (! bytes)
00748 {
00749 return NULL;
00750 }
00751
00752 size_t bytes_read = fread(bytes, 1, size, file);
00753
00754 if (bytes_read != size)
00755 {
00756 if (bytes)
00757 {
00758 free(bytes);
00759 bytes = NULL;
00760 }
00761
00762 return NULL;
00763 }
00764
00765 return bytes;
00766 }
00767
00768 static int splt_u_fname_is_directory_parent(char *fname, int fname_size)
00769 {
00770 return ((fname_size == 1) && (strcmp(fname, ".") == 0)) ||
00771 ((fname_size == 2) && (strcmp(fname, "..") == 0));
00772 }
00773