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
00028
00034 #include "config.h"
00035 #include "shared/file.h"
00036 #include "shared/log.h"
00037
00038 #include <errno.h>
00039 #include <fcntl.h>
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <sys/stat.h>
00044 #include <sys/types.h>
00045 #include <unistd.h>
00046
00047 #define BUFFER_SIZE (16 * 1024)
00048
00049 static const char* file_str = "file";
00050
00051
00056 const char*
00057 ods_file_mode2str(const char* mode)
00058 {
00059 if (!mode) {
00060 return "no mode";
00061 }
00062
00063 if (ods_strcmp(mode, "a") == 0) {
00064 return "appending";
00065 } else if (ods_strcmp(mode, "r") == 0) {
00066 return "reading";
00067 } else if (ods_strcmp(mode, "w") == 0) {
00068 return "writing";
00069 }
00070 return "unknown mode";
00071 }
00072
00073
00078 int
00079 ods_fgetc(FILE* fd, unsigned int* line_nr)
00080 {
00081 int c;
00082
00083 ods_log_assert(fd);
00084 ods_log_assert(line_nr);
00085
00086 c = fgetc(fd);
00087 if (c == '\n') {
00088 (*line_nr)++;
00089 }
00090 return c;
00091 }
00092
00093
00098 int
00099 ods_skip_whitespace(FILE* fd, unsigned int* line_nr)
00100 {
00101 int c;
00102
00103 ods_log_assert(fd);
00104 ods_log_assert(line_nr);
00105
00106 while ((c=ods_fgetc(fd, line_nr)) != EOF) {
00107 if (c == ' ' || c == '\t' || c == '\r') {
00108 continue;
00109 }
00110 return c;
00111 }
00112 return EOF;
00113 }
00114
00115
00120 char*
00121 ods_build_path(const char* file, const char* suffix, int dir)
00122 {
00123 size_t len_file = 0;
00124 size_t len_suffix = 0;
00125 size_t len_total = 0;
00126 char* openf = NULL;
00127
00128 if (file) {
00129 len_file = strlen(file);
00130 if (suffix) {
00131 len_suffix = strlen(suffix);
00132 }
00133 len_total = len_suffix + len_file;
00134 if (dir) {
00135 len_total++;
00136 }
00137
00138 if (len_total > 0) {
00139 openf = (char*) malloc(sizeof(char)*(len_total + 1));
00140 if (!openf) {
00141 ods_log_crit("[%s] build path failed: malloc failed", file_str);
00142 return NULL;
00143 }
00144
00145 strncpy(openf, file, len_file);
00146 openf[len_file] = '\0';
00147 if (suffix) {
00148 strncat(openf, suffix, len_suffix);
00149 }
00150 if (dir) {
00151 strncat(openf, "/", 1);
00152 }
00153 openf[len_total] = '\0';
00154 }
00155 }
00156
00157 return openf;
00158 }
00159
00160
00165 FILE*
00166 ods_fopen(const char* file, const char* dir, const char* mode)
00167 {
00168 FILE* fd = NULL;
00169 size_t len_file = 0;
00170 size_t len_dir = 0;
00171 size_t len_total = 0;
00172 char* openf = NULL;
00173
00174 ods_log_assert(mode);
00175 ods_log_debug("[%s] open file %s%s file=%s mode=%s", file_str,
00176 (dir?"dir=":""), (dir?dir:""), (file?file:"(null)"),
00177 ods_file_mode2str(mode));
00178
00179 if (dir) {
00180 len_dir= strlen(dir);
00181 }
00182 if (file) {
00183 len_file= strlen(file);
00184 }
00185 len_total = len_dir + len_file;
00186 if (len_total > 0) {
00187 openf = (char*) malloc(sizeof(char)*(len_total + 1));
00188 if (!openf) {
00189 return NULL;
00190 }
00191 if (dir) {
00192 strncpy(openf, dir, len_dir);
00193 openf[len_dir] = '\0';
00194 if (file) {
00195 strncat(openf, file, len_file);
00196 }
00197 } else if (file) {
00198 strncpy(openf, file, len_file);
00199 }
00200 openf[len_total] = '\0';
00201
00202 if (len_file) {
00203 fd = fopen(openf, mode);
00204 if (!fd) {
00205 ods_log_verbose("[%s] unable to open file %s for %s: %s",
00206 file_str, openf?openf:"(null)",
00207 ods_file_mode2str(mode), strerror(errno));
00208 }
00209 }
00210 free((void*) openf);
00211 }
00212 return fd;
00213 }
00214
00219 void
00220 ods_fclose(FILE* fd)
00221 {
00222 if (fd) {
00223 fclose(fd);
00224 }
00225 return;
00226 }
00227
00228
00233 ssize_t
00234 ods_writen(int fd, const void* vptr, size_t n)
00235 {
00236 size_t nleft;
00237 ssize_t nwritten;
00238 const char* ptr;
00239
00240 ptr = vptr;
00241 nleft = n;
00242 while (nleft > 0) {
00243 if ((nwritten = write(fd, ptr, nleft)) <= 0) {
00244 if (nwritten < 0 && errno == EINTR) {
00245 nwritten = 0;
00246 } else {
00247 return -1;
00248 }
00249 }
00250 nleft -= nwritten;
00251 ptr += nwritten;
00252 }
00253 return n;
00254 }
00255
00256
00261 time_t
00262 ods_file_lastmodified(const char* file)
00263 {
00264 int ret;
00265 struct stat buf;
00266 FILE* fd;
00267
00268 ods_log_assert(file);
00269
00270 if ((fd = ods_fopen(file, NULL, "r")) != NULL) {
00271 ret = stat(file, &buf);
00272 ods_fclose(fd);
00273 return buf.st_mtime;
00274 }
00275 return 0;
00276 }
00277
00278
00283 int
00284 ods_strcmp(const char* s1, const char* s2)
00285 {
00286 if (!s1 && !s2) {
00287 return 0;
00288 } else if (!s1) {
00289 return -1;
00290 } else if (!s2) {
00291 return -1;
00292 } else if (strlen(s1) != strlen(s2)) {
00293 if (strncmp(s1, s2, strlen(s1)) == 0) {
00294 return strlen(s1) - strlen(s2);
00295 }
00296 }
00297 return strncmp(s1, s2, strlen(s1));
00298 }
00299
00300
00305 const char*
00306 ods_replace(const char *str, const char *oldstr, const char *newstr)
00307 {
00308 char* buffer = NULL;
00309 char* ch = NULL;
00310 size_t part1_len = 0;
00311 size_t part2_len = 0;
00312 size_t part3_len = 0;
00313
00314 if (!str) {
00315 return NULL;
00316 }
00317 if (!oldstr || !newstr) {
00318 return str;
00319 }
00320
00321 if (!(ch = strstr(str, oldstr))) {
00322 buffer = strdup(str);
00323 return buffer;
00324 }
00325
00326 part1_len = ch-str;
00327 part2_len = strlen(newstr);
00328 part3_len = strlen(ch+strlen(oldstr));
00329 buffer = calloc(part1_len+part2_len+part3_len+1, sizeof(char));
00330 if (!buffer) {
00331 return NULL;
00332 }
00333
00334 if (part1_len) {
00335 strncpy(buffer, str, part1_len);
00336 buffer[part1_len] = '\0';
00337
00338 if (part2_len) {
00339 strncat(buffer, str, part2_len);
00340 buffer[part1_len+part2_len] = '\0';
00341 }
00342 } else {
00343 strncpy(buffer, newstr, part2_len);
00344 buffer[part2_len] = '\0';
00345 }
00346
00347 if (part3_len) {
00348 strncat(buffer, ch+strlen(oldstr), part3_len);
00349 buffer[part1_len+part2_len+part3_len] = '\0';
00350 }
00351
00352 buffer[ch-str] = '\0';
00353 snprintf(buffer+(ch-str), SYSTEM_MAXLEN, "%s%s", newstr, ch+strlen(oldstr));
00354 return buffer;
00355 }
00356
00357
00362 ods_status
00363 ods_file_copy(const char* file1, const char* file2)
00364 {
00365 char buf[BUFFER_SIZE];
00366 int fin = 0;
00367 int fout = 0;
00368 int read_size = 0;
00369 if (!file1 || !file2) {
00370 return ODS_STATUS_ASSERT_ERR;
00371 }
00372 if ((fin = open(file1, O_RDONLY|O_NONBLOCK)) < 0) {
00373 return ODS_STATUS_FOPEN_ERR;
00374 }
00375 if ((fout = open(file2, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
00376 close(fin);
00377 return ODS_STATUS_FOPEN_ERR;
00378 }
00379 while (1) {
00380 read_size = read(fin, buf, sizeof(buf));
00381 if (read_size == 0) {
00382 break;
00383 }
00384 if (read_size < 0) {
00385 close(fin);
00386 close(fout);
00387 return ODS_STATUS_FREAD_ERR;
00388 }
00389 if (write(fout, buf, (unsigned int) read_size) < 0) {
00390 close(fin);
00391 close(fout);
00392 return ODS_STATUS_FWRITE_ERR;
00393 }
00394 }
00395 close(fin);
00396 close(fout);
00397 return ODS_STATUS_OK;
00398 }
00399
00400
00405 char*
00406 ods_dir_name(const char* file) {
00407 int l = strlen(file);
00408 char* dir = NULL;
00409
00410 ods_log_assert(file);
00411
00412
00413 while (l>0 && strncmp(file + (l-1), "/", 1) != 0) {
00414 l--;
00415 }
00416
00417
00418 while (l>0 && strncmp(file + (l-1), "/", 1) == 0) {
00419 l--;
00420 }
00421
00422 if (l) {
00423 dir = (char*) calloc(l+1, sizeof(char));
00424 if (dir) {
00425 dir = strncpy(dir, file, l);
00426 }
00427 return dir;
00428 }
00429 return NULL;
00430 }
00431
00436 void
00437 ods_chown(const char* file, uid_t uid, gid_t gid, int getdir)
00438 {
00439 char* dir = NULL;
00440
00441 if (!file) {
00442 ods_log_warning("[%s] no filename given for chown()", file_str);
00443 return;
00444 }
00445
00446 if (!getdir) {
00447 ods_log_debug("[%s] create and chown %s with user=%ld group=%ld",
00448 file_str, file, (signed long) uid, (signed long) gid);
00449 if (chown(file, uid, gid) != 0) {
00450 ods_log_error("[%s] chown() %s failed: %s", file_str, file,
00451 strerror(errno));
00452 }
00453 } else if ((dir = ods_dir_name(file)) != NULL) {
00454 ods_log_debug("[%s] create and chown %s with user=%ld group=%ld",
00455 file_str, dir, (signed long) uid, (signed long) gid);
00456 if (chown(dir, uid, gid) != 0) {
00457 ods_log_error("[%s] chown() %s failed: %s", file_str,
00458 dir, strerror(errno));
00459 }
00460 free((void*) dir);
00461 } else {
00462 ods_log_warning("[%s] use of relative path: %s", file_str, file);
00463 }
00464 return;
00465 }
00466
00467
00472 void
00473 ods_str_trim(char* str)
00474 {
00475 int i = strlen(str), nl = 0;
00476
00477
00478 while (i>0) {
00479 --i;
00480 if (str[i] == '\n') {
00481 nl = 1;
00482 }
00483 if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') {
00484 str[i] = '\0';
00485 } else {
00486 break;
00487 }
00488 }
00489 if (nl) {
00490 str[++i] = '\n';
00491 }
00492
00493
00494 i = 0;
00495 while (str[i] == ' ' || str[i] == '\t') {
00496 i++;
00497 }
00498 while (*(str+i) != '\0') {
00499 *str = *(str+i);
00500 str++;
00501 }
00502 *str = '\0';
00503 return;
00504 }