2 Low level event script handling
4 Copyright (C) Amitay Isaacs 2017
5 Copyright (C) Martin Schwenke 2018
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "system/dir.h"
24 #include "system/glob.h"
28 #include "common/event_script.h"
30 static int script_filter(const struct dirent *de)
34 /* Match a script pattern */
35 ret = fnmatch("[0-9][0-9].*.script", de->d_name, 0);
43 int event_script_get_list(TALLOC_CTX *mem_ctx,
44 const char *script_dir,
45 struct event_script_list **out)
47 struct dirent **namelist = NULL;
48 struct event_script_list *script_list = NULL;
53 count = scandir(script_dir, &namelist, script_filter, alphasort);
59 script_list = talloc_zero(mem_ctx, struct event_script_list);
60 if (script_list == NULL) {
70 script_list->num_scripts = count;
71 script_list->script = talloc_zero_array(script_list,
72 struct event_script *,
74 if (script_list->script == NULL) {
78 ds_len = strlen(".script");
79 for (i = 0; i < count; i++) {
80 struct event_script *s;
83 s = talloc_zero(script_list->script, struct event_script);
88 script_list->script[i] = s;
90 s->name = talloc_strndup(script_list->script,
92 strlen(namelist[i]->d_name) - ds_len);
93 if (s->name == NULL) {
97 s->path = talloc_asprintf(script_list->script,
100 namelist[i]->d_name);
101 if (s->path == NULL) {
105 ret = stat(s->path, &statbuf);
108 * If ret != 0 this is either a dangling
109 * symlink or it has just disappeared. Either
110 * way, it isn't executable. See the note
111 * below about things that have disappeared.
113 if (statbuf.st_mode & S_IXUSR) {
124 talloc_free(script_list);
127 if (namelist != NULL && count != -1) {
128 for (i=0; i<count; i++) {
137 int event_script_chmod(const char *script_dir,
138 const char *script_name,
141 const char *dot_script = ".script";
142 size_t ds_len = strlen(dot_script);
143 size_t sn_len = strlen(script_name);
147 const char *script_file;
149 char filename[PATH_MAX];
155 /* Allow script_name to already have ".script" suffix */
156 if (sn_len > ds_len &&
157 strcmp(&script_name[sn_len - ds_len], dot_script) == 0) {
158 script_file = script_name;
160 ret = snprintf(buf, sizeof(buf), "%s.script", script_name);
161 if (ret >= sizeof(buf)) {
167 dirp = opendir(script_dir);
173 while ((de = readdir(dirp)) != NULL) {
174 if (strcmp(de->d_name, script_file) == 0) {
175 /* check for valid script names */
176 ret = script_filter(de);
183 found_inode = de->d_ino;
193 ret = snprintf(filename,
198 if (ret >= sizeof(filename)) {
202 fd = open(filename, O_RDWR);
208 ret = fstat(fd, &st);
215 * If the directory entry inode number doesn't match the one
216 * returned by fstat() then this is probably a symlink, so the
217 * caller should not be calling this function. Note that this
218 * is a cheap sanity check to catch most programming errors.
219 * This doesn't cost any extra system calls but can still miss
220 * the unlikely case where the symlink is to a file on a
221 * different filesystem with the same inode number as the
224 if (found && found_inode != st.st_ino) {
230 new_mode = st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH);
232 new_mode = st.st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH);
235 ret = fchmod(fd, new_mode);