]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/open.c
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU 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 the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "xfs/command.h"
21 #include "xfs/input.h"
27 #define __O_TMPFILE 0100000000
28 #elif defined(__hppa__)
29 #define __O_TMPFILE 040000000
30 #elif defined(__sparc__)
31 #define __O_TMPFILE 0x2000000
33 #define __O_TMPFILE 020000000
35 #endif /* __O_TMPFILE */
38 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
41 static cmdinfo_t open_cmd
;
42 static cmdinfo_t stat_cmd
;
43 static cmdinfo_t close_cmd
;
44 static cmdinfo_t statfs_cmd
;
45 static cmdinfo_t chproj_cmd
;
46 static cmdinfo_t lsproj_cmd
;
47 static cmdinfo_t extsize_cmd
;
56 if (fstat64(file
->fd
, &st
) < 0) {
66 switch (mode
& S_IFMT
) {
70 return _("directory");
72 return _("char device");
74 return _("block device");
76 return _("regular file");
78 return _("symbolic link");
91 struct fsxattr fsx
, fsxa
;
93 int verbose
= (argc
== 2 && !strcmp(argv
[1], "-v"));
95 printf(_("fd.path = \"%s\"\n"), file
->name
);
96 printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
97 file
->flags
& IO_OSYNC
? _("sync") : _("non-sync"),
98 file
->flags
& IO_DIRECT
? _("direct") : _("non-direct"),
99 file
->flags
& IO_READONLY
? _("read-only") : _("read-write"),
100 file
->flags
& IO_REALTIME
? _(",real-time") : "",
101 file
->flags
& IO_APPEND
? _(",append-only") : "",
102 file
->flags
& IO_NONBLOCK
? _(",non-block") : "",
103 file
->flags
& IO_TMPFILE
? _(",tmpfile") : "");
104 if (fstat64(file
->fd
, &st
) < 0) {
107 printf(_("stat.ino = %lld\n"), (long long)st
.st_ino
);
108 printf(_("stat.type = %s\n"), filetype(st
.st_mode
));
109 printf(_("stat.size = %lld\n"), (long long)st
.st_size
);
110 printf(_("stat.blocks = %lld\n"), (long long)st
.st_blocks
);
112 printf(_("stat.atime = %s"), ctime(&st
.st_atime
));
113 printf(_("stat.mtime = %s"), ctime(&st
.st_mtime
));
114 printf(_("stat.ctime = %s"), ctime(&st
.st_ctime
));
117 if (file
->flags
& IO_FOREIGN
)
119 if ((xfsctl(file
->name
, file
->fd
, XFS_IOC_FSGETXATTR
, &fsx
)) < 0 ||
120 (xfsctl(file
->name
, file
->fd
, XFS_IOC_FSGETXATTRA
, &fsxa
)) < 0) {
121 perror("XFS_IOC_FSGETXATTR");
123 printf(_("fsxattr.xflags = 0x%x "), fsx
.fsx_xflags
);
124 printxattr(fsx
.fsx_xflags
, verbose
, 0, file
->name
, 1, 1);
125 printf(_("fsxattr.projid = %u\n"), fsx
.fsx_projid
);
126 printf(_("fsxattr.extsize = %u\n"), fsx
.fsx_extsize
);
127 printf(_("fsxattr.nextents = %u\n"), fsx
.fsx_nextents
);
128 printf(_("fsxattr.naextents = %u\n"), fsxa
.fsx_nextents
);
130 if ((xfsctl(file
->name
, file
->fd
, XFS_IOC_DIOINFO
, &dio
)) < 0) {
131 perror("XFS_IOC_DIOINFO");
133 printf(_("dioattr.mem = 0x%x\n"), dio
.d_mem
);
134 printf(_("dioattr.miniosz = %u\n"), dio
.d_miniosz
);
135 printf(_("dioattr.maxiosz = %u\n"), dio
.d_maxiosz
);
143 xfs_fsop_geom_t
*geom
,
150 oflags
= flags
& IO_READONLY
? O_RDONLY
: O_RDWR
;
151 if (flags
& IO_APPEND
)
153 if (flags
& IO_CREAT
)
155 if (flags
& IO_DIRECT
)
157 if (flags
& IO_OSYNC
)
159 if (flags
& IO_TRUNC
)
161 if (flags
& IO_NONBLOCK
)
162 oflags
|= O_NONBLOCK
;
163 if (flags
& IO_TMPFILE
)
166 fd
= open(path
, oflags
, mode
);
168 if (errno
== EISDIR
&&
169 ((oflags
& (O_RDWR
|O_TMPFILE
)) == O_RDWR
)) {
170 /* make it as if we asked for O_RDONLY & try again */
173 flags
|= IO_READONLY
;
174 fd
= open(path
, oflags
, mode
);
185 if (!geom
|| !platform_test_xfs_fd(fd
))
188 if (xfsctl(path
, fd
, XFS_IOC_FSGEOMETRY
, geom
) < 0) {
189 perror("XFS_IOC_FSGEOMETRY");
194 if (!(flags
& IO_READONLY
) && (flags
& IO_REALTIME
)) {
197 if (xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &attr
) < 0) {
198 perror("XFS_IOC_FSGETXATTR");
202 if (!(attr
.fsx_xflags
& XFS_XFLAG_REALTIME
)) {
203 attr
.fsx_xflags
|= XFS_XFLAG_REALTIME
;
204 if (xfsctl(path
, fd
, XFS_IOC_FSSETXATTR
, &attr
) < 0) {
205 perror("XFS_IOC_FSSETXATTR");
218 xfs_fsop_geom_t
*geometry
,
223 filename
= strdup(name
);
230 /* Extend the table of currently open files */
231 filetable
= (fileio_t
*)realloc(filetable
, /* growing */
232 ++filecount
* sizeof(fileio_t
));
241 /* Finally, make this the new active open file */
242 file
= &filetable
[filecount
- 1];
245 file
->name
= filename
;
246 file
->geom
= *geometry
;
255 " opens a new file in the requested mode\n"
258 " 'open -cd /tmp/data' - creates/opens data file read-write for direct IO\n"
260 " Opens a file for subsequent use by all of the other xfs_io commands.\n"
261 " With no arguments, open uses the stat command to show the current file.\n"
262 " -a -- open with the O_APPEND flag (append-only mode)\n"
263 " -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n"
264 " -f -- open with O_CREAT (create the file if it doesn't exist)\n"
265 " -m -- permissions to use in case a new file is created (default 0600)\n"
266 " -n -- open with O_NONBLOCK\n"
267 " -r -- open with O_RDONLY, the default is O_RDWR\n"
268 " -s -- open with O_SYNC\n"
269 " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n"
270 " -R -- mark the file as a realtime XFS file immediately after opening it\n"
271 " -T -- open with O_TMPFILE (create a file not visible in the namespace)\n"
272 " Note1: usually read/write direct IO requests must be blocksize aligned;\n"
273 " some kernels, however, allow sectorsize alignment for direct IO.\n"
274 " Note2: the bmap for non-regular files can be obtained provided the file\n"
275 " was opened correctly (in particular, must be opened read-only).\n"
284 int c
, fd
, flags
= 0;
287 xfs_fsop_geom_t geometry
= { 0 };
291 return stat_f(argc
, argv
);
292 fprintf(stderr
, _("no files are open, try 'help open'\n"));
296 while ((c
= getopt(argc
, argv
, "FRTacdfm:nrstx")) != EOF
) {
299 /* Ignored / deprecated now, handled automatically */
312 mode
= strtoul(optarg
, &sp
, 0);
313 if (!sp
|| sp
== optarg
) {
314 printf(_("non-numeric mode -- %s\n"), optarg
);
319 flags
|= IO_NONBLOCK
;
322 flags
|= IO_READONLY
;
331 case 'x': /* backwards compatibility */
332 flags
|= IO_REALTIME
;
338 return command_usage(&open_cmd
);
342 if (optind
!= argc
- 1)
343 return command_usage(&open_cmd
);
345 if ((flags
& (IO_READONLY
|IO_TMPFILE
)) == (IO_READONLY
|IO_TMPFILE
)) {
346 fprintf(stderr
, _("-T and -r options are incompatible\n"));
350 fd
= openfile(argv
[optind
], &geometry
, flags
, mode
);
354 if (!platform_test_xfs_fd(fd
))
357 addfile(argv
[optind
], fd
, &geometry
, flags
);
369 if (close(file
->fd
) < 0) {
375 /* Shuffle the file table entries down over the removed entry */
376 offset
= file
- &filetable
[0];
377 length
= filecount
* sizeof(fileio_t
);
378 length
-= (offset
+ 1) * sizeof(fileio_t
);
380 memmove(file
, file
+ 1, length
);
382 /* Resize the memory allocated for the table, possibly freeing */
384 filetable
= (fileio_t
*)realloc(filetable
, /* shrinking */
385 filecount
* sizeof(fileio_t
));
386 if (offset
== filecount
)
388 file
= filetable
+ offset
;
391 file
= filetable
= NULL
;
402 " displays the project identifier associated with the current path\n"
405 " -R -- recursively descend (useful when current path is a directory)\n"
406 " -D -- recursively descend, but only list projects on directories\n"
413 const struct stat
*stat
,
420 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
423 if ((fd
= open(path
, O_RDONLY
)) == -1) {
424 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
425 progname
, path
, strerror(errno
));
427 if (getprojid(path
, fd
, &projid
) == 0)
428 printf("[%u] %s\n", (unsigned int)projid
, path
);
442 recurse_all
= recurse_dir
= 0;
443 while ((c
= getopt(argc
, argv
, "DR")) != EOF
) {
454 return command_usage(&lsproj_cmd
);
459 return command_usage(&lsproj_cmd
);
461 if (recurse_all
|| recurse_dir
)
462 nftw(file
->name
, lsproj_callback
,
463 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
464 else if (getprojid(file
->name
, file
->fd
, &projid
) < 0)
467 printf(_("projid = %u\n"), (unsigned int)projid
);
476 " modifies the project identifier associated with the current path\n"
478 " -R -- recursively descend (useful when current path is a directory)\n"
479 " -D -- recursively descend, only modifying projects on directories\n"
486 const struct stat
*stat
,
492 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
495 if ((fd
= open(path
, O_RDONLY
)) == -1) {
496 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
497 progname
, path
, strerror(errno
));
499 if (setprojid(path
, fd
, prid
) < 0)
513 recurse_all
= recurse_dir
= 0;
514 while ((c
= getopt(argc
, argv
, "DR")) != EOF
) {
525 return command_usage(&chproj_cmd
);
529 if (argc
!= optind
+ 1)
530 return command_usage(&chproj_cmd
);
532 prid
= prid_from_string(argv
[optind
]);
534 printf(_("invalid project ID -- %s\n"), argv
[optind
]);
538 if (recurse_all
|| recurse_dir
)
539 nftw(file
->name
, chproj_callback
,
540 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
541 else if (setprojid(file
->name
, file
->fd
, prid
) < 0)
551 " report or modify preferred extent size (in bytes) for the current path\n"
553 " -R -- recursively descend (useful when current path is a directory)\n"
554 " -D -- recursively descend, only modifying extsize on directories\n"
559 get_extsize(const char *path
, int fd
)
563 if ((xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
)) < 0) {
564 printf("%s: XFS_IOC_FSGETXATTR %s: %s\n",
565 progname
, path
, strerror(errno
));
568 printf("[%u] %s\n", fsx
.fsx_extsize
, path
);
573 set_extsize(const char *path
, int fd
, long extsz
)
578 if (fstat64(fd
, &stat
) < 0) {
582 if ((xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
)) < 0) {
583 printf("%s: XFS_IOC_FSGETXATTR %s: %s\n",
584 progname
, path
, strerror(errno
));
588 if (S_ISREG(stat
.st_mode
)) {
589 fsx
.fsx_xflags
|= XFS_XFLAG_EXTSIZE
;
590 } else if (S_ISDIR(stat
.st_mode
)) {
591 fsx
.fsx_xflags
|= XFS_XFLAG_EXTSZINHERIT
;
593 printf(_("invalid target file type - file %s\n"), path
);
596 fsx
.fsx_extsize
= extsz
;
598 if ((xfsctl(path
, fd
, XFS_IOC_FSSETXATTR
, &fsx
)) < 0) {
599 printf("%s: XFS_IOC_FSSETXATTR %s: %s\n",
600 progname
, path
, strerror(errno
));
608 get_extsize_callback(
610 const struct stat
*stat
,
616 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
619 if ((fd
= open(path
, O_RDONLY
)) == -1) {
620 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
621 progname
, path
, strerror(errno
));
623 get_extsize(path
, fd
);
630 set_extsize_callback(
632 const struct stat
*stat
,
638 if (recurse_dir
&& !S_ISDIR(stat
->st_mode
))
641 if ((fd
= open(path
, O_RDONLY
)) == -1) {
642 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
643 progname
, path
, strerror(errno
));
645 set_extsize(path
, fd
, extsize
);
656 size_t blocksize
, sectsize
;
659 recurse_all
= recurse_dir
= 0;
660 init_cvtnum(&blocksize
, §size
);
661 while ((c
= getopt(argc
, argv
, "DR")) != EOF
) {
672 return command_usage(&extsize_cmd
);
677 extsize
= (long)cvtnum(blocksize
, sectsize
, argv
[optind
]);
679 printf(_("non-numeric extsize argument -- %s\n"),
687 if (recurse_all
|| recurse_dir
)
688 nftw(file
->name
, (extsize
>= 0) ?
689 set_extsize_callback
: get_extsize_callback
,
690 100, FTW_PHYS
| FTW_MOUNT
| FTW_DEPTH
);
691 else if (extsize
>= 0)
692 set_extsize(file
->name
, file
->fd
, extsize
);
694 get_extsize(file
->name
, file
->fd
);
703 struct xfs_fsop_counts fscounts
;
704 struct xfs_fsop_geom fsgeo
;
707 printf(_("fd.path = \"%s\"\n"), file
->name
);
708 if (platform_fstatfs(file
->fd
, &st
) < 0) {
711 printf(_("statfs.f_bsize = %lld\n"), (long long) st
.f_bsize
);
712 printf(_("statfs.f_blocks = %lld\n"), (long long) st
.f_blocks
);
714 printf(_("statfs.f_frsize = %lld\n"), (long long) st
.f_frsize
);
716 printf(_("statfs.f_bavail = %lld\n"), (long long) st
.f_bavail
);
718 printf(_("statfs.f_files = %lld\n"), (long long) st
.f_files
);
719 printf(_("statfs.f_ffree = %lld\n"), (long long) st
.f_ffree
);
721 if (file
->flags
& IO_FOREIGN
)
723 if ((xfsctl(file
->name
, file
->fd
, XFS_IOC_FSGEOMETRY_V1
, &fsgeo
)) < 0) {
724 perror("XFS_IOC_FSGEOMETRY_V1");
726 printf(_("geom.bsize = %u\n"), fsgeo
.blocksize
);
727 printf(_("geom.agcount = %u\n"), fsgeo
.agcount
);
728 printf(_("geom.agblocks = %u\n"), fsgeo
.agblocks
);
729 printf(_("geom.datablocks = %llu\n"),
730 (unsigned long long) fsgeo
.datablocks
);
731 printf(_("geom.rtblocks = %llu\n"),
732 (unsigned long long) fsgeo
.rtblocks
);
733 printf(_("geom.rtextents = %llu\n"),
734 (unsigned long long) fsgeo
.rtextents
);
735 printf(_("geom.rtextsize = %u\n"), fsgeo
.rtextsize
);
736 printf(_("geom.sunit = %u\n"), fsgeo
.sunit
);
737 printf(_("geom.swidth = %u\n"), fsgeo
.swidth
);
739 if ((xfsctl(file
->name
, file
->fd
, XFS_IOC_FSCOUNTS
, &fscounts
)) < 0) {
740 perror("XFS_IOC_FSCOUNTS");
742 printf(_("counts.freedata = %llu\n"),
743 (unsigned long long) fscounts
.freedata
);
744 printf(_("counts.freertx = %llu\n"),
745 (unsigned long long) fscounts
.freertx
);
746 printf(_("counts.freeino = %llu\n"),
747 (unsigned long long) fscounts
.freeino
);
748 printf(_("counts.allocino = %llu\n"),
749 (unsigned long long) fscounts
.allocino
);
757 open_cmd
.name
= "open";
758 open_cmd
.altname
= "o";
759 open_cmd
.cfunc
= open_f
;
761 open_cmd
.argmax
= -1;
762 open_cmd
.flags
= CMD_NOMAP_OK
| CMD_NOFILE_OK
| CMD_FOREIGN_OK
;
763 open_cmd
.args
= _("[-acdrstxT] [path]");
764 open_cmd
.oneline
= _("open the file specified by path");
765 open_cmd
.help
= open_help
;
767 stat_cmd
.name
= "stat";
768 stat_cmd
.cfunc
= stat_f
;
771 stat_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
772 stat_cmd
.args
= _("[-v]");
773 stat_cmd
.oneline
= _("statistics on the currently open file");
775 close_cmd
.name
= "close";
776 close_cmd
.altname
= "c";
777 close_cmd
.cfunc
= close_f
;
778 close_cmd
.argmin
= 0;
779 close_cmd
.argmax
= 0;
780 close_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
781 close_cmd
.oneline
= _("close the current open file");
783 statfs_cmd
.name
= "statfs";
784 statfs_cmd
.cfunc
= statfs_f
;
785 statfs_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
787 _("statistics on the filesystem of the currently open file");
789 chproj_cmd
.name
= "chproj";
790 chproj_cmd
.cfunc
= chproj_f
;
791 chproj_cmd
.args
= _("[-D | -R] projid");
792 chproj_cmd
.argmin
= 1;
793 chproj_cmd
.argmax
= -1;
794 chproj_cmd
.flags
= CMD_NOMAP_OK
;
796 _("change project identifier on the currently open file");
797 chproj_cmd
.help
= chproj_help
;
799 lsproj_cmd
.name
= "lsproj";
800 lsproj_cmd
.cfunc
= lsproj_f
;
801 lsproj_cmd
.args
= _("[-D | -R]");
802 lsproj_cmd
.argmin
= 0;
803 lsproj_cmd
.argmax
= -1;
804 lsproj_cmd
.flags
= CMD_NOMAP_OK
;
806 _("list project identifier set on the currently open file");
807 lsproj_cmd
.help
= lsproj_help
;
809 extsize_cmd
.name
= "extsize";
810 extsize_cmd
.cfunc
= extsize_f
;
811 extsize_cmd
.args
= _("[-D | -R] [extsize]");
812 extsize_cmd
.argmin
= 0;
813 extsize_cmd
.argmax
= -1;
814 extsize_cmd
.flags
= CMD_NOMAP_OK
;
815 extsize_cmd
.oneline
=
816 _("get/set preferred extent size (in bytes) for the open file");
817 extsize_cmd
.help
= extsize_help
;
819 add_command(&open_cmd
);
820 add_command(&stat_cmd
);
821 add_command(&close_cmd
);
822 add_command(&statfs_cmd
);
823 add_command(&chproj_cmd
);
824 add_command(&lsproj_cmd
);
825 add_command(&extsize_cmd
);