OpenDNSSEC-signer  1.3.8
/build/buildd/opendnssec-1.3.8/signer/src/shared/file.c
Go to the documentation of this file.
00001 /*
00002  * $Id: file.c 6244 2012-04-03 13:56:27Z matthijs $
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 <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) /* use 16K buffers */
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 == '\r') { /* carriage return */
00088         c = ' ';
00089     }
00090     if (c == '\n') {
00091         (*line_nr)++;
00092     }
00093     return c;
00094 }
00095 
00096 
00101 int
00102 ods_skip_whitespace(FILE* fd, unsigned int* line_nr)
00103 {
00104     int c;
00105 
00106     ods_log_assert(fd);
00107     ods_log_assert(line_nr);
00108 
00109     while ((c=ods_fgetc(fd, line_nr)) != EOF) {
00110         if (c == ' ' || c == '\t' || c == '\r') {
00111             continue;
00112         }
00113         return c;
00114     }
00115     return EOF;
00116 }
00117 
00118 
00123 char*
00124 ods_build_path(const char* file, const char* suffix, int dir, int no_slash)
00125 {
00126     size_t len_file = 0;
00127     size_t len_suffix = 0;
00128     size_t len_total = 0;
00129     char* openf = NULL;
00130 
00131     if (file) {
00132         len_file = strlen(file);
00133         if (suffix) {
00134             len_suffix = strlen(suffix);
00135         }
00136         len_total = len_suffix + len_file;
00137         if (dir) {
00138             len_total++;
00139         }
00140 
00141         if (len_total > 0) {
00142             openf = (char*) malloc(sizeof(char)*(len_total + 1));
00143             if (!openf) {
00144                 ods_log_crit("[%s] build path failed: malloc failed", file_str);
00145                 return NULL;
00146             }
00147 
00148             strncpy(openf, file, len_file);
00149             openf[len_file] = '\0';
00150             if (no_slash) {
00151                 size_t i = 0;
00152                 for (i=0; i<len_file; i++) {
00153                     switch (openf[i]) {
00154                         case '/':
00155                         case ' ':
00156                         /* more? */
00157                             openf[i] = '-';
00158                             break;
00159                         default:
00160                             break;
00161                     }
00162                 }
00163             }
00164 
00165             if (suffix) {
00166                 strncat(openf, suffix, len_suffix);
00167             }
00168             if (dir) {
00169                 strncat(openf, "/", 1);
00170             }
00171             openf[len_total] = '\0';
00172         }
00173     }
00174 
00175     return openf;
00176 }
00177 
00178 
00183 FILE*
00184 ods_fopen(const char* file, const char* dir, const char* mode)
00185 {
00186     FILE* fd = NULL;
00187     size_t len_file = 0;
00188     size_t len_dir = 0;
00189     size_t len_total = 0;
00190     char* openf = NULL;
00191 
00192     ods_log_assert(mode);
00193     ods_log_debug("[%s] open file %s%s file=%s mode=%s", file_str,
00194         (dir?"dir=":""), (dir?dir:""), (file?file:"(null)"),
00195         ods_file_mode2str(mode));
00196 
00197     if (dir) {
00198         len_dir= strlen(dir);
00199     }
00200     if (file) {
00201         len_file= strlen(file);
00202     }
00203     len_total = len_dir + len_file;
00204     if (len_total > 0) {
00205         openf = (char*) malloc(sizeof(char)*(len_total + 1));
00206         if (!openf) {
00207             return NULL;
00208         }
00209         if (dir) {
00210            strncpy(openf, dir, len_dir);
00211            openf[len_dir] = '\0';
00212            if (file) {
00213                strncat(openf, file, len_file);
00214            }
00215         } else if (file) {
00216            strncpy(openf, file, len_file);
00217         }
00218         openf[len_total] = '\0';
00219 
00220         if (len_file) {
00221             fd = fopen(openf, mode);
00222             if (!fd) {
00223                 ods_log_verbose("[%s] unable to open file %s for %s: %s",
00224                     file_str, openf?openf:"(null)",
00225                     ods_file_mode2str(mode), strerror(errno));
00226             }
00227         }
00228         free((void*) openf);
00229     }
00230     return fd;
00231 }
00232 
00237 void
00238 ods_fclose(FILE* fd)
00239 {
00240     if (fd) {
00241         fclose(fd);
00242     }
00243     return;
00244 }
00245 
00246 
00251 ssize_t
00252 ods_writen(int fd, const void* vptr, size_t n)
00253 {
00254     size_t nleft;
00255     ssize_t nwritten;
00256     const char* ptr;
00257 
00258     ptr = vptr;
00259     nleft = n;
00260     while (nleft > 0) {
00261         if ((nwritten = write(fd, ptr, nleft)) <= 0) {
00262             if (nwritten < 0 && errno == EINTR) {
00263                 nwritten = 0; /* and call write again */
00264             } else {
00265                 return -1; /* error */
00266             }
00267         }
00268         nleft -= nwritten;
00269         ptr += nwritten;
00270     }
00271     return n;
00272 }
00273 
00274 
00279 time_t
00280 ods_file_lastmodified(const char* file)
00281 {
00282     int ret;
00283     struct stat buf;
00284     FILE* fd;
00285 
00286     ods_log_assert(file);
00287 
00288     if ((fd = ods_fopen(file, NULL, "r")) != NULL) {
00289         ret = stat(file, &buf);
00290         ods_fclose(fd);
00291         return buf.st_mtime;
00292     }
00293     return 0;
00294 }
00295 
00296 
00301 int
00302 ods_strcmp(const char* s1, const char* s2)
00303 {
00304     if (!s1 && !s2) {
00305         return 0;
00306     } else if (!s1) {
00307         return -1;
00308     } else if (!s2) {
00309         return -1;
00310     } else if (strlen(s1) != strlen(s2)) {
00311         if (strncmp(s1, s2, strlen(s1)) == 0) {
00312             return strlen(s1) - strlen(s2);
00313         }
00314     }
00315     return strncmp(s1, s2, strlen(s1));
00316 }
00317 
00318 
00323 const char*
00324 ods_replace(const char *str, const char *oldstr, const char *newstr)
00325 {
00326     char* buffer = NULL;
00327     char* ch = NULL;
00328     size_t part1_len = 0;
00329     size_t part2_len = 0;
00330     size_t part3_len = 0;
00331 
00332     if (!str) {
00333        return NULL;
00334     }
00335     if (!oldstr || !newstr) {
00336        return str;
00337     }
00338 
00339     if (!(ch = strstr(str, oldstr))) {
00340         buffer = strdup(str);
00341         return buffer;
00342     }
00343 
00344     part1_len = ch-str;
00345     part2_len = strlen(newstr);
00346     part3_len = strlen(ch+strlen(oldstr));
00347     buffer = calloc(part1_len+part2_len+part3_len+1, sizeof(char));
00348     if (!buffer) {
00349         return NULL;
00350     }
00351 
00352     if (part1_len) {
00353         strncpy(buffer, str, part1_len);
00354         buffer[part1_len] = '\0';
00355 
00356         if (part2_len) {
00357             strncat(buffer, str, part2_len);
00358             buffer[part1_len+part2_len] = '\0';
00359         }
00360     } else {
00361         strncpy(buffer, newstr, part2_len);
00362         buffer[part2_len] = '\0';
00363     }
00364 
00365     if (part3_len) {
00366         strncat(buffer, ch+strlen(oldstr), part3_len);
00367         buffer[part1_len+part2_len+part3_len] = '\0';
00368     }
00369 
00370     buffer[ch-str] = '\0';
00371     snprintf(buffer+(ch-str), SYSTEM_MAXLEN, "%s%s", newstr, ch+strlen(oldstr));
00372     return buffer;
00373 }
00374 
00375 
00380 ods_status
00381 ods_file_copy(const char* file1, const char* file2)
00382 {
00383     char buf[BUFFER_SIZE];
00384     int fin = 0;
00385     int fout = 0;
00386     int read_size = 0;
00387     if (!file1 || !file2) {
00388         return ODS_STATUS_ASSERT_ERR;
00389     }
00390     if ((fin = open(file1, O_RDONLY|O_NONBLOCK)) < 0) {
00391         return ODS_STATUS_FOPEN_ERR;
00392     }
00393     if ((fout = open(file2, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
00394         close(fin);
00395         return ODS_STATUS_FOPEN_ERR;
00396     }
00397     while (1) {
00398         read_size = read(fin, buf, sizeof(buf));
00399         if (read_size == 0) {
00400             break;
00401         }
00402         if (read_size < 0) {
00403             close(fin);
00404             close(fout);
00405             return ODS_STATUS_FREAD_ERR;
00406         }
00407         if (write(fout, buf, (unsigned int) read_size) < 0) {
00408             close(fin);
00409             close(fout);
00410             return ODS_STATUS_FWRITE_ERR;
00411         }
00412     }
00413     close(fin);
00414     close(fout);
00415     return ODS_STATUS_OK;
00416 }
00417 
00418 
00423 char*
00424 ods_dir_name(const char* file) {
00425     int l = strlen(file);
00426     char* dir = NULL;
00427 
00428     ods_log_assert(file);
00429 
00430     /* find seperator */
00431     while (l>0 && strncmp(file + (l-1), "/", 1) != 0) {
00432         l--;
00433     }
00434 
00435     /* now strip off (multiple seperators) */
00436     while (l>0 && strncmp(file + (l-1), "/", 1) == 0) {
00437         l--;
00438     }
00439 
00440     if (l) {
00441         dir = (char*) calloc(l+1, sizeof(char));
00442         if (dir) {
00443             dir = strncpy(dir, file, l);
00444         }
00445         return dir;
00446     }
00447     return NULL;
00448 }
00449 
00454 void
00455 ods_chown(const char* file, uid_t uid, gid_t gid, int getdir)
00456 {
00457     char* dir = NULL;
00458 
00459     if (!file) {
00460         ods_log_warning("[%s] no filename given for chown()", file_str);
00461         return;
00462     }
00463 
00464     if (!getdir) {
00465         ods_log_debug("[%s] create and chown %s with user=%ld group=%ld",
00466            file_str, file, (signed long) uid, (signed long) gid);
00467         if (chown(file, uid, gid) != 0) {
00468             ods_log_error("[%s] chown() %s failed: %s", file_str, file,
00469                 strerror(errno));
00470         }
00471     } else if ((dir = ods_dir_name(file)) != NULL) {
00472         ods_log_debug("[%s] create and chown %s with user=%ld group=%ld",
00473             file_str, dir, (signed long) uid, (signed long) gid);
00474         if (chown(dir, uid, gid) != 0) {
00475             ods_log_error("[%s] chown() %s failed: %s", file_str,
00476                 dir, strerror(errno));
00477         }
00478         free((void*) dir);
00479     } else {
00480         ods_log_warning("[%s] use of relative path: %s", file_str, file);
00481     }
00482     return;
00483 }
00484 
00485 
00490 void
00491 ods_str_trim(char* str)
00492 {
00493     int i = strlen(str), nl = 0;
00494 
00495     /* trailing */
00496     while (i>0) {
00497         --i;
00498         if (str[i] == '\n') {
00499             nl = 1;
00500         }
00501         if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') {
00502             str[i] = '\0';
00503         } else {
00504             break;
00505         }
00506     }
00507     if (nl) {
00508         str[++i] = '\n';
00509     }
00510 
00511     /* leading */
00512     i = 0;
00513     while (str[i] == ' ' || str[i] == '\t') {
00514         i++;
00515     }
00516     while (*(str+i) != '\0') {
00517         *str = *(str+i);
00518         str++;
00519     }
00520     *str = '\0';
00521     return;
00522 }