1 /* shift.c -- utilities to move regions of data in a file.
2 Copyright (C) 2004 Free Software Foundation, Inc.
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 (at
7 your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 #include <sys/types.h>
26 #define BUFFER_SIZE 1024
28 #define MIN(a, b) ((a) < (b) ? (a) : (b))
31 * Shift the contents of a file up by `amount' bytes, starting at `begin'.
32 * The file is not truncated, data from `amount' to `begin - amount' is
33 * overwritten. The current file pointer of `fd' is preserved. Note that
34 * this might be past the new "end" of the file.
36 * If this function is passed a `struct zipentry', then all `offset'
37 * fields from that entry down the list that are greater than or equal
38 * to `begin' will be decreased by `amount'.
40 * fd - The file descriptor.
41 * begin - The offset of the first byte that should be shifted.
42 * amount - The number of bytes to shift by.
43 * ze - A pointer into a list of zip entries that should be updated
44 * to reflect the modified offset.
47 shift_up (int fd, off_t begin, off_t amount, struct zipentry *ze)
49 extern off_t end_of_entries;
51 ub1 buffer[BUFFER_SIZE];
52 off_t where, end, save;
57 if ((save = lseek (fd, 0, SEEK_CUR)) == -1)
59 if ((end = lseek (fd, 0, SEEK_END)) == -1)
68 if (lseek (fd, where, SEEK_SET) < 0)
70 if ((len = read (fd, buffer, BUFFER_SIZE)) < 0)
74 if (lseek (fd, where - amount, SEEK_SET) < 0)
76 if (write (fd, buffer, len) < 0)
82 for (; ze; ze = ze->next_entry)
84 if (ze->offset >= begin)
91 end_of_entries -= amount;
93 if (lseek (fd, save, SEEK_SET) == -1)
99 * Shift the contents of this file down by `amount' bytes, extending the
100 * end of file, starting at `begin'. This function will preserve the
101 * current file pointer of `fd'. Naturally, this function will fail if
102 * `fd' is not seekable.
104 * If this function is passed a `struct zipentry', then all `offset'
105 * fields from that entry down the list that are greater than or equal
106 * to `begin' will be increased by `amount'.
108 * fd - The file descriptor.
109 * begin - The offset of the first byte that should be shifted.
110 * amount - The number of bytes to shift by.
111 * ze - A pointer into a list of zip entries that should be updated
112 * to reflect the modified offset.
115 shift_down (int fd, off_t begin, off_t amount, struct zipentry *ze)
117 extern off_t end_of_entries;
118 int off, len, moved = 0;
119 ub1 buffer[BUFFER_SIZE];
125 if ((save = lseek (fd, 0, SEEK_CUR)) == -1)
127 if ((where = lseek (fd, 0, SEEK_END)) == -1)
131 off = (where - begin) % BUFFER_SIZE;
133 where -= BUFFER_SIZE;
139 if (lseek (fd, where, SEEK_SET) < 0)
141 if ((len = read (fd, buffer, BUFFER_SIZE)) < 0)
143 if (lseek (fd, where + amount, SEEK_SET) < 0)
145 if (write (fd, buffer, len) < 0)
147 where -= BUFFER_SIZE;
149 while (where >= begin);
151 for (; ze; ze = ze->next_entry)
153 if (ze->offset >= begin)
155 ze->offset += amount;
160 end_of_entries += amount;
162 if (lseek (fd, save, SEEK_SET) == -1)