| 1401 | } |
| 1402 | |
| 1403 | gboolean |
| 1404 | crm_is_writable(const char *dir, const char *file, |
| 1405 | const char *user, const char *group, gboolean need_both) |
| 1406 | { |
| 1407 | int s_res = -1; |
| 1408 | struct stat buf; |
| 1409 | char *full_file = NULL; |
| 1410 | const char *target = NULL; |
| 1411 | |
| 1412 | gboolean pass = TRUE; |
| 1413 | gboolean readwritable = FALSE; |
| 1414 | |
| 1415 | CRM_ASSERT(dir != NULL); |
| 1416 | if (file != NULL) { |
| 1417 | full_file = crm_concat(dir, file, '/'); |
| 1418 | target = full_file; |
| 1419 | s_res = stat(full_file, &buf); |
| 1420 | if (s_res == 0 && S_ISREG(buf.st_mode) == FALSE) { |
| 1421 | crm_err("%s must be a regular file", target); |
| 1422 | pass = FALSE; |
| 1423 | goto out; |
| 1424 | } |
| 1425 | } |
| 1426 | |
| 1427 | if (s_res != 0) { |
| 1428 | target = dir; |
| 1429 | s_res = stat(dir, &buf); |
| 1430 | if (s_res != 0) { |
| 1431 | crm_err("%s must exist and be a directory", dir); |
| 1432 | pass = FALSE; |
| 1433 | goto out; |
| 1434 | |
| 1435 | } else if (S_ISDIR(buf.st_mode) == FALSE) { |
| 1436 | crm_err("%s must be a directory", dir); |
| 1437 | pass = FALSE; |
| 1438 | } |
| 1439 | } |
| 1440 | |
| 1441 | if (user) { |
| 1442 | struct passwd *sys_user = NULL; |
| 1443 | |
| 1444 | sys_user = getpwnam(user); |
| 1445 | readwritable = (sys_user != NULL |
| 1446 | && buf.st_uid == sys_user->pw_uid && (buf.st_mode & (S_IRUSR | S_IWUSR))); |
| 1447 | if (readwritable == FALSE) { |
| 1448 | crm_err("%s must be owned and r/w by user %s", target, user); |
| 1449 | if (need_both) { |
| 1450 | pass = FALSE; |
| 1451 | } |
| 1452 | } |
| 1453 | } |
| 1454 | |
| 1455 | if (group) { |
| 1456 | struct group *sys_grp = getgrnam(group); |
| 1457 | |
| 1458 | readwritable = (sys_grp != NULL |
| 1459 | && buf.st_gid == sys_grp->gr_gid && (buf.st_mode & (S_IRGRP | S_IWGRP))); |
| 1460 | if (readwritable == FALSE) { |
no test coverage detected