1 |
1026 |
ivang |
/*
|
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 |
|
|
* @(#) msdos_create.c,v 1.1 2002/02/28 20:43:50 joel Exp
|
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 (see M$ White Paper) is initialized, free space is
|
34 |
|
|
* found in parent directory and structure is written to the disk.
|
35 |
|
|
* In case of directory, all above steps present and also new cluster
|
36 |
|
|
* is allocated for a new directory and dot and dotdot nodes are created
|
37 |
|
|
* in alloceted cluster.
|
38 |
|
|
*
|
39 |
|
|
* PARAMETERS:
|
40 |
|
|
* parent_loc - parent (directory we are going to create node in)
|
41 |
|
|
* type - new node type (file or directory)
|
42 |
|
|
* name - new node name
|
43 |
|
|
* mode - mode
|
44 |
|
|
*
|
45 |
|
|
* RETURNS:
|
46 |
|
|
* RC_OK on success, or -1 if error occured (errno set appropriately).
|
47 |
|
|
*
|
48 |
|
|
*/
|
49 |
|
|
int
|
50 |
|
|
msdos_creat_node(
|
51 |
|
|
rtems_filesystem_location_info_t *parent_loc,
|
52 |
|
|
msdos_node_type_t type,
|
53 |
|
|
char *name,
|
54 |
|
|
mode_t mode
|
55 |
|
|
)
|
56 |
|
|
{
|
57 |
|
|
int rc = RC_OK;
|
58 |
|
|
ssize_t ret = 0;
|
59 |
|
|
msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
|
60 |
|
|
fat_file_fd_t *parent_fat_fd = parent_loc->node_access;
|
61 |
|
|
fat_file_fd_t *fat_fd = NULL;
|
62 |
|
|
time_t time_ret = 0;
|
63 |
|
|
unsigned16 time_val = 0;
|
64 |
|
|
unsigned16 date = 0;
|
65 |
|
|
fat_auxiliary_t aux;
|
66 |
|
|
unsigned char new_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
|
67 |
|
|
unsigned char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
|
68 |
|
|
|
69 |
|
|
memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
70 |
|
|
memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
|
71 |
|
|
|
72 |
|
|
/* set up name */
|
73 |
|
|
strncpy(MSDOS_DIR_NAME(new_node), name, MSDOS_NAME_MAX);
|
74 |
|
|
|
75 |
|
|
/* fill reserved field */
|
76 |
|
|
*MSDOS_DIR_NT_RES(new_node) = MSDOS_RES_NT_VALUE;
|
77 |
|
|
|
78 |
|
|
/* set up last write date and time */
|
79 |
|
|
time_ret = time(NULL);
|
80 |
|
|
if ( time_ret == -1 )
|
81 |
|
|
return -1;
|
82 |
|
|
|
83 |
|
|
msdos_date_unix2dos(time_ret, &time_val, &date);
|
84 |
|
|
*MSDOS_DIR_WRITE_TIME(new_node) = CT_LE_W(time_val);
|
85 |
|
|
*MSDOS_DIR_WRITE_DATE(new_node) = CT_LE_W(date);
|
86 |
|
|
|
87 |
|
|
/* initialize directory/file size */
|
88 |
|
|
*MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
|
89 |
|
|
|
90 |
|
|
if (type == MSDOS_DIRECTORY)
|
91 |
|
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
|
92 |
|
|
else
|
93 |
|
|
*MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
|
94 |
|
|
|
95 |
|
|
/*
|
96 |
|
|
* find free space in the parent directory and write new initialized
|
97 |
|
|
* FAT 32 Bytes Directory Entry Structure (see M$ White Paper)
|
98 |
|
|
* to the disk
|
99 |
|
|
*/
|
100 |
|
|
rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
|
101 |
|
|
if ( rc != RC_OK )
|
102 |
|
|
return rc;
|
103 |
|
|
|
104 |
|
|
/*
|
105 |
|
|
* if we create a new file we are done, if directory there are more steps
|
106 |
|
|
* to do
|
107 |
|
|
*/
|
108 |
|
|
if (type == MSDOS_DIRECTORY)
|
109 |
|
|
{
|
110 |
|
|
/* open new directory as fat-file */
|
111 |
|
|
rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
|
112 |
|
|
if (rc != RC_OK)
|
113 |
|
|
goto err;
|
114 |
|
|
|
115 |
|
|
/*
|
116 |
|
|
* we opened fat-file for node we just created, so initialize fat-file
|
117 |
|
|
* descritor
|
118 |
|
|
*/
|
119 |
|
|
fat_fd->info_cln = aux.cln;
|
120 |
|
|
fat_fd->info_ofs = aux.ofs;
|
121 |
|
|
fat_fd->fat_file_size = 0;
|
122 |
|
|
fat_fd->fat_file_type = FAT_DIRECTORY;
|
123 |
|
|
fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
|
124 |
|
|
|
125 |
|
|
/*
|
126 |
|
|
* dot and dotdot entries are identical to new node except the
|
127 |
|
|
* names
|
128 |
|
|
*/
|
129 |
|
|
memcpy(DOT_NODE_P(dot_dotdot), new_node,
|
130 |
|
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
131 |
|
|
memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
|
132 |
|
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
|
133 |
|
|
memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
|
134 |
|
|
MSDOS_NAME_MAX);
|
135 |
|
|
memcpy(MSDOS_DIR_NAME(DOTDOT_NODE_P(dot_dotdot)), MSDOS_DOTDOT_NAME,
|
136 |
|
|
MSDOS_NAME_MAX);
|
137 |
|
|
|
138 |
|
|
/* set up cluster num for dotdot entry */
|
139 |
|
|
/*
|
140 |
|
|
* here we can ommit FAT32 condition because for all FAT types dirs
|
141 |
|
|
* right under root dir should contain 0 in dotdot entry but for
|
142 |
|
|
* FAT12/16 parent_fat_fd->cluster_num always contains such value
|
143 |
|
|
*/
|
144 |
|
|
if ((FAT_FD_OF_ROOT_DIR(parent_fat_fd)) &&
|
145 |
|
|
(fs_info->fat.vol.type & FAT_FAT32))
|
146 |
|
|
{
|
147 |
|
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
148 |
|
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
|
149 |
|
|
}
|
150 |
|
|
else
|
151 |
|
|
{
|
152 |
|
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) =
|
153 |
|
|
CT_LE_W((unsigned16)((parent_fat_fd->cln) & 0x0000FFFF));
|
154 |
|
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) =
|
155 |
|
|
CT_LE_W((unsigned16)(((parent_fat_fd->cln) & 0xFFFF0000)>>16));
|
156 |
|
|
}
|
157 |
|
|
|
158 |
|
|
/*
|
159 |
|
|
* write dot and dotdot entries to new fat-file: currently fat-file
|
160 |
|
|
* correspondes to a new node is zero length, so it will be extended
|
161 |
|
|
* by one cluster and entries will be written
|
162 |
|
|
*/
|
163 |
|
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
164 |
|
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2,
|
165 |
|
|
dot_dotdot);
|
166 |
|
|
if (ret < 0)
|
167 |
|
|
{
|
168 |
|
|
rc = -1;
|
169 |
|
|
goto error;
|
170 |
|
|
}
|
171 |
|
|
|
172 |
|
|
/* increment fat-file size by cluster size */
|
173 |
|
|
fat_fd->fat_file_size += fs_info->fat.vol.bpc;
|
174 |
|
|
|
175 |
|
|
/* set up cluster num for dot entry */
|
176 |
|
|
*MSDOS_DIR_FIRST_CLUSTER_LOW(DOT_NODE_P(dot_dotdot)) =
|
177 |
|
|
CT_LE_W((unsigned16)((fat_fd->cln) & 0x0000FFFF));
|
178 |
|
|
*MSDOS_DIR_FIRST_CLUSTER_HI(DOT_NODE_P(dot_dotdot)) =
|
179 |
|
|
CT_LE_W((unsigned16)(((fat_fd->cln) & 0xFFFF0000) >> 16));
|
180 |
|
|
|
181 |
|
|
/* rewrite dot entry */
|
182 |
|
|
ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
|
183 |
|
|
MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
|
184 |
|
|
DOT_NODE_P(dot_dotdot));
|
185 |
|
|
if (ret < 0)
|
186 |
|
|
{
|
187 |
|
|
rc = -1;
|
188 |
|
|
goto error;
|
189 |
|
|
}
|
190 |
|
|
|
191 |
|
|
/* write first cluster num of a new directory to disk */
|
192 |
|
|
rc = msdos_set_first_cluster_num(parent_loc->mt_entry, fat_fd);
|
193 |
|
|
if (rc != RC_OK)
|
194 |
|
|
goto error;
|
195 |
|
|
|
196 |
|
|
fat_file_close(parent_loc->mt_entry, fat_fd);
|
197 |
|
|
}
|
198 |
|
|
return RC_OK;
|
199 |
|
|
|
200 |
|
|
error:
|
201 |
|
|
fat_file_close(parent_loc->mt_entry, fat_fd);
|
202 |
|
|
|
203 |
|
|
err:
|
204 |
|
|
/* mark 32bytes structure on the disk as free */
|
205 |
|
|
msdos_set_first_char4file_name(parent_loc->mt_entry, aux.cln, aux.ofs,
|
206 |
|
|
0xE5);
|
207 |
|
|
return rc;
|
208 |
|
|
}
|