]>
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.
9 int rtcp(char *, char *, int);
10 int xfsrtextsize(char *path
);
18 fprintf(stderr
, _("%s [-e extsize] [-p] [-V] source target\n"), progname
);
23 main(int argc
, char **argv
)
25 int c
, i
, r
, errflg
= 0;
29 progname
= basename(argv
[0]);
30 setlocale(LC_ALL
, "");
31 bindtextdomain(PACKAGE
, LOCALEDIR
);
34 while ((c
= getopt(argc
, argv
, "pe:V")) != EOF
) {
37 extsize
= atoi(optarg
);
43 printf(_("%s version %s\n"), progname
, VERSION
);
51 * Check for sufficient arguments or a usage error.
57 fprintf(stderr
, _("%s: must specify files to copy\n"),
66 * If there is more than a source and target,
67 * the last argument (the target) must be a directory
68 * which really exists.
71 if (stat(argv
[argc
-1], &s2
) < 0) {
72 fprintf(stderr
, _("%s: stat of %s failed\n"),
73 progname
, argv
[argc
-1]);
77 if (!S_ISDIR(s2
.st_mode
)) {
79 _("%s: final argument is not directory\n"),
86 * Perform a multiple argument rtcp by
87 * multiple invocations of rtcp().
90 for (i
= 0; i
< argc
-1; i
++)
91 r
+= rtcp(argv
[i
], argv
[argc
-1], extsize
);
94 * Show errors by nonzero exit code.
100 rtcp( char *source
, char *target
, int fextsize
)
102 int fromfd
, tofd
, readct
, writect
, iosz
, reopen
;
103 int remove
= 0, rtextsize
;
104 char *sp
, *fbuf
, *ptr
;
105 char tbuf
[ PATH_MAX
];
107 struct fsxattr fsxattr
;
108 struct dioattr dioattr
;
111 * While source or target have trailing /, remove them
114 sp
= source
+ strlen(source
);
116 while (*--sp
== '/' && sp
> source
)
119 sp
= target
+ strlen(target
);
121 while (*--sp
== '/' && sp
> target
)
125 if ( stat(source
, &s1
) ) {
126 fprintf(stderr
, _("%s: failed stat on %s: %s\n"),
127 progname
, source
, strerror(errno
));
132 * check for a realtime partition
134 snprintf(tbuf
, sizeof(tbuf
), "%s", target
);
135 if ( stat(target
, &s2
) ) {
136 if (!S_ISDIR(s2
.st_mode
)) {
137 /* take out target file name */
138 if ((ptr
= strrchr(tbuf
, '/')) != NULL
)
141 snprintf(tbuf
, sizeof(tbuf
), ".");
145 if ( (rtextsize
= xfsrtextsize( tbuf
)) <= 0 ) {
147 _("%s: %s filesystem has no realtime partition\n"),
153 * check if target is a directory
155 snprintf(tbuf
, sizeof(tbuf
), "%s", target
);
156 if ( !stat(target
, &s2
) ) {
157 if (S_ISDIR(s2
.st_mode
)) {
158 snprintf(tbuf
, sizeof(tbuf
), "%s/%s", target
,
163 if ( stat(tbuf
, &s2
) ) {
165 * create the file if it does not exist
167 if ( (tofd
= open(tbuf
, O_RDWR
|O_CREAT
|O_DIRECT
, 0666)) < 0 ) {
168 fprintf(stderr
, _("%s: open of %s failed: %s\n"),
169 progname
, tbuf
, strerror(errno
));
175 * mark the file as a realtime file
177 fsxattr
.fsx_xflags
= FS_XFLAG_REALTIME
;
179 fsxattr
.fsx_extsize
= fextsize
;
181 fsxattr
.fsx_extsize
= 0;
183 if ( xfsctl(tbuf
, tofd
, FS_IOC_FSSETXATTR
, &fsxattr
) ) {
185 _("%s: set attributes on %s failed: %s\n"),
186 progname
, tbuf
, strerror(errno
));
195 if ( (tofd
= open(tbuf
, O_RDWR
|O_DIRECT
)) < 0 ) {
196 fprintf(stderr
, _("%s: open of %s failed: %s\n"),
197 progname
, tbuf
, strerror(errno
));
201 if ( xfsctl(tbuf
, tofd
, FS_IOC_FSGETXATTR
, &fsxattr
) ) {
203 _("%s: get attributes of %s failed: %s\n"),
204 progname
, tbuf
, strerror(errno
));
210 * check if the existing file is already a realtime file
212 if ( !(fsxattr
.fsx_xflags
& FS_XFLAG_REALTIME
) ) {
213 fprintf(stderr
, _("%s: %s is not a realtime file.\n"),
220 * check for matching extent size
222 if ( (fextsize
!= -1) && (fsxattr
.fsx_extsize
!= fextsize
) ) {
223 fprintf(stderr
, _("%s: %s file extent size is %d, "
225 progname
, tbuf
, fsxattr
.fsx_extsize
, fextsize
);
232 * open the source file
235 if ( (fromfd
= open(source
, O_RDONLY
|O_DIRECT
)) < 0 ) {
236 fprintf(stderr
, _("%s: open of %s source failed: %s\n"),
237 progname
, source
, strerror(errno
));
244 fsxattr
.fsx_xflags
= 0;
245 fsxattr
.fsx_extsize
= 0;
246 if ( xfsctl(source
, fromfd
, FS_IOC_FSGETXATTR
, &fsxattr
) ) {
249 if (! (fsxattr
.fsx_xflags
& FS_XFLAG_REALTIME
) ){
250 fprintf(stderr
, _("%s: %s is not a realtime file.\n"),
258 if ( (fromfd
= open(source
, O_RDONLY
)) < 0 ) {
259 fprintf(stderr
, _("%s: open of %s source failed: %s\n"),
260 progname
, source
, strerror(errno
));
269 * get direct I/O parameters
271 if ( xfsctl(tbuf
, tofd
, XFS_IOC_DIOINFO
, &dioattr
) ) {
273 _("%s: couldn't get direct I/O information: %s\n"),
274 progname
, strerror(errno
));
282 if ( rtextsize
% dioattr
.d_miniosz
) {
283 fprintf(stderr
, _("%s: extent size %d not a multiple of %d.\n"),
284 progname
, rtextsize
, dioattr
.d_miniosz
);
293 * Check that the source file size is a multiple of the
294 * file system block size.
296 if ( s1
.st_size
% dioattr
.d_miniosz
) {
297 printf(_("The size of %s is not a multiple of %d.\n"),
298 source
, dioattr
.d_miniosz
);
300 printf(_("%s will be padded to %lld bytes.\n"),
302 (((s1
.st_size
/ dioattr
.d_miniosz
) + 1) *
303 dioattr
.d_miniosz
) );
306 printf(_("Use the -p option to pad %s to a "
307 "size which is a multiple of %d bytes.\n"),
308 tbuf
, dioattr
.d_miniosz
);
317 iosz
= dioattr
.d_miniosz
;
318 fbuf
= memalign( dioattr
.d_mem
, iosz
);
319 memset(fbuf
, 0, iosz
);
322 * read the entire source file
324 while ( ( readct
= read( fromfd
, fbuf
, iosz
) ) != 0 ) {
326 * if there is a read error - break
333 * if there is a short read, pad to a block boundary
335 if ( readct
!= iosz
) {
336 if ( (readct
% dioattr
.d_miniosz
) != 0 ) {
337 readct
= ( (readct
/dioattr
.d_miniosz
) + 1 ) *
343 * write to target file
345 writect
= write( tofd
, fbuf
, readct
);
347 if ( writect
!= readct
) {
348 fprintf(stderr
, _("%s: write error: %s\n"),
349 progname
, strerror(errno
));
356 memset( fbuf
, 0, iosz
);
366 * Determine the realtime extent size of the XFS file system
369 xfsrtextsize( char *path
)
371 int fd
, rval
, rtextsize
;
372 xfs_fsop_geom_v1_t geo
;
374 fd
= open( path
, O_RDONLY
);
376 fprintf(stderr
, _("%s: could not open %s: %s\n"),
377 progname
, path
, strerror(errno
));
380 rval
= xfsctl( path
, fd
, XFS_IOC_FSGEOMETRY_V1
, &geo
);
385 rtextsize
= geo
.rtextsize
* geo
.blocksize
;