Repair vlib API socket server
[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
42 #include <sys/stat.h>
43 #include <sys/types.h>
44 #include <sys/uio.h>            /* writev */
45 #include <fcntl.h>
46 #include <stdio.h>              /* for sprintf */
47
48 __thread uword __os_thread_index = 0;
49
50 clib_error_t *
51 clib_file_n_bytes (char *file, uword * result)
52 {
53   struct stat s;
54
55   if (stat (file, &s) < 0)
56     return clib_error_return_unix (0, "stat `%s'", file);
57
58   if (S_ISREG (s.st_mode))
59     *result = s.st_size;
60   else
61     *result = 0;
62
63   return /* no error */ 0;
64 }
65
66 clib_error_t *
67 clib_file_read_contents (char *file, u8 * result, uword n_bytes)
68 {
69   int fd = -1;
70   uword n_done, n_left;
71   clib_error_t *error = 0;
72   u8 *v = result;
73
74   if ((fd = open (file, 0)) < 0)
75     return clib_error_return_unix (0, "open `%s'", file);
76
77   n_left = n_bytes;
78   n_done = 0;
79   while (n_left > 0)
80     {
81       int n_read;
82       if ((n_read = read (fd, v + n_done, n_left)) < 0)
83         {
84           error = clib_error_return_unix (0, "open `%s'", file);
85           goto done;
86         }
87
88       /* End of file. */
89       if (n_read == 0)
90         break;
91
92       n_left -= n_read;
93       n_done += n_read;
94     }
95
96   if (n_left > 0)
97     {
98       error =
99         clib_error_return (0,
100                            " `%s' expected to read %wd bytes; read only %wd",
101                            file, n_bytes, n_bytes - n_left);
102       goto done;
103     }
104
105 done:
106   close (fd);
107   return error;
108 }
109
110 clib_error_t *
111 clib_file_contents (char *file, u8 ** result)
112 {
113   uword n_bytes;
114   clib_error_t *error = 0;
115   u8 *v;
116
117   if ((error = clib_file_n_bytes (file, &n_bytes)))
118     return error;
119
120   v = 0;
121   vec_resize (v, n_bytes);
122
123   error = clib_file_read_contents (file, v, n_bytes);
124
125   if (error)
126     vec_free (v);
127   else
128     *result = v;
129
130   return error;
131 }
132
133 clib_error_t *
134 unix_proc_file_contents (char *file, u8 ** result)
135 {
136   u8 *rv = 0;
137   uword pos;
138   int bytes, fd;
139
140   /* Unfortunately, stat(/proc/XXX) returns zero... */
141   fd = open (file, O_RDONLY);
142
143   if (fd < 0)
144     return clib_error_return_unix (0, "open `%s'", file);
145
146   vec_validate (rv, 4095);
147   pos = 0;
148   while (1)
149     {
150       bytes = read (fd, rv + pos, 4096);
151       if (bytes < 0)
152         {
153           close (fd);
154           vec_free (rv);
155           return clib_error_return_unix (0, "read '%s'", file);
156         }
157
158       if (bytes == 0)
159         {
160           _vec_len (rv) = pos;
161           break;
162         }
163       pos += bytes;
164       vec_validate (rv, pos + 4095);
165     }
166   *result = rv;
167   close (fd);
168   return 0;
169 }
170
171 void os_panic (void) __attribute__ ((weak));
172
173 void
174 os_panic (void)
175 {
176   abort ();
177 }
178
179 void os_exit (int) __attribute__ ((weak));
180
181 void
182 os_exit (int code)
183 {
184   exit (code);
185 }
186
187 void os_puts (u8 * string, uword string_length, uword is_error)
188   __attribute__ ((weak));
189
190 void
191 os_puts (u8 * string, uword string_length, uword is_error)
192 {
193   int cpu = os_get_thread_index ();
194   int nthreads = os_get_nthreads ();
195   char buf[64];
196   int fd = is_error ? 2 : 1;
197   struct iovec iovs[2];
198   int n_iovs = 0;
199
200   if (nthreads > 1)
201     {
202       snprintf (buf, sizeof (buf), "%d: ", cpu);
203
204       iovs[n_iovs].iov_base = buf;
205       iovs[n_iovs].iov_len = strlen (buf);
206       n_iovs++;
207     }
208
209   iovs[n_iovs].iov_base = string;
210   iovs[n_iovs].iov_len = string_length;
211   n_iovs++;
212
213   if (writev (fd, iovs, n_iovs) < 0)
214     ;
215 }
216
217 void os_out_of_memory (void) __attribute__ ((weak));
218 void
219 os_out_of_memory (void)
220 {
221   os_panic ();
222 }
223
224 uword os_get_nthreads (void) __attribute__ ((weak));
225 uword
226 os_get_nthreads (void)
227 {
228   return 1;
229 }
230
231 /*
232  * fd.io coding-style-patch-verification: ON
233  *
234  * Local Variables:
235  * eval: (c-set-style "gnu")
236  * End:
237  */