]>
git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod-util.c
2 * libkmod - interface to kernel module operations
4 * Copyright (C) 2011-2013 ProFUSION embedded systems
5 * Copyright (C) 2012 Lucas De Marchi <lucas.de.marchi@gmail.com>
6 * Copyright (C) 2013 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "libkmod-internal.h"
37 * Read one logical line from a configuration file.
39 * Line endings may be escaped with backslashes, to form one logical line from
40 * several physical lines. No end of line character(s) are included in the
43 * If linenum is not NULL, it is incremented by the number of physical lines
44 * which have been read.
46 char *getline_wrapped(FILE *fp
, unsigned int *linenum
)
50 _cleanup_free_
char *buf
= malloc(size
);
56 int ch
= getc_unlocked(fp
);
62 /* else fall through */
70 ret
= realloc(buf
, size
+ 1);
83 ch
= getc_unlocked(fp
);
89 /* else fall through */
97 tmp
= realloc(buf
, size
);
106 inline int alias_normalize(const char *alias
, char buf
[PATH_MAX
], size_t *len
)
110 for (s
= 0; s
< PATH_MAX
- 1; s
++) {
111 const char c
= alias
[s
];
119 while (alias
[s
] != ']' && alias
[s
] != '\0') {
145 inline char *modname_normalize(const char *modname
, char buf
[PATH_MAX
],
150 for (s
= 0; s
< PATH_MAX
- 1; s
++) {
151 const char c
= modname
[s
];
154 else if (c
== '\0' || c
== '.')
168 char *path_to_modname(const char *path
, char buf
[PATH_MAX
], size_t *len
)
172 modname
= basename(path
);
173 if (modname
== NULL
|| modname
[0] == '\0')
176 return modname_normalize(modname
, buf
, len
);
179 inline void *memdup(const void *p
, size_t n
)
186 return memcpy(r
, p
, n
);
189 ssize_t
read_str_safe(int fd
, char *buf
, size_t buflen
)
191 size_t todo
= buflen
- 1;
195 ssize_t r
= read(fd
, buf
+ done
, todo
);
203 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
||
215 ssize_t
write_str_safe(int fd
, const char *buf
, size_t buflen
)
217 size_t todo
= buflen
;
221 ssize_t r
= write(fd
, buf
+ done
, todo
);
229 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
||
240 int read_str_long(int fd
, long *value
, int base
)
247 err
= read_str_safe(fd
, buf
, sizeof(buf
));
251 v
= strtol(buf
, &end
, base
);
252 if (end
== buf
|| !isspace(*end
))
259 int read_str_ulong(int fd
, unsigned long *value
, int base
)
266 err
= read_str_safe(fd
, buf
, sizeof(buf
));
270 v
= strtoul(buf
, &end
, base
);
271 if (end
== buf
|| !isspace(*end
))
277 char *strchr_replace(char *s
, int c
, char r
)
281 for (p
= s
; *p
!= '\0'; p
++)
288 bool path_is_absolute(const char *p
)
295 char *path_make_absolute_cwd(const char *p
)
297 _cleanup_free_
char *cwd
= NULL
;
301 if (path_is_absolute(p
))
304 cwd
= get_current_dir_name();
309 cwdlen
= strlen(cwd
);
311 /* cwd + '/' + p + '\0' */
312 r
= realloc(cwd
, cwdlen
+ 1 + plen
+ 1);
318 memcpy(&r
[cwdlen
+ 1], p
, plen
+ 1);
323 static inline int is_dir(const char *path
)
327 if (stat(path
, &st
) >= 0)
328 return S_ISDIR(st
.st_mode
);
333 int mkdir_p(const char *path
, int len
, mode_t mode
)
337 start
= strndupa(path
, len
);
341 * scan backwards, replacing '/' with '\0' while the component doesn't
345 int r
= is_dir(start
);
349 if (end
== start
+ len
)
352 /* end != start, since it would be caught on the first
364 /* Find the next component, backwards, discarding extra '/'*/
365 while (end
> start
&& *end
!= '/')
368 while (end
> start
&& *(end
- 1) == '/')
372 for (; end
< start
+ len
;) {
373 if (mkdir(start
, mode
) < 0 && errno
!= EEXIST
)
383 int mkdir_parents(const char *path
, mode_t mode
)
385 char *end
= strrchr(path
, '/');
387 /* no parent directories */
391 return mkdir_p(path
, end
- path
, mode
);
394 const struct kmod_ext kmod_exts
[] = {
395 {".ko", sizeof(".ko") - 1},
397 {".ko.gz", sizeof(".ko.gz") - 1},
400 {".ko.xz", sizeof(".ko.xz") - 1},
405 bool path_ends_with_kmod_ext(const char *path
, size_t len
)
407 const struct kmod_ext
*eitr
;
409 for (eitr
= kmod_exts
; eitr
->ext
!= NULL
; eitr
++) {
410 if (len
<= eitr
->len
)
412 if (streq(path
+ len
- eitr
->len
, eitr
->ext
))
419 #define USEC_PER_SEC 1000000ULL
420 #define NSEC_PER_USEC 1000ULL
421 unsigned long long ts_usec(const struct timespec
*ts
)
423 return (unsigned long long) ts
->tv_sec
* USEC_PER_SEC
+
424 (unsigned long long) ts
->tv_nsec
/ NSEC_PER_USEC
;
427 unsigned long long stat_mstamp(const struct stat
*st
)
429 #ifdef HAVE_STRUCT_STAT_ST_MTIM
430 return ts_usec(&st
->st_mtim
);
432 return (unsigned long long) st
->st_mtime
;