blob: b77de3753a7f52e644261e1ff95b926206220f24 [file] [log] [blame]
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -07001/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#include <ctype.h>
Luis Hector Chavez40b25742013-09-22 19:44:06 -07007#include <stdio.h>
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -07008#include <string.h>
Jorge Lucangeli Obes7b2e29c2016-08-04 12:21:03 -04009#include <sys/utsname.h>
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -070010
11#include "util.h"
12
Luis Hector Chavez40b25742013-09-22 19:44:06 -070013#include "libconstants.h"
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -070014#include "libsyscalls.h"
15
Mike Frysingerfccb4c92013-10-19 02:42:07 -040016/*
17 * These are syscalls used by the syslog() C library call. You can find them
18 * by running a simple test program. See below for x86_64 behavior:
19 * $ cat test.c
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080020 * #include <syslog.h>
Mike Frysingerfccb4c92013-10-19 02:42:07 -040021 * main() { syslog(0, "foo"); }
22 * $ gcc test.c -static
23 * $ strace ./a.out
24 * ...
25 * socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3 <- look for socket connection
26 * connect(...) <- important
27 * sendto(...) <- important
28 * exit_group(0) <- finish!
29 */
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070030#if defined(__x86_64__)
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080031#if defined(__ANDROID__)
32const char *log_syscalls[] = {"socket", "connect", "fcntl", "writev"};
Alex Deymo7c6899c2016-01-27 18:24:19 -080033#else
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080034const char *log_syscalls[] = {"connect", "sendto"};
35#endif
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070036#elif defined(__i386__)
Jeff Vander Stoep1482f202016-01-07 11:21:31 -080037#if defined(__ANDROID__)
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080038const char *log_syscalls[] = {"socketcall", "writev", "fcntl64",
39 "clock_gettime"};
Jeff Vander Stoep1482f202016-01-07 11:21:31 -080040#else
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080041const char *log_syscalls[] = {"socketcall", "time"};
Jeff Vander Stoep1482f202016-01-07 11:21:31 -080042#endif
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070043#elif defined(__arm__)
Jeff Vander Stoepd38f3992015-12-02 10:54:51 -080044#if defined(__ANDROID__)
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080045const char *log_syscalls[] = {"clock_gettime", "connect", "fcntl64", "socket",
46 "writev"};
Jeff Vander Stoepd38f3992015-12-02 10:54:51 -080047#else
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080048const char *log_syscalls[] = {"connect", "gettimeofday", "send"};
Jeff Vander Stoepd38f3992015-12-02 10:54:51 -080049#endif
50#elif defined(__aarch64__)
51#if defined(__ANDROID__)
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080052const char *log_syscalls[] = {"connect", "fcntl", "sendto", "socket", "writev"};
Jeff Vander Stoepd38f3992015-12-02 10:54:51 -080053#else
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080054const char *log_syscalls[] = {"connect", "send"};
Jeff Vander Stoepd38f3992015-12-02 10:54:51 -080055#endif
Jorge Lucangeli Obesb98ad292016-01-25 15:07:30 -080056#elif defined(__powerpc__) || defined(__ia64__) || defined(__hppa__) || \
57 defined(__sparc__) || defined(__mips__)
58const char *log_syscalls[] = {"connect", "send"};
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070059#else
60#error "Unsupported platform"
61#endif
62
63const size_t log_syscalls_len = sizeof(log_syscalls)/sizeof(log_syscalls[0]);
64
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -070065int lookup_syscall(const char *name)
66{
67 const struct syscall_entry *entry = syscall_table;
68 for (; entry->name && entry->nr >= 0; ++entry)
69 if (!strcmp(entry->name, name))
70 return entry->nr;
71 return -1;
72}
73
74const char *lookup_syscall_name(int nr)
75{
76 const struct syscall_entry *entry = syscall_table;
77 for (; entry->name && entry->nr >= 0; ++entry)
78 if (entry->nr == nr)
79 return entry->name;
80 return NULL;
81}
82
Jorge Lucangeli Obes7b2e29c2016-08-04 12:21:03 -040083long int parse_single_constant(char *constant_str, char **endptr)
84{
85 const struct constant_entry *entry = constant_table;
86 for (; entry->name; ++entry) {
87 if (!strcmp(entry->name, constant_str)) {
88 if (endptr)
89 *endptr = constant_str + strlen(constant_str);
90
91 return entry->value;
92 }
93 }
94
95 return strtol(constant_str, endptr, 0);
96}
97
Luis Hector Chavez40b25742013-09-22 19:44:06 -070098long int parse_constant(char *constant_str, char **endptr)
99{
Luis Hector Chavez21224552015-06-27 18:10:39 +0000100 long int value = 0;
101 char *group, *lastpos = constant_str;
102 char *original_constant_str = constant_str;
103
104 /*
105 * Try to parse constants separated by pipes. Note that since
106 * |constant_str| is an atom, there can be no spaces between the
107 * constant and the pipe. Constants can be either a named constant
108 * defined in libconstants.gen.c or a number parsed with strtol.
109 *
110 * If there is an error parsing any of the constants, the whole process
111 * fails.
112 */
113 while ((group = tokenize(&constant_str, "|")) != NULL) {
114 char *end = group;
115 value |= parse_single_constant(group, &end);
116 if (end == group) {
117 lastpos = original_constant_str;
118 value = 0;
119 break;
120 }
121 lastpos = end;
122 }
123 if (endptr)
124 *endptr = lastpos;
125 return value;
126}
127
Jorge Lucangeli Obesa6b034d2012-08-07 15:29:20 -0700128char *strip(char *s)
129{
130 char *end;
131 while (*s && isblank(*s))
132 s++;
133 end = s + strlen(s) - 1;
134 while (end >= s && *end && (isblank(*end) || *end == '\n'))
135 end--;
136 *(end + 1) = '\0';
137 return s;
138}
Jorge Lucangeli Obes66cfc142012-11-30 15:42:52 -0800139
Jorge Lucangeli Obesc8b21e12014-06-13 14:26:16 -0700140char *tokenize(char **stringp, const char *delim)
141{
Jorge Lucangeli Obes66cfc142012-11-30 15:42:52 -0800142 char *ret = NULL;
143
144 /* If the string is NULL or empty, there are no tokens to be found. */
145 if (stringp == NULL || *stringp == NULL || **stringp == '\0')
146 return NULL;
147
148 /*
149 * If the delimiter is NULL or empty,
150 * the full string makes up the only token.
151 */
152 if (delim == NULL || *delim == '\0') {
153 ret = *stringp;
154 *stringp = NULL;
155 return ret;
156 }
157
158 char *found;
159 while (**stringp != '\0') {
160 found = strstr(*stringp, delim);
161
162 if (!found) {
163 /*
164 * The delimiter was not found, so the full string
165 * makes up the only token, and we're done.
166 */
167 ret = *stringp;
168 *stringp = NULL;
169 break;
170 }
171
172 if (found != *stringp) {
173 /* There's a non-empty token before the delimiter. */
174 *found = '\0';
175 ret = *stringp;
176 *stringp = found + strlen(delim);
177 break;
178 }
179
180 /*
181 * The delimiter was found at the start of the string,
182 * skip it and keep looking for a non-empty token.
183 */
184 *stringp += strlen(delim);
185 }
186
187 return ret;
188}
Jorge Lucangeli Obes7b2e29c2016-08-04 12:21:03 -0400189
190int kernel_lessthan_3_8()
191{
192 int major, minor;
193 struct utsname uts;
194 return (uname(&uts) != -1 &&
195 sscanf(uts.release, "%d.%d", &major, &minor) == 2 &&
196 ((major < 3) || ((major == 3) && (minor < 8))));
197}
198
199char *path_join(const char *external_path, const char *internal_path)
200{
201 char *path;
202 size_t pathlen;
203
204 /* One extra char for '/' and one for '\0', hence + 2. */
205 pathlen = strlen(external_path) + strlen(internal_path) + 2;
206 path = malloc(pathlen);
207 snprintf(path, pathlen, "%s/%s", external_path, internal_path);
208
209 return path;
210}
211
212void *consumebytes(size_t length, char **buf, size_t *buflength)
213{
214 char *p = *buf;
215 if (length > *buflength)
216 return NULL;
217 *buf += length;
218 *buflength -= length;
219 return p;
220}
221
222char *consumestr(char **buf, size_t *buflength)
223{
224 size_t len = strnlen(*buf, *buflength);
225 if (len == *buflength)
226 /* There's no null-terminator. */
227 return NULL;
228 return consumebytes(len + 1, buf, buflength);
229}