home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / rsync221.zip / fileio.c < prev    next >
C/C++ Source or Header  |  1999-03-04  |  5KB  |  219 lines

  1. /* 
  2.    Copyright (C) Andrew Tridgell 1998
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*
  20.   File IO utilities used in rsync 
  21.   */
  22. #include "rsync.h"
  23.  
  24. static char last_byte;
  25. static int last_sparse;
  26. extern int sparse_files;
  27.  
  28. int sparse_end(int f)
  29. {
  30.     if (last_sparse) {
  31.         do_lseek(f,-1,SEEK_CUR);
  32.         return (write(f,&last_byte,1) == 1 ? 0 : -1);
  33.     }
  34.     last_sparse = 0;
  35.     return 0;
  36. }
  37.  
  38.  
  39. static int write_sparse(int f,char *buf,int len)
  40. {
  41.     int l1=0,l2=0;
  42.     int ret;
  43.  
  44.     for (l1=0;l1<len && buf[l1]==0;l1++) ;
  45.     for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
  46.  
  47.     last_byte = buf[len-1];
  48.  
  49.     if (l1 == len || l2 > 0)
  50.         last_sparse=1;
  51.  
  52.     if (l1 > 0)
  53.         do_lseek(f,l1,SEEK_CUR);  
  54.  
  55.     if (l1 == len) 
  56.         return len;
  57.  
  58.     if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
  59.         if (ret == -1 || ret == 0) return ret;
  60.         return (l1+ret);
  61.     }
  62.  
  63.     if (l2 > 0)
  64.         do_lseek(f,l2,SEEK_CUR);
  65.     
  66.     return len;
  67. }
  68.  
  69.  
  70.  
  71. int write_file(int f,char *buf,int len)
  72. {
  73.     int ret = 0;
  74.  
  75.     if (!sparse_files) 
  76.         return write(f,buf,len);
  77.  
  78.     while (len>0) {
  79.         int len1 = MIN(len, SPARSE_WRITE_SIZE);
  80.         int r1 = write_sparse(f, buf, len1);
  81.         if (r1 <= 0) {
  82.             if (ret > 0) return ret;
  83.             return r1;
  84.         }
  85.         len -= r1;
  86.         buf += r1;
  87.         ret += r1;
  88.     }
  89.     return ret;
  90. }
  91.  
  92.  
  93.  
  94. struct map_struct *map_file(int fd,OFF_T len)
  95. {
  96.     struct map_struct *ret;
  97.     ret = (struct map_struct *)malloc(sizeof(*ret));
  98.     if (!ret) out_of_memory("map_file");
  99.  
  100.     ret->map = NULL;
  101.     ret->fd = fd;
  102.     ret->size = len;
  103.     ret->p = NULL;
  104.     ret->p_size = 0;
  105.     ret->p_offset = 0;
  106.     ret->p_len = 0;
  107.  
  108. #ifdef USE_MMAP
  109.     len = MIN(len, MAX_MAP_SIZE);
  110.     ret->map = (char *)do_mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
  111.     if (ret->map == (char *)-1) {
  112.         ret->map = NULL;
  113.     } else {
  114.         ret->p_len = len;
  115.     }
  116. #endif
  117.     return ret;
  118. }
  119.  
  120.  
  121. char *map_ptr(struct map_struct *map,OFF_T offset,int len)
  122. {
  123.     int nread;
  124.  
  125.     if (len == 0) 
  126.         return NULL;
  127.  
  128.     if (len > (map->size-offset))
  129.         len = map->size-offset;
  130.  
  131. #ifdef USE_MMAP
  132.     if (map->map) {
  133.         if (offset >= map->p_offset && 
  134.             offset+len <= map->p_offset+map->p_len) {
  135.             return (map->map + (offset - map->p_offset));
  136.         }
  137.         if (munmap(map->map, map->p_len) != 0) {
  138.             rprintf(FERROR,"munmap failed : %s\n", strerror(errno));
  139.             exit_cleanup(RERR_MALLOC);
  140.         }
  141.  
  142.         /* align the mmap region on a nice boundary back a bit from
  143.            where it is asked for to allow for some seeking */
  144.         if (offset > 2*CHUNK_SIZE) {
  145.             map->p_offset = offset - 2*CHUNK_SIZE;
  146.             map->p_offset &= ~((OFF_T)(CHUNK_SIZE-1));
  147.         } else {
  148.             map->p_offset = 0;
  149.         }
  150.         
  151.         /* map up to MAX_MAP_SIZE */
  152.         map->p_len = MAX(len, MAX_MAP_SIZE);
  153.         map->p_len = MIN(map->p_len, map->size - map->p_offset);
  154.  
  155.         map->map = (char *)do_mmap(NULL,map->p_len,PROT_READ,
  156.                        MAP_SHARED,map->fd,map->p_offset);
  157.  
  158.         if (map->map == (char *)-1) {
  159.             map->map = NULL;
  160.             map->p_len = 0;
  161.             map->p_offset = 0;
  162.         } else {
  163.             return (map->map + (offset - map->p_offset));
  164.         }
  165.     }
  166. #endif
  167.  
  168.     if (offset >= map->p_offset && 
  169.         offset+len <= map->p_offset+map->p_len) {
  170.         return (map->p + (offset - map->p_offset));
  171.     }
  172.  
  173.     len = MAX(len,CHUNK_SIZE);
  174.     if (len > (map->size-offset))
  175.         len = map->size-offset;
  176.  
  177.     if (len > map->p_size) {
  178.         if (map->p) free(map->p);
  179.         map->p = (char *)malloc(len);
  180.         if (!map->p) out_of_memory("map_ptr");
  181.         map->p_size = len;
  182.     }
  183.  
  184.     map->p_offset = offset;
  185.     map->p_len = len;
  186.  
  187.     if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
  188.         rprintf(FERROR,"lseek failed in map_ptr\n");
  189.         exit_cleanup(RERR_FILEIO);
  190.     }
  191.  
  192.     if ((nread=read(map->fd,map->p,len)) != len) {        
  193.         if (nread < 0) nread = 0;
  194.         /* the best we can do is zero the buffer - the file
  195.                    has changed mid transfer! */
  196.         memset(map->p+nread, 0, len - nread);
  197.     }
  198.   
  199.     return map->p; 
  200. }
  201.  
  202.  
  203. void unmap_file(struct map_struct *map)
  204. {
  205. #ifdef USE_MMAP
  206.     if (map->map) {
  207.         munmap(map->map,map->p_len);
  208.         map->map = NULL;
  209.     }
  210. #endif
  211.     if (map->p) {
  212.         free(map->p);
  213.         map->p = NULL;
  214.     }
  215.     memset(map, 0, sizeof(*map));
  216.     free(map);
  217. }
  218.  
  219.