• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/vfs/fs_mkdir.c
3  *
4  *   Copyright (C) 2007, 2008, 2014, 2017 Gregory Nutt. All rights reserved.
5  *   Author: Gregory Nutt <gnutt@nuttx.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name NuttX nor the names of its contributors may be
18  *    used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  ****************************************************************************/
35 
36 /****************************************************************************
37  * Included Files
38  ****************************************************************************/
39 
40 #include "vfs_config.h"
41 #include "errno.h"
42 #include "sys/types.h"
43 #include "sys/stat.h"
44 #include "stdlib.h"
45 #include "vnode.h"
46 #include "string.h"
47 #include "capability_api.h"
48 #include "path_cache.h"
49 
50 /****************************************************************************
51  * Private Functions
52  ****************************************************************************/
do_mkdir(int dirfd,const char * pathname,mode_t mode)53 int do_mkdir(int dirfd, const char *pathname, mode_t mode)
54 {
55   struct Vnode *parentVnode = NULL;
56   struct Vnode *vnode = NULL;
57   struct Mount *mount = NULL;
58   int ret;
59   char *fullpath = NULL;
60   char *relativepath = NULL;
61   char *dirname = NULL;
62 
63   mode &= ~GetUmask();
64   mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
65 
66   /* Get absolute path by dirfd*/
67   ret = get_path_from_fd(dirfd, &relativepath);
68   if (ret < 0)
69     {
70       goto errout;
71     }
72 
73   ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
74   if (relativepath)
75     {
76       free(relativepath);
77     }
78 
79   if (ret < 0)
80     {
81       goto errout;
82     }
83   if (!strncmp(fullpath, "/dev", 4) || !strncmp(fullpath, "/proc", 5))
84     {
85       // virtual root create virtual dir
86       VnodeHold();
87       ret = VnodeLookup(fullpath, &vnode, V_DUMMY|V_CREATE);
88       if (ret != OK)
89         {
90           goto errout_with_lock;
91         }
92       vnode->mode = mode | S_IFDIR;
93       vnode->type = VNODE_TYPE_DIR;
94       VnodeDrop();
95       goto out;
96     }
97 
98   dirname = strrchr(fullpath, '/') + 1;
99 
100   VnodeHold();
101   ret = VnodeLookup(fullpath, &parentVnode, 0);
102   if (ret == OK)
103     {
104       ret = -EEXIST;
105       goto errout_with_lock;
106     }
107 
108   if (parentVnode == NULL)
109     {
110       ret = -ENOENT;
111       goto errout_with_lock;
112     }
113   mount = parentVnode->originMount;
114   if ((mount != NULL) && (mount->mountFlags & MS_RDONLY))
115     {
116       ret = -EROFS;
117       goto errout_with_lock;
118     }
119 
120   parentVnode->useCount++;
121 
122   if (VfsVnodePermissionCheck(parentVnode, (WRITE_OP | EXEC_OP)))
123     {
124       ret = -EACCES;
125       goto errout_with_count;
126     }
127 
128   if ((parentVnode->vop != NULL) && (parentVnode->vop->Mkdir != NULL))
129     {
130       ret = parentVnode->vop->Mkdir(parentVnode, dirname, mode, &vnode);
131     }
132   else
133     {
134       ret = -ENOSYS;
135     }
136 
137   if (ret < 0)
138     {
139       goto errout_with_count;
140     }
141 
142   struct PathCache *dt = PathCacheAlloc(parentVnode, vnode, dirname, strlen(dirname));
143   if (dt == NULL) {
144       // alloc name cache failed is not a critical problem, let it go.
145       PRINT_ERR("alloc path cache %s failed\n", dirname);
146   }
147   vnode->filePath = strdup(fullpath);
148   parentVnode->useCount--;
149   VnodeDrop();
150 out:
151   /* Directory successfully created */
152   free(fullpath);
153 
154   return OK;
155 errout_with_count:
156   parentVnode->useCount--;
157 errout_with_lock:
158   VnodeDrop();
159 errout:
160   set_errno(-ret);
161   if (fullpath)
162     {
163       free(fullpath);
164     }
165   return VFS_ERROR;
166 }
167 
168 /****************************************************************************
169  * Public Functions
170  ****************************************************************************/
171 
172 /****************************************************************************
173  * Name: mkdir
174  *
175  * Description:  Create a directory
176  *
177  ****************************************************************************/
178 
mkdir(const char * pathname,mode_t mode)179 int mkdir(const char *pathname, mode_t mode)
180 {
181   return do_mkdir(AT_FDCWD, pathname, mode);
182 }
183 
184 /****************************************************************************
185  * Name: mkdirat
186  *
187  * Description:  Create a directory by dirfd
188  *
189  ****************************************************************************/
190 
mkdirat(int dirfd,const char * pathname,mode_t mode)191 int mkdirat(int dirfd, const char *pathname, mode_t mode)
192 {
193   return do_mkdir(dirfd, pathname, mode);
194 }
195