00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <limits.h>
00024 #include <string.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <sys/stat.h>
00028 #include <unistd.h>
00029
00030 #include "htdebug.h"
00031 #include "htexcept.h"
00032 #include "htsys.h"
00033 #include "stream.h"
00034 #include "tools.h"
00035
00036
00037
00038
00039
00040 #define STREAM_COPYBUF_SIZE (64*1024)
00041
00042 ht_stream::~ht_stream()
00043 {
00044 }
00045
00046 void ht_stream::init()
00047 {
00048 stream_error_func = NULL;
00049 error = 0;
00050 access_mode = FAM_NULL;
00051 }
00052
00053 void ht_stream::done()
00054 {
00055 }
00056
00057 int ht_stream::call_error_func()
00058 {
00059 if (stream_error_func) return stream_error_func(this); else
00060 return SERR_FAIL;
00061 }
00062
00063 void ht_stream::copy_to(ht_stream *stream)
00064 {
00065 const UINT bufsize=STREAM_COPYBUF_SIZE;
00066 byte *buf=(byte*)malloc(bufsize);
00067 UINT r;
00068 do {
00069 r=read(buf, bufsize);
00070 stream->write(buf, r);
00071 } while (r == bufsize);
00072 free(buf);
00073 }
00074
00075 UINT ht_stream::get_access_mode()
00076 {
00077 return access_mode;
00078 }
00079
00080 int ht_stream::get_error()
00081 {
00082 return error;
00083 }
00084
00085 const char *ht_stream::get_desc()
00086 {
00087 return NULL;
00088 }
00089
00090 bool ht_stream::set_access_mode(UINT a)
00091 {
00092 access_mode=a;
00093 return true;
00094 }
00095
00096 void ht_stream::set_error(int e)
00097 {
00098 error=e;
00099 }
00100
00101 void ht_stream::set_error_func(stream_error_func_ptr s)
00102 {
00103 stream_error_func=s;
00104 }
00105
00106 UINT ht_stream::read(void *buf, UINT size)
00107 {
00108 return 0;
00109 }
00110
00111 UINT ht_stream::write(const void *buf, UINT size)
00112 {
00113 return 0;
00114 }
00115
00116
00117
00118
00119
00120 void ht_layer_stream::init(ht_stream *s, bool own)
00121 {
00122 ht_stream::init();
00123 stream=s;
00124 own_stream=own;
00125 }
00126
00127 void ht_layer_stream::done()
00128 {
00129 if (own_stream) {
00130 stream->done();
00131 delete stream;
00132 }
00133 ht_stream::done();
00134 }
00135
00136 void ht_layer_stream::copy_to(ht_stream *stream)
00137 {
00138 return ht_stream::copy_to(stream);
00139 }
00140
00141 UINT ht_layer_stream::get_access_mode()
00142 {
00143 return stream->get_access_mode();
00144 }
00145
00146 int ht_layer_stream::get_error()
00147 {
00148 return stream->get_error();
00149 }
00150
00151 const char *ht_layer_stream::get_desc()
00152 {
00153 return stream->get_desc();
00154 }
00155
00156 bool ht_layer_stream::set_access_mode(UINT access_mode)
00157 {
00158 return stream->set_access_mode(access_mode);
00159 }
00160
00161 void ht_layer_stream::set_error(int error)
00162 {
00163 stream->set_error(error);
00164 }
00165
00166 void ht_layer_stream::set_error_func(stream_error_func_ptr stream_error_func)
00167 {
00168 stream->set_error_func(stream_error_func);
00169 }
00170
00171 void ht_layer_stream::set_stream_ownership(bool own)
00172 {
00173 own_stream=own;
00174 }
00175
00176 UINT ht_layer_stream::read(void *buf, UINT size)
00177 {
00178 return stream->read(buf, size);
00179 }
00180
00181 UINT ht_layer_stream::write(const void *buf, UINT size)
00182 {
00183 return stream->write(buf, size);
00184 }
00185
00186
00187
00188
00189
00190 void ht_object_stream::init(ht_stream *s)
00191 {
00192 ht_layer_stream::init(s, false);
00193 }
00194
00195 void ht_object_stream::done()
00196 {
00197 ht_layer_stream::done();
00198 }
00199
00200 int ht_object_stream::getInt(int size, char *desc)
00201 {
00202 return getIntHex(size, desc);
00203 }
00204
00205 UINT ht_object_stream::recordStart(UINT size)
00206 {
00207 return 0;
00208 }
00209
00210 void ht_object_stream::recordEnd(UINT a)
00211 {
00212 }
00213
00214 void ht_object_stream::putInt(int a, int size, char *desc)
00215 {
00216 putIntHex(a, size, desc);
00217 }
00218
00219
00220
00221
00222
00223 int ht_streamfile::cntl(UINT cmd, ...)
00224 {
00225 va_list vargs;
00226 va_start(vargs, cmd);
00227 int ret=vcntl(cmd, vargs);
00228 va_end(vargs);
00229 return ret;
00230 }
00231
00232 int ht_streamfile::extend(UINT newsize)
00233 {
00234 return ENOSYS;
00235 }
00236
00237 const char *ht_streamfile::get_filename()
00238 {
00239 return NULL;
00240 }
00241
00242 UINT ht_streamfile::get_size()
00243 {
00244 return 0;
00245 }
00246
00247 void ht_streamfile::pstat(pstat_t *s)
00248 {
00249 s->caps=0;
00250 }
00251
00252 int ht_streamfile::seek(FILEOFS offset)
00253 {
00254 return ENOSYS;
00255 }
00256
00257 FILEOFS ht_streamfile::tell()
00258 {
00259 return 0;
00260 }
00261
00262 int ht_streamfile::truncate(UINT newsize)
00263 {
00264 return ENOSYS;
00265 }
00266
00267 int ht_streamfile::vcntl(UINT cmd, va_list vargs)
00268 {
00269 return ENOSYS;
00270 }
00271
00272 ht_streamfile *ht_streamfile::get_layered()
00273 {
00274 return NULL;
00275 }
00276
00277 void ht_streamfile::set_layered(ht_streamfile *s)
00278 {
00279 }
00280
00281
00282
00283
00284
00285 void ht_layer_streamfile::init(ht_streamfile *s, bool own)
00286 {
00287 ht_streamfile::init();
00288 streamfile=s;
00289 own_streamfile=own;
00290 }
00291
00292 void ht_layer_streamfile::done()
00293 {
00294 if (own_streamfile) {
00295 streamfile->done();
00296 delete streamfile;
00297 }
00298 ht_streamfile::done();
00299 }
00300
00301 void ht_layer_streamfile::copy_to(ht_stream *stream)
00302 {
00303 return ht_streamfile::copy_to(stream);
00304 }
00305
00306 int ht_layer_streamfile::extend(UINT newsize)
00307 {
00308 return streamfile->extend(newsize);
00309 }
00310
00311 UINT ht_layer_streamfile::get_access_mode()
00312 {
00313 return streamfile->get_access_mode();
00314 }
00315
00316 int ht_layer_streamfile::get_error()
00317 {
00318 return streamfile->get_error();
00319 }
00320
00321 ht_streamfile *ht_layer_streamfile::get_layered()
00322 {
00323 ht_streamfile *q = streamfile->get_layered();
00324 return q ? q : streamfile;
00325 }
00326
00327 const char *ht_layer_streamfile::get_desc()
00328 {
00329 return streamfile->get_desc();
00330 }
00331
00332 const char *ht_layer_streamfile::get_filename()
00333 {
00334 return streamfile->get_filename();
00335 }
00336
00337 UINT ht_layer_streamfile::get_size()
00338 {
00339 return streamfile->get_size();
00340 }
00341
00342 void ht_layer_streamfile::pstat(pstat_t *s)
00343 {
00344 streamfile->pstat(s);
00345 }
00346
00347 UINT ht_layer_streamfile::read(void *buf, UINT size)
00348 {
00349 return streamfile->read(buf, size);
00350 }
00351
00352 int ht_layer_streamfile::seek(FILEOFS offset)
00353 {
00354 return streamfile->seek(offset);
00355 }
00356
00357 bool ht_layer_streamfile::set_access_mode(UINT access_mode)
00358 {
00359 return streamfile->set_access_mode(access_mode);
00360 }
00361
00362 void ht_layer_streamfile::set_error(int error)
00363 {
00364 streamfile->set_error(error);
00365 }
00366
00367 void ht_layer_streamfile::set_error_func(stream_error_func_ptr stream_error_func)
00368 {
00369 streamfile->set_error_func(stream_error_func);
00370 }
00371
00372 void ht_layer_streamfile::set_layered(ht_streamfile *s)
00373 {
00374 ht_streamfile *q = streamfile->get_layered();
00375 if (q) streamfile->set_layered(s); else streamfile = s;
00376 }
00377
00378 void ht_layer_streamfile::set_streamfile_ownership(bool own)
00379 {
00380 own_streamfile=own;
00381 }
00382
00383 FILEOFS ht_layer_streamfile::tell()
00384 {
00385 return streamfile->tell();
00386 }
00387
00388 int ht_layer_streamfile::truncate(UINT newsize)
00389 {
00390 return streamfile->truncate(newsize);
00391 }
00392
00393 int ht_layer_streamfile::vcntl(UINT cmd, va_list vargs)
00394 {
00395 return streamfile->vcntl(cmd, vargs);
00396 }
00397
00398 UINT ht_layer_streamfile::write(const void *buf, UINT size)
00399 {
00400 return streamfile->write(buf, size);
00401 }
00402
00403
00404
00405
00406
00407 void ht_sys_file::init(int f, bool ofd, UINT am)
00408 {
00409 ht_streamfile::init();
00410 fd = f;
00411 offset = 0;
00412 own_fd = ofd;
00413 set_access_mode(am);
00414 }
00415
00416 void ht_sys_file::done()
00417 {
00418 if (own_fd && (fd>=0)) close(fd);
00419 ht_streamfile::done();
00420 }
00421
00422 #define EXTEND_BUFSIZE 1024
00423 int ht_sys_file::extend(UINT newsize)
00424 {
00425 int r=0;
00426
00427 UINT oldmode=get_access_mode();
00428 if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode | FAM_WRITE);
00429
00430 UINT s=get_size();
00431 char buf[EXTEND_BUFSIZE];
00432 memset(buf, 0, sizeof buf);
00433 newsize-=s;
00434 if ((r = seek(s))) return r;
00435 while (newsize) {
00436 UINT k=MIN(sizeof buf, newsize);
00437 UINT l=write(buf, k);
00438 if (l!=k) {
00439 r=EIO;
00440 break;
00441 }
00442 newsize-=l;
00443 }
00444
00445 if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode);
00446 return r;
00447 }
00448
00449 const char *ht_sys_file::get_desc()
00450 {
00451 return "file descriptor based file";
00452 }
00453
00454 UINT ht_sys_file::get_size()
00455 {
00456 int t = tell();
00457 UINT r = lseek(fd, 0, SEEK_END);
00458 lseek(fd, t, SEEK_SET);
00459 return r;
00460 }
00461
00462 UINT ht_sys_file::read(void *buf, UINT size)
00463 {
00464 if (!(access_mode & FAM_READ)) return 0;
00465 UINT r = ::read(fd, buf, size);
00466 offset += r;
00467 return r;
00468 }
00469
00470 int ht_sys_file::seek(FILEOFS o)
00471 {
00472 if (o == offset) return 0;
00473 off_t r = lseek(fd, o, SEEK_SET);
00474 offset = r;
00475 return (offset == o) ? 0 : EIO;
00476 }
00477
00478 FILEOFS ht_sys_file::tell()
00479 {
00480 return offset;
00481 }
00482
00483 UINT ht_sys_file::write(const void *buf, UINT size)
00484 {
00485 if (!(access_mode & FAM_WRITE)) return 0;
00486 UINT r = ::write(fd, buf, size);
00487 offset += r;
00488 return r;
00489 }
00490
00491
00492
00493
00494
00495 void ht_stdio_file::init(FILE *f, bool ofile, UINT am)
00496 {
00497 ht_streamfile::init();
00498 file = f;
00499 offset = 0;
00500 own_file = ofile;
00501 set_access_mode(am);
00502 }
00503
00504 void ht_stdio_file::done()
00505 {
00506 if (own_file && file) fclose(file);
00507 ht_streamfile::done();
00508 }
00509
00510 #define EXTEND_BUFSIZE 1024
00511 int ht_stdio_file::extend(UINT newsize)
00512 {
00513 int r=0;
00514
00515 UINT oldmode=get_access_mode();
00516 if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode | FAM_WRITE);
00517
00518 UINT s=get_size();
00519 char buf[EXTEND_BUFSIZE];
00520 memset(buf, 0, sizeof buf);
00521 newsize-=s;
00522 if ((r = seek(s))) return r;
00523 while (newsize) {
00524 UINT k=MIN(sizeof buf, newsize);
00525 UINT l=write(buf, k);
00526 if (l!=k) {
00527 r=EIO;
00528 break;
00529 }
00530 newsize-=l;
00531 }
00532
00533 if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode);
00534 return r;
00535 }
00536
00537 const char *ht_stdio_file::get_desc()
00538 {
00539 return "FILE based file";
00540 }
00541
00542 UINT ht_stdio_file::get_size()
00543 {
00544 int t = tell();
00545 fseek(file, 0, SEEK_END);
00546 int r = ftell(file);
00547 fseek(file, t, SEEK_SET);
00548 return r;
00549 }
00550
00551 UINT ht_stdio_file::read(void *buf, UINT size)
00552 {
00553 if (!(access_mode & FAM_READ)) return 0;
00554 UINT r = fread(buf, 1, size, file);
00555 offset += r;
00556 return r;
00557 }
00558
00559 int ht_stdio_file::seek(FILEOFS o)
00560 {
00561 if (o == offset) return 0;
00562 int r = fseek(file, o, SEEK_SET);
00563 if (r == 0) offset = o;
00564 return r;
00565 }
00566
00567 FILEOFS ht_stdio_file::tell()
00568 {
00569 return offset;
00570 }
00571
00572 UINT ht_stdio_file::write(const void *buf, UINT size)
00573 {
00574 if (!(access_mode & FAM_WRITE)) return 0;
00575 UINT r = fwrite(buf, 1, size, file);
00576 offset += r;
00577 return r;
00578 }
00579
00580
00581
00582
00583
00584 void ht_file::init(const char *fn, UINT am, UINT om)
00585 {
00586 filename = strdup(fn);
00587 open_mode = om;
00588 ht_stdio_file::init(NULL, true, am);
00589 open_mode = FOM_EXISTS;
00590 }
00591
00592 void ht_file::done()
00593 {
00594 if (filename) free(filename);
00595 ht_stdio_file::done();
00596 }
00597
00598 const char *ht_file::get_desc()
00599 {
00600 return filename;
00601 }
00602
00603 const char *ht_file::get_filename()
00604 {
00605 return filename;
00606 }
00607
00608 void ht_file::pstat(pstat_t *s)
00609 {
00610 sys_pstat(s, filename);
00611 }
00612
00613 bool ht_file::set_access_mode(UINT am)
00614 {
00615 UINT orig_access_mode = access_mode;
00616 bool r = set_access_mode_internal(am);
00617 if (!r && !set_access_mode_internal(orig_access_mode))
00618 throw new ht_io_exception("fatal error: couldn't restore file access mode. %s possibly damaged...", get_filename());
00619 return r;
00620 }
00621
00622 bool ht_file::set_access_mode_internal(UINT am)
00623 {
00624 RETRY:
00625 if (access_mode == am) return true;
00626 if (file) {
00627 fclose(file);
00628 file = NULL;
00629 }
00630 access_mode = FAM_NULL;
00631 char *mode = NULL;
00632
00633 if (open_mode & FOM_APPEND) {
00634 mode = "ab+";
00635 } else if (open_mode & FOM_CREATE) {
00636 if (am & FAM_WRITE) mode = "wb";
00637 if (am & FAM_READ) mode = "wb+";
00638 } else {
00639 if (am & FAM_READ) mode = "rb";
00640 if (am & FAM_WRITE) mode = "rb+";
00641 }
00642
00643 bool retval = true;
00644 if (am != FAM_NULL) {
00645 int e = 0;
00646 if (open_mode != FOM_CREATE) {
00647 pstat_t s;
00648 e = sys_pstat(&s, filename);
00649 if (!e) {
00650 if ((!(s.caps & pstat_mode_type) || !HT_S_ISREG(s.mode)) && (am & FAM_WRITE)) {
00651
00652 e = EACCES;
00653 } else if (HT_S_ISDIR(s.mode)) {
00654 e = EISDIR;
00655 } else if (!HT_S_ISREG(s.mode) && !HT_S_ISBLK(s.mode)) {
00656 e = EINVAL;
00657 }
00658 }
00659 }
00660 if (!e) {
00661 file = fopen(filename, mode);
00662 if (!file) e = errno;
00663 }
00664 if (e) {
00665 set_error(e | STERR_SYSTEM);
00666 if ((stream_error_func) && (stream_error_func(this) == SERR_RETRY))
00667 goto RETRY;
00668 retval = false;
00669 }
00670 }
00671 return retval && ht_streamfile::set_access_mode(am);
00672 }
00673
00674 int ht_file::truncate(UINT newsize)
00675 {
00676 int e;
00677 int old_access_mode = access_mode;
00678 if (set_access_mode(FAM_NULL)) {
00679 e = sys_truncate(filename, newsize);
00680 } else {
00681 e = EACCES;
00682 }
00683
00684 set_access_mode(old_access_mode);
00685 return e;
00686 }
00687
00688 int ht_file::vcntl(UINT cmd, va_list vargs)
00689 {
00690 switch (cmd) {
00691 case FCNTL_FLUSH_STAT: {
00692 UINT m = get_access_mode();
00693 set_access_mode(FAM_NULL);
00694 set_access_mode(m);
00695 return 0;
00696 }
00697 }
00698 return ht_streamfile::vcntl(cmd, vargs);
00699 }
00700
00701
00702
00703
00704
00705 void ht_temp_file::init(UINT am)
00706 {
00707 ht_stdio_file::init(tmpfile(), true, am);
00708 }
00709
00710 void ht_temp_file::done()
00711 {
00712 ht_stdio_file::done();
00713 }
00714
00715 const char *ht_temp_file::get_desc()
00716 {
00717 return "temporary file";
00718 }
00719
00720 void ht_temp_file::pstat(pstat_t *s)
00721 {
00722 s->caps = pstat_size;
00723 s->size = get_size();
00724 s->size_high = 0;
00725 }
00726
00727
00728
00729
00730
00731 void ht_memmap_file::init(byte *b, UINT s)
00732 {
00733 ht_streamfile::init();
00734 buf = b;
00735 pos = 0;
00736 size = s;
00737 }
00738
00739 void ht_memmap_file::done()
00740 {
00741 }
00742
00743 const char *ht_memmap_file::get_desc()
00744 {
00745 return "memmap";
00746 }
00747
00748 UINT ht_memmap_file::get_size()
00749 {
00750 return size;
00751 }
00752
00753 UINT ht_memmap_file::read(void *b, UINT s)
00754 {
00755 if (pos+s > size) s = size-pos;
00756 memmove(b, (char*)buf+pos, s);
00757 pos += s;
00758 return s;
00759 }
00760
00761 int ht_memmap_file::seek(FILEOFS offset)
00762 {
00763 pos = offset;
00764 if (pos > size) pos = size;
00765 return 0;
00766 }
00767
00768 FILEOFS ht_memmap_file::tell()
00769 {
00770 return pos;
00771 }
00772
00773 UINT ht_memmap_file::write(const void *b, UINT s)
00774 {
00775 if (pos+s > size) s = size-pos;
00776 memmove(((byte*)buf)+pos, b, s);
00777 pos += s;
00778 return s;
00779 }
00780
00781
00782
00783
00784
00785 void ht_null_file::init()
00786 {
00787 ht_streamfile::init();
00788 }
00789
00790 void ht_null_file::done()
00791 {
00792 ht_streamfile::done();
00793 }
00794
00795 int ht_null_file::extend(UINT newsize)
00796 {
00797 return newsize ? EINVAL : 0;
00798 }
00799
00800 UINT ht_null_file::get_access_mode()
00801 {
00802 return access_mode;
00803 }
00804
00805 const char *ht_null_file::get_desc()
00806 {
00807 return "null device";
00808 }
00809
00810 UINT ht_null_file::get_size()
00811 {
00812 return 0;
00813 }
00814
00815 void ht_null_file::pstat(pstat_t *s)
00816 {
00817 s->caps = pstat_size;
00818 s->size = get_size();
00819 s->size_high = 0;
00820 }
00821
00822 UINT ht_null_file::read(void *buf, UINT size)
00823 {
00824 return 0;
00825 }
00826
00827 int ht_null_file::seek(FILEOFS offset)
00828 {
00829 return offset ? EINVAL : 0;
00830 }
00831
00832 bool ht_null_file::set_access_mode(UINT am)
00833 {
00834 return (am == access_mode);
00835 }
00836
00837 FILEOFS ht_null_file::tell()
00838 {
00839 return 0;
00840 }
00841
00842 int ht_null_file::truncate(UINT newsize)
00843 {
00844 return newsize ? EINVAL : 0;
00845 }
00846
00847 UINT ht_null_file::write(const void *buf, UINT size)
00848 {
00849 return 0;
00850 }
00851
00852
00853
00854
00855
00856 #define HTMEMFILE_INITIAL_SIZE 1024
00857 #define HTMEMFILE_GROW_FACTOR_NUM 4
00858 #define HTMEMFILE_GROW_FACTOR_DENOM 3
00859
00860 void ht_mem_file::init()
00861 {
00862 ht_mem_file::init(0, HTMEMFILE_INITIAL_SIZE, FAM_READ | FAM_WRITE);
00863 }
00864
00865 void ht_mem_file::init(FILEOFS o, UINT size, UINT am)
00866 {
00867 ht_streamfile::init();
00868 ofs = o;
00869 buf = (byte*)malloc(size ? size : 1);
00870 ibufsize = size;
00871 bufsize = size;
00872 memset(buf, 0, size);
00873 pos = 0;
00874 dsize = 0;
00875 access_mode = 0;
00876 if (!set_access_mode(am)) throw new ht_io_exception("unable to open memfile");
00877 }
00878
00879 void ht_mem_file::done()
00880 {
00881 free(buf);
00882 ht_stream::done();
00883 }
00884
00885 void *ht_mem_file::bufptr()
00886 {
00887 return buf;
00888 }
00889
00890 int ht_mem_file::extend(UINT newsize)
00891 {
00892 while (bufsize<newsize) extendbuf();
00893 dsize = newsize;
00894 return 0;
00895 }
00896
00897 void ht_mem_file::extendbuf()
00898 {
00899 resizebuf(extendbufsize(bufsize));
00900 }
00901
00902 UINT ht_mem_file::extendbufsize(UINT bufsize)
00903 {
00904 return bufsize * HTMEMFILE_GROW_FACTOR_NUM / HTMEMFILE_GROW_FACTOR_DENOM;
00905 }
00906
00907 UINT ht_mem_file::get_access_mode()
00908 {
00909 return ht_stream::get_access_mode();
00910 }
00911
00912 const char *ht_mem_file::get_desc()
00913 {
00914 return "memfile";
00915 }
00916
00917 UINT ht_mem_file::get_size()
00918 {
00919 return dsize;
00920 }
00921
00922 void ht_mem_file::pstat(pstat_t *s)
00923 {
00924 s->caps = pstat_size;
00925 s->size = get_size();
00926 s->size_high = 0;
00927 }
00928
00929 UINT ht_mem_file::read(void *b, UINT size)
00930 {
00931 if (pos+size>dsize) {
00932 if (pos >= dsize) return 0;
00933 size=dsize-pos;
00934 }
00935 memmove(b, buf+pos, size);
00936 pos+=size;
00937 return size;
00938 }
00939
00940 void ht_mem_file::resizebuf(UINT newsize)
00941 {
00942 bufsize=newsize;
00943
00944 assert(dsize <= bufsize);
00945
00946 byte *t=(byte*)malloc(bufsize ? bufsize : 1);
00947 memset(t, 0, bufsize);
00948 memmove(t, buf, dsize);
00949 free(buf);
00950 buf=t;
00951 }
00952
00953 int ht_mem_file::seek(FILEOFS o)
00954 {
00955 if (o<ofs) return EINVAL;
00956 pos=o-ofs;
00957 return 0;
00958 }
00959
00960 bool ht_mem_file::set_access_mode(UINT access_mode)
00961 {
00962 if (ht_stream::set_access_mode(access_mode)) {
00963 if (seek(ofs) != 0) return false;
00964 return true;
00965 }
00966 return false;
00967 }
00968
00969 UINT ht_mem_file::shrinkbufsize(UINT bufsize)
00970 {
00971 return bufsize * HTMEMFILE_GROW_FACTOR_DENOM / HTMEMFILE_GROW_FACTOR_NUM;
00972 }
00973
00974 void ht_mem_file::shrinkbuf()
00975 {
00976 resizebuf(shrinkbufsize(bufsize));
00977 }
00978
00979 FILEOFS ht_mem_file::tell()
00980 {
00981 return pos+ofs;
00982 }
00983
00984 int ht_mem_file::truncate(UINT newsize)
00985 {
00986 dsize=newsize;
00987
00988 UINT s=ibufsize;
00989 while (s<dsize) s=extendbufsize(s);
00990
00991 resizebuf(s);
00992
00993 return 0;
00994 }
00995
00996 UINT ht_mem_file::write(const void *b, UINT size)
00997 {
00998 while (pos+size>=bufsize) extendbuf();
00999 memmove(((byte*)buf)+pos, b, size);
01000 pos+=size;
01001 if (pos>dsize) dsize=pos;
01002 return size;
01003 }
01004
01005
01006
01007
01008
01009 char *fgetstrz(ht_streamfile *file)
01010 {
01011 FILEOFS o=file->tell();
01012
01013 char buf[64];
01014 int s, z=0;
01015 int found=0;
01016 while (!found) {
01017 if (!(s=file->read(buf, 64))) return NULL;
01018 for (int i=0; i<s; i++) {
01019 z++;
01020 if (!buf[i]) {
01021 found=1;
01022 break;
01023 }
01024 }
01025 }
01026
01027 char *str=(char *)malloc(z);
01028 file->seek(o);
01029 file->read(str, z);
01030 return str;
01031 }
01032
01033
01034 #define REASONABLE_STRING_LIMIT 1024
01035
01036 char *getstrz(ht_stream *stream)
01037 {
01038
01039 char buf[REASONABLE_STRING_LIMIT];
01040 int s, z=0;
01041 while (1) {
01042 if ((s=stream->read(buf+z, 1))!=1) return NULL;
01043 z++;
01044 if (z>=REASONABLE_STRING_LIMIT) {
01045 z=REASONABLE_STRING_LIMIT;
01046 break;
01047 }
01048 if (!buf[z-1]) break;
01049 }
01050 if (!z) return NULL;
01051 char *str=(char *)malloc(z);
01052 memmove(str, buf, z-1);
01053 str[z-1]=0;
01054 return str;
01055 }
01056
01057 void putstrz(ht_stream *stream, const char *str)
01058 {
01059 stream->write(str, strlen(str)+1);
01060 }
01061
01062 char *getstrp(ht_stream *stream)
01063 {
01064 unsigned char l;
01065 stream->read(&l, 1);
01066 char *str=(char*)malloc(l+1);
01067 stream->read(str, l);
01068 *(str+l)=0;
01069 return str;
01070 }
01071
01072 void putstrp(ht_stream *stream, const char *str)
01073 {
01074 unsigned char l=strlen(str);
01075 stream->write(&l, 1);
01076 stream->write(str, l);
01077 }
01078
01079 char *getstrw(ht_stream *stream)
01080 {
01081 short t;
01082 byte lbuf[2];
01083 stream->read(lbuf, 2);
01084 int l = lbuf[0] | lbuf[1] << 8;
01085 char *a=(char*)malloc(l+1);
01086 for (int i=0; i<l; i++) {
01087 stream->read(&t, 2);
01088 *(a+i)=(char)t;
01089 }
01090 *(a+l)=0;
01091 return a;
01092 }
01093
01094 void putstrw(ht_stream *stream, const char *str)
01095 {
01096
01097 }
01098
01099 char *ht_strerror(int error)
01100 {
01101 return strerror(error & (~STERR_SYSTEM));
01102 }
01103