364cbbdbc10561a2b942e5905d82b0f0633566a4
[libsamsung-ipc.git] / samsung-ipc / utils.c
1 /*
2  * This file is part of libsamsung-ipc.
3  *
4  * Copyright (C) 2013-2014 Paul Kocialkowski <contact@paulk.fr>
5  *
6  * libsamsung-ipc is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * libsamsung-ipc is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <ctype.h>
26 #include <sys/ioctl.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <asm/types.h>
31 #include <linux/netlink.h>
32 #include <net/if.h>
33
34 #include "utils.h"
35
36 void *file_data_read(const char *path, size_t size, size_t chunk_size,
37     size_t offset)
38 {
39     void *data = NULL;
40     int fd = -1;
41     size_t count;
42     off_t seek;
43     unsigned char *p;
44     int rc;
45
46     if (path == NULL || size == 0 || chunk_size == 0 || chunk_size > size)
47         return NULL;
48
49     fd = open(path, O_RDONLY);
50     if (fd < 0)
51         goto error;
52
53     seek = lseek(fd, (off_t) offset, SEEK_SET);
54     if (seek < (off_t) offset)
55         goto error;
56
57     data = calloc(1, size);
58
59     p = (unsigned char *) data;
60
61     count = 0;
62     while (count < size) {
63         rc = read(fd, p, size - count > chunk_size ? chunk_size : size - count);
64         if (rc <= 0)
65             goto error;
66
67         p += rc;
68         count += rc;
69     }
70
71     goto complete;
72
73 error:
74     if (data != NULL) {
75         free(data);
76         data = NULL;
77     }
78
79 complete:
80     if (fd >= 0)
81         close(fd);
82
83     return data;
84 }
85
86 int file_data_write(const char *path, const void *data, size_t size,
87     size_t chunk_size, size_t offset)
88 {
89     int fd = -1;
90     size_t count;
91     off_t seek;
92     unsigned char *p;
93     int rc;
94
95     if (path == NULL || data == NULL || size == 0 || chunk_size == 0 || chunk_size > size)
96         return -1;
97
98     fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
99     if (fd < 0)
100         goto error;
101
102     seek = lseek(fd, (off_t) offset, SEEK_SET);
103     if (seek < (off_t) offset)
104         goto error;
105
106     p = (unsigned char *) data;
107
108     count = 0;
109     while (count < size) {
110         rc = write(fd, p, size - count > chunk_size ? chunk_size : size - count);
111         if (rc <= 0)
112             goto error;
113
114         p += rc;
115         count += rc;
116     }
117
118     rc = 0;
119     goto complete;
120
121 error:
122     rc = -1;
123
124 complete:
125     if (fd >= 0)
126         close(fd);
127
128     return rc;
129 }
130
131 int network_iface_up(const char *iface, int domain, int type)
132 {
133     struct ifreq ifr;
134     int fd = -1;
135     int rc;
136
137     if (iface == NULL)
138         return -1;
139
140     memset(&ifr, 0, sizeof(ifr));
141     strncpy(ifr.ifr_name, iface, IFNAMSIZ);
142
143     fd = socket(domain, type, 0);
144     if (fd < 0)
145         goto error;
146
147     rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
148     if (rc < 0)
149         goto error;
150
151     ifr.ifr_flags |= IFF_UP;
152
153     rc = ioctl(fd, SIOCSIFFLAGS, &ifr);
154     if (rc < 0)
155         goto error;
156
157     rc = 0;
158     goto complete;
159
160 error:
161     rc = -1;
162
163 complete:
164     if (fd >= 0)
165         close(fd);
166
167     return rc;
168 }
169
170 int network_iface_down(const char *iface, int domain, int type)
171 {
172     struct ifreq ifr;
173     int fd = -1;
174     int rc;
175
176     if (iface == NULL)
177         return -1;
178
179     memset(&ifr, 0, sizeof(ifr));
180     strncpy(ifr.ifr_name, iface, IFNAMSIZ);
181
182     fd = socket(domain, type, 0);
183     if (fd < 0)
184         goto error;
185
186     rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
187     if (rc < 0)
188         goto error;
189
190     ifr.ifr_flags = (ifr.ifr_flags & (~IFF_UP));
191
192     rc = ioctl(fd, SIOCSIFFLAGS, &ifr);
193     if (rc < 0)
194         goto error;
195
196     rc = 0;
197     goto complete;
198
199 error:
200     rc = -1;
201
202 complete:
203     if (fd >= 0)
204         close(fd);
205
206     return rc;
207 }
208
209 int sysfs_value_read(const char *path)
210 {
211     char buffer[100];
212     int value;
213     int fd = -1;
214     int rc;
215
216     if (path == NULL)
217         return -1;
218
219     fd = open(path, O_RDONLY);
220     if (fd < 0)
221         goto error;
222
223     rc = read(fd, &buffer, sizeof(buffer));
224     if (rc <= 0)
225         goto error;
226
227     value = atoi(buffer);
228     goto complete;
229
230 error:
231     value = -1;
232
233 complete:
234     if (fd >= 0)
235         close(fd);
236
237     return value;
238 }
239
240 int sysfs_value_write(const char *path, int value)
241 {
242     char buffer[100];
243     int fd = -1;
244     int rc;
245
246     if (path == NULL)
247         return -1;
248
249     fd = open(path, O_WRONLY);
250     if (fd < 0)
251         goto error;
252
253     snprintf((char *) &buffer, sizeof(buffer), "%d\n", value);
254
255     rc = write(fd, buffer, strlen(buffer));
256     if (rc < (int) strlen(buffer))
257         goto error;
258
259     rc = 0;
260     goto complete;
261
262 error:
263     rc = -1;
264
265 complete:
266     if (fd >= 0)
267         close(fd);
268
269     return rc;
270 }
271
272 char *sysfs_string_read(const char *path, size_t length)
273 {
274     char *string = NULL;
275     int fd = -1;
276     int rc;
277
278     if (path == NULL || length == 0)
279         return NULL;
280
281     fd = open(path, O_RDONLY);
282     if (fd < 0)
283         goto error;
284
285     string = (char *) calloc(1, length);
286
287     rc = read(fd, string, length);
288     if (rc <= 0)
289         goto error;
290
291     goto complete;
292
293 error:
294     if (string != NULL) {
295         free(string);
296         string = NULL;
297     }
298
299 complete:
300     if (fd >= 0)
301         close(fd);
302
303     return string;
304 }
305
306 int sysfs_string_write(const char *path, const char *buffer, size_t length)
307 {
308     int fd = -1;
309     int rc;
310
311     if (path == NULL || buffer == NULL || length == 0)
312         return -1;
313
314     fd = open(path, O_WRONLY);
315     if (fd < 0)
316         goto error;
317
318     rc = write(fd, buffer, length);
319     if (rc < (int) length)
320         goto error;
321
322     rc = 0;
323     goto complete;
324
325 error:
326     rc = -1;
327
328 complete:
329     if (fd >= 0)
330         close(fd);
331
332     return rc;
333 }
334
335 char *data2string(const void *data, size_t size)
336 {
337     char *string;
338     size_t length;
339     char *p;
340     size_t i;
341
342     if (data == NULL || size == 0)
343         return NULL;
344
345     length = size * 2 + 1;
346     string = (char *) calloc(1, length);
347
348     p = string;
349
350     for (i = 0; i < size; i++) {
351         sprintf(p, "%02x", *((unsigned char *) data + i));
352         p += 2 * sizeof(char);
353     }
354
355     return string;
356 }
357
358 void *string2data(const char *string, size_t *size_p)
359 {
360     void *data;
361     size_t size;
362     size_t length;
363     int shift;
364     unsigned char *p;
365     unsigned int b;
366     size_t i;
367     int rc;
368
369     if (string == NULL)
370         return NULL;
371
372     length = strlen(string);
373     if (length == 0)
374         return NULL;
375
376     if (length % 2 == 0) {
377         size = length / 2;
378         shift = 0;
379     } else {
380         size = (length - (length % 2)) / 2 + 1;
381         shift = 1;
382     }
383
384     data = calloc(1, size);
385
386     p = (unsigned char *) data;
387
388     for (i = 0; i < length; i++) {
389         rc = sscanf(&string[i], "%01x", &b);
390         if (rc < 1)
391             b = 0;
392
393         if ((shift % 2) == 0)
394             *p |= ((b & 0x0f) << 4);
395         else
396             *p++ |= b & 0x0f;
397
398         shift++;
399     }
400
401     if (size_p != NULL)
402         *size_p = size;
403
404     return data;
405 }
406
407 // vim:ts=4:sw=4:expandtab