Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
io.c
Go to the documentation of this file.
1 /*
2  * Provide streaming read of BTS branch records from a file.
3  */
4 #include <errno.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <assert.h>
9 #include <bts.h>
10 
11 struct bts_stream {
12  FILE *fd;
13  uint64_t recno;
14 };
15 
16 #define _BBUFSIZE (10240 * sizeof(struct bts_rec))
17 
18 BTSFD
19 bts_open(const char *logname)
20 {
21  struct bts_stream *bs;
22 
23  bs = malloc(sizeof *bs);
24  if (bs == 0) {
25  fprintf(stderr, "No memory\n");
26  return 0;
27  }
28  memset(bs, 0, sizeof *bs);
29 
30  bs->fd = fopen(logname, "r");
31  if (bs->fd == NULL) {
32  perror(logname);
33  free(bs);
34  return 0;
35  }
36 
37  return (BTSFD)bs;
38 }
39 
40 /*
41  * Seek to a specific record number.
42  * Return 0 on sucess, -1 otherwise.
43  */
44 int
45 bts_seek(BTSFD fd, uint64_t recno)
46 {
47  struct bts_stream *bs = fd;
48  off_t foff = recno * sizeof(struct bts_rec);
49 
50  if (bs == 0) {
51  fprintf(stderr, "bts_seek: invalid BTSFD\n");
52  return -1;
53  }
54 
55  if (bs->recno != recno) {
56  if (fseeko(bs->fd, foff, SEEK_SET) == -1) {
57  fprintf(stderr, "bts_seek: cannot seek to 0x%llx\n",
58  (unsigned long long)foff);
59  return -1;
60  }
61  bs->recno = recno;
62  }
63 
64  return 0;
65 }
66 
67 /*
68  * Read up to maxrec branch records from the current offset into buf.
69  * Returns the number of records sucessfully read (0 on EOF),
70  * or -1 on error.
71  */
72 int
73 bts_read(BTSFD fd, struct bts_rec *buf, int maxrec)
74 {
75  struct bts_stream *bs = fd;
76  size_t nbytes, rbytes;
77  int nrecs;
78 
79  if (bs == 0 || buf == 0) {
80  fprintf(stderr, "bts_read: invalid BTSFD or buffer\n");
81  return -1;
82  }
83 
84  nbytes = maxrec * sizeof(struct bts_rec);
85  rbytes = fread(buf, 1, nbytes, bs->fd);
86  if (rbytes != nbytes) {
87  if (rbytes == 0) {
88  if (feof(bs->fd))
89  return 0;
90  return -1;
91  }
92  nrecs = rbytes / sizeof(struct bts_rec);
93  if ((rbytes % sizeof(struct bts_rec)) != 0) {
94  if (nrecs == 0) {
95  fprintf(stderr, "bts_read: got partial record!\n");
96  return -1;
97  }
98  fprintf(stderr, "bts_read: read not multiple of record size, "
99  "truncating!\n");
100 
101  /* get to a record boundary in the file */
102  bts_seek(fd, bs->recno+nrecs);
103  return nrecs;
104  }
105  } else
106  nrecs = maxrec;
107 
108  bs->recno += nrecs;
109  return nrecs;
110 }
111 
112 void
114 {
115  struct bts_stream *bs = fd;
116 
117  if (bs) {
118  fclose(bs->fd);
119  free(bs);
120  }
121 }
122 
123 /*
124  * Local variables:
125  * mode: C
126  * c-set-style: "BSD"
127  * c-basic-offset: 4
128  * End:
129  */
Definition: bts.h:23
void bts_close(BTSFD fd)
Definition: io.c:113
void * BTSFD
Definition: bts.h:29
Definition: io.c:11
int bts_seek(BTSFD fd, uint64_t recno)
Definition: io.c:45
BTSFD bts_open(const char *logname)
Definition: io.c:19
int bts_read(BTSFD fd, struct bts_rec *buf, int maxrec)
Definition: io.c:73
void free(void *ptr)
Definition: debugserver.c:207
FILE * fd
Definition: io.c:12
void * malloc(size_t size)
Definition: debugserver.c:214
uint64_t recno
Definition: io.c:13