]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - rtcp/xfs_rtcp.c
Allow swab.h to be used in -pedantic c++ build environments.
[thirdparty/xfsprogs-dev.git] / rtcp / xfs_rtcp.c
CommitLineData
f91dde66 1/*
93d9f139 2 * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
dfc130f3 3 *
f91dde66
NS
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
dfc130f3 7 *
f91dde66
NS
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
dfc130f3 11 *
f91dde66
NS
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
dfc130f3 18 *
f91dde66
NS
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
dfc130f3 22 *
f91dde66
NS
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
dfc130f3
RC
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
f91dde66
NS
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33#include <libxfs.h>
f91dde66
NS
34
35int rtcp(char *, char *, int);
36int xfsrtextsize(char *path);
37
38int pflag;
39char *progname;
40
41void
42usage()
43{
9440d84d 44 fprintf(stderr, _("%s [-e extsize] [-p] source target\n"), progname);
f91dde66
NS
45 exit(2);
46}
47
48int
49main(int argc, char **argv)
50{
51 register int c, i, r, errflg = 0;
9440d84d 52 struct stat64 s2;
f91dde66
NS
53 int eflag;
54 int extsize = - 1;
55
56 progname = basename(argv[0]);
9440d84d
NS
57 setlocale(LC_ALL, "");
58 bindtextdomain(PACKAGE, LOCALEDIR);
59 textdomain(PACKAGE);
f91dde66
NS
60
61 while ((c = getopt(argc, argv, "pe:V")) != EOF) {
62 switch (c) {
63 case 'e':
64 eflag = 1;
65 extsize = atoi(optarg);
66 break;
67 case 'p':
68 pflag = 1;
69 break;
70 case 'V':
9440d84d 71 printf(_("%s version %s\n"), progname, VERSION);
3d98fe63 72 exit(0);
f91dde66
NS
73 default:
74 errflg++;
75 }
76 }
77
78 /*
79 * Check for sufficient arguments or a usage error.
80 */
81 argc -= optind;
82 argv = &argv[optind];
83
84 if (argc < 2) {
9440d84d
NS
85 fprintf(stderr, _("%s: must specify files to copy\n"),
86 progname);
f91dde66
NS
87 errflg++;
88 }
89
90 if (errflg)
91 usage();
92
93 /*
94 * If there is more than a source and target,
95 * the last argument (the target) must be a directory
96 * which really exists.
97 */
98 if (argc > 2) {
9440d84d
NS
99 if (stat64(argv[argc-1], &s2) < 0) {
100 fprintf(stderr, _("%s: stat64 of %s failed\n"),
f91dde66
NS
101 progname, argv[argc-1]);
102 exit(2);
103 }
104
105 if (!S_ISDIR(s2.st_mode)) {
9440d84d
NS
106 fprintf(stderr,
107 _("%s: final argument is not directory\n"),
f91dde66
NS
108 progname);
109 usage();
110 }
111 }
112
113 /*
114 * Perform a multiple argument rtcp by
115 * multiple invocations of rtcp().
116 */
117 r = 0;
118 for (i = 0; i < argc-1; i++)
119 r += rtcp(argv[i], argv[argc-1], extsize);
120
121 /*
122 * Show errors by nonzero exit code.
123 */
124 exit(r?2:0);
125}
126
127int
128rtcp( char *source, char *target, int fextsize)
129{
130 int fromfd, tofd, readct, writect, iosz, reopen;
131 int remove = 0, rtextsize;
dfc130f3 132 char *sp, *fbuf, *ptr;
f91dde66 133 char tbuf[ PATH_MAX ];
9440d84d 134 struct stat64 s1, s2;
f91dde66
NS
135 struct fsxattr fsxattr;
136 struct dioattr dioattr;
137
138 /*
139 * While source or target have trailing /, remove them
140 * unless only "/".
141 */
142 sp = source + strlen(source);
143 if (sp) {
144 while (*--sp == '/' && sp > source)
145 *sp = '\0';
146 }
147 sp = target + strlen(target);
148 if (sp) {
149 while (*--sp == '/' && sp > target)
150 *sp = '\0';
151 }
152
9440d84d
NS
153 if ( stat64(source, &s1) ) {
154 fprintf(stderr, _("%s: failed stat64 on %s: %s\n"),
155 progname, source, strerror(errno));
f91dde66
NS
156 return( -1);
157 }
158
159 /*
160 * check for a realtime partition
161 */
2d9475a4 162 snprintf(tbuf, sizeof(tbuf), "%s", target);
9440d84d 163 if ( stat64(target, &s2) ) {
f91dde66
NS
164 if (!S_ISDIR(s2.st_mode)) {
165 /* take out target file name */
166 if ((ptr = strrchr(tbuf, '/')) != NULL)
167 *ptr = '\0';
168 else
2d9475a4 169 snprintf(tbuf, sizeof(tbuf), ".");
dfc130f3 170 }
f91dde66
NS
171 }
172
173 if ( (rtextsize = xfsrtextsize( tbuf )) <= 0 ) {
9440d84d
NS
174 fprintf(stderr,
175 _("%s: %s filesystem has no realtime partition\n"),
f91dde66
NS
176 progname, tbuf);
177 return( -1 );
178 }
179
180 /*
181 * check if target is a directory
182 */
2d9475a4 183 snprintf(tbuf, sizeof(tbuf), "%s", target);
9440d84d 184 if ( !stat64(target, &s2) ) {
f91dde66 185 if (S_ISDIR(s2.st_mode)) {
2d9475a4
NS
186 snprintf(tbuf, sizeof(tbuf), "%s/%s", target,
187 basename(source));
dfc130f3 188 }
f91dde66 189 }
dfc130f3 190
9440d84d 191 if ( stat64(tbuf, &s2) ) {
f91dde66
NS
192 /*
193 * create the file if it does not exist
194 */
195 if ( (tofd = open(tbuf, O_RDWR|O_CREAT|O_DIRECT, 0666)) < 0 ) {
9440d84d
NS
196 fprintf(stderr, _("%s: open of %s failed: %s\n"),
197 progname, tbuf, strerror(errno));
f91dde66
NS
198 return( -1 );
199 }
200 remove = 1;
dfc130f3 201
f91dde66
NS
202 /*
203 * mark the file as a realtime file
204 */
205 fsxattr.fsx_xflags = XFS_XFLAG_REALTIME;
206 if (fextsize != -1 )
207 fsxattr.fsx_extsize = fextsize;
208 else
209 fsxattr.fsx_extsize = 0;
210
dfc130f3 211 if ( xfsctl(tbuf, tofd, XFS_IOC_FSSETXATTR, &fsxattr) ) {
9440d84d
NS
212 fprintf(stderr,
213 _("%s: set attributes on %s failed: %s\n"),
214 progname, tbuf, strerror(errno));
f91dde66
NS
215 close( tofd );
216 unlink( tbuf );
217 return( -1 );
218 }
219 } else {
220 /*
221 * open existing file
222 */
223 if ( (tofd = open(tbuf, O_RDWR|O_DIRECT)) < 0 ) {
9440d84d
NS
224 fprintf(stderr, _("%s: open of %s failed: %s\n"),
225 progname, tbuf, strerror(errno));
f91dde66
NS
226 return( -1 );
227 }
dfc130f3 228
93d9f139 229 if ( xfsctl(tbuf, tofd, XFS_IOC_FSGETXATTR, &fsxattr) ) {
9440d84d
NS
230 fprintf(stderr,
231 _("%s: get attributes of %s failed: %s\n"),
232 progname, tbuf, strerror(errno));
f91dde66
NS
233 close( tofd );
234 return( -1 );
235 }
236
237 /*
238 * check if the existing file is already a realtime file
239 */
240 if ( !(fsxattr.fsx_xflags & XFS_XFLAG_REALTIME) ) {
9440d84d 241 fprintf(stderr, _("%s: %s is not a realtime file.\n"),
f91dde66
NS
242 progname, tbuf);
243 return( -1 );
244 }
dfc130f3 245
f91dde66
NS
246 /*
247 * check for matching extent size
248 */
249 if ( (fextsize != -1) && (fsxattr.fsx_extsize != fextsize) ) {
9440d84d
NS
250 fprintf(stderr, _("%s: %s file extent size is %d, "
251 "instead of %d.\n"),
f91dde66
NS
252 progname, tbuf, fsxattr.fsx_extsize, fextsize);
253 return( -1 );
254 }
255 }
256
257 /*
258 * open the source file
259 */
260 reopen = 0;
261 if ( (fromfd = open(source, O_RDONLY|O_DIRECT)) < 0 ) {
9440d84d
NS
262 fprintf(stderr, _("%s: open of %s source failed: %s\n"),
263 progname, source, strerror(errno));
f91dde66
NS
264 close( tofd );
265 if (remove)
266 unlink( tbuf );
267 return( -1 );
268 }
269
270 fsxattr.fsx_xflags = 0;
271 fsxattr.fsx_extsize = 0;
93d9f139 272 if ( xfsctl(source, fromfd, XFS_IOC_FSGETXATTR, &fsxattr) ) {
f91dde66
NS
273 reopen = 1;
274 } else {
275 if (! (fsxattr.fsx_xflags & XFS_XFLAG_REALTIME) ){
9440d84d 276 fprintf(stderr, _("%s: %s is not a realtime file.\n"),
f91dde66
NS
277 progname, source);
278 reopen = 1;
279 }
280 }
281
282 if (reopen) {
283 close( fromfd );
284 if ( (fromfd = open(source, O_RDONLY )) < 0 ) {
9440d84d
NS
285 fprintf(stderr, _("%s: open of %s source failed: %s\n"),
286 progname, source, strerror(errno));
f91dde66
NS
287 close( tofd );
288 if (remove)
289 unlink( tbuf );
290 return( -1 );
291 }
292 }
293
294 /*
295 * get direct I/O parameters
296 */
93d9f139 297 if ( xfsctl(tbuf, tofd, XFS_IOC_DIOINFO, &dioattr) ) {
9440d84d
NS
298 fprintf(stderr,
299 _("%s: couldn't get direct I/O information: %s\n"),
300 progname, strerror(errno));
f91dde66
NS
301 close( fromfd );
302 close( tofd );
dfc130f3 303 if ( remove )
f91dde66
NS
304 unlink( tbuf );
305 return( -1 );
306 }
307
308 if ( rtextsize % dioattr.d_miniosz ) {
9440d84d 309 fprintf(stderr, _("%s: extent size %d not a multiple of %d.\n"),
f91dde66
NS
310 progname, rtextsize, dioattr.d_miniosz);
311 close( fromfd );
312 close( tofd );
313 if ( remove )
314 unlink( tbuf );
315 return( -1 );
316 }
317
318 /*
319 * Check that the source file size is a multiple of the
320 * file system block size.
321 */
322 if ( s1.st_size % dioattr.d_miniosz ) {
9440d84d 323 printf(_("The size of %s is not a multiple of %d.\n"),
f91dde66
NS
324 source, dioattr.d_miniosz);
325 if ( pflag ) {
9440d84d 326 printf(_("%s will be padded to %lld bytes.\n"),
e6c5396e 327 tbuf, (long long)
f91dde66
NS
328 (((s1.st_size / dioattr.d_miniosz) + 1) *
329 dioattr.d_miniosz) );
dfc130f3 330
f91dde66 331 } else {
9440d84d
NS
332 printf(_("Use the -p option to pad %s to a "
333 "size which is a multiple of %d bytes.\n"),
f91dde66
NS
334 tbuf, dioattr.d_miniosz);
335 close( fromfd );
336 close( tofd );
337 if ( remove )
338 unlink( tbuf );
339 return( -1 );
340 }
341 }
342
343 iosz = dioattr.d_miniosz;
344 fbuf = memalign( dioattr.d_mem, iosz);
345 bzero (fbuf, iosz);
346
347 /*
348 * read the entire source file
349 */
350 while ( ( readct = read( fromfd, fbuf, iosz) ) != 0 ) {
351 /*
352 * if there is a read error - break
353 */
354 if (readct < 0 ) {
355 break;
356 }
357
358 /*
359 * if there is a short read, pad to a block boundary
dfc130f3 360 */
f91dde66
NS
361 if ( readct != iosz ) {
362 if ( (readct % dioattr.d_miniosz) != 0 ) {
363 readct = ( (readct/dioattr.d_miniosz) + 1 ) *
364 dioattr.d_miniosz;
365 }
366 }
367
368 /*
dfc130f3 369 * write to target file
f91dde66
NS
370 */
371 writect = write( tofd, fbuf, readct);
372
373 if ( writect != readct ) {
9440d84d
NS
374 fprintf(stderr, _("%s: write error: %s\n"),
375 progname, strerror(errno));
f91dde66
NS
376 close(fromfd);
377 close(tofd);
378 free( fbuf );
379 return( -1 );
380 }
381
382 bzero( fbuf, iosz);
383 }
384
385 close(fromfd);
386 close(tofd);
387 free( fbuf );
388 return( 0 );
389}
390
391/*
dfc130f3 392 * Determine the realtime extent size of the XFS file system
f91dde66
NS
393 */
394int
395xfsrtextsize( char *path)
396{
397 int fd, rval, rtextsize;
9d77aadd 398 xfs_fsop_geom_v1_t geo;
f91dde66
NS
399
400 fd = open( path, O_RDONLY );
401 if ( fd < 0 ) {
9440d84d
NS
402 fprintf(stderr, _("%s: could not open %s: %s\n"),
403 progname, path, strerror(errno));
f91dde66
NS
404 return -1;
405 }
93d9f139 406 rval = xfsctl( path, fd, XFS_IOC_FSGEOMETRY_V1, &geo );
f91dde66 407 close(fd);
9d77aadd
NS
408 if ( rval < 0 )
409 return -1;
f91dde66
NS
410
411 rtextsize = geo.rtextsize * geo.blocksize;
412
f91dde66
NS
413 return rtextsize;
414}