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
) {
125 talloc_free(script_list
);
128 if (namelist
!= NULL
&& count
!= -1) {
129 for (i
=0; i
<count
; i
++) {
138 int event_script_chmod(const char *script_dir
,
139 const char *script_name
,
142 const char *dot_script
= ".script";
143 size_t ds_len
= strlen(dot_script
);
144 size_t sn_len
= strlen(script_name
);
148 const char *script_file
;
150 char filename
[PATH_MAX
];
156 /* Allow script_name to already have ".script" suffix */
157 if (sn_len
> ds_len
&&
158 strcmp(&script_name
[sn_len
- ds_len
], dot_script
) == 0) {
159 script_file
= script_name
;
161 ret
= snprintf(buf
, sizeof(buf
), "%s.script", script_name
);
162 if (ret
< 0 || (size_t)ret
>= sizeof(buf
)) {
168 dirp
= opendir(script_dir
);
174 while ((de
= readdir(dirp
)) != NULL
) {
175 if (strcmp(de
->d_name
, script_file
) == 0) {
176 /* check for valid script names */
177 ret
= script_filter(de
);
184 found_inode
= de
->d_ino
;
194 ret
= snprintf(filename
,
199 if (ret
< 0 || (size_t)ret
>= sizeof(filename
)) {
203 fd
= open(filename
, O_RDWR
);
209 ret
= fstat(fd
, &st
);
216 * If the directory entry inode number doesn't match the one
217 * returned by fstat() then this is probably a symlink, so the
218 * caller should not be calling this function. Note that this
219 * is a cheap sanity check to catch most programming errors.
220 * This doesn't cost any extra system calls but can still miss
221 * the unlikely case where the symlink is to a file on a
222 * different filesystem with the same inode number as the
225 if (found
&& found_inode
!= st
.st_ino
) {
231 new_mode
= st
.st_mode
| (S_IXUSR
| S_IXGRP
| S_IXOTH
);
233 new_mode
= st
.st_mode
& ~(S_IXUSR
| S_IXGRP
| S_IXOTH
);
236 ret
= fchmod(fd
, new_mode
);