• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef LOSCFG_KERNEL_PLIMITS
69   if (!strncmp(fullpath, "/dev", 4) || !strcmp(fullpath, "/proc"))
70 #else
71   if (!strncmp(fullpath, "/dev", 4) || !strncmp(fullpath, "/proc", 5))
72 #endif
73     {
74       // virtual root create virtual dir
75       VnodeHold();
76       ret = VnodeLookup(fullpath, &vnode, V_DUMMY|V_CREATE);
77       if (ret != OK)
78         {
79           goto errout_with_lock;
80         }
81       vnode->mode = mode | S_IFDIR;
82       vnode->type = VNODE_TYPE_DIR;
83       VnodeDrop();
84       goto out;
85     }
86 
87   dirname = strrchr(fullpath, '/') + 1;
88 
89   VnodeHold();
90   ret = VnodeLookup(fullpath, &parentVnode, 0);
91   if (ret == OK)
92     {
93       ret = -EEXIST;
94       goto errout_with_lock;
95     }
96 
97   if (parentVnode == NULL)
98     {
99       ret = -ENOENT;
100       goto errout_with_lock;
101     }
102   mount = parentVnode->originMount;
103   if ((mount != NULL) && (mount->mountFlags & MS_RDONLY))
104     {
105       ret = -EROFS;
106       goto errout_with_lock;
107     }
108 
109   parentVnode->useCount++;
110 
111   if (VfsVnodePermissionCheck(parentVnode, (WRITE_OP | EXEC_OP)))
112     {
113       ret = -EACCES;
114       goto errout_with_count;
115     }
116 
117   if ((parentVnode->vop != NULL) && (parentVnode->vop->Mkdir != NULL))
118     {
119       ret = parentVnode->vop->Mkdir(parentVnode, dirname, mode, &vnode);
120     }
121   else
122     {
123       ret = -ENOSYS;
124     }
125 
126   if (ret < 0)
127     {
128       goto errout_with_count;
129     }
130 
131   struct PathCache *dt = PathCacheAlloc(parentVnode, vnode, dirname, strlen(dirname));
132   if (dt == NULL) {
133       // alloc name cache failed is not a critical problem, let it go.
134       PRINT_ERR("alloc path cache %s failed\n", dirname);
135   }
136   vnode->filePath = strdup(fullpath);
137   parentVnode->useCount--;
138   VnodeDrop();
139 out:
140   /* Directory successfully created */
141   free(fullpath);
142 
143   return OK;
144 errout_with_count:
145   parentVnode->useCount--;
146 errout_with_lock:
147   VnodeDrop();
148 errout:
149   set_errno(-ret);
150   if (fullpath)
151     {
152       free(fullpath);
153     }
154   return VFS_ERROR;
155 }
156 
157 /****************************************************************************
158  * Public Functions
159  ****************************************************************************/
160 
161 /****************************************************************************
162  * Name: mkdir
163  *
164  * Description:  Create a directory
165  *
166  ****************************************************************************/
167 
mkdir(const char * pathname,mode_t mode)168 int mkdir(const char *pathname, mode_t mode)
169 {
170   return do_mkdir(AT_FDCWD, pathname, mode);
171 }
172 
173 /****************************************************************************
174  * Name: mkdirat
175  *
176  * Description:  Create a directory by dirfd
177  *
178  ****************************************************************************/
179 
mkdirat(int dirfd,const char * pathname,mode_t mode)180 int mkdirat(int dirfd, const char *pathname, mode_t mode)
181 {
182   return do_mkdir(dirfd, pathname, mode);
183 }
184