OSDN Git Service

2005-04-19 Roman Kennke <roman@kennke.org>
[pf3gnuchains/gcc-fork.git] / fastjar / shift.c
1 /* shift.c -- utilities to move regions of data in a file.
2    Copyright (C) 2004  Free Software Foundation, Inc.
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 (at
7 your option) any later version.
8   
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA.  */
18
19
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 #include "jartool.h"
24 #include "shift.h"
25
26 #define BUFFER_SIZE 1024
27
28 #define MIN(a, b) ((a) < (b) ? (a) : (b))
29
30 /*
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.
35  *
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'.
39  * 
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.
45  */
46 int
47 shift_up (int fd, off_t begin, off_t amount, struct zipentry *ze)
48 {
49   extern off_t end_of_entries;
50   int len, moved = 0;
51   ub1 buffer[BUFFER_SIZE];
52   off_t where, end, save;
53
54   if (amount <= 0)
55     return 0;
56
57   if ((save = lseek (fd, 0, SEEK_CUR)) == -1)
58     return 1;
59   if ((end = lseek (fd, 0, SEEK_END)) == -1)
60     return 1;
61   if (end < begin)
62     return 0;
63
64   where = begin;
65
66   do
67     {
68       if (lseek (fd, where, SEEK_SET) < 0)
69         return 1;
70       if ((len = read (fd, buffer, BUFFER_SIZE)) < 0)
71         return 1;
72       if (len == 0)
73         break;
74       if (lseek (fd, where - amount, SEEK_SET) < 0)
75         return 1;
76       if (write (fd, buffer, len) < 0)
77         return 1;
78       where += len;
79     }
80   while (where < end);
81
82   for (; ze; ze = ze->next_entry)
83     {
84       if (ze->offset >= begin)
85         {
86           ze->offset -= amount;
87           moved = 1;
88         }
89     }
90   if (moved)
91     end_of_entries -= amount;
92
93   if (lseek (fd, save, SEEK_SET) == -1)
94     return 1;
95   return 0;
96 }
97
98 /*
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.
103  *
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'.
107  *
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.
113  */
114 int
115 shift_down (int fd, off_t begin, off_t amount, struct zipentry *ze)
116 {
117   extern off_t end_of_entries;
118   int off, len, moved = 0;
119   ub1 buffer[BUFFER_SIZE];
120   off_t where, save;
121
122   if (amount <= 0)
123     return 0;
124
125   if ((save = lseek (fd, 0, SEEK_CUR)) == -1)
126     return 1;
127   if ((where = lseek (fd, 0, SEEK_END)) == -1)
128     return 1;
129   if (where < begin)
130     return 0;
131   off = (where - begin) % BUFFER_SIZE;
132   if (off == 0)
133     where -= BUFFER_SIZE;
134   else
135     where -= off;
136
137   do
138     {
139       if (lseek (fd, where, SEEK_SET) < 0)
140         return 1;
141       if ((len = read (fd, buffer, BUFFER_SIZE)) < 0)
142         return 1;
143       if (lseek (fd, where + amount, SEEK_SET) < 0)
144         return 1;
145       if (write (fd, buffer, len) < 0)
146         return 1;
147       where -= BUFFER_SIZE;
148     }
149   while (where >= begin);
150
151   for (; ze; ze = ze->next_entry)
152     {
153       if (ze->offset >= begin)
154         {
155           ze->offset += amount;
156           moved = 1;
157         }
158     }
159   if (moved)
160     end_of_entries += amount;
161
162   if (lseek (fd, save, SEEK_SET) == -1)
163     return 1;
164
165   return 0;
166 }