2 * kmod - 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-2014 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, see <http://www.gnu.org/licenses/>.
32 #include <shared/missing.h>
33 #include <shared/util.h>
35 #define USEC_PER_SEC 1000000ULL
36 #define NSEC_PER_USEC 1000ULL
38 static const struct kmod_ext
{
42 {KMOD_EXTENSION_UNCOMPRESSED
, sizeof(KMOD_EXTENSION_UNCOMPRESSED
) - 1},
44 {".ko.gz", sizeof(".ko.gz") - 1},
47 {".ko.xz", sizeof(".ko.xz") - 1},
52 assert_cc(EAGAIN
== EWOULDBLOCK
);
54 /* string handling functions and memory allocations */
55 /* ************************************************************************ */
57 void *memdup(const void *p
, size_t n
)
64 return memcpy(r
, p
, n
);
67 char *strchr_replace(char *s
, char c
, char r
)
71 for (p
= s
; *p
!= '\0'; p
++) {
79 /* module-related functions */
80 /* ************************************************************************ */
81 int alias_normalize(const char *alias
, char buf
[static PATH_MAX
], size_t *len
)
85 for (i
= 0; i
< PATH_MAX
- 1; i
++) {
86 const char c
= alias
[i
];
94 while (alias
[i
] != ']' && alias
[i
] != '\0') {
120 * Replace dashes with underscores.
121 * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
123 * For convenience, it returns error if @s is NULL
125 int underscores(char *s
)
132 for (i
= 0; s
[i
]; i
++) {
140 i
+= strcspn(&s
[i
], "]");
150 char *modname_normalize(const char *modname
, char buf
[static PATH_MAX
], size_t *len
)
154 for (s
= 0; s
< PATH_MAX
- 1; s
++) {
155 const char c
= modname
[s
];
158 else if (c
== '\0' || c
== '.')
172 char *path_to_modname(const char *path
, char buf
[static PATH_MAX
], size_t *len
)
176 modname
= basename(path
);
177 if (modname
== NULL
|| modname
[0] == '\0')
180 return modname_normalize(modname
, buf
, len
);
183 bool path_ends_with_kmod_ext(const char *path
, size_t len
)
185 const struct kmod_ext
*eitr
;
187 for (eitr
= kmod_exts
; eitr
->ext
!= NULL
; eitr
++) {
188 if (len
<= eitr
->len
)
190 if (streq(path
+ len
- eitr
->len
, eitr
->ext
))
197 /* read-like and fread-like functions */
198 /* ************************************************************************ */
199 ssize_t
read_str_safe(int fd
, char *buf
, size_t buflen
)
201 size_t todo
= buflen
- 1;
205 ssize_t r
= read(fd
, buf
+ done
, todo
);
213 if (errno
== EAGAIN
|| errno
== EINTR
)
224 ssize_t
write_str_safe(int fd
, const char *buf
, size_t buflen
)
226 size_t todo
= buflen
;
230 ssize_t r
= write(fd
, buf
+ done
, todo
);
238 if (errno
== EAGAIN
|| errno
== EINTR
)
248 int read_str_long(int fd
, long *value
, int base
)
255 err
= read_str_safe(fd
, buf
, sizeof(buf
));
259 v
= strtol(buf
, &end
, base
);
260 if (end
== buf
|| !isspace(*end
))
267 int read_str_ulong(int fd
, unsigned long *value
, int base
)
274 err
= read_str_safe(fd
, buf
, sizeof(buf
));
278 v
= strtoul(buf
, &end
, base
);
279 if (end
== buf
|| !isspace(*end
))
286 * Read one logical line from a configuration file.
288 * Line endings may be escaped with backslashes, to form one logical line from
289 * several physical lines. No end of line character(s) are included in the
292 * If linenum is not NULL, it is incremented by the number of physical lines
293 * which have been read.
295 char *freadline_wrapped(FILE *fp
, unsigned int *linenum
)
299 _cleanup_free_
char *buf
= malloc(size
);
305 int ch
= getc_unlocked(fp
);
311 /* else fall through */
326 ch
= getc_unlocked(fp
);
332 /* else fall through */
340 tmp
= realloc(buf
, size
);
349 /* path handling functions */
350 /* ************************************************************************ */
352 bool path_is_absolute(const char *p
)
359 char *path_make_absolute_cwd(const char *p
)
361 _cleanup_free_
char *cwd
= NULL
;
365 if (path_is_absolute(p
))
368 cwd
= get_current_dir_name();
373 cwdlen
= strlen(cwd
);
375 /* cwd + '/' + p + '\0' */
376 r
= realloc(cwd
, cwdlen
+ 1 + plen
+ 1);
382 memcpy(&r
[cwdlen
+ 1], p
, plen
+ 1);
387 static inline int is_dir(const char *path
)
391 if (stat(path
, &st
) >= 0)
392 return S_ISDIR(st
.st_mode
);
397 int mkdir_p(const char *path
, int len
, mode_t mode
)
401 start
= strndupa(path
, len
);
405 * scan backwards, replacing '/' with '\0' while the component doesn't
409 int r
= is_dir(start
);
413 if (end
== start
+ len
)
416 /* end != start, since it would be caught on the first
428 /* Find the next component, backwards, discarding extra '/'*/
429 while (end
> start
&& *end
!= '/')
432 while (end
> start
&& *(end
- 1) == '/')
436 for (; end
< start
+ len
;) {
437 if (mkdir(start
, mode
) < 0 && errno
!= EEXIST
)
447 int mkdir_parents(const char *path
, mode_t mode
)
449 char *end
= strrchr(path
, '/');
451 /* no parent directories */
455 return mkdir_p(path
, end
- path
, mode
);
458 unsigned long long ts_usec(const struct timespec
*ts
)
460 return (unsigned long long) ts
->tv_sec
* USEC_PER_SEC
+
461 (unsigned long long) ts
->tv_nsec
/ NSEC_PER_USEC
;
464 unsigned long long stat_mstamp(const struct stat
*st
)
466 #ifdef HAVE_STRUCT_STAT_ST_MTIM
467 return ts_usec(&st
->st_mtim
);
469 return (unsigned long long) st
->st_mtime
;