]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - rtcp/xfs_rtcp.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
8 #include "libfrog/fsgeom.h"
10 int rtcp(char *, char *, int);
11 int xfsrtextsize(char *path
);
19 fprintf(stderr
, _("%s [-e extsize] [-p] [-V] source target\n"), progname
);
24 main(int argc
, char **argv
)
26 int c
, i
, r
, errflg
= 0;
30 progname
= basename(argv
[0]);
31 setlocale(LC_ALL
, "");
32 bindtextdomain(PACKAGE
, LOCALEDIR
);
35 while ((c
= getopt(argc
, argv
, "pe:V")) != EOF
) {
38 extsize
= atoi(optarg
);
44 printf(_("%s version %s\n"), progname
, VERSION
);
52 * Check for sufficient arguments or a usage error.
58 fprintf(stderr
, _("%s: must specify files to copy\n"),
67 * If there is more than a source and target,
68 * the last argument (the target) must be a directory
69 * which really exists.
72 if (stat(argv
[argc
-1], &s2
) < 0) {
73 fprintf(stderr
, _("%s: stat of %s failed\n"),
74 progname
, argv
[argc
-1]);
78 if (!S_ISDIR(s2
.st_mode
)) {
80 _("%s: final argument is not directory\n"),
87 * Perform a multiple argument rtcp by
88 * multiple invocations of rtcp().
91 for (i
= 0; i
< argc
-1; i
++)
92 r
+= rtcp(argv
[i
], argv
[argc
-1], extsize
);
95 * Show errors by nonzero exit code.
101 rtcp( char *source
, char *target
, int fextsize
)
103 int fromfd
, tofd
, readct
, writect
, iosz
, reopen
;
104 int remove
= 0, rtextsize
;
105 char *sp
, *fbuf
, *ptr
;
106 char tbuf
[ PATH_MAX
];
108 struct fsxattr fsxattr
;
109 struct dioattr dioattr
;
112 * While source or target have trailing /, remove them
115 sp
= source
+ strlen(source
);
117 while (*--sp
== '/' && sp
> source
)
120 sp
= target
+ strlen(target
);
122 while (*--sp
== '/' && sp
> target
)
126 if ( stat(source
, &s1
) ) {
127 fprintf(stderr
, _("%s: failed stat on %s: %s\n"),
128 progname
, source
, strerror(errno
));
133 * check for a realtime partition
135 snprintf(tbuf
, sizeof(tbuf
), "%s", target
);
136 if ( stat(target
, &s2
) ) {
137 if (!S_ISDIR(s2
.st_mode
)) {
138 /* take out target file name */
139 if ((ptr
= strrchr(tbuf
, '/')) != NULL
)
142 snprintf(tbuf
, sizeof(tbuf
), ".");
146 if ( (rtextsize
= xfsrtextsize( tbuf
)) <= 0 ) {
148 _("%s: %s filesystem has no realtime partition\n"),
154 * check if target is a directory
156 snprintf(tbuf
, sizeof(tbuf
), "%s", target
);
157 if ( !stat(target
, &s2
) ) {
158 if (S_ISDIR(s2
.st_mode
)) {
159 snprintf(tbuf
, sizeof(tbuf
), "%s/%s", target
,
164 if ( stat(tbuf
, &s2
) ) {
166 * create the file if it does not exist
168 if ( (tofd
= open(tbuf
, O_RDWR
|O_CREAT
|O_DIRECT
, 0666)) < 0 ) {
169 fprintf(stderr
, _("%s: open of %s failed: %s\n"),
170 progname
, tbuf
, strerror(errno
));
176 * mark the file as a realtime file
178 fsxattr
.fsx_xflags
= FS_XFLAG_REALTIME
;
180 fsxattr
.fsx_extsize
= fextsize
;
182 fsxattr
.fsx_extsize
= 0;
184 if ( xfsctl(tbuf
, tofd
, FS_IOC_FSSETXATTR
, &fsxattr
) ) {
186 _("%s: set attributes on %s failed: %s\n"),
187 progname
, tbuf
, strerror(errno
));
196 if ( (tofd
= open(tbuf
, O_RDWR
|O_DIRECT
)) < 0 ) {
197 fprintf(stderr
, _("%s: open of %s failed: %s\n"),
198 progname
, tbuf
, strerror(errno
));
202 if ( xfsctl(tbuf
, tofd
, FS_IOC_FSGETXATTR
, &fsxattr
) ) {
204 _("%s: get attributes of %s failed: %s\n"),
205 progname
, tbuf
, strerror(errno
));
211 * check if the existing file is already a realtime file
213 if ( !(fsxattr
.fsx_xflags
& FS_XFLAG_REALTIME
) ) {
214 fprintf(stderr
, _("%s: %s is not a realtime file.\n"),
221 * check for matching extent size
223 if ( (fextsize
!= -1) && (fsxattr
.fsx_extsize
!= fextsize
) ) {
224 fprintf(stderr
, _("%s: %s file extent size is %d, "
226 progname
, tbuf
, fsxattr
.fsx_extsize
, fextsize
);
233 * open the source file
236 if ( (fromfd
= open(source
, O_RDONLY
|O_DIRECT
)) < 0 ) {
237 fprintf(stderr
, _("%s: open of %s source failed: %s\n"),
238 progname
, source
, strerror(errno
));
245 fsxattr
.fsx_xflags
= 0;
246 fsxattr
.fsx_extsize
= 0;
247 if ( xfsctl(source
, fromfd
, FS_IOC_FSGETXATTR
, &fsxattr
) ) {
250 if (! (fsxattr
.fsx_xflags
& FS_XFLAG_REALTIME
) ){
251 fprintf(stderr
, _("%s: %s is not a realtime file.\n"),
259 if ( (fromfd
= open(source
, O_RDONLY
)) < 0 ) {
260 fprintf(stderr
, _("%s: open of %s source failed: %s\n"),
261 progname
, source
, strerror(errno
));
270 * get direct I/O parameters
272 if ( xfsctl(tbuf
, tofd
, XFS_IOC_DIOINFO
, &dioattr
) ) {
274 _("%s: couldn't get direct I/O information: %s\n"),
275 progname
, strerror(errno
));
283 if ( rtextsize
% dioattr
.d_miniosz
) {
284 fprintf(stderr
, _("%s: extent size %d not a multiple of %d.\n"),
285 progname
, rtextsize
, dioattr
.d_miniosz
);
294 * Check that the source file size is a multiple of the
295 * file system block size.
297 if ( s1
.st_size
% dioattr
.d_miniosz
) {
298 printf(_("The size of %s is not a multiple of %d.\n"),
299 source
, dioattr
.d_miniosz
);
301 printf(_("%s will be padded to %lld bytes.\n"),
303 (((s1
.st_size
/ dioattr
.d_miniosz
) + 1) *
304 dioattr
.d_miniosz
) );
307 printf(_("Use the -p option to pad %s to a "
308 "size which is a multiple of %d bytes.\n"),
309 tbuf
, dioattr
.d_miniosz
);
318 iosz
= dioattr
.d_miniosz
;
319 fbuf
= memalign( dioattr
.d_mem
, iosz
);
320 memset(fbuf
, 0, iosz
);
323 * read the entire source file
325 while ( ( readct
= read( fromfd
, fbuf
, iosz
) ) != 0 ) {
327 * if there is a read error - break
334 * if there is a short read, pad to a block boundary
336 if ( readct
!= iosz
) {
337 if ( (readct
% dioattr
.d_miniosz
) != 0 ) {
338 readct
= ( (readct
/dioattr
.d_miniosz
) + 1 ) *
344 * write to target file
346 writect
= write( tofd
, fbuf
, readct
);
348 if ( writect
!= readct
) {
349 fprintf(stderr
, _("%s: write error: %s\n"),
350 progname
, strerror(errno
));
357 memset( fbuf
, 0, iosz
);
367 * Determine the realtime extent size of the XFS file system
370 xfsrtextsize( char *path
)
372 struct xfs_fsop_geom geo
;
373 int fd
, rval
, rtextsize
;
375 fd
= open( path
, O_RDONLY
);
377 fprintf(stderr
, _("%s: could not open %s: %s\n"),
378 progname
, path
, strerror(errno
));
381 rval
= -xfrog_geometry(fd
, &geo
);
386 rtextsize
= geo
.rtextsize
* geo
.blocksize
;