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