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 #ifndef lint
00034 static char copyright[] =
00035 "@(#) Copyright (c) 2002-2004\n\
00036 Netherlands Forensic Institute. All rights reserved.\n";
00037 #endif
00038
00039 #ifdef HAVE_CONFIG_H
00040 #include <config.h>
00041 #endif
00042
00043 #include <errno.h>
00044 #include <fcntl.h>
00045 #include <stdarg.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 #include <unistd.h>
00049 #include <sys/stat.h>
00050
00051 #include "rdd.h"
00052 #include "writer.h"
00053
00054
00055
00056 static int safe_write(RDD_WRITER *w, const unsigned char *buf, unsigned nbyte);
00057 static int safe_close(RDD_WRITER *w);
00058 static int safe_compare_address(RDD_WRITER *w, struct addrinfo *address, int *result);
00059
00060 static RDD_WRITE_OPS safe_write_ops = {
00061 safe_write,
00062 safe_close,
00063 safe_compare_address
00064 };
00065
00066 typedef struct _RDD_SAFE_WRITER {
00067 char *path;
00068 RDD_WRITER *parent;
00069 } RDD_SAFE_WRITER;
00070
00071
00072
00073
00074 static int
00075 path_exists(const char *path, struct stat *info)
00076 {
00077 return stat(path, info) != -1 || errno != ENOENT;
00078 }
00079
00080 int
00081 rdd_open_safe_writer(RDD_WRITER **self, const char *path,
00082 rdd_write_mode_t wmode)
00083 {
00084 RDD_WRITER *w = 0;
00085 RDD_SAFE_WRITER *state = 0;
00086 struct stat statinfo;
00087 int rc = RDD_OK;
00088 char *pathcopy = 0;
00089
00090 if (self == 0) {
00091 return RDD_BADARG;
00092 }
00093 if (path == 0) {
00094 return RDD_BADARG;
00095 }
00096
00097 if (wmode == RDD_NO_OVERWRITE && path_exists(path, &statinfo)) {
00098 rc = RDD_EEXISTS;
00099 goto error;
00100 }
00101
00102 rc = rdd_new_writer(&w, &safe_write_ops, sizeof(RDD_SAFE_WRITER));
00103 if (rc != RDD_OK) {
00104 goto error;
00105 }
00106 state = (RDD_SAFE_WRITER *) w->state;
00107
00108 if ((pathcopy = malloc(strlen(path) + 1)) == 0) {
00109 rc = RDD_NOMEM;
00110 goto error;
00111 }
00112 strcpy(pathcopy, path);
00113 state->path = pathcopy;
00114
00115 rc = rdd_open_file_writer(&state->parent, path);
00116 if (rc != RDD_OK) {
00117 goto error;
00118 }
00119
00120
00121 *self = w;
00122 return RDD_OK;
00123
00124 error:
00125 *self = 0;
00126 if (pathcopy != 0) {
00127 free(pathcopy);
00128 }
00129 if (state != 0) {
00130 free(state);
00131 }
00132 if (w != 0) {
00133 free(w);
00134 }
00135 return rc;
00136 }
00137
00138 static int
00139 safe_write(RDD_WRITER *w, const unsigned char *buf, unsigned nbyte)
00140 {
00141 RDD_SAFE_WRITER *state = w->state;
00142
00143 return rdd_writer_write(state->parent, buf, nbyte);
00144 }
00145
00146 static int
00147 safe_close(RDD_WRITER *self)
00148 {
00149 RDD_SAFE_WRITER *state = self->state;
00150 struct stat statinfo;
00151 int rc;
00152
00153 if ((rc = rdd_writer_close(state->parent)) != RDD_OK) {
00154 return rc;
00155 }
00156
00157 if (stat(state->path, &statinfo) < 0) {
00158 return RDD_ECLOSE;
00159 }
00160
00161 if (S_ISREG(statinfo.st_mode)
00162 && chmod(state->path, S_IRUSR|S_IRGRP|S_IROTH) < 0) {
00163
00164
00165
00166 }
00167
00168 free(state->path);
00169 state->path = 0;
00170
00171 return RDD_OK;
00172 }
00173
00174 static int
00175 safe_compare_address(RDD_WRITER *self, struct addrinfo *address, int *result)
00176 {
00177
00178 if (self == 0) {
00179 return RDD_BADARG;
00180 }
00181 if (result == 0) {
00182 return RDD_BADARG;
00183 }
00184
00185 *result = (address == 0);
00186 return RDD_OK;
00187 }