]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - db/write.c
metadump: warn about corruption if log is dirty
[thirdparty/xfsprogs-dev.git] / db / write.c
CommitLineData
2bd0ea18 1/*
da23017d
NS
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
dfc130f3 4 *
da23017d
NS
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
2bd0ea18 7 * published by the Free Software Foundation.
dfc130f3 8 *
da23017d
NS
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.
dfc130f3 13 *
da23017d
NS
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
2bd0ea18
NS
17 */
18
6b803e5a 19#include "libxfs.h"
2bd0ea18
NS
20#include <ctype.h>
21#include <time.h>
22#include "bit.h"
23#include "block.h"
24#include "command.h"
2bd0ea18
NS
25#include "type.h"
26#include "faddr.h"
27#include "fprint.h"
28#include "field.h"
29#include "flist.h"
30#include "io.h"
4ca431fc 31#include "init.h"
2bd0ea18
NS
32#include "output.h"
33#include "print.h"
34#include "write.h"
35#include "malloc.h"
36
37static int write_f(int argc, char **argv);
38static void write_help(void);
39
40static const cmdinfo_t write_cmd =
c9f5e3db 41 { "write", NULL, write_f, 0, -1, 0, N_("[-c] [field or value]..."),
9ee7055c 42 N_("write value to disk"), write_help };
2bd0ea18
NS
43
44void
45write_init(void)
46{
4ca431fc 47 if (!expert_mode)
2bd0ea18
NS
48 return;
49
50 add_command(&write_cmd);
51 srand48(clock());
52}
53
dfc130f3 54static void
2bd0ea18
NS
55write_help(void)
56{
9ee7055c 57 dbprintf(_(
2bd0ea18
NS
58"\n"
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"
67"\n"
68" Examples:\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"
dfc130f3 73" 'write uuid 00112233-4455-6677-8899-aabbccddeeff'\n"
2bd0ea18
NS
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"
80"\n"
81" In data mode type 'write' by itself for a list of specific commands.\n\n"
86769b32
DC
82" Specifying the -c option will allow writes of invalid (corrupt) data with\n"
83" an invalid CRC. Specifying the -d option will allow writes of invalid data,\n"
84" but still recalculate the CRC so we are forced to check and detect the\n"
85" invalid data appropriately.\n\n"
9ee7055c 86));
2bd0ea18
NS
87
88}
89
90static int
91write_f(
92 int argc,
93 char **argv)
94{
95 pfunc_t pf;
96 extern char *progname;
c9f5e3db 97 int c;
86769b32
DC
98 bool corrupt = false; /* Allow write of bad data w/ invalid CRC */
99 bool invalid_data = false; /* Allow write of bad data w/ valid CRC */
100 struct xfs_buf_ops local_ops;
c9f5e3db 101 const struct xfs_buf_ops *stashed_ops = NULL;
2bd0ea18 102
4ca431fc 103 if (x.isreadonly & LIBXFS_ISREADONLY) {
9ee7055c 104 dbprintf(_("%s started in read only mode, writing disabled\n"),
2bd0ea18
NS
105 progname);
106 return 0;
107 }
108
109 if (cur_typ == NULL) {
9ee7055c 110 dbprintf(_("no current type\n"));
2bd0ea18
NS
111 return 0;
112 }
113
114 pf = cur_typ->pfunc;
115 if (pf == NULL) {
9ee7055c 116 dbprintf(_("no handler function for type %s, write unsupported.\n"),
2bd0ea18
NS
117 cur_typ->name);
118 return 0;
119 }
120
86769b32 121 while ((c = getopt(argc, argv, "cd")) != EOF) {
c9f5e3db
ES
122 switch (c) {
123 case 'c':
86769b32
DC
124 corrupt = true;
125 break;
126 case 'd':
127 invalid_data = true;
c9f5e3db
ES
128 break;
129 default:
130 dbprintf(_("bad option for write command\n"));
131 return 0;
132 }
133 }
134
86769b32
DC
135 if (corrupt && invalid_data) {
136 dbprintf(_("Cannot specify both -c and -d options\n"));
137 return 0;
138 }
139
6f7f8928
DW
140 if (invalid_data &&
141 iocur_top->typ->crc_off == TYP_F_NO_CRC_OFF &&
aa13f87a
ES
142 !iocur_top->ino_buf &&
143 !iocur_top->dquot_buf) {
86769b32
DC
144 dbprintf(_("Cannot recalculate CRCs on this type of object\n"));
145 return 0;
146 }
147
c9f5e3db
ES
148 argc -= optind;
149 argv += optind;
150
86769b32
DC
151 /*
152 * If the buffer has no verifier or we are using standard verifier
153 * paths, then just write it out and return
154 */
155 if (!iocur_top->bp->b_ops ||
156 !(corrupt || invalid_data)) {
157 (*pf)(DB_WRITE, cur_typ->fields, argc, argv);
158 return 0;
159 }
160
161
162 /* Temporarily remove write verifier to write bad data */
163 stashed_ops = iocur_top->bp->b_ops;
164 local_ops.verify_read = stashed_ops->verify_read;
165 iocur_top->bp->b_ops = &local_ops;
166
167 if (corrupt) {
168 local_ops.verify_write = xfs_dummy_verify;
169 dbprintf(_("Allowing write of corrupted data and bad CRC\n"));
6f7f8928
DW
170 } else if (iocur_top->ino_buf) {
171 local_ops.verify_write = xfs_verify_recalc_inode_crc;
172 dbprintf(_("Allowing write of corrupted inode with good CRC\n"));
aa13f87a
ES
173 } else if (iocur_top->dquot_buf) {
174 local_ops.verify_write = xfs_verify_recalc_dquot_crc;
175 dbprintf(_("Allowing write of corrupted dquot with good CRC\n"));
86769b32
DC
176 } else { /* invalid data */
177 local_ops.verify_write = xfs_verify_recalc_crc;
178 dbprintf(_("Allowing write of corrupted data with good CRC\n"));
c9f5e3db 179 }
2bd0ea18
NS
180
181 (*pf)(DB_WRITE, cur_typ->fields, argc, argv);
182
86769b32 183 iocur_top->bp->b_ops = stashed_ops;
c9f5e3db 184
2bd0ea18
NS
185 return 0;
186}
187
188/* compare significant portions of commands */
189
190static int
191sigcmp(
192 char *s1,
193 char *s2,
194 int sig)
195{
196 int sigcnt;
197
198 if (!s1 || !s2)
199 return 0;
200
201 for (sigcnt = 0; *s1 == *s2; s1++, s2++) {
202 sigcnt++;
203 if (*s1 == '\0')
204 return 1;
205 }
206 if (*s1 && *s2)
207 return 0;
208
209 if (sig && (sigcnt >= sig))
210 return 1;
211
212 return 0;
213}
214
215/* ARGSUSED */
216static void
217bwrite_lshift(
218 int start,
219 int len,
220 int shift,
221 int from,
222 int to)
223{
224 char *base;
225
226 if (shift == -1)
227 shift = 1;
228 if (start == -1)
229 start = 0;
230 if (len == -1)
231 len = iocur_top->len - start;
232
233 if (len+start > iocur_top->len) {
9ee7055c 234 dbprintf(_("length (%d) too large for data block size (%d)"),
2bd0ea18
NS
235 len, iocur_top->len);
236 }
237
238 base = (char *)iocur_top->data + start;
239
240 memcpy(base, base+shift, len-shift);
241 memset(base+(len-shift), 0, shift);
242}
243
244/* ARGSUSED */
245static void
246bwrite_rshift(
247 int start,
248 int len,
249 int shift,
250 int from,
251 int to)
252{
253 char *base;
254
255 if (shift == -1)
256 shift = 1;
257 if (start == -1)
258 start = 0;
259 if (len == -1)
260 len = iocur_top->len - start;
261
262 if (len+start > iocur_top->len) {
9ee7055c 263 dbprintf(_("length (%d) too large for data block size (%d)"),
2bd0ea18
NS
264 len, iocur_top->len);
265 }
266
267 base = (char *)iocur_top->data + start;
268
269 memcpy(base+shift, base, len-shift);
270 memset(base, 0, shift);
271}
272
273/* ARGSUSED */
274static void
275bwrite_lrot(
276 int start,
277 int len,
278 int shift,
279 int from,
280 int to)
281{
282 char *base;
283 char *hold_region;
284
285 if (shift == -1)
286 shift = 1;
287 if (start == -1)
288 start = 0;
289 if (len == -1)
290 len = iocur_top->len - start;
291
292 if (len+start > iocur_top->len) {
9ee7055c 293 dbprintf(_("length (%d) too large for data block size (%d)"),
2bd0ea18
NS
294 len, iocur_top->len);
295 }
296
297 base = (char *)iocur_top->data + start;
298
299 hold_region = xmalloc(shift);
300 memcpy(hold_region, base, shift);
301 memcpy(base, base+shift, len-shift);
302 memcpy(base+(len-shift), hold_region, shift);
355ac015 303 free(hold_region);
2bd0ea18
NS
304}
305
306/* ARGSUSED */
307static void
308bwrite_rrot(
309 int start,
310 int len,
311 int shift,
312 int from,
313 int to)
314{
315 char *base;
316 char *hold_region;
317
318 if (shift == -1)
319 shift = 1;
320 if (start == -1)
321 start = 0;
322 if (len == -1)
323 len = iocur_top->len - start;
324
325 if (len+start > iocur_top->len) {
9ee7055c 326 dbprintf(_("length (%d) too large for data block size (%d)"),
2bd0ea18
NS
327 len, iocur_top->len);
328 }
329
330 base = (char *)iocur_top->data + start;
331
332 hold_region = xmalloc(shift);
333 memcpy(hold_region, base+(len-shift), shift);
0e6b2a43 334 memmove(base+shift, base, len-shift);
2bd0ea18 335 memcpy(base, hold_region, shift);
355ac015 336 free(hold_region);
2bd0ea18
NS
337}
338
339/* ARGSUSED */
340static void
341bwrite_seq(
342 int start,
343 int len,
344 int step,
345 int from,
346 int to)
347{
348 int i;
349 int tmp;
350 int base;
351 int range;
352 int top;
0e6b2a43 353 char *buf;
2bd0ea18
NS
354
355 if (start == -1)
356 start = 0;
357
358 if (len == -1)
359 len = iocur_top->len - start;
360
361 if (len+start > iocur_top->len) {
9ee7055c 362 dbprintf(_("length (%d) too large for data block size (%d)"),
2bd0ea18
NS
363 len, iocur_top->len);
364 }
365
366 if (from == -1 || from > 255)
367 from = 0;
368 if (to == -1 || to > 255)
369 to = 255;
370 if (step == -1)
371 step = 1;
372
373 base = from;
374 top = to;
375 if (from > to) {
376 base = to;
377 top = from;
378 if (step > 0)
379 step = -step;
380 }
381
382 range = top - base;
0e6b2a43 383 buf = (char *)iocur_top->data + start;
2bd0ea18
NS
384
385 tmp = 0;
386 for (i = start; i < start+len; i++) {
387 *buf++ = tmp + base;
388 tmp = (tmp + step)%(range+1);
389 }
390}
391
392/* ARGSUSED */
393static void
394bwrite_random(
395 int start,
396 int len,
397 int shift,
398 int from,
399 int to)
400{
401 int i;
0e6b2a43 402 char *buf;
2bd0ea18
NS
403
404 if (start == -1)
405 start = 0;
406
407 if (len == -1)
408 len = iocur_top->len - start;
409
410 if (len+start > iocur_top->len) {
9ee7055c 411 dbprintf(_("length (%d) too large for data block size (%d)"),
2bd0ea18
NS
412 len, iocur_top->len);
413 }
414
0e6b2a43
NS
415 buf = (char *)iocur_top->data + start;
416
2bd0ea18
NS
417 for (i = start; i < start+len; i++)
418 *buf++ = (char)lrand48();
419}
420
421/* ARGSUSED */
422static void
423bwrite_fill(
424 int start,
425 int len,
426 int value,
427 int from,
428 int to)
429{
430 char *base;
431
432 if (value == -1)
433 value = 0;
434 if (start == -1)
435 start = 0;
436 if (len == -1)
437 len = iocur_top->len - start;
438
439 if (len+start > iocur_top->len) {
9ee7055c 440 dbprintf(_("length (%d) too large for data block size (%d)"),
2bd0ea18
NS
441 len, iocur_top->len);
442 }
443
444 base = (char *)iocur_top->data + start;
445
446 memset(base, value, len);
447}
448
449static struct bw_cmd {
450 void (*cmdfunc)(int,int,int,int,int);
451 char *cmdstr;
452 int sig_chars;
453 int argmin;
454 int argmax;
455 int shiftcount_arg;
456 int from_arg;
457 int to_arg;
458 int start_arg;
459 int len_arg;
460 char *usage;
461} bw_cmdtab[] = {
462 /* cmd sig min max sh frm to start len */
463 { bwrite_lshift, "lshift", 2, 0, 3, 1, 0, 0, 2, 3,
464 "[shiftcount] [start] [len]", },
465 { bwrite_rshift, "rshift", 2, 0, 3, 1, 0, 0, 2, 3,
466 "[shiftcount] [start] [len]", },
467 { bwrite_lrot, "lrot", 2, 0, 3, 1, 0, 0, 2, 3,
468 "[shiftcount] [start] [len]", },
469 { bwrite_rrot, "rrot", 2, 0, 3, 1, 0, 0, 2, 3,
470 "[shiftcount] [start] [len]", },
471 { bwrite_seq, "sequence", 3, 0, 4, 0, 1, 2, 3, 4,
472 "[from] [to] [start] [len]", },
473 { bwrite_random, "random", 3, 0, 2, 0, 0, 0, 1, 2,
474 "[start] [len]", },
475 { bwrite_fill, "fill", 1, 1, 3, 1, 0, 0, 2, 3,
476 "num [start] [len]" }
477};
478
479#define BWRITE_CMD_MAX (sizeof(bw_cmdtab)/sizeof(bw_cmdtab[0]))
480
481static int
482convert_oct(
483 char *arg,
484 int *ret)
485{
486 int count;
487 int i;
488 int val = 0;
489
490 /* only allow 1 case, '\' and 3 octal digits (or less) */
491
492 for (count = 0; count < 3; count++) {
493 if (arg[count] == '\0')
494 break;
495
496 if ((arg[count] < '0') && (arg[count] > '7'))
497 break;
498 }
499
500 for (i = 0; i < count; i++) {
501 val |= ((arg[(count-1)-i]-'0')&0x07)<<(i*3);
502 }
503
504 *ret = val&0xff;
505
506 return(count);
507}
508
509#define NYBBLE(x) (isdigit(x)?(x-'0'):(tolower(x)-'a'+0xa))
510
dc151328
MT
511/*
512 * convert_arg allows input in the following forms:
513 *
514 * - A string ("ABTB") whose ASCII value is placed in an array in the order
515 * matching the input.
516 *
517 * - An even number of hex numbers. If the length is greater than 64 bits,
518 * then the output is an array of bytes whose top nibble is the first hex
519 * digit in the input, the lower nibble is the second hex digit in the
520 * input. UUID entries are entered in this manner.
521 *
522 * - A decimal or hexadecimal integer to be used with setbitval().
523 *
524 * Numbers that are passed to setbitval() need to be in big endian format and
525 * are adjusted in the buffer so that the first input bit is to be be written to
526 * the first bit in the output.
527 */
2bd0ea18
NS
528static char *
529convert_arg(
dc151328
MT
530 char *arg,
531 int bit_length)
2bd0ea18 532{
dc151328
MT
533 int i;
534 int alloc_size;
535 int octval;
536 int offset;
537 int ret;
538 static char *buf = NULL;
539 char *endp;
540 char *rbuf;
541 char *ostr;
542 __u64 *value;
543 __u64 val = 0;
2bd0ea18
NS
544
545 if (bit_length <= 64)
546 alloc_size = 8;
547 else
dc151328 548 alloc_size = (bit_length + 7) / 8;
2bd0ea18
NS
549
550 buf = xrealloc(buf, alloc_size);
551 memset(buf, 0, alloc_size);
dc151328 552 value = (__u64 *)buf;
2bd0ea18
NS
553 rbuf = buf;
554
555 if (*arg == '\"') {
dc151328 556 /* input a string and output ASCII array of characters */
2bd0ea18
NS
557
558 /* zap closing quote if there is one */
dc151328
MT
559 ostr = strrchr(arg + 1, '\"');
560 if (ostr)
2bd0ea18
NS
561 *ostr = '\0';
562
dc151328 563 ostr = arg + 1;
2bd0ea18
NS
564 for (i = 0; i < alloc_size; i++) {
565 if (!*ostr)
566 break;
567
dc151328 568 /* do octal conversion */
2bd0ea18 569 if (*ostr == '\\') {
dc151328
MT
570 if (*(ostr + 1) >= '0' || *(ostr + 1) <= '7') {
571 ret = convert_oct(ostr + 1, &octval);
2bd0ea18 572 *rbuf++ = octval;
dc151328 573 ostr += ret + 1;
2bd0ea18
NS
574 continue;
575 }
576 }
577 *rbuf++ = *ostr++;
578 }
2bd0ea18 579 return buf;
dc151328
MT
580 }
581
582 if (arg[0] == '#' || ((arg[0] != '-') && strchr(arg,'-'))) {
dfc130f3
RC
583 /*
584 * handle hex blocks ie
585 * #00112233445566778899aabbccddeeff
586 * and uuids ie
587 * 1122334455667788-99aa-bbcc-ddee-ff00112233445566778899
75efd6ca
ES
588 *
589 * (but if it starts with "-" assume it's just an integer)
dfc130f3 590 */
dc151328
MT
591 int bytes = bit_length / NBBY;
592
593 /* is this an array of hec numbers? */
594 if (bit_length % NBBY)
595 return NULL;
dfc130f3
RC
596
597 /* skip leading hash */
dc151328
MT
598 if (*arg == '#')
599 arg++;
dfc130f3
RC
600
601 while (*arg && bytes--) {
dc151328
MT
602 /* skip hypens */
603 while (*arg == '-')
604 arg++;
605
606 /* get first nybble */
607 if (!isxdigit((int)*arg))
608 return NULL;
609 *rbuf = NYBBLE((int)*arg) << 4;
610 arg++;
611
612 /* skip more hyphens */
613 while (*arg == '-')
614 arg++;
615
616 /* get second nybble */
617 if (!isxdigit((int)*arg))
618 return NULL;
619 *rbuf++ |= NYBBLE((int)*arg);
620 arg++;
dfc130f3 621 }
dc151328
MT
622 if (bytes < 0 && *arg)
623 return NULL;
624
dfc130f3 625 return buf;
2bd0ea18 626 }
dc151328
MT
627
628 /* handle decimal / hexadecimal integers */
629 val = strtoll(arg, &endp, 0);
630 /* return if not a clean number */
631 if (*endp != '\0')
632 return NULL;
633
634 /* Does the value fit into the range of the destination bitfield? */
97ada363 635 if (bit_length < 64 && (val >> bit_length) > 0)
dc151328
MT
636 return NULL;
637 /*
638 * If the length of the field is not a multiple of a byte, push
639 * the bits up in the field, so the most signicant field bit is
640 * the most significant bit in the byte:
641 *
642 * before:
643 * val |----|----|----|----|----|--MM|mmmm|llll|
644 * after
645 * val |----|----|----|----|----|MMmm|mmll|ll00|
646 */
647 offset = bit_length % NBBY;
648 if (offset)
649 val <<= (NBBY - offset);
650
651 /*
652 * convert to big endian and copy into the array
653 * rbuf |----|----|----|----|----|MMmm|mmll|ll00|
654 */
655 *value = cpu_to_be64(val);
656
657 /*
658 * Align the array to point to the field in the array.
659 * rbuf = |MMmm|mmll|ll00|
660 */
661 offset = sizeof(__be64) - 1 - ((bit_length - 1) / sizeof(__be64));
662 rbuf += offset;
663 return rbuf;
2bd0ea18
NS
664}
665
666
667/* ARGSUSED */
668void
669write_struct(
670 const field_t *fields,
671 int argc,
672 char **argv)
673{
674 const ftattr_t *fa;
675 flist_t *fl;
dc151328
MT
676 flist_t *sfl;
677 int bit_length;
678 char *buf;
2bd0ea18
NS
679 int parentoffset;
680
681 if (argc != 2) {
9ee7055c 682 dbprintf(_("usage: write fieldname value\n"));
2bd0ea18
NS
683 return;
684 }
685
686 fl = flist_scan(argv[0]);
687 if (!fl) {
9ee7055c 688 dbprintf(_("unable to parse '%s'.\n"), argv[0]);
2bd0ea18
NS
689 return;
690 }
691
692 /* if we're a root field type, go down 1 layer to get field list */
693 if (fields->name[0] == '\0') {
694 fa = &ftattrtab[fields->ftyp];
695 ASSERT(fa->ftyp == fields->ftyp);
696 fields = fa->subfld;
697 }
698
699 /* run down the field list and set offsets into the data */
700 if (!flist_parse(fields, fl, iocur_top->data, 0)) {
701 flist_free(fl);
9ee7055c 702 dbprintf(_("parsing error\n"));
2bd0ea18
NS
703 return;
704 }
705
706 sfl = fl;
707 parentoffset = 0;
708 while (sfl->child) {
709 parentoffset = sfl->offset;
710 sfl = sfl->child;
711 }
712
4222d000
DC
713 /*
714 * For structures, fsize * fcount tells us the size of the region we are
715 * modifying, which is usually a single structure member and is pointed
716 * to by the last child in the list.
717 *
718 * However, if the base structure is an array and we have a direct index
719 * into the array (e.g. write bno[5]) then we are returned a single
720 * flist object with the offset pointing directly at the location we
721 * need to modify. The length of the object we are modifying is then
722 * determined by the size of the individual array entry (fsize) and the
723 * indexes defined in the object, not the overall size of the array
724 * (which is what fcount returns).
725 */
2bd0ea18 726 bit_length = fsize(sfl->fld, iocur_top->data, parentoffset, 0);
4222d000
DC
727 if (sfl->fld->flags & FLD_ARRAY)
728 bit_length *= sfl->high - sfl->low + 1;
729 else
730 bit_length *= fcount(sfl->fld, iocur_top->data, parentoffset);
2bd0ea18
NS
731
732 /* convert this to a generic conversion routine */
733 /* should be able to handle str, num, or even labels */
dfc130f3 734
2bd0ea18
NS
735 buf = convert_arg(argv[1], bit_length);
736 if (!buf) {
9ee7055c 737 dbprintf(_("unable to convert value '%s'.\n"), argv[1]);
9c1c2e32 738 flist_free(fl);
2bd0ea18
NS
739 return;
740 }
741
dfc130f3 742 setbitval(iocur_top->data, sfl->offset, bit_length, buf);
2bd0ea18
NS
743 write_cur();
744
745 flist_print(fl);
dfc130f3 746 print_flist(fl);
2bd0ea18
NS
747 flist_free(fl);
748}
749
750/* ARGSUSED */
751void
752write_string(
753 const field_t *fields,
754 int argc,
755 char **argv)
756{
757 char *buf;
758 int i;
759
760 if (argc != 1) {
9ee7055c 761 dbprintf(_("usage (in string mode): write \"string...\"\n"));
2bd0ea18
NS
762 return;
763 }
764
765 buf = convert_arg(argv[0], (int)((strlen(argv[0])+1)*8));
766 for (i = 0; i < iocur_top->len; i++) {
767 ((char *)iocur_top->data)[i] = *buf;
768 if (*buf++ == '\0')
769 break;
770 }
771
772 /* write back to disk */
773 write_cur();
774}
775
776/* ARGSUSED */
777void
778write_block(
779 const field_t *fields,
780 int argc,
781 char **argv)
782{
783 int i;
dfc130f3 784 int shiftcount = -1;
2bd0ea18
NS
785 int start = -1;
786 int len = -1;
787 int from = -1;
788 int to = -1;
789 struct bw_cmd *cmd = NULL;
790
791 if (argc <= 1 || argc > 5)
792 goto block_usage;
793
794 for (i = 0; i < BWRITE_CMD_MAX; i++) {
795 if (sigcmp(argv[0], bw_cmdtab[i].cmdstr,
796 bw_cmdtab[i].sig_chars)) {
797 cmd = &bw_cmdtab[i];
798 break;
799 }
800 }
801
802 if (!cmd) {
9ee7055c 803 dbprintf(_("write: invalid subcommand\n"));
2bd0ea18
NS
804 goto block_usage;
805 }
806
807 if ((argc < cmd->argmin + 1) || (argc > cmd->argmax + 1)) {
9ee7055c 808 dbprintf(_("write %s: invalid number of arguments\n"),
2bd0ea18
NS
809 cmd->cmdstr);
810 goto block_usage;
811 }
dfc130f3 812
2bd0ea18
NS
813 if (cmd->shiftcount_arg && (cmd->shiftcount_arg < argc))
814 shiftcount = (int)strtoul(argv[cmd->shiftcount_arg], NULL, 0);
815 if (cmd->start_arg && (cmd->start_arg < argc))
816 start = (int)strtoul(argv[cmd->start_arg], NULL, 0);
817 if (cmd->len_arg && (cmd->len_arg < argc))
818 len = (int)strtoul(argv[cmd->len_arg], NULL, 0);
819 if (cmd->from_arg && (cmd->len_arg < argc))
820 from = (int)strtoul(argv[cmd->from_arg], NULL, 0);
821 if (cmd->to_arg && (cmd->len_arg < argc))
822 to = (int)strtoul(argv[cmd->to_arg], NULL, 0);
823
824 cmd->cmdfunc(start, len, shiftcount, from, to);
825
826 /* write back to disk */
827 write_cur();
828 return;
829
830 block_usage:
831
9ee7055c 832 dbprintf(_("usage: write (in data mode)\n"));
2bd0ea18
NS
833 for (i = 0; i < BWRITE_CMD_MAX; i++) {
834 dbprintf(" %-9.9s %s\n",
835 bw_cmdtab[i].cmdstr, bw_cmdtab[i].usage);
836 }
837 dbprintf("\n");
838 return;
839}