embox
117 строк · 2.1 Кб
1/**
2* @file
3* @brief
4*
5* @author Anton Kozlov
6* @date 14.02.2013
7*/
8
9#include <errno.h>10#include <unistd.h>11#include <stdlib.h>12#include <sys/stat.h>13
14#include <fs/vfs.h>15#include <fs/inode.h>16#include <fs/inode_operation.h>17#include <fs/hlpr_path.h>18
19#include <security/security.h>20
21int fs_perm_mask(struct inode *node) {22int perm = node->i_mode & S_IRWXA;23uid_t uid = getuid();24
25if (uid == 0) {26/* super user */27return S_IRWXO;28}29
30if (node->i_owner_id == uid) {31perm >>= 6;32} else if (node->i_group_id == getgid()) {33perm >>= 3;34}35perm &= S_IRWXO;36
37return perm;38}
39
40int fs_perm_check(struct inode *node, int fd_flags) {41/* Here, we rely on the fact that fd_flags correspond to OTH perm bits. */42return (fd_flags & ~fs_perm_mask(node)) ? -EACCES :43security_node_permissions(node, fd_flags);44}
45
46int fs_perm_lookup(const char *path, const char **pathlast,47struct path *nodelast) {48struct path node_path;49struct path dir_path;50size_t len = 0;51int ret;52
53if (!path) {54return -EINVAL;55}56
57if (path[0] == '/') {58vfs_get_root_path(&node_path);59} else {60vfs_get_leaf_path(&node_path);61}62
63do {64struct inode *dnode;65
66path = path_next(path + len, &len);67
68*nodelast = node_path;69
70if (pathlast != NULL) {71*pathlast = path;72}73
74if (!path) {75return 0;76}77
78if (0 != (ret = fs_perm_check(node_path.node, S_IXOTH))) {79return ret;80}81
82dir_path = node_path;83if_mounted_follow_down(&node_path);84dnode = node_path.node;85vfs_lookup_childn(&node_path, path, len, &node_path);86
87if (NULL != node_path.node) {88if (dnode && dnode->i_ops && dnode->i_ops->ino_lookup) {89if (dnode->i_ops == dir_path.node->i_ops) {90dnode->i_ops->ino_lookup(node_path.node, path, dir_path.node);91} else {92/* find mount inode */93dnode->i_ops->ino_lookup(node_path.node, path, NULL);94
95}96}97}98
99} while (node_path.node);100
101return -ENOENT;102}
103
104int fs_perm_lookup_relative(const char *path, const char **pathlast,105struct path *nodelast) {106int ret = 0;107
108if (0 != (ret = fs_perm_lookup(path, pathlast, nodelast))) {109return ret;110}111
112if (!S_ISDIR(nodelast->node->i_mode)) {113return 0;114}115
116return 0;117}
118