OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
fsw_core.c
Go to the documentation of this file.
1
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_core.h"
39
40
41// functions
42
43static void fsw_blockcache_free(struct fsw_volume *vol);
44
45#define MAX_CACHE_LEVEL (5)
46
47
62fsw_status_t fsw_mount(void *host_data,
63 struct fsw_host_table *host_table,
64 struct fsw_fstype_table *fstype_table,
65 struct fsw_volume **vol_out)
66{
67 fsw_status_t status;
68 struct fsw_volume *vol;
69
70 // allocate memory for the structure
71 status = fsw_alloc_zero(fstype_table->volume_struct_size, (void **)&vol);
72 if (status)
73 return status;
74
75 // initialize fields
76 vol->phys_blocksize = 512;
77 vol->log_blocksize = 512;
79 vol->host_data = host_data;
83
84 // let the fs driver mount the file system
85 status = vol->fstype_table->volume_mount(vol);
86 if (status)
87 goto errorexit;
88
89 // TODO: anything else?
90
91 *vol_out = vol;
92 return FSW_SUCCESS;
93
94errorexit:
95 fsw_unmount(vol);
96 return status;
97}
98
107void fsw_unmount(struct fsw_volume *vol)
108{
109 if (vol->root)
111 // TODO: check that no other dnodes are still around
112
113 vol->fstype_table->volume_free(vol);
114
115 fsw_blockcache_free(vol);
116 fsw_strfree(&vol->label);
117 fsw_free(vol);
118}
119
126{
127 return vol->fstype_table->volume_stat(vol, sb);
128}
129
146{
147 // TODO: Check the sizes. Both must be powers of 2. log_blocksize must not be smaller than
148 // phys_blocksize.
149
150 // drop core block cache if present
151 fsw_blockcache_free(vol);
152
153 // signal host driver to drop caches etc.
155 vol->phys_blocksize, vol->log_blocksize,
157
160}
161
179fsw_status_t fsw_block_get(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, fsw_u32 cache_level, void **buffer_out)
180{
181 fsw_status_t status;
182 fsw_u32 i, discard_level, new_bcache_size;
183 struct fsw_blockcache *new_bcache;
184
185 // TODO: allow the host driver to do its own caching; just call through if
186 // the appropriate function pointers are set
187
190
191 // check block cache
192 for (i = 0; i < vol->bcache_size; i++) {
193 if (vol->bcache[i].phys_bno == phys_bno) {
194 // cache hit!
195 if (vol->bcache[i].cache_level < cache_level)
196 vol->bcache[i].cache_level = cache_level; // promote the entry
197 vol->bcache[i].refcount++;
198 *buffer_out = vol->bcache[i].data;
199 return FSW_SUCCESS;
200 }
201 }
202
203 // find a free entry in the cache table
204 for (i = 0; i < vol->bcache_size; i++) {
205 if (vol->bcache[i].phys_bno == FSW_INVALID_BNO)
206 break;
207 }
208 if (i >= vol->bcache_size) {
209 for (discard_level = 0; discard_level <= MAX_CACHE_LEVEL; discard_level++) {
210 for (i = 0; i < vol->bcache_size; i++) {
211 if (vol->bcache[i].refcount == 0 && vol->bcache[i].cache_level <= discard_level)
212 break;
213 }
214 if (i < vol->bcache_size)
215 break;
216 }
217 }
218 if (i >= vol->bcache_size) {
219 // enlarge / create the cache
220 if (vol->bcache_size < 16)
221 new_bcache_size = 16;
222 else
223 new_bcache_size = vol->bcache_size << 1;
224 status = fsw_alloc(new_bcache_size * sizeof(struct fsw_blockcache), &new_bcache);
225 if (status)
226 return status;
227 if (vol->bcache_size > 0)
228 fsw_memcpy(new_bcache, vol->bcache, vol->bcache_size * sizeof(struct fsw_blockcache));
229 for (i = vol->bcache_size; i < new_bcache_size; i++) {
230 new_bcache[i].refcount = 0;
231 new_bcache[i].cache_level = 0;
232 new_bcache[i].phys_bno = FSW_INVALID_BNO;
233 new_bcache[i].data = NULL;
234 }
235 i = vol->bcache_size;
236
237 // switch caches
238 if (vol->bcache != NULL)
239 fsw_free(vol->bcache);
240 vol->bcache = new_bcache;
241 vol->bcache_size = new_bcache_size;
242 }
243 vol->bcache[i].phys_bno = FSW_INVALID_BNO;
244
245 // read the data
246 if (vol->bcache[i].data == NULL) {
247 status = fsw_alloc(vol->phys_blocksize, &vol->bcache[i].data);
248 if (status)
249 return status;
250 }
251 status = vol->host_table->read_block(vol, phys_bno, vol->bcache[i].data);
252 if (status)
253 return status;
254
255 vol->bcache[i].phys_bno = phys_bno;
256 vol->bcache[i].cache_level = cache_level;
257 vol->bcache[i].refcount = 1;
258 *buffer_out = vol->bcache[i].data;
259 return FSW_SUCCESS;
260}
261
267void fsw_block_release(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, void *buffer)
268{
269 fsw_u32 i;
270
271 // TODO: allow the host driver to do its own caching; just call through if
272 // the appropriate function pointers are set
273
274 // update block cache
275 for (i = 0; i < vol->bcache_size; i++) {
276 if (vol->bcache[i].phys_bno == phys_bno && vol->bcache[i].refcount > 0)
277 vol->bcache[i].refcount--;
278 }
279}
280
286static void fsw_blockcache_free(struct fsw_volume *vol)
287{
288 fsw_u32 i;
289
290 for (i = 0; i < vol->bcache_size; i++) {
291 if (vol->bcache[i].data != NULL)
292 fsw_free(vol->bcache[i].data);
293 }
294 if (vol->bcache != NULL) {
295 fsw_free(vol->bcache);
296 vol->bcache = NULL;
297 }
298 vol->bcache_size = 0;
299}
300
307static void fsw_dnode_register(struct fsw_volume *vol, struct fsw_dnode *dno)
308{
309 dno->next = vol->dnode_head;
310 if (vol->dnode_head != NULL)
311 vol->dnode_head->prev = dno;
312 dno->prev = NULL;
313 vol->dnode_head = dno;
314}
315
323fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, struct fsw_dnode **dno_out)
324{
325 fsw_status_t status;
326 struct fsw_dnode *dno;
327
328 // allocate memory for the structure
329 status = fsw_alloc_zero(vol->fstype_table->dnode_struct_size, (void **)&dno);
330 if (status)
331 return status;
332
333 // fill the structure
334 dno->vol = vol;
335 dno->parent = NULL;
336 dno->dnode_id = dnode_id;
338 dno->refcount = 1;
339 dno->complete = 1;
341 // TODO: instead, call a function to create an empty string in the native string type
342
343 fsw_dnode_register(vol, dno);
345
346 *dno_out = dno;
347 return FSW_SUCCESS;
348}
349
350int fsw_dnode_is_root(struct fsw_dnode *dno) {
351 return dno->parent == NULL && dno->type == FSW_DNODE_TYPE_DIR && fsw_strlen(&dno->name) == 0;
352}
353
373 struct fsw_string *name, struct fsw_dnode **dno_out)
374{
375 fsw_status_t status;
376 struct fsw_dnode *dno;
377 // check if we already have a dnode with the same id
378 for (dno = vol->dnode_head; dno; dno = dno->next) {
379 if (dno->dnode_id == dnode_id) {
380 fsw_dnode_retain(dno);
381 *dno_out = dno;
382 return FSW_SUCCESS;
383 }
384 }
385
386 // allocate memory for the structure
387 status = fsw_alloc_zero(vol->fstype_table->dnode_struct_size, (void **)&dno);
388 if (status)
389 return status;
390
391 // Flag must be set by fsw_dnode_mkcomplete() call
392 dno->complete = 0;
393
394 // fill the structure
395 dno->vol = vol;
396 dno->parent = parent_dno;
397
398 // Parent may be null and filled in future by fsw_dnode_fill() call
399 if (parent_dno != NULL) {
401 }
402 dno->dnode_id = dnode_id;
403 dno->type = type;
404 dno->refcount = 1;
405 status = fsw_strdup_coerce(&dno->name, vol->host_table->native_string_type, name);
406 if (status) {
407 fsw_free(dno);
408 return status;
409 }
410
411 fsw_dnode_register(vol, dno);
412
413 *dno_out = dno;
414 return FSW_SUCCESS;
415}
416
421 dno->complete = 1;
422}
423
431{
432 dno->refcount++;
433}
434
443{
444 struct fsw_volume *vol = dno->vol;
445 struct fsw_dnode *parent_dno;
446
447 dno->refcount--;
448
449 if (dno->refcount == 0) {
450 parent_dno = dno->parent;
451
452 // de-register from volume's list
453 if (dno->next)
454 dno->next->prev = dno->prev;
455 if (dno->prev)
456 dno->prev->next = dno->next;
457 if (vol->dnode_head == dno)
458 vol->dnode_head = dno->next;
459
460 // run fstype-specific cleanup
461 vol->fstype_table->dnode_free(vol, dno);
462
463 fsw_strfree(&dno->name);
464 fsw_free(dno);
465
466 // release our pointer to the parent, possibly deallocating it, too
467 if (parent_dno)
468 fsw_dnode_release(parent_dno);
469 }
470}
471
484{
485 // TODO: check a flag right here, call fstype's dnode_fill only once per dnode
486 if (dno->complete) {
487 return FSW_SUCCESS;
488 }
489 return dno->vol->fstype_table->dnode_fill(dno->vol, dno);
490}
491
503{
504 fsw_status_t status;
505
506 status = fsw_dnode_fill(dno);
507 if (status)
508 return status;
509
510 sb->used_bytes = 0;
511 status = dno->vol->fstype_table->dnode_stat(dno->vol, dno, sb);
512 if (!status && !sb->used_bytes)
513 sb->used_bytes = DivU64x32(dno->size + dno->vol->log_blocksize - 1, dno->vol->log_blocksize, NULL);
514 return status;
515}
516
530 struct fsw_string *lookup_name, struct fsw_dnode **child_dno_out)
531{
532 fsw_status_t status;
533
534 status = fsw_dnode_fill(dno);
535 if (status)
536 return status;
537 if (dno->type != FSW_DNODE_TYPE_DIR)
538 return FSW_UNSUPPORTED;
539
540 return dno->vol->fstype_table->dir_lookup(dno->vol, dno, lookup_name, child_dno_out);
541}
542
555 struct fsw_string *lookup_path, char separator,
556 struct fsw_dnode **child_dno_out)
557{
558 fsw_status_t status;
559 struct fsw_volume *vol = dno->vol;
560 struct fsw_dnode *child_dno = NULL;
561 struct fsw_string lookup_name;
562 struct fsw_string remaining_path;
563 int root_if_empty;
564
565 remaining_path = *lookup_path;
566 fsw_dnode_retain(dno);
567
568 // loop over the path
569 for (root_if_empty = 1; fsw_strlen(&remaining_path) > 0; root_if_empty = 0) {
570 // parse next path component
571 fsw_strsplit(&lookup_name, &remaining_path, separator);
572
573 FSW_MSG_DEBUG((FSW_MSGSTR("fsw_dnode_lookup_path: split into %d '%s' and %d '%s'\n"),
574 lookup_name.len, lookup_name.data,
575 remaining_path.len, remaining_path.data));
576
577 if (fsw_strlen(&lookup_name) == 0) { // empty path component
578 if (root_if_empty)
579 child_dno = vol->root;
580 else
581 child_dno = dno;
582 fsw_dnode_retain(child_dno);
583
584 } else {
585 // do an actual directory lookup
586
587 // ensure we have full information
588 status = fsw_dnode_fill(dno);
589 if (status)
590 goto errorexit;
591
592 // resolve symlink if necessary
593 if (dno->type == FSW_DNODE_TYPE_SYMLINK) {
594 status = fsw_dnode_resolve(dno, &child_dno);
595 if (status)
596 goto errorexit;
597
598 // symlink target becomes the new dno
600 dno = child_dno; // is already retained
601 child_dno = NULL;
602
603 // ensure we have full information
604 status = fsw_dnode_fill(dno);
605 if (status)
606 goto errorexit;
607 }
608
609 // make sure we operate on a directory
610 if (dno->type != FSW_DNODE_TYPE_DIR) {
611 return FSW_UNSUPPORTED;
612 goto errorexit;
613 }
614
615 // check special paths
616 if (fsw_streq_cstr(&lookup_name, ".")) { // self directory
617 child_dno = dno;
618 fsw_dnode_retain(child_dno);
619
620 } else if (fsw_streq_cstr(&lookup_name, "..")) { // parent directory
621 if (dno->parent == NULL) {
622 // We cannot go up from the root directory. Caution: Certain apps like the EFI shell
623 // rely on this behaviour!
624 status = FSW_NOT_FOUND;
625 goto errorexit;
626 }
627 child_dno = dno->parent;
628 fsw_dnode_retain(child_dno);
629
630 } else {
631 // do an actual lookup
632 status = vol->fstype_table->dir_lookup(vol, dno, &lookup_name, &child_dno);
633 if (status)
634 goto errorexit;
635 }
636 }
637
638 // child_dno becomes the new dno
640 dno = child_dno; // is already retained
641 child_dno = NULL;
642
643 FSW_MSG_DEBUG((FSW_MSGSTR("fsw_dnode_lookup_path: now at inode %d\n"), dno->dnode_id));
644 }
645
646 *child_dno_out = dno;
647 return FSW_SUCCESS;
648
649errorexit:
650 FSW_MSG_DEBUG((FSW_MSGSTR("fsw_dnode_lookup_path: leaving with error %d\n"), status));
652 if (child_dno != NULL)
653 fsw_dnode_release(child_dno);
654 return status;
655}
656
669fsw_status_t fsw_dnode_dir_read(struct fsw_shandle *shand, struct fsw_dnode **child_dno_out)
670{
671 fsw_status_t status;
672 struct fsw_dnode *dno = shand->dnode;
673 fsw_u64 saved_pos;
674
675 if (dno->type != FSW_DNODE_TYPE_DIR)
676 return FSW_UNSUPPORTED;
677
678 saved_pos = shand->pos;
679 status = dno->vol->fstype_table->dir_read(dno->vol, dno, shand, child_dno_out);
680 if (status)
681 shand->pos = saved_pos;
682 return status;
683}
684
695fsw_status_t fsw_dnode_readlink(struct fsw_dnode *dno, struct fsw_string *target_name)
696{
697 fsw_status_t status;
698
699 status = fsw_dnode_fill(dno);
700 if (status)
701 return status;
702 if (dno->type != FSW_DNODE_TYPE_SYMLINK)
703 return FSW_UNSUPPORTED;
704
705 return dno->vol->fstype_table->readlink(dno->vol, dno, target_name);
706}
707
721{
722 fsw_status_t status;
723 struct fsw_shandle shand;
724 fsw_u32 buffer_size;
725 char buffer[FSW_PATH_MAX];
726 struct fsw_string s;
727
728 if (dno->size > FSW_PATH_MAX)
730
732 s.size = s.len = (int)dno->size;
733 s.data = buffer;
734
735 // open shandle and read the data
736 status = fsw_shandle_open(dno, &shand);
737 if (status)
738 return status;
739 buffer_size = (fsw_u32)s.size;
740 status = fsw_shandle_read(&shand, &buffer_size, buffer);
741 fsw_shandle_close(&shand);
742 if (status)
743 return status;
744 if ((int)buffer_size < s.size)
746
747 status = fsw_strdup_coerce(link_target, dno->vol->host_string_type, &s);
748 return status;
749}
750
764fsw_status_t fsw_dnode_resolve(struct fsw_dnode *dno, struct fsw_dnode **target_dno_out)
765{
766 fsw_status_t status;
767 struct fsw_string target_name;
768 struct fsw_dnode *target_dno;
769
770 fsw_dnode_retain(dno);
771
772 while (1) {
773 // get full information
774 status = fsw_dnode_fill(dno);
775 if (status)
776 goto errorexit;
777 if (dno->type != FSW_DNODE_TYPE_SYMLINK) {
778 // found a non-symlink target, return it
779 *target_dno_out = dno;
780 return FSW_SUCCESS;
781 }
782 if (dno->parent == NULL) { // safety measure, cannot happen in theory
783 status = FSW_NOT_FOUND;
784 goto errorexit;
785 }
786
787 // read the link's target
788 status = fsw_dnode_readlink(dno, &target_name);
789 if (status)
790 goto errorexit;
791
792 // resolve it
793 status = fsw_dnode_lookup_path(dno->parent, &target_name, '/', &target_dno);
794 fsw_strfree(&target_name);
795 if (status)
796 goto errorexit;
797
798 // target_dno becomes the new dno
800 dno = target_dno; // is already retained
801 }
802
803errorexit:
805 return status;
806}
807
823{
824 fsw_status_t status;
825
826 // read full dnode information into memory
827 status = fsw_dnode_fill(dno);
828 if (status)
829 return status;
830
831 // setup shandle
832 fsw_dnode_retain(dno);
833
834 shand->dnode = dno;
835 shand->pos = 0;
837
838 return FSW_SUCCESS;
839}
840
849{
850 if (shand->extent.type == FSW_EXTENT_TYPE_BUFFER)
851 fsw_free(shand->extent.buffer);
852 fsw_dnode_release(shand->dnode);
853}
854
860fsw_status_t fsw_shandle_read(struct fsw_shandle *shand, fsw_u32 *buffer_size_inout, void *buffer_in)
861{
862 fsw_status_t status;
863 struct fsw_dnode *dno = shand->dnode;
864 struct fsw_volume *vol = dno->vol;
865 fsw_u8 *buffer, *block_buffer;
866 fsw_u32 buflen, copylen, pos;
867 fsw_u32 log_bno, pos_in_extent, phys_bno, pos_in_physblock;
868 fsw_u32 cache_level;
869
870 if (shand->pos >= dno->size) { // already at EOF
871 *buffer_size_inout = 0;
872 return FSW_SUCCESS;
873 }
874
875 // initialize vars
876 buffer = buffer_in;
877 buflen = *buffer_size_inout;
878 pos = (fsw_u32)shand->pos;
879 cache_level = (dno->type != FSW_DNODE_TYPE_FILE) ? 1 : 0;
880 // restrict read to file size
881 if (buflen > dno->size - pos)
882 buflen = (fsw_u32)(dno->size - pos);
883
884 while (buflen > 0) {
885 // get extent for the current logical block
886 log_bno = pos / vol->log_blocksize;
887 if (shand->extent.type == FSW_EXTENT_TYPE_INVALID ||
888 log_bno < shand->extent.log_start ||
889 log_bno >= shand->extent.log_start + shand->extent.log_count) {
890
891 if (shand->extent.type == FSW_EXTENT_TYPE_BUFFER)
892 fsw_free(shand->extent.buffer);
893
894 // ask the file system for the proper extent
895 shand->extent.log_start = log_bno;
896 status = vol->fstype_table->get_extent(vol, dno, &shand->extent);
897 if (status) {
899 return status;
900 }
901 }
902
903 pos_in_extent = pos - shand->extent.log_start * vol->log_blocksize;
904
905 // dispatch by extent type
906 if (shand->extent.type == FSW_EXTENT_TYPE_PHYSBLOCK) {
907 // convert to physical block number and offset
908 phys_bno = shand->extent.phys_start + pos_in_extent / vol->phys_blocksize;
909 pos_in_physblock = pos_in_extent & (vol->phys_blocksize - 1);
910 copylen = vol->phys_blocksize - pos_in_physblock;
911 if (copylen > buflen)
912 copylen = buflen;
913
914 // get one physical block
915 status = fsw_block_get(vol, phys_bno, cache_level, (void **)&block_buffer);
916 if (status)
917 return status;
918
919 // copy data from it
920 fsw_memcpy(buffer, block_buffer + pos_in_physblock, copylen);
921 fsw_block_release(vol, phys_bno, block_buffer);
922
923 } else if (shand->extent.type == FSW_EXTENT_TYPE_BUFFER) {
924 copylen = shand->extent.log_count * vol->log_blocksize - pos_in_extent;
925 if (copylen > buflen)
926 copylen = buflen;
927 fsw_memcpy(buffer, (fsw_u8 *)shand->extent.buffer + pos_in_extent, copylen);
928
929 } else { // _SPARSE or _INVALID
930 copylen = shand->extent.log_count * vol->log_blocksize - pos_in_extent;
931 if (copylen > buflen)
932 copylen = buflen;
933 fsw_memzero(buffer, copylen);
934
935 }
936
937 buffer += copylen;
938 buflen -= copylen;
939 pos += copylen;
940 }
941
942 *buffer_size_inout = (fsw_u32)(pos - shand->pos);
943 shand->pos = pos;
944
945 return FSW_SUCCESS;
946}
947
948fsw_status_t fsw_dnode_get_path(struct fsw_volume *vol, struct fsw_dnode *dno, struct fsw_string *out_path) {
949 fsw_status_t status;
950 struct fsw_string *array, *temp_arr_ptr;
951 fsw_u32 array_capacity, array_len;
952 fsw_s64 i;
953 fsw_u16 *temp_char_ptr;
954
955 // Simple growable array
956#define START_BUF_SIZE 5
957 array_capacity = START_BUF_SIZE;
958 array_len = 0;
959 temp_arr_ptr = NULL;
960 status = fsw_alloc(array_capacity * sizeof(struct fsw_string), &array);
961 if (status) {
962 return status;
963 }
964#undef START_BUF_SIZE
965
966 out_path->len = 0;
967 out_path->size = 0;
968
969 while (status == FSW_SUCCESS && !fsw_dnode_is_root(dno)) {
970 // dnode should be filled!
971 fsw_dnode_fill(dno);
972
973 // Extend array capacity if needed
974 if (array_len == array_capacity) {
975 temp_arr_ptr = array;
976 array_capacity *= 2;
977 status = fsw_alloc(array_capacity * sizeof(struct fsw_string), &array);
978
979 if (!status) {
980 // Copy array contents
981 for (i = 0; i < (fsw_s64) array_len; ++i)
982 array[i] = temp_arr_ptr[i];
983
984 // Free the old pool
985 fsw_free(temp_arr_ptr);
986 temp_arr_ptr = NULL;
987 } else
988 // Store actual pointer into 'array'
989 array = temp_arr_ptr;
990 }
991
992 // If no errors - copy dnode name
993 if (status == FSW_SUCCESS)
994 status = fsw_strdup_coerce(&array[array_len], FSW_STRING_TYPE_UTF16, &dno->name);
995
996 // On any error free all allocated memory
997 if (status)
998 goto done;
999
1000 out_path->len += array[array_len].len + 1;
1001
1002 ++array_len;
1003 dno = dno->parent;
1004 }
1005
1006#define SEP_CHAR L'\\'
1007 out_path->type = FSW_STRING_TYPE_UTF16;
1008
1009 if (out_path->len == 0) {
1010 out_path->len = 1;
1011 }
1012
1013 out_path->size = out_path->len * sizeof(fsw_u16);
1014 status = fsw_alloc(out_path->size, &out_path->data);
1015 if (status)
1016 goto done;
1017
1018 temp_char_ptr = (fsw_u16 *) out_path->data;
1019 if (array_len > 0) {
1020 for (i = (fsw_s64) array_len - 1; i >= 0; --i) {
1021 *(temp_char_ptr++) = SEP_CHAR;
1022 fsw_memcpy(temp_char_ptr, array[i].data, array[i].size);
1023 temp_char_ptr += array[i].len;
1024 }
1025 } else {
1026 *temp_char_ptr = SEP_CHAR;
1027 }
1028
1029#undef SEP_CHAR
1030
1031done:
1032 for (i = 0; i < (fsw_s64) array_len; ++i)
1033 fsw_strfree(&array[i]);
1034 fsw_free(array);
1035
1036 return status;
1037}
1038
1039fsw_status_t fsw_get_bless_info(struct fsw_volume *vol, int type, struct fsw_string *out_path) {
1040 fsw_status_t status;
1041 struct fsw_dnode *dnode;
1042
1043 status = vol->fstype_table->get_bless_info(vol, type, &dnode);
1044 if (status) {
1045 return status;
1046 }
1047
1048 status = fsw_dnode_get_path(vol, dnode, out_path);
1049 return status;
1050}
1051
1052// EOF
cache_type_t type
UINT32 size
#define FSW_MSG_DEBUG(params)
Definition fsw_base.h:70
#define START_BUF_SIZE
fsw_status_t fsw_shandle_read(struct fsw_shandle *shand, fsw_u32 *buffer_size_inout, void *buffer_in)
Definition fsw_core.c:860
#define SEP_CHAR
fsw_status_t fsw_dnode_stat(struct fsw_dnode *dno, struct fsw_dnode_stat *sb)
Definition fsw_core.c:502
fsw_status_t fsw_dnode_fill(struct fsw_dnode *dno)
Definition fsw_core.c:483
fsw_status_t fsw_block_get(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, fsw_u32 cache_level, void **buffer_out)
Definition fsw_core.c:179
fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, struct fsw_dnode **dno_out)
Definition fsw_core.c:323
int fsw_dnode_is_root(struct fsw_dnode *dno)
Definition fsw_core.c:350
fsw_status_t fsw_dnode_dir_read(struct fsw_shandle *shand, struct fsw_dnode **child_dno_out)
Definition fsw_core.c:669
void fsw_shandle_close(struct fsw_shandle *shand)
Definition fsw_core.c:848
fsw_status_t fsw_dnode_lookup_path(struct fsw_dnode *dno, struct fsw_string *lookup_path, char separator, struct fsw_dnode **child_dno_out)
Definition fsw_core.c:554
void fsw_set_blocksize(struct fsw_volume *vol, fsw_u32 phys_blocksize, fsw_u32 log_blocksize)
Definition fsw_core.c:145
#define MAX_CACHE_LEVEL
Definition fsw_core.c:45
fsw_status_t fsw_shandle_open(struct fsw_dnode *dno, struct fsw_shandle *shand)
Definition fsw_core.c:822
fsw_status_t fsw_dnode_get_path(struct fsw_volume *vol, struct fsw_dnode *dno, struct fsw_string *out_path)
Definition fsw_core.c:948
fsw_status_t fsw_volume_stat(struct fsw_volume *vol, struct fsw_volume_stat *sb)
Definition fsw_core.c:125
void fsw_block_release(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, void *buffer)
Definition fsw_core.c:267
fsw_status_t fsw_dnode_lookup(struct fsw_dnode *dno, struct fsw_string *lookup_name, struct fsw_dnode **child_dno_out)
Definition fsw_core.c:529
fsw_status_t fsw_get_bless_info(struct fsw_volume *vol, int type, struct fsw_string *out_path)
Definition fsw_core.c:1039
fsw_status_t fsw_dnode_resolve(struct fsw_dnode *dno, struct fsw_dnode **target_dno_out)
Definition fsw_core.c:764
fsw_status_t fsw_dnode_readlink_data(struct fsw_dnode *dno, struct fsw_string *link_target)
Definition fsw_core.c:720
fsw_status_t fsw_mount(void *host_data, struct fsw_host_table *host_table, struct fsw_fstype_table *fstype_table, struct fsw_volume **vol_out)
Definition fsw_core.c:62
void fsw_unmount(struct fsw_volume *vol)
Definition fsw_core.c:107
fsw_status_t fsw_dnode_create(struct fsw_volume *vol, struct fsw_dnode *parent_dno, fsw_u32 dnode_id, int type, struct fsw_string *name, struct fsw_dnode **dno_out)
Definition fsw_core.c:372
void fsw_dnode_release(struct fsw_dnode *dno)
Definition fsw_core.c:442
void fsw_dnode_retain(struct fsw_dnode *dno)
Definition fsw_core.c:430
fsw_status_t fsw_dnode_readlink(struct fsw_dnode *dno, struct fsw_string *target_name)
Definition fsw_core.c:695
void fsw_dnode_mkcomplete(struct fsw_dnode *dno)
Definition fsw_core.c:420
int fsw_status_t
Definition fsw_core.h:153
void fsw_strfree(struct fsw_string *s)
Definition fsw_lib.c:310
@ FSW_DNODE_TYPE_SYMLINK
Definition fsw_core.h:267
@ FSW_DNODE_TYPE_FILE
Definition fsw_core.h:265
@ FSW_DNODE_TYPE_DIR
Definition fsw_core.h:266
int fsw_streq_cstr(struct fsw_string *s1, const char *s2)
Definition fsw_lib.c:169
#define VOLSTRUCTNAME
Definition fsw_core.h:139
int fsw_strlen(struct fsw_string *s)
Definition fsw_lib.c:79
@ FSW_EXTENT_TYPE_BUFFER
Definition fsw_core.h:297
@ FSW_EXTENT_TYPE_PHYSBLOCK
Definition fsw_core.h:296
@ FSW_EXTENT_TYPE_INVALID
Definition fsw_core.h:294
fsw_status_t fsw_strdup_coerce(struct fsw_string *dest, int type, struct fsw_string *src)
Definition fsw_lib.c:190
@ FSW_UNSUPPORTED
Definition fsw_core.h:162
@ FSW_NOT_FOUND
Definition fsw_core.h:163
@ FSW_SUCCESS
Definition fsw_core.h:159
@ FSW_VOLUME_CORRUPTED
Definition fsw_core.h:164
#define FSW_INVALID_BNO
Definition fsw_core.h:56
void fsw_strsplit(struct fsw_string *lookup_name, struct fsw_string *buffer, char separator)
Definition fsw_lib.c:246
fsw_status_t fsw_alloc_zero(int len, void **ptr_out)
Definition fsw_lib.c:49
#define FSW_PATH_MAX
Definition fsw_core.h:48
@ FSW_STRING_TYPE_ISO88591
Definition fsw_core.h:186
@ FSW_STRING_TYPE_EMPTY
Definition fsw_core.h:185
@ FSW_STRING_TYPE_UTF16
Definition fsw_core.h:188
#define fsw_memcpy(dest, src, size)
#define fsw_memzero(dest, size)
INT64 fsw_s64
UINT16 fsw_u16
UINT32 fsw_u32
UINT64 fsw_u64
#define fsw_free(ptr)
#define fsw_alloc(size, ptrptr)
UINT8 fsw_u8
#define FSW_MSGSTR(s)
#define DivU64x32(x, y, z)
fsw_u32 phys_bno
Physical block number.
Definition fsw_core.h:213
void * data
Block data buffer.
Definition fsw_core.h:214
fsw_u32 refcount
Reference count.
Definition fsw_core.h:211
fsw_u32 cache_level
Level of importance of this block.
Definition fsw_core.h:212
fsw_u64 used_bytes
Bytes actually used by the file on disk.
Definition fsw_core.h:326
struct VOLSTRUCTNAME * vol
The volume this dnode belongs to.
Definition fsw_core.h:247
struct fsw_dnode * prev
Doubly-linked list of all dnodes: next dnode.
Definition fsw_core.h:256
fsw_u32 dnode_id
Unique id number (usually the inode number)
Definition fsw_core.h:251
fsw_u64 size
Data size in bytes.
Definition fsw_core.h:253
struct fsw_dnode * next
Doubly-linked list of all dnodes: previous dnode.
Definition fsw_core.h:255
fsw_u32 complete
Flag to be set on all dnode info was filled.
Definition fsw_core.h:245
fsw_u32 refcount
Reference count.
Definition fsw_core.h:244
struct DNODESTRUCTNAME * parent
Parent directory dnode.
Definition fsw_core.h:248
int type
Type of the dnode - file, dir, symlink, special.
Definition fsw_core.h:252
struct fsw_string name
Name of this item in the parent directory.
Definition fsw_core.h:249
int type
Type of extent specification.
Definition fsw_core.h:282
fsw_u32 log_count
Logical block count.
Definition fsw_core.h:284
fsw_u32 log_start
Starting logical block number.
Definition fsw_core.h:283
void * buffer
Allocated buffer pointer (for FSW_EXTENT_TYPE_BUFFER only)
Definition fsw_core.h:286
fsw_u32 phys_start
Starting physical block number (for FSW_EXTENT_TYPE_PHYSBLOCK only)
Definition fsw_core.h:285
fsw_u32 volume_struct_size
Size for allocating the fsw_volume structure.
Definition fsw_core.h:362
fsw_status_t(* volume_stat)(struct VOLSTRUCTNAME *vol, struct fsw_volume_stat *sb)
Definition fsw_core.h:367
void(* volume_free)(struct VOLSTRUCTNAME *vol)
Definition fsw_core.h:366
fsw_status_t(* dir_lookup)(struct VOLSTRUCTNAME *vol, struct DNODESTRUCTNAME *dno, struct fsw_string *lookup_name, struct DNODESTRUCTNAME **child_dno)
Definition fsw_core.h:376
fsw_status_t(* get_extent)(struct VOLSTRUCTNAME *vol, struct DNODESTRUCTNAME *dno, struct fsw_extent *extent)
Definition fsw_core.h:373
fsw_status_t(* volume_mount)(struct VOLSTRUCTNAME *vol)
Definition fsw_core.h:365
int native_string_type
String type used by the host environment.
Definition fsw_core.h:347
void(* change_blocksize)(struct fsw_volume *vol, fsw_u32 old_phys_blocksize, fsw_u32 old_log_blocksize, fsw_u32 new_phys_blocksize, fsw_u32 new_log_blocksize)
Definition fsw_core.h:349
struct fsw_extent extent
Current extent.
Definition fsw_core.h:309
fsw_u64 pos
Current file pointer in bytes.
Definition fsw_core.h:308
struct fsw_dnode * dnode
The dnode this handle reads data from.
Definition fsw_core.h:306
void * data
Data pointer (may be NULL if type is EMPTY or len is zero)
Definition fsw_core.h:177
int len
Length in characters.
Definition fsw_core.h:175
int size
Total data size in bytes.
Definition fsw_core.h:176
int type
Encoding of the string - empty, ISO-8859-1, UTF8, UTF16.
Definition fsw_core.h:174
fsw_u32 phys_blocksize
Block size for disk access / file system structures.
Definition fsw_core.h:222
struct fsw_blockcache * bcache
Array of block cache entries.
Definition fsw_core.h:230
struct fsw_dnode * dnode_head
List of all dnodes allocated for this volume.
Definition fsw_core.h:228
struct fsw_string label
Volume label.
Definition fsw_core.h:226
fsw_u32 log_blocksize
Block size for logical file data.
Definition fsw_core.h:223
int host_string_type
String type used by the host environment.
Definition fsw_core.h:236
fsw_u32 bcache_size
Number of entries in the block cache array.
Definition fsw_core.h:231
struct fsw_fstype_table * fstype_table
Dispatch table for file system specific functions.
Definition fsw_core.h:235
struct fsw_host_table * host_table
Dispatch table for host-specific functions.
Definition fsw_core.h:234
void * host_data
Hook for a host-specific data structure.
Definition fsw_core.h:233
struct DNODESTRUCTNAME * root
Root directory dnode.
Definition fsw_core.h:225