1 /* shift.c -- utilities to move regions of data in a file.
2 Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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 ((off_t
) 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 ((off_t
) ze
->offset
>= begin
)
155 ze
->offset
+= amount
;
160 end_of_entries
+= amount
;
162 if (lseek (fd
, save
, SEEK_SET
) == -1)