00001 #include <imagezero/file.h> 00002 00003 #ifdef HAVE_CONFIG_H 00004 #include "iz_config.h" 00005 #endif 00006 00007 #if defined(HAVE_MMAP) 00008 00010 00011 #include <cstdlib> 00012 #include <fcntl.h> 00013 #include <unistd.h> 00014 #include <sys/mman.h> 00015 #include <sys/stat.h> 00016 00017 namespace IZ 00018 { 00019 class InputFile::Private 00020 { 00021 public: 00022 Private() : addr(MAP_FAILED) 00023 {} 00024 00025 void* addr; 00026 size_t size; 00027 }; 00028 00029 InputFile::InputFile(const char* filename) 00030 : d(new Private) 00031 { 00032 int fd = open(filename, O_RDONLY); 00033 if (fd != -1) 00034 { 00035 struct stat sb; 00036 fstat(fd, &sb); 00037 d->size = sb.st_size; 00038 d->addr = mmap(0, d->size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0); 00039 if (d->addr == MAP_FAILED) 00040 { 00041 d->addr = mmap(0, d->size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 00042 if (d->addr != MAP_FAILED) 00043 { 00044 read(fd, d->addr, d->size); 00045 } 00046 } 00047 close(fd); 00048 } 00049 } 00050 00051 InputFile::~InputFile() 00052 { 00053 if (d->addr != MAP_FAILED) 00054 { 00055 munmap(d->addr, d->size); 00056 } 00057 delete d; 00058 } 00059 00060 bool InputFile::isReadable() const 00061 { 00062 return d->addr != MAP_FAILED; 00063 } 00064 00065 const unsigned char* InputFile::data() const 00066 { 00067 return (const unsigned char*) d->addr; 00068 } 00069 00070 size_t InputFile::dataSize() const 00071 { 00072 return d->size; 00073 } 00074 00075 00076 class OutputFile::Private 00077 { 00078 public: 00079 Private() 00080 {} 00081 00082 int fd; 00083 size_t mapSize; 00084 }; 00085 00086 OutputFile::OutputFile(const char* filename) 00087 : d(new Private) 00088 { 00089 d->fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); 00090 } 00091 00092 OutputFile::~OutputFile() 00093 { 00094 if (d->fd != -1) 00095 { 00096 close(d->fd); 00097 } 00098 delete d; 00099 } 00100 00101 bool OutputFile::isWritable() const 00102 { 00103 if (d->fd != -1) 00104 { 00105 return true; 00106 } 00107 return false; 00108 } 00109 00110 unsigned char* OutputFile::prepareData(size_t maxSize) 00111 { 00112 if (d->fd != -1) 00113 { 00114 ftruncate(d->fd, maxSize); 00115 d->mapSize = maxSize; 00116 void* addr = mmap(0, d->mapSize, PROT_WRITE | PROT_READ, MAP_SHARED, d->fd, 0); 00117 if (addr != MAP_FAILED) 00118 { 00119 return (unsigned char*) addr; 00120 } 00121 ftruncate(d->fd, 0); 00122 d->mapSize = 0; 00123 return (unsigned char*) malloc(maxSize); 00124 } 00125 return 0; 00126 } 00127 00128 void OutputFile::commitData(unsigned char* data, size_t size) 00129 { 00130 if (data) 00131 { 00132 if (d->mapSize) 00133 { 00134 munmap(data, d->mapSize); 00135 ftruncate(d->fd, size); 00136 } 00137 else 00138 { 00139 write(d->fd, data, size); 00140 free(data); 00141 } 00142 } 00143 } 00144 00145 #else // defined(HAVE_MMAP) 00146 00148 00149 #include <cstdio> 00150 #include <cstdlib> 00151 00152 class InputFile::Private 00153 { 00154 public: 00155 Private() : buffer(0), size(0) { } 00156 00157 unsigned char *buffer; 00158 size_t size; 00159 }; 00160 00161 InputFile::InputFile(const char *filename) 00162 : d(new Private) 00163 { 00164 FILE *fp = fopen(filename, "rb"); 00165 if (fp) { 00166 setbuf(fp, 0); 00167 fseek(fp, 0, SEEK_END); 00168 d->size = ftell(fp); 00169 fseek(fp, 0, SEEK_SET); 00170 if (d->size > 0) { 00171 d->buffer = (unsigned char *) malloc(d->size); 00172 if (d->buffer) { 00173 d->size = fread(d->buffer, 1, d->size, fp); 00174 } 00175 } 00176 fclose(fp); 00177 } 00178 } 00179 00180 InputFile::~InputFile() 00181 { 00182 if (d->buffer) { 00183 free(d->buffer); 00184 } 00185 delete d; 00186 } 00187 00188 bool InputFile::isReadable() const 00189 { 00190 return d->buffer != 0; 00191 } 00192 00193 const unsigned char *InputFile::data() const 00194 { 00195 return d->buffer; 00196 } 00197 00198 size_t InputFile::dataSize() const 00199 { 00200 return d->size; 00201 } 00202 00203 00204 class OutputFile::Private 00205 { 00206 public: 00207 Private() { } 00208 00209 FILE *fp; 00210 }; 00211 00212 OutputFile::OutputFile(const char *filename) 00213 : d(new Private) 00214 { 00215 d->fp = fopen(filename, "wb"); 00216 if (d->fp) { 00217 setbuf(d->fp, 0); 00218 } 00219 } 00220 00221 OutputFile::~OutputFile() 00222 { 00223 if (d->fp) { 00224 fclose(d->fp); 00225 } 00226 delete d; 00227 } 00228 00229 bool OutputFile::isWritable() const 00230 { 00231 if (d->fp) { 00232 return true; 00233 } 00234 return false; 00235 } 00236 00237 unsigned char *OutputFile::prepareData(size_t maxSize) 00238 { 00239 return (unsigned char *) malloc(maxSize); 00240 } 00241 00242 void OutputFile::commitData(unsigned char *data, size_t size) 00243 { 00244 if (data) { 00245 if (d->fp) { 00246 fwrite(data, 1, size, d->fp); 00247 } 00248 free(data); 00249 } 00250 } 00251 00252 #endif // defined(HAVE_MMAP) 00253 00254 }