source: rtems/cpukit/libfs/src/dosfs/msdos_create.c @ d9c2dce0

Last change on this file since d9c2dce0 was d9c2dce0, checked in by Chris Johns <chrisj@…>, on 07/02/03 at 13:58:38

Patch from Victor V. Vengerov <vvv@…> to remove Linux code.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 * Routine to create a new MSDOS filesystem node
3 *
4 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
5 * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
6 *
7 * The license and distribution terms for this file may be
8 * found in the file LICENSE in this distribution or at
9 * http://www.OARcorp.com/rtems/license.html.
10 *
11 * @(#) $Id$
12 *
13 */
14#if HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18#include <errno.h>
19#include <assert.h>
20#include <stdlib.h>
21#include <string.h>
22#include <rtems/libio_.h>
23#include <time.h>
24
25#include "fat.h"
26#include "fat_fat_operations.h"
27#include "fat_file.h"
28
29#include "msdos.h"
30
31/* msdos_creat_node --
32 *     Create a new node. If a new node is file, FAT 32 Bytes Directory
33 *     Entry Structure is initialized, free space is found in parent
34 *     directory and structure is written to the disk. In case of directory,
35 *     all above steps present and also new cluster is allocated for a
36 *     new directory and dot and dotdot nodes are created in alloceted cluster.
37 *
38 * PARAMETERS:
39 *     parent_loc - parent (directory we are going to create node in)
40 *     type       - new node type (file or directory)
41 *     name       - new node name
42 *     mode       - mode
43 *
44 * RETURNS:
45 *     RC_OK on success, or -1 if error occured (errno set appropriately).
46 *     
47 */
48int
49msdos_creat_node(
50    rtems_filesystem_location_info_t  *parent_loc,
51    msdos_node_type_t                  type,
52    char                              *name,
53    mode_t                             mode
54    )
55{
56    int              rc = RC_OK;
57    ssize_t          ret = 0;
58    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
59    fat_file_fd_t   *parent_fat_fd = parent_loc->node_access;
60    fat_file_fd_t   *fat_fd = NULL;
61    time_t           time_ret = 0;
62    unsigned16       time_val = 0;
63    unsigned16       date = 0;
64    fat_auxiliary_t  aux;
65    unsigned char    new_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
66    unsigned char    dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
67   
68    memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
69    memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
70 
71    /* set up name */
72    strncpy(MSDOS_DIR_NAME(new_node), name, MSDOS_NAME_MAX);
73
74    /* fill reserved field */
75    *MSDOS_DIR_NT_RES(new_node) = MSDOS_RES_NT_VALUE;
76 
77    /* set up last write date and time */
78    time_ret = time(NULL);
79    if ( time_ret == -1 )
80        return -1;
81
82    msdos_date_unix2dos(time_ret, &time_val, &date);
83    *MSDOS_DIR_WRITE_TIME(new_node) = CT_LE_W(time_val);
84    *MSDOS_DIR_WRITE_DATE(new_node) = CT_LE_W(date);
85 
86    /* initialize directory/file size */
87    *MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
88
89    if (type == MSDOS_DIRECTORY)
90        *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
91    else
92        *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
93
94    /*
95     * find free space in the parent directory and write new initialized
96     * FAT 32 Bytes Directory Entry Structure to the disk
97     */
98    rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
99    if ( rc != RC_OK )
100        return rc;
101 
102    /*
103     * if we create a new file we are done, if directory there are more steps
104     * to do
105     */
106    if (type == MSDOS_DIRECTORY)
107    {
108        /* open new directory as fat-file */
109        rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
110        if (rc != RC_OK)
111            goto err;
112
113        /*
114         * we opened fat-file for node we just created, so initialize fat-file
115         * descritor
116         */
117        fat_fd->info_cln = aux.cln;
118        fat_fd->info_ofs = aux.ofs;
119        fat_fd->fat_file_size = 0;
120        fat_fd->fat_file_type = FAT_DIRECTORY;
121        fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
122   
123        /*
124         * dot and dotdot entries are identical to new node except the
125         * names
126         */
127        memcpy(DOT_NODE_P(dot_dotdot), new_node,
128               MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
129        memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
130               MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
131        memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
132               MSDOS_NAME_MAX);
133        memcpy(MSDOS_DIR_NAME(DOTDOT_NODE_P(dot_dotdot)), MSDOS_DOTDOT_NAME,
134               MSDOS_NAME_MAX);
135           
136        /* set up cluster num for dotdot entry */
137        /*
138         * here we can ommit FAT32 condition because for all FAT types dirs
139         * right under root dir should contain 0 in dotdot entry but for
140         * FAT12/16 parent_fat_fd->cluster_num always contains such value
141         */   
142        if ((FAT_FD_OF_ROOT_DIR(parent_fat_fd)) &&
143            (fs_info->fat.vol.type & FAT_FAT32))
144        {
145            *MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
146            *MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
147        }
148        else
149        {
150            *MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) =
151                CT_LE_W((unsigned16)((parent_fat_fd->cln) & 0x0000FFFF));
152            *MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) =
153                CT_LE_W((unsigned16)(((parent_fat_fd->cln) & 0xFFFF0000)>>16));
154        }       
155   
156        /*
157         * write dot and dotdot entries to new fat-file: currently fat-file
158         * correspondes to a new node is zero length, so it will be extended
159         * by one cluster and entries will be written
160         */
161        ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
162                             MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2,
163                             dot_dotdot);
164        if (ret < 0)
165        {
166            rc = -1;
167            goto error;
168        }
169   
170        /* increment fat-file size by cluster size */
171        fat_fd->fat_file_size += fs_info->fat.vol.bpc;
172
173        /* set up cluster num for dot entry */
174        *MSDOS_DIR_FIRST_CLUSTER_LOW(DOT_NODE_P(dot_dotdot)) =
175                CT_LE_W((unsigned16)((fat_fd->cln) & 0x0000FFFF));
176        *MSDOS_DIR_FIRST_CLUSTER_HI(DOT_NODE_P(dot_dotdot)) =
177                CT_LE_W((unsigned16)(((fat_fd->cln) & 0xFFFF0000) >> 16));
178
179        /* rewrite dot entry */
180        ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
181                             MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
182                             DOT_NODE_P(dot_dotdot));
183        if (ret < 0)
184        {
185            rc = -1;
186            goto error;
187        }
188   
189        /* write first cluster num of a new directory to disk */
190        rc = msdos_set_first_cluster_num(parent_loc->mt_entry, fat_fd);   
191        if (rc != RC_OK)
192            goto error;         
193 
194        fat_file_close(parent_loc->mt_entry, fat_fd);
195    }
196    return RC_OK;
197
198error:
199    fat_file_close(parent_loc->mt_entry, fat_fd);
200
201err:
202    /* mark 32bytes structure on the disk as free */
203    msdos_set_first_char4file_name(parent_loc->mt_entry, aux.cln, aux.ofs,
204                                   0xE5);
205    return rc;
206}
Note: See TracBrowser for help on using the repository browser.