6a7328bd8738b54af9684e782e01f2ea01f92800
[vpp.git] / src / vppinfra / unix-misc.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2005 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #include <vppinfra/error.h>
39 #include <vppinfra/os.h>
40 #include <vppinfra/unix.h>
41 #include <vppinfra/format.h>
42
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 #include <sys/uio.h>            /* writev */
46 #include <fcntl.h>
47 #include <stdio.h>              /* for sprintf */
48 #include <limits.h>
49
50 __clib_export __thread uword __os_thread_index = 0;
51 __clib_export __thread uword __os_numa_index = 0;
52
53 clib_error_t *
54 clib_file_n_bytes (char *file, uword * result)
55 {
56   struct stat s;
57
58   if (stat (file, &s) < 0)
59     return clib_error_return_unix (0, "stat `%s'", file);
60
61   if (S_ISREG (s.st_mode))
62     *result = s.st_size;
63   else
64     *result = 0;
65
66   return /* no error */ 0;
67 }
68
69 clib_error_t *
70 clib_file_read_contents (char *file, u8 * result, uword n_bytes)
71 {
72   int fd = -1;
73   uword n_done, n_left;
74   clib_error_t *error = 0;
75   u8 *v = result;
76
77   if ((fd = open (file, 0)) < 0)
78     return clib_error_return_unix (0, "open `%s'", file);
79
80   n_left = n_bytes;
81   n_done = 0;
82   while (n_left > 0)
83     {
84       int n_read;
85       if ((n_read = read (fd, v + n_done, n_left)) < 0)
86         {
87           error = clib_error_return_unix (0, "open `%s'", file);
88           goto done;
89         }
90
91       /* End of file. */
92       if (n_read == 0)
93         break;
94
95       n_left -= n_read;
96       n_done += n_read;
97     }
98
99   if (n_left > 0)
100     {
101       error =
102         clib_error_return (0,
103                            " `%s' expected to read %wd bytes; read only %wd",
104                            file, n_bytes, n_bytes - n_left);
105       goto done;
106     }
107
108 done:
109   close (fd);
110   return error;
111 }
112
113 __clib_export clib_error_t *
114 clib_file_contents (char *file, u8 ** result)
115 {
116   uword n_bytes;
117   clib_error_t *error = 0;
118   u8 *v;
119
120   if ((error = clib_file_n_bytes (file, &n_bytes)))
121     return error;
122
123   v = 0;
124   vec_resize (v, n_bytes);
125
126   error = clib_file_read_contents (file, v, n_bytes);
127
128   if (error)
129     vec_free (v);
130   else
131     *result = v;
132
133   return error;
134 }
135
136 __clib_export u8 *
137 clib_file_get_resolved_basename (char *fmt, ...)
138 {
139   va_list va;
140   char *p, buffer[PATH_MAX];
141   u8 *link, *s = 0;
142   int r;
143
144   va_start (va, fmt);
145   link = va_format (0, fmt, &va);
146   va_end (va);
147   vec_add1 (link, 0);
148
149   r = readlink ((char *) link, buffer, sizeof (buffer) - 1);
150   vec_free (link);
151
152   if (r < 1)
153     return 0;
154
155   buffer[r] = 0;
156   p = buffer + r - 1;
157   while (p > buffer && p[-1] != '/')
158     p--;
159
160   while (p[0])
161     vec_add1 (s, p++[0]);
162
163   vec_add1 (s, 0);
164   return s;
165 }
166
167 clib_error_t *
168 unix_proc_file_contents (char *file, u8 ** result)
169 {
170   u8 *rv = 0;
171   uword pos;
172   int bytes, fd;
173
174   /* Unfortunately, stat(/proc/XXX) returns zero... */
175   fd = open (file, O_RDONLY);
176
177   if (fd < 0)
178     return clib_error_return_unix (0, "open `%s'", file);
179
180   vec_validate (rv, 4095);
181   pos = 0;
182   while (1)
183     {
184       bytes = read (fd, rv + pos, 4096);
185       if (bytes < 0)
186         {
187           close (fd);
188           vec_free (rv);
189           return clib_error_return_unix (0, "read '%s'", file);
190         }
191
192       if (bytes == 0)
193         {
194           vec_set_len (rv, pos);
195           break;
196         }
197       pos += bytes;
198       vec_validate (rv, pos + 4095);
199     }
200   *result = rv;
201   close (fd);
202   return 0;
203 }
204
205 void os_panic (void) __attribute__ ((weak));
206
207 __clib_export void
208 os_panic (void)
209 {
210   abort ();
211 }
212
213 void os_exit (int) __attribute__ ((weak));
214
215 void
216 os_exit (int code)
217 {
218   exit (code);
219 }
220
221 void os_puts (u8 * string, uword string_length, uword is_error)
222   __attribute__ ((weak));
223
224 void
225 os_puts (u8 * string, uword string_length, uword is_error)
226 {
227   int cpu = os_get_thread_index ();
228   int nthreads = os_get_nthreads ();
229   char buf[64];
230   int fd = is_error ? 2 : 1;
231   struct iovec iovs[2];
232   int n_iovs = 0;
233
234   if (nthreads > 1)
235     {
236       snprintf (buf, sizeof (buf), "%d: ", cpu);
237
238       iovs[n_iovs].iov_base = buf;
239       iovs[n_iovs].iov_len = strlen (buf);
240       n_iovs++;
241     }
242
243   iovs[n_iovs].iov_base = string;
244   iovs[n_iovs].iov_len = string_length;
245   n_iovs++;
246
247   if (writev (fd, iovs, n_iovs) < 0)
248     ;
249 }
250
251 __clib_export __clib_weak void
252 os_out_of_memory (void)
253 {
254   os_panic ();
255 }
256
257 __clib_export __clib_weak uword
258 os_get_nthreads (void)
259 {
260   return 1;
261 }
262
263 /*
264  * fd.io coding-style-patch-verification: ON
265  *
266  * Local Variables:
267  * eval: (c-set-style "gnu")
268  * End:
269  */