0ef7fa368c8ba852f20d42c0ba4a099d5d79c420
[deliverable/binutils-gdb.git] / gdb / nat / linux-osdata.c
1 /* Linux-specific functions to retrieve OS data.
2
3 Copyright (C) 2009-2014 Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>. */
19
20 #ifdef GDBSERVER
21 #include "server.h"
22 #else
23 #include "defs.h"
24 #endif
25
26 #include "linux-osdata.h"
27
28 #include <sys/types.h>
29 #include <sys/sysinfo.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <utmp.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include <pwd.h>
36 #include <grp.h>
37 #include <netdb.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40
41 #include "xml-utils.h"
42 #include "buffer.h"
43 #include <dirent.h>
44 #include <sys/stat.h>
45 #include "filestuff.h"
46
47 #define NAMELEN(dirent) strlen ((dirent)->d_name)
48
49 /* Define PID_T to be a fixed size that is at least as large as pid_t,
50 so that reading pid values embedded in /proc works
51 consistently. */
52
53 typedef long long PID_T;
54
55 /* Define TIME_T to be at least as large as time_t, so that reading
56 time values embedded in /proc works consistently. */
57
58 typedef long long TIME_T;
59
60 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
61
62 /* Returns the CPU core that thread PTID is currently running on. */
63
64 /* Compute and return the processor core of a given thread. */
65
66 int
67 linux_common_core_of_thread (ptid_t ptid)
68 {
69 char filename[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN];
70 FILE *f;
71 char *content = NULL;
72 char *p;
73 char *ts = 0;
74 int content_read = 0;
75 int i;
76 int core;
77
78 sprintf (filename, "/proc/%lld/task/%lld/stat",
79 (PID_T) ptid_get_pid (ptid), (PID_T) ptid_get_lwp (ptid));
80 f = gdb_fopen_cloexec (filename, "r");
81 if (!f)
82 return -1;
83
84 for (;;)
85 {
86 int n;
87 content = xrealloc (content, content_read + 1024);
88 n = fread (content + content_read, 1, 1024, f);
89 content_read += n;
90 if (n < 1024)
91 {
92 content[content_read] = '\0';
93 break;
94 }
95 }
96
97 /* ps command also relies on no trailing fields ever contain ')'. */
98 p = strrchr (content, ')');
99 if (p != NULL)
100 p++;
101
102 /* If the first field after program name has index 0, then core number is
103 the field with index 36. There's no constant for that anywhere. */
104 if (p != NULL)
105 p = strtok_r (p, " ", &ts);
106 for (i = 0; p != NULL && i != 36; ++i)
107 p = strtok_r (NULL, " ", &ts);
108
109 if (p == NULL || sscanf (p, "%d", &core) == 0)
110 core = -1;
111
112 xfree (content);
113 fclose (f);
114
115 return core;
116 }
117
118 /* Finds the command-line of process PID and copies it into COMMAND.
119 At most MAXLEN characters are copied. If the command-line cannot
120 be found, PID is copied into command in text-form. */
121
122 static void
123 command_from_pid (char *command, int maxlen, PID_T pid)
124 {
125 char *stat_path = xstrprintf ("/proc/%lld/stat", pid);
126 FILE *fp = gdb_fopen_cloexec (stat_path, "r");
127
128 command[0] = '\0';
129
130 if (fp)
131 {
132 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
133 include/linux/sched.h in the Linux kernel sources) plus two
134 (for the brackets). */
135 char cmd[18];
136 PID_T stat_pid;
137 int items_read = fscanf (fp, "%lld %17s", &stat_pid, cmd);
138
139 if (items_read == 2 && pid == stat_pid)
140 {
141 cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */
142 strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */
143 }
144
145 fclose (fp);
146 }
147 else
148 {
149 /* Return the PID if a /proc entry for the process cannot be found. */
150 snprintf (command, maxlen, "%lld", pid);
151 }
152
153 command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */
154
155 xfree (stat_path);
156 }
157
158 /* Returns the command-line of the process with the given PID. The
159 returned string needs to be freed using xfree after use. */
160
161 static char *
162 commandline_from_pid (PID_T pid)
163 {
164 char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
165 char *commandline = NULL;
166 FILE *f = gdb_fopen_cloexec (pathname, "r");
167
168 if (f)
169 {
170 size_t len = 0;
171
172 while (!feof (f))
173 {
174 char buf[1024];
175 size_t read_bytes = fread (buf, 1, sizeof (buf), f);
176
177 if (read_bytes)
178 {
179 commandline = (char *) xrealloc (commandline, len + read_bytes + 1);
180 memcpy (commandline + len, buf, read_bytes);
181 len += read_bytes;
182 }
183 }
184
185 fclose (f);
186
187 if (commandline)
188 {
189 size_t i;
190
191 /* Replace null characters with spaces. */
192 for (i = 0; i < len; ++i)
193 if (commandline[i] == '\0')
194 commandline[i] = ' ';
195
196 commandline[len] = '\0';
197 }
198 else
199 {
200 /* Return the command in square brackets if the command-line
201 is empty. */
202 commandline = (char *) xmalloc (32);
203 commandline[0] = '[';
204 command_from_pid (commandline + 1, 31, pid);
205
206 len = strlen (commandline);
207 if (len < 31)
208 strcat (commandline, "]");
209 }
210 }
211
212 xfree (pathname);
213
214 return commandline;
215 }
216
217 /* Finds the user name for the user UID and copies it into USER. At
218 most MAXLEN characters are copied. */
219
220 static void
221 user_from_uid (char *user, int maxlen, uid_t uid)
222 {
223 struct passwd *pwentry = getpwuid (uid);
224
225 if (pwentry)
226 {
227 strncpy (user, pwentry->pw_name, maxlen);
228 /* Ensure that the user name is null-terminated. */
229 user[maxlen - 1] = '\0';
230 }
231 else
232 user[0] = '\0';
233 }
234
235 /* Finds the owner of process PID and returns the user id in OWNER.
236 Returns 0 if the owner was found, -1 otherwise. */
237
238 static int
239 get_process_owner (uid_t *owner, PID_T pid)
240 {
241 struct stat statbuf;
242 char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN];
243
244 sprintf (procentry, "/proc/%lld", pid);
245
246 if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
247 {
248 *owner = statbuf.st_uid;
249 return 0;
250 }
251 else
252 return -1;
253 }
254
255 /* Find the CPU cores used by process PID and return them in CORES.
256 CORES points to an array of NUM_CORES elements. */
257
258 static int
259 get_cores_used_by_process (PID_T pid, int *cores, const int num_cores)
260 {
261 char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
262 DIR *dir;
263 struct dirent *dp;
264 int task_count = 0;
265
266 sprintf (taskdir, "/proc/%lld/task", pid);
267 dir = opendir (taskdir);
268 if (dir)
269 {
270 while ((dp = readdir (dir)) != NULL)
271 {
272 PID_T tid;
273 int core;
274
275 if (!isdigit (dp->d_name[0])
276 || NAMELEN (dp) > MAX_PID_T_STRLEN)
277 continue;
278
279 sscanf (dp->d_name, "%lld", &tid);
280 core = linux_common_core_of_thread (ptid_build ((pid_t) pid,
281 (pid_t) tid, 0));
282
283 if (core >= 0 && core < num_cores)
284 {
285 ++cores[core];
286 ++task_count;
287 }
288 }
289
290 closedir (dir);
291 }
292
293 return task_count;
294 }
295
296 static LONGEST
297 linux_xfer_osdata_processes (gdb_byte *readbuf,
298 ULONGEST offset, ULONGEST len)
299 {
300 /* We make the process list snapshot when the object starts to be read. */
301 static const char *buf;
302 static LONGEST len_avail = -1;
303 static struct buffer buffer;
304
305 if (offset == 0)
306 {
307 DIR *dirp;
308
309 if (len_avail != -1 && len_avail != 0)
310 buffer_free (&buffer);
311 len_avail = 0;
312 buf = NULL;
313 buffer_init (&buffer);
314 buffer_grow_str (&buffer, "<osdata type=\"processes\">\n");
315
316 dirp = opendir ("/proc");
317 if (dirp)
318 {
319 const int num_cores = sysconf (_SC_NPROCESSORS_ONLN);
320 struct dirent *dp;
321
322 while ((dp = readdir (dirp)) != NULL)
323 {
324 PID_T pid;
325 uid_t owner;
326 char user[UT_NAMESIZE];
327 char *command_line;
328 int *cores;
329 int task_count;
330 char *cores_str;
331 int i;
332
333 if (!isdigit (dp->d_name[0])
334 || NAMELEN (dp) > MAX_PID_T_STRLEN)
335 continue;
336
337 sscanf (dp->d_name, "%lld", &pid);
338 command_line = commandline_from_pid (pid);
339
340 if (get_process_owner (&owner, pid) == 0)
341 user_from_uid (user, sizeof (user), owner);
342 else
343 strcpy (user, "?");
344
345 /* Find CPU cores used by the process. */
346 cores = (int *) xcalloc (num_cores, sizeof (int));
347 task_count = get_cores_used_by_process (pid, cores, num_cores);
348 cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1);
349
350 for (i = 0; i < num_cores && task_count > 0; ++i)
351 if (cores[i])
352 {
353 char core_str[sizeof ("4294967295")];
354
355 sprintf (core_str, "%d", i);
356 strcat (cores_str, core_str);
357
358 task_count -= cores[i];
359 if (task_count > 0)
360 strcat (cores_str, ",");
361 }
362
363 xfree (cores);
364
365 buffer_xml_printf (
366 &buffer,
367 "<item>"
368 "<column name=\"pid\">%lld</column>"
369 "<column name=\"user\">%s</column>"
370 "<column name=\"command\">%s</column>"
371 "<column name=\"cores\">%s</column>"
372 "</item>",
373 pid,
374 user,
375 command_line ? command_line : "",
376 cores_str);
377
378 xfree (command_line);
379 xfree (cores_str);
380 }
381
382 closedir (dirp);
383 }
384
385 buffer_grow_str0 (&buffer, "</osdata>\n");
386 buf = buffer_finish (&buffer);
387 len_avail = strlen (buf);
388 }
389
390 if (offset >= len_avail)
391 {
392 /* Done. Get rid of the buffer. */
393 buffer_free (&buffer);
394 buf = NULL;
395 len_avail = 0;
396 return 0;
397 }
398
399 if (len > len_avail - offset)
400 len = len_avail - offset;
401 memcpy (readbuf, buf + offset, len);
402
403 return len;
404 }
405
406 /* Auxiliary function used by qsort to sort processes by process
407 group. Compares two processes with ids PROCESS1 and PROCESS2.
408 PROCESS1 comes before PROCESS2 if it has a lower process group id.
409 If they belong to the same process group, PROCESS1 comes before
410 PROCESS2 if it has a lower process id or is the process group
411 leader. */
412
413 static int
414 compare_processes (const void *process1, const void *process2)
415 {
416 PID_T pid1 = *((PID_T *) process1);
417 PID_T pid2 = *((PID_T *) process2);
418 PID_T pgid1 = *((PID_T *) process1 + 1);
419 PID_T pgid2 = *((PID_T *) process2 + 1);
420
421 /* Sort by PGID. */
422 if (pgid1 < pgid2)
423 return -1;
424 else if (pgid1 > pgid2)
425 return 1;
426 else
427 {
428 /* Process group leaders always come first, else sort by PID. */
429 if (pid1 == pgid1)
430 return -1;
431 else if (pid2 == pgid2)
432 return 1;
433 else if (pid1 < pid2)
434 return -1;
435 else if (pid1 > pid2)
436 return 1;
437 else
438 return 0;
439 }
440 }
441
442 /* Collect all process groups from /proc. */
443
444 static LONGEST
445 linux_xfer_osdata_processgroups (gdb_byte *readbuf,
446 ULONGEST offset, ULONGEST len)
447 {
448 /* We make the process list snapshot when the object starts to be read. */
449 static const char *buf;
450 static LONGEST len_avail = -1;
451 static struct buffer buffer;
452
453 if (offset == 0)
454 {
455 DIR *dirp;
456
457 if (len_avail != -1 && len_avail != 0)
458 buffer_free (&buffer);
459 len_avail = 0;
460 buf = NULL;
461 buffer_init (&buffer);
462 buffer_grow_str (&buffer, "<osdata type=\"process groups\">\n");
463
464 dirp = opendir ("/proc");
465 if (dirp)
466 {
467 struct dirent *dp;
468 const size_t list_block_size = 512;
469 PID_T *process_list = (PID_T *) xmalloc (list_block_size * 2 * sizeof (PID_T));
470 size_t process_count = 0;
471 size_t i;
472
473 /* Build list consisting of PIDs followed by their
474 associated PGID. */
475 while ((dp = readdir (dirp)) != NULL)
476 {
477 PID_T pid, pgid;
478
479 if (!isdigit (dp->d_name[0])
480 || NAMELEN (dp) > MAX_PID_T_STRLEN)
481 continue;
482
483 sscanf (dp->d_name, "%lld", &pid);
484 pgid = getpgid (pid);
485
486 if (pgid > 0)
487 {
488 process_list[2 * process_count] = pid;
489 process_list[2 * process_count + 1] = pgid;
490 ++process_count;
491
492 /* Increase the size of the list if necessary. */
493 if (process_count % list_block_size == 0)
494 process_list = (PID_T *) xrealloc (
495 process_list,
496 (process_count + list_block_size)
497 * 2 * sizeof (PID_T));
498 }
499 }
500
501 closedir (dirp);
502
503 /* Sort the process list. */
504 qsort (process_list, process_count, 2 * sizeof (PID_T),
505 compare_processes);
506
507 for (i = 0; i < process_count; ++i)
508 {
509 PID_T pid = process_list[2 * i];
510 PID_T pgid = process_list[2 * i + 1];
511 char leader_command[32];
512 char *command_line;
513
514 command_from_pid (leader_command, sizeof (leader_command), pgid);
515 command_line = commandline_from_pid (pid);
516
517 buffer_xml_printf (
518 &buffer,
519 "<item>"
520 "<column name=\"pgid\">%lld</column>"
521 "<column name=\"leader command\">%s</column>"
522 "<column name=\"pid\">%lld</column>"
523 "<column name=\"command line\">%s</column>"
524 "</item>",
525 pgid,
526 leader_command,
527 pid,
528 command_line ? command_line : "");
529
530 xfree (command_line);
531 }
532
533 xfree (process_list);
534 }
535
536 buffer_grow_str0 (&buffer, "</osdata>\n");
537 buf = buffer_finish (&buffer);
538 len_avail = strlen (buf);
539 }
540
541 if (offset >= len_avail)
542 {
543 /* Done. Get rid of the buffer. */
544 buffer_free (&buffer);
545 buf = NULL;
546 len_avail = 0;
547 return 0;
548 }
549
550 if (len > len_avail - offset)
551 len = len_avail - offset;
552 memcpy (readbuf, buf + offset, len);
553
554 return len;
555 }
556
557 /* Collect all the threads in /proc by iterating through processes and
558 then tasks within each process. */
559
560 static LONGEST
561 linux_xfer_osdata_threads (gdb_byte *readbuf,
562 ULONGEST offset, ULONGEST len)
563 {
564 /* We make the process list snapshot when the object starts to be read. */
565 static const char *buf;
566 static LONGEST len_avail = -1;
567 static struct buffer buffer;
568
569 if (offset == 0)
570 {
571 DIR *dirp;
572
573 if (len_avail != -1 && len_avail != 0)
574 buffer_free (&buffer);
575 len_avail = 0;
576 buf = NULL;
577 buffer_init (&buffer);
578 buffer_grow_str (&buffer, "<osdata type=\"threads\">\n");
579
580 dirp = opendir ("/proc");
581 if (dirp)
582 {
583 struct dirent *dp;
584
585 while ((dp = readdir (dirp)) != NULL)
586 {
587 struct stat statbuf;
588 char procentry[sizeof ("/proc/4294967295")];
589
590 if (!isdigit (dp->d_name[0])
591 || NAMELEN (dp) > sizeof ("4294967295") - 1)
592 continue;
593
594 sprintf (procentry, "/proc/%s", dp->d_name);
595 if (stat (procentry, &statbuf) == 0
596 && S_ISDIR (statbuf.st_mode))
597 {
598 DIR *dirp2;
599 char *pathname;
600 PID_T pid;
601 char command[32];
602
603 pathname = xstrprintf ("/proc/%s/task", dp->d_name);
604
605 pid = atoi (dp->d_name);
606 command_from_pid (command, sizeof (command), pid);
607
608 dirp2 = opendir (pathname);
609
610 if (dirp2)
611 {
612 struct dirent *dp2;
613
614 while ((dp2 = readdir (dirp2)) != NULL)
615 {
616 PID_T tid;
617 int core;
618
619 if (!isdigit (dp2->d_name[0])
620 || NAMELEN (dp2) > sizeof ("4294967295") - 1)
621 continue;
622
623 tid = atoi (dp2->d_name);
624 core = linux_common_core_of_thread (ptid_build (pid, tid, 0));
625
626 buffer_xml_printf (
627 &buffer,
628 "<item>"
629 "<column name=\"pid\">%lld</column>"
630 "<column name=\"command\">%s</column>"
631 "<column name=\"tid\">%lld</column>"
632 "<column name=\"core\">%d</column>"
633 "</item>",
634 pid,
635 command,
636 tid,
637 core);
638 }
639
640 closedir (dirp2);
641 }
642
643 xfree (pathname);
644 }
645 }
646
647 closedir (dirp);
648 }
649
650 buffer_grow_str0 (&buffer, "</osdata>\n");
651 buf = buffer_finish (&buffer);
652 len_avail = strlen (buf);
653 }
654
655 if (offset >= len_avail)
656 {
657 /* Done. Get rid of the buffer. */
658 buffer_free (&buffer);
659 buf = NULL;
660 len_avail = 0;
661 return 0;
662 }
663
664 if (len > len_avail - offset)
665 len = len_avail - offset;
666 memcpy (readbuf, buf + offset, len);
667
668 return len;
669 }
670
671 /* Collect all the open file descriptors found in /proc and put the details
672 found about them into READBUF. */
673
674 static LONGEST
675 linux_xfer_osdata_fds (gdb_byte *readbuf,
676 ULONGEST offset, ULONGEST len)
677 {
678 /* We make the process list snapshot when the object starts to be read. */
679 static const char *buf;
680 static LONGEST len_avail = -1;
681 static struct buffer buffer;
682
683 if (offset == 0)
684 {
685 DIR *dirp;
686
687 if (len_avail != -1 && len_avail != 0)
688 buffer_free (&buffer);
689 len_avail = 0;
690 buf = NULL;
691 buffer_init (&buffer);
692 buffer_grow_str (&buffer, "<osdata type=\"files\">\n");
693
694 dirp = opendir ("/proc");
695 if (dirp)
696 {
697 struct dirent *dp;
698
699 while ((dp = readdir (dirp)) != NULL)
700 {
701 struct stat statbuf;
702 char procentry[sizeof ("/proc/4294967295")];
703
704 if (!isdigit (dp->d_name[0])
705 || NAMELEN (dp) > sizeof ("4294967295") - 1)
706 continue;
707
708 sprintf (procentry, "/proc/%s", dp->d_name);
709 if (stat (procentry, &statbuf) == 0
710 && S_ISDIR (statbuf.st_mode))
711 {
712 char *pathname;
713 DIR *dirp2;
714 PID_T pid;
715 char command[32];
716
717 pid = atoi (dp->d_name);
718 command_from_pid (command, sizeof (command), pid);
719
720 pathname = xstrprintf ("/proc/%s/fd", dp->d_name);
721 dirp2 = opendir (pathname);
722
723 if (dirp2)
724 {
725 struct dirent *dp2;
726
727 while ((dp2 = readdir (dirp2)) != NULL)
728 {
729 char *fdname;
730 char buf[1000];
731 ssize_t rslt;
732
733 if (!isdigit (dp2->d_name[0]))
734 continue;
735
736 fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
737 rslt = readlink (fdname, buf, sizeof (buf) - 1);
738 if (rslt >= 0)
739 buf[rslt] = '\0';
740
741 buffer_xml_printf (
742 &buffer,
743 "<item>"
744 "<column name=\"pid\">%s</column>"
745 "<column name=\"command\">%s</column>"
746 "<column name=\"file descriptor\">%s</column>"
747 "<column name=\"name\">%s</column>"
748 "</item>",
749 dp->d_name,
750 command,
751 dp2->d_name,
752 (rslt >= 0 ? buf : dp2->d_name));
753 }
754
755 closedir (dirp2);
756 }
757
758 xfree (pathname);
759 }
760 }
761
762 closedir (dirp);
763 }
764
765 buffer_grow_str0 (&buffer, "</osdata>\n");
766 buf = buffer_finish (&buffer);
767 len_avail = strlen (buf);
768 }
769
770 if (offset >= len_avail)
771 {
772 /* Done. Get rid of the buffer. */
773 buffer_free (&buffer);
774 buf = NULL;
775 len_avail = 0;
776 return 0;
777 }
778
779 if (len > len_avail - offset)
780 len = len_avail - offset;
781 memcpy (readbuf, buf + offset, len);
782
783 return len;
784 }
785
786 /* Returns the socket state STATE in textual form. */
787
788 static const char *
789 format_socket_state (unsigned char state)
790 {
791 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
792 enum {
793 TCP_ESTABLISHED = 1,
794 TCP_SYN_SENT,
795 TCP_SYN_RECV,
796 TCP_FIN_WAIT1,
797 TCP_FIN_WAIT2,
798 TCP_TIME_WAIT,
799 TCP_CLOSE,
800 TCP_CLOSE_WAIT,
801 TCP_LAST_ACK,
802 TCP_LISTEN,
803 TCP_CLOSING
804 };
805
806 switch (state)
807 {
808 case TCP_ESTABLISHED:
809 return "ESTABLISHED";
810 case TCP_SYN_SENT:
811 return "SYN_SENT";
812 case TCP_SYN_RECV:
813 return "SYN_RECV";
814 case TCP_FIN_WAIT1:
815 return "FIN_WAIT1";
816 case TCP_FIN_WAIT2:
817 return "FIN_WAIT2";
818 case TCP_TIME_WAIT:
819 return "TIME_WAIT";
820 case TCP_CLOSE:
821 return "CLOSE";
822 case TCP_CLOSE_WAIT:
823 return "CLOSE_WAIT";
824 case TCP_LAST_ACK:
825 return "LAST_ACK";
826 case TCP_LISTEN:
827 return "LISTEN";
828 case TCP_CLOSING:
829 return "CLOSING";
830 default:
831 return "(unknown)";
832 }
833 }
834
835 union socket_addr
836 {
837 struct sockaddr sa;
838 struct sockaddr_in sin;
839 struct sockaddr_in6 sin6;
840 };
841
842 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
843 information for all open internet sockets of type FAMILY on the
844 system into BUFFER. If TCP is set, only TCP sockets are processed,
845 otherwise only UDP sockets are processed. */
846
847 static void
848 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
849 {
850 const char *proc_file;
851 FILE *fp;
852
853 if (family == AF_INET)
854 proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
855 else if (family == AF_INET6)
856 proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
857 else
858 return;
859
860 fp = gdb_fopen_cloexec (proc_file, "r");
861 if (fp)
862 {
863 char buf[8192];
864
865 do
866 {
867 if (fgets (buf, sizeof (buf), fp))
868 {
869 uid_t uid;
870 unsigned int local_port, remote_port, state;
871 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
872 int result;
873
874 #if NI_MAXHOST <= 32
875 #error "local_address and remote_address buffers too small"
876 #endif
877
878 result = sscanf (buf,
879 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
880 local_address, &local_port,
881 remote_address, &remote_port,
882 &state,
883 &uid);
884
885 if (result == 6)
886 {
887 union socket_addr locaddr, remaddr;
888 size_t addr_size;
889 char user[UT_NAMESIZE];
890 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
891
892 if (family == AF_INET)
893 {
894 sscanf (local_address, "%X",
895 &locaddr.sin.sin_addr.s_addr);
896 sscanf (remote_address, "%X",
897 &remaddr.sin.sin_addr.s_addr);
898
899 locaddr.sin.sin_port = htons (local_port);
900 remaddr.sin.sin_port = htons (remote_port);
901
902 addr_size = sizeof (struct sockaddr_in);
903 }
904 else
905 {
906 sscanf (local_address, "%8X%8X%8X%8X",
907 locaddr.sin6.sin6_addr.s6_addr32,
908 locaddr.sin6.sin6_addr.s6_addr32 + 1,
909 locaddr.sin6.sin6_addr.s6_addr32 + 2,
910 locaddr.sin6.sin6_addr.s6_addr32 + 3);
911 sscanf (remote_address, "%8X%8X%8X%8X",
912 remaddr.sin6.sin6_addr.s6_addr32,
913 remaddr.sin6.sin6_addr.s6_addr32 + 1,
914 remaddr.sin6.sin6_addr.s6_addr32 + 2,
915 remaddr.sin6.sin6_addr.s6_addr32 + 3);
916
917 locaddr.sin6.sin6_port = htons (local_port);
918 remaddr.sin6.sin6_port = htons (remote_port);
919
920 locaddr.sin6.sin6_flowinfo = 0;
921 remaddr.sin6.sin6_flowinfo = 0;
922 locaddr.sin6.sin6_scope_id = 0;
923 remaddr.sin6.sin6_scope_id = 0;
924
925 addr_size = sizeof (struct sockaddr_in6);
926 }
927
928 locaddr.sa.sa_family = remaddr.sa.sa_family = family;
929
930 result = getnameinfo (&locaddr.sa, addr_size,
931 local_address, sizeof (local_address),
932 local_service, sizeof (local_service),
933 NI_NUMERICHOST | NI_NUMERICSERV
934 | (tcp ? 0 : NI_DGRAM));
935 if (result)
936 continue;
937
938 result = getnameinfo (&remaddr.sa, addr_size,
939 remote_address,
940 sizeof (remote_address),
941 remote_service,
942 sizeof (remote_service),
943 NI_NUMERICHOST | NI_NUMERICSERV
944 | (tcp ? 0 : NI_DGRAM));
945 if (result)
946 continue;
947
948 user_from_uid (user, sizeof (user), uid);
949
950 buffer_xml_printf (
951 buffer,
952 "<item>"
953 "<column name=\"local address\">%s</column>"
954 "<column name=\"local port\">%s</column>"
955 "<column name=\"remote address\">%s</column>"
956 "<column name=\"remote port\">%s</column>"
957 "<column name=\"state\">%s</column>"
958 "<column name=\"user\">%s</column>"
959 "<column name=\"family\">%s</column>"
960 "<column name=\"protocol\">%s</column>"
961 "</item>",
962 local_address,
963 local_service,
964 remote_address,
965 remote_service,
966 format_socket_state (state),
967 user,
968 (family == AF_INET) ? "INET" : "INET6",
969 tcp ? "STREAM" : "DGRAM");
970 }
971 }
972 }
973 while (!feof (fp));
974
975 fclose (fp);
976 }
977 }
978
979 /* Collect data about internet sockets and write it into READBUF. */
980
981 static LONGEST
982 linux_xfer_osdata_isockets (gdb_byte *readbuf,
983 ULONGEST offset, ULONGEST len)
984 {
985 static const char *buf;
986 static LONGEST len_avail = -1;
987 static struct buffer buffer;
988
989 if (offset == 0)
990 {
991 if (len_avail != -1 && len_avail != 0)
992 buffer_free (&buffer);
993 len_avail = 0;
994 buf = NULL;
995 buffer_init (&buffer);
996 buffer_grow_str (&buffer, "<osdata type=\"I sockets\">\n");
997
998 print_sockets (AF_INET, 1, &buffer);
999 print_sockets (AF_INET, 0, &buffer);
1000 print_sockets (AF_INET6, 1, &buffer);
1001 print_sockets (AF_INET6, 0, &buffer);
1002
1003 buffer_grow_str0 (&buffer, "</osdata>\n");
1004 buf = buffer_finish (&buffer);
1005 len_avail = strlen (buf);
1006 }
1007
1008 if (offset >= len_avail)
1009 {
1010 /* Done. Get rid of the buffer. */
1011 buffer_free (&buffer);
1012 buf = NULL;
1013 len_avail = 0;
1014 return 0;
1015 }
1016
1017 if (len > len_avail - offset)
1018 len = len_avail - offset;
1019 memcpy (readbuf, buf + offset, len);
1020
1021 return len;
1022 }
1023
1024 /* Converts the time SECONDS into textual form and copies it into a
1025 buffer TIME, with at most MAXLEN characters copied. */
1026
1027 static void
1028 time_from_time_t (char *time, int maxlen, TIME_T seconds)
1029 {
1030 if (!seconds)
1031 time[0] = '\0';
1032 else
1033 {
1034 time_t t = (time_t) seconds;
1035
1036 strncpy (time, ctime (&t), maxlen);
1037 time[maxlen - 1] = '\0';
1038 }
1039 }
1040
1041 /* Finds the group name for the group GID and copies it into GROUP.
1042 At most MAXLEN characters are copied. */
1043
1044 static void
1045 group_from_gid (char *group, int maxlen, gid_t gid)
1046 {
1047 struct group *grentry = getgrgid (gid);
1048
1049 if (grentry)
1050 {
1051 strncpy (group, grentry->gr_name, maxlen);
1052 /* Ensure that the group name is null-terminated. */
1053 group[maxlen - 1] = '\0';
1054 }
1055 else
1056 group[0] = '\0';
1057 }
1058
1059 /* Collect data about shared memory recorded in /proc and write it
1060 into READBUF. */
1061
1062 static LONGEST
1063 linux_xfer_osdata_shm (gdb_byte *readbuf,
1064 ULONGEST offset, ULONGEST len)
1065 {
1066 static const char *buf;
1067 static LONGEST len_avail = -1;
1068 static struct buffer buffer;
1069
1070 if (offset == 0)
1071 {
1072 FILE *fp;
1073
1074 if (len_avail != -1 && len_avail != 0)
1075 buffer_free (&buffer);
1076 len_avail = 0;
1077 buf = NULL;
1078 buffer_init (&buffer);
1079 buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
1080
1081 fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1082 if (fp)
1083 {
1084 char buf[8192];
1085
1086 do
1087 {
1088 if (fgets (buf, sizeof (buf), fp))
1089 {
1090 key_t key;
1091 uid_t uid, cuid;
1092 gid_t gid, cgid;
1093 PID_T cpid, lpid;
1094 int shmid, size, nattch;
1095 TIME_T atime, dtime, ctime;
1096 unsigned int perms;
1097 int items_read;
1098
1099 items_read = sscanf (buf,
1100 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1101 &key, &shmid, &perms, &size,
1102 &cpid, &lpid,
1103 &nattch,
1104 &uid, &gid, &cuid, &cgid,
1105 &atime, &dtime, &ctime);
1106
1107 if (items_read == 14)
1108 {
1109 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1110 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1111 char ccmd[32], lcmd[32];
1112 char atime_str[32], dtime_str[32], ctime_str[32];
1113
1114 user_from_uid (user, sizeof (user), uid);
1115 group_from_gid (group, sizeof (group), gid);
1116 user_from_uid (cuser, sizeof (cuser), cuid);
1117 group_from_gid (cgroup, sizeof (cgroup), cgid);
1118
1119 command_from_pid (ccmd, sizeof (ccmd), cpid);
1120 command_from_pid (lcmd, sizeof (lcmd), lpid);
1121
1122 time_from_time_t (atime_str, sizeof (atime_str), atime);
1123 time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1124 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1125
1126 buffer_xml_printf (
1127 &buffer,
1128 "<item>"
1129 "<column name=\"key\">%d</column>"
1130 "<column name=\"shmid\">%d</column>"
1131 "<column name=\"permissions\">%o</column>"
1132 "<column name=\"size\">%d</column>"
1133 "<column name=\"creator command\">%s</column>"
1134 "<column name=\"last op. command\">%s</column>"
1135 "<column name=\"num attached\">%d</column>"
1136 "<column name=\"user\">%s</column>"
1137 "<column name=\"group\">%s</column>"
1138 "<column name=\"creator user\">%s</column>"
1139 "<column name=\"creator group\">%s</column>"
1140 "<column name=\"last shmat() time\">%s</column>"
1141 "<column name=\"last shmdt() time\">%s</column>"
1142 "<column name=\"last shmctl() time\">%s</column>"
1143 "</item>",
1144 key,
1145 shmid,
1146 perms,
1147 size,
1148 ccmd,
1149 lcmd,
1150 nattch,
1151 user,
1152 group,
1153 cuser,
1154 cgroup,
1155 atime_str,
1156 dtime_str,
1157 ctime_str);
1158 }
1159 }
1160 }
1161 while (!feof (fp));
1162
1163 fclose (fp);
1164 }
1165
1166 buffer_grow_str0 (&buffer, "</osdata>\n");
1167 buf = buffer_finish (&buffer);
1168 len_avail = strlen (buf);
1169 }
1170
1171 if (offset >= len_avail)
1172 {
1173 /* Done. Get rid of the buffer. */
1174 buffer_free (&buffer);
1175 buf = NULL;
1176 len_avail = 0;
1177 return 0;
1178 }
1179
1180 if (len > len_avail - offset)
1181 len = len_avail - offset;
1182 memcpy (readbuf, buf + offset, len);
1183
1184 return len;
1185 }
1186
1187 /* Collect data about semaphores recorded in /proc and write it
1188 into READBUF. */
1189
1190 static LONGEST
1191 linux_xfer_osdata_sem (gdb_byte *readbuf,
1192 ULONGEST offset, ULONGEST len)
1193 {
1194 static const char *buf;
1195 static LONGEST len_avail = -1;
1196 static struct buffer buffer;
1197
1198 if (offset == 0)
1199 {
1200 FILE *fp;
1201
1202 if (len_avail != -1 && len_avail != 0)
1203 buffer_free (&buffer);
1204 len_avail = 0;
1205 buf = NULL;
1206 buffer_init (&buffer);
1207 buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
1208
1209 fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1210 if (fp)
1211 {
1212 char buf[8192];
1213
1214 do
1215 {
1216 if (fgets (buf, sizeof (buf), fp))
1217 {
1218 key_t key;
1219 uid_t uid, cuid;
1220 gid_t gid, cgid;
1221 unsigned int perms, nsems;
1222 int semid;
1223 TIME_T otime, ctime;
1224 int items_read;
1225
1226 items_read = sscanf (buf,
1227 "%d %d %o %u %d %d %d %d %lld %lld",
1228 &key, &semid, &perms, &nsems,
1229 &uid, &gid, &cuid, &cgid,
1230 &otime, &ctime);
1231
1232 if (items_read == 10)
1233 {
1234 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1235 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1236 char otime_str[32], ctime_str[32];
1237
1238 user_from_uid (user, sizeof (user), uid);
1239 group_from_gid (group, sizeof (group), gid);
1240 user_from_uid (cuser, sizeof (cuser), cuid);
1241 group_from_gid (cgroup, sizeof (cgroup), cgid);
1242
1243 time_from_time_t (otime_str, sizeof (otime_str), otime);
1244 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1245
1246 buffer_xml_printf (
1247 &buffer,
1248 "<item>"
1249 "<column name=\"key\">%d</column>"
1250 "<column name=\"semid\">%d</column>"
1251 "<column name=\"permissions\">%o</column>"
1252 "<column name=\"num semaphores\">%u</column>"
1253 "<column name=\"user\">%s</column>"
1254 "<column name=\"group\">%s</column>"
1255 "<column name=\"creator user\">%s</column>"
1256 "<column name=\"creator group\">%s</column>"
1257 "<column name=\"last semop() time\">%s</column>"
1258 "<column name=\"last semctl() time\">%s</column>"
1259 "</item>",
1260 key,
1261 semid,
1262 perms,
1263 nsems,
1264 user,
1265 group,
1266 cuser,
1267 cgroup,
1268 otime_str,
1269 ctime_str);
1270 }
1271 }
1272 }
1273 while (!feof (fp));
1274
1275 fclose (fp);
1276 }
1277
1278 buffer_grow_str0 (&buffer, "</osdata>\n");
1279 buf = buffer_finish (&buffer);
1280 len_avail = strlen (buf);
1281 }
1282
1283 if (offset >= len_avail)
1284 {
1285 /* Done. Get rid of the buffer. */
1286 buffer_free (&buffer);
1287 buf = NULL;
1288 len_avail = 0;
1289 return 0;
1290 }
1291
1292 if (len > len_avail - offset)
1293 len = len_avail - offset;
1294 memcpy (readbuf, buf + offset, len);
1295
1296 return len;
1297 }
1298
1299 /* Collect data about message queues recorded in /proc and write it
1300 into READBUF. */
1301
1302 static LONGEST
1303 linux_xfer_osdata_msg (gdb_byte *readbuf,
1304 ULONGEST offset, ULONGEST len)
1305 {
1306 static const char *buf;
1307 static LONGEST len_avail = -1;
1308 static struct buffer buffer;
1309
1310 if (offset == 0)
1311 {
1312 FILE *fp;
1313
1314 if (len_avail != -1 && len_avail != 0)
1315 buffer_free (&buffer);
1316 len_avail = 0;
1317 buf = NULL;
1318 buffer_init (&buffer);
1319 buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
1320
1321 fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1322 if (fp)
1323 {
1324 char buf[8192];
1325
1326 do
1327 {
1328 if (fgets (buf, sizeof (buf), fp))
1329 {
1330 key_t key;
1331 PID_T lspid, lrpid;
1332 uid_t uid, cuid;
1333 gid_t gid, cgid;
1334 unsigned int perms, cbytes, qnum;
1335 int msqid;
1336 TIME_T stime, rtime, ctime;
1337 int items_read;
1338
1339 items_read = sscanf (buf,
1340 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1341 &key, &msqid, &perms, &cbytes, &qnum,
1342 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1343 &stime, &rtime, &ctime);
1344
1345 if (items_read == 14)
1346 {
1347 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1348 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1349 char lscmd[32], lrcmd[32];
1350 char stime_str[32], rtime_str[32], ctime_str[32];
1351
1352 user_from_uid (user, sizeof (user), uid);
1353 group_from_gid (group, sizeof (group), gid);
1354 user_from_uid (cuser, sizeof (cuser), cuid);
1355 group_from_gid (cgroup, sizeof (cgroup), cgid);
1356
1357 command_from_pid (lscmd, sizeof (lscmd), lspid);
1358 command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1359
1360 time_from_time_t (stime_str, sizeof (stime_str), stime);
1361 time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1362 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1363
1364 buffer_xml_printf (
1365 &buffer,
1366 "<item>"
1367 "<column name=\"key\">%d</column>"
1368 "<column name=\"msqid\">%d</column>"
1369 "<column name=\"permissions\">%o</column>"
1370 "<column name=\"num used bytes\">%u</column>"
1371 "<column name=\"num messages\">%u</column>"
1372 "<column name=\"last msgsnd() command\">%s</column>"
1373 "<column name=\"last msgrcv() command\">%s</column>"
1374 "<column name=\"user\">%s</column>"
1375 "<column name=\"group\">%s</column>"
1376 "<column name=\"creator user\">%s</column>"
1377 "<column name=\"creator group\">%s</column>"
1378 "<column name=\"last msgsnd() time\">%s</column>"
1379 "<column name=\"last msgrcv() time\">%s</column>"
1380 "<column name=\"last msgctl() time\">%s</column>"
1381 "</item>",
1382 key,
1383 msqid,
1384 perms,
1385 cbytes,
1386 qnum,
1387 lscmd,
1388 lrcmd,
1389 user,
1390 group,
1391 cuser,
1392 cgroup,
1393 stime_str,
1394 rtime_str,
1395 ctime_str);
1396 }
1397 }
1398 }
1399 while (!feof (fp));
1400
1401 fclose (fp);
1402 }
1403
1404 buffer_grow_str0 (&buffer, "</osdata>\n");
1405 buf = buffer_finish (&buffer);
1406 len_avail = strlen (buf);
1407 }
1408
1409 if (offset >= len_avail)
1410 {
1411 /* Done. Get rid of the buffer. */
1412 buffer_free (&buffer);
1413 buf = NULL;
1414 len_avail = 0;
1415 return 0;
1416 }
1417
1418 if (len > len_avail - offset)
1419 len = len_avail - offset;
1420 memcpy (readbuf, buf + offset, len);
1421
1422 return len;
1423 }
1424
1425 /* Collect data about loaded kernel modules and write it into
1426 READBUF. */
1427
1428 static LONGEST
1429 linux_xfer_osdata_modules (gdb_byte *readbuf,
1430 ULONGEST offset, ULONGEST len)
1431 {
1432 static const char *buf;
1433 static LONGEST len_avail = -1;
1434 static struct buffer buffer;
1435
1436 if (offset == 0)
1437 {
1438 FILE *fp;
1439
1440 if (len_avail != -1 && len_avail != 0)
1441 buffer_free (&buffer);
1442 len_avail = 0;
1443 buf = NULL;
1444 buffer_init (&buffer);
1445 buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
1446
1447 fp = gdb_fopen_cloexec ("/proc/modules", "r");
1448 if (fp)
1449 {
1450 char buf[8192];
1451
1452 do
1453 {
1454 if (fgets (buf, sizeof (buf), fp))
1455 {
1456 char *name, *dependencies, *status, *tmp;
1457 unsigned int size;
1458 unsigned long long address;
1459 int uses;
1460
1461 name = strtok (buf, " ");
1462 if (name == NULL)
1463 continue;
1464
1465 tmp = strtok (NULL, " ");
1466 if (tmp == NULL)
1467 continue;
1468 if (sscanf (tmp, "%u", &size) != 1)
1469 continue;
1470
1471 tmp = strtok (NULL, " ");
1472 if (tmp == NULL)
1473 continue;
1474 if (sscanf (tmp, "%d", &uses) != 1)
1475 continue;
1476
1477 dependencies = strtok (NULL, " ");
1478 if (dependencies == NULL)
1479 continue;
1480
1481 status = strtok (NULL, " ");
1482 if (status == NULL)
1483 continue;
1484
1485 tmp = strtok (NULL, "\n");
1486 if (tmp == NULL)
1487 continue;
1488 if (sscanf (tmp, "%llx", &address) != 1)
1489 continue;
1490
1491 buffer_xml_printf (
1492 &buffer,
1493 "<item>"
1494 "<column name=\"name\">%s</column>"
1495 "<column name=\"size\">%u</column>"
1496 "<column name=\"num uses\">%d</column>"
1497 "<column name=\"dependencies\">%s</column>"
1498 "<column name=\"status\">%s</column>"
1499 "<column name=\"address\">%llx</column>"
1500 "</item>",
1501 name,
1502 size,
1503 uses,
1504 dependencies,
1505 status,
1506 address);
1507 }
1508 }
1509 while (!feof (fp));
1510
1511 fclose (fp);
1512 }
1513
1514 buffer_grow_str0 (&buffer, "</osdata>\n");
1515 buf = buffer_finish (&buffer);
1516 len_avail = strlen (buf);
1517 }
1518
1519 if (offset >= len_avail)
1520 {
1521 /* Done. Get rid of the buffer. */
1522 buffer_free (&buffer);
1523 buf = NULL;
1524 len_avail = 0;
1525 return 0;
1526 }
1527
1528 if (len > len_avail - offset)
1529 len = len_avail - offset;
1530 memcpy (readbuf, buf + offset, len);
1531
1532 return len;
1533 }
1534
1535 struct osdata_type {
1536 char *type;
1537 char *title;
1538 char *description;
1539 LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
1540 } osdata_table[] = {
1541 { "processes", "Processes", "Listing of all processes",
1542 linux_xfer_osdata_processes },
1543 { "procgroups", "Process groups", "Listing of all process groups",
1544 linux_xfer_osdata_processgroups },
1545 { "threads", "Threads", "Listing of all threads",
1546 linux_xfer_osdata_threads },
1547 { "files", "File descriptors", "Listing of all file descriptors",
1548 linux_xfer_osdata_fds },
1549 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1550 linux_xfer_osdata_isockets },
1551 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1552 linux_xfer_osdata_shm },
1553 { "semaphores", "Semaphores", "Listing of all semaphores",
1554 linux_xfer_osdata_sem },
1555 { "msg", "Message queues", "Listing of all message queues",
1556 linux_xfer_osdata_msg },
1557 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1558 linux_xfer_osdata_modules },
1559 { NULL, NULL, NULL }
1560 };
1561
1562 LONGEST
1563 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1564 ULONGEST offset, ULONGEST len)
1565 {
1566 if (!annex || *annex == '\0')
1567 {
1568 static const char *buf;
1569 static LONGEST len_avail = -1;
1570 static struct buffer buffer;
1571
1572 if (offset == 0)
1573 {
1574 int i;
1575
1576 if (len_avail != -1 && len_avail != 0)
1577 buffer_free (&buffer);
1578 len_avail = 0;
1579 buf = NULL;
1580 buffer_init (&buffer);
1581 buffer_grow_str (&buffer, "<osdata type=\"types\">\n");
1582
1583 for (i = 0; osdata_table[i].type; ++i)
1584 buffer_xml_printf (
1585 &buffer,
1586 "<item>"
1587 "<column name=\"Type\">%s</column>"
1588 "<column name=\"Description\">%s</column>"
1589 "<column name=\"Title\">%s</column>"
1590 "</item>",
1591 osdata_table[i].type,
1592 osdata_table[i].description,
1593 osdata_table[i].title);
1594
1595 buffer_grow_str0 (&buffer, "</osdata>\n");
1596 buf = buffer_finish (&buffer);
1597 len_avail = strlen (buf);
1598 }
1599
1600 if (offset >= len_avail)
1601 {
1602 /* Done. Get rid of the buffer. */
1603 buffer_free (&buffer);
1604 buf = NULL;
1605 len_avail = 0;
1606 return 0;
1607 }
1608
1609 if (len > len_avail - offset)
1610 len = len_avail - offset;
1611 memcpy (readbuf, buf + offset, len);
1612
1613 return len;
1614 }
1615 else
1616 {
1617 int i;
1618
1619 for (i = 0; osdata_table[i].type; ++i)
1620 {
1621 if (strcmp (annex, osdata_table[i].type) == 0)
1622 {
1623 gdb_assert (readbuf);
1624
1625 return (osdata_table[i].getter) (readbuf, offset, len);
1626 }
1627 }
1628
1629 return 0;
1630 }
1631 }
1632
This page took 0.130407 seconds and 4 git commands to generate.