00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef lint
00039 static char copyright[] =
00040 "@(#) Copyright (c) 2002\n\
00041 Netherlands Forensic Institute. All rights reserved.\n";
00042 #endif
00043
00044 #ifdef HAVE_CONFIG_H
00045 #include <config.h>
00046 #endif
00047
00048 #include <limits.h>
00049 #include <stdlib.h>
00050 #include <stdio.h>
00051 #include <string.h>
00052 #include <sys/time.h>
00053 #include <sys/types.h>
00054 #include <fcntl.h>
00055 #include <unistd.h>
00056 #include <time.h>
00057 #include <signal.h>
00058
00059 #include "rdd.h"
00060 #include "rdd_internals.h"
00061 #include "error.h"
00062
00063 #define MAX_SIZE_BUF_LEN 64
00064 #define TIME_BUF_SIZE 64
00065 #define TIME_FORMAT "%Y-%m-%d %H:%M:%S %Z"
00066
00067 #define bitcount(t) (sizeof(t) * CHAR_BIT)
00068
00069
00070
00071 static void
00072 check_type_sizes(void)
00073 {
00074 if (bitcount(off_t) < 64) {
00075 error("configuration problem: off_t not wide enough");
00076 }
00077 if (bitcount(rdd_count_t) < 64) {
00078 error("configuration problem: rdd_count_t not wide enough");
00079 }
00080 if (bitcount(uint32_t) < 32) {
00081 error("configuration problem: uint32_t is not 32 bits wide");
00082 }
00083 if (bitcount(uint64_t) < 64) {
00084 error("configuration problem: uint64_t is not 64 bits wide");
00085 }
00086 if (bitcount(unsigned char) != 8) {
00087 error("configuration problem: unsigned char is not 8 bits wide");
00088 }
00089 if (bitcount(rdd_checksum_t) != 32) {
00090 error("configuration problem: rdd_checksum_t is not 32 bits wide");
00091 }
00092 }
00093
00094 void
00095 rdd_init(void)
00096 {
00097 check_type_sizes();
00098 }
00099
00102 void *
00103 rdd_malloc(size_t nbyte)
00104 {
00105 void *p;
00106
00107 if ((p = malloc(nbyte)) == 0) {
00108 error("out of memory (%u bytes requested)", nbyte);
00109 }
00110 memset(p, 0, nbyte);
00111 return p;
00112 }
00113
00114 void
00115 rdd_free(void *p)
00116 {
00117 free(p);
00118 }
00119
00120 int
00121 rdd_buf2hex(const unsigned char *buf, unsigned bufsize,
00122 char *hexbuf, unsigned hexbuflen)
00123 {
00124 static char *hexdigits = "0123456789abcdef";
00125 unsigned d, k, i;
00126
00127 if (2*bufsize + 1 > hexbuflen) {
00128 return RDD_ESPACE;
00129 }
00130
00131 for (i = k = 0; i < bufsize; i++) {
00132 d = (buf[i] >> 4) & 0xf;
00133 hexbuf[k++] = hexdigits[d];
00134
00135 d = buf[i] & 0xf;
00136 hexbuf[k++] = hexdigits[d];
00137 }
00138 hexbuf[k] = '\000';
00139
00140 return RDD_OK;
00141 }
00142
00143 char *
00144 rdd_ctime(void)
00145 {
00146 static char timebuf[TIME_BUF_SIZE];
00147 time_t now;
00148 struct tm *now_local;
00149
00150 now = time(NULL);
00151 if (now == (time_t) -1) {
00152 unix_error("cannot retrieve current time");
00153 }
00154
00155 if ((now_local = localtime(&now)) == NULL) {
00156 error("cannot convert Unix ticks to local time");
00157 }
00158
00159 if (strftime(timebuf, TIME_BUF_SIZE, TIME_FORMAT, now_local) == 0) {
00160 error("cannot convert local time to a string");
00161 }
00162
00163 return timebuf;
00164 }
00165
00166 double
00167 rdd_gettime(void)
00168 {
00169 struct timeval now;
00170
00171 if (gettimeofday(&now, 0) < 0) {
00172 unix_error("cannot read time-of-day");
00173 }
00174
00175 return ((double) now.tv_sec) + (1e-6 * now.tv_usec);
00176 }
00177
00178 char *
00179 rdd_strsize(rdd_count_t size)
00180 {
00181 static char sizestr[MAX_SIZE_BUF_LEN];
00182
00183 if (size == RDD_WHOLE_FILE) {
00184 snprintf(sizestr, MAX_SIZE_BUF_LEN - 1, "unknown size");
00185 } else {
00186 snprintf(sizestr, MAX_SIZE_BUF_LEN - 1, "%lu", (long unsigned int) size);
00187 }
00188 sizestr[MAX_SIZE_BUF_LEN-1] = '\000';
00189
00190 if (strlen(sizestr) >= MAX_SIZE_BUF_LEN - 1) {
00191 bug("rdd_strsize: size too large for string conversion?");
00192 }
00193
00194 return sizestr;
00195 }
00196
00197 static void
00198 signal_exit(int signum)
00199 {
00200 char buf[128];
00201
00202
00203
00204 sprintf(buf, "rdd received signal %d and exits\n", signum);
00205
00206
00207 if (write(2, buf, strlen(buf)));
00208 _exit(EXIT_FAILURE);
00209 }
00210
00211 static void
00212 set_signal_handler(int signum, void (*handler)(int sig))
00213 {
00214 struct sigaction siginfo;
00215
00216 siginfo.sa_handler = handler;
00217 sigemptyset(&siginfo.sa_mask);
00218 siginfo.sa_flags = 0;
00219
00220 if (sigaction(signum, &siginfo, 0) < 0) {
00221 unix_error("cannot install signal handler for signal %d", signum);
00222 }
00223 }
00224
00225 void
00226 rdd_catch_signals(void)
00227 {
00228
00229
00230
00231
00232 #if defined(SIGPIPE)
00233 set_signal_handler(SIGPIPE, SIG_IGN);
00234 #endif
00235 #if defined(SIGXFSZ)
00236 set_signal_handler(SIGXFSZ, SIG_IGN);
00237 #endif
00238
00239
00240
00241
00242 #if defined(SIGINT)
00243 set_signal_handler(SIGINT, signal_exit);
00244 #endif
00245 #if defined(SIGTERM)
00246 set_signal_handler(SIGTERM, signal_exit);
00247 #endif
00248 }
00249
00250 int
00251 rdd_device_size(const char *path, rdd_count_t *size)
00252 {
00253 off_t offset;
00254 int fd;
00255
00256 #if 0
00257
00258
00259
00260
00261
00262 if (stat(&pathinfo, path) < 0) {
00263 }
00264
00265 if ((pathinfo.st_mode & S_ISREG) != 0) {
00266 *size = pathinfo.st_size;
00267 return RDD_OK;
00268 }
00269
00270
00271
00272 #if defined(0)
00273
00274 #else
00275 *size = RDD_WHOLE_FILE;
00276 return RDD_OK;
00277 #endif
00278 #endif
00279
00280 if ((fd = open(path, O_RDONLY)) < 0) {
00281 return RDD_EOPEN;
00282 }
00283 if ((offset = lseek(fd, 0, SEEK_END)) == (off_t) -1) {
00284 return RDD_ESEEK;
00285 }
00286
00287 *size = offset;
00288 return RDD_OK;
00289 }
00290
00291 int timeUnits(double timeInSecs, int * secs, int * mins, int * hours, int * days)
00292 {
00293 if (secs == 0) {
00294 return RDD_BADARG;
00295 }
00296 if (mins == 0) {
00297 return RDD_BADARG;
00298 }
00299 if (hours == 0) {
00300 return RDD_BADARG;
00301 }
00302 if (days == 0) {
00303 return RDD_BADARG;
00304 }
00305 (*mins) = ((int) (timeInSecs / 60));
00306 (*hours) = ((int) ((*mins) / 60));
00307 (*days) = ((int) ((*hours) / 24));
00308
00309 (*hours) %= 24;
00310 (*mins) %= 60;
00311 (*secs) = ((int) timeInSecs % 60);
00312
00313 return RDD_OK;
00314 }