• 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   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