* gdb/fileio.h: New file.
[deliverable/binutils-gdb.git] / gdb / linux-proc.c
CommitLineData
ca557f44
AC
1/* GNU/Linux specific methods for using the /proc file system.
2
be4d1333 3 Copyright 2001, 2002 Free Software Foundation, Inc.
4b09dc8c
MS
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22#include "defs.h"
be4d1333 23#include "inferior.h"
6949171e
JJ
24#include <sys/param.h> /* for MAXPATHLEN */
25#include <sys/procfs.h> /* for elf_gregset etc. */
26#include "gdb_stat.h" /* for struct stat */
27#include <ctype.h> /* for isdigit */
28#include <unistd.h> /* for open, pread64 */
29#include <fcntl.h> /* for O_RDONLY */
30#include "regcache.h" /* for registers_changed */
31#include "gregset.h" /* for gregset */
32#include "gdbcore.h" /* for get_exec_file */
33#include "gdbthread.h" /* for struct thread_info etc. */
34#include "elf-bfd.h" /* for elfcore_write_* */
2bf543a6 35#include "cli/cli-decode.h" /* for add_info */
ff5922b5 36#include "gdb_string.h"
be4d1333 37
eb784848
DJ
38#ifndef O_LARGEFILE
39#define O_LARGEFILE 0
40#endif
41
be4d1333
MS
42/* Function: child_pid_to_exec_file
43 *
44 * Accepts an integer pid
45 * Returns a string representing a file that can be opened
46 * to get the symbols for the child process.
47 */
4b09dc8c
MS
48
49char *
50child_pid_to_exec_file (int pid)
51{
145fdc6e 52 char *name1, *name2;
4b09dc8c 53
145fdc6e
MS
54 name1 = xmalloc (MAXPATHLEN);
55 name2 = xmalloc (MAXPATHLEN);
56 make_cleanup (xfree, name1);
57 make_cleanup (xfree, name2);
58 memset (name2, 0, MAXPATHLEN);
59
60 sprintf (name1, "/proc/%d/exe", pid);
61 if (readlink (name1, name2, MAXPATHLEN) > 0)
62 return name2;
63 else
64 return name1;
4b09dc8c 65}
be4d1333 66
2bf543a6
MS
67/* Function: read_mappings
68 *
69 * Service function for corefiles and info proc.
70 */
71
6949171e
JJ
72static int
73read_mapping (FILE *mapfile,
74 long long *addr,
75 long long *endaddr,
76 char *permissions,
77 long long *offset,
78 char *device, long long *inode, char *filename)
2bf543a6 79{
6949171e 80 int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx",
2bf543a6
MS
81 addr, endaddr, permissions, offset, device, inode);
82
83 if (ret > 0 && ret != EOF && *inode != 0)
84 {
ee677e8d 85 /* Eat everything up to EOL for the filename. This will prevent
6949171e
JJ
86 weird filenames (such as one with embedded whitespace) from
87 confusing this code. It also makes this code more robust
88 in respect to annotations the kernel may add after the
89 filename.
ee677e8d 90
6949171e 91 Note the filename is used for informational purposes only. */
ee677e8d 92 ret += fscanf (mapfile, "%[^\n]\n", filename);
2bf543a6
MS
93 }
94 else
95 {
96 filename[0] = '\0'; /* no filename */
97 fscanf (mapfile, "\n");
98 }
99 return (ret != 0 && ret != EOF);
100}
101
be4d1333
MS
102/* Function: linux_find_memory_regions
103 *
104 * Fills the "to_find_memory_regions" target vector.
105 * Lists the memory regions in the inferior for a corefile.
106 */
107
108static int
6949171e 109linux_find_memory_regions (int (*func) (CORE_ADDR,
be4d1333 110 unsigned long,
6949171e 111 int, int, int, void *), void *obfd)
be4d1333
MS
112{
113 long long pid = PIDGET (inferior_ptid);
2bf543a6
MS
114 char mapsfilename[MAXPATHLEN];
115 FILE *mapsfile;
be4d1333 116 long long addr, endaddr, size, offset, inode;
2bf543a6 117 char permissions[8], device[8], filename[MAXPATHLEN];
be4d1333
MS
118 int read, write, exec;
119 int ret;
120
121 /* Compose the filename for the /proc memory map, and open it. */
2bf543a6
MS
122 sprintf (mapsfilename, "/proc/%lld/maps", pid);
123 if ((mapsfile = fopen (mapsfilename, "r")) == NULL)
124 error ("Could not open %s\n", mapsfilename);
be4d1333
MS
125
126 if (info_verbose)
6949171e 127 fprintf_filtered (gdb_stdout,
2bf543a6 128 "Reading memory regions from %s\n", mapsfilename);
be4d1333
MS
129
130 /* Now iterate until end-of-file. */
6949171e 131 while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0],
2bf543a6 132 &offset, &device[0], &inode, &filename[0]))
be4d1333
MS
133 {
134 size = endaddr - addr;
135
136 /* Get the segment's permissions. */
6949171e 137 read = (strchr (permissions, 'r') != 0);
2bf543a6 138 write = (strchr (permissions, 'w') != 0);
6949171e 139 exec = (strchr (permissions, 'x') != 0);
be4d1333
MS
140
141 if (info_verbose)
142 {
6949171e
JJ
143 fprintf_filtered (gdb_stdout,
144 "Save segment, %lld bytes at 0x%s (%c%c%c)",
145 size, paddr_nz (addr),
146 read ? 'r' : ' ',
147 write ? 'w' : ' ', exec ? 'x' : ' ');
be4d1333 148 if (filename && filename[0])
6949171e 149 fprintf_filtered (gdb_stdout, " for %s", filename);
be4d1333
MS
150 fprintf_filtered (gdb_stdout, "\n");
151 }
152
153 /* Invoke the callback function to create the corefile segment. */
154 func (addr, size, read, write, exec, obfd);
be4d1333 155 }
2bf543a6 156 fclose (mapsfile);
be4d1333
MS
157 return 0;
158}
159
160/* Function: linux_do_thread_registers
161 *
162 * Records the thread's register state for the corefile note section.
163 */
164
165static char *
6949171e 166linux_do_thread_registers (bfd *obfd, ptid_t ptid,
be4d1333
MS
167 char *note_data, int *note_size)
168{
169 gdb_gregset_t gregs;
170 gdb_fpregset_t fpregs;
32872fa7
DJ
171#ifdef FILL_FPXREGSET
172 gdb_fpxregset_t fpxregs;
173#endif
be4d1333
MS
174 unsigned long merged_pid = ptid_get_tid (ptid) << 16 | ptid_get_pid (ptid);
175
176 fill_gregset (&gregs, -1);
6949171e
JJ
177 note_data = (char *) elfcore_write_prstatus (obfd,
178 note_data,
179 note_size,
180 merged_pid,
181 stop_signal, &gregs);
be4d1333
MS
182
183 fill_fpregset (&fpregs, -1);
6949171e
JJ
184 note_data = (char *) elfcore_write_prfpreg (obfd,
185 note_data,
186 note_size,
187 &fpregs, sizeof (fpregs));
32872fa7
DJ
188#ifdef FILL_FPXREGSET
189 fill_fpxregset (&fpxregs, -1);
6949171e
JJ
190 note_data = (char *) elfcore_write_prxfpreg (obfd,
191 note_data,
192 note_size,
193 &fpxregs, sizeof (fpxregs));
32872fa7 194#endif
be4d1333
MS
195 return note_data;
196}
197
8acc2935
MK
198struct linux_corefile_thread_data
199{
200 bfd *obfd;
be4d1333 201 char *note_data;
8acc2935
MK
202 int *note_size;
203 int num_notes;
be4d1333
MS
204};
205
206/* Function: linux_corefile_thread_callback
207 *
208 * Called by gdbthread.c once per thread.
209 * Records the thread's register state for the corefile note section.
210 */
211
212static int
213linux_corefile_thread_callback (struct thread_info *ti, void *data)
214{
215 struct linux_corefile_thread_data *args = data;
216 ptid_t saved_ptid = inferior_ptid;
217
218 inferior_ptid = ti->ptid;
219 registers_changed ();
220 target_fetch_registers (-1); /* FIXME should not be necessary;
221 fill_gregset should do it automatically. */
6949171e
JJ
222 args->note_data = linux_do_thread_registers (args->obfd,
223 ti->ptid,
224 args->note_data,
be4d1333 225 args->note_size);
8acc2935 226 args->num_notes++;
be4d1333
MS
227 inferior_ptid = saved_ptid;
228 registers_changed ();
229 target_fetch_registers (-1); /* FIXME should not be necessary;
230 fill_gregset should do it automatically. */
231 return 0;
232}
233
234/* Function: linux_make_note_section
235 *
236 * Fills the "to_make_corefile_note" target vector.
237 * Builds the note section for a corefile, and returns it
238 * in a malloc buffer.
239 */
240
241static char *
242linux_make_note_section (bfd *obfd, int *note_size)
243{
244 struct linux_corefile_thread_data thread_args;
245 struct cleanup *old_chain;
6949171e
JJ
246 char fname[16] = { '\0' };
247 char psargs[80] = { '\0' };
be4d1333
MS
248 char *note_data = NULL;
249 ptid_t current_ptid = inferior_ptid;
250
251 if (get_exec_file (0))
252 {
253 strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
6949171e 254 strncpy (psargs, get_exec_file (0), sizeof (psargs));
be4d1333
MS
255 if (get_inferior_args ())
256 {
6949171e
JJ
257 strncat (psargs, " ", sizeof (psargs) - strlen (psargs));
258 strncat (psargs, get_inferior_args (),
be4d1333
MS
259 sizeof (psargs) - strlen (psargs));
260 }
6949171e
JJ
261 note_data = (char *) elfcore_write_prpsinfo (obfd,
262 note_data,
263 note_size, fname, psargs);
be4d1333
MS
264 }
265
266 /* Dump information for threads. */
267 thread_args.obfd = obfd;
268 thread_args.note_data = note_data;
269 thread_args.note_size = note_size;
8acc2935 270 thread_args.num_notes = 0;
be4d1333 271 iterate_over_threads (linux_corefile_thread_callback, &thread_args);
8acc2935 272 if (thread_args.num_notes == 0)
be4d1333
MS
273 {
274 /* iterate_over_threads didn't come up with any threads;
6949171e
JJ
275 just use inferior_ptid. */
276 note_data = linux_do_thread_registers (obfd, inferior_ptid,
be4d1333
MS
277 note_data, note_size);
278 }
279 else
280 {
281 note_data = thread_args.note_data;
282 }
283
284 make_cleanup (xfree, note_data);
285 return note_data;
286}
287
2bf543a6
MS
288/*
289 * Function: linux_info_proc_cmd
290 *
291 * Implement the "info proc" command.
292 */
293
294static void
295linux_info_proc_cmd (char *args, int from_tty)
296{
297 long long pid = PIDGET (inferior_ptid);
298 FILE *procfile;
299 char **argv = NULL;
300 char buffer[MAXPATHLEN];
301 char fname1[MAXPATHLEN], fname2[MAXPATHLEN];
302 int cmdline_f = 1;
303 int cwd_f = 1;
304 int exe_f = 1;
305 int mappings_f = 0;
306 int environ_f = 0;
307 int status_f = 0;
308 int stat_f = 0;
309 int all = 0;
310 struct stat dummy;
311
312 if (args)
313 {
314 /* Break up 'args' into an argv array. */
315 if ((argv = buildargv (args)) == NULL)
316 nomem (0);
317 else
318 make_cleanup_freeargv (argv);
319 }
320 while (argv != NULL && *argv != NULL)
321 {
322 if (isdigit (argv[0][0]))
323 {
324 pid = strtoul (argv[0], NULL, 10);
325 }
326 else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0)
327 {
328 mappings_f = 1;
329 }
330 else if (strcmp (argv[0], "status") == 0)
331 {
332 status_f = 1;
333 }
334 else if (strcmp (argv[0], "stat") == 0)
335 {
336 stat_f = 1;
337 }
338 else if (strcmp (argv[0], "cmd") == 0)
339 {
340 cmdline_f = 1;
341 }
342 else if (strncmp (argv[0], "exe", strlen (argv[0])) == 0)
343 {
344 exe_f = 1;
345 }
346 else if (strcmp (argv[0], "cwd") == 0)
347 {
348 cwd_f = 1;
349 }
350 else if (strncmp (argv[0], "all", strlen (argv[0])) == 0)
351 {
352 all = 1;
353 }
354 else
355 {
356 /* [...] (future options here) */
357 }
358 argv++;
359 }
360 if (pid == 0)
361 error ("No current process: you must name one.");
362
363 sprintf (fname1, "/proc/%lld", pid);
364 if (stat (fname1, &dummy) != 0)
365 error ("No /proc directory: '%s'", fname1);
366
367 printf_filtered ("process %lld\n", pid);
368 if (cmdline_f || all)
369 {
370 sprintf (fname1, "/proc/%lld/cmdline", pid);
371 if ((procfile = fopen (fname1, "r")) > 0)
372 {
373 fgets (buffer, sizeof (buffer), procfile);
374 printf_filtered ("cmdline = '%s'\n", buffer);
375 fclose (procfile);
376 }
377 else
378 warning ("unable to open /proc file '%s'", fname1);
379 }
380 if (cwd_f || all)
381 {
382 sprintf (fname1, "/proc/%lld/cwd", pid);
383 memset (fname2, 0, sizeof (fname2));
384 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
385 printf_filtered ("cwd = '%s'\n", fname2);
386 else
387 warning ("unable to read link '%s'", fname1);
388 }
389 if (exe_f || all)
390 {
391 sprintf (fname1, "/proc/%lld/exe", pid);
392 memset (fname2, 0, sizeof (fname2));
393 if (readlink (fname1, fname2, sizeof (fname2)) > 0)
394 printf_filtered ("exe = '%s'\n", fname2);
395 else
396 warning ("unable to read link '%s'", fname1);
397 }
398 if (mappings_f || all)
399 {
400 sprintf (fname1, "/proc/%lld/maps", pid);
401 if ((procfile = fopen (fname1, "r")) > 0)
402 {
403 long long addr, endaddr, size, offset, inode;
404 char permissions[8], device[8], filename[MAXPATHLEN];
405 char *header_fmt_string, *data_fmt_string;
406
407 if (TARGET_ADDR_BIT == 32)
408 {
409 header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
6949171e 410 data_fmt_string = "\t%#10lx %#10lx %#10x %#10x %7s\n";
2bf543a6
MS
411 }
412 else
413 {
414 header_fmt_string = " %18s %18s %10s %10s %7s\n";
6949171e 415 data_fmt_string = " %#18lx %#18lx %#10x %#10x %7s\n";
2bf543a6
MS
416 }
417
418 printf_filtered ("Mapped address spaces:\n\n");
6949171e 419 printf_filtered (header_fmt_string,
2bf543a6
MS
420 "Start Addr",
421 " End Addr",
6949171e
JJ
422 " Size", " Offset", "objfile");
423
424 while (read_mapping (procfile, &addr, &endaddr, &permissions[0],
2bf543a6
MS
425 &offset, &device[0], &inode, &filename[0]))
426 {
427 size = endaddr - addr;
6949171e
JJ
428 printf_filtered (data_fmt_string, (unsigned long) addr, /* FIXME: pr_addr */
429 (unsigned long) endaddr,
430 (int) size,
431 (unsigned int) offset,
2bf543a6 432 filename[0] ? filename : "");
6949171e 433
2bf543a6
MS
434 }
435
436 fclose (procfile);
437 }
438 else
439 warning ("unable to open /proc file '%s'", fname1);
440 }
441 if (status_f || all)
442 {
443 sprintf (fname1, "/proc/%lld/status", pid);
444 if ((procfile = fopen (fname1, "r")) > 0)
445 {
446 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
447 printf_filtered (buffer);
448 fclose (procfile);
449 }
6949171e 450 else
2bf543a6
MS
451 warning ("unable to open /proc file '%s'", fname1);
452 }
453 if (stat_f || all)
454 {
455 sprintf (fname1, "/proc/%lld/stat", pid);
456 if ((procfile = fopen (fname1, "r")) > 0)
457 {
458 int itmp;
459 char ctmp;
460
461 if (fscanf (procfile, "%d ", &itmp) > 0)
462 printf_filtered ("Process: %d\n", itmp);
463 if (fscanf (procfile, "%s ", &buffer[0]) > 0)
464 printf_filtered ("Exec file: %s\n", buffer);
465 if (fscanf (procfile, "%c ", &ctmp) > 0)
466 printf_filtered ("State: %c\n", ctmp);
467 if (fscanf (procfile, "%d ", &itmp) > 0)
468 printf_filtered ("Parent process: %d\n", itmp);
469 if (fscanf (procfile, "%d ", &itmp) > 0)
470 printf_filtered ("Process group: %d\n", itmp);
471 if (fscanf (procfile, "%d ", &itmp) > 0)
472 printf_filtered ("Session id: %d\n", itmp);
473 if (fscanf (procfile, "%d ", &itmp) > 0)
474 printf_filtered ("TTY: %d\n", itmp);
475 if (fscanf (procfile, "%d ", &itmp) > 0)
476 printf_filtered ("TTY owner process group: %d\n", itmp);
477 if (fscanf (procfile, "%u ", &itmp) > 0)
478 printf_filtered ("Flags: 0x%x\n", itmp);
479 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 480 printf_filtered ("Minor faults (no memory page): %u\n",
2bf543a6
MS
481 (unsigned int) itmp);
482 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 483 printf_filtered ("Minor faults, children: %u\n",
2bf543a6
MS
484 (unsigned int) itmp);
485 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 486 printf_filtered ("Major faults (memory page faults): %u\n",
2bf543a6
MS
487 (unsigned int) itmp);
488 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 489 printf_filtered ("Major faults, children: %u\n",
2bf543a6
MS
490 (unsigned int) itmp);
491 if (fscanf (procfile, "%d ", &itmp) > 0)
492 printf_filtered ("utime: %d\n", itmp);
493 if (fscanf (procfile, "%d ", &itmp) > 0)
494 printf_filtered ("stime: %d\n", itmp);
495 if (fscanf (procfile, "%d ", &itmp) > 0)
496 printf_filtered ("utime, children: %d\n", itmp);
497 if (fscanf (procfile, "%d ", &itmp) > 0)
498 printf_filtered ("stime, children: %d\n", itmp);
499 if (fscanf (procfile, "%d ", &itmp) > 0)
6949171e 500 printf_filtered ("jiffies remaining in current time slice: %d\n",
2bf543a6
MS
501 itmp);
502 if (fscanf (procfile, "%d ", &itmp) > 0)
503 printf_filtered ("'nice' value: %d\n", itmp);
504 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 505 printf_filtered ("jiffies until next timeout: %u\n",
2bf543a6
MS
506 (unsigned int) itmp);
507 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 508 printf_filtered ("jiffies until next SIGALRM: %u\n",
2bf543a6
MS
509 (unsigned int) itmp);
510 if (fscanf (procfile, "%d ", &itmp) > 0)
6949171e 511 printf_filtered ("start time (jiffies since system boot): %d\n",
2bf543a6
MS
512 itmp);
513 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 514 printf_filtered ("Virtual memory size: %u\n",
2bf543a6
MS
515 (unsigned int) itmp);
516 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 517 printf_filtered ("Resident set size: %u\n", (unsigned int) itmp);
2bf543a6 518 if (fscanf (procfile, "%u ", &itmp) > 0)
6949171e 519 printf_filtered ("rlim: %u\n", (unsigned int) itmp);
2bf543a6
MS
520 if (fscanf (procfile, "%u ", &itmp) > 0)
521 printf_filtered ("Start of text: 0x%x\n", itmp);
522 if (fscanf (procfile, "%u ", &itmp) > 0)
523 printf_filtered ("End of text: 0x%x\n", itmp);
524 if (fscanf (procfile, "%u ", &itmp) > 0)
525 printf_filtered ("Start of stack: 0x%x\n", itmp);
6949171e
JJ
526#if 0 /* Don't know how architecture-dependent the rest is...
527 Anyway the signal bitmap info is available from "status". */
2bf543a6
MS
528 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
529 printf_filtered ("Kernel stack pointer: 0x%x\n", itmp);
530 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
531 printf_filtered ("Kernel instr pointer: 0x%x\n", itmp);
532 if (fscanf (procfile, "%d ", &itmp) > 0)
533 printf_filtered ("Pending signals bitmap: 0x%x\n", itmp);
534 if (fscanf (procfile, "%d ", &itmp) > 0)
535 printf_filtered ("Blocked signals bitmap: 0x%x\n", itmp);
536 if (fscanf (procfile, "%d ", &itmp) > 0)
537 printf_filtered ("Ignored signals bitmap: 0x%x\n", itmp);
538 if (fscanf (procfile, "%d ", &itmp) > 0)
539 printf_filtered ("Catched signals bitmap: 0x%x\n", itmp);
540 if (fscanf (procfile, "%u ", &itmp) > 0) /* FIXME arch? */
541 printf_filtered ("wchan (system call): 0x%x\n", itmp);
542#endif
543 fclose (procfile);
544 }
545 else
546 warning ("unable to open /proc file '%s'", fname1);
547 }
548}
549
be4d1333
MS
550void
551_initialize_linux_proc (void)
552{
553 extern void inftarg_set_find_memory_regions ();
554 extern void inftarg_set_make_corefile_notes ();
555
556 inftarg_set_find_memory_regions (linux_find_memory_regions);
557 inftarg_set_make_corefile_notes (linux_make_note_section);
2bf543a6 558
6949171e 559 add_info ("proc", linux_info_proc_cmd,
2bf543a6
MS
560 "Show /proc process information about any running process.\n\
561Specify any process id, or use the program being debugged by default.\n\
562Specify any of the following keywords for detailed info:\n\
563 mappings -- list of mapped memory regions.\n\
564 stat -- list a bunch of random process info.\n\
565 status -- list a different bunch of random process info.\n\
566 all -- list all available /proc info.");
be4d1333 567}
eb784848 568
6949171e
JJ
569int
570linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len, int write,
571 struct mem_attrib *attrib, struct target_ops *target)
eb784848
DJ
572{
573 int fd, ret;
574 char filename[64];
575
576 if (write)
577 return 0;
578
579 /* Don't bother for one word. */
580 if (len < 3 * sizeof (long))
581 return 0;
582
583 /* We could keep this file open and cache it - possibly one
584 per thread. That requires some juggling, but is even faster. */
585 sprintf (filename, "/proc/%d/mem", PIDGET (inferior_ptid));
586 fd = open (filename, O_RDONLY | O_LARGEFILE);
587 if (fd == -1)
588 return 0;
589
590 /* If pread64 is available, use it. It's faster if the kernel
591 supports it (only one syscall), and it's 64-bit safe even
592 on 32-bit platforms (for instance, SPARC debugging a SPARC64
593 application).
594
595 We play some autoconf and CFLAGS games to get this declaration
596 exposed: -D_XOPEN_SOURCE=500 -D_LARGEFILE64_SOURCE. And then
597 a -D_BSD_SOURCE to counteract the defaults for _XOPEN_SOURCE. */
598#ifdef HAVE_PREAD64
599 if (pread64 (fd, myaddr, len, addr) != len)
600#else
6949171e 601 if (lseek (fd, addr, SEEK_SET) == -1 || read (fd, myaddr, len) != len)
eb784848
DJ
602#endif
603 ret = 0;
604 else
605 ret = len;
606
607 close (fd);
608 return ret;
609}
This page took 0.181262 seconds and 4 git commands to generate.