]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/write.c
2 * Copyright (c) 2000-2002,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
19 #include <xfs/libxfs.h>
37 static int write_f(int argc
, char **argv
);
38 static void write_help(void);
40 static const cmdinfo_t write_cmd
=
41 { "write", NULL
, write_f
, 0, -1, 0, N_("[field or value]..."),
42 N_("write value to disk"), write_help
};
50 add_command(&write_cmd
);
59 " The 'write' command takes on different personalities depending on the\n"
60 " type of object being worked with.\n\n"
61 " Write has 3 modes:\n"
62 " 'struct mode' - is active anytime you're looking at a filesystem object\n"
63 " which contains individual fields (ex: an inode).\n"
64 " 'data mode' - is active anytime you set a disk address directly or set\n"
65 " the type to 'data'.\n"
66 " 'string mode' - only used for writing symlink blocks.\n"
69 " Struct mode: 'write core.uid 23' - set an inode uid field to 23.\n"
70 " 'write fname \"hello\\000\"' - write superblock fname.\n"
71 " (note: in struct mode strings are not null terminated)\n"
72 " 'write fname #6669736800' - write superblock fname with hex.\n"
73 " 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n"
74 " - write superblock uuid.\n"
75 " Data mode: 'write fill 0xff' - fill the entire block with 0xff's\n"
76 " 'write lshift 3' - shift the block 3 bytes to the left\n"
77 " 'write sequence 1 5' - write a cycle of number [1-5] through\n"
78 " the entire block.\n"
79 " String mode: 'write \"This_is_a_filename\" - write null terminated string.\n"
81 " In data mode type 'write' by itself for a list of specific commands.\n\n"
92 extern char *progname
;
94 if (x
.isreadonly
& LIBXFS_ISREADONLY
) {
95 dbprintf(_("%s started in read only mode, writing disabled\n"),
100 if (cur_typ
== NULL
) {
101 dbprintf(_("no current type\n"));
107 dbprintf(_("no handler function for type %s, write unsupported.\n"),
112 /* move past the "write" command */
116 (*pf
)(DB_WRITE
, cur_typ
->fields
, argc
, argv
);
121 /* compare significant portions of commands */
134 for (sigcnt
= 0; *s1
== *s2
; s1
++, s2
++) {
142 if (sig
&& (sigcnt
>= sig
))
164 len
= iocur_top
->len
- start
;
166 if (len
+start
> iocur_top
->len
) {
167 dbprintf(_("length (%d) too large for data block size (%d)"),
168 len
, iocur_top
->len
);
171 base
= (char *)iocur_top
->data
+ start
;
173 memcpy(base
, base
+shift
, len
-shift
);
174 memset(base
+(len
-shift
), 0, shift
);
193 len
= iocur_top
->len
- start
;
195 if (len
+start
> iocur_top
->len
) {
196 dbprintf(_("length (%d) too large for data block size (%d)"),
197 len
, iocur_top
->len
);
200 base
= (char *)iocur_top
->data
+ start
;
202 memcpy(base
+shift
, base
, len
-shift
);
203 memset(base
, 0, shift
);
223 len
= iocur_top
->len
- start
;
225 if (len
+start
> iocur_top
->len
) {
226 dbprintf(_("length (%d) too large for data block size (%d)"),
227 len
, iocur_top
->len
);
230 base
= (char *)iocur_top
->data
+ start
;
232 hold_region
= xmalloc(shift
);
233 memcpy(hold_region
, base
, shift
);
234 memcpy(base
, base
+shift
, len
-shift
);
235 memcpy(base
+(len
-shift
), hold_region
, shift
);
255 len
= iocur_top
->len
- start
;
257 if (len
+start
> iocur_top
->len
) {
258 dbprintf(_("length (%d) too large for data block size (%d)"),
259 len
, iocur_top
->len
);
262 base
= (char *)iocur_top
->data
+ start
;
264 hold_region
= xmalloc(shift
);
265 memcpy(hold_region
, base
+(len
-shift
), shift
);
266 memmove(base
+shift
, base
, len
-shift
);
267 memcpy(base
, hold_region
, shift
);
290 len
= iocur_top
->len
- start
;
292 if (len
+start
> iocur_top
->len
) {
293 dbprintf(_("length (%d) too large for data block size (%d)"),
294 len
, iocur_top
->len
);
297 if (from
== -1 || from
> 255)
299 if (to
== -1 || to
> 255)
314 buf
= (char *)iocur_top
->data
+ start
;
317 for (i
= start
; i
< start
+len
; i
++) {
319 tmp
= (tmp
+ step
)%(range
+1);
339 len
= iocur_top
->len
- start
;
341 if (len
+start
> iocur_top
->len
) {
342 dbprintf(_("length (%d) too large for data block size (%d)"),
343 len
, iocur_top
->len
);
346 buf
= (char *)iocur_top
->data
+ start
;
348 for (i
= start
; i
< start
+len
; i
++)
349 *buf
++ = (char)lrand48();
368 len
= iocur_top
->len
- start
;
370 if (len
+start
> iocur_top
->len
) {
371 dbprintf(_("length (%d) too large for data block size (%d)"),
372 len
, iocur_top
->len
);
375 base
= (char *)iocur_top
->data
+ start
;
377 memset(base
, value
, len
);
380 static struct bw_cmd
{
381 void (*cmdfunc
)(int,int,int,int,int);
393 /* cmd sig min max sh frm to start len */
394 { bwrite_lshift
, "lshift", 2, 0, 3, 1, 0, 0, 2, 3,
395 "[shiftcount] [start] [len]", },
396 { bwrite_rshift
, "rshift", 2, 0, 3, 1, 0, 0, 2, 3,
397 "[shiftcount] [start] [len]", },
398 { bwrite_lrot
, "lrot", 2, 0, 3, 1, 0, 0, 2, 3,
399 "[shiftcount] [start] [len]", },
400 { bwrite_rrot
, "rrot", 2, 0, 3, 1, 0, 0, 2, 3,
401 "[shiftcount] [start] [len]", },
402 { bwrite_seq
, "sequence", 3, 0, 4, 0, 1, 2, 3, 4,
403 "[from] [to] [start] [len]", },
404 { bwrite_random
, "random", 3, 0, 2, 0, 0, 0, 1, 2,
406 { bwrite_fill
, "fill", 1, 1, 3, 1, 0, 0, 2, 3,
407 "num [start] [len]" }
410 #define BWRITE_CMD_MAX (sizeof(bw_cmdtab)/sizeof(bw_cmdtab[0]))
421 /* only allow 1 case, '\' and 3 octal digits (or less) */
423 for (count
= 0; count
< 3; count
++) {
424 if (arg
[count
] == '\0')
427 if ((arg
[count
] < '0') && (arg
[count
] > '7'))
431 for (i
= 0; i
< count
; i
++) {
432 val
|= ((arg
[(count
-1)-i
]-'0')&0x07)<<(i
*3);
440 #define NYBBLE(x) (isdigit(x)?(x-'0'):(tolower(x)-'a'+0xa))
448 static char *buf
= NULL
;
455 if (bit_length
<= 64)
458 alloc_size
= (bit_length
+7)/8;
460 buf
= xrealloc(buf
, alloc_size
);
461 memset(buf
, 0, alloc_size
);
462 value
= (long long *)buf
;
468 /* zap closing quote if there is one */
469 if ((ostr
= strrchr(arg
+1, '\"')) != NULL
)
473 for (i
= 0; i
< alloc_size
; i
++) {
479 if (*(ostr
+1) >= '0' || *(ostr
+1) <= '7') {
480 ret
= convert_oct(ostr
+1, &octval
);
490 } else if (arg
[0] == '#' || ((arg
[0] != '-') && strchr(arg
,'-'))) {
492 * handle hex blocks ie
493 * #00112233445566778899aabbccddeeff
495 * 1122334455667788-99aa-bbcc-ddee-ff00112233445566778899
497 * (but if it starts with "-" assume it's just an integer)
499 int bytes
=bit_length
/8;
501 /* skip leading hash */
502 if (*arg
=='#') arg
++;
504 while (*arg
&& bytes
--) {
506 while (*arg
=='-') arg
++;
508 /* get first nybble */
509 if (!isxdigit((int)*arg
)) return NULL
;
510 *rbuf
=NYBBLE((int)*arg
)<<4;
513 /* skip more hyphens */
514 while (*arg
=='-') arg
++;
516 /* get second nybble */
517 if (!isxdigit((int)*arg
)) return NULL
;
518 *rbuf
++|=NYBBLE((int)*arg
);
521 if (bytes
<0&&*arg
) return NULL
;
527 *value
= strtoll(arg
, NULL
, 0);
529 #if __BYTE_ORDER == BIG_ENDIAN
530 /* hackery for big endian */
531 if (bit_length
<= 8) {
533 } else if (bit_length
<= 16) {
535 } else if (bit_length
<= 32) {
547 const field_t
*fields
,
559 dbprintf(_("usage: write fieldname value\n"));
563 fl
= flist_scan(argv
[0]);
565 dbprintf(_("unable to parse '%s'.\n"), argv
[0]);
569 /* if we're a root field type, go down 1 layer to get field list */
570 if (fields
->name
[0] == '\0') {
571 fa
= &ftattrtab
[fields
->ftyp
];
572 ASSERT(fa
->ftyp
== fields
->ftyp
);
576 /* run down the field list and set offsets into the data */
577 if (!flist_parse(fields
, fl
, iocur_top
->data
, 0)) {
579 dbprintf(_("parsing error\n"));
586 parentoffset
= sfl
->offset
;
590 bit_length
= fsize(sfl
->fld
, iocur_top
->data
, parentoffset
, 0);
591 bit_length
*= fcount(sfl
->fld
, iocur_top
->data
, parentoffset
);
593 /* convert this to a generic conversion routine */
594 /* should be able to handle str, num, or even labels */
596 buf
= convert_arg(argv
[1], bit_length
);
598 dbprintf(_("unable to convert value '%s'.\n"), argv
[1]);
602 setbitval(iocur_top
->data
, sfl
->offset
, bit_length
, buf
);
613 const field_t
*fields
,
621 dbprintf(_("usage (in string mode): write \"string...\"\n"));
625 buf
= convert_arg(argv
[0], (int)((strlen(argv
[0])+1)*8));
626 for (i
= 0; i
< iocur_top
->len
; i
++) {
627 ((char *)iocur_top
->data
)[i
] = *buf
;
632 /* write back to disk */
639 const field_t
*fields
,
649 struct bw_cmd
*cmd
= NULL
;
651 if (argc
<= 1 || argc
> 5)
654 for (i
= 0; i
< BWRITE_CMD_MAX
; i
++) {
655 if (sigcmp(argv
[0], bw_cmdtab
[i
].cmdstr
,
656 bw_cmdtab
[i
].sig_chars
)) {
663 dbprintf(_("write: invalid subcommand\n"));
667 if ((argc
< cmd
->argmin
+ 1) || (argc
> cmd
->argmax
+ 1)) {
668 dbprintf(_("write %s: invalid number of arguments\n"),
673 if (cmd
->shiftcount_arg
&& (cmd
->shiftcount_arg
< argc
))
674 shiftcount
= (int)strtoul(argv
[cmd
->shiftcount_arg
], NULL
, 0);
675 if (cmd
->start_arg
&& (cmd
->start_arg
< argc
))
676 start
= (int)strtoul(argv
[cmd
->start_arg
], NULL
, 0);
677 if (cmd
->len_arg
&& (cmd
->len_arg
< argc
))
678 len
= (int)strtoul(argv
[cmd
->len_arg
], NULL
, 0);
679 if (cmd
->from_arg
&& (cmd
->len_arg
< argc
))
680 from
= (int)strtoul(argv
[cmd
->from_arg
], NULL
, 0);
681 if (cmd
->to_arg
&& (cmd
->len_arg
< argc
))
682 to
= (int)strtoul(argv
[cmd
->to_arg
], NULL
, 0);
684 cmd
->cmdfunc(start
, len
, shiftcount
, from
, to
);
686 /* write back to disk */
692 dbprintf(_("usage: write (in data mode)\n"));
693 for (i
= 0; i
< BWRITE_CMD_MAX
; i
++) {
694 dbprintf(" %-9.9s %s\n",
695 bw_cmdtab
[i
].cmdstr
, bw_cmdtab
[i
].usage
);