7 #include <sys/sysmacros.h>
9 #include <sys/utsname.h>
11 #include <sys/resource.h>
16 #include <mpath_persist.h>
31 for (i=strlen(str)-1; i >=0 && isspace(str[i]); --i) ;
37 basenamecpy (const char *src, char *dst, size_t size)
41 if (!src || !dst || !strlen(src))
46 for (e = p + strlen(p) - 1; e >= p && isspace(*e); --e) ;
47 if (e < p || e - p > size - 2)
50 strlcpy(dst, p, e - p + 2);
55 filepresent (char * run) {
63 char *get_next_string(char **temp, char *split_char)
66 token = strsep(temp, split_char);
67 while (token != NULL && !strcmp(token, ""))
68 token = strsep(temp, split_char);
73 get_word (char * sentence, char ** word)
82 while (*sentence == ' ') {
86 if (*sentence == '\0')
91 while (*p != ' ' && *p != '\0')
94 len = (int) (p - sentence);
99 *word = MALLOC(len + 1);
102 condlog(0, "get_word : oom");
105 strncpy(*word, sentence, len);
107 condlog(4, "*word = %s, len = %i", *word, len);
115 size_t strlcpy(char *dst, const char *src, size_t size)
122 while ((ch = *p++)) {
128 /* If size == 0 there is no space for a final null... */
134 size_t strlcat(char *dst, const char *src, size_t size)
141 while (bytes < size && *q) {
146 return (bytes + strlen(src));
148 while ((ch = *p++)) {
158 int devt2devname(char *devname, int devname_len, char *devt)
161 unsigned int tmpmaj, tmpmin, major, minor;
162 char dev[FILE_NAME_SIZE];
163 char block_path[PATH_SIZE];
166 memset(block_path, 0, sizeof(block_path));
167 memset(dev, 0, sizeof(dev));
168 if (sscanf(devt, "%u:%u", &major, &minor) != 2) {
169 condlog(0, "Invalid device number %s", devt);
173 if (devname_len > FILE_NAME_SIZE)
174 devname_len = FILE_NAME_SIZE;
176 if (stat("/sys/dev/block", &statbuf) == 0) {
177 /* Newer kernels have /sys/dev/block */
178 sprintf(block_path,"/sys/dev/block/%u:%u", major, minor);
179 if (lstat(block_path, &statbuf) == 0) {
180 if (S_ISLNK(statbuf.st_mode) &&
181 readlink(block_path, dev, FILE_NAME_SIZE-1) > 0) {
182 char *p = strrchr(dev, '/');
185 condlog(0, "No sysfs entry for %s",
190 strncpy(devname, p, devname_len);
196 memset(block_path, 0, sizeof(block_path));
198 if (!(fd = fopen("/proc/partitions", "r"))) {
199 condlog(0, "Cannot open /proc/partitions");
204 int r = fscanf(fd,"%u %u %*d %s",&tmpmaj, &tmpmin, dev);
206 r = fscanf(fd,"%*s\n");
212 if ((major == tmpmaj) && (minor == tmpmin)) {
213 if (snprintf(block_path, sizeof(block_path),
214 "/sys/block/%s", dev) >= sizeof(block_path)) {
215 condlog(0, "device name %s is too long", dev);
224 if (strncmp(block_path,"/sys/block", 10)) {
225 condlog(3, "No device found for %u:%u", major, minor);
229 if (stat(block_path, &statbuf) < 0) {
230 condlog(0, "No sysfs entry for %s", block_path);
234 if (S_ISDIR(statbuf.st_mode) == 0) {
235 condlog(0, "sysfs entry %s is not a directory", block_path);
238 basenamecpy((const char *)block_path, devname, devname_len);
242 /* This function returns a pointer inside of the supplied pathname string.
243 * If is_path_device is true, it may also modify the supplied string */
244 char *convert_dev(char *name, int is_path_device)
250 if (is_path_device) {
251 ptr = strstr(name, "cciss/");
257 if (!strncmp(name, "/dev/", 5) && strlen(name) > 5)
264 dev_t parse_devt(const char *dev_t)
268 if (sscanf(dev_t,"%d:%d", &maj, &min) != 2)
271 return makedev(maj, min);
274 char *parse_uid_attribute_by_attrs(char *uid_attrs, char *path_dev)
277 char *uid_attr_record;
283 if(!uid_attrs || !path_dev)
286 count = get_word(uid_attrs, &uid_attr_record);
287 while (uid_attr_record) {
288 tmp = strrchr(uid_attr_record, ':');
290 free(uid_attr_record);
294 count = get_word(uid_attrs, &uid_attr_record);
297 dev = uid_attr_record;
301 if(!strncmp(path_dev, dev, strlen(dev))) {
302 uid_attribute = STRDUP(attr);
303 free(uid_attr_record);
304 return uid_attribute;
307 free(uid_attr_record);
311 count = get_word(uid_attrs, &uid_attr_record);
317 setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached)
321 ret = pthread_attr_init(attr);
323 if (stacksize < PTHREAD_STACK_MIN)
324 stacksize = PTHREAD_STACK_MIN;
325 ret = pthread_attr_setstacksize(attr, stacksize);
328 ret = pthread_attr_setdetachstate(attr,
329 PTHREAD_CREATE_DETACHED);
334 int systemd_service_enabled_in(const char *dev, const char *prefix)
336 char path[PATH_SIZE], file[PATH_MAX], service[PATH_SIZE];
341 snprintf(service, PATH_SIZE, "multipathd.service");
342 snprintf(path, PATH_SIZE, "%s/systemd/system", prefix);
343 condlog(3, "%s: checking for %s in %s", dev, service, path);
345 dirfd = opendir(path);
349 while ((d = readdir(dirfd)) != NULL) {
353 if ((strcmp(d->d_name,".") == 0) ||
354 (strcmp(d->d_name,"..") == 0))
357 if (strlen(d->d_name) < 6)
360 p = d->d_name + strlen(d->d_name) - 6;
361 if (strcmp(p, ".wants"))
363 snprintf(file, sizeof(file), "%s/%s/%s",
364 path, d->d_name, service);
365 if (stat(file, &stbuf) == 0) {
366 condlog(3, "%s: found %s", dev, file);
376 int systemd_service_enabled(const char *dev)
380 found = systemd_service_enabled_in(dev, "/etc");
382 found = systemd_service_enabled_in(dev, "/usr/lib");
384 found = systemd_service_enabled_in(dev, "/lib");
386 found = systemd_service_enabled_in(dev, "/run");
390 static int _linux_version_code;
391 static pthread_once_t _lvc_initialized = PTHREAD_ONCE_INIT;
393 /* Returns current kernel version encoded as major*65536 + minor*256 + patch,
394 * so, for example, to check if the kernel is greater than 2.2.11:
396 * if (get_linux_version_code() > KERNEL_VERSION(2,2,11)) { <stuff> }
398 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
399 * Code copied from busybox (GPLv2 or later)
402 _set_linux_version_code(void)
408 uname(&name); /* never fails */
411 for (i = 0; i < 3; i++) {
413 r = r * 256 + (t ? atoi(t) : 0);
416 _linux_version_code = r;
419 int get_linux_version_code(void)
421 pthread_once(&_lvc_initialized, _set_linux_version_code);
422 return _linux_version_code;
425 int parse_prkey(char *ptr, uint64_t *prkey)
431 if (*ptr == 'x' || *ptr == 'X')
433 if (*ptr == '\0' || strlen(ptr) > 16)
435 if (strlen(ptr) != strspn(ptr, "0123456789aAbBcCdDeEfF"))
437 if (sscanf(ptr, "%" SCNx64 "", prkey) != 1)
442 int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags)
446 flagstr = strchr(ptr, ':');
450 if (strlen(flagstr) == 5 && strcmp(flagstr, "aptpl") == 0)
451 *flags = MPATH_F_APTPL_MASK;
453 return parse_prkey(ptr, prkey);
456 int safe_write(int fd, const void *buf, size_t count)
459 ssize_t r = write(fd, buf, count);
466 buf = (const char *)buf + r;
471 void set_max_fds(int max_fds)
473 struct rlimit fd_limit;
478 if (getrlimit(RLIMIT_NOFILE, &fd_limit) < 0) {
479 condlog(0, "can't get open fds limit: %s",
481 fd_limit.rlim_cur = 0;
482 fd_limit.rlim_max = 0;
484 if (fd_limit.rlim_cur < max_fds) {
485 fd_limit.rlim_cur = max_fds;
486 if (fd_limit.rlim_max < max_fds)
487 fd_limit.rlim_max = max_fds;
488 if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) {
489 condlog(0, "can't set open fds limit to "
491 fd_limit.rlim_cur, fd_limit.rlim_max,
494 condlog(3, "set open fds limit to %lu/%lu",
495 fd_limit.rlim_cur, fd_limit.rlim_max);
500 void free_scandir_result(struct scandir_result *res)
504 for (i = 0; i < res->n; i++)