]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/open.c
xfsprogs update - fine-tune xfs_io size/offsets to be like mkfs, libdisk and build...
[thirdparty/xfsprogs-dev.git] / io / open.c
1 /*
2 * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
3 *
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.
7 *
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.
11 *
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.
18 *
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.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <xfs/libxfs.h>
34 #include "command.h"
35 #include "input.h"
36 #include "init.h"
37
38 static cmdinfo_t open_cmd;
39 static cmdinfo_t stat_cmd;
40 static cmdinfo_t setfl_cmd;
41 static cmdinfo_t statfs_cmd;
42 static cmdinfo_t extsize_cmd;
43 static int stat_f(int, char **);
44
45 int
46 openfile(
47 char *path,
48 xfs_fsop_geom_t *geom,
49 int aflag,
50 int cflag,
51 int dflag,
52 int rflag,
53 int sflag,
54 int tflag,
55 int xflag)
56 {
57 int fd;
58 int oflags;
59
60 oflags = (rflag ? O_RDONLY : O_RDWR);
61 if (aflag)
62 oflags |= O_APPEND;
63 if (cflag)
64 oflags |= O_CREAT;
65 if (dflag)
66 oflags |= O_DIRECT;
67 if (sflag)
68 oflags |= O_SYNC;
69 if (tflag)
70 oflags |= O_TRUNC;
71
72 fd = open(path, oflags, 0644);
73 if (fd < 0) {
74 perror(path);
75 return -1;
76 }
77 if (!platform_test_xfs_fd(fd)) {
78 fprintf(stderr, _("%s: specified file "
79 "[\"%s\"] is not on an XFS filesystem\n"),
80 progname, fname);
81 close(fd);
82 return -1;
83 }
84
85 if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
86 perror("XFS_IOC_FSGEOMETRY");
87 close(fd);
88 return -1;
89 }
90
91 if (!readonly && xflag) { /* read/write and realtime */
92 struct fsxattr attr;
93
94 if (xfsctl(path, fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
95 perror("XFS_IOC_FSGETXATTR");
96 close(fd);
97 return -1;
98 }
99 if (!(attr.fsx_xflags & XFS_XFLAG_REALTIME)) {
100 attr.fsx_xflags |= XFS_XFLAG_REALTIME;
101 if (xfsctl(path, fd, XFS_IOC_FSSETXATTR, &attr) < 0) {
102 perror("XFS_IOC_FSSETXATTR");
103 close(fd);
104 return -1;
105 }
106 }
107 }
108 return fd;
109 }
110
111 static int
112 usage(void)
113 {
114 printf("%s %s\n", open_cmd.name, open_cmd.oneline);
115 return 0;
116 }
117
118 static void
119 open_help(void)
120 {
121 printf(_(
122 "\n"
123 " opens a new file in the requested mode, after closing the current file\n"
124 "\n"
125 " Example:\n"
126 " 'open -d /tmp/data' - opens data file read-write for direct IO\n"
127 "\n"
128 " Opens a file for subsequent use by all of the other xfs_io commands.\n"
129 " With no arguments, open uses the stat command to show the current file.\n"
130 " -a -- open with the O_APPEND flag (append-only mode)\n"
131 " -c -- open with O_CREAT (create the file if it doesn't exist)\n"
132 " -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n"
133 " -r -- open with O_RDONLY, the default is O_RDWR\n"
134 " -s -- open with O_SYNC\n"
135 " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n"
136 " -x -- mark the file as a realtime XFS file immediately after opening it\n"
137 " Note1: read/write direct IO requests must be blocksize aligned.\n"
138 " Note2: the bmap for non-regular files can be obtained provided the file\n"
139 " was opened appropriately (in particular, must be opened read-only).\n"
140 "\n"));
141 }
142
143 static int
144 open_f(
145 int argc,
146 char **argv)
147 {
148 int aflag = 0;
149 int cflag = 0;
150 int dflag = 0;
151 int rflag = 0;
152 int sflag = 0;
153 int tflag = 0;
154 int xflag = 0;
155 char *filename;
156 xfs_fsop_geom_t geometry;
157 int fd;
158 int c;
159
160 if (argc == 1)
161 return stat_f(argc, argv);
162
163 while ((c = getopt(argc, argv, "acdrstx")) != EOF) {
164 switch (c) {
165 case 'a':
166 aflag = 1;
167 break;
168 case 'c':
169 cflag = 1;
170 break;
171 case 'd':
172 dflag = 1;
173 break;
174 case 'r':
175 rflag = 1;
176 break;
177 case 's':
178 sflag = 1;
179 break;
180 case 't':
181 tflag = 1;
182 break;
183 case 'x':
184 xflag = 1;
185 break;
186 default:
187 return usage();
188 }
189 }
190
191 if (optind != argc - 1)
192 return usage();
193
194 fd = openfile(argv[optind], &geometry,
195 aflag, cflag, dflag, rflag, sflag, tflag, xflag);
196 if (fd < 0)
197 return 0;
198
199 filename = strdup(argv[optind]);
200 if (!filename) {
201 perror("strdup");
202 close(fd);
203 return 0;
204 }
205
206 /*
207 * All OK, proceed to make this the new global open file
208 */
209 osync = sflag;
210 trunc = tflag;
211 append = aflag;
212 directio = dflag;
213 readonly = rflag;
214 realtime = xflag;
215 if (fname) {
216 close(fdesc);
217 free(fname);
218 }
219 fgeom = geometry;
220 fname = filename;
221 fdesc = fd;
222 return 0;
223 }
224
225 off64_t
226 filesize(void)
227 {
228 struct stat64 st;
229
230 if (fstat64(fdesc, &st) < 0) {
231 perror("fstat64");
232 return -1;
233 }
234 return st.st_size;
235 }
236
237 static char *
238 filetype(mode_t mode)
239 {
240 switch (mode & S_IFMT) {
241 case S_IFSOCK:
242 return _("socket");
243 case S_IFDIR:
244 return _("directory");
245 case S_IFCHR:
246 return _("char device");
247 case S_IFBLK:
248 return _("block device");
249 case S_IFREG:
250 return _("regular file");
251 case S_IFLNK:
252 return _("symbolic link");
253 case S_IFIFO:
254 return _("fifo");
255 }
256 return NULL;
257 }
258
259 static int
260 stat_f(
261 int argc,
262 char **argv)
263 {
264 struct fsxattr fsx;
265 struct stat64 st;
266 char fullname[PATH_MAX + 1];
267
268 printf(_("fd.path = \"%s\"\n"),
269 realpath(fname, fullname) ? fullname : fname);
270 printf(_("fd.flags = %s,%s,%s%s%s\n"),
271 osync ? _("sync") : _("non-sync"),
272 directio ? _("direct") : _("non-direct"),
273 readonly ? _("read-only") : _("read-write"),
274 realtime ? _(",real-time") : "",
275 append ? _(",append-only") : "");
276 if (fstat64(fdesc, &st) < 0) {
277 perror("fstat64");
278 } else {
279 printf(_("stat.ino = %lld\n"), (long long)st.st_ino);
280 printf(_("stat.type = %s\n"), filetype(st.st_mode));
281 printf(_("stat.size = %lld\n"), (long long)st.st_size);
282 printf(_("stat.blocks = %lld\n"), (long long)st.st_blocks);
283 if (argc == 2 && !strcmp(argv[1], "-v")) {
284 printf(_("stat.atime = %s"), ctime(&st.st_atime));
285 printf(_("stat.mtime = %s"), ctime(&st.st_mtime));
286 printf(_("stat.ctime = %s"), ctime(&st.st_ctime));
287 }
288 }
289 if ((xfsctl(fname, fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
290 perror("xfsctl(XFS_IOC_FSGETXATTR)");
291 } else {
292 printf(_("xattr.xflags = 0x%x\n"), fsx.fsx_xflags);
293 printf(_("xattr.extsize = %u\n"), fsx.fsx_extsize);
294 printf(_("xattr.nextents = %u\n"), fsx.fsx_nextents);
295 }
296 return 0;
297 }
298
299 static int
300 setfl_f(
301 int argc,
302 char **argv)
303 {
304 int c, flags;
305
306 flags = fcntl(fdesc, F_GETFL, 0);
307 if (flags < 0) {
308 perror("fcntl(F_GETFL)");
309 return 0;
310 }
311
312 while ((c = getopt(argc, argv, "ad")) != EOF) {
313 switch (c) {
314 case 'a':
315 if (flags & O_APPEND)
316 flags |= O_APPEND;
317 else
318 flags &= ~O_APPEND;
319 break;
320 case 'd':
321 if (flags & O_DIRECT)
322 flags |= O_DIRECT;
323 else
324 flags &= ~O_DIRECT;
325 break;
326 default:
327 printf(_("invalid setfl argument -- '%c'\n"), c);
328 return 0;
329 }
330 }
331
332 if (fcntl(fdesc, F_SETFL, flags) < 0)
333 perror("fcntl(F_SETFL)");
334
335 return 0;
336 }
337
338 static int
339 extsize_f(
340 int argc,
341 char **argv)
342 {
343 struct fsxattr fsx;
344 long extsize;
345
346 extsize = (long)cvtnum(fgeom.blocksize, fgeom.sectsize, argv[1]);
347 if (extsize < 0) {
348 printf(_("non-numeric extsize argument -- %s\n"), argv[1]);
349 return 0;
350 }
351 if ((xfsctl(fname, fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
352 perror("xfsctl(XFS_IOC_FSGETXATTR)");
353 return 0;
354 }
355 fsx.fsx_extsize = extsize;
356 if ((xfsctl(fname, fdesc, XFS_IOC_FSSETXATTR, &fsx)) < 0) {
357 perror("xfsctl(XFS_IOC_FSSETXATTR)");
358 return 0;
359 }
360
361 return 0;
362 }
363
364 static int
365 statfs_f(
366 int argc,
367 char **argv)
368 {
369 struct xfs_fsop_geom_v1 fsgeo;
370 struct statfs st;
371 char fullname[PATH_MAX + 1];
372
373 printf(_("fd.path = \"%s\"\n"),
374 realpath(fname, fullname) ? fullname : fname);
375 if (platform_fstatfs(fdesc, &st) < 0) {
376 perror("fstatfs");
377 } else {
378 printf(_("statfs.f_bsize = %lld\n"), (long long) st.f_bsize);
379 printf(_("statfs.f_blocks = %lld\n"), (long long) st.f_blocks);
380 #if !defined(__sgi__)
381 printf(_("statfs.f_bavail = %lld\n"), (long long) st.f_bavail);
382 #endif
383 }
384 if ((xfsctl(fname, fdesc, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) {
385 perror("xfsctl(XFS_IOC_FSGEOMETRY_V1)");
386 } else {
387 printf(_("geom.bsize = %u\n"), fsgeo.blocksize);
388 printf(_("geom.agcount = %u\n"), fsgeo.agcount);
389 printf(_("geom.agblocks = %u\n"), fsgeo.agblocks);
390 printf(_("geom.datablocks = %llu\n"),
391 (unsigned long long) fsgeo.datablocks);
392 printf(_("geom.rtblocks = %llu\n"),
393 (unsigned long long) fsgeo.rtblocks);
394 printf(_("geom.rtextents = %llu\n"),
395 (unsigned long long) fsgeo.rtextents);
396 printf(_("geom.rtextsize = %u\n"), fsgeo.rtextsize);
397 printf(_("geom.sunit = %u\n"), fsgeo.sunit);
398 printf(_("geom.swidth = %u\n"), fsgeo.swidth);
399 }
400 return 0;
401 }
402
403 void
404 open_init(void)
405 {
406 open_cmd.name = _("open");
407 open_cmd.altname = _("o");
408 open_cmd.cfunc = open_f;
409 open_cmd.argmin = 0;
410 open_cmd.argmax = -1;
411 open_cmd.args = _("[-acdrstx] [path]");
412 open_cmd.oneline =
413 _("close the current file, open file specified by path");
414 open_cmd.help = open_help;
415
416 stat_cmd.name = _("stat");
417 stat_cmd.cfunc = stat_f;
418 stat_cmd.argmin = 0;
419 stat_cmd.argmax = 1;
420 stat_cmd.args = _("[-v]");
421 stat_cmd.oneline =
422 _("statistics on the currently open file");
423
424 setfl_cmd.name = _("setfl");
425 setfl_cmd.cfunc = setfl_f;
426 setfl_cmd.args = _("[-adx]");
427 setfl_cmd.oneline =
428 _("set/clear append/direct flags on the open file");
429
430 statfs_cmd.name = _("statfs");
431 statfs_cmd.cfunc = statfs_f;
432 statfs_cmd.oneline =
433 _("statistics on the filesystem of the currently open file");
434
435 extsize_cmd.name = _("extsize");
436 extsize_cmd.cfunc = extsize_f;
437 extsize_cmd.argmin = 1;
438 extsize_cmd.argmax = 1;
439 extsize_cmd.oneline =
440 _("set prefered extent size (in bytes) for the open file");
441
442 add_command(&open_cmd);
443 add_command(&stat_cmd);
444 add_command(&setfl_cmd);
445 add_command(&statfs_cmd);
446 add_command(&extsize_cmd);
447 }