root/main/trunk/package-kits/scripts/gs-mkdir/gs-mkdir.c @ 29703

Revision 29703, 6.4 KB (checked in by jts21, 5 years ago)

Fixed error message for invalid username

Line 
1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4#include <pwd.h>
5#include <string.h>
6#include <errno.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <sys/acl.h>
10#include <acl/libacl.h>
11
12#define GREENSTONE_DIR "/Greenstone"
13// #define DEBUG
14
15static acl_entry_t
16find_entry(
17    acl_t acl,
18    acl_tag_t type,
19    id_t id)
20{
21    acl_entry_t ent;
22    acl_tag_t e_type;
23    id_t *e_id_p;
24
25    if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1)
26        return NULL;
27
28    for(;;) {
29        acl_get_tag_type(ent, &e_type);
30        if (type == e_type) {
31            if (id != ACL_UNDEFINED_ID) {
32                e_id_p = acl_get_qualifier(ent);
33                if (e_id_p == NULL)
34                    return NULL;
35                if (*e_id_p == id) {
36                    acl_free(e_id_p);
37                    return ent;
38                }
39                acl_free(e_id_p);
40            } else {
41                return ent;
42            }
43        }
44        if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1)
45            return NULL;
46    }
47}
48
49static int
50clone_entry(
51    acl_t from_acl,
52    acl_tag_t from_type,
53    acl_t *to_acl,
54    acl_tag_t to_type)
55{
56    acl_entry_t from_entry, to_entry;
57    from_entry = find_entry(from_acl, from_type, ACL_UNDEFINED_ID);
58    if (from_entry) {
59        if (acl_create_entry(to_acl, &to_entry) != 0)
60            return -1;
61        acl_copy_entry(to_entry, from_entry);
62        acl_set_tag_type(to_entry, to_type);
63        return 0;
64    } else {
65        return 1;
66    }
67}
68
69static int set_perms (acl_t *acl, int type, int uid, int perms) {
70    acl_entry_t entry = find_entry (*acl, type, uid);
71    if (!entry) {
72        if (acl_create_entry(acl, &entry)) {
73            perror ("acl_create_entry");
74            return 1;
75        }
76        acl_set_tag_type(entry, type);
77        acl_set_qualifier(entry, &uid);
78    }
79    acl_permset_t set;
80    acl_get_permset(entry, &set);
81   
82    if (perms & 4) {
83        acl_add_perm(set, ACL_READ);
84    } else {
85        acl_delete_perm(set, ACL_READ);
86    }
87    if (perms & 2) {
88        acl_add_perm(set, ACL_WRITE);
89    } else {
90        acl_delete_perm(set, ACL_WRITE);
91    }
92    if (perms & 1) {
93        acl_add_perm(set, ACL_EXECUTE);
94    } else {
95        acl_delete_perm(set, ACL_EXECUTE);
96    }
97    return 0;
98}
99
100static int check_acl (acl_t *acl) {
101#ifdef DEBUG
102    int which_entry;
103    int error;
104    if ((error = acl_check(*acl, &which_entry))) {
105        if (error > 0) {
106            fprintf (stderr,
107                    "Malformed ACL '%s': %s at entry %d\n",
108                    acl_to_any_text(*acl, NULL, ',', 0),
109                    acl_error(error), which_entry + 1
110            );
111        }
112#else
113    if (acl_check(*acl, NULL)) {
114        perror ("acl_check");
115#endif
116        return 1;
117    }
118    return 0;
119}
120
121static int set_acl (char *fpath, int user_uid, int greenstone_gid) {
122    acl_t default_acl = acl_get_file (fpath, ACL_TYPE_DEFAULT);
123    acl_t acl = acl_get_file (fpath, ACL_TYPE_ACCESS);
124    if (!default_acl || !acl) {
125        perror (fpath);
126        return 1;
127    }
128    int error = 0;
129
130    set_perms (&default_acl, ACL_USER, user_uid, 07);
131    set_perms (&acl, ACL_USER, user_uid, 07);
132    set_perms (&default_acl, ACL_GROUP, greenstone_gid, 07);
133    set_perms (&acl, ACL_GROUP, greenstone_gid, 07);
134
135    /* Try to fill in missing entries */
136    if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
137        clone_entry(acl, ACL_USER_OBJ, &default_acl, ACL_USER_OBJ);
138    }
139    if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
140        clone_entry(acl, ACL_GROUP_OBJ, &default_acl, ACL_GROUP_OBJ);
141    }
142    if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) {
143        clone_entry(acl, ACL_OTHER, &default_acl, ACL_OTHER);
144    }
145
146    if (acl_equiv_mode (acl, NULL) != 0) {
147        if (!find_entry (acl, ACL_MASK, ACL_UNDEFINED_ID)) {
148            clone_entry (acl, ACL_GROUP_OBJ, &acl, ACL_MASK);
149        }
150        acl_calc_mask(&acl);
151    }
152    if (acl_equiv_mode (default_acl, NULL) != 0) {
153        if (!find_entry (default_acl, ACL_MASK, ACL_UNDEFINED_ID)) {
154            clone_entry (default_acl, ACL_GROUP_OBJ, &default_acl, ACL_MASK);
155        }
156        acl_calc_mask(&default_acl);
157    }
158
159    if (check_acl (&acl) || check_acl (&default_acl)) {
160        goto acl_error;
161    }
162
163    if (acl_set_file (fpath, ACL_TYPE_DEFAULT, default_acl) ||
164        acl_set_file (fpath, ACL_TYPE_ACCESS, acl)) {
165        perror ("acl_set_file");
166        goto acl_error;
167    }
168
169acl_cleanup:
170    if (acl_free (acl) || acl_free (default_acl)) {
171        perror ("acl_free");
172    }
173    return error;
174acl_error:
175    error = 1;
176    goto acl_cleanup;
177}
178
179
180int main(int argc, char **argv) {
181    if (argc < 2) {
182        fprintf (stderr, "Usage: gs-mkdir <username> [...]\n");
183        return 1;
184    }
185    int greenstone_gid;
186    {
187        struct stat greenstone_user;
188        if (stat (argv[0], &greenstone_user)) {
189            perror (argv[0]);
190            return 1;
191        }
192        greenstone_gid = greenstone_user.st_gid;
193    }
194
195    int i;
196    for (i = 1; i < argc; i++) {
197        /* Ensure the user exists */
198        struct passwd *user = getpwnam(argv[i]);
199        if (!user) {
200            fprintf (stderr, "User '%s' does not exist\n", argv[i]);
201            return 1;
202        }
203
204        char *path = user->pw_dir;
205        struct stat st;
206        /* Ensure the user home folder exists */
207        if (stat (path, &st)) {
208            perror (path);
209            return 1;
210        }
211        int path_len = strlen (path);
212        char *full_path = malloc (path_len + strlen (GREENSTONE_DIR) + 1);
213        memcpy (full_path, path, path_len);
214        memcpy (full_path + path_len, GREENSTONE_DIR, strlen (GREENSTONE_DIR));
215        full_path[path_len + strlen (GREENSTONE_DIR)] = 0;
216
217        /* Check if the user's greenstone folder exists */
218        if (stat (full_path, &st)) {
219            if (errno == ENOENT) {
220                /* Create the folder as it doesn't exist */
221                if (mkdir (full_path, 0770)) {
222                    perror (full_path);
223                    return 1;
224                }
225                chown (full_path, user->pw_uid, user->pw_gid);
226
227                if (set_acl (full_path, user->pw_uid, greenstone_gid)) {
228                    return 1;
229                }
230            } else {
231                /* Something went wrong */
232                perror (full_path);
233                return 1;
234            }
235        }
236       
237        puts (full_path);
238        free (full_path);
239    }
240    return 0;
241}
Note: See TracBrowser for help on using the browser.