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 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036
00037 #include <string.h>
00038 #include <sys/stat.h>
00039
00040 #include "rdd.h"
00041 #include "rdd_internals.h"
00042 #include "msgprinter.h"
00043 #include "outfile.h"
00044
00045 typedef struct _RDD_FILE_MSGPRINTER {
00046 char *path;
00047 FILE *stream;
00048 } RDD_FILE_MSGPRINTER;
00049
00050 static void file_print(RDD_MSGPRINTER *self, rdd_message_t type, int errcode, const char *msg);
00051 static int file_close(RDD_MSGPRINTER *self, unsigned flags);
00052
00053 static RDD_MSGPRINTER_OPS file_ops = {
00054 file_print,
00055 file_close
00056 };
00057
00058 int
00059 rdd_mp_open_file_printer(RDD_MSGPRINTER **self, const char *path, const int force_overwrite)
00060 {
00061 RDD_MSGPRINTER *p = 0;
00062 RDD_FILE_MSGPRINTER *state = 0;
00063 char *path_copy = 0;
00064 int rc = RDD_OK;
00065 FILE *fp = NULL;
00066
00067 rc = rdd_mp_open_printer(&p, &file_ops, sizeof(RDD_FILE_MSGPRINTER));
00068 if (rc != RDD_OK) {
00069 goto error;
00070 }
00071
00072 if ((path_copy = malloc(strlen(path) + 1)) == 0) {
00073 rc = RDD_NOMEM;
00074 goto error;
00075 }
00076 strcpy(path_copy, path);
00077
00078 state = (RDD_FILE_MSGPRINTER *) p->state;
00079
00080 outfile_fopen(&fp, path, force_overwrite);
00081
00082 state->stream = fp;
00083 state->path = path_copy;
00084
00085 *self = p;
00086 return RDD_OK;
00087
00088 error:
00089 *self = 0;
00090 if (fp != NULL) (void) fclose(fp);
00091 if (path_copy != 0) free(path_copy);
00092 if (state != 0) free(state);
00093 return rc;
00094 }
00095
00096 static void
00097 file_print(RDD_MSGPRINTER *self, rdd_message_t type, int errcode,
00098 const char *msg)
00099 {
00100 RDD_FILE_MSGPRINTER *file = (RDD_FILE_MSGPRINTER *) self->state;
00101
00102 fprintf(file->stream, "%s\n", msg);
00103 }
00104
00105 static int
00106 file_close(RDD_MSGPRINTER *self, unsigned flags)
00107 {
00108 RDD_FILE_MSGPRINTER *file = (RDD_FILE_MSGPRINTER *) self->state;
00109 struct stat fileinfo;
00110 mode_t ro_mode;
00111
00112 if (file->stream != NULL) (void) fclose(file->stream);
00113
00114 if (file->path != 0) {
00115 if ((flags & RDD_MP_READONLY) != 0) {
00116
00117
00118 memset(&fileinfo, 0, sizeof fileinfo);
00119 if (stat(file->path, &fileinfo) < 0) {
00120 return RDD_ECLOSE;
00121 }
00122
00123
00124
00125
00126
00127 ro_mode = fileinfo.st_mode;
00128 ro_mode &= ~(S_IFMT|S_IWUSR|S_IWGRP|S_IWOTH);
00129
00130 if (chmod(file->path, ro_mode) < 0) {
00131 return RDD_ECLOSE;
00132 }
00133 }
00134
00135 free(file->path);
00136 }
00137
00138 memset(file, 0, sizeof *file);
00139 return RDD_OK;
00140 }