OpenDNSSEC-signer 1.2.1

/build/buildd-opendnssec_1.2.1.dfsg-1-mips-p9AT07/opendnssec-1.2.1.dfsg/signer/src/util/file.c

Go to the documentation of this file.
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 }