blob: b6e3cfc53aa0a59a986e29a5eda9a59672a4e6a1 [file] [log] [blame]
Lucas De Marchi4462c4a2011-11-29 18:05:43 -02001/*
2 * libkmod - interface to kernel module operations
3 *
4 * Copyright (C) 2011 ProFUSION embedded systems
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation version 2.1.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
Lucas De Marchi7e317da2011-11-30 19:20:19 -020020#include <assert.h>
Lucas De Marchi4462c4a2011-11-29 18:05:43 -020021#include <stdio.h>
22#include <stdlib.h>
23#include <stddef.h>
24#include <stdarg.h>
25#include <unistd.h>
26#include <errno.h>
27#include <string.h>
28#include <ctype.h>
29
30#include "libkmod.h"
31#include "libkmod-private.h"
32
33/*
34 * Read one logical line from a configuration file.
35 *
36 * Line endings may be escaped with backslashes, to form one logical line from
37 * several physical lines. No end of line character(s) are included in the
38 * result.
39 *
40 * If linenum is not NULL, it is incremented by the number of physical lines
41 * which have been read.
42 */
43char *getline_wrapped(FILE *fp, unsigned int *linenum)
44{
45 int size = 256;
46 int i = 0;
47 char *buf = malloc(size);
48 for(;;) {
49 int ch = getc_unlocked(fp);
50
51 switch(ch) {
52 case EOF:
53 if (i == 0) {
54 free(buf);
55 return NULL;
56 }
57 /* else fall through */
58
59 case '\n':
60 if (linenum)
61 (*linenum)++;
62 if (i == size)
63 buf = realloc(buf, size + 1);
64 buf[i] = '\0';
65 return buf;
66
67 case '\\':
68 ch = getc_unlocked(fp);
69
70 if (ch == '\n') {
71 if (linenum)
72 (*linenum)++;
73 continue;
74 }
75 /* else fall through */
76
77 default:
78 buf[i++] = ch;
79
80 if (i == size) {
81 size *= 2;
82 buf = realloc(buf, size);
83 }
84 }
85 }
86}
Lucas De Marchi8185fc92011-11-30 02:14:33 -020087
88/*
89 * Replace dashes with underscores.
90 * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
91 */
92char *underscores(struct kmod_ctx *ctx, char *s)
93{
94 unsigned int i;
95
96 if (!s)
97 return NULL;
98
99 for (i = 0; s[i]; i++) {
100 switch (s[i]) {
101 case '-':
102 s[i] = '_';
103 break;
104
105 case ']':
106 INFO(ctx, "Unmatched bracket in %s\n", s);
107 break;
108
109 case '[':
110 i += strcspn(&s[i], "]");
111 if (!s[i])
112 INFO(ctx, "Unmatched bracket in %s\n", s);
113 break;
114 }
115 }
116 return s;
117}
118
Lucas De Marchi7e317da2011-11-30 19:20:19 -0200119bool startswith(const char *s, const char *prefix) {
120 size_t sl, pl;
121
122 assert(s);
123 assert(prefix);
124
125 sl = strlen(s);
126 pl = strlen(prefix);
127
128 if (pl == 0)
129 return true;
130
131 if (sl < pl)
132 return false;
133
134 return memcmp(s, prefix, pl) == 0;
135}
Lucas De Marchie22c85f2011-12-02 17:21:18 -0200136
137inline void *memdup(const void *p, size_t n)
138{
139 void *r = malloc(n);
140
141 if (r == NULL)
142 return NULL;
143
144 return memcpy(r, p, n);
145}