OpenDNSSEC-signer 1.3.0
/build/buildd/opendnssec-1.3.0/signer/src/shared/file.c
Go to the documentation of this file.
00001 /*
00002  * $Id: file.c 5320 2011-07-12 10:42:26Z 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 ods_status
00359 ods_file_copy(const char* file1, const char* file2)
00360 {
00361     char str[SYSTEM_MAXLEN];
00362     FILE* fd = NULL;
00363     int retval = 0;
00364 
00365     if (!file1 || !file2) {
00366         return ODS_STATUS_ASSERT_ERR;
00367     }
00368 
00369     if ((fd = ods_fopen(file1, NULL, "r")) != NULL) {
00370         ods_fclose(fd);
00371         snprintf(str, SYSTEM_MAXLEN, "%s %s %s > /dev/null",
00372             CP_COMMAND, file1, file2);
00373         ods_log_debug("system call: %s", str);
00374         retval = system(str);
00375         switch (retval) {
00376             case 0:
00377                 return ODS_STATUS_OK;
00378             default:
00379                 ods_log_error("[%s] %s failed: return value %i",
00380                     file_str, CP_COMMAND, retval);
00381                 return ODS_STATUS_ERR;
00382         }
00383     }
00384     return ODS_STATUS_FOPEN_ERR;
00385 }
00386 
00391 char*
00392 ods_dir_name(const char* file) {
00393     int l = strlen(file);
00394     char* dir = NULL;
00395 
00396     ods_log_assert(file);
00397 
00398     /* find seperator */
00399     while (l>0 && strncmp(file + (l-1), "/", 1) != 0) {
00400         l--;
00401     }
00402 
00403     /* now strip off (multiple seperators) */
00404     while (l>0 && strncmp(file + (l-1), "/", 1) == 0) {
00405         l--;
00406     }
00407 
00408     if (l) {
00409         dir = (char*) calloc(l+1, sizeof(char));
00410         if (dir) {
00411             dir = strncpy(dir, file, l);
00412         }
00413         return dir;
00414     }
00415     return NULL;
00416 }
00417 
00422 void
00423 ods_chown(const char* file, uid_t uid, gid_t gid, int getdir)
00424 {
00425     char* dir = NULL;
00426 
00427     if (!file) {
00428         ods_log_warning("[%s] no filename given for chown()", file_str);
00429         return;
00430     }
00431 
00432     if (!getdir) {
00433         ods_log_debug("[%s] create and chown %s with user=%ld group=%ld",
00434            file_str, file, (signed long) uid, (signed long) gid);
00435         if (chown(file, uid, gid) != 0) {
00436             ods_log_error("[%s] chown() %s failed: %s", file_str, file,
00437                 strerror(errno));
00438         }
00439     } else if ((dir = ods_dir_name(file)) != NULL) {
00440         ods_log_debug("[%s] create and chown %s with user=%ld group=%ld",
00441             file_str, dir, (signed long) uid, (signed long) gid);
00442         if (chown(dir, uid, gid) != 0) {
00443             ods_log_error("[%s] chown() %s failed: %s", file_str,
00444                 dir, strerror(errno));
00445         }
00446         free((void*) dir);
00447     } else {
00448         ods_log_warning("[%s] use of relative path: %s", file_str, file);
00449     }
00450     return;
00451 }
00452 
00453 
00458 void
00459 ods_str_trim(char* str)
00460 {
00461     int i = strlen(str), nl = 0;
00462 
00463     /* trailing */
00464     while (i>0) {
00465         --i;
00466         if (str[i] == '\n') {
00467             nl = 1;
00468         }
00469         if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') {
00470             str[i] = '\0';
00471         } else {
00472             break;
00473         }
00474     }
00475     if (nl) {
00476         str[++i] = '\n';
00477     }
00478 
00479     /* leading */
00480     i = 0;
00481     while (str[i] == ' ' || str[i] == '\t') {
00482         i++;
00483     }
00484     while (*(str+i) != '\0') {
00485         *str = *(str+i);
00486         str++;
00487     }
00488     *str = '\0';
00489     return;
00490 }