VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxFsDxe/test/fsw_posix.c

Last change on this file was 69612, checked in by vboxsync, 7 years ago

Touched up test code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.7 KB
Line 
1/**
2 * \file fsw_posix.c
3 * POSIX user space host environment code.
4 */
5
6/*-
7 * Copyright (c) 2006 Christoph Pfisterer
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the
19 * distribution.
20 *
21 * * Neither the name of Christoph Pfisterer nor the names of the
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "fsw_posix.h"
39
40
41#ifndef FSTYPE
42/** The file system type name to use. */
43#define FSTYPE ext2
44#endif
45
46
47// function prototypes
48
49fsw_status_t fsw_posix_open_dno(struct fsw_posix_volume *pvol, const char *path, int required_type,
50 struct fsw_shandle *shand);
51
52void fsw_posix_change_blocksize(struct fsw_volume *vol,
53 fsw_u32 old_phys_blocksize, fsw_u32 old_log_blocksize,
54 fsw_u32 new_phys_blocksize, fsw_u32 new_log_blocksize);
55fsw_status_t fsw_posix_read_block(struct fsw_volume *vol, fsw_u32 phys_bno, void *buffer);
56
57/**
58 * Dispatch table for our FSW host driver.
59 */
60
61struct fsw_host_table fsw_posix_host_table = {
62 FSW_STRING_TYPE_ISO88591,
63
64 fsw_posix_change_blocksize,
65 fsw_posix_read_block
66};
67
68extern struct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(FSTYPE);
69
70
71/**
72 * Mount function.
73 */
74
75struct fsw_posix_volume * fsw_posix_mount(const char *path, struct fsw_fstype_table *fstype_table)
76{
77 fsw_status_t status;
78 struct fsw_posix_volume *pvol;
79
80 // allocate volume structure
81 status = fsw_alloc_zero(sizeof(struct fsw_posix_volume), (void **)&pvol);
82 if (status)
83 return NULL;
84 pvol->fd = -1;
85
86 // open underlying file/device
87 pvol->fd = open(path, O_RDONLY | O_BINARY, 0);
88 if (pvol->fd < 0) {
89 fprintf(stderr, "fsw_posix_mount: %s: %s\n", path, strerror(errno));
90 fsw_free(pvol);
91 return NULL;
92 }
93
94 // mount the filesystem
95 if (fstype_table == NULL)
96 fstype_table = &FSW_FSTYPE_TABLE_NAME(FSTYPE);
97 status = fsw_mount(pvol, &fsw_posix_host_table, fstype_table, &pvol->vol);
98 if (status) {
99 fprintf(stderr, "fsw_posix_mount: fsw_mount returned %d\n", status);
100 fsw_free(pvol);
101 return NULL;
102 }
103
104 return pvol;
105}
106
107/**
108 * Unmount function.
109 */
110
111int fsw_posix_unmount(struct fsw_posix_volume *pvol)
112{
113 if (pvol->vol != NULL)
114 fsw_unmount(pvol->vol);
115 fsw_free(pvol);
116 return 0;
117}
118
119/**
120 * Open a named regular file.
121 */
122
123struct fsw_posix_file * fsw_posix_open(struct fsw_posix_volume *pvol, const char *path, int flags, mode_t mode)
124{
125 fsw_status_t status;
126 struct fsw_posix_file *file;
127
128 // TODO: check flags for unwanted values
129
130 // allocate file structure
131 status = fsw_alloc(sizeof(struct fsw_posix_file), &file);
132 if (status)
133 return NULL;
134 file->pvol = pvol;
135
136 // open the file
137 status = fsw_posix_open_dno(pvol, path, FSW_DNODE_TYPE_FILE, &file->shand);
138 if (status) {
139 fprintf(stderr, "fsw_posix_open: open_dno returned %d\n", status);
140 fsw_free(file);
141 return NULL;
142 }
143
144 return file;
145}
146
147/**
148 * Read data from a regular file.
149 */
150
151ssize_t fsw_posix_read(struct fsw_posix_file *file, void *buf, size_t nbytes)
152{
153 fsw_status_t status;
154 fsw_u32 buffer_size;
155
156 buffer_size = nbytes;
157 status = fsw_shandle_read(&file->shand, &buffer_size, buf);
158 if (status)
159 return -1;
160 return buffer_size;
161}
162
163/**
164 * Change position within a regular file.
165 */
166
167off_t fsw_posix_lseek(struct fsw_posix_file *file, off_t offset, int whence)
168{
169 fsw_u64 base_offset = 0;
170
171 // get base offset
172 base_offset = 0;
173 if (whence == SEEK_CUR)
174 base_offset = file->shand.pos;
175 else if (whence == SEEK_END)
176 base_offset = file->shand.dnode->size;
177
178 // calculate new offset, prevent seeks before the start of the file
179 if (offset < 0 && -offset > base_offset)
180 file->shand.pos = 0;
181 else
182 file->shand.pos = base_offset + offset;
183
184 return file->shand.pos;
185}
186
187/**
188 * Close a regular file.
189 */
190
191int fsw_posix_close(struct fsw_posix_file *file)
192{
193 fsw_shandle_close(&file->shand);
194 fsw_free(file);
195 return 0;
196}
197
198/**
199 * Open a directory for iteration.
200 */
201
202struct fsw_posix_dir * fsw_posix_opendir(struct fsw_posix_volume *pvol, const char *path)
203{
204 fsw_status_t status;
205 struct fsw_posix_dir *dir;
206
207 // allocate file structure
208 status = fsw_alloc(sizeof(struct fsw_posix_dir), &dir);
209 if (status)
210 return NULL;
211 dir->pvol = pvol;
212
213 // open the directory
214 status = fsw_posix_open_dno(pvol, path, FSW_DNODE_TYPE_DIR, &dir->shand);
215 if (status) {
216 fprintf(stderr, "fsw_posix_opendir: open_dno returned %d\n", status);
217 fsw_free(dir);
218 return NULL;
219 }
220
221 return dir;
222}
223
224/**
225 * Read the next entry from a directory.
226 */
227
228struct fsw_posix_dirent * fsw_posix_readdir(struct fsw_posix_dir *dir)
229{
230 fsw_status_t status;
231 struct fsw_dnode *dno;
232 static struct fsw_posix_dirent dent;
233
234 // get next entry from file system
235 status = fsw_dnode_dir_read(&dir->shand, &dno);
236 if (status) {
237 if (status != 4)
238 fprintf(stderr, "fsw_posix_readdir: fsw_dnode_dir_read returned %d\n", status);
239 return NULL;
240 }
241 status = fsw_dnode_fill(dno);
242 if (status) {
243 fprintf(stderr, "fsw_posix_readdir: fsw_dnode_fill returned %d\n", status);
244 fsw_dnode_release(dno);
245 return NULL;
246 }
247
248 // fill dirent structure
249 dent.d_fileno = dno->dnode_id;
250 //dent.d_reclen = 8 + dno->name.size + 1;
251 switch (dno->type) {
252 case FSW_DNODE_TYPE_FILE:
253 dent.d_type = DT_REG;
254 break;
255 case FSW_DNODE_TYPE_DIR:
256 dent.d_type = DT_DIR;
257 break;
258 case FSW_DNODE_TYPE_SYMLINK:
259 dent.d_type = DT_LNK;
260 break;
261 default:
262 dent.d_type = DT_UNKNOWN;
263 break;
264 }
265#if 0
266 dent.d_namlen = dno->name.size;
267#endif
268 memcpy(dent.d_name, dno->name.data, dno->name.size);
269 dent.d_name[dno->name.size] = 0;
270
271 return &dent;
272}
273
274/**
275 * Rewind a directory to the start.
276 */
277
278void fsw_posix_rewinddir(struct fsw_posix_dir *dir)
279{
280 dir->shand.pos = 0;
281}
282
283/**
284 * Close a directory.
285 */
286
287int fsw_posix_closedir(struct fsw_posix_dir *dir)
288{
289 fsw_shandle_close(&dir->shand);
290 fsw_free(dir);
291 return 0;
292}
293
294/**
295 * Open a shand of a required type by path.
296 */
297
298fsw_status_t fsw_posix_open_dno(struct fsw_posix_volume *pvol, const char *path, int required_type, struct fsw_shandle *shand)
299{
300 fsw_status_t status;
301 struct fsw_dnode *dno;
302 struct fsw_dnode *target_dno;
303 struct fsw_string lookup_path;
304
305 lookup_path.type = FSW_STRING_TYPE_ISO88591;
306 lookup_path.len = strlen(path);
307 lookup_path.size = lookup_path.len;
308 lookup_path.data = (void *)path;
309
310 // resolve the path (symlinks along the way are automatically resolved)
311 status = fsw_dnode_lookup_path(pvol->vol->root, &lookup_path, '/', &dno);
312 if (status) {
313 fprintf(stderr, "fsw_posix_open_dno: fsw_dnode_lookup_path returned %d\n", status);
314 return status;
315 }
316
317 // if the final node is a symlink, also resolve it
318 status = fsw_dnode_resolve(dno, &target_dno);
319 fsw_dnode_release(dno);
320 if (status) {
321 fprintf(stderr, "fsw_posix_open_dno: fsw_dnode_resolve returned %d\n", status);
322 return status;
323 }
324 dno = target_dno;
325
326 // check that it is a regular file
327 status = fsw_dnode_fill(dno);
328 if (status) {
329 fprintf(stderr, "fsw_posix_open_dno: fsw_dnode_fill returned %d\n", status);
330 fsw_dnode_release(dno);
331 return status;
332 }
333 if (dno->type != required_type) {
334 fprintf(stderr, "fsw_posix_open_dno: dnode is not of the requested type\n");
335 fsw_dnode_release(dno);
336 return FSW_UNSUPPORTED;
337 }
338
339 // open shandle
340 status = fsw_shandle_open(dno, shand);
341 if (status) {
342 fprintf(stderr, "fsw_posix_open_dno: fsw_shandle_open returned %d\n", status);
343 }
344 fsw_dnode_release(dno);
345 return status;
346}
347
348/**
349 * FSW interface function for block size changes. This function is called by the FSW core
350 * when the file system driver changes the block sizes for the volume.
351 */
352
353void fsw_posix_change_blocksize(struct fsw_volume *vol,
354 fsw_u32 old_phys_blocksize, fsw_u32 old_log_blocksize,
355 fsw_u32 new_phys_blocksize, fsw_u32 new_log_blocksize)
356{
357 // nothing to do
358}
359
360/**
361 * FSW interface function to read data blocks. This function is called by the FSW core
362 * to read a block of data from the device. The buffer is allocated by the core code.
363 */
364
365fsw_status_t fsw_posix_read_block(struct fsw_volume *vol, fsw_u32 phys_bno, void *buffer)
366{
367 struct fsw_posix_volume *pvol = (struct fsw_posix_volume *)vol->host_data;
368 off_t block_offset, seek_result;
369 ssize_t read_result;
370
371 FSW_MSG_DEBUGV((FSW_MSGSTR("fsw_posix_read_block: %d (%d)\n"), phys_bno, vol->phys_blocksize));
372
373 // read from disk
374 block_offset = (off_t)phys_bno * vol->phys_blocksize;
375 seek_result = lseek(pvol->fd, block_offset, SEEK_SET);
376 if (seek_result != block_offset) {
377 fprintf(stderr, "fsw_posix_read_block: failed to seek to block %u (offset %u)\n", phys_bno, block_offset);
378 return FSW_IO_ERROR;
379 }
380 read_result = read(pvol->fd, buffer, vol->phys_blocksize);
381 if (read_result != vol->phys_blocksize) {
382 fprintf(stderr, "fsw_posix_read_block: failed to read %u bytes at %u\n", vol->phys_blocksize, block_offset);
383 return FSW_IO_ERROR;
384 }
385
386 return FSW_SUCCESS;
387}
388
389
390/**
391 * Time mapping callback for the fsw_dnode_stat call. This function converts
392 * a Posix style timestamp into an EFI_TIME structure and writes it to the
393 * appropriate member of the EFI_FILE_INFO structure that we're filling.
394 */
395
396/*
397static void fsw_posix_store_time_posix(struct fsw_dnode_stat *sb, int which, fsw_u32 posix_time)
398{
399 EFI_FILE_INFO *FileInfo = (EFI_FILE_INFO *)sb->host_data;
400
401 if (which == FSW_DNODE_STAT_CTIME)
402 fsw_posix_decode_time(&FileInfo->CreateTime, posix_time);
403 else if (which == FSW_DNODE_STAT_MTIME)
404 fsw_posix_decode_time(&FileInfo->ModificationTime, posix_time);
405 else if (which == FSW_DNODE_STAT_ATIME)
406 fsw_posix_decode_time(&FileInfo->LastAccessTime, posix_time);
407}
408*/
409
410/**
411 * Mode mapping callback for the fsw_dnode_stat call. This function looks at
412 * the Posix mode passed by the file system driver and makes appropriate
413 * adjustments to the EFI_FILE_INFO structure that we're filling.
414 */
415
416/*
417static void fsw_posix_store_attr_posix(struct fsw_dnode_stat *sb, fsw_u16 posix_mode)
418{
419 EFI_FILE_INFO *FileInfo = (EFI_FILE_INFO *)sb->host_data;
420
421 if ((posix_mode & S_IWUSR) == 0)
422 FileInfo->Attribute |= EFI_FILE_READ_ONLY;
423}
424*/
425
426/**
427 * Common function to fill an EFI_FILE_INFO with information about a dnode.
428 */
429
430/*
431EFI_STATUS fsw_posix_dnode_fill_FileInfo(IN FSW_VOLUME_DATA *Volume,
432 IN struct fsw_dnode *dno,
433 IN OUT UINTN *BufferSize,
434 OUT VOID *Buffer)
435{
436 EFI_STATUS Status;
437 EFI_FILE_INFO *FileInfo;
438 UINTN RequiredSize;
439 struct fsw_dnode_stat sb;
440
441 // make sure the dnode has complete info
442 Status = fsw_posix_map_status(fsw_dnode_fill(dno), Volume);
443 if (EFI_ERROR(Status))
444 return Status;
445
446 // TODO: check/assert that the dno's name is in UTF16
447
448 // check buffer size
449 RequiredSize = SIZE_OF_EFI_FILE_INFO + fsw_posix_strsize(&dno->name);
450 if (*BufferSize < RequiredSize) {
451 // TODO: wind back the directory in this case
452
453 *BufferSize = RequiredSize;
454 return EFI_BUFFER_TOO_SMALL;
455 }
456
457 // fill structure
458 ZeroMem(Buffer, RequiredSize);
459 FileInfo = (EFI_FILE_INFO *)Buffer;
460 FileInfo->Size = RequiredSize;
461 FileInfo->FileSize = dno->size;
462 FileInfo->Attribute = 0;
463 if (dno->type == FSW_DNODE_TYPE_DIR)
464 FileInfo->Attribute |= EFI_FILE_DIRECTORY;
465 fsw_posix_strcpy(FileInfo->FileName, &dno->name);
466
467 // get the missing info from the fs driver
468 ZeroMem(&sb, sizeof(struct fsw_dnode_stat));
469 sb.store_time_posix = fsw_posix_store_time_posix;
470 sb.store_attr_posix = fsw_posix_store_attr_posix;
471 sb.host_data = FileInfo;
472 Status = fsw_posix_map_status(fsw_dnode_stat(dno, &sb), Volume);
473 if (EFI_ERROR(Status))
474 return Status;
475 FileInfo->PhysicalSize = sb.used_bytes;
476
477 // prepare for return
478 *BufferSize = RequiredSize;
479 return EFI_SUCCESS;
480}
481*/
482
483// EOF
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use