00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "rsync.h"
00024
00025 static char last_byte;
00026 static int last_sparse;
00027 extern int sparse_files;
00028
00029 int sparse_end(int f)
00030 {
00031 if (last_sparse) {
00032 do_lseek(f,-1,SEEK_CUR);
00033 return (write(f,&last_byte,1) == 1 ? 0 : -1);
00034 }
00035 last_sparse = 0;
00036 return 0;
00037 }
00038
00039
00040 static int write_sparse(int f,char *buf,size_t len)
00041 {
00042 size_t l1=0, l2=0;
00043 int ret;
00044
00045 for (l1=0;l1<len && buf[l1]==0;l1++) ;
00046 for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
00047
00048 last_byte = buf[len-1];
00049
00050 if (l1 == len || l2 > 0)
00051 last_sparse=1;
00052
00053 if (l1 > 0) {
00054 do_lseek(f,l1,SEEK_CUR);
00055 }
00056
00057 if (l1 == len)
00058 return len;
00059
00060 ret = write(f, buf + l1, len - (l1+l2));
00061 if (ret == -1 || ret == 0)
00062 return ret;
00063 else if (ret != (int) (len - (l1+l2)))
00064 return (l1+ret);
00065
00066 if (l2 > 0)
00067 do_lseek(f,l2,SEEK_CUR);
00068
00069 return len;
00070 }
00071
00072
00073
00074 int write_file(int f,char *buf,size_t len)
00075 {
00076 int ret = 0;
00077
00078 if (!sparse_files) {
00079 return write(f,buf,len);
00080 }
00081
00082 while (len>0) {
00083 int len1 = MIN(len, SPARSE_WRITE_SIZE);
00084 int r1 = write_sparse(f, buf, len1);
00085 if (r1 <= 0) {
00086 if (ret > 0) return ret;
00087 return r1;
00088 }
00089 len -= r1;
00090 buf += r1;
00091 ret += r1;
00092 }
00093 return ret;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102 struct map_struct *map_file(int fd,OFF_T len)
00103 {
00104 struct map_struct *map;
00105 map = (struct map_struct *)malloc(sizeof(*map));
00106 if (!map) out_of_memory("map_file");
00107
00108 map->fd = fd;
00109 map->file_size = len;
00110 map->p = NULL;
00111 map->p_size = 0;
00112 map->p_offset = 0;
00113 map->p_fd_offset = 0;
00114 map->p_len = 0;
00115
00116 return map;
00117 }
00118
00119
00120 char *map_ptr(struct map_struct *map,OFF_T offset,int len)
00121 {
00122 int nread;
00123 OFF_T window_start, read_start;
00124 int window_size, read_size, read_offset;
00125
00126 if (len == 0) {
00127 return NULL;
00128 }
00129
00130
00131 if (len > (map->file_size - offset)) {
00132 len = map->file_size - offset;
00133 }
00134
00135
00136 if (offset >= map->p_offset &&
00137 offset+len <= map->p_offset+map->p_len) {
00138 return (map->p + (offset - map->p_offset));
00139 }
00140
00141
00142
00143 if (offset > 2*CHUNK_SIZE) {
00144 window_start = offset - 2*CHUNK_SIZE;
00145 window_start &= ~((OFF_T)(CHUNK_SIZE-1));
00146 } else {
00147 window_start = 0;
00148 }
00149 window_size = MAX_MAP_SIZE;
00150 if (window_start + window_size > map->file_size) {
00151 window_size = map->file_size - window_start;
00152 }
00153 if (offset + len > window_start + window_size) {
00154 window_size = (offset+len) - window_start;
00155 }
00156
00157
00158 if (window_size > map->p_size) {
00159 map->p = (char *)Realloc(map->p, window_size);
00160 if (!map->p) out_of_memory("map_ptr");
00161 map->p_size = window_size;
00162 }
00163
00164
00165
00166 if (window_start >= map->p_offset &&
00167 window_start < map->p_offset + map->p_len &&
00168 window_start + window_size >= map->p_offset + map->p_len) {
00169 read_start = map->p_offset + map->p_len;
00170 read_offset = read_start - window_start;
00171 read_size = window_size - read_offset;
00172 memmove(map->p, map->p + (map->p_len - read_offset), read_offset);
00173 } else {
00174 read_start = window_start;
00175 read_size = window_size;
00176 read_offset = 0;
00177 }
00178
00179 if (read_size <= 0) {
00180 rprintf(FINFO,"Warning: unexpected read size of %d in map_ptr\n", read_size);
00181 } else {
00182 if (map->p_fd_offset != read_start) {
00183 if (do_lseek(map->fd,read_start,SEEK_SET) != read_start) {
00184 rprintf(FERROR,"lseek failed in map_ptr\n");
00185 exit_cleanup(RERR_FILEIO);
00186 }
00187 map->p_fd_offset = read_start;
00188 }
00189
00190 if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
00191 if (nread < 0) nread = 0;
00192
00193
00194 memset(map->p+read_offset+nread, 0, read_size - nread);
00195 }
00196 map->p_fd_offset += nread;
00197 }
00198
00199 map->p_offset = window_start;
00200 map->p_len = window_size;
00201
00202 return map->p + (offset - map->p_offset);
00203 }
00204
00205
00206 void unmap_file(struct map_struct *map)
00207 {
00208 if (map->p) {
00209 free(map->p);
00210 map->p = NULL;
00211 }
00212 memset(map, 0, sizeof(*map));
00213 free(map);
00214 }
00215