]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/mmap.c
libxfs/linux.c: Replace use of ustat by stat
[thirdparty/xfsprogs-dev.git] / io / mmap.c
CommitLineData
48c46ee3 1/*
da23017d
NS
2 * Copyright (c) 2004-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
48c46ee3 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
48c46ee3
NS
7 * published by the Free Software Foundation.
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.
48c46ee3 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
48c46ee3
NS
17 */
18
6b803e5a
CH
19#include "command.h"
20#include "input.h"
48c46ee3
NS
21#include <sys/mman.h>
22#include <signal.h>
48c46ee3
NS
23#include "init.h"
24#include "io.h"
25
26static cmdinfo_t mmap_cmd;
27static cmdinfo_t mread_cmd;
28static cmdinfo_t msync_cmd;
29static cmdinfo_t munmap_cmd;
30static cmdinfo_t mwrite_cmd;
a49984b3 31#ifdef HAVE_MREMAP
4f20f6a3 32static cmdinfo_t mremap_cmd;
a49984b3 33#endif /* HAVE_MREMAP */
48c46ee3
NS
34
35mmap_region_t *maptable;
36int mapcount;
37mmap_region_t *mapping;
38
39static void
40print_mapping(
41 mmap_region_t *map,
42 int index,
43 int braces)
44{
45 unsigned char buffer[8] = { 0 };
46 int i;
47
48 static struct {
49 int prot;
50 int mode;
51 } *p, pflags[] = {
52 { PROT_READ, 'r' },
53 { PROT_WRITE, 'w' },
54 { PROT_EXEC, 'x' },
55 { PROT_NONE, 0 }
56 };
57
58 for (i = 0, p = pflags; p->prot != PROT_NONE; i++, p++)
59 buffer[i] = (map->prot & p->prot) ? p->mode : '-';
153563c4 60 printf("%c%03d%c 0x%lx - 0x%lx %s %14s (%lld : %ld)\n",
48c46ee3
NS
61 braces? '[' : ' ', index, braces? ']' : ' ',
62 (unsigned long)map->addr,
5ecb3de2 63 (unsigned long)((char *)map->addr + map->length),
48c46ee3
NS
64 buffer, map->name ? map->name : "???",
65 (long long)map->offset, (long)map->length);
66}
67
0bba1a49 68void *
48c46ee3
NS
69check_mapping_range(
70 mmap_region_t *map,
71 off64_t offset,
72 size_t length,
73 int pagealign)
74{
75 off64_t relative;
76
77 if (offset < mapping->offset) {
78 printf(_("offset (%lld) is before start of mapping (%lld)\n"),
79 (long long)offset, (long long)mapping->offset);
80 return NULL;
81 }
82 relative = offset - mapping->offset;
83 if (relative > mapping->length) {
84 printf(_("offset (%lld) is beyond end of mapping (%lld)\n"),
85 (long long)relative, (long long)mapping->offset);
86 return NULL;
87 }
88 if ((relative + length) > (mapping->offset + mapping->length)) {
89 printf(_("range (%lld:%lld) is beyond mapping (%lld:%ld)\n"),
90 (long long)offset, (long long)relative,
91 (long long)mapping->offset, (long)mapping->length);
92 return NULL;
93 }
5ecb3de2 94 if (pagealign && (long)((char *)mapping->addr + relative) % pagesize) {
48c46ee3 95 printf(_("offset address (%p) is not page aligned\n"),
5ecb3de2 96 (char *)mapping->addr + relative);
48c46ee3
NS
97 return NULL;
98 }
99
5ecb3de2 100 return (char *)mapping->addr + relative;
48c46ee3
NS
101}
102
103int
104maplist_f(void)
105{
106 int i;
107
108 for (i = 0; i < mapcount; i++)
109 print_mapping(&maptable[i], i, &maptable[i] == mapping);
110 return 0;
111}
112
113static int
114mapset_f(
115 int argc,
116 char **argv)
117{
118 int i;
119
120 ASSERT(argc == 2);
121 i = atoi(argv[1]);
122 if (i < 0 || i >= mapcount) {
123 printf("value %d is out of range (0-%d)\n", i, mapcount);
124 } else {
125 mapping = &maptable[i];
126 maplist_f();
127 }
128 return 0;
129}
130
131static void
132mmap_help(void)
133{
134 printf(_(
135"\n"
136" maps a range within the current file into memory\n"
137"\n"
138" Example:\n"
139" 'mmap -rw 0 1m' - maps one megabyte from the start of the current file\n"
140"\n"
141" Memory maps a range of a file for subsequent use by other xfs_io commands.\n"
142" With no arguments, mmap shows the current mappings. The current mapping\n"
143" can be set by using the single argument form (mapping number or address).\n"
144" If two arguments are specified (a range), a new mapping is created and the\n"
145" following options are available:\n"
146" -r -- map with PROT_READ protection\n"
147" -w -- map with PROT_WRITE protection\n"
148" -x -- map with PROT_EXEC protection\n"
e0a88082 149" -s <size> -- first do mmap(size)/munmap(size), try to reserve some free space\n"
48c46ee3
NS
150" If no protection mode is specified, all are used by default.\n"
151"\n"));
152}
153
154static int
155mmap_f(
156 int argc,
157 char **argv)
158{
159 off64_t offset;
e0a88082
ZL
160 ssize_t length = 0, length2 = 0;
161 void *address = NULL;
48c46ee3 162 char *filename;
2c2f6d79 163 size_t blocksize, sectsize;
48c46ee3
NS
164 int c, prot = 0;
165
166 if (argc == 1) {
167 if (mapping)
168 return maplist_f();
169 fprintf(stderr, file ?
f8149110 170 _("no mapped regions, try 'help mmap'\n") :
48c46ee3
NS
171 _("no files are open, try 'help open'\n"));
172 return 0;
173 } else if (argc == 2) {
174 if (mapping)
175 return mapset_f(argc, argv);
176 fprintf(stderr, file ?
177 _("no mapped regions, try 'help mmap'\n") :
178 _("no files are open, try 'help open'\n"));
179 return 0;
180 } else if (!file) {
181 fprintf(stderr, _("no files are open, try 'help open'\n"));
182 return 0;
183 }
184
e0a88082
ZL
185 init_cvtnum(&blocksize, &sectsize);
186
187 while ((c = getopt(argc, argv, "rwxs:")) != EOF) {
48c46ee3
NS
188 switch (c) {
189 case 'r':
190 prot |= PROT_READ;
191 break;
192 case 'w':
193 prot |= PROT_WRITE;
194 break;
195 case 'x':
196 prot |= PROT_EXEC;
197 break;
e0a88082
ZL
198 case 's':
199 length2 = cvtnum(blocksize, sectsize, optarg);
200 break;
48c46ee3
NS
201 default:
202 return command_usage(&mmap_cmd);
203 }
204 }
205 if (!prot)
206 prot = PROT_READ | PROT_WRITE | PROT_EXEC;
207
208 if (optind != argc - 2)
209 return command_usage(&mmap_cmd);
210
48c46ee3
NS
211 offset = cvtnum(blocksize, sectsize, argv[optind]);
212 if (offset < 0) {
213 printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
214 return 0;
215 }
216 optind++;
217 length = cvtnum(blocksize, sectsize, argv[optind]);
218 if (length < 0) {
219 printf(_("non-numeric length argument -- %s\n"), argv[optind]);
220 return 0;
221 }
222
223 filename = strdup(file->name);
224 if (!filename) {
225 perror("strdup");
226 return 0;
227 }
228
e0a88082
ZL
229 /*
230 * mmap and munmap memory area of length2 region is helpful to
231 * make a region of extendible free memory. It's generally used
232 * for later mremap operation(no MREMAP_MAYMOVE flag). But there
233 * isn't guarantee that the memory after length (up to length2)
234 * will stay free.
235 */
236 if (length2 > length) {
237 address = mmap(NULL, length2, prot,
238 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
239 munmap(address, length2);
240 }
241 address = mmap(address, length, prot, MAP_SHARED, file->fd, offset);
48c46ee3
NS
242 if (address == MAP_FAILED) {
243 perror("mmap");
244 free(filename);
245 return 0;
246 }
247
248 /* Extend the control array of mmap'd regions */
249 maptable = (mmap_region_t *)realloc(maptable, /* growing */
250 ++mapcount * sizeof(mmap_region_t));
251 if (!maptable) {
252 perror("realloc");
253 mapcount = 0;
254 munmap(address, length);
255 free(filename);
256 return 0;
257 }
258
259 /* Finally, make this the new active mapping */
260 mapping = &maptable[mapcount - 1];
261 mapping->addr = address;
262 mapping->length = length;
263 mapping->offset = offset;
264 mapping->name = filename;
265 mapping->prot = prot;
266 return 0;
267}
268
269static void
270msync_help(void)
271{
272 printf(_(
273"\n"
274" flushes a range of bytes in the current memory mapping\n"
275"\n"
276" Writes all modified copies of pages over the specified range (or entire\n"
277" mapping if no range specified) to their backing storage locations. Also,\n"
278" optionally invalidates so that subsequent references to the pages will be\n"
279" obtained from their backing storage locations (instead of cached copies).\n"
280" -a -- perform asynchronous writes (MS_ASYNC)\n"
281" -i -- invalidate mapped pages (MS_INVALIDATE)\n"
282" -s -- perform synchronous writes (MS_SYNC)\n"
283"\n"));
284}
285
286int
287msync_f(
288 int argc,
289 char **argv)
290{
291 off64_t offset;
5ecb3de2 292 ssize_t length;
48c46ee3 293 void *start;
cb7ba2b0 294 int c, flags = 0;
2c2f6d79 295 size_t blocksize, sectsize;
48c46ee3
NS
296
297 while ((c = getopt(argc, argv, "ais")) != EOF) {
298 switch (c) {
299 case 'a':
300 flags |= MS_ASYNC;
301 break;
302 case 'i':
303 flags |= MS_INVALIDATE;
304 break;
305 case 's':
306 flags |= MS_SYNC;
307 break;
308 default:
309 return command_usage(&msync_cmd);
310 }
311 }
312
313 if (optind == argc) {
314 offset = mapping->offset;
315 length = mapping->length;
316 } else if (optind == argc - 2) {
317 init_cvtnum(&blocksize, &sectsize);
318 offset = cvtnum(blocksize, sectsize, argv[optind]);
319 if (offset < 0) {
320 printf(_("non-numeric offset argument -- %s\n"),
321 argv[optind]);
322 return 0;
323 }
324 optind++;
325 length = cvtnum(blocksize, sectsize, argv[optind]);
326 if (length < 0) {
327 printf(_("non-numeric length argument -- %s\n"),
328 argv[optind]);
329 return 0;
330 }
331 } else {
332 return command_usage(&msync_cmd);
333 }
334
335 start = check_mapping_range(mapping, offset, length, 1);
336 if (!start)
337 return 0;
338
339 if (msync(start, length, flags) < 0)
340 perror("msync");
341
342 return 0;
343}
344
48c46ee3
NS
345static void
346mread_help(void)
347{
348 printf(_(
349"\n"
350" reads a range of bytes in the current memory mapping\n"
351"\n"
352" Example:\n"
353" 'mread -v 512 20' - dumps 20 bytes read from 512 bytes into the mapping\n"
354"\n"
355" Accesses a range of the current memory mapping, optionally dumping it to\n"
356" the standard output stream (with -v option) for subsequent inspection.\n"
357" -f -- verbose mode, dump bytes with offsets relative to start of file.\n"
ff1f79a7 358" -r -- reverse order; start accessing from the end of range, moving backward\n"
48c46ee3
NS
359" -v -- verbose mode, dump bytes with offsets relative to start of mapping.\n"
360" The accesses are performed sequentially from the start offset by default.\n"
361" Notes:\n"
362" References to whole pages following the end of the backing file results\n"
363" in delivery of the SIGBUS signal. SIGBUS signals may also be delivered\n"
364" on various filesystem conditions, including quota exceeded errors, and\n"
365" for physical device errors (such as unreadable disk blocks). No attempt\n"
366" has been made to catch signals at this stage...\n"
367"\n"));
368}
369
370int
371mread_f(
372 int argc,
373 char **argv)
374{
8e192991 375 off64_t offset, tmp, dumpoffset, printoffset;
5ecb3de2 376 ssize_t length;
8e192991 377 size_t dumplen, cnt = 0;
48c46ee3
NS
378 char *bp;
379 void *start;
cb7ba2b0 380 int dump = 0, rflag = 0, c;
2c2f6d79 381 size_t blocksize, sectsize;
48c46ee3
NS
382
383 while ((c = getopt(argc, argv, "frv")) != EOF) {
384 switch (c) {
385 case 'f':
386 dump = 2; /* file offset dump */
387 break;
388 case 'r':
389 rflag = 1; /* read in reverse */
390 break;
391 case 'v':
392 dump = 1; /* mapping offset dump */
393 break;
394 default:
395 return command_usage(&mread_cmd);
396 }
397 }
398
399 if (optind == argc) {
400 offset = mapping->offset;
401 length = mapping->length;
402 } else if (optind == argc - 2) {
403 init_cvtnum(&blocksize, &sectsize);
404 offset = cvtnum(blocksize, sectsize, argv[optind]);
405 if (offset < 0) {
406 printf(_("non-numeric offset argument -- %s\n"),
407 argv[optind]);
408 return 0;
409 }
410 optind++;
411 length = cvtnum(blocksize, sectsize, argv[optind]);
412 if (length < 0) {
413 printf(_("non-numeric length argument -- %s\n"),
414 argv[optind]);
415 return 0;
416 }
417 } else {
418 return command_usage(&mread_cmd);
419 }
420
421 start = check_mapping_range(mapping, offset, length, 0);
422 if (!start)
423 return 0;
8e192991
BN
424 dumpoffset = offset - mapping->offset;
425 if (dump == 2)
426 printoffset = offset;
427 else
428 printoffset = dumpoffset;
48c46ee3
NS
429
430 if (alloc_buffer(pagesize, 0, 0) < 0)
431 return 0;
432 bp = (char *)buffer;
433
434 dumplen = length % pagesize;
435 if (!dumplen)
436 dumplen = pagesize;
437
438 if (rflag) {
8e192991
BN
439 for (tmp = length - 1, c = 0; tmp >= 0; tmp--, c = 1) {
440 *bp = *(((char *)mapping->addr) + dumpoffset + tmp);
441 cnt++;
442 if (c && cnt == dumplen) {
443 if (dump) {
444 dump_buffer(printoffset, dumplen);
445 printoffset += dumplen;
446 }
48c46ee3
NS
447 bp = (char *)buffer;
448 dumplen = pagesize;
8e192991
BN
449 cnt = 0;
450 } else {
451 bp++;
48c46ee3 452 }
8e192991 453 }
48c46ee3 454 } else {
8e192991
BN
455 for (tmp = 0, c = 0; tmp < length; tmp++, c = 1) {
456 *bp = *(((char *)mapping->addr) + dumpoffset + tmp);
457 cnt++;
458 if (c && cnt == dumplen) {
459 if (dump)
460 dump_buffer(printoffset + tmp -
461 (dumplen - 1), dumplen);
48c46ee3
NS
462 bp = (char *)buffer;
463 dumplen = pagesize;
8e192991
BN
464 cnt = 0;
465 } else {
466 bp++;
48c46ee3 467 }
48c46ee3
NS
468 }
469 }
470 return 0;
471}
472
473int
474munmap_f(
475 int argc,
476 char **argv)
477{
5ecb3de2 478 ssize_t length;
48c46ee3
NS
479 unsigned int offset;
480
481 if (munmap(mapping->addr, mapping->length) < 0) {
482 perror("munmap");
483 return 0;
484 }
485 free(mapping->name);
486
487 /* Shuffle the mapping table entries down over the removed entry */
488 offset = mapping - &maptable[0];
489 length = mapcount * sizeof(mmap_region_t);
490 length -= (offset + 1) * sizeof(mmap_region_t);
491 if (length)
492 memmove(mapping, mapping + 1, length);
493
494 /* Resize the memory allocated for the table, possibly freeing */
495 if (--mapcount) {
496 maptable = (mmap_region_t *)realloc(maptable, /* shrinking */
497 mapcount * sizeof(mmap_region_t));
498 if (offset == mapcount)
499 offset--;
500 mapping = maptable + offset;
501 } else {
502 free(maptable);
503 mapping = maptable = NULL;
504 }
505 maplist_f();
506 return 0;
507}
508
509static void
510mwrite_help(void)
511{
512 printf(_(
513"\n"
514" dirties a range of bytes in the current memory mapping\n"
515"\n"
516" Example:\n"
517" 'mwrite 512 20 - writes 20 bytes at 512 bytes into the current mapping.\n"
518"\n"
519" Stores a byte into memory for a range within a mapping.\n"
520" The default stored value is 'X', repeated to fill the range specified.\n"
521" -S -- use an alternate seed character\n"
ff1f79a7 522" -r -- reverse order; start storing from the end of range, moving backward\n"
48c46ee3
NS
523" The stores are performed sequentially from the start offset by default.\n"
524"\n"));
525}
526
527int
528mwrite_f(
529 int argc,
530 char **argv)
531{
532 off64_t offset, tmp;
5ecb3de2 533 ssize_t length;
48c46ee3
NS
534 void *start;
535 char *sp;
536 int seed = 'X';
537 int rflag = 0;
cb7ba2b0 538 int c;
2c2f6d79 539 size_t blocksize, sectsize;
48c46ee3
NS
540
541 while ((c = getopt(argc, argv, "rS:")) != EOF) {
542 switch (c) {
543 case 'r':
544 rflag = 1;
545 break;
546 case 'S':
547 seed = (int)strtol(optarg, &sp, 0);
548 if (!sp || sp == optarg) {
549 printf(_("non-numeric seed -- %s\n"), optarg);
550 return 0;
551 }
552 break;
553 default:
554 return command_usage(&mwrite_cmd);
555 }
556 }
557
558 if (optind == argc) {
559 offset = mapping->offset;
560 length = mapping->length;
561 } else if (optind == argc - 2) {
562 init_cvtnum(&blocksize, &sectsize);
563 offset = cvtnum(blocksize, sectsize, argv[optind]);
564 if (offset < 0) {
565 printf(_("non-numeric offset argument -- %s\n"),
566 argv[optind]);
567 return 0;
568 }
569 optind++;
570 length = cvtnum(blocksize, sectsize, argv[optind]);
571 if (length < 0) {
572 printf(_("non-numeric length argument -- %s\n"),
573 argv[optind]);
574 return 0;
575 }
576 } else {
577 return command_usage(&mwrite_cmd);
578 }
579
580 start = check_mapping_range(mapping, offset, length, 0);
581 if (!start)
582 return 0;
583
f0911c29 584 offset -= mapping->offset;
48c46ee3 585 if (rflag) {
8e192991 586 for (tmp = offset + length -1; tmp >= offset; tmp--)
48c46ee3
NS
587 ((char *)mapping->addr)[tmp] = seed;
588 } else {
589 for (tmp = offset; tmp < offset + length; tmp++)
590 ((char *)mapping->addr)[tmp] = seed;
591 }
592
593 return 0;
594}
595
a49984b3 596#ifdef HAVE_MREMAP
4f20f6a3
ES
597static void
598mremap_help(void)
599{
600 printf(_(
601"\n"
602" resizes the current memory mapping\n"
603"\n"
604" Examples:\n"
605" 'mremap 8192' - resizes the current mapping to 8192 bytes.\n"
606"\n"
607" Resizes the mappping, growing or shrinking from the current size.\n"
608" The default stored value is 'X', repeated to fill the range specified.\n"
6f224a2c 609" -f <new_address> -- use MREMAP_FIXED flag to mremap on new_address\n"
4f20f6a3
ES
610" -m -- use the MREMAP_MAYMOVE flag\n"
611"\n"));
612}
613
614int
615mremap_f(
616 int argc,
617 char **argv)
618{
619 ssize_t new_length;
6f224a2c 620 void *new_addr = NULL;
4f20f6a3
ES
621 int flags = 0;
622 int c;
623 size_t blocksize, sectsize;
624
6f224a2c
ZL
625 init_cvtnum(&blocksize, &sectsize);
626
627 while ((c = getopt(argc, argv, "f:m")) != EOF) {
4f20f6a3
ES
628 switch (c) {
629 case 'f':
630 flags = MREMAP_FIXED|MREMAP_MAYMOVE;
6f224a2c
ZL
631 new_addr = (void *)cvtnum(blocksize, sectsize,
632 optarg);
4f20f6a3
ES
633 break;
634 case 'm':
635 flags = MREMAP_MAYMOVE;
636 break;
637 default:
638 return command_usage(&mremap_cmd);
639 }
640 }
641
6f224a2c
ZL
642 if (optind != argc - 1)
643 return command_usage(&mremap_cmd);
644
4f20f6a3
ES
645 new_length = cvtnum(blocksize, sectsize, argv[optind]);
646 if (new_length < 0) {
647 printf(_("non-numeric offset argument -- %s\n"),
648 argv[optind]);
649 return 0;
650 }
651
6f224a2c
ZL
652 if (!new_addr)
653 new_addr = mremap(mapping->addr, mapping->length,
654 new_length, flags);
655 else
656 new_addr = mremap(mapping->addr, mapping->length,
657 new_length, flags, new_addr);
4f20f6a3
ES
658 if (new_addr == MAP_FAILED)
659 perror("mremap");
660 else {
661 mapping->addr = new_addr;
662 mapping->length = new_length;
663 }
664
665 return 0;
666}
a49984b3 667#endif /* HAVE_MREMAP */
4f20f6a3 668
48c46ee3
NS
669void
670mmap_init(void)
671{
ad765595
AM
672 mmap_cmd.name = "mmap";
673 mmap_cmd.altname = "mm";
48c46ee3
NS
674 mmap_cmd.cfunc = mmap_f;
675 mmap_cmd.argmin = 0;
676 mmap_cmd.argmax = -1;
677 mmap_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK;
e0a88082 678 mmap_cmd.args = _("[N] | [-rwx] [-s size] [off len]");
48c46ee3
NS
679 mmap_cmd.oneline =
680 _("mmap a range in the current file, show mappings");
681 mmap_cmd.help = mmap_help;
682
ad765595
AM
683 mread_cmd.name = "mread";
684 mread_cmd.altname = "mr";
48c46ee3
NS
685 mread_cmd.cfunc = mread_f;
686 mread_cmd.argmin = 0;
687 mread_cmd.argmax = -1;
688 mread_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
689 mread_cmd.args = _("[-r] [off len]");
690 mread_cmd.oneline =
691 _("reads data from a region in the current memory mapping");
692 mread_cmd.help = mread_help;
693
ad765595
AM
694 msync_cmd.name = "msync";
695 msync_cmd.altname = "ms";
48c46ee3
NS
696 msync_cmd.cfunc = msync_f;
697 msync_cmd.argmin = 0;
698 msync_cmd.argmax = -1;
699 msync_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
700 msync_cmd.args = _("[-ais] [off len]");
701 msync_cmd.oneline = _("flush a region in the current memory mapping");
702 msync_cmd.help = msync_help;
703
ad765595
AM
704 munmap_cmd.name = "munmap";
705 munmap_cmd.altname = "mu";
48c46ee3
NS
706 munmap_cmd.cfunc = munmap_f;
707 munmap_cmd.argmin = 0;
708 munmap_cmd.argmax = 0;
709 munmap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
710 munmap_cmd.oneline = _("unmaps the current memory mapping");
711
ad765595
AM
712 mwrite_cmd.name = "mwrite";
713 mwrite_cmd.altname = "mw";
48c46ee3
NS
714 mwrite_cmd.cfunc = mwrite_f;
715 mwrite_cmd.argmin = 0;
716 mwrite_cmd.argmax = -1;
717 mwrite_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
718 mwrite_cmd.args = _("[-r] [-S seed] [off len]");
719 mwrite_cmd.oneline =
720 _("writes data into a region in the current memory mapping");
721 mwrite_cmd.help = mwrite_help;
722
a49984b3 723#ifdef HAVE_MREMAP
4f20f6a3
ES
724 mremap_cmd.name = "mremap";
725 mremap_cmd.altname = "mrm";
726 mremap_cmd.cfunc = mremap_f;
727 mremap_cmd.argmin = 1;
6f224a2c 728 mremap_cmd.argmax = 3;
4f20f6a3 729 mremap_cmd.flags = CMD_NOFILE_OK | CMD_FOREIGN_OK;
6f224a2c 730 mremap_cmd.args = _("[-m|-f <new_address>] newsize");
4f20f6a3
ES
731 mremap_cmd.oneline =
732 _("alters the size of the current memory mapping");
733 mremap_cmd.help = mremap_help;
a49984b3 734#endif /* HAVE_MREMAP */
4f20f6a3 735
48c46ee3
NS
736 add_command(&mmap_cmd);
737 add_command(&mread_cmd);
738 add_command(&msync_cmd);
739 add_command(&munmap_cmd);
740 add_command(&mwrite_cmd);
a49984b3 741#ifdef HAVE_MREMAP
4f20f6a3 742 add_command(&mremap_cmd);
a49984b3 743#endif /* HAVE_MREMAP */
48c46ee3 744}