"Fossies" - the Fresh Open Source Software Archive

Member "bed-3.1.1/src/memory.cpp" (20 May 2021, 52534 Bytes) of package /linux/misc/bed-3.1.1.src.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "memory.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.1.0_vs_3.1.1.

    1 #include "defines.h"
    2 /*     Bed a Binary EDitor for Linux and for Rxvt running under Linux.       */
    3 /*     Copyright (C) 1998  Jaap Korthals Altes <binaryeditor@gmx.com>      */
    4 /*                                                                           */
    5 /*     Bed is free software; you can redistribute it and/or modify           */
    6 /*     it under the terms of the GNU General Public License as published by  */
    7 /*     the Free Software Foundation; either version 2 of the License, or     */
    8 /*     (at your option) any later version.                                   */
    9 /*                                                                           */
   10 /*     Bed is distributed in the hope that it will be useful,                */
   11 /*     but WITHOUT ANY WARRANTY; without even the implied warranty of        */
   12 /*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
   13 /*     GNU General Public License for more details.                          */
   14 /*                                                                           */
   15 /*     You should have received a copy of the GNU General Public License     */
   16 /*     along with bed; if not, write to the Free Software                    */
   17 /*     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             */
   18 /*                                                                           */
   19 /* Sun Dec  6 18:34:27 1998                                                  */
   20 
   21 
   22 #define DEBUGUIT(...) //fprintf(stderr,__VA_ARGS__);
   23 #include "desturbe.h"
   24 #include <features.h>
   25 #include <stdio.h>
   26 #include <string.h>
   27 #include <stdlib.h>
   28 #include <sys/time.h>
   29 #include <stdint.h>
   30 #include <assert.h>
   31 #ifdef __linux__
   32 #include <linux/fs.h>
   33 #if !(defined(__LITTLE_ENDIAN_BITFIELD) || defined(__BIG_ENDIAN_BITFIELD))
   34 #define __LITTLE_ENDIAN_BITFIELD 1
   35 #endif
   36 #include <linux/cdrom.h>
   37 #endif
   38 #ifdef  HAVE_SYS_IOCTL_H 
   39 #include <sys/ioctl.h>
   40 #endif
   41 #include <limits.h>
   42 #include <unistd.h>
   43 #include <ctype.h>
   44 #include "memory.h"
   45 #include "system.h"
   46 #include "myalloc.h"
   47 #include "main.h"
   48 #include "misc.h"
   49 #ifdef USE_WINFILE
   50 #include <windows.h>
   51 #include <winioctl.h>
   52 #include "win.h"
   53 #include "winsparsecp.h"
   54 #endif
   55 
   56 extern const char NEWFILENAME[];
   57 extern const int newfilenamelen;
   58 const char NEWFILENAME[]="Untitled";
   59 const int newfilenamelen=sizeof(NEWFILENAME)-1;
   60 
   61 //s/sectoralloc(\([^;]*;\)$/alignedalloc(blocksize(),\1/g
   62 //s/sectorfree\(.*\)$/alignedfree\1/g
   63 
   64 #define databuffree(x) alignedfree(x)
   65 #define databufalloc(size) (char *)alignedalloc(BLOCKSIZE, size)
   66 
   67 int userblocksize=-1;
   68 
   69 
   70 OFFTYPE setfilepos(FILEHANDLE file,OFFTYPE offset) ;
   71 
   72 
   73 #ifdef NEEDS_BLOCKMODE
   74 inline BOOL Memory::sizehigher(OFFTYPE sizefile) {
   75 if(blockreadonly>1) {
   76     char *blk=alignedalloc(blocksize(),BLOCKSIZE);
   77     OFFTYPE offunder=(sizefile/blockreadonly)*blockreadonly;
   78     BEDS_SIZE_T  got=realblockreadat(blk,BLOCKSIZE,offunder);
   79     alignedfree(blk);
   80     return (offunder+got)>sizefile;
   81 }
   82 else {
   83     char readtestchar;
   84     return (realblockreadat(&readtestchar,1,(sizefile))>=1);
   85         }
   86 }
   87 #else
   88 inline BOOL Memory::sizehigher(OFFTYPE sizefile) {
   89     char readtestchar;
   90     return (realblockreadat(&readtestchar,1,(sizefile))>=1);
   91     }
   92 #endif
   93 //#define sizehigher(sizefile) (readat(&readtestchar,1,(sizefile))>=1)
   94 
   95 /*slaat nergens op in blocks*/
   96 inline BOOL Memory::testsize(OFFTYPE sizetest) {
   97     return (sizehigher((sizetest))?0:((sizehigher(((sizetest)-1)))?1:0));
   98     }
   99 #define MAXCDSIZEDEF (20LL*1024*1024*1024LL)
  100 extern OFFTYPE MAXCDSIZE;
  101 #if OFFTYPEMAX> MAXCDSIZEDEF
  102 OFFTYPE MAXCDSIZE = MAXCDSIZEDEF;
  103 #else
  104 OFFTYPE MAXCDSIZE = OFFTYPEMAX;
  105 #endif
  106 char realsize=0;
  107 
  108 
  109 #ifndef NEEDS_BLOCKMODE
  110 void Memory::exploresize(FILEHANDLE file,OFFTYPE begin, OFFTYPE end) {
  111     OFFTYPE half;
  112     do {
  113         half=(OFFTYPE)((LARGERTYPE)(end+begin)/2);
  114         if(sizehigher((half)))
  115             begin=half+1;
  116         else
  117             end=half;
  118         } while(end>begin);
  119     filesize=begin;
  120     if(filesize>= MAXDISCSIZE)
  121         errors=6;
  122     }
  123 #else
  124 void Memory::exploresize(FILEHANDLE file,OFFTYPE begin, OFFTYPE end) {
  125     OFFTYPE half;
  126     OFFTYPE beginblock=begin/(LARGERTYPE)blockreadonly;
  127     OFFTYPE endblock=end/(LARGERTYPE)blockreadonly;
  128     do {
  129         half=(OFFTYPE)((LARGERTYPE)(endblock+beginblock)/2);
  130         if(sizehigher((half*blockreadonly)))
  131             beginblock=half+1;
  132         else
  133             endblock=half;
  134         } while(endblock>beginblock);
  135 
  136     filesize= beginblock*blockreadonly;
  137     if(filesize>= MAXDISCSIZE)
  138         errors=6;
  139     }
  140 #endif
  141 //#define xEXPLORESIZE {if((filesize=exploresize(filehandle,begin,end))>=MAXDISCSIZE) { errors=6;}; return;}
  142 //s/EXPLORESIZE/return exploresize(filehandle,begin,end)/g
  143 OFFTYPE sizespecified=0;
  144 #ifdef USE_WINFILE
  145 FILEHANDLE opencreate(const char *filename) {
  146 return CreateFile(
  147     filename,   // address of name of the file 
  148     GENERIC_WRITE,  // access (read-write) mode 
  149     FILE_SHARE_READ|FILE_SHARE_WRITE,   // share mode 
  150     NULL,   // address of security descriptor 
  151     CREATE_ALWAYS,  // how to create 
  152     FILE_ATTRIBUTE_NORMAL,  // file attributes 
  153     NULL    // handle of file with attributes to copy  
  154    );
  155     }
  156 
  157 FILEHANDLE openreadwrite(const char *filename) {
  158 FILEHANDLE handleuit= CreateFile(
  159     filename,   // address of name of the file 
  160     GENERIC_READ|GENERIC_WRITE, // access (read-write) mode 
  161 //  FILE_SHARE_READ,
  162     FILE_SHARE_READ|FILE_SHARE_WRITE,   // share mode 
  163     NULL,   // address of security descriptor 
  164     OPEN_EXISTING,  // how to create 
  165     FILE_ATTRIBUTE_NORMAL,  // file attributes 
  166     NULL    // handle of file with attributes to copy  
  167    );
  168 
  169 return handleuit;
  170     }
  171 
  172 
  173 FILEHANDLE openreading(const char *filename) {
  174 extern char messagebuf[];
  175 extern const int maxmessagebuf;
  176 FILEHANDLE handleuit=CreateFile(
  177       filename, // address of name of the file 
  178       GENERIC_READ, // access (read-write) mode 
  179       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE
  180 ,   // share mode 
  181       NULL, // address of security descriptor 
  182       OPEN_EXISTING,    // how to create 
  183 //    FILE_ATTRIBUTE_READONLY | FILE_FLAG_NO_BUFFERING 
  184 //   FILE_ATTRIBUTE_READONLY 
  185 FILE_ATTRIBUTE_NORMAL
  186 //FILE_FLAG_RANDOM_ACCESS
  187 //0 
  188 ,   // file attributes 
  189       NULL  // handle of file with attributes to copy  
  190      );
  191 
  192 if(handleuit==INVALID_HANDLE_VALUE)
  193 {
  194 
  195  winerror(messagebuf, maxmessagebuf );
  196 /*
  197     DWORD dw = GetLastError(); 
  198     FormatMessage(
  199         FORMAT_MESSAGE_FROM_SYSTEM |
  200         FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_MAX_WIDTH_MASK,
  201         NULL,
  202         dw,
  203         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  204         (LPTSTR) &messagebuf,
  205         maxmessagebuf, NULL );
  206 */
  207 }
  208 /*
  209 gettimeofday(&tvalend,NULL);
  210 timersub(&tvalend, &tvalstart, &tvaldiff);
  211 fprintf(stderr,"%s: sec=%ld, usec=%ld\n",filename,tvaldiff.tv_sec ,tvaldiff.tv_usec);
  212 */
  213 
  214 return handleuit;
  215     }
  216 #else 
  217 
  218 #ifndef HAVE_TRUNCATE64
  219 static int mytruncate64(const char * const filename,OFFTYPE filesize) {
  220     FILEHANDLE han=LOPEN(filename,O_WRONLY LARGEFILE_FLAG BINARY_FLAG);
  221     if(han<0)
  222             return han;
  223     int ret=FTRUNCATE(han,filesize);
  224     LCLOSE(han);
  225     return ret;
  226     }
  227 #endif
  228 FILEHANDLE openreading(const char *filename) {
  229     return LOPEN(filename,O_RDONLY LARGEFILE_FLAG BINARY_FLAG);
  230     }
  231 FILEHANDLE openreadwrite(const char *filename) {
  232   return LOPEN(filename,O_RDWR LARGEFILE_FLAG BINARY_FLAG);
  233     }
  234 
  235 FILEHANDLE opencreate(const char *filename) {
  236   return LOPEN(filename,O_WRONLY|O_CREAT|O_TRUNC         LARGEFILE_FLAG BINARY_FLAG,0600);
  237     }
  238 #endif
  239 /*
  240 Returns -1 if no diskdevice, otherwise a bios disk identifier 
  241 */
  242 int isdiskdevice(char *filename) 
  243 {
  244 int disknum=-1;
  245 char start[]="\\\\.\\";
  246 char disk[]="PHYSICALDRIVE";
  247 //const int disklen=sizeof(disk)-1;
  248 const int disklen=strlen(disk);
  249 if(!strncmp(filename,start,sizeof(start)-1)) 
  250   {
  251   char *ptr=filename+sizeof(start)-1;
  252   if(ptr[2]=='\0'&&ptr[1]==':') {
  253         if((ptr[0]>='a'&&ptr[0]<='z'))   {
  254             disknum=ptr[0]-'a';
  255             }
  256   else  {
  257             if(ptr[0]>='A'&&ptr[0]<='Z') {
  258                 disknum=ptr[0]-'A';
  259                 }
  260             }
  261 
  262             }
  263   else {
  264       if(!strncasecmp(disk,ptr,disklen)) {
  265           char *endp;
  266           disknum=strtol(ptr+disklen, &endp,10);
  267           if(!endp  ||!*endp) {
  268               disknum|=0x80;
  269               }
  270 
  271           }
  272       }
  273   }
  274 return disknum;
  275 }
  276 
  277 #ifdef BIOSDISK
  278 
  279 extern bool doswin(void);
  280 
  281 #include "winpad.h"
  282 Diskread diskread=NULL,diskwrite=NULL;
  283 Getfilesize getfilesize=NULL,getblocksize=NULL;
  284 Diskopen diskopener=NULL;
  285 Diskreopen diskreopen=NULL;
  286 Diskclose diskclose=NULL;
  287 Diskpresent diskpresenter=NULL;
  288 
  289 #define BIOSDISKDLL "biosdisk32.dll"
  290 HINSTANCE biosdiskhinstance=NULL;
  291 void freebiosdisk(void) {
  292     if(biosdiskhinstance){
  293             FreeLibrary(biosdiskhinstance);
  294             biosdiskhinstance=NULL;
  295 
  296             DEBUGGING("freebiosdisk ")
  297             }
  298     }
  299 BOOL loadbiosdisk(void) {
  300     if(biosdiskhinstance)
  301         return 1;
  302 //  if( !(biosdiskhinstance=LoadLibrary(CONFDIRWIN "//" BIOSDISKDLL)))
  303     if( !(biosdiskhinstance=LoadLibrary(CONFDIRWIN "\\" BIOSDISKDLL)))
  304         if(!(biosdiskhinstance=LoadLibrary(BIOSDISKDLL))) {
  305             fprintf(stderr,"LoadLibrary(%s) failed\n",BIOSDISKDLL);
  306             return 0;
  307             }
  308     atexit(freebiosdisk);
  309     if(!(diskopener=(Diskopen)GetProcAddress(biosdiskhinstance,"diskopen"))) {
  310         fprintf(stderr,"GetProcAddress(%s,diskopen) failed\n",BIOSDISKDLL);
  311         freebiosdisk();
  312         return 0;
  313         }
  314     if(!(diskread=(Diskread)GetProcAddress(biosdiskhinstance,"diskread"))) {
  315         fprintf(stderr,"GetProcAddress(%s,diskread) failed\n",BIOSDISKDLL);
  316         freebiosdisk();
  317         return 0;
  318         }
  319     if(!(diskwrite=(Diskread)GetProcAddress(biosdiskhinstance,"diskwrite"))) {
  320         fprintf(stderr,"GetProcAddress(%s,diskwrite) failed\n",BIOSDISKDLL);
  321         freebiosdisk();
  322         return 0;
  323         }
  324     if(!(diskclose=(Diskclose)GetProcAddress(biosdiskhinstance,"diskclose"))) {
  325         fprintf(stderr,"GetProcAddress(%s,diskclose) failed\n",BIOSDISKDLL);
  326         freebiosdisk();
  327         return 0;
  328         }
  329     if(!(getblocksize=(Getfilesize)GetProcAddress(biosdiskhinstance,"getblocksize"))) {
  330         fprintf(stderr,"GetProcAddress(%s,getblocksize) failed %ld\n",BIOSDISKDLL,GetLastError());
  331         freebiosdisk();
  332         return 0;
  333         }
  334     if(!(diskreopen=(Diskreopen)GetProcAddress(biosdiskhinstance,"diskreopen"))) {
  335         fprintf(stderr,"GetProcAddress(%s,diskreopen) failed\n",BIOSDISKDLL);
  336         freebiosdisk();
  337         return 0;
  338         }
  339     if(!(getfilesize=(Getfilesize)GetProcAddress(biosdiskhinstance,"getfilesize"))) {
  340         fprintf(stderr,"GetProcAddress(%s,getfilesize) failed\n",BIOSDISKDLL);
  341         freebiosdisk();
  342         return 0;
  343         }
  344     if(!(diskpresenter=(Diskpresent)GetProcAddress(biosdiskhinstance,"diskpresent"))) {
  345         fprintf(stderr,"GetProcAddress(%s,diskpresenter) failed\n",BIOSDISKDLL);
  346         freebiosdisk();
  347         return 0;
  348         }
  349     DEBUGGING("loadbiosdisk slaagt ")
  350     return 1;
  351     }
  352 BOOL diskpresent(int disknum) {
  353     if( !loadbiosdisk() ) {
  354             return FALSE;
  355             }
  356 try {
  357 #ifdef DEBUGON
  358     DEBUGGING("try diskpresenter(%d).. ",disknum)
  359         BOOL ret= diskpresenter(disknum);
  360 if(ret)
  361     DEBUGGING("slaagt ")
  362 else
  363     DEBUGGING("faalt ")
  364     return ret;
  365 #else
  366         return diskpresenter(disknum);
  367 #endif
  368 }
  369 catch(...) {
  370 fprintf(stderr,"Error testing biosdisk %d\n",disknum);
  371 return FALSE;
  372 }
  373         }
  374  
  375 Diskinfo *diskopen(int disknum,int access) {
  376     if( !loadbiosdisk() ) {
  377             return NULL;
  378             }
  379     return diskopener(disknum,access);
  380     }
  381     
  382 struct regdisk {
  383     DWORD cylinders;
  384     DWORD heads;
  385     DWORD sectors;
  386     LONGLONG disksectors; 
  387     WORD BytesPerSector;
  388     LONGLONG disksize;
  389    }  PACKSTRUCT;
  390 typedef struct regdisk RegDisk;
  391 char registrysubkey[]="SOFTWARE\\Bed\\harddrives";
  392 OFFTYPE Memory::getregistrysize(Diskinfo *infodisk,OFFTYPE &begin,OFFTYPE &end) 
  393 {
  394     HKEY hkProtocol;
  395 //  memset(&statdata,'\0',sizeof(statdata));
  396 //  memset(&FileInfo,'\0',sizeof(FileInfo));
  397     FileInfo.nNumberOfLinks=0;
  398     if((blockreadonly=getblocksize(infodisk))<=0)  {
  399         fprintf(stderr,"Zero Blocksize\n");
  400         return OFFTYPEINVALID;
  401         }
  402     
  403     filehandle=GetStdHandle(STD_ERROR_HANDLE); /*Don't point to anyone */
  404 
  405     if((infodisk->drive&0x80)) {
  406         int disknr=infodisk->drive&0x0F;
  407         char name[10]="disk";
  408         OFFTYPE cylen= infodisk->heads*infodisk->sectors*infodisk->BytesPerSector;
  409         filesize=getfilesize(infodisk);
  410         end=filesize+cylen;
  411         sprintf(name+4,"%d",disknr);
  412         DWORD bintype=REG_BINARY,dwType ;
  413         RegDisk diskgegs;
  414         if(RegOpenKeyEx( HKEY_LOCAL_MACHINE, registrysubkey,
  415                 0, 
  416                     KEY_ALL_ACCESS  ,   // desired security access 
  417                     &hkProtocol // address of buffer for opened handle  
  418                  )==ERROR_SUCCESS) 
  419         {
  420         DWORD diskgegslen=sizeof(diskgegs);
  421         if(RegQueryValueEx(
  422                 hkProtocol, // handle of key to query 
  423                 name,   // address of name of value to query 
  424                 0,
  425                 &dwType,    // address of buffer for value type 
  426                 (BYTE *)&diskgegs,  // address of data buffer 
  427                 &diskgegslen    // address of data buffer size 
  428              )==ERROR_SUCCESS) {
  429              if(dwType==bintype&&diskgegslen==sizeof(diskgegs)&&
  430                 !memcmp(&diskgegs,infodisk,((char*)&diskgegs.disksize)-((char *)&diskgegs.cylinders))) {
  431 
  432         ;
  433                     RegCloseKey(hkProtocol);
  434                     filesize=diskgegs.disksize;
  435                     if(!realsize)
  436                             return begin=end=filesize;
  437 
  438                     }
  439                 }
  440          RegCloseKey(hkProtocol);
  441         }
  442     /*To large end doesn't fail anymore, so try something which works
  443     with my three harddisks */
  444     if(sizehigher((end))) 
  445       {
  446       do {
  447           end+=filesize;
  448           if(end>=MAXDISCSIZE) {
  449               break;
  450               }
  451           } while(sizehigher((end)));
  452       };
  453         return filesize;
  454     }
  455 #if 1
  456 else 
  457     {
  458         if(realsize)
  459         {
  460             filesize=getfilesize(infodisk);
  461             begin=0;end=2*filesize;
  462             return filesize;
  463         }   
  464         else 
  465             return filesize=begin=end=getfilesize(infodisk);
  466     }
  467 #else
  468 else     { /*Determine floppy size */
  469         const OFFTYPE highsize=2880*512,doubsize=1440*512;
  470         end=getfilesize(infodisk);
  471     if(end>=highsize&&sizehigher((highsize-1))) {
  472                 if(end==highsize||!sizehigher(highsize))
  473                     return filesize=begin=end=highsize;
  474                 else    {
  475                     begin=highsize+1;
  476                     }
  477                 }
  478         else {
  479             fprintf(stderr,"end="OFFPRINT " highsize=" OFFPRINT,end,highsize);
  480                 if(sizehigher(doubsize-1)) {
  481                         if(!sizehigher(doubsize))
  482                             return filesize=begin=end=doubsize;
  483                         else    {
  484                             begin=doubsize-1;
  485                             end=highsize-1;
  486                             }
  487 
  488                         }
  489                 else {
  490                     end=doubsize-1;
  491                     }
  492                 }
  493 
  494     return 0;
  495     }
  496 #endif
  497 }
  498 BOOL Memory::setregistrysize(Diskinfo *infodisk,OFFTYPE filesize) 
  499 {
  500 if(!(infodisk->drive&0x80))
  501     return TRUE;
  502 
  503     HKEY hkProtocol;
  504     DWORD dispos;
  505     if(RegCreateKeyEx(
  506             HKEY_LOCAL_MACHINE,
  507             registrysubkey,
  508             0,  // reserved 
  509             "Geometry", // address of class string 
  510             REG_OPTION_VOLATILE,    // special options flag 
  511             KEY_ALL_ACCESS  ,   // desired security access 
  512             NULL,   // address of key security structure 
  513             &hkProtocol,    // address of buffer for opened handle  
  514             &dispos     // address of disposition value buffer 
  515                  )==ERROR_SUCCESS) 
  516      {
  517         RegDisk diskgegs;
  518         int disknr=infodisk->drive&0x0F;
  519         char name[10]="disk";
  520         sprintf(name+4,"%d",disknr);
  521         DWORD bintype=REG_BINARY;
  522         memcpy(&diskgegs,infodisk,(((char*)&diskgegs.disksize)-((char *)&diskgegs.cylinders)));
  523         diskgegs.disksize=filesize;
  524         if(RegSetValueEx(hkProtocol,
  525                 name,   // address of value to set 
  526                 0,
  527                 bintype,    // flag for value type 
  528                 (BYTE *)&diskgegs,  // address of value data 
  529                 sizeof(diskgegs)    // size of value data 
  530              )!=ERROR_SUCCESS) 
  531         {
  532             fprintf(stderr,"RegSetValueEx failed\n"); 
  533             return FALSE;
  534         }
  535         return TRUE;
  536     }
  537 return FALSE;
  538 }
  539 
  540 #endif
  541 #ifdef USE_WINFILE
  542 
  543 inline bool set_dasd_io(HANDLE filehandle) {
  544     DWORD retsize;
  545 return  DeviceIoControl(
  546       filehandle,              // handle to device
  547       FSCTL_ALLOW_EXTENDED_DASD_IO,  // dwIoControlCode
  548       NULL,                          // lpInBuffer
  549       0,                             // nInBufferSize
  550       NULL,                          // lpOutBuffer
  551       0,                             // nOutBufferSize
  552         &retsize,     // number of bytes returned
  553       NULL   // OVERLAPPED structure
  554     );
  555     }
  556 
  557 inline FILEHANDLE Memory::openreading(const char *filename) {
  558 FILEHANDLE handleuit=::openreading(filename);
  559 #ifdef USE_WINFILE
  560 if(used_dasd_io) {
  561       set_dasd_io( handleuit);
  562     }
  563 #endif
  564 return handleuit;
  565 }
  566 
  567 inline FILEHANDLE Memory::openreadwrite(const char *filename) {
  568 FILEHANDLE handleuit= :: openreadwrite(filename);
  569 #ifdef USE_WINFILE
  570 if(used_dasd_io) {
  571       set_dasd_io( handleuit);
  572     }
  573 #endif
  574 return handleuit;
  575 }
  576 
  577 
  578 
  579 #define TOLONGLONG(largeint) (((largeint).LowPart)|(((long long)((largeint).HighPart))<<32))
  580 extern OSVERSIONINFO WindowsVersion;
  581 OFFTYPE Memory::win32diskfilesize(FILEHANDLE filehandle,OFFTYPE *begin,OFFTYPE *end) {
  582 if(WindowsVersion.dwOSVersionInfoSize&&WindowsVersion.dwPlatformId!=VER_PLATFORM_WIN32_WINDOWS) {
  583     OFFTYPE abegin=0,anend=MAXDISCSIZE;
  584 
  585     DWORD retsize;
  586 #warning "FSCTL_ALLOW_EXTENDED_DASD_IO doesn't work for PhysicalDrive0 etc. Check on what?"
  587 if(set_dasd_io(filehandle))
  588     used_dasd_io=true;
  589   DISK_GEOMETRY diskgeo;
  590     if(DeviceIoControl(filehandle, IOCTL_DISK_GET_DRIVE_GEOMETRY
  591         , NULL, 0, &diskgeo, sizeof(diskgeo), &retsize,NULL)) {
  592     abegin=TOLONGLONG(diskgeo.Cylinders)*diskgeo.TracksPerCylinder*
  593        diskgeo.SectorsPerTrack*diskgeo.BytesPerSector;
  594 
  595 #ifndef NEEDS_BLOCKMODE
  596 int
  597 #endif
  598     blockreadonly=diskgeo.BytesPerSector;
  599     BLOCKSIZE=((BLOCKSIZE-1)/blockreadonly+1)*blockreadonly;
  600     }
  601 if(WindowsVersion.dwMajorVersion>5||( WindowsVersion.dwMajorVersion==5&& WindowsVersion.dwMinorVersion>0)) {
  602     GET_LENGTH_INFORMATION devlen;
  603     if(DeviceIoControl(
  604           filehandle,              // handle to device
  605           IOCTL_DISK_GET_LENGTH_INFO,    // dwIoControlCode
  606           NULL,                          // lpInBuffer
  607           0,                             // nInBufferSize
  608           (LPVOID) &devlen,          // output buffer
  609           (DWORD) sizeof(devlen),        // size of output buffer
  610           (LPDWORD) &retsize,     // number of bytes returned
  611           NULL    // OVERLAPPED structure
  612             )){
  613 
  614             if(realsize) {
  615                 anend= devlen.Length.QuadPart;
  616 
  617                 }   
  618             else
  619                 return devlen.Length.QuadPart;
  620 
  621         }
  622     }
  623     else {
  624     PARTITION_INFORMATION parinfo;
  625     if(DeviceIoControl(filehandle, IOCTL_DISK_GET_PARTITION_INFO 
  626 
  627         , NULL, 0, &parinfo, sizeof(parinfo), &retsize,NULL)) {
  628     anend=(OFFTYPE)parinfo.PartitionLength.QuadPart;
  629     }
  630     }
  631     if(abegin>anend)
  632         myswap(abegin,anend);
  633     if(*begin<abegin) {
  634       if(sizehigher(abegin-1)) {
  635         if(!sizehigher(abegin))
  636         return abegin;
  637         else
  638         *begin=abegin;
  639        }
  640      else {
  641         *end=abegin-1;
  642         return 0;
  643         }
  644      }
  645     if(anend<*end) {
  646         if(!sizehigher(anend)) {
  647             if(sizehigher(anend-1))
  648                 return anend;
  649             *end=anend-1;
  650             }
  651         else {
  652             if(!realsize)
  653                 return anend;
  654             }
  655         }
  656     }
  657 
  658 return 0;
  659 }
  660 #endif
  661 int setblocksize(int bsize) {
  662     int BLOCKSIZE;
  663     if(userblocksize>0) {
  664         BLOCKSIZE=userblocksize;
  665         }
  666     else {
  667         if(bsize>STBLOCKSIZE)
  668             BLOCKSIZE=bsize;
  669         else
  670             BLOCKSIZE=STBLOCKSIZE;
  671         }
  672     return BLOCKSIZE;   
  673     }
  674 
  675 #ifdef __FreeBSD__
  676 int getblockreadonly(FILEHANDLE filehandle) 
  677 {
  678     char readtestchar;
  679     int blockread=1;
  680     if(LPREAD(filehandle,&readtestchar,1,0)<1) 
  681     {
  682         int freebsdblocksize=1024;
  683         char buf[freebsdblocksize];
  684         if(LPREAD(filehandle,buf,freebsdblocksize,0)==freebsdblocksize) 
  685         {
  686             blockread=freebsdblocksize;
  687             LSEEK(filehandle,0,SEEK_SET);
  688         }
  689     }
  690     return blockread;
  691 }
  692 #endif
  693 inline BOOL Memory::checkfilesize(OFFTYPE filsize,OFFTYPE &begin,OFFTYPE &end) 
  694 {
  695 
  696     if(sizehigher(filsize)) {
  697         if(filsize>begin)
  698             begin=filsize;
  699         }
  700     else 
  701     {
  702         if(sizehigher(filsize-1)) 
  703             return TRUE;
  704         else {
  705             if(filsize<=end)
  706                 end=filsize-1;
  707             }
  708     }
  709     return FALSE;
  710 }   
  711 #ifdef _WIN32
  712 int Memory::getfileinfo( BY_HANDLE_FILE_INFORMATION *FInfo ) {
  713 int ret;
  714 if(!(ret=GetFileInformationByHandle(filehandle,FInfo ))) {
  715         FInfo->nNumberOfLinks=0;
  716         }
  717 return ret;
  718 }
  719 
  720 
  721 /*
  722 inline bool Memory::opendosdrive(const char *const filename,OFFTYPE &begin, OFFTYPE &end) {
  723 int disknum;
  724 if((disknum=isdiskdevice(filename))!=-1) 
  725   {
  726   if((infodisk=diskopen(disknum,O_RDONLY))) 
  727     {
  728     if((filesize=getregistrysize(infodisk,begin,end))==OFFTYPEINVALID) {
  729             diskclose(infodisk);infodisk=NULL;  
  730             errors=77;
  731             return;
  732             }
  733     if(begin==end)
  734         dontcheck=1;
  735     }
  736 */
  737 #endif
  738 
  739 #ifdef __linux__
  740 bool Memory::getsizelinux(OFFTYPE &begin,OFFTYPE &end) {
  741 const bool foundsize=true;
  742 const bool notfoundsize=false;
  743         if(S_ISBLK(statdata.st_mode)) {
  744             int blkgetsize;
  745             if(ioctl(filehandle,BLKGETSIZE ,&blkgetsize)>=0) { 
  746                 filesize= (OFFTYPE) blkgetsize*512;
  747                 if(sizehigher(filesize)) 
  748                     begin=filesize;
  749                 else {
  750                     if(sizehigher(filesize-1)) 
  751                         return foundsize;
  752                     else
  753                         end=filesize-1;
  754                     }
  755                 }
  756         DEBUG("BLKGETSIZE failed\n");
  757 /*Maybe a cdrom drive */
  758 #ifdef CDROM_DISC_STATUS
  759         if(ioctl(filehandle,CDROM_DISC_STATUS)<0) {
  760                  return notfoundsize;
  761             }
  762         else { /*Cdrom */
  763                 uint32_t pos[2];
  764 //              char sbuf[8];
  765 //              char *sbuf=reinterpret_cast<char *>(pos);
  766                 char *sbuf=(char *)(pos);
  767                 OFFTYPE lookat=0x8050;
  768                 OFFTYPE newbegin,newend;
  769 
  770                 if(readat(sbuf,8,lookat)>=8&&memcmp(sbuf,sbuf+4,4)) {
  771                     for(int i=0;i<4;i++) {
  772                         if(sbuf[i]!=sbuf[7-i]) {
  773                             DEBUG("No opposite");
  774                         return notfoundsize;
  775                             }
  776                         }
  777                     newbegin=*pos*static_cast<OFFTYPE>(2048);
  778 //                  newbegin=*reinterpret_cast<uint32_t*>(&sbuf)*static_cast<OFFTYPE>(2048);
  779                     if(sizehigher(newbegin-1)) {
  780 
  781                         if(realsize&&sizehigher(newbegin)) {
  782                             begin=newbegin;
  783                             newend=MAXCDSIZE;
  784                             if(sizehigher(newend)) 
  785                                 begin=newend;
  786                             else {
  787                                 end=newend;
  788                                      }
  789                         return notfoundsize;
  790                             }
  791                         else {
  792                             filesize=newbegin;
  793 
  794                         return foundsize;
  795                             }
  796 
  797                         }
  798                     else {
  799                         end=newbegin; 
  800                         }
  801                     
  802                     } /*End Read cdromsize */
  803 
  804                         return notfoundsize;
  805 
  806             } /*END cdrom */
  807 #else
  808             return notfoundsize;
  809 #endif
  810         } /*END block device */
  811 
  812     return notfoundsize;
  813     }
  814 #endif /*linux */
  815 /*
  816 typedef union _LARGE_INTEGER {
  817   struct {
  818     DWORD LowPart;
  819     LONG  HighPart;
  820   };
  821   struct {
  822     DWORD LowPart;
  823     LONG  HighPart;
  824   } u;
  825   LONGLONG QuadPart;
  826 } LARGE_INTEGER, *PLARGE_INTEGER;
  827 */
  828 inline void Memory::regfilesize(void ) {
  829     #ifdef USE_WINFILE
  830 filesize=((unsigned long long)FileInfo.nFileSizeHigh)<<32|FileInfo.nFileSizeLow;
  831 if(filesize==0LL) {
  832 #if 0
  833     ((DWORD *)&filesize)[0]= GetFileSize(filehandle, ((DWORD *)&filesize)+1 );
  834 #else
  835     if(!GetFileSizeEx( filehandle, reinterpret_cast<PLARGE_INTEGER>(&filesize)))
  836             filesize=0;
  837 #endif
  838     }
  839 #else
  840     filesize=statdata.st_size;
  841 #endif
  842 //fprintf(stderr,"Filesize="OFFPRINT"\n",filesize);
  843     }
  844 #ifndef _WIN32
  845 bool Memory::statmis() {
  846 #ifdef PROCLOCKSBUG
  847     if(!strcmp(filename,"/proc/locks")) {
  848         errors=9;
  849         return true;
  850         }
  851 #endif
  852     if(STAT(filename,&statdata)) {
  853 #ifdef NOSTAT
  854         memset(&statdata,'\0',sizeof(statdata));
  855 #else
  856         errors=8;   
  857         return true;
  858 #endif
  859         }
  860     else
  861     if( S_ISFIFO(statdata.st_mode)  ) {
  862         errors=7;
  863         return true;
  864         }
  865 return false;
  866     }
  867 #endif
  868 void Memory::openfile(void) 
  869 {
  870 OFFTYPE begin=0;
  871 OFFTYPE end = MAXDISCSIZE;
  872 filehandle=MY_INVALID_HANDLE_VALUE;
  873 #ifdef BIOSDISK
  874 
  875 if(doswin()) 
  876 {
  877 int disknum;
  878 if((disknum=isdiskdevice(filename))!=-1) 
  879   {
  880   if((infodisk=diskopen(disknum,O_RDONLY))) 
  881     {
  882     if((filesize=getregistrysize(infodisk,begin,end))==OFFTYPEINVALID) {
  883             diskclose(infodisk);infodisk=NULL;  
  884             errors=77;
  885             return;
  886             }
  887     goto havesize;
  888    }
  889   }
  890 }
  891 {
  892 #endif
  893 #ifndef _WIN32
  894 if(statmis())
  895     return;
  896 #endif
  897 
  898 if((filehandle=openreading(filename))==MY_INVALID_HANDLE_VALUE) {
  899       errors=9;
  900       return;
  901     }   
  902 #ifdef __FreeBSD__
  903 if(statdata.st_mode&S_IFBLK ) 
  904     blockreadonly=getblockreadonly(filehandle);
  905 #endif
  906 
  907 
  908 #ifdef _WIN32
  909 getfileinfo(&FileInfo);
  910 #endif
  911 #ifdef BIOSDISK
  912 }
  913 havesize:
  914 
  915 #endif
  916 
  917 #ifdef _WIN32
  918 BLOCKSIZE= setblocksize(STBLOCKSIZE );
  919 #else
  920 BLOCKSIZE=setblocksize(statdata.st_blksize);
  921 #endif
  922 
  923 
  924 #ifdef USE_WINFILE
  925 if(filename[0]=='\\'
  926 
  927 #ifdef BIOSDISK
  928 &&!infodisk
  929 #endif
  930 ) {
  931     filesize=win32diskfilesize(filehandle,&begin,&end) ;
  932 }
  933 #endif
  934 if(sizespecified) {
  935     filesize=sizespecified;
  936     return;
  937     }
  938 
  939 #ifdef BIOSDISK
  940 if(infodisk) {
  941     if(begin==end&&!realsize) 
  942         return;
  943     if((filesize>0&&checkfilesize(filesize,begin,end))) 
  944                     return;
  945     return exploresize(filehandle,begin,end) ;
  946     }
  947 else
  948 #endif
  949 #ifdef USE_WINFILE
  950 {
  951 if(filesize)
  952         return;
  953 if(begin||(end!= MAXDISCSIZE)) {
  954     return exploresize(filehandle,begin,end) ;
  955     }
  956 }
  957 #endif
  958 #ifndef ALWAYSEXPLORESIZE
  959 #ifdef _WIN32
  960 if(FileInfo.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
  961 {
  962     errors=5;
  963     return;
  964 }
  965 #else
  966 if(S_ISREG(statdata.st_mode) ) 
  967 {
  968 #endif
  969 mmapfailed=0;
  970 regfilesize();
  971 if(filesize>0&&checkfilesize(filesize,begin,end))
  972         return;
  973     goto catchall;
  974 #ifndef _WIN32
  975 }
  976 else   
  977 {
  978 
  979 #ifdef __linux__
  980 if(getsizelinux(begin,end)) 
  981     return;
  982 #endif
  983 } /*END not regular */
  984 if(S_ISDIR(statdata.st_mode)) 
  985 {
  986     errors=5;
  987     return;
  988 }
  989 else 
  990 #endif // WIN32
  991 #endif /*ALWAYSEXPLORESIZE*/
  992 {
  993  catchall:
  994  return exploresize(filehandle,begin,end) ;
  995 }
  996 }
  997 
  998 
  999 
 1000 
 1001 
 1002 
 1003 
 1004 
 1005 
 1006 
 1007 
 1008 
 1009 
 1010 
 1011 
 1012 
 1013 
 1014 
 1015 
 1016 
 1017 
 1018 
 1019 
 1020 
 1021 
 1022 
 1023 
 1024 
 1025 
 1026 
 1027 
 1028 
 1029 
 1030 
 1031 
 1032 
 1033 
 1034 
 1035 
 1036 
 1037 
 1038 
 1039 
 1040 
 1041 
 1042 
 1043 
 1044 
 1045 inline void Memory::initall(void) {
 1046 }
 1047 void Memory::init(const char *name) {
 1048     initall();
 1049     const int len=filenamelen+1;
 1050     filename=myallocar( char,len+3);
 1051     memcpy(filename,name,len);
 1052 
 1053     openfile();
 1054 #ifdef BIOSDISK
 1055 if(infodisk)
 1056     setregistrysize(infodisk,filesize);
 1057 #endif
 1058     diskfilesize=filesize;
 1059 
 1060     useddiskfilesize=diskfilesize;
 1061 
 1062 #if defined(USETHREADS) && !defined(INTSEARCH)
 1063 //if(filesize>(OFFTYPE)40000000L)
 1064 //  lastforward|=0x10;
 1065 #endif
 1066     }
 1067 
 1068 
 1069 int newfilesize=1024;
 1070 extern int newfilesize;
 1071 
 1072 Memory::Memory(const char *name): 
 1073 #ifdef USE_WINFILE
 1074     used_dasd_io(false),
 1075 #endif
 1076 #ifdef BIOSDISK
 1077     infodisk(NULL),
 1078 #endif
 1079 #ifdef NEEDS_BLOCKMODE
 1080 blockreadonly(1),
 1081 #endif
 1082 errors(0),
 1083 //readonly(0),filesize(0), lastforward(1),filenamelen(strlen(name))
 1084 //readonly(0),filesize(0), lastforward(3),searchpos(0),filenamelen(name?strlen(name):0)
 1085 readonly(0),filesize(0), filenamelen(name?strlen(name):0)
 1086 {
 1087      INITUSELSEEK;
 1088      if(name)
 1089         init(name);
 1090      else {
 1091        initall();
 1092     filesize=newfilesize;
 1093     BLOCKSIZE=512;
 1094     filehandle= MY_INVALID_HANDLE_VALUE;
 1095 #ifndef _WIN32
 1096     memset((void *)&statdata,0,sizeof(statdata));
 1097 #endif
 1098     }
 1099 }
 1100 void closefilehandle(FILEHANDLE file) {
 1101   #ifdef USE_WINFILE
 1102       if(file!=MY_INVALID_HANDLE_VALUE) {
 1103           if(!CloseHandle(file)) {
 1104               fprintf(stderr,"Close failed\n");
 1105               }
 1106           }
 1107   #else
 1108       if(file>0)
 1109           LCLOSE(file);
 1110   #endif
 1111     }
 1112 void Memory::endfile(void) {
 1113 #ifdef BIOSDISK
 1114     if(infodisk) {
 1115         diskclose(infodisk);
 1116         infodisk=NULL;
 1117         }
 1118     else
 1119 #endif
 1120       closefilehandle(filehandle);
 1121     empty();
 1122     if(filename)
 1123         myfree( filename);
 1124     }
 1125 /*
 1126 int Memory::reinit(const char *name) {
 1127     endfile();
 1128      init(name);
 1129      return 0;
 1130     }
 1131 int Memory::reinit(void) {
 1132     return reinit(filename);
 1133     }
 1134     */
 1135 int Memory::empty(void) {
 1136     for(Treel *iter=tree.treecontrol->roottree;iter!=tree.NIL;iter=tree.next(iter))
 1137         databuffree( iter->data.buf);
 1138     tree.empty();
 1139     return 0;
 1140     }
 1141 
 1142 Memory::~Memory() {
 1143     endfile();
 1144      DESTROYUSELSEEK;
 1145     }
 1146 
 1147 
 1148 #ifdef USE_WINFILEnietgebruikt
 1149 int myftruncate(FILEHANDLE output,OFFTYPE size) {
 1150     if(setfilepos(output,size)!=size) {
 1151         return -1;
 1152         }
 1153     if(!SetEndOfFile(output)) {
 1154         return -1;
 1155         }
 1156     return 0;
 1157     }
 1158 #endif
 1159 
 1160 #ifdef USE_WINFILE
 1161 #define myftruncate  sparsesize
 1162 extern bool mksparse(HANDLE hOutFile) ;
 1163 #else
 1164 #define mksparse(x)
 1165 #endif
 1166 FILEHANDLE Memory::reopen() {
 1167     FILEHANDLE output=openreadwrite(filename);
 1168     if(output==MY_INVALID_HANDLE_VALUE)
 1169        return MY_INVALID_HANDLE_VALUE;
 1170     if(filesize!=diskfilesize) {
 1171         if(filesize>useddiskfilesize) {
 1172             mksparse(output);
 1173             if( FTRUNCATEHANDLE(output,useddiskfilesize)!=0) {
 1174                 closefilehandle(output);
 1175                 return MY_INVALID_HANDLE_VALUE;
 1176                 }
 1177             }
 1178         if( FTRUNCATEHANDLE(output,filesize)!=0) {
 1179             closefilehandle(output);
 1180             return MY_INVALID_HANDLE_VALUE;
 1181             }
 1182         }
 1183     return output;
 1184     }
 1185 
 1186 
 1187 
 1188 
 1189 
 1190 /* Bepaal of file veranderd is na opstarte of laatste keer saven             */
 1191 /* Ga alle nodes af en save die nodes.                                       */
 1192 /* Nodes delete                                                              */
 1193 /*                                                                           */
 1194 /* Saven van een node:                                                       */
 1195 /*  - ga naar positie file;                                                  */
 1196 /*  - schrijf gegevens in file                                               */
 1197 /*  - delete gegevens                                                        */
 1198 /* Sat Oct  3 00:50:05 1998                                                  */
 1199 
 1200 int Memory::savenode(FILEHANDLE output, Treel *node) {
 1201     DEBUG("Save " BLOCKPRINT "\n",node->data.blocknr);
 1202     OFFTYPE diff=filesize-(node->data.blocknr*BLOCKSIZE);
 1203     if(diff>0) {
 1204         BEDS_SIZE_T size=(diff<BLOCKSIZE)?diff:BLOCKSIZE;
 1205         if(node->data.size<size) {
 1206             fprintf(stderr,"WARNING: savenode/1: not enough in node " BLOCKPRINT " " SIZE_TPRINT "<" SIZE_TPRINT "\n",node->data.blocknr,size,node->data.size);
 1207             size=node->data.size;
 1208             }
 1209         return writeat(output,node->data.buf,size,node->data.blocknr*BLOCKSIZE);
 1210         }
 1211     return 0;
 1212     }
 1213 
 1214 int Memory::touched(void) {
 1215     if(isnewfile())
 1216         return 0;
 1217 #ifdef BIOSDISK
 1218 if(!infodisk) 
 1219 #endif
 1220 {
 1221 #ifdef _WIN32
 1222 
 1223 BY_HANDLE_FILE_INFORMATION FInfo;
 1224 
 1225 if(!getfileinfo(&FInfo )) {
 1226     return -1;
 1227     }
 1228 #define ongelijk(info) FInfo.info!=FileInfo.info
 1229 #define oncmp
 1230 #define lastw(name) (char *)&(name.ftLastWriteTime)
 1231 if(memcmp(lastw(FInfo),lastw(FileInfo),sizeof(FInfo.ftLastWriteTime)))
 1232     return 5;
 1233 if(ongelijk(nFileSizeHigh))
 1234     return 3;
 1235 if(ongelijk(nFileSizeLow))
 1236     return 3;
 1237 if(ongelijk(nFileIndexHigh))
 1238     return 4;
 1239 if(ongelijk(nFileIndexLow))
 1240     return 4;
 1241 
 1242 #else
 1243     STATTYPE st;
 1244     if(STAT(filename,&st)<0)
 1245         return -1;
 1246     if(st.st_mtime!=statdata.st_mtime)
 1247         return 5;
 1248     if(st.st_size!=statdata.st_size)
 1249         return 3;
 1250     if(st.st_ino!=statdata.st_ino)
 1251         return 4;
 1252 #endif
 1253     }
 1254     return 0;
 1255     }
 1256 OFFTYPE setfilepos(FILEHANDLE file,OFFTYPE offset) {
 1257 #ifdef USE_WINFILE
 1258 LONG hi=offset>>32;
 1259 DWORD lo;
 1260 lo=SetFilePointer(file,
 1261         offset&0xFFFFFFFF,  // number of bytes to move file pointer 
 1262             &hi,    // address of high-order word of distance to move  
 1263         FILE_BEGIN
 1264                    );
 1265 if(lo==0xFFFFFFFF&&GetLastError()) {
 1266     return OFFTYPEINVALID;
 1267     }
 1268 return (lo|(((OFFTYPE)hi)<<32));
 1269 #else
 1270 return LSEEK(file,offset,SEEK_SET);
 1271 #endif
 1272 }
 1273 
 1274 int Memory::saveall(void) {
 1275 int errors=0;
 1276 #ifdef USE_WINFILE
 1277 FILEHANDLE output=GetStdHandle(STD_ERROR_HANDLE); /* So it doesn't point to someone */
 1278 #else
 1279 FILEHANDLE output=STDERR_FILENO; 
 1280 #endif
 1281 
 1282     if(readonly) {
 1283         return -2;
 1284         }
 1285 #ifdef BIOSDISK
 1286 if(infodisk) {
 1287     infodisk=diskreopen(infodisk,O_RDWR);
 1288     for(Treel *iter=tree.treecontrol->roottree;iter!=tree.NIL;iter=tree.next(iter)) {
 1289         if(savenode(output,iter)<0) {
 1290               infodisk=diskreopen(infodisk,O_RDONLY);
 1291                 errors=-3;
 1292                 return errors;
 1293                 }
 1294         databuffree( iter->data.buf);
 1295         }
 1296     tree.empty();
 1297     infodisk=diskreopen(infodisk,O_RDONLY);
 1298     return errors;
 1299     }
 1300 else
 1301 #endif
 1302 {
 1303     closefilehandle(filehandle); /*Because file is changed */ 
 1304 
 1305 if((output=reopen())==MY_INVALID_HANDLE_VALUE) {
 1306 //      readonly=1;
 1307 #ifdef USE_WINFILE
 1308 errors=WINERROR;
 1309     Memory::errors=GetLastError();
 1310 #else
 1311         if(errno)
 1312             errors=errno;
 1313         else
 1314             errors=-1;
 1315 #endif
 1316         if((filehandle=openreading(filename))==MY_INVALID_HANDLE_VALUE) {
 1317 #ifndef USE_WINFILE
 1318             if(errno)
 1319                 errors=errno;
 1320             else
 1321                 errors=-1;
 1322 #else
 1323     Memory::errors=GetLastError();
 1324 #endif
 1325             }
 1326         return errors;
 1327         }
 1328 /*
 1329 #ifdef USE_WINFILE
 1330 if(used_dasd_io) {
 1331       set_dasd_io( filehandle);
 1332     }
 1333 #endif
 1334 */
 1335     for(Treel *iter=tree.treecontrol->roottree;iter!=tree.NIL;iter=tree.next(iter)) {
 1336         if(savenode(output,iter)<0) {
 1337             #ifdef USE_WINFILE
 1338                 Memory::errors=GetLastError();
 1339             errors=WINERROR;
 1340 #else
 1341                 if(errno)
 1342                         errors=errno;
 1343                 else
 1344                      errors=-4;
 1345 #endif
 1346                 closefilehandle(output);
 1347                 if((filehandle=openreading(filename))==MY_INVALID_HANDLE_VALUE) {
 1348 #ifdef USE_WINFILE
 1349     Memory::errors=GetLastError();
 1350 #else
 1351                     if(errno)
 1352                         errors=errno;
 1353                     else
 1354                         errors=-1;
 1355 #endif
 1356                     }
 1357                 return errors;
 1358                 }
 1359         databuffree( iter->data.buf);
 1360         }
 1361     closefilehandle(output);
 1362     tree.empty();
 1363     if((filehandle=openreading(filename))==MY_INVALID_HANDLE_VALUE) {
 1364 #ifdef USE_WINFILE
 1365     Memory::errors=GetLastError();
 1366 errors=WINERROR;
 1367 #else
 1368         if(errno)
 1369             errors=errno;
 1370         else
 1371             errors=-1;
 1372 #endif
 1373         }
 1374 #ifdef USE_WINFILE
 1375 //  STAT(filename,&statdata);
 1376 getfileinfo(&FileInfo);
 1377 #else
 1378     FSTAT(filehandle,&statdata);
 1379 #endif
 1380 
 1381     useddiskfilesize=diskfilesize=filesize;
 1382     return errors;
 1383     }
 1384 }
 1385 int Memory::zerochange(void) {
 1386     if(filesize!=newfilesize)
 1387         return 1;
 1388     char tmpbuf[newfilesize];
 1389     getpart(0,newfilesize,tmpbuf); /*Niet verbonden aan file, sector grens maakt niet uit*/
 1390     int *ints=(int *) tmpbuf;
 1391     int len=newfilesize*sizeof(char)/sizeof(int);
 1392     for(int i=0;i<len;i++) 
 1393         if(ints[i])
 1394             return 1;
 1395     return 0;
 1396     }
 1397 int Memory::changednode(Treel *node) {
 1398     char *tmpbuf=databufalloc(BLOCKSIZE);
 1399     OFFTYPE diff=filesize-((OFFTYPE)node->data.blocknr*BLOCKSIZE);
 1400 int ret=0;
 1401     if(diff>0) {
 1402         BEDS_SIZE_T size=(diff<BLOCKSIZE)?diff:BLOCKSIZE;
 1403         if(node->data.size<size) {
 1404             fprintf(stderr,"WARNING: changednode/1: not enough in node " BLOCKPRINT" " SIZE_TPRINT ">" SIZE_TPRINT "\n",node->data.blocknr,size,node->data.size);
 1405             size=node->data.size;
 1406             }
 1407         blockreadat(tmpbuf,size,node->data.blocknr*BLOCKSIZE);
 1408         ret= memcmp(tmpbuf, node->data.buf, size);
 1409         }
 1410 databuffree(tmpbuf);
 1411     return ret;
 1412     }
 1413 
 1414 int Memory::changed(void) {
 1415     OFFTYPE disksize;
 1416     if(isnewfile())
 1417         disksize=(OFFTYPE)newfilesize;
 1418     else
 1419         disksize=diskfilesize;
 1420 
 1421 //  DEBUG("diskfilesize=" OFFPRINT " real size=" OFFPRINT " tosavesize=" OFFPRINT "\n",diskfilesize,disksize,filesize);
 1422     if(disksize!=filesize)
 1423         return -1;
 1424     for(Treel *iter=tree.treecontrol->roottree;iter!=tree.NIL;iter=tree.next(iter)) {
 1425         if(changednode(iter)) {
 1426             return -1;
 1427             }
 1428         }
 1429     for(Treel *iter=tree.treecontrol->roottree;iter!=tree.NIL;iter=tree.next(iter)) 
 1430         databuffree( iter->data.buf);
 1431     tree.empty();
 1432     return errors;
 1433     }
 1434 OFFTYPE  Memory::putblocks(const BLOCKTYPE een,char *startbuf,const BLOCKTYPE nr){  
 1435 BLOCKTYPE end=een+nr;
 1436 char *buf=startbuf;
 1437 for(BLOCKTYPE iter=een;iter<end;iter++) {
 1438     BEDS_SIZE_T ret=putblock(iter,buf);
 1439     buf+=ret;
 1440     if(ret<BLOCKSIZE) {
 1441         if(ret<0)
 1442              return OFFTYPEINVALID;
 1443         else
 1444             break;
 1445         }
 1446     }
 1447 return buf-startbuf;
 1448 }
 1449 
 1450 OFFTYPE  Memory::getblocks(const BLOCKTYPE een,char *startbuf,const BLOCKTYPE nr){  
 1451 BLOCKTYPE end=een+nr;
 1452 char *buf=startbuf;
 1453 for(BLOCKTYPE iter=een;iter<end;iter++) {
 1454     BEDS_SIZE_T ret=getblock(iter,buf);
 1455     buf+=ret;
 1456     if(ret<BLOCKSIZE) {
 1457         if(ret<0)
 1458              return OFFTYPEINVALID;
 1459         else
 1460             break;
 1461         }
 1462     }
 1463 return buf-startbuf;
 1464 }
 1465 
 1466 #if  defined(USE_WINFILE) ||(defined(HAVE_SENDFILE) && defined(SEEK_DATA))
 1467 extern int nonsparsecp(FILEHANDLE inhandle,OFFTYPE instart,OFFTYPE inlen,FILEHANDLE uit) ;
 1468 //extern int sparsecp(FILEHANDLE inhandle,FILEHANDLE uit);
 1469 extern int sparsecp(int inhandle,OFFTYPE instart,OFFTYPE inlen,int uit) ;
 1470 int Memory::saveto(FILEHANDLE handle) {
 1471     if(useddiskfilesize<filesize) {
 1472         mksparse(handle);
 1473         if(FTRUNCATEHANDLE(handle,filesize)!=0)
 1474             perror("ftruncate");
 1475         }
 1476     
 1477     if(int res;filehandle!=MY_INVALID_HANDLE_VALUE&&(res=sparsecp(filehandle,0,useddiskfilesize,handle))!=0) {
 1478         if(res!=-1) 
 1479             return -1;
 1480 #ifndef USE_WINFILE
 1481         lseek(handle,0, SEEK_SET);
 1482 #endif
 1483         if(nonsparsecp(filehandle,0,useddiskfilesize,handle)<0) {
 1484         /*  lseek(handle,0, SEEK_SET);
 1485             return nonsparsesaveto(handle);*/
 1486             return -2;
 1487             }
 1488         }
 1489     for(Treel *iter=tree.treecontrol->roottree;iter!=tree.NIL;iter=tree.next(iter)) {
 1490         if(savenode(handle,iter)<0) {
 1491                 return -3;
 1492                 }
 1493         }
 1494     return 0;
 1495     }
 1496 int Memory::nonsparsesaveto(FILEHANDLE handle) {
 1497 #else
 1498 int Memory::saveto(FILEHANDLE handle) {
 1499 #endif
 1500     if(useddiskfilesize<filesize) {
 1501         mksparse(handle);
 1502         if(FTRUNCATEHANDLE(handle,filesize)!=0)
 1503             perror("ftruncate");
 1504         }
 1505     char *buf=databufalloc(BLOCKSIZE);
 1506     BLOCKTYPE nr;
 1507     BEDS_SIZE_T did, ret=0;
 1508     BLOCKTYPE endblock=(useddiskfilesize+BLOCKSIZE-1)/BLOCKSIZE;
 1509     for(nr=0;nr<endblock;nr++) {
 1510             did=getblock(nr, buf);
 1511             ret=writetofile(handle,buf,did);
 1512             if(ret!=did) {
 1513                 databuffree(buf);
 1514                 return -1;
 1515                 }
 1516             }
 1517     databuffree(buf);
 1518     if(diskfilesize>=filesize) {
 1519         if((maxnum((OFFTYPE)(nr-1)*BLOCKSIZE,0)+ret)!=filesize) return -1;
 1520         return 0;
 1521         }
 1522     for(Treel *iter=tree.treecontrol->roottree;iter!=tree.NIL;iter=tree.next(iter)) {
 1523         BLOCKTYPE bl=iter->data.blocknr;
 1524         if(bl>=endblock) {
 1525             OFFTYPE offset=bl*BLOCKSIZE;
 1526             int len=((offset+BLOCKSIZE)>filesize) ?(filesize-offset): iter->data.size;
 1527             writeat(handle,iter->data.buf,len,offset);
 1528             }
 1529         }
 1530         /*
 1531     for(OFFTYPE offset=nr*BLOCKSIZE;offset<filesize;nr++,offset+=BLOCKSIZE) {
 1532         Treel *el=tree.search(nr);
 1533         if(el!=tree.NIL) {
 1534             int len=((offset+BLOCKSIZE)>filesize) ?(filesize-offset): el->data.size;
 1535             writeat(handle,el->data.buf,len,offset);
 1536             }
 1537         } */
 1538 //  if((maxnum((OFFTYPE)(nr-1)*BLOCKSIZE,0)+ret)!=filesize) return -1;
 1539     return 0;
 1540     }
 1541 BEDS_SIZE_T Memory::getblockpiece(OFFTYPE beg,BEDS_SIZE_T len,char *get) {
 1542     BLOCKTYPE onder=beg/BLOCKSIZE;
 1543     BEDS_SIZE_T ret;
 1544     BEDS_SIZE_T in=beg%BLOCKSIZE;
 1545     Treel *el=tree.search(onder);
 1546     if(el!=tree.NIL) {
 1547         ret=minnum(el->data.size,len);
 1548         memmove(get,el->data.buf+in,ret);
 1549         }
 1550     else {
 1551         ret=readat(get,len,beg);
 1552         }
 1553     return ret;
 1554     }
 1555 
 1556 #ifdef _WIN32
 1557 OFFTYPE Memory::getpartaligned(const OFFTYPE beg,const OFFTYPE len,char *const gegs) {
 1558 BLOCKTYPE start;
 1559 BEDS_SIZE_T begover=beg%BLOCKSIZE;
 1560 int blks=(len+begover-1)/BLOCKSIZE+1;   
 1561 char *tmpbuf= (char *)alignedalloc(BLOCKSIZE, blks*BLOCKSIZE);
 1562 start=(beg/BLOCKSIZE);
 1563 BLOCKTYPE end=start+blks;
 1564 char *ptr=tmpbuf;
 1565 for(BLOCKTYPE nr=start;nr<end;nr++,ptr+=BLOCKSIZE) 
 1566     getblock(nr, ptr);
 1567 memcpy(gegs,tmpbuf+begover,len);
 1568 alignedfree(tmpbuf);
 1569 return len;
 1570 }
 1571 #endif
 1572 OFFTYPE Memory::getpart(OFFTYPE beg,OFFTYPE len,char *gegs) {
 1573     if(beg>=filesize) {
 1574         if(beg==filesize&&!len)
 1575             return 0;
 1576         else
 1577             return OFFTYPEINVALID;
 1578         }
 1579 #if defined(_WIN32) 
 1580 #ifdef NDEBUG
 1581     if(blockreadonly>1) 
 1582 #endif
 1583         return getpartaligned(beg, len,gegs) ;
 1584 #endif
 1585 
 1586     BLOCKTYPE start,bl;
 1587     BEDS_SIZE_T over; 
 1588     OFFTYPE full,end=minnum(beg+len,filesize);
 1589     len=end-beg;
 1590     over=(BLOCKSIZE-(beg%BLOCKSIZE));
 1591     over=minnum(len,over);
 1592 
 1593     if(getblockpiece(beg,over,gegs)!=over)
 1594         return OFFTYPEINVALID;
 1595 
 1596 
 1597     full=len-over;
 1598     if(full>0) {
 1599         char *ptr;
 1600         BEDS_SIZE_T nog; 
 1601         start=(beg/BLOCKSIZE)+1;
 1602         bl=full/BLOCKSIZE+start;
 1603         nog=full%BLOCKSIZE;
 1604         ptr=gegs+over;
 1605         for(BLOCKTYPE nr=start;nr<bl;nr++,ptr+=BLOCKSIZE) {
 1606             if((BLOCKSIZE!=getblock(nr, ptr)))
 1607                 return OFFTYPEINVALID;
 1608             }
 1609         if(getblockpiece(end-nog,nog,ptr)!=nog)
 1610             return OFFTYPEINVALID;
 1611         }
 1612     return len;
 1613     }
 1614 
 1615 OFFTYPE Memory::putpart(OFFTYPE beg,OFFTYPE aanlen,char *gegs) {
 1616     if(beg>=filesize) {
 1617         if(beg==filesize&&!aanlen)
 1618             return 0;
 1619         else
 1620             return OFFTYPEINVALID;
 1621         }
 1622     OFFTYPE len=aanlen;
 1623     BLOCKTYPE start,bl;
 1624     BEDS_SIZE_T over;
 1625     OFFTYPE end=minnum(beg+len,filesize),full;
 1626     len=end-beg;
 1627     over=(BLOCKSIZE-(beg%BLOCKSIZE));
 1628     over=minnum(len,over);
 1629     if(over)
 1630         if(putblockpiece(beg,over,gegs)!=over)
 1631             return OFFTYPEINVALID;
 1632 
 1633 
 1634     full=len-over;
 1635     if(full>0) {
 1636         char *ptr;
 1637         BEDS_SIZE_T nog;
 1638         start=(beg/BLOCKSIZE)+1;
 1639         bl=full/BLOCKSIZE+start;
 1640         nog=full%BLOCKSIZE;
 1641         ptr=gegs+over;
 1642         for(BLOCKTYPE nr=start;nr<bl;nr++,ptr+=BLOCKSIZE) {
 1643             if((BLOCKSIZE!=putblock(nr, ptr)))
 1644                 return OFFTYPEINVALID;
 1645             }
 1646         if(putblockpiece(end-nog,nog,ptr)!=nog)
 1647             return OFFTYPEINVALID;
 1648         }
 1649     return len;
 1650     }
 1651 
 1652 
 1653 #if  defined(USE_WINFILE) ||(defined(HAVE_SENDFILE) && defined(SEEK_DATA))
 1654 BEDS_SIZE_T Memory::saveto(FILEHANDLE handle,OFFTYPE beg,OFFTYPE len) {
 1655     mksparse(handle);
 1656     if(FTRUNCATEHANDLE(handle,len)!=0) {
 1657         perror("ftruncate");
 1658         }
 1659     if(filehandle!=MY_INVALID_HANDLE_VALUE) {
 1660         OFFTYPE left=useddiskfilesize-beg;
 1661         OFFTYPE disklen=minnum(left,len);
 1662         if(int res=sparsecp(filehandle,beg,disklen,handle);res!=0) {
 1663             if(res!=-1)
 1664                 return -1;
 1665         #ifndef USE_WINFILE
 1666             lseek(handle,0, SEEK_SET);
 1667         #endif
 1668             if(nonsparsecp(filehandle,beg,disklen,handle)<0) {
 1669                 /*  lseek(handle,0, SEEK_SET);
 1670                     return nonsparsesaveto(handle,beg, len) ; */
 1671                     return -2;
 1672                     }
 1673             }
 1674         }
 1675     OFFTYPE end=beg+len;
 1676     OFFTYPE startblock=beg/BLOCKSIZE;
 1677     OFFTYPE endblock=(end+BLOCKSIZE-1)/BLOCKSIZE;
 1678     for(Treel *node=tree.treecontrol->roottree;node!=tree.NIL;node=tree.next(node)) {
 1679         auto blnr=node->data.blocknr;
 1680         if(blnr>=startblock&&blnr<endblock) {
 1681             OFFTYPE off=blnr*BLOCKSIZE;
 1682             OFFTYPE diff=end-off;
 1683             if(diff>0) {
 1684                 int bufoff=0;
 1685                 if(off<beg) {
 1686                     bufoff=beg-off;
 1687                     off=beg;
 1688                     }
 1689                 BEDS_SIZE_T size=(diff<BLOCKSIZE)?diff:BLOCKSIZE;
 1690                 writeat(handle,node->data.buf+bufoff,size-bufoff,off-beg);
 1691                 }
 1692             }
 1693         }
 1694     return 0;
 1695     }
 1696 BEDS_SIZE_T Memory::nonsparsesaveto(FILEHANDLE handle,OFFTYPE beg,OFFTYPE len) {
 1697 #else
 1698 BEDS_SIZE_T Memory::saveto(FILEHANDLE handle,OFFTYPE beg,OFFTYPE len) {
 1699 #endif
 1700     if(beg>=filesize) {
 1701         if(beg==filesize&&!len)
 1702             return 0;
 1703         else
 1704             return -1;
 1705         }
 1706     OFFTYPE full;
 1707     BEDS_SIZE_T over;
 1708 //  char buf[BLOCKSIZE];
 1709     sectorbuf buf(BLOCKSIZE, BLOCKSIZE);
 1710 //  OFFTYPE end=beg+len;
 1711     int inblock=(beg%BLOCKSIZE);
 1712     over=(BLOCKSIZE-inblock);
 1713     over=minnum(len,over);
 1714     BLOCKTYPE start=(beg/BLOCKSIZE);
 1715     if(over) {
 1716         getblock(start, buf.data());
 1717         if(writetofile(handle,buf.data()+inblock,over)!=over)
 1718             return -1;
 1719         }
 1720     start++;
 1721 
 1722     full=len-over;
 1723     if(full) {
 1724         BEDS_SIZE_T nog;
 1725         BLOCKTYPE bl=full/BLOCKSIZE+start,nr;
 1726         nog=full%BLOCKSIZE;
 1727         for(nr=start;nr<bl;nr++) {
 1728             if((BLOCKSIZE!=getblock(nr, buf.data())))
 1729                 return -1;
 1730             BEDS_SIZE_T ret=writetofile(handle,buf.data(),BLOCKSIZE);
 1731             if(ret!=BLOCKSIZE) {
 1732                 return -1;
 1733                 }
 1734             }
 1735         if(nog) {
 1736             getblock(nr, buf.data());
 1737             if(writetofile(handle,buf.data(),nog)!=nog)
 1738                 return -1;
 1739             }
 1740         }
 1741     return 0;
 1742     }
 1743 Treel *Memory::gettreel(BLOCKTYPE blockiter) {
 1744         Treel *el=tree.search(blockiter);
 1745         if(el==tree.NIL) {
 1746             char *gegs=databufalloc(BLOCKSIZE);
 1747             tree.insert((Data){blockiter,gegs,0});
 1748             el=tree.search(blockiter);
 1749             }
 1750         return el;
 1751         }
 1752 #ifdef USE_WINFILE
 1753 
 1754 #ifdef USE_PREAD
 1755 
 1756 static inline BEDS_SIZE_T mypread64(FILEHANDLE input,char *buf,BEDS_SIZE_T nr,OFFTYPE offset) {
 1757 
 1758 DWORD did;
 1759 OVERLAPPED overlap;
 1760 memset(&overlap,'\0',sizeof(overlap));
 1761 overlap.Offset = ((unsigned long long)offset)&0xFFFFFFFF;
 1762 overlap.OffsetHigh = ((unsigned long long)offset)>>32;
 1763 DEBUGGING(OFFPRINT " " SIZE_TPRINT " %llx-%llx\n",offset,nr,(unsigned long long)buf,(unsigned long long)buf+nr);
 1764 if(!ReadFile(
 1765     input,  // handle of file to write to 
 1766     buf,    // address of data to write to file 
 1767     nr, // number of bytes to write 
 1768     &did,   // address of number of bytes written 
 1769     &overlap    // addr. of structure needed for overlapped I/O  
 1770    )) {
 1771 #ifndef NDEBUG
 1772      DWORD dwerror = GetLastError();
 1773     char errorbuf[150];
 1774     winerror(errorbuf,150,dwerror);
 1775     fprintf(stderr,"ReadFile " OFFPRINT "," SIZE_TPRINT ": %s\n",offset,nr,errorbuf);
 1776 #endif
 1777     return -1;
 1778     }
 1779 return did;
 1780 }
 1781 
 1782 
 1783 BEDS_SIZE_T mypwrite64(FILEHANDLE outputhandle,const char *buf,BEDS_SIZE_T nr,OFFTYPE offset) {
 1784 DWORD did;
 1785 OVERLAPPED overlap;
 1786 memset(&overlap,'\0',sizeof(overlap));
 1787 overlap.Offset = ((unsigned long long)offset)&0xFFFFFFFF;
 1788 overlap.OffsetHigh = ((unsigned long long)offset)>>32;
 1789 
 1790 if(!WriteFile(
 1791     outputhandle,   // handle of file to write to 
 1792     buf,    // address of data to write to file 
 1793     nr, // number of bytes to write 
 1794     &did,   // address of number of bytes written 
 1795     &overlap    // addr. of structure needed for overlapped I/O  
 1796    ))
 1797     return -1;
 1798 else 
 1799     return did;
 1800 }
 1801 #endif
 1802 #endif
 1803 BEDS_SIZE_T readfromfile(FILEHANDLE input,char *buf,BEDS_SIZE_T nr) {
 1804 #ifdef USE_WINFILE
 1805 DWORD did;
 1806 if(!ReadFile(
 1807 
 1808     input,  // handle of file to write to 
 1809     buf,    // address of data to write to file 
 1810     nr, // number of bytes to write 
 1811     &did,   // address of number of bytes written 
 1812     NULL    // addr. of structure needed for overlapped I/O  
 1813    ))
 1814     return -1;
 1815 else 
 1816     return did;
 1817 #else
 1818 return LREAD(input,buf,nr);
 1819 #endif
 1820 }
 1821 BEDS_SIZE_T writetofile(FILEHANDLE output,const char *buf,BEDS_SIZE_T nr) {
 1822 #ifdef USE_WINFILE
 1823 DWORD did;
 1824 if(!WriteFile(
 1825 
 1826     output, // handle of file to write to 
 1827     buf,    // address of data to write to file 
 1828     nr, // number of bytes to write 
 1829     &did,   // address of number of bytes written 
 1830     NULL    // addr. of structure needed for overlapped I/O  
 1831    ))
 1832     return -1;
 1833 else 
 1834     return did;
 1835 #else
 1836 return LWRITE(output,buf,nr);
 1837 #endif
 1838 }
 1839 
 1840 #ifdef USE_PREAD
 1841 #define USE_PWRITE 1
 1842 #endif
 1843 
 1844 BEDS_SIZE_T Memory::writeat(FILEHANDLE output,char *ptr,BEDS_SIZE_T size,OFFTYPE offset) {
 1845 
 1846 #ifdef NEEDS_BLOCKMODE
 1847     assert(((blockreadonly>1)?(((intptr_t)ptr)%BLOCKSIZE==0):true));
 1848 #endif
 1849 #ifdef BIOSDISK
 1850     if(infodisk)    {
 1851         BEDS_SIZE_T count=size/blockreadonly;
 1852         if(count<=0) {
 1853           fprintf(stderr,"Memory::writeat " SIZE_TPRINT " is not a multiple of %d ( disk blocksize)\n",size,blockreadonly);
 1854         return -5;
 1855             }
 1856         if(diskwrite(infodisk, ptr,size/blockreadonly,offset/blockreadonly)) {
 1857             return size;
 1858             }
 1859         return -4;
 1860         }
 1861     else    
 1862 #endif
 1863 {
 1864 #ifdef USE_PWRITE
 1865     BEDS_SIZE_T ret;
 1866     ret=LPWRITE(output,ptr,size,offset);
 1867     if(ret!=size) {
 1868         fprintf(stderr,"write failed " SIZE_TPRINT "!=" SIZE_TPRINT "\n",ret,size);
 1869         return -2;
 1870         }
 1871     return ret;
 1872 #else
 1873     STARTUSELSEEK;
 1874     OFFTYPE isof=setfilepos(output,offset);
 1875     BEDS_SIZE_T ret;
 1876     if(isof!=offset) {
 1877         fprintf(stderr,"writeat: lseek failed " OFFPRINT "!=" OFFPRINT "\n",isof,offset);
 1878         STOPUSELSEEK;
 1879         return -1;
 1880         }
 1881     ret=writetofile(output,ptr,size);
 1882     if(ret!=size) {
 1883         fprintf(stderr,"write failed " SIZE_TPRINT "!=" SIZE_TPRINT "\n",ret,size);
 1884         STOPUSELSEEK;
 1885         return -2;
 1886         }
 1887     STOPUSELSEEK;
 1888     return ret;
 1889 #endif
 1890  }
 1891     }
 1892 BEDS_SIZE_T Memory::blockreadat(char *ptr,BEDS_SIZE_T size,OFFTYPE offset) {
 1893 
 1894 if(offset>=useddiskfilesize) {
 1895 #ifdef HAVE_BZERO
 1896     bzero(ptr,size);
 1897 #else
 1898     memset(ptr,'\0',size);
 1899 #endif
 1900     return size;
 1901     }
 1902 return realblockreadat(ptr,size,offset);
 1903 }
 1904 BEDS_SIZE_T Memory::realblockreadat(char *ptr,BEDS_SIZE_T size,OFFTYPE offset) {
 1905 
 1906 #ifdef NEEDS_BLOCKMODE
 1907     assert(((blockreadonly>1)?(((intptr_t)ptr)%BLOCKSIZE==0):true));
 1908 #endif
 1909         BEDS_SIZE_T ret;
 1910 #ifdef BIOSDISK
 1911     if(infodisk)    {
 1912         BEDS_SIZE_T count=size/blockreadonly;
 1913         if(count<=0) {
 1914           fprintf(stderr,"Memory::blockreadat " SIZE_TPRINT " is not a multiple of %d ( disk blocksize)\n",size,blockreadonly);
 1915                         return -5; 
 1916             }
 1917         if(diskread(infodisk, ptr,count,offset/blockreadonly)) {
 1918             return size;
 1919             }
 1920         return -4;
 1921         }
 1922     else    
 1923 #endif
 1924 {
 1925 #ifdef USE_PREAD
 1926         ret=LPREAD(filehandle,ptr,size,offset);
 1927 /*
 1928         if(ret!=size) {
 1929 //          fprintf(stderr,"readat failed " SIZE_TPRINT  "!=" SIZE_TPRINT "\n",ret,size);
 1930             return -2;
 1931             }
 1932 */
 1933         return ret;
 1934 #else
 1935         STARTUSELSEEK;
 1936         OFFTYPE isof=setfilepos(filehandle,offset);
 1937         if(isof!=offset) {
 1938 //          fprintf(stderr,"readat: lseek failed " OFFPRINT "!=" OFFPRINT "\n",isof,offset);
 1939             STOPUSELSEEK;
 1940             return -1;
 1941             }
 1942         ret= readfromfile(filehandle,ptr,size);
 1943 /*
 1944         if(ret!=size) {
 1945 //          fprintf(stderr,"readat failed " SIZE_TPRINT  "!=" SIZE_TPRINT "\n",ret,size);
 1946             STOPUSELSEEK;
 1947             return -2;
 1948             }
 1949 */
 1950         STOPUSELSEEK;
 1951         return ret;
 1952 #endif
 1953 }
 1954 }
 1955 
 1956 #ifdef NEEDS_BLOCKMODE
 1957 inline BEDS_SIZE_T Memory::readat(char *ptr,BEDS_SIZE_T size,OFFTYPE offset) {
 1958     if(blockreadonly>1) {
 1959         OFFTYPE offunder=(offset/blockreadonly)*blockreadonly;
 1960         BEDS_SIZE_T extra=offset-offunder;
 1961         BEDS_SIZE_T blen=(((size+extra)+blockreadonly-1)/blockreadonly)*blockreadonly;
 1962 if(!extra&&blen==size)
 1963     goto DIRECT;
 1964 char *buf=databufalloc(blen);
 1965 fprintf(stderr,"readat: %llx-%llx ",(unsigned long long)buf,(unsigned long long) buf+blen);
 1966         if(blockreadat(buf,blen,offunder)<(size+extra))
 1967                 return -1;
 1968         memcpy(ptr,buf+extra,size);
 1969         databuffree(buf);
 1970         return size;        
 1971         }
 1972     else {
 1973 DIRECT:
 1974         return blockreadat( ptr,size,offset);
 1975         }
 1976     }
 1977 #else
 1978 inline BEDS_SIZE_T Memory::readat(char *ptr,BEDS_SIZE_T size,OFFTYPE offset) {
 1979         return blockreadat( ptr,size,offset);
 1980     }
 1981 #endif
 1982 BEDS_SIZE_T Memory::getblock(BLOCKTYPE blocknr,char *buf) {
 1983 
 1984     OFFTYPE offset=(blocknr*BLOCKSIZE);
 1985     if(offset>=filesize)
 1986         return 0;
 1987     Treel *el=tree.search(blocknr);
 1988     if(el!=tree.NIL) {
 1989         memmove(buf,el->data.buf,el->data.size);
 1990         return minnum(filesize-offset,el->data.size);
 1991         }
 1992     else {
 1993         int len=minnum(filesize-offset,BLOCKSIZE);
 1994         return blockreadat(buf,len,offset);
 1995         }
 1996     }
 1997 
 1998 BEDS_SIZE_T Memory::putblock(BLOCKTYPE blocknr,char *buf) {
 1999     OFFTYPE offset=(blocknr*BLOCKSIZE);
 2000     if(offset>=filesize)
 2001         return 0;
 2002     BEDS_SIZE_T thissize=minnum(filesize-offset,BLOCKSIZE);
 2003     Treel *el=gettreel(blocknr);
 2004     memmove(el->data.buf,buf,thissize);
 2005     el->data.size=thissize;
 2006     return thissize;
 2007     }
 2008 
 2009 void    Memory::setborder(OFFTYPE pos) {
 2010     BLOCKTYPE under=pos/BLOCKSIZE;
 2011     Treel *el=tree.search(under);
 2012     if(el==tree.NIL)
 2013         return;
 2014     OFFTYPE offset=under*BLOCKSIZE;
 2015     el->data.size=minnum(filesize-offset,BLOCKSIZE);
 2016     }
 2017 void Memory::extend(OFFTYPE newsize) {
 2018     OFFTYPE oldsize=filesize;
 2019     BLOCKTYPE under=oldsize/BLOCKSIZE;
 2020     Treel *el=tree.search(under);
 2021     if(el==tree.NIL) {
 2022         char buf[BLOCKSIZE]; /*Alignment doesn't matter, you can't extend \\.\PhysicalDriveX */
 2023         OFFTYPE begin=under*BLOCKSIZE,sizebuf=filesize-begin;
 2024         blockreadat(buf,sizebuf,begin);
 2025         putpart(begin,sizebuf,buf) ;
 2026         el=tree.search(under);
 2027         }
 2028 /*  else {
 2029         long begin=(oldsize%BLOCKSIZE);
 2030         memset(el->data.buf+begin,'\0',BLOCKSIZE-begin);
 2031         } */
 2032     filesize=newsize;
 2033     OFFTYPE offset=under*BLOCKSIZE;
 2034     el->data.size=minnum(filesize-offset,BLOCKSIZE);
 2035     return;
 2036     }
 2037 
 2038 void Memory::undotruncate(OFFTYPE newsize,OFFTYPE useddisk) {
 2039 //void Memory::undotruncate(OFFTYPE newsize) {
 2040 /*  OFFTYPE wassize=filesize;
 2041     BLOCKTYPE  bl=filesize/BLOCKSIZE;
 2042     char buf[BLOCKSIZE];
 2043     getblock(bl,buf); */
 2044     extend(newsize) ;
 2045     /*
 2046     if(newsize<=diskfilesize) {
 2047         useddiskfilesize=newsize;
 2048         }
 2049     else {
 2050         fprintf(stderr,"Undo truncate to larger file " OFFPRINT " > " OFFPRINT "\n",newsize,diskfilesize);
 2051         }
 2052         */
 2053     }
 2054 void Memory::truncatefile(OFFTYPE pos) {            /* v2 */
 2055     Treel *el=tree.search(filesize);
 2056     if(el!=tree.NIL) {      /* CAUTION old data is not removed. No problem: extending goes always with putpart? (extend, undo, saveall?) */
 2057 
 2058         el->data.size=BLOCKSIZE;
 2059         }
 2060     filesize=pos;
 2061     useddiskfilesize=minnum(useddiskfilesize,filesize);
 2062     setborder(pos);
 2063     }
 2064 BEDS_SIZE_T Memory::putblockpiece(OFFTYPE  beg,BEDS_SIZE_T len,char *get) {
 2065      BLOCKTYPE onder=beg/BLOCKSIZE;
 2066     BEDS_SIZE_T ret;
 2067      OFFTYPE bstart=onder*BLOCKSIZE;
 2068     BEDS_SIZE_T in=beg%BLOCKSIZE;
 2069     Treel *el=tree.search(onder);
 2070     BEDS_SIZE_T thissize=minnum(filesize-bstart,BLOCKSIZE);
 2071     if(el!=tree.NIL) {
 2072         if(el->data.size<thissize) {
 2073             fprintf(stderr,"putblockpiece " SIZE_TPRINT " (intree)!=" SIZE_TPRINT " (should)\n",el->data.size,thissize);
 2074             char *gegs=databufalloc(BLOCKSIZE);
 2075             char *old; 
 2076             ret=blockreadat(gegs,thissize,bstart);
 2077             if(ret!=thissize) {
 2078                 fprintf(stderr,"putblockpiece " SIZE_TPRINT "(read)!=" SIZE_TPRINT "(should)\n",ret,thissize);
 2079                 }
 2080             memmove(gegs,el->data.buf,ret);
 2081             old=el->data.buf;
 2082             el->data.buf=gegs;
 2083             databuffree( old);
 2084             el->data.size=ret;
 2085             }
 2086         memmove(el->data.buf+in,get,len);
 2087         }
 2088     else {
 2089         char *gegs=databufalloc(BLOCKSIZE); 
 2090         if(in!=0||len!=thissize)
 2091             ret=blockreadat(gegs,thissize,bstart);
 2092         /*
 2093         if(ret!=thissize) {
 2094             fprintf(stderr,"2:putblockpiece %ld(read)!=%ld(should)\n",ret,thissize);
 2095             }*/
 2096         memmove(gegs+in,get,len);
 2097         tree.insert((Data){onder,gegs,thissize});
 2098         }
 2099     return len;
 2100     }
 2101 
 2102 /*
 2103 OFFTYPE Memory::search(OFFTYPE beg, signed char *str,int len) {
 2104 #ifdef DONTINTCURSES 
 2105 DECPDDEST();
 2106 #endif
 2107     OFFTYPE ret= OFFTYPEINVALID;
 2108         switch(lastforward&0x7) {
 2109                                 //forward, icase, norm
 2110         case 3: ret= casesearch(beg,str,len);break;
 2111         case 1: ret= icasesearch(beg,str,len);break;
 2112         case 7:ret= regexsearch(beg,str,len);break;
 2113         case 5: ret= icaseregexsearch(beg,str,len);break;
 2114 
 2115 
 2116 
 2117         case 2: ret= backsearch(beg,str,len);break;
 2118         case 0: ret= backicasesearch(beg,str,len);break;
 2119         case 6: ret= backregexsearch(beg,str,len);break;
 2120         case 4: ret= backicaseregexsearch(beg,str,len);break;
 2121         default: ret= OFFTYPEINVALID;break;
 2122         };
 2123 #ifdef DONTINTCURSES 
 2124 INCPDDEST();
 2125 #endif
 2126     return ret;
 2127     }
 2128 
 2129 */
 2130 
 2131 #ifdef TEST
 2132 //#include "basic.h"
 2133 int main(int argc, char **argv) {
 2134 #define MAXBUF 0xffff
 2135     int pos,len;
 2136     char buf[MAXBUF];
 2137     char command[256]="cat   /tmp/memoryXXXXXX",*hierfile=command+6;
 2138     if(argc!=2) {
 2139         fprintf(stderr,"Gebruik: %s filename\n",argv[0]);
 2140         exit(1);
 2141         }
 2142     Memory mem(argv[1]);
 2143 
 2144     if(mem.error()) {
 2145         fprintf(stderr,"%s: error \n",argv[0]);
 2146         exit(2);
 2147         }
 2148     printf("size=%d\n",mem.size());
 2149     puts("Give filepostition and lenght (pos len)");
 2150     while(gets(buf)) {
 2151         if(buf[0]=='q')
 2152             break;
 2153         if((sscanf(buf,"%d %d",&pos,&len)<2)||len>MAXBUF)
 2154             continue;
 2155         int handle,newlen;
 2156         newlen=mem.getpart(pos,len,buf);
 2157         strcpyn(hierfile+11,"XXXXXX",239);
 2158         if(!(mktemp(hierfile)))
 2159             fatal("tmpnam(/tmp/memory) fails\n");
 2160         puts(hierfile);
 2161         if((handle=creat(hierfile,0600))<0)
 2162             fatal("creat(%s)\n",hierfile);
 2163         write(handle,buf,newlen);
 2164         LCLOSE(handle);
 2165         system(command);
 2166         if((handle=LOPEN(hierfile,O_RDONLY BINARY_FLAG))<0)
 2167             fatal("Can't open %s for readonly\n",hierfile);
 2168         seekread(handle,0L,SEEK_SET,buf,newlen);
 2169         LCLOSE(handle);
 2170         len=mem.putpart(pos,len,buf);
 2171         puts("Give filepostition and lenght (pos len)");
 2172         }
 2173     mem.tree.showtree();
 2174     puts("Save file (j/n)");
 2175     gets(buf);
 2176     if(buf[0]=='j') {
 2177         mem.saveall();
 2178         puts("Saved");
 2179         }
 2180     mem.tree.showtree();
 2181     return 0;
 2182     }
 2183 #endif
 2184 #ifdef TESTMEM
 2185 extern int testmem(void) ;
 2186 int testmem(void) {
 2187 const char *filename="\\\\.\\PhysicalDrive0";
 2188 
 2189     Memory mem(filename);
 2190 
 2191     if(mem.error()) {
 2192         fprintf(stderr,"%s: error \n",filename);
 2193         exit(2);
 2194         }
 2195 OFFTYPE pos=0;
 2196 long blk=512,len=blk;
 2197 char buf[len];
 2198 for(int i=0;i<9;i++,pos+=blk) {
 2199         fprintf(stderr,"t: ");
 2200         int newlen=mem.getpart(pos,len,buf);
 2201 
 2202         }
 2203     return 0;
 2204 }
 2205     
 2206 #endif