2 Copyright (C) Andrew Tridgell 1998
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.
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.
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.
20 File IO utilities used in rsync
24 static char last_byte;
25 static int last_sparse;
26 extern int sparse_files;
31 do_lseek(f,-1,SEEK_CUR);
32 return (write(f,&last_byte,1) == 1 ? 0 : -1);
39 static int write_sparse(int f,char *buf,int len)
44 for (l1=0;l1<len && buf[l1]==0;l1++) ;
45 for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
47 last_byte = buf[len-1];
49 if (l1 == len || l2 > 0)
53 do_lseek(f,l1,SEEK_CUR);
58 if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
59 if (ret == -1 || ret == 0) return ret;
64 do_lseek(f,l2,SEEK_CUR);
71 int write_file(int f,char *buf,int len)
76 return write(f,buf,len);
79 int len1 = MIN(len, SPARSE_WRITE_SIZE);
80 int r1 = write_sparse(f, buf, len1);
82 if (ret > 0) return ret;
94 struct map_struct *map_file(int fd,OFF_T len)
96 struct map_struct *ret;
97 ret = (struct map_struct *)malloc(sizeof(*ret));
98 if (!ret) out_of_memory("map_file");
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) {
121 char *map_ptr(struct map_struct *map,OFF_T offset,int len)
128 if (len > (map->size-offset))
129 len = map->size-offset;
133 if (offset >= map->p_offset &&
134 offset+len <= map->p_offset+map->p_len) {
135 return (map->map + (offset - map->p_offset));
137 if (munmap(map->map, map->p_len) != 0) {
138 rprintf(FERROR,"munmap failed : %s\n", strerror(errno));
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));
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);
155 map->map = (char *)do_mmap(NULL,map->p_len,PROT_READ,
156 MAP_SHARED,map->fd,map->p_offset);
158 if (map->map == (char *)-1) {
163 return (map->map + (offset - map->p_offset));
168 if (offset >= map->p_offset &&
169 offset+len <= map->p_offset+map->p_len) {
170 return (map->p + (offset - map->p_offset));
173 len = MAX(len,CHUNK_SIZE);
174 if (len > (map->size-offset))
175 len = map->size-offset;
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");
184 map->p_offset = offset;
187 if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
188 rprintf(FERROR,"lseek failed in map_ptr\n");
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);
203 void unmap_file(struct map_struct *map)
207 munmap(map->map,map->p_len);
215 memset(map, 0, sizeof(*map));