1 /**
2 * Copyright (c) 2008-2015 Alper Akcan <alper.akcan@gmail.com>
3 * Copyright (c) 2009 Renzo Davoli <renzo@cs.unibo.it>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program (in the main directory of the fuse-ext2
17 * distribution in the file COPYING); if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "fuse-ext2.h"
22
op_mkdir(const char * path,mode_t mode)23 int op_mkdir (const char *path, mode_t mode)
24 {
25 int rt;
26 time_t tm;
27 errcode_t rc;
28
29 char *p_path;
30 char *r_path;
31
32 ext2_ino_t ino;
33 struct ext2_inode inode;
34
35 struct fuse_context *ctx;
36
37 ext2_filsys e2fs = current_ext2fs();
38
39 debugf("enter");
40 debugf("path = %s, mode: 0%o, dir:0%o", path, mode, LINUX_S_IFDIR);
41
42 rt = do_check_split(path, &p_path ,&r_path);
43 if (rt != 0) {
44 debugf("do_check(%s); failed", path);
45 return rt;
46 }
47
48 debugf("parent: %s, child: %s, pathmax: %d", p_path, r_path, PATH_MAX);
49
50 rt = do_readinode(e2fs, p_path, &ino, &inode);
51 if (rt) {
52 debugf("do_readinode(%s, &ino, &inode); failed", p_path);
53 free_split(p_path, r_path);
54 return rt;
55 }
56
57 do {
58 debugf("calling ext2fs_mkdir(e2fs, %d, 0, %s);", ino, r_path);
59 rc = ext2fs_mkdir(e2fs, ino, 0, r_path);
60 if (rc == EXT2_ET_DIR_NO_SPACE) {
61 debugf("calling ext2fs_expand_dir(e2fs, &d)", ino);
62 if (ext2fs_expand_dir(e2fs, ino)) {
63 debugf("error while expanding directory %s (%d)", p_path, ino);
64 free_split(p_path, r_path);
65 return -ENOSPC;
66 }
67 }
68 } while (rc == EXT2_ET_DIR_NO_SPACE);
69 if (rc) {
70 debugf("ext2fs_mkdir(e2fs, %d, 0, %s); failed (%d)", ino, r_path, rc);
71 debugf("e2fs: %p, e2fs->inode_map: %p", e2fs, e2fs->inode_map);
72 free_split(p_path, r_path);
73 return -EIO;
74 }
75
76 rt = do_readinode(e2fs, path, &ino, &inode);
77 if (rt) {
78 debugf("do_readinode(%s, &ino, &inode); failed", path);
79 free_split(p_path, r_path);
80 return -EIO;
81 }
82 tm = e2fs->now ? e2fs->now : time(NULL);
83 inode.i_mode = LINUX_S_IFDIR | mode;
84 inode.i_ctime = inode.i_atime = inode.i_mtime = tm;
85 ctx = fuse_get_context();
86 if (ctx) {
87 ext2_write_uid(&inode, ctx->uid);
88 ext2_write_gid(&inode, ctx->gid);
89 }
90 rc = do_writeinode(e2fs, ino, &inode);
91 if (rc) {
92 debugf("do_writeinode(e2fs, ino, &inode); failed");
93 free_split(p_path, r_path);
94 return -EIO;
95 }
96
97 /* update parent dir */
98 rt = do_readinode(e2fs, p_path, &ino, &inode);
99 if (rt) {
100 debugf("do_readinode(%s, &ino, &inode); dailed", p_path);
101 free_split(p_path, r_path);
102 return -EIO;
103 }
104 inode.i_ctime = inode.i_mtime = tm;
105 rc = do_writeinode(e2fs, ino, &inode);
106 if (rc) {
107 debugf("do_writeinode(e2fs, ino, &inode); failed");
108 free_split(p_path, r_path);
109 return -EIO;
110 }
111
112 free_split(p_path, r_path);
113
114 debugf("leave");
115 return 0;
116 }
117