#include #include #include #include #include #include #include #include #include #include #define GREENSTONE_DIR "/Greenstone" // #define DEBUG static acl_entry_t find_entry( acl_t acl, acl_tag_t type, id_t id) { acl_entry_t ent; acl_tag_t e_type; id_t *e_id_p; if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1) return NULL; for(;;) { acl_get_tag_type(ent, &e_type); if (type == e_type) { if (id != ACL_UNDEFINED_ID) { e_id_p = acl_get_qualifier(ent); if (e_id_p == NULL) return NULL; if (*e_id_p == id) { acl_free(e_id_p); return ent; } acl_free(e_id_p); } else { return ent; } } if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1) return NULL; } } static int clone_entry( acl_t from_acl, acl_tag_t from_type, acl_t *to_acl, acl_tag_t to_type) { acl_entry_t from_entry, to_entry; from_entry = find_entry(from_acl, from_type, ACL_UNDEFINED_ID); if (from_entry) { if (acl_create_entry(to_acl, &to_entry) != 0) return -1; acl_copy_entry(to_entry, from_entry); acl_set_tag_type(to_entry, to_type); return 0; } else { return 1; } } static int set_perms (acl_t *acl, int type, int uid, int perms) { acl_entry_t entry = find_entry (*acl, type, uid); if (!entry) { if (acl_create_entry(acl, &entry)) { perror ("acl_create_entry"); return 1; } acl_set_tag_type(entry, type); acl_set_qualifier(entry, &uid); } acl_permset_t set; acl_get_permset(entry, &set); if (perms & 4) { acl_add_perm(set, ACL_READ); } else { acl_delete_perm(set, ACL_READ); } if (perms & 2) { acl_add_perm(set, ACL_WRITE); } else { acl_delete_perm(set, ACL_WRITE); } if (perms & 1) { acl_add_perm(set, ACL_EXECUTE); } else { acl_delete_perm(set, ACL_EXECUTE); } return 0; } static int check_acl (acl_t *acl) { #ifdef DEBUG int which_entry; int error; if ((error = acl_check(*acl, &which_entry))) { if (error > 0) { fprintf (stderr, "Malformed ACL '%s': %s at entry %d\n", acl_to_any_text(*acl, NULL, ',', 0), acl_error(error), which_entry + 1 ); } #else if (acl_check(*acl, NULL)) { perror ("acl_check"); #endif return 1; } return 0; } static int set_acl (char *fpath, int user_uid, int greenstone_gid) { acl_t default_acl = acl_get_file (fpath, ACL_TYPE_DEFAULT); acl_t acl = acl_get_file (fpath, ACL_TYPE_ACCESS); if (!default_acl || !acl) { perror (fpath); return 1; } int error = 0; set_perms (&default_acl, ACL_USER, user_uid, 07); set_perms (&acl, ACL_USER, user_uid, 07); set_perms (&default_acl, ACL_GROUP, greenstone_gid, 07); set_perms (&acl, ACL_GROUP, greenstone_gid, 07); /* Try to fill in missing entries */ if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) { clone_entry(acl, ACL_USER_OBJ, &default_acl, ACL_USER_OBJ); } if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) { clone_entry(acl, ACL_GROUP_OBJ, &default_acl, ACL_GROUP_OBJ); } if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) { clone_entry(acl, ACL_OTHER, &default_acl, ACL_OTHER); } if (acl_equiv_mode (acl, NULL) != 0) { if (!find_entry (acl, ACL_MASK, ACL_UNDEFINED_ID)) { clone_entry (acl, ACL_GROUP_OBJ, &acl, ACL_MASK); } acl_calc_mask(&acl); } if (acl_equiv_mode (default_acl, NULL) != 0) { if (!find_entry (default_acl, ACL_MASK, ACL_UNDEFINED_ID)) { clone_entry (default_acl, ACL_GROUP_OBJ, &default_acl, ACL_MASK); } acl_calc_mask(&default_acl); } if (check_acl (&acl) || check_acl (&default_acl)) { goto acl_error; } if (acl_set_file (fpath, ACL_TYPE_DEFAULT, default_acl) || acl_set_file (fpath, ACL_TYPE_ACCESS, acl)) { perror ("acl_set_file"); goto acl_error; } acl_cleanup: if (acl_free (acl) || acl_free (default_acl)) { perror ("acl_free"); } return error; acl_error: error = 1; goto acl_cleanup; } int main(int argc, char **argv) { if (argc < 2) { fprintf (stderr, "Usage: gs-mkdir [...]\n"); return 1; } int greenstone_gid; { struct stat greenstone_user; if (stat (argv[0], &greenstone_user)) { perror (argv[0]); return 1; } greenstone_gid = greenstone_user.st_gid; } int i; for (i = 1; i < argc; i++) { /* Ensure the user exists */ struct passwd *user = getpwnam(argv[i]); if (!user) { fprintf (stderr, "User '%s' does not exist\n", argv[i]); return 1; } char *path = user->pw_dir; struct stat st; /* Ensure the user home folder exists */ if (stat (path, &st)) { perror (path); return 1; } int path_len = strlen (path); char *full_path = malloc (path_len + strlen (GREENSTONE_DIR) + 1); memcpy (full_path, path, path_len); memcpy (full_path + path_len, GREENSTONE_DIR, strlen (GREENSTONE_DIR)); full_path[path_len + strlen (GREENSTONE_DIR)] = 0; /* Check if the user's greenstone folder exists */ if (stat (full_path, &st)) { if (errno == ENOENT) { /* Create the folder as it doesn't exist */ if (mkdir (full_path, 0770)) { perror (full_path); return 1; } chown (full_path, user->pw_uid, user->pw_gid); if (set_acl (full_path, user->pw_uid, greenstone_gid)) { return 1; } } else { /* Something went wrong */ perror (full_path); return 1; } } puts (full_path); free (full_path); } return 0; }