1 /****************************************************************************
2 * fs/vfs/fs_mkdir.c
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership. The
7 * ASF licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the
9 * License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
17 * under the License.
18 *
19 ****************************************************************************/
20
21 /****************************************************************************
22 * Included Files
23 ****************************************************************************/
24
25 #include "vfs_config.h"
26 #include "errno.h"
27 #include "sys/types.h"
28 #include "sys/stat.h"
29 #include "stdlib.h"
30 #include "vnode.h"
31 #include "string.h"
32 #include "capability_api.h"
33 #include "path_cache.h"
34
35 /****************************************************************************
36 * Private Functions
37 ****************************************************************************/
do_mkdir(int dirfd,const char * pathname,mode_t mode)38 int do_mkdir(int dirfd, const char *pathname, mode_t mode)
39 {
40 struct Vnode *parentVnode = NULL;
41 struct Vnode *vnode = NULL;
42 struct Mount *mount = NULL;
43 int ret;
44 char *fullpath = NULL;
45 char *relativepath = NULL;
46 char *dirname = NULL;
47
48 mode &= ~GetUmask();
49 mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
50
51 /* Get absolute path by dirfd*/
52 ret = get_path_from_fd(dirfd, &relativepath);
53 if (ret < 0)
54 {
55 goto errout;
56 }
57
58 ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
59 if (relativepath)
60 {
61 free(relativepath);
62 }
63
64 if (ret < 0)
65 {
66 goto errout;
67 }
68 if (!strncmp(fullpath, "/dev", 4) || !strncmp(fullpath, "/proc", 5))
69 {
70 // virtual root create virtual dir
71 VnodeHold();
72 ret = VnodeLookup(fullpath, &vnode, V_DUMMY|V_CREATE);
73 if (ret != OK)
74 {
75 goto errout_with_lock;
76 }
77 vnode->mode = mode | S_IFDIR;
78 vnode->type = VNODE_TYPE_DIR;
79 VnodeDrop();
80 goto out;
81 }
82
83 dirname = strrchr(fullpath, '/') + 1;
84
85 VnodeHold();
86 ret = VnodeLookup(fullpath, &parentVnode, 0);
87 if (ret == OK)
88 {
89 ret = -EEXIST;
90 goto errout_with_lock;
91 }
92
93 if (parentVnode == NULL)
94 {
95 ret = -ENOENT;
96 goto errout_with_lock;
97 }
98 mount = parentVnode->originMount;
99 if ((mount != NULL) && (mount->mountFlags & MS_RDONLY))
100 {
101 ret = -EROFS;
102 goto errout_with_lock;
103 }
104
105 parentVnode->useCount++;
106
107 if (VfsVnodePermissionCheck(parentVnode, (WRITE_OP | EXEC_OP)))
108 {
109 ret = -EACCES;
110 goto errout_with_count;
111 }
112
113 if ((parentVnode->vop != NULL) && (parentVnode->vop->Mkdir != NULL))
114 {
115 ret = parentVnode->vop->Mkdir(parentVnode, dirname, mode, &vnode);
116 }
117 else
118 {
119 ret = -ENOSYS;
120 }
121
122 if (ret < 0)
123 {
124 goto errout_with_count;
125 }
126
127 struct PathCache *dt = PathCacheAlloc(parentVnode, vnode, dirname, strlen(dirname));
128 if (dt == NULL) {
129 // alloc name cache failed is not a critical problem, let it go.
130 PRINT_ERR("alloc path cache %s failed\n", dirname);
131 }
132 vnode->filePath = strdup(fullpath);
133 parentVnode->useCount--;
134 VnodeDrop();
135 out:
136 /* Directory successfully created */
137 free(fullpath);
138
139 return OK;
140 errout_with_count:
141 parentVnode->useCount--;
142 errout_with_lock:
143 VnodeDrop();
144 errout:
145 set_errno(-ret);
146 if (fullpath)
147 {
148 free(fullpath);
149 }
150 return VFS_ERROR;
151 }
152
153 /****************************************************************************
154 * Public Functions
155 ****************************************************************************/
156
157 /****************************************************************************
158 * Name: mkdir
159 *
160 * Description: Create a directory
161 *
162 ****************************************************************************/
163
mkdir(const char * pathname,mode_t mode)164 int mkdir(const char *pathname, mode_t mode)
165 {
166 return do_mkdir(AT_FDCWD, pathname, mode);
167 }
168
169 /****************************************************************************
170 * Name: mkdirat
171 *
172 * Description: Create a directory by dirfd
173 *
174 ****************************************************************************/
175
mkdirat(int dirfd,const char * pathname,mode_t mode)176 int mkdirat(int dirfd, const char *pathname, mode_t mode)
177 {
178 return do_mkdir(dirfd, pathname, mode);
179 }
180