OpenDNSSEC-signer 1.2.1
|
00001 /* 00002 * $Id: file.c 4294 2011-01-13 19:58:29Z 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 "util/file.h" 00036 #include "util/log.h" 00037 #include "util/se_malloc.h" 00038 00039 #include <errno.h> 00040 #include <stdio.h> /* fgetc(), fopen(), fclose(), ferror() */ 00041 #include <stdlib.h> /* system() */ 00042 #include <string.h> /* strlen(), strncmp(), strncat(), strncpy(), strerror() */ 00043 #include <sys/stat.h> /* stat() */ 00044 #include <unistd.h> /* chown() */ 00045 00046 00051 const char* 00052 se_file_mode2str(const char* mode) 00053 { 00054 se_log_assert(mode); 00055 00056 if (se_strcmp(mode, "a") == 0) { 00057 return "appending"; 00058 } else if (se_strcmp(mode, "r") == 0) { 00059 return "reading"; 00060 } else if (se_strcmp(mode, "w") == 0) { 00061 return "writing"; 00062 } 00063 return "unknown mode"; 00064 } 00065 00066 00071 int 00072 se_fgetc(FILE* fd, unsigned int* line_nr) 00073 { 00074 int c; 00075 00076 se_log_assert(fd); 00077 se_log_assert(line_nr); 00078 00079 c = fgetc(fd); 00080 if (c == '\n') { 00081 (*line_nr)++; 00082 } 00083 return c; 00084 } 00085 00086 00091 int 00092 se_skip_whitespace(FILE* fd, unsigned int* line_nr) 00093 { 00094 int c; 00095 00096 se_log_assert(fd); 00097 se_log_assert(line_nr); 00098 00099 while ((c=se_fgetc(fd, line_nr)) != EOF) { 00100 if (c == ' ' || c == '\t' || c == '\r') { 00101 continue; 00102 } 00103 return c; 00104 } 00105 return EOF; 00106 } 00107 00108 00113 char* 00114 se_build_path(const char* file, const char* suffix, int dir) 00115 { 00116 size_t len_file = 0; 00117 size_t len_suffix = 0; 00118 size_t len_total = 0; 00119 char* openf = NULL; 00120 00121 if (file) { 00122 len_file = strlen(file); 00123 if (suffix) { 00124 len_suffix = strlen(suffix); 00125 } 00126 len_total = len_suffix + len_file; 00127 if (dir) { 00128 len_total++; 00129 } 00130 00131 if (len_total > 0) { 00132 openf = (char*) se_malloc(sizeof(char)*(len_total + 1)); 00133 00134 strncpy(openf, file, len_file); 00135 openf[len_file] = '\0'; 00136 if (suffix) { 00137 strncat(openf, suffix, len_suffix); 00138 } 00139 if (dir) { 00140 strncat(openf, "/", 1); 00141 } 00142 openf[len_total] = '\0'; 00143 } 00144 } 00145 00146 return openf; 00147 } 00148 00149 00154 FILE* 00155 se_fopen(const char* file, const char* dir, const char* mode) 00156 { 00157 FILE* fd = NULL; 00158 size_t len_file = 0; 00159 size_t len_dir = 0; 00160 size_t len_total = 0; 00161 char* openf = NULL; 00162 00163 se_log_assert(mode); 00164 se_log_debug("open file: dir %s file %s for %s", 00165 (dir?dir:"(null)"), (file?file:"(null)"), 00166 se_file_mode2str(mode)); 00167 00168 if (dir) { 00169 len_dir= strlen(dir); 00170 } 00171 if (file) { 00172 len_file= strlen(file); 00173 } 00174 len_total = len_dir + len_file; 00175 if (len_total > 0) { 00176 openf = (char*) se_malloc(sizeof(char)*(len_total + 1)); 00177 if (dir) { 00178 strncpy(openf, dir, len_dir); 00179 openf[len_dir] = '\0'; 00180 if (file) { 00181 strncat(openf, file, len_file); 00182 } 00183 } else if (file) { 00184 strncpy(openf, file, len_file); 00185 } 00186 openf[len_total] = '\0'; 00187 00188 if (len_file) { 00189 fd = fopen(openf, mode); 00190 if (!fd) { 00191 se_log_error("unable to open file %s for %s: %s", 00192 openf?openf:"(null)", 00193 se_file_mode2str(mode), strerror(errno)); 00194 } 00195 } 00196 se_free((void*) openf); 00197 } 00198 return fd; 00199 } 00200 00205 void 00206 se_fclose(FILE* fd) 00207 { 00208 if (fd) { 00209 fclose(fd); 00210 } 00211 return; 00212 } 00213 00214 00219 ssize_t 00220 se_writen(int fd, const void* vptr, size_t n) 00221 { 00222 size_t nleft; 00223 ssize_t nwritten; 00224 const char* ptr; 00225 00226 ptr = vptr; 00227 nleft = n; 00228 while (nleft > 0) { 00229 if ((nwritten = write(fd, ptr, nleft)) <= 0) { 00230 if (nwritten < 0 && errno == EINTR) { 00231 nwritten = 0; /* and call write again */ 00232 } else { 00233 return -1; /* error */ 00234 } 00235 } 00236 nleft -= nwritten; 00237 ptr += nwritten; 00238 } 00239 return n; 00240 } 00241 00242 00247 time_t 00248 se_file_lastmodified(const char* file) 00249 { 00250 int ret; 00251 struct stat buf; 00252 FILE* fd; 00253 00254 se_log_assert(file); 00255 00256 if ((fd = se_fopen(file, NULL, "r")) != NULL) { 00257 ret = stat(file, &buf); 00258 se_fclose(fd); 00259 return buf.st_mtime; 00260 } 00261 return 0; 00262 } 00263 00264 00269 int 00270 se_strcmp(const char* s1, const char* s2) 00271 { 00272 if (!s1 && !s2) { 00273 return 0; 00274 } else if (!s1) { 00275 return -1; 00276 } else if (!s2) { 00277 return -1; 00278 } else if (strlen(s1) != strlen(s2)) { 00279 if (strncmp(s1, s2, strlen(s1)) == 0) { 00280 return strlen(s1) - strlen(s2); 00281 } 00282 } 00283 return strncmp(s1, s2, strlen(s1)); 00284 } 00285 00286 00291 const char* 00292 se_replace(const char *str, const char *oldstr, const char *newstr) 00293 { 00294 char* buffer = NULL; 00295 char* ch = NULL; 00296 size_t part1_len = 0; 00297 size_t part2_len = 0; 00298 size_t part3_len = 0; 00299 00300 se_log_assert(str); 00301 se_log_assert(oldstr); 00302 se_log_assert(newstr); 00303 00304 if (!(ch = strstr(str, oldstr))) { 00305 buffer = se_strdup(str); 00306 return buffer; 00307 } 00308 00309 part1_len = ch-str; 00310 part2_len = strlen(newstr); 00311 part3_len = strlen(ch+strlen(oldstr)); 00312 buffer = se_calloc(part1_len+part2_len+part3_len+1, sizeof(char)); 00313 00314 if (part1_len) { 00315 strncpy(buffer, str, part1_len); 00316 buffer[part1_len] = '\0'; 00317 00318 if (part2_len) { 00319 strncat(buffer, str, part2_len); 00320 buffer[part1_len+part2_len] = '\0'; 00321 } 00322 } else { 00323 strncpy(buffer, newstr, part2_len); 00324 buffer[part2_len] = '\0'; 00325 } 00326 00327 if (part3_len) { 00328 strncat(buffer, ch+strlen(oldstr), part3_len); 00329 buffer[part1_len+part2_len+part3_len] = '\0'; 00330 } 00331 00332 buffer[ch-str] = '\0'; 00333 snprintf(buffer+(ch-str), SYSTEM_MAXLEN, "%s%s", newstr, ch+strlen(oldstr)); 00334 return buffer; 00335 } 00336 00337 00342 int 00343 se_file_copy(const char* file1, const char* file2) 00344 { 00345 char str[SYSTEM_MAXLEN]; 00346 FILE* fd = NULL; 00347 00348 se_log_assert(file1); 00349 se_log_assert(file2); 00350 00351 if ((fd = se_fopen(file1, NULL, "r")) != NULL) { 00352 se_fclose(fd); 00353 snprintf(str, SYSTEM_MAXLEN, "%s %s %s > /dev/null", 00354 CP_COMMAND, file1, file2); 00355 se_log_debug("system call: %s", str); 00356 return system(str); 00357 } 00358 /* no such file */ 00359 return 1; 00360 } 00361 00366 char* 00367 se_dir_name(const char* file) { 00368 int l = strlen(file); 00369 char* dir = NULL; 00370 00371 se_log_assert(file); 00372 00373 /* find seperator */ 00374 while (l>0 && strncmp(file + (l-1), "/", 1) != 0) { 00375 l--; 00376 } 00377 00378 /* now strip off (multiple seperators) */ 00379 while (l>0 && strncmp(file + (l-1), "/", 1) == 0) { 00380 l--; 00381 } 00382 00383 if (l) { 00384 dir = (char*) se_calloc(l+1, sizeof(char)); 00385 dir = strncpy(dir, file, l); 00386 return dir; 00387 } 00388 return NULL; 00389 } 00390 00395 void 00396 se_chown(const char* file, uid_t uid, gid_t gid, int getdir) 00397 { 00398 char* dir = NULL; 00399 00400 if (!file) { 00401 se_log_warning("no filename given for chown()"); 00402 return; 00403 } 00404 00405 if (!getdir) { 00406 se_log_debug("create and chown directory %s [user %ld] [group %ld]", 00407 file, (signed long) uid, (signed long) gid); 00408 if (chown(file, uid, gid) != 0) { 00409 se_log_error("chown() for %s failed: %s", file?file:"(null)", 00410 strerror(errno)); 00411 } 00412 } else if ((dir = se_dir_name(file)) != NULL) { 00413 se_log_debug("create and chown directory %s [user %ld] [group %ld]", 00414 dir, (signed long) uid, (signed long) gid); 00415 if (chown(dir, uid, gid) != 0) { 00416 se_log_error("chown() for %s failed: %s", dir, 00417 strerror(errno)); 00418 } 00419 se_free((void*) dir); 00420 } else { 00421 se_log_warning("use of relative path: %s", file); 00422 } 00423 return; 00424 } 00425 00426 00431 void 00432 se_str_trim(char* str) 00433 { 00434 int i = strlen(str), nl = 0; 00435 00436 /* trailing */ 00437 while (i>0) { 00438 --i; 00439 if (str[i] == '\n') { 00440 nl = 1; 00441 } 00442 if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') { 00443 str[i] = '\0'; 00444 } else { 00445 break; 00446 } 00447 } 00448 if (nl) { 00449 str[++i] = '\n'; 00450 } 00451 00452 /* leading */ 00453 i = 0; 00454 while (str[i] == ' ' || str[i] == '\t') { 00455 i++; 00456 } 00457 while (*(str+i) != '\0') { 00458 *str = *(str+i); 00459 str++; 00460 } 00461 *str = '\0'; 00462 return; 00463 }