home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / isam / _dynrec.c < prev    next >
C/C++ Source or Header  |  2000-11-17  |  34KB  |  1,248 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.  
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17.     /* Functions to handle space-packed-records and blobs */
  18.  
  19. #include "isamdef.h"
  20.  
  21. /* Enough for comparing if number is zero */
  22. static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  23.  
  24. static int write_dynamic_record(N_INFO *info,const byte *record,
  25.                 uint reclength);
  26. static int _nisam_find_writepos(N_INFO *info,uint reclength,ulong *filepos,
  27.                  uint *length);
  28. static int update_dynamic_record(N_INFO *info,ulong filepos,byte *record,
  29.                  uint reclength);
  30. static int delete_dynamic_record(N_INFO *info,ulong filepos,
  31.                  uint second_read);
  32. static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos,
  33.               uint length);
  34.  
  35. #ifdef THREAD
  36. /* Play it safe; We have a small stack when using threads */
  37. #undef my_alloca
  38. #undef my_afree
  39. #define my_alloca(A) my_malloc((A),MYF(0))
  40. #define my_afree(A) my_free((A),MYF(0))
  41. #endif
  42.  
  43.     /* Interface function from N_INFO */
  44.  
  45. int _nisam_write_dynamic_record(N_INFO *info, const byte *record)
  46. {
  47.   uint reclength=_nisam_rec_pack(info,info->rec_buff,record);
  48.   return (write_dynamic_record(info,info->rec_buff,reclength));
  49. }
  50.  
  51. int _nisam_update_dynamic_record(N_INFO *info, ulong pos, const byte *record)
  52. {
  53.   uint length=_nisam_rec_pack(info,info->rec_buff,record);
  54.   return (update_dynamic_record(info,pos,info->rec_buff,length));
  55. }
  56.  
  57. int _nisam_write_blob_record(N_INFO *info, const byte *record)
  58. {
  59.   byte *rec_buff;
  60.   int error;
  61.   uint reclength,extra;
  62.  
  63.   extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
  64.     DYN_DELETE_BLOCK_HEADER;
  65.   if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+
  66.                    _calc_total_blob_length(info,record)+
  67.                    extra)))
  68.     return(-1);
  69.   reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
  70.              record);
  71.   error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
  72.                  reclength);
  73.   my_afree(rec_buff);
  74.   return(error);
  75. }
  76.  
  77.  
  78. int _nisam_update_blob_record(N_INFO *info, ulong pos, const byte *record)
  79. {
  80.   byte *rec_buff;
  81.   int error;
  82.   uint reclength,extra;
  83.  
  84.   extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
  85.     DYN_DELETE_BLOCK_HEADER;
  86.   if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+
  87.                    _calc_total_blob_length(info,record)+
  88.                    extra)))
  89.     return(-1);
  90.   reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
  91.              record);
  92.   error=update_dynamic_record(info,pos,
  93.                   rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
  94.                   reclength);
  95.   my_afree(rec_buff);
  96.   return(error);
  97. }
  98.  
  99. int _nisam_delete_dynamic_record(N_INFO *info)
  100. {
  101.   return delete_dynamic_record(info,info->lastpos,0);
  102. }
  103.  
  104.  
  105.     /* Write record to data-file */
  106.  
  107. static int write_dynamic_record(N_INFO *info, const byte *record,
  108.                 uint reclength)
  109. {
  110.   int flag;
  111.   uint length;
  112.   ulong filepos;
  113.   DBUG_ENTER("write_dynamic_record");
  114.  
  115.   flag=0;
  116.   while (reclength)
  117.   {
  118.     if (_nisam_find_writepos(info,reclength,&filepos,&length))
  119.       goto err;
  120.     if (_nisam_write_part_record(info,filepos,length,info->s->state.dellink,
  121.                   (byte**) &record,&reclength,&flag))
  122.       goto err;
  123.   }
  124.  
  125.   DBUG_RETURN(0);
  126.  err:
  127.   DBUG_RETURN(1);
  128. }
  129.  
  130.  
  131.     /* Get a block for data ; The given data-area must be used !! */
  132.  
  133. static int _nisam_find_writepos(N_INFO *info,
  134.                  uint reclength, /* record length */
  135.                  ulong *filepos, /* Return file pos */
  136.                  uint *length)   /* length of block at filepos */
  137. {
  138.   BLOCK_INFO block_info;
  139.   DBUG_ENTER("_nisam_find_writepos");
  140.  
  141.   if (info->s->state.dellink != NI_POS_ERROR)
  142.   {
  143.     *filepos=info->s->state.dellink;
  144.     block_info.second_read=0;
  145.     info->rec_cache.seek_not_done=1;
  146.  
  147.     if (!(_nisam_get_block_info(&block_info,info->dfile,
  148.                 info->s->state.dellink) & BLOCK_DELETED))
  149.     {
  150.       my_errno=HA_ERR_WRONG_IN_RECORD;
  151.       DBUG_RETURN(-1);
  152.     }
  153.     info->s->state.dellink=block_info.next_filepos;
  154.     info->s->state.del--;
  155.     info->s->state.empty-= block_info.block_len;
  156.     *length= block_info.block_len;
  157.   }
  158.   else
  159.   {
  160.     if (info->s->state.data_file_length > info->s->base.max_data_file_length)
  161.     {
  162.       my_errno=HA_ERR_RECORD_FILE_FULL;
  163.       DBUG_RETURN(-1);
  164.     }
  165.     *filepos=info->s->state.data_file_length;        /* New block last */
  166.     if ((*length=reclength+3 + test(reclength > 65532)) <
  167.     info->s->base.min_block_length)
  168.       *length=info->s->base.min_block_length;
  169.     info->s->state.data_file_length+= *length;
  170.     info->s->state.splitt++;
  171.     info->update|=HA_STATE_WRITE_AT_END;
  172.   }
  173.   DBUG_RETURN(0);
  174. } /* _nisam_find_writepos */
  175.  
  176.  
  177.     /* Write a block to datafile */
  178.  
  179. int _nisam_write_part_record(N_INFO *info,
  180.               ulong filepos,    /* points at empty block */
  181.               uint length,        /* length of block */
  182.               ulong next_filepos,    /* Next empty block */
  183.               byte **record,    /* pointer to record ptr */
  184.               uint *reclength,    /* length of *record */
  185.               int *flag)        /* *flag == 0 if header */
  186. {
  187.   uint head_length,res_length,extra_length,long_block,del_length;
  188.   byte *pos,*record_end;
  189.   uchar temp[N_SPLITT_LENGTH+DYN_DELETE_BLOCK_HEADER];
  190.   DBUG_ENTER("_nisam_write_part_record");
  191.  
  192.   res_length=extra_length=0;
  193.   if (length > *reclength + N_SPLITT_LENGTH)
  194.   {                        /* Splitt big block */
  195.     res_length=length- *reclength - 3 - N_EXTEND_BLOCK_LENGTH;
  196.     length-= res_length;            /* Use this for first part */
  197.   }
  198.   long_block= (length < 65535L && *reclength < 65535L) ? 0 : 1;
  199.   if (length-long_block == *reclength+3 || length == *reclength + 4)
  200.   {                        /* Exact what we need */
  201.     temp[0]=(uchar) (1+ *flag);            /* 1, or 9 */
  202.     if (long_block)
  203.     {
  204.       int3store(temp+1,*reclength);
  205.     }
  206.     else
  207.     {
  208.       int2store(temp+1,*reclength);
  209.     }
  210.     head_length=3+long_block;
  211.     if (length-long_block == *reclength+4)
  212.     {
  213.       length--;
  214.       temp[0]++;                /* 2 or 10 */
  215.       extra_length++;                /* One empty */
  216.     }
  217.   }
  218.   else if (length-long_block*2 < *reclength+5)
  219.   {                        /* To short block */
  220.     if (next_filepos == NI_POS_ERROR)
  221.       next_filepos=info->s->state.dellink != NI_POS_ERROR ?
  222.     info->s->state.dellink : info->s->state.data_file_length;
  223.     if (*flag == 0)                /* First block */
  224.     {
  225.       head_length=5+4+long_block*2;
  226.       temp[0]=4;
  227.       if (long_block)
  228.       {
  229.     int3store(temp+1,*reclength);
  230.     int3store(temp+4,length-head_length);
  231.     int4store((byte*) temp+7,next_filepos);
  232.       }
  233.       else
  234.       {
  235.     int2store(temp+1,*reclength);
  236.     int2store(temp+3,length-head_length);
  237.     int4store((byte*) temp+5,next_filepos);
  238.       }
  239.     }
  240.     else
  241.     {
  242.       head_length=3+4+long_block;
  243.       temp[0]=12;
  244.       if (long_block)
  245.       {
  246.     int3store(temp+1,length-head_length);
  247.     int4store((byte*) temp+4,next_filepos);
  248.       }
  249.       else
  250.       {
  251.     int2store(temp+1,length-head_length);
  252.     int4store((byte*) temp+3,next_filepos);
  253.       }
  254.     }
  255.   }
  256.   else
  257.   {                    /* Block with empty info last */
  258.     head_length=5+long_block*2;
  259.     temp[0]= (uchar) (3+ *flag);    /* 3 or 11 */
  260.     if (long_block)
  261.     {
  262.       int3store(temp+1,*reclength);
  263.       int3store(temp+4,length-7);
  264.     }
  265.     else
  266.     {
  267.       int2store(temp+1,*reclength);
  268.       int2store(temp+3,length-5);
  269.     }
  270.     extra_length= length- *reclength-head_length;
  271.     length=      *reclength+head_length;    /* Write only what is needed */
  272.   }
  273.   temp[0]+=(uchar) (long_block*4);
  274.   DBUG_DUMP("header",(byte*) temp,head_length);
  275.  
  276.     /* Make a long block for one write */
  277.   record_end= *record+length-head_length;
  278.   del_length=(res_length ? DYN_DELETE_BLOCK_HEADER : 0);
  279.   bmove((byte*) (*record-head_length),(byte*) temp,head_length);
  280.   memcpy(temp,record_end,(size_t) (extra_length+del_length));
  281.   bzero((byte*) record_end,extra_length);
  282.   if (res_length)
  283.   {
  284.     pos=record_end+extra_length;
  285.     pos[0]= '\0';
  286.     int3store(pos+1,res_length);
  287.     int4store(pos+4,info->s->state.dellink);
  288.     info->s->state.dellink= filepos+length+extra_length;
  289.     info->s->state.del++;
  290.     info->s->state.empty+=res_length;
  291.     info->s->state.splitt++;
  292.   }
  293.   if (info->opt_flag & WRITE_CACHE_USED && info->update & HA_STATE_WRITE_AT_END)
  294.   {
  295.     if (my_b_write(&info->rec_cache,(byte*) *record-head_length,
  296.            length+extra_length+del_length))
  297.       goto err;
  298.   }
  299.   else
  300.   {
  301.     info->rec_cache.seek_not_done=1;
  302.     if (my_pwrite(info->dfile,(byte*) *record-head_length,length+extra_length+
  303.           del_length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
  304.       goto err;
  305.   }
  306.   memcpy(record_end,temp,(size_t) (extra_length+del_length));
  307.   *record=record_end;
  308.   *reclength-=(length-head_length);
  309.   *flag=8;
  310.  
  311.   DBUG_RETURN(0);
  312. err:
  313.   DBUG_PRINT("exit",("errno: %d",my_errno));
  314.   DBUG_RETURN(1);
  315. } /*_nisam_write_part_record */
  316.  
  317.  
  318.     /* update record from datafile */
  319.  
  320. static int update_dynamic_record(N_INFO *info, ulong filepos, byte *record, uint reclength)
  321. {
  322.   int flag;
  323.   uint error,length;
  324.   BLOCK_INFO block_info;
  325.   DBUG_ENTER("update_dynamic_record");
  326.  
  327.   flag=block_info.second_read=0;
  328.   while (reclength > 0)
  329.   {
  330.     if (filepos != info->s->state.dellink)
  331.     {
  332.       block_info.next_filepos= NI_POS_ERROR;
  333.       if ((error=_nisam_get_block_info(&block_info,info->dfile,filepos))
  334.       & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
  335.          BLOCK_FATAL_ERROR))
  336.       {
  337.     if (!(error & BLOCK_FATAL_ERROR))
  338.       my_errno=HA_ERR_WRONG_IN_RECORD;
  339.     goto err;
  340.       }
  341.       length=(uint) (block_info.filepos-filepos) + block_info.block_len;
  342.     }
  343.     else
  344.     {
  345.       if (_nisam_find_writepos(info,reclength,&filepos,&length))
  346.     goto err;
  347.     }
  348.     if (_nisam_write_part_record(info,filepos,length,block_info.next_filepos,
  349.                   &record,&reclength,&flag))
  350.       goto err;
  351.     if ((filepos=block_info.next_filepos) == NI_POS_ERROR)
  352.       filepos=info->s->state.dellink;
  353.   }
  354.  
  355.   if (block_info.next_filepos != NI_POS_ERROR)
  356.     if (delete_dynamic_record(info,block_info.next_filepos,1))
  357.       goto err;
  358.   DBUG_RETURN(0);
  359. err:
  360.   DBUG_RETURN(1);
  361. }
  362.  
  363.     /* Delete datarecord from database */
  364.     /* info->rec_cache.seek_not_done is updated in cmp_record */
  365.  
  366. static int delete_dynamic_record(N_INFO *info, ulong filepos, uint second_read)
  367. {
  368.   uint length,b_type;
  369.   BLOCK_INFO block_info;
  370.   DBUG_ENTER("delete_dynamic_record");
  371.  
  372.   block_info.second_read=second_read;
  373.   do
  374.   {
  375.     if ((b_type=_nisam_get_block_info(&block_info,info->dfile,filepos))
  376.     & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
  377.        BLOCK_FATAL_ERROR) ||
  378.     (length=(uint) (block_info.filepos-filepos) +block_info.block_len) <
  379.     N_MIN_BLOCK_LENGTH)
  380.     {
  381.       my_errno=HA_ERR_WRONG_IN_RECORD;
  382.       DBUG_RETURN(1);
  383.     }
  384.     block_info.header[0]=0;
  385.     length=(uint) (block_info.filepos-filepos) +block_info.block_len;
  386.     int3store(block_info.header+1,length);
  387.     int4store(block_info.header+4,info->s->state.dellink);
  388.     if (my_pwrite(info->dfile,(byte*) block_info.header,8,filepos,
  389.           MYF(MY_NABP)))
  390.       DBUG_RETURN(1);
  391.     info->s->state.dellink = filepos;
  392.     info->s->state.del++;
  393.     info->s->state.empty+=length;
  394.     filepos=block_info.next_filepos;
  395.   } while (!(b_type & BLOCK_LAST));
  396.   DBUG_RETURN(0);
  397. }
  398.  
  399.  
  400.     /* Pack a record. Return new reclength */
  401.  
  402. uint _nisam_rec_pack(N_INFO *info, register byte *to, register const byte *from)
  403. {
  404.   uint        length,new_length,flag,bit,i;
  405.   char        *pos,*end,*startpos,*packpos;
  406.   enum en_fieldtype type;
  407.   reg3 N_RECINFO *rec;
  408.   N_BLOB    *blob;
  409.   DBUG_ENTER("_nisam_rec_pack");
  410.  
  411.   flag=0 ; bit=1;
  412.   startpos=packpos=to; to+= info->s->base.pack_bits; blob=info->blobs;
  413.   rec=info->s->rec;
  414.  
  415.   for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length)
  416.   {
  417.     length=(uint) rec->base.length;
  418.     if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
  419.     {
  420.       if (type == FIELD_BLOB)
  421.       {
  422.     if (!blob->length)
  423.       flag|=bit;
  424.     else
  425.     {
  426.       char *temp_pos;
  427.       memcpy((byte*) to,from,(size_t) length);
  428.       memcpy_fixed(&temp_pos,from+length,sizeof(char*));
  429.       memcpy(to+length,temp_pos,(size_t) blob->length);
  430.       to+=length+blob->length;
  431.     }
  432.     blob++;
  433.     from+=sizeof(char*);            /* Skipp blob-pointer */
  434.       }
  435.       else if (type == FIELD_SKIPP_ZERO)
  436.       {
  437.     if (memcmp((byte*) from,zero_string,length) == 0)
  438.       flag|=bit;
  439.     else
  440.     {
  441.       memcpy((byte*) to,from,(size_t) length); to+=length;
  442.     }
  443.       }
  444.       else if (type == FIELD_SKIPP_ENDSPACE ||
  445.            type == FIELD_SKIPP_PRESPACE)
  446.       {
  447.     pos= (byte*) from; end= (byte*) from + length;
  448.     if (type == FIELD_SKIPP_ENDSPACE)
  449.     {                    /* Pack trailing spaces */
  450.       while (end > from && *(end-1) == ' ')
  451.         end--;
  452.     }
  453.     else
  454.     {                    /* Pack pref-spaces */
  455.       while (pos < end && *pos == ' ')
  456.         pos++;
  457.     }
  458.     new_length=(uint) (end-pos);
  459.     if (new_length +1 + test(rec->base.length > 255 && new_length > 127)
  460.         < length)
  461.     {
  462.       if (rec->base.length > 255 && new_length > 127)
  463.       {
  464.         to[0]=(char) ((new_length & 127)+128);
  465.         to[1]=(char) (new_length >> 7);
  466.         to+=2;
  467.       }
  468.       else
  469.         *to++= (char) new_length;
  470.       memcpy((byte*) to,pos,(size_t) new_length); to+=new_length;
  471.       flag|=bit;
  472.     }
  473.     else
  474.     {
  475.       memcpy(to,from,(size_t) length); to+=length;
  476.     }
  477.       }
  478.       else if (type == FIELD_ZERO)
  479.     continue;                /* Don't store this */
  480.       else
  481.       {
  482.     memcpy(to,from,(size_t) length); to+=length;
  483.     continue;                /* Normal field */
  484.       }
  485.       if ((bit= bit << 1) >= 256)
  486.       {
  487.     *packpos++ = (char) (uchar) flag;
  488.     bit=1; flag=0;
  489.       }
  490.     }
  491.     else
  492.     {
  493.       memcpy(to,from,(size_t) length); to+=length;
  494.     }
  495.   }
  496.   if (bit != 1)
  497.     *packpos= (char) (uchar) flag;
  498.   DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos)));
  499.   DBUG_RETURN((uint) (to-startpos));
  500. } /* _nisam_rec_pack */
  501.  
  502.  
  503.  
  504. /*
  505. ** Check if a record was correctly packed. Used only by isamchk
  506. ** Returns 0 if record is ok.
  507. */
  508.  
  509. my_bool _nisam_rec_check(N_INFO *info,const char *from)
  510. {
  511.   uint        length,new_length,flag,bit,i;
  512.   char        *pos,*end,*packpos,*to;
  513.   enum en_fieldtype type;
  514.   reg3 N_RECINFO *rec;
  515.   DBUG_ENTER("_nisam_rec_check");
  516.  
  517.   packpos=info->rec_buff; to= info->rec_buff+info->s->base.pack_bits;
  518.   rec=info->s->rec;
  519.   flag= *packpos; bit=1;
  520.  
  521.   for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length)
  522.   {
  523.     length=(uint) rec->base.length;
  524.     if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
  525.     {
  526.       if (type == FIELD_BLOB)
  527.       {
  528.     uint blob_length= _calc_blob_length(length,from);
  529.     if (!blob_length && !(flag & bit))
  530.       goto err;
  531.     if (blob_length)
  532.       to+=length+ blob_length;
  533.     from+=sizeof(char*);
  534.       }
  535.       else if (type == FIELD_SKIPP_ZERO)
  536.       {
  537.     if (memcmp((byte*) from,zero_string,length) == 0)
  538.     {
  539.       if (!(flag & bit))
  540.         goto err;
  541.     }
  542.     else
  543.       to+=length;
  544.       }
  545.       else if (type == FIELD_SKIPP_ENDSPACE ||
  546.            type == FIELD_SKIPP_PRESPACE)
  547.       {
  548.     pos= (byte*) from; end= (byte*) from + length;
  549.     if (type == FIELD_SKIPP_ENDSPACE)
  550.     {                    /* Pack trailing spaces */
  551.       while (end > from && *(end-1) == ' ')
  552.         end--;
  553.     }
  554.     else
  555.     {                    /* Pack pre-spaces */
  556.       while (pos < end && *pos == ' ')
  557.         pos++;
  558.     }
  559.     new_length=(uint) (end-pos);
  560.     if (new_length +1 + test(rec->base.length > 255 && new_length > 127)
  561.         < length)
  562.     {
  563.       if (!(flag & bit))
  564.         goto err;
  565.       if (rec->base.length > 255 && new_length > 127)
  566.       {
  567.         if (to[0] != (char) ((new_length & 127)+128) ||
  568.         to[1] != (char) (new_length >> 7))
  569.           goto err;
  570.         to+=2;
  571.       }
  572.       else if (*to++ != (char) new_length)
  573.         goto err;
  574.       to+=new_length;
  575.     }
  576.     else
  577.       to+=length;
  578.       }
  579.       else
  580.       {
  581.     if (type != FIELD_ZERO)
  582.       to+=length;                /* Not packed field */
  583.     continue;
  584.       }
  585.       if ((bit= bit << 1) >= 256)
  586.       {
  587.     flag= *++packpos;
  588.     bit=1;
  589.       }
  590.     }
  591.     else
  592.     {
  593.       to+=length;
  594.     }
  595.   }
  596.   if (bit != 1)
  597.     *packpos= (char) (uchar) flag;
  598.   if (info->packed_length == (uint) (to - info->rec_buff) &&
  599.       (bit == 1 || !(flag & ~(bit - 1))))
  600.     DBUG_RETURN(0);
  601.  
  602.  err:
  603.   DBUG_RETURN(1);
  604. }
  605.  
  606.  
  607.  
  608.     /* Unpacks a record */
  609.     /* Returns -1 and my_errno =HA_ERR_RECORD_DELETED if reclength isn't */
  610.     /* right. Returns reclength (>0) if ok */
  611.  
  612. uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from,
  613.             uint found_length)
  614. {
  615.   uint flag,bit,length,rec_length,min_pack_length;
  616.   enum en_fieldtype type;
  617.   byte *from_end,*to_end,*packpos;
  618.   reg3 N_RECINFO *rec,*end_field;
  619.   DBUG_ENTER("_nisam_rec_unpack");
  620.  
  621.   to_end=to + info->s->base.reclength;
  622.   from_end=from+found_length;
  623.   flag= (uchar) *from; bit=1; packpos=from;
  624.   if (found_length < info->s->base.min_pack_length)
  625.     goto err;
  626.   from+= info->s->base.pack_bits;
  627.   min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits;
  628.  
  629.   for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
  630.        rec < end_field ; to+= rec_length, rec++)
  631.   {
  632.     rec_length=rec->base.length;
  633.     if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
  634.     {
  635.       if (type == FIELD_ZERO)
  636.     continue;                /* Skipp this */
  637.       if (flag & bit)
  638.       {
  639.     if (type == FIELD_BLOB)
  640.     {
  641.       bzero((byte*) to,rec_length+sizeof(char*));
  642.       to+=sizeof(char*);
  643.     }
  644.     else if (type == FIELD_SKIPP_ZERO)
  645.       bzero((byte*) to,rec_length);
  646.     else if (type == FIELD_SKIPP_ENDSPACE ||
  647.          type == FIELD_SKIPP_PRESPACE)
  648.     {
  649.       if (rec->base.length > 255 && *from & 128)
  650.       {
  651.         if (from + 1 >= from_end)
  652.           goto err;
  653.         length= (*from & 127)+ ((uint) (uchar) *(from+1) << 7); from+=2;
  654.       }
  655.       else
  656.       {
  657.         if (from == from_end)
  658.           goto err;
  659.         length= (uchar) *from++;
  660.       }
  661.       min_pack_length--;
  662.       if (length >= rec_length ||
  663.           min_pack_length + length > (uint) (from_end - from))
  664.         goto err;
  665.       if (type == FIELD_SKIPP_ENDSPACE)
  666.       {
  667.         memcpy(to,(byte*) from,(size_t) length);
  668.         bfill((byte*) to+length,rec_length-length,' ');
  669.       }
  670.       else
  671.       {
  672.         bfill((byte*) to,rec_length-length,' ');
  673.         memcpy(to+rec_length-length,(byte*) from,(size_t) length);
  674.       }
  675.       from+=length;
  676.     }
  677.       }
  678.       else if (type == FIELD_BLOB)
  679.       {
  680.     ulong blob_length=_calc_blob_length(rec_length,from);
  681.     if ((ulong) (from_end-from) - rec_length < blob_length ||
  682.         min_pack_length > (uint) (from_end -(from+rec_length+blob_length)))
  683.       goto err;
  684.     memcpy((byte*) to,(byte*) from,(size_t) rec_length);
  685.     from+=rec_length;
  686.     /* memcpy crasches alpha egcs 1.1.2 */
  687.     bmove((byte*) to+rec_length,(byte*) &from,sizeof(char*));
  688.     from+=blob_length;
  689.     to+=sizeof(char*);
  690.       }
  691.       else
  692.       {
  693.     if (type == FIELD_SKIPP_ENDSPACE || type == FIELD_SKIPP_PRESPACE)
  694.       min_pack_length--;
  695.     if (min_pack_length + rec_length > (uint) (from_end - from))
  696.       goto err;
  697.     memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
  698.       }
  699.       if ((bit= bit << 1) >= 256)
  700.       {
  701.     flag= (uchar) *++packpos; bit=1;
  702.       }
  703.     }
  704.     else
  705.     {
  706.       if (min_pack_length > (uint) (from_end - from))
  707.     goto err;
  708.       min_pack_length-=rec_length;
  709.       memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
  710.     }
  711.   }
  712.   if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1))))
  713.     DBUG_RETURN((info->packed_length=found_length));
  714.  err:
  715.   my_errno=HA_ERR_RECORD_DELETED;
  716.   DBUG_PRINT("error",("to_end: %lx -> %lx  from_end: %lx -> %lx",
  717.               to,to_end,from,from_end));
  718.   DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length);
  719.   DBUG_RETURN(MY_FILE_ERROR);
  720. } /* _nisam_rec_unpack */
  721.  
  722.  
  723.     /* Calc length of blob. Update info in blobs->length */
  724.  
  725. uint _calc_total_blob_length(N_INFO *info, const byte *record)
  726. {
  727.   uint i,length;
  728.   N_BLOB *blob;
  729.  
  730.   for (i=length=0, blob= info->blobs; i++ < info->s->base.blobs ; blob++)
  731.   {
  732.     blob->length=_calc_blob_length(blob->pack_length,record + blob->offset);
  733.     length+=blob->length;
  734.   }
  735.   return length;
  736. }
  737.  
  738.  
  739. uint _calc_blob_length(uint length, const byte *pos)
  740. {
  741.   switch (length) {
  742.   case 1:
  743.     return (uint) (uchar) *pos;
  744.   case 2:
  745.     {
  746.       short j; shortget(j,pos);
  747.       return (uint) (unsigned short) j;
  748.     }
  749. #ifdef MSDOS
  750.     break;                    /* skipp microsoft warning */
  751. #endif
  752.   case 3:
  753.     return uint3korr(pos);
  754.   case 4:
  755.     {
  756.       long j; longget(j,pos);
  757.       return (uint) j;
  758.     }
  759. #ifdef MSDOS
  760.     break;
  761. #endif
  762.   default:
  763.     break;
  764.   }
  765.   return 0; /* Impossible */
  766. }
  767.  
  768.     /* Read record from datafile */
  769.     /* Returns 0 if ok, -1 if error */
  770.  
  771. int _nisam_read_dynamic_record(N_INFO *info, ulong filepos, byte *buf)
  772. {
  773.   int flag;
  774.   uint b_type,left_length;
  775.   byte *to;
  776.   BLOCK_INFO block_info;
  777.   File file;
  778.   DBUG_ENTER("ni_read_dynamic_record");
  779.  
  780.   if (filepos != NI_POS_ERROR)
  781.   {
  782.     LINT_INIT(to);
  783.     LINT_INIT(left_length);
  784.     file=info->dfile;
  785.     block_info.next_filepos=filepos;    /* for easyer loop */
  786.     flag=block_info.second_read=0;
  787.     do
  788.     {
  789.       if (info->opt_flag & WRITE_CACHE_USED &&
  790.       info->rec_cache.pos_in_file <= block_info.next_filepos &&
  791.       flush_io_cache(&info->rec_cache))
  792.     goto err;
  793.       info->rec_cache.seek_not_done=1;
  794.       if ((b_type=_nisam_get_block_info(&block_info,file,
  795.                      block_info.next_filepos))
  796.       & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
  797.          BLOCK_FATAL_ERROR))
  798.       {
  799.     if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
  800.       my_errno=HA_ERR_RECORD_DELETED;
  801.     goto err;
  802.       }
  803.       if (flag == 0)            /* First block */
  804.       {
  805.     flag=1;
  806.     if (block_info.rec_len > (uint) info->s->base.max_pack_length)
  807.       goto panic;
  808.     if (info->s->base.blobs)
  809.     {
  810.       if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
  811.         goto err;
  812.     }
  813.     else
  814.       to= info->rec_buff;
  815.     left_length=block_info.rec_len;
  816.       }
  817.       if (left_length < block_info.data_len || ! block_info.data_len)
  818.     goto panic;            /* Wrong linked record */
  819.       if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos,
  820.            MYF(MY_NABP)))
  821.     goto panic;
  822.       left_length-=block_info.data_len;
  823.       to+=block_info.data_len;
  824.     } while (left_length);
  825.  
  826.     info->update|= HA_STATE_AKTIV;    /* We have a aktive record */
  827.     VOID(_nisam_writeinfo(info,0));
  828.     DBUG_RETURN(_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
  829.         MY_FILE_ERROR ? 0 : -1);
  830.   }
  831.   VOID(_nisam_writeinfo(info,0));
  832.   DBUG_RETURN(-1);            /* Wrong data to read */
  833.  
  834. panic:
  835.   my_errno=HA_ERR_WRONG_IN_RECORD;
  836. err:
  837.   VOID(_nisam_writeinfo(info,0));
  838.   DBUG_RETURN(-1);
  839. }
  840.  
  841.  
  842. byte *fix_rec_buff_for_blob(N_INFO *info, uint length)
  843. {
  844.   uint extra;
  845.   if (! info->rec_buff || length > info->alloced_rec_buff_length)
  846.   {
  847.     byte *newptr;
  848.     extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
  849.       DYN_DELETE_BLOCK_HEADER;
  850.     if (!(newptr=(byte*) my_realloc((gptr) info->rec_alloc,length+extra,
  851.                     MYF(MY_ALLOW_ZERO_PTR))))
  852.       return newptr;
  853.     info->rec_alloc=newptr;
  854.     info->rec_buff=newptr+ALIGN_SIZE(DYN_DELETE_BLOCK_HEADER);
  855.     info->alloced_rec_buff_length=length;
  856.   }
  857.   return info->rec_buff;
  858. }
  859.  
  860.  
  861.     /* Compare of record one disk with packed record in memory */
  862.  
  863. int _nisam_cmp_dynamic_record(register N_INFO *info, register const byte *record)
  864. {
  865.   uint flag,reclength,b_type;
  866.   ulong filepos;
  867.   byte *buffer;
  868.   BLOCK_INFO block_info;
  869.   DBUG_ENTER("_nisam_cmp_dynamic_record");
  870.  
  871.     /* We are going to do changes; dont let anybody disturb */
  872.   dont_break();                /* Dont allow SIGHUP or SIGINT */
  873.  
  874.   if (info->opt_flag & WRITE_CACHE_USED)
  875.   {
  876.     info->update&= ~HA_STATE_WRITE_AT_END;
  877.     if (flush_io_cache(&info->rec_cache))
  878.       DBUG_RETURN(-1);
  879.   }
  880.   info->rec_cache.seek_not_done=1;
  881.  
  882.     /* If nobody have touched the database we don't have to test rec */
  883.  
  884.   buffer=info->rec_buff;
  885.   if ((info->opt_flag & READ_CHECK_USED))
  886.   {                        /* If check isn't disabled  */
  887.     if (info->s->base.blobs)
  888.     {
  889.       if (!(buffer=(byte*) my_alloca(info->s->base.pack_reclength+
  890.                      _calc_total_blob_length(info,record))))
  891.     DBUG_RETURN(-1);
  892.     }
  893.     reclength=_nisam_rec_pack(info,buffer,record);
  894.     record= buffer;
  895.  
  896.     filepos=info->lastpos;
  897.     flag=block_info.second_read=0;
  898.     block_info.next_filepos=filepos;
  899.     while (reclength > 0)
  900.     {
  901.       if ((b_type=_nisam_get_block_info(&block_info,info->dfile,
  902.                     block_info.next_filepos))
  903.       & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
  904.          BLOCK_FATAL_ERROR))
  905.       {
  906.     if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
  907.       my_errno=HA_ERR_RECORD_CHANGED;
  908.     goto err;
  909.       }
  910.       if (flag == 0)                /* First block */
  911.       {
  912.     flag=1;
  913.     if (reclength != block_info.rec_len)
  914.     {
  915.       my_errno=HA_ERR_RECORD_CHANGED;
  916.       goto err;
  917.     }
  918.       } else if (reclength < block_info.data_len)
  919.       {
  920.     my_errno=HA_ERR_WRONG_IN_RECORD;
  921.     goto err;
  922.       }
  923.       reclength-=block_info.data_len;
  924.       if (_nisam_cmp_buffer(info->dfile,record,block_info.filepos,
  925.              block_info.data_len))
  926.       {
  927.     my_errno=HA_ERR_RECORD_CHANGED;
  928.     goto err;
  929.       }
  930.       flag=1;
  931.       record+=block_info.data_len;
  932.     }
  933.   }
  934.   my_errno=0;
  935.  err:
  936.   if (buffer != info->rec_buff)
  937.     my_afree((gptr) buffer);
  938.   DBUG_RETURN(my_errno);
  939. }
  940.  
  941.  
  942.     /* Compare file to buffert */
  943.  
  944. static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos, uint length)
  945. {
  946.   uint next_length;
  947.   char temp_buff[IO_SIZE*2];
  948.   DBUG_ENTER("_nisam_cmp_buffer");
  949.  
  950.   VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
  951.   next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1));
  952.  
  953.   while (length > IO_SIZE*2)
  954.   {
  955.     if (my_read(file,temp_buff,next_length,MYF(MY_NABP)))
  956.       goto err;
  957.     if (memcmp((byte*) buff,temp_buff,IO_SIZE))
  958.       DBUG_RETURN(1);
  959.     buff+=next_length;
  960.     length-= next_length;
  961.     next_length=IO_SIZE*2;
  962.   }
  963.   if (my_read(file,temp_buff,length,MYF(MY_NABP)))
  964.     goto err;
  965.   DBUG_RETURN(memcmp((byte*) buff,temp_buff,length));
  966. err:
  967.   DBUG_RETURN(1);
  968. }
  969.  
  970.  
  971. int _nisam_read_rnd_dynamic_record(N_INFO *info, byte *buf, register ulong filepos, int skipp_deleted_blocks)
  972. {
  973.   int flag,info_read,fatal_errcode;
  974.   uint left_len,b_type;
  975.   byte *to;
  976.   BLOCK_INFO block_info;
  977.   ISAM_SHARE *share=info->s;
  978.   DBUG_ENTER("_nisam_read_rnd_dynamic_record");
  979.  
  980.   info_read=0;
  981.   fatal_errcode= -1;
  982.   LINT_INIT(to);
  983.  
  984. #ifndef NO_LOCKING
  985.   if (info->lock_type == F_UNLCK)
  986.   {
  987. #ifndef UNSAFE_LOCKING
  988.     if (share->r_locks == 0 && share->w_locks == 0)
  989.     {
  990.       if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
  991.           MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
  992.     DBUG_RETURN(fatal_errcode);
  993.     }
  994. #else
  995.     info->tmp_lock_type=F_RDLCK;
  996. #endif
  997.   }
  998.   else
  999.     info_read=1;                /* memory-keyinfoblock is ok */
  1000. #endif /* !NO_LOCKING */
  1001.  
  1002.   flag=block_info.second_read=0;
  1003.   left_len=1;
  1004.   do
  1005.   {
  1006.     if (filepos >= share->state.data_file_length)
  1007.     {
  1008. #ifndef NO_LOCKING
  1009.       if (!info_read)
  1010.       {                        /* Check if changed */
  1011.     info_read=1;
  1012.     info->rec_cache.seek_not_done=1;
  1013.     if (my_pread(share->kfile,(char*) &share->state.header,
  1014.              share->state_length, 0L,MYF(MY_NABP)))
  1015.       goto err;
  1016.       }
  1017.       if (filepos >= share->state.data_file_length)
  1018. #endif
  1019.       {
  1020.     my_errno= HA_ERR_END_OF_FILE;
  1021.     goto err;
  1022.       }
  1023.     }
  1024.     if (info->opt_flag & READ_CACHE_USED)
  1025.     {
  1026.       if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
  1027.             sizeof(block_info.header),
  1028.             test(!flag && skipp_deleted_blocks) | 2))
  1029.     goto err;
  1030.       b_type=_nisam_get_block_info(&block_info,-1,filepos);
  1031.     }
  1032.     else
  1033.     {
  1034.       if (info->opt_flag & WRITE_CACHE_USED &&
  1035.       info->rec_cache.pos_in_file <= filepos &&
  1036.       flush_io_cache(&info->rec_cache))
  1037.     DBUG_RETURN(-1);
  1038.       info->rec_cache.seek_not_done=1;
  1039.       b_type=_nisam_get_block_info(&block_info,info->dfile,filepos);
  1040.     }
  1041.  
  1042.     if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
  1043.           BLOCK_FATAL_ERROR))
  1044.     {
  1045.       if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
  1046.       && skipp_deleted_blocks)
  1047.       {
  1048.     filepos=block_info.filepos+block_info.block_len;
  1049.     block_info.second_read=0;
  1050.     continue;        /* Search after next_record */
  1051.       }
  1052.       if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
  1053.       {
  1054.     my_errno=HA_ERR_RECORD_DELETED;
  1055.     info->lastpos=block_info.filepos;
  1056.     info->nextpos=block_info.filepos+block_info.block_len;
  1057.     fatal_errcode=1;
  1058.       }
  1059.       goto err;
  1060.     }
  1061.     if (flag == 0)                /* First block */
  1062.     {
  1063.       if (block_info.rec_len > (uint) share->base.max_pack_length)
  1064.     goto panic;
  1065.       info->lastpos=filepos;
  1066.       if (share->base.blobs)
  1067.       {
  1068.     if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
  1069.       goto err;
  1070.       }
  1071.       else
  1072.     to= info->rec_buff;
  1073.       left_len=block_info.rec_len;
  1074.     }
  1075.     if (left_len < block_info.data_len)
  1076.       goto panic;                /* Wrong linked record */
  1077.  
  1078.     if (info->opt_flag & READ_CACHE_USED)
  1079.     {
  1080.       if (_nisam_read_cache(&info->rec_cache,(byte*) to,block_info.filepos,
  1081.             block_info.data_len,
  1082.             test(!flag && skipp_deleted_blocks)))
  1083.     goto err;
  1084.     }
  1085.     else
  1086.     {
  1087.       VOID(my_seek(info->dfile,block_info.filepos,MY_SEEK_SET,MYF(0)));
  1088.       if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP)))
  1089.     goto err;
  1090.     }
  1091.     if (flag++ == 0)
  1092.     {
  1093.       info->nextpos=block_info.filepos+block_info.block_len;
  1094.       skipp_deleted_blocks=0;
  1095.     }
  1096.     left_len-=block_info.data_len;
  1097.     to+=block_info.data_len;
  1098.     filepos=block_info.next_filepos;
  1099.   } while (left_len);
  1100.  
  1101.   info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
  1102.   VOID(_nisam_writeinfo(info,0));
  1103.   if (_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
  1104.       MY_FILE_ERROR)
  1105.     DBUG_RETURN(0);
  1106.   DBUG_RETURN(fatal_errcode);            /* Wrong record */
  1107.  
  1108. panic:
  1109.   my_errno=HA_ERR_WRONG_IN_RECORD;        /* Something is fatal wrong */
  1110. err:
  1111.   VOID(_nisam_writeinfo(info,0));
  1112.   DBUG_RETURN(fatal_errcode);
  1113. }
  1114.  
  1115.  
  1116.     /* Read and process header from a dynamic-record-file */
  1117.  
  1118. uint _nisam_get_block_info(BLOCK_INFO *info, File file, ulong filepos)
  1119. {
  1120.   uint return_val=0,length;
  1121.   uchar *header=info->header;
  1122.  
  1123.   if (file >= 0)
  1124.   {
  1125.     VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
  1126.     if ((length=my_read(file,(char*) header,BLOCK_INFO_HEADER_LENGTH,MYF(0)))
  1127.     == MY_FILE_ERROR)
  1128.       return BLOCK_FATAL_ERROR;
  1129.     if (length != BLOCK_INFO_HEADER_LENGTH)
  1130.     {                    /* Test if short block */
  1131.       if (length < 3)
  1132.       {
  1133.     my_errno=HA_ERR_WRONG_IN_RECORD;     /* Garbage */
  1134.     return BLOCK_FATAL_ERROR;
  1135.       }
  1136.       bzero((byte*) header+length,BLOCK_INFO_HEADER_LENGTH-length);
  1137.     }
  1138.   }
  1139.   DBUG_DUMP("header",(byte*) header,BLOCK_INFO_HEADER_LENGTH);
  1140.   if (info->second_read)
  1141.   {
  1142.     if (info->header[0] <= 8)
  1143.       return_val=BLOCK_SYNC_ERROR;
  1144.   }
  1145.   else
  1146.   {
  1147.     if (info->header[0] > 8)
  1148.       return_val=BLOCK_SYNC_ERROR;
  1149.   }
  1150.   info->next_filepos= (ulong) NI_POS_ERROR; /* Dummy ifall no next block */
  1151.  
  1152.   switch (info->header[0]) {
  1153.   case 0:
  1154.     if ((info->block_len=(uint) uint3korr(header+1)) < N_MIN_BLOCK_LENGTH)
  1155.       return BLOCK_FATAL_ERROR;
  1156.     info->filepos=filepos;
  1157.     info->next_filepos=uint4korr(header+4);
  1158.     if (info->next_filepos == (uint32) ~0)    /* Fix for 64 bit long */
  1159.       info->next_filepos=NI_POS_ERROR;
  1160.     return return_val | BLOCK_DELETED;        /* Deleted block */
  1161.   case 1:
  1162.     info->rec_len=info->data_len=info->block_len=uint2korr(header+1);
  1163.     info->filepos=filepos+3;
  1164.     return return_val | BLOCK_FIRST | BLOCK_LAST;
  1165.   case 2:
  1166.     info->block_len=(info->rec_len=info->data_len=uint2korr(header+1))+1;
  1167.     info->filepos=filepos+3;
  1168.     return return_val | BLOCK_FIRST | BLOCK_LAST;
  1169.   case 3:
  1170.     info->rec_len=info->data_len=uint2korr(header+1);
  1171.     info->block_len=uint2korr(header+3);
  1172.     info->filepos=filepos+5;
  1173.     return return_val | BLOCK_FIRST | BLOCK_LAST;
  1174.   case 4:
  1175.     info->rec_len=uint2korr(header+1);
  1176.     info->block_len=info->data_len=uint2korr(header+3);
  1177.     info->next_filepos=uint4korr(header+5);
  1178.     info->second_read=1;
  1179.     info->filepos=filepos+9;
  1180.     return return_val | BLOCK_FIRST;
  1181. #if defined(_MSC_VER) || !defined(__WIN__)
  1182.   case 5:
  1183.     info->rec_len=info->data_len=info->block_len=uint3korr(header+1);
  1184.     info->filepos=filepos+4;
  1185.     return return_val | BLOCK_FIRST | BLOCK_LAST;
  1186.   case 6:
  1187.     info->block_len=(info->rec_len=info->data_len=uint3korr(header+1))+1;
  1188.     info->filepos=filepos+4;
  1189.     return return_val | BLOCK_FIRST | BLOCK_LAST;
  1190.   case 7:
  1191.     info->rec_len=info->data_len=uint3korr(header+1);
  1192.     info->block_len=uint3korr(header+4);
  1193.     info->filepos=filepos+7;
  1194.     return return_val | BLOCK_FIRST | BLOCK_LAST;
  1195.   case 8:
  1196.     info->rec_len=uint3korr(header+1);
  1197.     info->block_len=info->data_len=uint3korr(header+4);
  1198.     info->next_filepos=uint4korr(header+7);
  1199.     info->second_read=1;
  1200.     info->filepos=filepos+11;
  1201.     return return_val | BLOCK_FIRST;
  1202. #endif
  1203.   case 9:
  1204.     info->data_len=info->block_len=uint2korr(header+1);
  1205.     info->filepos=filepos+3;
  1206.     return return_val | BLOCK_LAST;
  1207.   case 10:
  1208.     info->block_len=(info->data_len=uint2korr(header+1))+1;
  1209.     info->filepos=filepos+3;
  1210.     return return_val | BLOCK_LAST;
  1211.   case 11:
  1212.     info->data_len=uint2korr(header+1);
  1213.     info->block_len=uint2korr(header+3);
  1214.     info->filepos=filepos+5;
  1215.     return return_val | BLOCK_LAST;
  1216.   case 12:
  1217.     info->data_len=info->block_len=uint2korr(header+1);
  1218.     info->next_filepos=uint4korr(header+3);
  1219.     info->second_read=1;
  1220.     info->filepos=filepos+7;
  1221.     return return_val;
  1222. #if defined(_MSC_VER) || !defined(__WIN__)
  1223.   case 13:
  1224.     info->data_len=info->block_len=uint3korr(header+1);
  1225.     info->filepos=filepos+4;
  1226.     return return_val | BLOCK_LAST;
  1227.   case 14:
  1228.     info->block_len=(info->data_len=uint3korr(header+1))+1;
  1229.     info->filepos=filepos+4;
  1230.     return return_val | BLOCK_LAST;
  1231.   case 15:
  1232.     info->data_len=uint3korr(header+1);
  1233.     info->block_len=uint3korr(header+4);
  1234.     info->filepos=filepos+7;
  1235.     return return_val | BLOCK_LAST;
  1236.   case 16:
  1237.     info->data_len=info->block_len=uint3korr(header+1);
  1238.     info->next_filepos=uint4korr(header+4);
  1239.     info->second_read=1;
  1240.     info->filepos=filepos+8;
  1241.     return return_val;
  1242. #endif
  1243.   default:
  1244.     my_errno=HA_ERR_WRONG_IN_RECORD;     /* Garbage */
  1245.     return BLOCK_ERROR;
  1246.   }
  1247. }
  1248.