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 #define MODULE_NAME "compress"
00030 #define MAKING_COMPRESS
00031
00032 #include <string.h>
00033 #include <errno.h>
00034 #include <zlib.h>
00035
00036 #include "src/mod/module.h"
00037 #include "share.mod/share.h"
00038
00039 #ifdef HAVE_MMAP
00040 # undef panic
00041 # include <sys/types.h>
00042 # include <sys/mman.h>
00043 # include <sys/stat.h>
00044 #endif
00045
00046 #include "compress.h"
00047
00048 #define BUFLEN 512
00049
00050
00051 static Function *global = NULL, *share_funcs = NULL;
00052
00053 static unsigned int compressed_files;
00054 static unsigned int uncompressed_files;
00055 static unsigned int share_compressed;
00056 static unsigned int compress_level;
00057
00058
00059 static int uncompress_to_file(char *f_src, char *f_target);
00060 static int compress_to_file(char *f_src, char *f_target, int mode_num);
00061 static int compress_file(char *filename, int mode_num);
00062 static int uncompress_file(char *filename);
00063 static int is_compressedfile(char *filename);
00064
00065 #include "tclcompress.c"
00066
00067
00068
00069
00070
00071
00072 static int is_compressedfile(char *filename)
00073 {
00074 char buf1[50], buf2[50];
00075 FILE *fin;
00076 register int len1, len2, i;
00077
00078 egg_memset(buf1, 0, 50);
00079 egg_memset(buf2, 0, 50);
00080 if (!is_file(filename))
00081 return COMPF_FAILED;
00082
00083
00084
00085 fin = gzopen(filename, "rb");
00086 if (!fin)
00087 return COMPF_FAILED;
00088 len1 = gzread(fin, buf1, sizeof(buf1));
00089 if (len1 < 0)
00090 return COMPF_FAILED;
00091 if (gzclose(fin) != Z_OK)
00092 return COMPF_FAILED;
00093
00094
00095
00096 fin = fopen(filename, "rb");
00097 if (!fin)
00098 return COMPF_FAILED;
00099 len2 = fread(buf2, 1, sizeof(buf2), fin);
00100 if (ferror(fin))
00101 return COMPF_FAILED;
00102 fclose(fin);
00103
00104
00105
00106 if (len1 != len2)
00107 return COMPF_COMPRESSED;
00108 for (i = 0; i < sizeof(buf1); i++)
00109 if (buf1[i] != buf2[i])
00110 return COMPF_COMPRESSED;
00111 return COMPF_UNCOMPRESSED;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121 static int uncompress_to_file(char *f_src, char *f_target)
00122 {
00123 char buf[BUFLEN];
00124 int len;
00125 FILE *fin, *fout;
00126
00127 if (!is_file(f_src)) {
00128 putlog(LOG_MISC, "*", "Failed to uncompress file `%s': not a file.", f_src);
00129 return COMPF_ERROR;
00130 }
00131 fin = gzopen(f_src, "rb");
00132 if (!fin) {
00133 putlog(LOG_MISC, "*", "Failed to uncompress file `%s': gzopen failed.",
00134 f_src);
00135 return COMPF_ERROR;
00136 }
00137
00138 fout = fopen(f_target, "wb");
00139 if (!fout) {
00140 putlog(LOG_MISC, "*", "Failed to uncompress file `%s': open failed: %s.",
00141 f_src, strerror(errno));
00142 return COMPF_ERROR;
00143 }
00144
00145 while (1) {
00146 len = gzread(fin, buf, sizeof(buf));
00147 if (len < 0) {
00148 putlog(LOG_MISC, "*", "Failed to uncompress file `%s': gzread failed.",
00149 f_src);
00150 return COMPF_ERROR;
00151 }
00152 if (!len)
00153 break;
00154 if ((int) fwrite(buf, 1, (unsigned int) len, fout) != len) {
00155 putlog(LOG_MISC, "*", "Failed to uncompress file `%s': fwrite "
00156 "failed: %s.", f_src, strerror(errno));
00157 return COMPF_ERROR;
00158 }
00159 }
00160 if (fclose(fout)) {
00161 putlog(LOG_MISC, "*", "Failed to uncompress file `%s': fclose failed: %s.",
00162 f_src, strerror(errno));
00163 return COMPF_ERROR;
00164 }
00165 if (gzclose(fin) != Z_OK) {
00166 putlog(LOG_MISC, "*", "Failed to uncompress file `%s': gzclose failed.",
00167 f_src);
00168 return COMPF_ERROR;
00169 }
00170 uncompressed_files++;
00171 return COMPF_SUCCESS;
00172 }
00173
00174
00175
00176 inline static void adjust_mode_num(int *mode)
00177 {
00178 if (*mode > 9)
00179 *mode = 9;
00180 else if (*mode < 0)
00181 *mode = 0;
00182 }
00183
00184 #ifdef HAVE_MMAP
00185
00186
00187 static int compress_to_file_mmap(FILE *fout, FILE *fin)
00188 {
00189 int len, ifd = fileno(fin);
00190 char *buf;
00191 struct stat st;
00192
00193
00194 if (fstat(ifd, &st) < 0)
00195 return COMPF_ERROR;
00196 if (st.st_size <= 0)
00197 return COMPF_ERROR;
00198
00199
00200 buf = mmap(0, st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
00201 if (buf < 0)
00202 return COMPF_ERROR;
00203
00204
00205 len = gzwrite(fout, buf, st.st_size);
00206 if (len != (int) st.st_size)
00207 return COMPF_ERROR;
00208
00209 munmap(buf, st.st_size);
00210 fclose(fin);
00211 if (gzclose(fout) != Z_OK)
00212 return COMPF_ERROR;
00213 return COMPF_SUCCESS;
00214 }
00215 #endif
00216
00217
00218
00219 static int compress_to_file(char *f_src, char *f_target, int mode_num)
00220 {
00221 char buf[BUFLEN], mode[5];
00222 FILE *fin, *fout;
00223 int len;
00224
00225 adjust_mode_num(&mode_num);
00226 egg_snprintf(mode, sizeof mode, "wb%d", mode_num);
00227
00228 if (!is_file(f_src)) {
00229 putlog(LOG_MISC, "*", "Failed to compress file `%s': not a file.", f_src);
00230 return COMPF_ERROR;
00231 }
00232 fin = fopen(f_src, "rb");
00233 if (!fin) {
00234 putlog(LOG_MISC, "*", "Failed to compress file `%s': open failed: %s.",
00235 f_src, strerror(errno));
00236 return COMPF_ERROR;
00237 }
00238
00239 fout = gzopen(f_target, mode);
00240 if (!fout) {
00241 putlog(LOG_MISC, "*", "Failed to compress file `%s': gzopen failed.",
00242 f_src);
00243 return COMPF_ERROR;
00244 }
00245
00246 #ifdef HAVE_MMAP
00247 if (compress_to_file_mmap(fout, fin) == COMPF_SUCCESS) {
00248 compressed_files++;
00249 return COMPF_SUCCESS;
00250 } else {
00251
00252
00253
00254 gzclose(fout);
00255 fout = gzopen(f_target, mode);
00256 }
00257 #endif
00258
00259 while (1) {
00260 len = fread(buf, 1, sizeof(buf), fin);
00261 if (ferror(fin)) {
00262 putlog(LOG_MISC, "*", "Failed to compress file `%s': fread failed: %s",
00263 f_src, strerror(errno));
00264 return COMPF_ERROR;
00265 }
00266 if (!len)
00267 break;
00268 if (gzwrite(fout, buf, (unsigned int) len) != len) {
00269 putlog(LOG_MISC, "*", "Failed to compress file `%s': gzwrite failed.",
00270 f_src);
00271 return COMPF_ERROR;
00272 }
00273 }
00274 fclose(fin);
00275 if (gzclose(fout) != Z_OK) {
00276 putlog(LOG_MISC, "*", "Failed to compress file `%s': gzclose failed.",
00277 f_src);
00278 return COMPF_ERROR;
00279 }
00280 compressed_files++;
00281 return COMPF_SUCCESS;
00282 }
00283
00284
00285
00286 static int compress_file(char *filename, int mode_num)
00287 {
00288 char *temp_fn, randstr[5];
00289 int ret;
00290
00291
00292 temp_fn = nmalloc(strlen(filename) + 5);
00293 make_rand_str(randstr, 4);
00294 strcpy(temp_fn, filename);
00295 strcat(temp_fn, randstr);
00296
00297
00298 ret = compress_to_file(filename, temp_fn, mode_num);
00299
00300
00301
00302
00303 if (ret == COMPF_SUCCESS)
00304 movefile(temp_fn, filename);
00305
00306 nfree(temp_fn);
00307 return ret;
00308 }
00309
00310
00311
00312 static int uncompress_file(char *filename)
00313 {
00314 char *temp_fn, randstr[5];
00315 int ret;
00316
00317
00318 temp_fn = nmalloc(strlen(filename) + 5);
00319 make_rand_str(randstr, 4);
00320 strcpy(temp_fn, filename);
00321 strcat(temp_fn, randstr);
00322
00323
00324 ret = uncompress_to_file(filename, temp_fn);
00325
00326
00327
00328
00329 if (ret == COMPF_SUCCESS)
00330 movefile(temp_fn, filename);
00331
00332 nfree(temp_fn);
00333 return ret;
00334 }
00335
00336
00337
00338
00339
00340
00341 static int uff_comp(int idx, char *filename)
00342 {
00343 debug1("Compressing user file for %s.", dcc[idx].nick);
00344 return compress_file(filename, compress_level);
00345 }
00346
00347 static int uff_uncomp(int idx, char *filename)
00348 {
00349 debug1("Uncompressing user file from %s.", dcc[idx].nick);
00350 return uncompress_file(filename);
00351 }
00352
00353 static int uff_ask_compress(int idx)
00354 {
00355 if (share_compressed)
00356 return 1;
00357 else
00358 return 0;
00359 }
00360
00361 static uff_table_t compress_uff_table[] = {
00362 {"compress", UFF_COMPRESS, uff_ask_compress, 100, uff_comp, uff_uncomp},
00363 {NULL, 0, NULL, 0, NULL, NULL}
00364 };
00365
00366
00367
00368
00369
00370 static tcl_ints my_tcl_ints[] = {
00371 {"share-compressed", (int *)&share_compressed},
00372 {"compress-level", (int *)&compress_level},
00373 {NULL, NULL}
00374 };
00375
00376 static int compress_expmem(void)
00377 {
00378 return 0;
00379 }
00380
00381 static int compress_report(int idx, int details)
00382 {
00383 if (details) {
00384 int size = compress_expmem();
00385
00386 dprintf(idx, " %u file%s compressed\n", compressed_files,
00387 (compressed_files != 1) ? "s" : "");
00388 dprintf(idx, " %u file%s uncompressed\n", uncompressed_files,
00389 (uncompressed_files != 1) ? "s" : "");
00390 dprintf(idx, " Using %d byte%s of memory\n", size,
00391 (size != 1) ? "s" : "");
00392 }
00393 return 0;
00394 }
00395
00396 static char *compress_close()
00397 {
00398 rem_help_reference("compress.help");
00399 rem_tcl_commands(my_tcl_cmds);
00400 rem_tcl_ints(my_tcl_ints);
00401 uff_deltable(compress_uff_table);
00402
00403 module_undepend(MODULE_NAME);
00404 return NULL;
00405 }
00406
00407 EXPORT_SCOPE char *compress_start();
00408
00409 static Function compress_table[] = {
00410
00411 (Function) compress_start,
00412 (Function) compress_close,
00413 (Function) compress_expmem,
00414 (Function) compress_report,
00415
00416 (Function) compress_to_file,
00417 (Function) compress_file,
00418 (Function) uncompress_to_file,
00419 (Function) uncompress_file,
00420
00421 (Function) is_compressedfile,
00422 };
00423
00424 char *compress_start(Function *global_funcs)
00425 {
00426 global = global_funcs;
00427
00428 compressed_files = 0;
00429 uncompressed_files = 0;
00430 share_compressed = 0;
00431 compress_level = 9;
00432
00433 module_register(MODULE_NAME, compress_table, 1, 1);
00434 if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
00435 module_undepend(MODULE_NAME);
00436 return "This module requires Eggdrop 1.6.0 or later.";
00437 }
00438
00439 share_funcs = module_depend(MODULE_NAME, "share", 2, 3);
00440 if (!share_funcs) {
00441 module_undepend(MODULE_NAME);
00442 return "This module requires share module 2.3 or later.";
00443 }
00444
00445 uff_addtable(compress_uff_table);
00446 add_tcl_ints(my_tcl_ints);
00447 add_tcl_commands(my_tcl_cmds);
00448 add_help_reference("compress.help");
00449 return NULL;
00450 }