pacemaker  1.1.16-94ff4df
Scalable High-Availability cluster resource manager
procfs.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <crm_internal.h>
20 
21 #ifndef _GNU_SOURCE
22 # define _GNU_SOURCE
23 #endif
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <dirent.h>
31 
45 int
46 crm_procfs_process_info(struct dirent *entry, char *name, int *pid)
47 {
48  int fd, local_pid;
49  FILE *file;
50  struct stat statbuf;
51  char key[16] = { 0 }, procpath[128] = { 0 };
52 
53  /* We're only interested in entries whose name is a PID,
54  * so skip anything non-numeric or that is too long.
55  *
56  * 114 = 128 - strlen("/proc/") - strlen("/status") - 1
57  */
58  local_pid = atoi(entry->d_name);
59  if ((local_pid <= 0) || (strlen(entry->d_name) > 114)) {
60  return -1;
61  }
62  if (pid) {
63  *pid = local_pid;
64  }
65 
66  /* Get this entry's file information */
67  strcpy(procpath, "/proc/");
68  strcat(procpath, entry->d_name);
69  fd = open(procpath, O_RDONLY);
70  if (fd < 0 ) {
71  return -1;
72  }
73  if (fstat(fd, &statbuf) < 0) {
74  close(fd);
75  return -1;
76  }
77  close(fd);
78 
79  /* We're only interested in subdirectories */
80  if (!S_ISDIR(statbuf.st_mode)) {
81  return -1;
82  }
83 
84  /* Read the first entry ("Name:") from the process's status file.
85  * We could handle the valgrind case if we parsed the cmdline file
86  * instead, but that's more of a pain than it's worth.
87  */
88  if (name != NULL) {
89  strcat(procpath, "/status");
90  file = fopen(procpath, "r");
91  if (!file) {
92  return -1;
93  }
94  if ((fscanf(file, "%15s%63s", key, name) != 2)
95  || safe_str_neq(key, "Name:")) {
96  fclose(file);
97  return -1;
98  }
99  fclose(file);
100  }
101 
102  return 0;
103 }
104 
116 int
117 crm_procfs_pid_of(const char *name)
118 {
119  DIR *dp;
120  struct dirent *entry;
121  int pid = 0;
122  char entry_name[64] = { 0 };
123 
124  dp = opendir("/proc");
125  if (dp == NULL) {
126  crm_notice("Can not read /proc directory to track existing components");
127  return 0;
128  }
129 
130  while ((entry = readdir(dp)) != NULL) {
131  if ((crm_procfs_process_info(entry, entry_name, &pid) == 0)
132  && safe_str_eq(entry_name, name)
133  && (crm_pid_active(pid, NULL) == 1)) {
134 
135  crm_info("Found %s active as process %d", name, pid);
136  break;
137  }
138  pid = 0;
139  }
140  closedir(dp);
141  return pid;
142 }
#define crm_notice(fmt, args...)
Definition: logging.h:250
int crm_pid_active(long pid, const char *daemon)
Definition: utils.c:1018
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:150
uint32_t pid
Definition: internal.h:49
int crm_procfs_process_info(struct dirent *entry, char *name, int *pid)
Definition: procfs.c:46
#define safe_str_eq(a, b)
Definition: util.h:63
#define crm_info(fmt, args...)
Definition: logging.h:251
int crm_procfs_pid_of(const char *name)
Definition: procfs.c:117