OpenDNSSEC-signer 1.3.0rc3
|
00001 /* 00002 * $Id: file.c 5227 2011-06-12 08:51:24Z jakob $ 00003 * 00004 * Copyright (c) 2009 NLNet Labs. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00034 #include "config.h" 00035 #include "shared/file.h" 00036 #include "shared/log.h" 00037 00038 #include <errno.h> 00039 #include <stdio.h> 00040 #include <stdlib.h> 00041 #include <string.h> 00042 #include <sys/stat.h> 00043 #include <unistd.h> 00044 00045 static const char* file_str = "file"; 00046 00047 00052 const char* 00053 ods_file_mode2str(const char* mode) 00054 { 00055 if (!mode) { 00056 return "no mode"; 00057 } 00058 00059 if (ods_strcmp(mode, "a") == 0) { 00060 return "appending"; 00061 } else if (ods_strcmp(mode, "r") == 0) { 00062 return "reading"; 00063 } else if (ods_strcmp(mode, "w") == 0) { 00064 return "writing"; 00065 } 00066 return "unknown mode"; 00067 } 00068 00069 00074 int 00075 ods_fgetc(FILE* fd, unsigned int* line_nr) 00076 { 00077 int c; 00078 00079 ods_log_assert(fd); 00080 ods_log_assert(line_nr); 00081 00082 c = fgetc(fd); 00083 if (c == '\n') { 00084 (*line_nr)++; 00085 } 00086 return c; 00087 } 00088 00089 00094 int 00095 ods_skip_whitespace(FILE* fd, unsigned int* line_nr) 00096 { 00097 int c; 00098 00099 ods_log_assert(fd); 00100 ods_log_assert(line_nr); 00101 00102 while ((c=ods_fgetc(fd, line_nr)) != EOF) { 00103 if (c == ' ' || c == '\t' || c == '\r') { 00104 continue; 00105 } 00106 return c; 00107 } 00108 return EOF; 00109 } 00110 00111 00116 char* 00117 ods_build_path(const char* file, const char* suffix, int dir) 00118 { 00119 size_t len_file = 0; 00120 size_t len_suffix = 0; 00121 size_t len_total = 0; 00122 char* openf = NULL; 00123 00124 if (file) { 00125 len_file = strlen(file); 00126 if (suffix) { 00127 len_suffix = strlen(suffix); 00128 } 00129 len_total = len_suffix + len_file; 00130 if (dir) { 00131 len_total++; 00132 } 00133 00134 if (len_total > 0) { 00135 openf = (char*) malloc(sizeof(char)*(len_total + 1)); 00136 if (!openf) { 00137 ods_log_crit("[%s] build path failed: malloc failed", file_str); 00138 return NULL; 00139 } 00140 00141 strncpy(openf, file, len_file); 00142 openf[len_file] = '\0'; 00143 if (suffix) { 00144 strncat(openf, suffix, len_suffix); 00145 } 00146 if (dir) { 00147 strncat(openf, "/", 1); 00148 } 00149 openf[len_total] = '\0'; 00150 } 00151 } 00152 00153 return openf; 00154 } 00155 00156 00161 FILE* 00162 ods_fopen(const char* file, const char* dir, const char* mode) 00163 { 00164 FILE* fd = NULL; 00165 size_t len_file = 0; 00166 size_t len_dir = 0; 00167 size_t len_total = 0; 00168 char* openf = NULL; 00169 00170 ods_log_assert(mode); 00171 ods_log_debug("[%s] open file %s%s file=%s mode=%s", file_str, 00172 (dir?"dir=":""), (dir?dir:""), (file?file:"(null)"), 00173 ods_file_mode2str(mode)); 00174 00175 if (dir) { 00176 len_dir= strlen(dir); 00177 } 00178 if (file) { 00179 len_file= strlen(file); 00180 } 00181 len_total = len_dir + len_file; 00182 if (len_total > 0) { 00183 openf = (char*) malloc(sizeof(char)*(len_total + 1)); 00184 if (!openf) { 00185 return NULL; 00186 } 00187 if (dir) { 00188 strncpy(openf, dir, len_dir); 00189 openf[len_dir] = '\0'; 00190 if (file) { 00191 strncat(openf, file, len_file); 00192 } 00193 } else if (file) { 00194 strncpy(openf, file, len_file); 00195 } 00196 openf[len_total] = '\0'; 00197 00198 if (len_file) { 00199 fd = fopen(openf, mode); 00200 if (!fd) { 00201 ods_log_verbose("[%s] unable to open file %s for %s: %s", 00202 file_str, openf?openf:"(null)", 00203 ods_file_mode2str(mode), strerror(errno)); 00204 } 00205 } 00206 free((void*) openf); 00207 } 00208 return fd; 00209 } 00210 00215 void 00216 ods_fclose(FILE* fd) 00217 { 00218 if (fd) { 00219 fclose(fd); 00220 } 00221 return; 00222 } 00223 00224 00229 ssize_t 00230 ods_writen(int fd, const void* vptr, size_t n) 00231 { 00232 size_t nleft; 00233 ssize_t nwritten; 00234 const char* ptr; 00235 00236 ptr = vptr; 00237 nleft = n; 00238 while (nleft > 0) { 00239 if ((nwritten = write(fd, ptr, nleft)) <= 0) { 00240 if (nwritten < 0 && errno == EINTR) { 00241 nwritten = 0; /* and call write again */ 00242 } else { 00243 return -1; /* error */ 00244 } 00245 } 00246 nleft -= nwritten; 00247 ptr += nwritten; 00248 } 00249 return n; 00250 } 00251 00252 00257 time_t 00258 ods_file_lastmodified(const char* file) 00259 { 00260 int ret; 00261 struct stat buf; 00262 FILE* fd; 00263 00264 ods_log_assert(file); 00265 00266 if ((fd = ods_fopen(file, NULL, "r")) != NULL) { 00267 ret = stat(file, &buf); 00268 ods_fclose(fd); 00269 return buf.st_mtime; 00270 } 00271 return 0; 00272 } 00273 00274 00279 int 00280 ods_strcmp(const char* s1, const char* s2) 00281 { 00282 if (!s1 && !s2) { 00283 return 0; 00284 } else if (!s1) { 00285 return -1; 00286 } else if (!s2) { 00287 return -1; 00288 } else if (strlen(s1) != strlen(s2)) { 00289 if (strncmp(s1, s2, strlen(s1)) == 0) { 00290 return strlen(s1) - strlen(s2); 00291 } 00292 } 00293 return strncmp(s1, s2, strlen(s1)); 00294 } 00295 00296 00301 const char* 00302 ods_replace(const char *str, const char *oldstr, const char *newstr) 00303 { 00304 char* buffer = NULL; 00305 char* ch = NULL; 00306 size_t part1_len = 0; 00307 size_t part2_len = 0; 00308 size_t part3_len = 0; 00309 00310 if (!str) { 00311 return NULL; 00312 } 00313 if (!oldstr || !newstr) { 00314 return str; 00315 } 00316 00317 if (!(ch = strstr(str, oldstr))) { 00318 buffer = strdup(str); 00319 return buffer; 00320 } 00321 00322 part1_len = ch-str; 00323 part2_len = strlen(newstr); 00324 part3_len = strlen(ch+strlen(oldstr)); 00325 buffer = calloc(part1_len+part2_len+part3_len+1, sizeof(char)); 00326 if (!buffer) { 00327 return NULL; 00328 } 00329 00330 if (part1_len) { 00331 strncpy(buffer, str, part1_len); 00332 buffer[part1_len] = '\0'; 00333 00334 if (part2_len) { 00335 strncat(buffer, str, part2_len); 00336 buffer[part1_len+part2_len] = '\0'; 00337 } 00338 } else { 00339 strncpy(buffer, newstr, part2_len); 00340 buffer[part2_len] = '\0'; 00341 } 00342 00343 if (part3_len) { 00344 strncat(buffer, ch+strlen(oldstr), part3_len); 00345 buffer[part1_len+part2_len+part3_len] = '\0'; 00346 } 00347 00348 buffer[ch-str] = '\0'; 00349 snprintf(buffer+(ch-str), SYSTEM_MAXLEN, "%s%s", newstr, ch+strlen(oldstr)); 00350 return buffer; 00351 } 00352 00353 00358 int 00359 ods_file_copy(const char* file1, const char* file2) 00360 { 00361 char str[SYSTEM_MAXLEN]; 00362 FILE* fd = NULL; 00363 00364 if (!file1 || !file2) { 00365 return 1; 00366 } 00367 00368 if ((fd = ods_fopen(file1, NULL, "r")) != NULL) { 00369 ods_fclose(fd); 00370 snprintf(str, SYSTEM_MAXLEN, "%s %s %s > /dev/null", 00371 CP_COMMAND, file1, file2); 00372 ods_log_debug("system call: %s", str); 00373 return system(str); 00374 } 00375 /* no such file */ 00376 return 1; 00377 } 00378 00383 char* 00384 ods_dir_name(const char* file) { 00385 int l = strlen(file); 00386 char* dir = NULL; 00387 00388 ods_log_assert(file); 00389 00390 /* find seperator */ 00391 while (l>0 && strncmp(file + (l-1), "/", 1) != 0) { 00392 l--; 00393 } 00394 00395 /* now strip off (multiple seperators) */ 00396 while (l>0 && strncmp(file + (l-1), "/", 1) == 0) { 00397 l--; 00398 } 00399 00400 if (l) { 00401 dir = (char*) calloc(l+1, sizeof(char)); 00402 if (dir) { 00403 dir = strncpy(dir, file, l); 00404 } 00405 return dir; 00406 } 00407 return NULL; 00408 } 00409 00414 void 00415 ods_chown(const char* file, uid_t uid, gid_t gid, int getdir) 00416 { 00417 char* dir = NULL; 00418 00419 if (!file) { 00420 ods_log_warning("[%s] no filename given for chown()", file_str); 00421 return; 00422 } 00423 00424 if (!getdir) { 00425 ods_log_debug("[%s] create and chown %s with user=%ld group=%ld", 00426 file_str, file, (signed long) uid, (signed long) gid); 00427 if (chown(file, uid, gid) != 0) { 00428 ods_log_error("[%s] chown() %s failed: %s", file_str, file, 00429 strerror(errno)); 00430 } 00431 } else if ((dir = ods_dir_name(file)) != NULL) { 00432 ods_log_debug("[%s] create and chown %s with user=%ld group=%ld", 00433 file_str, dir, (signed long) uid, (signed long) gid); 00434 if (chown(dir, uid, gid) != 0) { 00435 ods_log_error("[%s] chown() %s failed: %s", file_str, 00436 dir, strerror(errno)); 00437 } 00438 free((void*) dir); 00439 } else { 00440 ods_log_warning("[%s] use of relative path: %s", file_str, file); 00441 } 00442 return; 00443 } 00444 00445 00450 void 00451 ods_str_trim(char* str) 00452 { 00453 int i = strlen(str), nl = 0; 00454 00455 /* trailing */ 00456 while (i>0) { 00457 --i; 00458 if (str[i] == '\n') { 00459 nl = 1; 00460 } 00461 if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') { 00462 str[i] = '\0'; 00463 } else { 00464 break; 00465 } 00466 } 00467 if (nl) { 00468 str[++i] = '\n'; 00469 } 00470 00471 /* leading */ 00472 i = 0; 00473 while (str[i] == ' ' || str[i] == '\t') { 00474 i++; 00475 } 00476 while (*(str+i) != '\0') { 00477 *str = *(str+i); 00478 str++; 00479 } 00480 *str = '\0'; 00481 return; 00482 }