mkdir.c revision efc6f628e15de95bcd13e4f0ee223cb42115d520
1cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project/* 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * mkdir.c --- make a directory in the filesystem 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * 4cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * Copyright (C) 1994, 1995 Theodore Ts'o. 5cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * %Begin-Header% 7cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * This file may be redistributed under the terms of the GNU Public 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang * License. 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * %End-Header% 10cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project */ 11cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 12cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <stdio.h> 13cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <string.h> 14cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#if HAVE_UNISTD_H 15cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <unistd.h> 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <fcntl.h> 18cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <time.h> 19cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#if HAVE_SYS_STAT_H 20cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <sys/stat.h> 21cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#endif 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_SYS_TYPES_H 23cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include <sys/types.h> 24cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#endif 25cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 26cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "ext2_fs.h" 27cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#include "ext2fs.h" 28cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 29cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#ifndef EXT2_FT_DIR 30cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#define EXT2_FT_DIR 2 31cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project#endif 32cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 33cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Projecterrcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, 34cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project const char *name) 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 36cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project errcode_t retval; 37cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project struct ext2_inode parent_inode, inode; 38cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project ext2_ino_t ino = inum; 39cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project ext2_ino_t scratch_ino; 40cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project blk_t blk; 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *block = 0; 42cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 43cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project /* 46cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * Allocate an inode, if necessary 47cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project */ 48cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (!ino) { 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 0, &ino); 51cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (retval) 52cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project goto cleanup; 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 54cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 55cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project /* 56cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * Allocate a data block for the directory 57cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project */ 58cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project retval = ext2fs_new_block(fs, 0, 0, &blk); 59cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (retval) 60cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project goto cleanup; 61cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 62cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project /* 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Create a scratch template for the directory 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 65cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project retval = ext2fs_new_dir_block(fs, ino, parent, &block); 66cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (retval) 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto cleanup; 68cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 69cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project /* 70cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * Get the parent's inode, if necessary 71cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project */ 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (parent != ino) { 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang retval = ext2fs_read_inode(fs, parent, &parent_inode); 74cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (retval) 75cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project goto cleanup; 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } else 77cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project memset(&parent_inode, 0, sizeof(parent_inode)); 78cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 79cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project /* 80cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * Create the inode structure.... 81cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project */ 82cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project memset(&inode, 0, sizeof(struct ext2_inode)); 83cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); 84cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project inode.i_uid = inode.i_gid = 0; 85cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project ext2fs_iblk_set(fs, &inode, 1); 86cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project inode.i_block[0] = blk; 87cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project inode.i_links_count = 2; 88cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project inode.i_size = fs->blocksize; 89cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project 90cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project /* 91cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project * Write out the inode and inode data block 92cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project */ 93cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project retval = ext2fs_write_dir_block(fs, blk, block); 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (retval) 95cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project goto cleanup; 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang retval = ext2fs_write_new_inode(fs, ino, &inode); 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (retval) 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto cleanup; 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Link the directory into the filesystem hierarchy 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 103cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project if (name) { 104cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, 105cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project &scratch_ino); 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!retval) { 107cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project retval = EXT2_ET_DIR_EXISTS; 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang name = 0; 109cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project goto cleanup; 110cea198a11f15a2eb071d98491ca9a8bc8cebfbc4The Android Open Source Project } 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (retval != EXT2_ET_FILE_NOT_FOUND) 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto cleanup; 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (retval) 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto cleanup; 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Update parent inode's counts 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (parent != ino) { 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang parent_inode.i_links_count++; 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang retval = ext2fs_write_inode(fs, parent, &parent_inode); 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (retval) 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto cleanup; 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Update accounting.... 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang */ 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang ext2fs_block_alloc_stats(fs, blk, +1); 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wangcleanup: 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (block) 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang ext2fs_free_mem(&block); 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return retval; 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang