/Module.symvers
/.tmp_versions
+# .swp files which are generated by open vim sessions.
+*.swp
+
#
# cscope files
#
cscope.*
+
+#emfile
+emfile-*
+
+# here are the files that are copied into the direct folder. They are modified
+# when they are copied. We don't want to track them.
+
+direct/yaffs_allocator.c
+direct/yaffs_allocator.h
+direct/yaffs_attribs.h
+direct/yaffs_bitmap.c
+direct/yaffs_bitmap.h
+direct/yaffs_cache.c
+direct/yaffs_cache.h
+direct/yaffs_checkptrw.c
+direct/yaffs_checkptrw.h
+direct/yaffs_ecc.c
+direct/yaffs_ecc.h
+direct/yaffs_endian.c
+direct/yaffs_endian.h
+direct/yaffs_getblockinfo.h
+direct/yaffs_guts.c
+direct/yaffs_guts.h
+direct/yaffs_nameval.c
+direct/yaffs_nameval.h
+direct/yaffs_nand.c
+direct/yaffs_nand.h
+direct/yaffs_packedtags1.c
+direct/yaffs_packedtags1.h
+direct/yaffs_packedtags2.c
+direct/yaffs_packedtags2.h
+direct/yaffs_summary.c
+direct/yaffs_summary.h
+direct/yaffs_tagscompat.c
+direct/yaffs_tagscompat.h
+direct/yaffs_tagsmarshall.c
+direct/yaffs_tagsmarshall.h
+direct/yaffs_trace.h
+direct/yaffs_verify.c
+direct/yaffs_verify.h
+direct/yaffs_yaffs1.c
+direct/yaffs_yaffs1.h
+direct/yaffs_yaffs2.c
+direct/yaffs_yaffs2.h
+
+
+
+# here are all the symlinks that yaffs direct uses
+# we don't want to track them.
+# this list was created using the command run in the root directory.
+# $ find * -type l -not -exec grep -q "^{}$" .gitignore \; -print >> .gitignore
+
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nanddrv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_packedtags2.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nandsim.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_cache.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_hweight.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_ramem2k.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_flexible_file_sim.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_cache.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_m18_drv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nandstore_file.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nand.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_bitmap.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_yaffs2.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_fileem2k.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_checkptrw.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_error.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_flashif.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_getblockinfo.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_list.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_ecc.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffsfs.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nand_drv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/ydirectenv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_allocator.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nanddrv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_verify.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffsfs.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nandsim.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_ramdisk.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nand_chip.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_summary.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nameval.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_summary.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_checkptrw.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nand_store.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_endian.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_m18_drv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_tagsmarshall.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_yaffs2.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nandsim_file.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_allocator.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yportenv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_packedtags2.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_osglue.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_flashif2.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_tagsmarshall.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_endian.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nand_drv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nandsim_file.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_fileem2k.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nor_drv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_verify.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nandsim_file.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_packedtags1.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nor_drv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/ynorsim.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nand.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_attribs.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_fileem.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_yaffs1.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_guts.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffscfg2k.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffscfg.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_flexible_file_sim.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_guts.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/ynorsim.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_ramdisk.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_hweight.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_packedtags1.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_trace.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_tagscompat.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_attribs.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_ecc.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_yaffs1.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_bitmap.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nameval.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nandemul2k.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_tagscompat.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_nandsim_file.h
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/yaffs_osglue.c
+direct/test-framework/unit_tests/64_and_32_bit_time/64_bit/nandstore_file.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nanddrv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_packedtags2.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nandsim.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_cache.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_hweight.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_ramem2k.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_flexible_file_sim.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_cache.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_m18_drv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nandstore_file.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nand.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_bitmap.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_yaffs2.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_fileem2k.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_checkptrw.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_error.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_flashif.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_getblockinfo.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_list.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_ecc.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffsfs.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nand_drv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/ydirectenv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_allocator.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nanddrv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_verify.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffsfs.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nandsim.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_ramdisk.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nand_chip.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_summary.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nameval.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_summary.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_checkptrw.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nand_store.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_endian.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_m18_drv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_tagsmarshall.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_yaffs2.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nandsim_file.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_allocator.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yportenv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_packedtags2.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_osglue.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_flashif2.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_tagsmarshall.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_endian.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nand_drv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nandsim_file.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_fileem2k.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nor_drv.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_verify.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nandsim_file.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_packedtags1.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nor_drv.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/ynorsim.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nand.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_attribs.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_fileem.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_yaffs1.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_guts.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffscfg2k.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffscfg.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_flexible_file_sim.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_guts.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/ynorsim.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_ramdisk.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_hweight.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_packedtags1.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_trace.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_tagscompat.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_attribs.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_ecc.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_yaffs1.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_bitmap.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nameval.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nandemul2k.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_tagscompat.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_nandsim_file.h
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/yaffs_osglue.c
+direct/test-framework/unit_tests/64_and_32_bit_time/32_bit/nandstore_file.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/nanddrv.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_packedtags2.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/nandsim.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_cache.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_hweight.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_ramem2k.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_flexible_file_sim.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_cache.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_m18_drv.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/nandstore_file.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nand.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_bitmap.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_yaffs2.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_fileem2k.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_checkptrw.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_error.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_flashif.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_getblockinfo.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_list.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_ecc.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffsfs.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nand_drv.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/ydirectenv.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_allocator.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/nanddrv.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_verify.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffsfs.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/nandsim.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_ramdisk.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/nand_chip.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_summary.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nameval.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_summary.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_checkptrw.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/nand_store.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_endian.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_m18_drv.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_tagsmarshall.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_yaffs2.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/nandsim_file.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_allocator.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yportenv.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_packedtags2.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_osglue.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_flashif2.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_tagsmarshall.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_endian.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nand_drv.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nandsim_file.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_fileem2k.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nor_drv.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_verify.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/nandsim_file.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_packedtags1.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nor_drv.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/ynorsim.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nand.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_attribs.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_fileem.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_yaffs1.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_guts.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffscfg2k.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffscfg.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_flexible_file_sim.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_guts.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/ynorsim.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_ramdisk.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_hweight.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_packedtags1.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_trace.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_tagscompat.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_attribs.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_ecc.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_yaffs1.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_bitmap.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nameval.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nandemul2k.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_tagscompat.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_nandsim_file.h
+direct/test-framework/unit_tests/is_yaffs_working_tests/yaffs_osglue.c
+direct/test-framework/unit_tests/is_yaffs_working_tests/nandstore_file.c
+direct/test-framework/unit_tests/quick_tests/nanddrv.c
+direct/test-framework/unit_tests/quick_tests/yaffs_packedtags2.h
+direct/test-framework/unit_tests/quick_tests/nandsim.h
+direct/test-framework/unit_tests/quick_tests/yaffs_cache.h
+direct/test-framework/unit_tests/quick_tests/yaffs_hweight.c
+direct/test-framework/unit_tests/quick_tests/yaffs_ramem2k.c
+direct/test-framework/unit_tests/quick_tests/yaffs_flexible_file_sim.c
+direct/test-framework/unit_tests/quick_tests/yaffs_cache.c
+direct/test-framework/unit_tests/quick_tests/yaffs_m18_drv.c
+direct/test-framework/unit_tests/quick_tests/nandstore_file.h
+direct/test-framework/unit_tests/quick_tests/yaffs_nand.c
+direct/test-framework/unit_tests/quick_tests/yaffs_bitmap.h
+direct/test-framework/unit_tests/quick_tests/yaffs_yaffs2.c
+direct/test-framework/unit_tests/quick_tests/yaffs_fileem2k.h
+direct/test-framework/unit_tests/quick_tests/yaffs_checkptrw.h
+direct/test-framework/unit_tests/quick_tests/yaffs_error.c
+direct/test-framework/unit_tests/quick_tests/yaffs_flashif.h
+direct/test-framework/unit_tests/quick_tests/yaffs_getblockinfo.h
+direct/test-framework/unit_tests/quick_tests/yaffs_list.h
+direct/test-framework/unit_tests/quick_tests/yaffs_ecc.c
+direct/test-framework/unit_tests/quick_tests/yaffsfs.h
+direct/test-framework/unit_tests/quick_tests/yaffs_nand_drv.c
+direct/test-framework/unit_tests/quick_tests/ydirectenv.h
+direct/test-framework/unit_tests/quick_tests/yaffs_allocator.h
+direct/test-framework/unit_tests/quick_tests/nanddrv.h
+direct/test-framework/unit_tests/quick_tests/yaffs_verify.h
+direct/test-framework/unit_tests/quick_tests/yaffsfs.c
+direct/test-framework/unit_tests/quick_tests/nandsim.c
+direct/test-framework/unit_tests/quick_tests/yaffs_ramdisk.h
+direct/test-framework/unit_tests/quick_tests/nand_chip.h
+direct/test-framework/unit_tests/quick_tests/yaffs_summary.h
+direct/test-framework/unit_tests/quick_tests/yaffs_nameval.c
+direct/test-framework/unit_tests/quick_tests/yaffs_summary.c
+direct/test-framework/unit_tests/quick_tests/yaffs_checkptrw.c
+direct/test-framework/unit_tests/quick_tests/nand_store.h
+direct/test-framework/unit_tests/quick_tests/yaffs_endian.c
+direct/test-framework/unit_tests/quick_tests/yaffs_m18_drv.h
+direct/test-framework/unit_tests/quick_tests/yaffs_tagsmarshall.c
+direct/test-framework/unit_tests/quick_tests/yaffs_yaffs2.h
+direct/test-framework/unit_tests/quick_tests/nandsim_file.c
+direct/test-framework/unit_tests/quick_tests/yaffs_allocator.c
+direct/test-framework/unit_tests/quick_tests/yportenv.h
+direct/test-framework/unit_tests/quick_tests/yaffs_packedtags2.c
+direct/test-framework/unit_tests/quick_tests/yaffs_osglue.h
+direct/test-framework/unit_tests/quick_tests/yaffs_flashif2.h
+direct/test-framework/unit_tests/quick_tests/yaffs_tagsmarshall.h
+direct/test-framework/unit_tests/quick_tests/yaffs_endian.h
+direct/test-framework/unit_tests/quick_tests/yaffs_nand_drv.h
+direct/test-framework/unit_tests/quick_tests/yaffs_nandsim_file.c
+direct/test-framework/unit_tests/quick_tests/yaffs_fileem2k.c
+direct/test-framework/unit_tests/quick_tests/yaffs_nor_drv.h
+direct/test-framework/unit_tests/quick_tests/yaffs_verify.c
+direct/test-framework/unit_tests/quick_tests/nandsim_file.h
+direct/test-framework/unit_tests/quick_tests/yaffs_packedtags1.c
+direct/test-framework/unit_tests/quick_tests/yaffs_nor_drv.c
+direct/test-framework/unit_tests/quick_tests/ynorsim.c
+direct/test-framework/unit_tests/quick_tests/yaffs_nand.h
+direct/test-framework/unit_tests/quick_tests/yaffs_attribs.h
+direct/test-framework/unit_tests/quick_tests/yaffs_fileem.c
+direct/test-framework/unit_tests/quick_tests/yaffs_yaffs1.c
+direct/test-framework/unit_tests/quick_tests/yaffs_guts.h
+direct/test-framework/unit_tests/quick_tests/yaffscfg2k.c
+direct/test-framework/unit_tests/quick_tests/yaffscfg.h
+direct/test-framework/unit_tests/quick_tests/yaffs_flexible_file_sim.h
+direct/test-framework/unit_tests/quick_tests/yaffs_guts.c
+direct/test-framework/unit_tests/quick_tests/ynorsim.h
+direct/test-framework/unit_tests/quick_tests/yaffs_ramdisk.c
+direct/test-framework/unit_tests/quick_tests/yaffs_hweight.h
+direct/test-framework/unit_tests/quick_tests/yaffs_packedtags1.h
+direct/test-framework/unit_tests/quick_tests/yaffs_trace.h
+direct/test-framework/unit_tests/quick_tests/yaffs_tagscompat.h
+direct/test-framework/unit_tests/quick_tests/yaffs_attribs.c
+direct/test-framework/unit_tests/quick_tests/yaffs_ecc.h
+direct/test-framework/unit_tests/quick_tests/yaffs_yaffs1.h
+direct/test-framework/unit_tests/quick_tests/yaffs_bitmap.c
+direct/test-framework/unit_tests/quick_tests/yaffs_nameval.h
+direct/test-framework/unit_tests/quick_tests/yaffs_nandemul2k.h
+direct/test-framework/unit_tests/quick_tests/yaffs_tagscompat.c
+direct/test-framework/unit_tests/quick_tests/yaffs_nandsim_file.h
+direct/test-framework/unit_tests/quick_tests/yaffs_osglue.c
+direct/test-framework/unit_tests/quick_tests/nandstore_file.c
+direct/test-framework/stress_tests/stress_tester/nanddrv.c
+direct/test-framework/stress_tests/stress_tester/yaffs_packedtags2.h
+direct/test-framework/stress_tests/stress_tester/nandsim.h
+direct/test-framework/stress_tests/stress_tester/yaffs_cache.h
+direct/test-framework/stress_tests/stress_tester/yaffs_hweight.c
+direct/test-framework/stress_tests/stress_tester/yaffs_ramem2k.c
+direct/test-framework/stress_tests/stress_tester/yaffs_flexible_file_sim.c
+direct/test-framework/stress_tests/stress_tester/yaffs_cache.c
+direct/test-framework/stress_tests/stress_tester/yaffs_m18_drv.c
+direct/test-framework/stress_tests/stress_tester/nandstore_file.h
+direct/test-framework/stress_tests/stress_tester/yaffs_nand.c
+direct/test-framework/stress_tests/stress_tester/yaffs_bitmap.h
+direct/test-framework/stress_tests/stress_tester/yaffs_yaffs2.c
+direct/test-framework/stress_tests/stress_tester/yaffs_fileem2k.h
+direct/test-framework/stress_tests/stress_tester/yaffs_checkptrw.h
+direct/test-framework/stress_tests/stress_tester/yaffs_error.c
+direct/test-framework/stress_tests/stress_tester/yaffs_flashif.h
+direct/test-framework/stress_tests/stress_tester/yaffs_getblockinfo.h
+direct/test-framework/stress_tests/stress_tester/yaffs_list.h
+direct/test-framework/stress_tests/stress_tester/yaffs_ecc.c
+direct/test-framework/stress_tests/stress_tester/yaffsfs.h
+direct/test-framework/stress_tests/stress_tester/yaffs_nand_drv.c
+direct/test-framework/stress_tests/stress_tester/ydirectenv.h
+direct/test-framework/stress_tests/stress_tester/yaffs_allocator.h
+direct/test-framework/stress_tests/stress_tester/nanddrv.h
+direct/test-framework/stress_tests/stress_tester/yaffs_verify.h
+direct/test-framework/stress_tests/stress_tester/yaffsfs.c
+direct/test-framework/stress_tests/stress_tester/nandsim.c
+direct/test-framework/stress_tests/stress_tester/yaffs_ramdisk.h
+direct/test-framework/stress_tests/stress_tester/nand_chip.h
+direct/test-framework/stress_tests/stress_tester/yaffs_summary.h
+direct/test-framework/stress_tests/stress_tester/yaffs_nameval.c
+direct/test-framework/stress_tests/stress_tester/yaffs_summary.c
+direct/test-framework/stress_tests/stress_tester/yaffs_checkptrw.c
+direct/test-framework/stress_tests/stress_tester/nand_store.h
+direct/test-framework/stress_tests/stress_tester/yaffs_endian.c
+direct/test-framework/stress_tests/stress_tester/yaffs_m18_drv.h
+direct/test-framework/stress_tests/stress_tester/yaffs_tagsmarshall.c
+direct/test-framework/stress_tests/stress_tester/yaffs_yaffs2.h
+direct/test-framework/stress_tests/stress_tester/nandsim_file.c
+direct/test-framework/stress_tests/stress_tester/yaffs_allocator.c
+direct/test-framework/stress_tests/stress_tester/yportenv.h
+direct/test-framework/stress_tests/stress_tester/yaffs_packedtags2.c
+direct/test-framework/stress_tests/stress_tester/yaffs_osglue.h
+direct/test-framework/stress_tests/stress_tester/yaffs_flashif2.h
+direct/test-framework/stress_tests/stress_tester/yaffs_tagsmarshall.h
+direct/test-framework/stress_tests/stress_tester/yaffs_endian.h
+direct/test-framework/stress_tests/stress_tester/yaffs_nand_drv.h
+direct/test-framework/stress_tests/stress_tester/yaffs_nandsim_file.c
+direct/test-framework/stress_tests/stress_tester/yaffs_fileem2k.c
+direct/test-framework/stress_tests/stress_tester/yaffs_nor_drv.h
+direct/test-framework/stress_tests/stress_tester/yaffs_verify.c
+direct/test-framework/stress_tests/stress_tester/nandsim_file.h
+direct/test-framework/stress_tests/stress_tester/yaffs_packedtags1.c
+direct/test-framework/stress_tests/stress_tester/yaffs_nor_drv.c
+direct/test-framework/stress_tests/stress_tester/ynorsim.c
+direct/test-framework/stress_tests/stress_tester/yaffs_nand.h
+direct/test-framework/stress_tests/stress_tester/yaffs_attribs.h
+direct/test-framework/stress_tests/stress_tester/yaffs_fileem.c
+direct/test-framework/stress_tests/stress_tester/yaffs_yaffs1.c
+direct/test-framework/stress_tests/stress_tester/yaffs_guts.h
+direct/test-framework/stress_tests/stress_tester/yaffscfg2k.c
+direct/test-framework/stress_tests/stress_tester/yaffscfg.h
+direct/test-framework/stress_tests/stress_tester/yaffs_flexible_file_sim.h
+direct/test-framework/stress_tests/stress_tester/yaffs_guts.c
+direct/test-framework/stress_tests/stress_tester/ynorsim.h
+direct/test-framework/stress_tests/stress_tester/yaffs_ramdisk.c
+direct/test-framework/stress_tests/stress_tester/yaffs_hweight.h
+direct/test-framework/stress_tests/stress_tester/yaffs_packedtags1.h
+direct/test-framework/stress_tests/stress_tester/yaffs_trace.h
+direct/test-framework/stress_tests/stress_tester/yaffs_tagscompat.h
+direct/test-framework/stress_tests/stress_tester/yaffs_attribs.c
+direct/test-framework/stress_tests/stress_tester/yaffs_ecc.h
+direct/test-framework/stress_tests/stress_tester/yaffs_yaffs1.h
+direct/test-framework/stress_tests/stress_tester/yaffs_bitmap.c
+direct/test-framework/stress_tests/stress_tester/yaffs_nameval.h
+direct/test-framework/stress_tests/stress_tester/yaffs_nandemul2k.h
+direct/test-framework/stress_tests/stress_tester/yaffs_tagscompat.c
+direct/test-framework/stress_tests/stress_tester/yaffs_nandsim_file.h
+direct/test-framework/stress_tests/stress_tester/yaffs_osglue.c
+direct/test-framework/stress_tests/stress_tester/nandstore_file.c
+direct/test-framework/stress_tests/threading/nanddrv.c
+direct/test-framework/stress_tests/threading/yaffs_packedtags2.h
+direct/test-framework/stress_tests/threading/nandsim.h
+direct/test-framework/stress_tests/threading/yaffs_cache.h
+direct/test-framework/stress_tests/threading/yaffs_hweight.c
+direct/test-framework/stress_tests/threading/yaffs_ramem2k.c
+direct/test-framework/stress_tests/threading/yaffs_flexible_file_sim.c
+direct/test-framework/stress_tests/threading/yaffs_cache.c
+direct/test-framework/stress_tests/threading/yaffs_m18_drv.c
+direct/test-framework/stress_tests/threading/nandstore_file.h
+direct/test-framework/stress_tests/threading/yaffs_nand.c
+direct/test-framework/stress_tests/threading/yaffs_bitmap.h
+direct/test-framework/stress_tests/threading/yaffs_yaffs2.c
+direct/test-framework/stress_tests/threading/yaffs_fileem2k.h
+direct/test-framework/stress_tests/threading/yaffs_checkptrw.h
+direct/test-framework/stress_tests/threading/yaffs_error.c
+direct/test-framework/stress_tests/threading/yaffs_flashif.h
+direct/test-framework/stress_tests/threading/yaffs_getblockinfo.h
+direct/test-framework/stress_tests/threading/yaffs_list.h
+direct/test-framework/stress_tests/threading/yaffs_ecc.c
+direct/test-framework/stress_tests/threading/yaffsfs.h
+direct/test-framework/stress_tests/threading/yaffs_nand_drv.c
+direct/test-framework/stress_tests/threading/ydirectenv.h
+direct/test-framework/stress_tests/threading/yaffs_allocator.h
+direct/test-framework/stress_tests/threading/nanddrv.h
+direct/test-framework/stress_tests/threading/yaffs_verify.h
+direct/test-framework/stress_tests/threading/yaffsfs.c
+direct/test-framework/stress_tests/threading/nandsim.c
+direct/test-framework/stress_tests/threading/yaffs_ramdisk.h
+direct/test-framework/stress_tests/threading/nand_chip.h
+direct/test-framework/stress_tests/threading/yaffs_summary.h
+direct/test-framework/stress_tests/threading/yaffs_nameval.c
+direct/test-framework/stress_tests/threading/yaffs_summary.c
+direct/test-framework/stress_tests/threading/yaffs_checkptrw.c
+direct/test-framework/stress_tests/threading/nand_store.h
+direct/test-framework/stress_tests/threading/yaffs_endian.c
+direct/test-framework/stress_tests/threading/yaffs_m18_drv.h
+direct/test-framework/stress_tests/threading/yaffs_tagsmarshall.c
+direct/test-framework/stress_tests/threading/yaffs_yaffs2.h
+direct/test-framework/stress_tests/threading/nandsim_file.c
+direct/test-framework/stress_tests/threading/yaffs_allocator.c
+direct/test-framework/stress_tests/threading/yportenv.h
+direct/test-framework/stress_tests/threading/yaffs_packedtags2.c
+direct/test-framework/stress_tests/threading/yaffs_osglue.h
+direct/test-framework/stress_tests/threading/yaffs_flashif2.h
+direct/test-framework/stress_tests/threading/yaffs_tagsmarshall.h
+direct/test-framework/stress_tests/threading/yaffs_endian.h
+direct/test-framework/stress_tests/threading/yaffs_nand_drv.h
+direct/test-framework/stress_tests/threading/yaffs_nandsim_file.c
+direct/test-framework/stress_tests/threading/yaffs_fileem2k.c
+direct/test-framework/stress_tests/threading/yaffs_nor_drv.h
+direct/test-framework/stress_tests/threading/yaffs_verify.c
+direct/test-framework/stress_tests/threading/nandsim_file.h
+direct/test-framework/stress_tests/threading/yaffs_packedtags1.c
+direct/test-framework/stress_tests/threading/yaffs_nor_drv.c
+direct/test-framework/stress_tests/threading/ynorsim.c
+direct/test-framework/stress_tests/threading/yaffs_nand.h
+direct/test-framework/stress_tests/threading/yaffs_attribs.h
+direct/test-framework/stress_tests/threading/yaffs_fileem.c
+direct/test-framework/stress_tests/threading/yaffs_yaffs1.c
+direct/test-framework/stress_tests/threading/yaffs_guts.h
+direct/test-framework/stress_tests/threading/yaffscfg2k.c
+direct/test-framework/stress_tests/threading/yaffscfg.h
+direct/test-framework/stress_tests/threading/yaffs_flexible_file_sim.h
+direct/test-framework/stress_tests/threading/yaffs_guts.c
+direct/test-framework/stress_tests/threading/ynorsim.h
+direct/test-framework/stress_tests/threading/yaffs_ramdisk.c
+direct/test-framework/stress_tests/threading/yaffs_hweight.h
+direct/test-framework/stress_tests/threading/yaffs_packedtags1.h
+direct/test-framework/stress_tests/threading/yaffs_trace.h
+direct/test-framework/stress_tests/threading/yaffs_tagscompat.h
+direct/test-framework/stress_tests/threading/yaffs_attribs.c
+direct/test-framework/stress_tests/threading/yaffs_ecc.h
+direct/test-framework/stress_tests/threading/yaffs_yaffs1.h
+direct/test-framework/stress_tests/threading/yaffs_bitmap.c
+direct/test-framework/stress_tests/threading/yaffs_nameval.h
+direct/test-framework/stress_tests/threading/yaffs_nandemul2k.h
+direct/test-framework/stress_tests/threading/yaffs_tagscompat.c
+direct/test-framework/stress_tests/threading/yaffs_nandsim_file.h
+direct/test-framework/stress_tests/threading/yaffs_osglue.c
+direct/test-framework/stress_tests/threading/nandstore_file.c
+direct/test-framework/stress_tests/handle_tests/nanddrv.c
+direct/test-framework/stress_tests/handle_tests/yaffs_packedtags2.h
+direct/test-framework/stress_tests/handle_tests/nandsim.h
+direct/test-framework/stress_tests/handle_tests/yaffs_cache.h
+direct/test-framework/stress_tests/handle_tests/yaffs_hweight.c
+direct/test-framework/stress_tests/handle_tests/yaffs_ramem2k.c
+direct/test-framework/stress_tests/handle_tests/yaffs_flexible_file_sim.c
+direct/test-framework/stress_tests/handle_tests/yaffs_cache.c
+direct/test-framework/stress_tests/handle_tests/yaffs_m18_drv.c
+direct/test-framework/stress_tests/handle_tests/nandstore_file.h
+direct/test-framework/stress_tests/handle_tests/yaffs_nand.c
+direct/test-framework/stress_tests/handle_tests/yaffs_bitmap.h
+direct/test-framework/stress_tests/handle_tests/yaffs_yaffs2.c
+direct/test-framework/stress_tests/handle_tests/yaffs_fileem2k.h
+direct/test-framework/stress_tests/handle_tests/yaffs_checkptrw.h
+direct/test-framework/stress_tests/handle_tests/yaffs_error.c
+direct/test-framework/stress_tests/handle_tests/yaffs_flashif.h
+direct/test-framework/stress_tests/handle_tests/yaffs_getblockinfo.h
+direct/test-framework/stress_tests/handle_tests/yaffs_list.h
+direct/test-framework/stress_tests/handle_tests/yaffs_ecc.c
+direct/test-framework/stress_tests/handle_tests/yaffsfs.h
+direct/test-framework/stress_tests/handle_tests/yaffs_nand_drv.c
+direct/test-framework/stress_tests/handle_tests/ydirectenv.h
+direct/test-framework/stress_tests/handle_tests/yaffs_allocator.h
+direct/test-framework/stress_tests/handle_tests/nanddrv.h
+direct/test-framework/stress_tests/handle_tests/yaffs_verify.h
+direct/test-framework/stress_tests/handle_tests/yaffsfs.c
+direct/test-framework/stress_tests/handle_tests/nandsim.c
+direct/test-framework/stress_tests/handle_tests/yaffs_ramdisk.h
+direct/test-framework/stress_tests/handle_tests/nand_chip.h
+direct/test-framework/stress_tests/handle_tests/yaffs_summary.h
+direct/test-framework/stress_tests/handle_tests/yaffs_nameval.c
+direct/test-framework/stress_tests/handle_tests/yaffs_summary.c
+direct/test-framework/stress_tests/handle_tests/yaffs_checkptrw.c
+direct/test-framework/stress_tests/handle_tests/nand_store.h
+direct/test-framework/stress_tests/handle_tests/yaffs_endian.c
+direct/test-framework/stress_tests/handle_tests/yaffs_m18_drv.h
+direct/test-framework/stress_tests/handle_tests/yaffs_tagsmarshall.c
+direct/test-framework/stress_tests/handle_tests/yaffs_yaffs2.h
+direct/test-framework/stress_tests/handle_tests/nandsim_file.c
+direct/test-framework/stress_tests/handle_tests/yaffs_allocator.c
+direct/test-framework/stress_tests/handle_tests/yportenv.h
+direct/test-framework/stress_tests/handle_tests/yaffs_packedtags2.c
+direct/test-framework/stress_tests/handle_tests/yaffs_osglue.h
+direct/test-framework/stress_tests/handle_tests/yaffs_flashif2.h
+direct/test-framework/stress_tests/handle_tests/yaffs_tagsmarshall.h
+direct/test-framework/stress_tests/handle_tests/yaffs_endian.h
+direct/test-framework/stress_tests/handle_tests/yaffs_nand_drv.h
+direct/test-framework/stress_tests/handle_tests/yaffs_nandsim_file.c
+direct/test-framework/stress_tests/handle_tests/yaffs_fileem2k.c
+direct/test-framework/stress_tests/handle_tests/yaffs_nor_drv.h
+direct/test-framework/stress_tests/handle_tests/yaffs_verify.c
+direct/test-framework/stress_tests/handle_tests/nandsim_file.h
+direct/test-framework/stress_tests/handle_tests/yaffs_packedtags1.c
+direct/test-framework/stress_tests/handle_tests/yaffs_nor_drv.c
+direct/test-framework/stress_tests/handle_tests/ynorsim.c
+direct/test-framework/stress_tests/handle_tests/yaffs_nand.h
+direct/test-framework/stress_tests/handle_tests/yaffs_attribs.h
+direct/test-framework/stress_tests/handle_tests/yaffs_fileem.c
+direct/test-framework/stress_tests/handle_tests/yaffs_yaffs1.c
+direct/test-framework/stress_tests/handle_tests/yaffs_guts.h
+direct/test-framework/stress_tests/handle_tests/yaffscfg2k.c
+direct/test-framework/stress_tests/handle_tests/yaffscfg.h
+direct/test-framework/stress_tests/handle_tests/yaffs_flexible_file_sim.h
+direct/test-framework/stress_tests/handle_tests/yaffs_guts.c
+direct/test-framework/stress_tests/handle_tests/ynorsim.h
+direct/test-framework/stress_tests/handle_tests/yaffs_ramdisk.c
+direct/test-framework/stress_tests/handle_tests/yaffs_hweight.h
+direct/test-framework/stress_tests/handle_tests/yaffs_packedtags1.h
+direct/test-framework/stress_tests/handle_tests/yaffs_trace.h
+direct/test-framework/stress_tests/handle_tests/yaffs_tagscompat.h
+direct/test-framework/stress_tests/handle_tests/yaffs_attribs.c
+direct/test-framework/stress_tests/handle_tests/yaffs_ecc.h
+direct/test-framework/stress_tests/handle_tests/yaffs_yaffs1.h
+direct/test-framework/stress_tests/handle_tests/yaffs_bitmap.c
+direct/test-framework/stress_tests/handle_tests/yaffs_nameval.h
+direct/test-framework/stress_tests/handle_tests/yaffs_nandemul2k.h
+direct/test-framework/stress_tests/handle_tests/yaffs_tagscompat.c
+direct/test-framework/stress_tests/handle_tests/yaffs_nandsim_file.h
+direct/test-framework/stress_tests/handle_tests/yaffs_osglue.c
+direct/test-framework/stress_tests/handle_tests/nandstore_file.c
obj-m := $(YAFFS_O)
- yaffs2-objs := yaffs_mtdif_single.o
+ yaffs2-objs := yaffs_cache.o
+ yaffs2-objs += yaffs_mtdif_single.o
yaffs2-objs += yaffs_packedtags1.o
yaffs2-objs += yaffs_ecc.o yaffs_vfs_single.o yaffs_guts.o
yaffs2-objs += yaffs_packedtags2.o
yaffs2-objs += yaffs_endian.o
yaffs2-objs += yaffs_summary.o
- yaffs2multi-objs := yaffs_mtdif_multi.o
+ yaffs2multi-objs := yaffs_cache.o
+ yaffs2multi-objs += yaffs_mtdif_multi.o
yaffs2multi-objs += yaffs_packedtags1.o
yaffs2multi-objs += yaffs_ecc.o yaffs_vfs_multi.o yaffs_guts.o
yaffs2multi-objs += yaffs_packedtags2.o
yaffs-y += yaffs_bitmap.o
yaffs-y += yaffs_summary.o
yaffs-y += yaffs_verify.o
+yaffs-y += yaffs_cache.o
#! /bin/sh
YAFFS_COMMON_SOURCES="\
- yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h \
+ yaffs_ecc.c yaffs_ecc.h \
+ yaffs_cache.c yaffs_cache.h \
+ yaffs_guts.c yaffs_guts.h \
yaffs_tagscompat.c yaffs_tagscompat.h \
yaffs_tagsmarshall.c yaffs_tagsmarshall.h \
yaffs_packedtags1.c yaffs_packedtags1.h \
-e "s/strncmp/yaffs_strncmp/g"\
-e "s/loff_t/Y_LOFF_T/g" \
>$i
+
+ chmod 0444 $i
done
elif [ "$1" = "clean" ] ; then
for i in $YAFFS_COMMON_SOURCES ; do
vecswap(pb, pn - r, r);
r = pb - pa;
if (r > es)
- yaffs_qsort(a, r / es, es, cmp);
+ qsort(a, r / es, es, cmp);
r = pd - pc;
if (r > es) {
/* Iterate rather than recurse to save stack space */
n = r / es;
goto loop;
}
-/* yaffs_qsort(pn - r, r / es, es, cmp);*/
+/* qsort(pn - r, r / es, es, cmp);*/
}
#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
-CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -DCONFIG_YAFFS_DEFINES_TYPES
+CFLAGS += -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -DCONFIG_YAFFS_DEFINES_TYPES
CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES
+CFLAGS += -DCONFIG_YAFFS_MONITOR_MALLOC
CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing -Werror
#CFLAGS += -fno-strict-aliasing
CFLAGS += -O0
#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
-
+CLEAN_OBJS += emfile-2k-0 emfile-nand emfile-nand128MB
COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o yaffs_error.o\
yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
+ yaffs_flexible_file_sim.o \
yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
yaffs_tagscompat.o yaffs_tagsmarshall.o \
yaffs_packedtags2.o yaffs_nand.o \
+ yaffs_cache.o \
yaffs_checkptrw.o \
yaffs_endian.o \
yaffs_nameval.o yaffs_attribs.o \
yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
yaffsfs.h yaffs_osglue.h ydirectenv.h \
yaffscfg.h \
+ yaffs_cache.c yaffs_cache.h\
yaffs_nandemul2k.h yaffs_list.h \
yaffs_attribs.c \
yportenv.h \
FRAMEWORKEXTRASYMLINKS = \
yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
yaffs_fileem.c yaffs_m18_drv.c yaffs_m18_drv.h \
+ yaffs_flexible_file_sim.c yaffs_flexible_file_sim.h \
yaffs_nor_drv.c yaffs_nor_drv.h \
yaffs_nand_drv.c yaffs_nand_drv.h \
yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \
ln -s $(YDI_FRAMEWORK_DIR)/$@ $@
$(ALLOBJS): %.o: %.c
- gcc -c $(CFLAGS) -o $@ $<
YDI_DIR = ../../
YDI_FRAMEWORK_DIR = ../
-TARGETS = directtest2k
+TARGETS = directtest2k reldevtest
all: $(TARGETS)
DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o
+RELDEVOBJS = $(COMMONTESTOBJS) reldevtest.o
-ALL_UNSORTED_OBJS += $(DIRECTTESTOBJS)
+ALL_UNSORTED_OBJS += $(DIRECTTESTOBJS) $(RELDEVOBJS)
include ../FrameworkRules.mk
-directtest2k: $(FRAMEWORK_SOURCES) $(DIRECTTESTOBJS)
+directtest2k: $(FRAMEWORK_SOURCES) $(DIRECTTESTOBJS) Makefile
gcc -o $@ $(DIRECTTESTOBJS) -lpthread
+reldevtest: $(FRAMEWORK_SOURCES) $(RELDEVOBJS) Makefile
+ gcc -o $@ $(RELDEVOBJS) -lpthread
+
--- /dev/null
+basic-tests README
+
+This test is where we write a tests to
+reproduce errors that are hard to recreate.
+
+These errors frequently require yaffs to be put
+into abnormal states, which will not work well in
+normal test rig.
+
+The solutions are manually verified here.
+
+This is not designed to be run by you as a test rig.
+It is just here for us to use for debugging purposes.
#include <time.h>
#include <ctype.h>
+
#include "yaffsfs.h"
#include "yaffs_guts.h" /* Only for dumping device innards */
+#include "yaffs_endian.h" /*For testing the swap_u64 macro */
extern int yaffs_trace_mask;
}
-
-
-
int dump_file_data(char *fn)
{
int h;
yaffs_DIR *d;
struct yaffs_dirent *de;
struct yaffs_stat s;
- char str[100];
+ char str[300];
d = yaffs_opendir(dname);
int total = 0;
int lastTotal = 0;
- char str[100];
+ char str[300];
yaffs_start_up();
}
+void fill_n_file_test(const char *mountpt, int n, int syz)
+{
+ int i;
+ int l;
+
+ yaffs_start_up();
+
+ yaffs_format(mountpt, 0, 0, 0);
+ yaffs_mount(mountpt);
+
+
+ for(i = 0; i < n; i++)
+ {
+ int h;
+ char fname[200];
+
+ sprintf(fname, "%s/%d", mountpt, i);
+
+ h = yaffs_open(fname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE);
+
+ l = syz;
+
+ while(l > 0) {
+ yaffs_write(h, fname, sizeof(fname));
+ l -= sizeof(fname);
+ }
+
+ yaffs_close(h);
+
+ }
+
+}
+
+
void fill_files_test(const char *mountpt)
{
int i;
struct yaffs_utimbuf utb;
struct yaffs_stat st;
+ //setup
yaffs_start_up();
yaffs_mount(mountpt);
h = yaffs_open(name,O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE);
yaffs_fstat(h,&st);
- printf(" times %lu %lu %lu\n",
- st.yst_atime, st.yst_ctime, st.yst_mtime);
+ printf(" times before %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
+ //here are the last access and modification times.
utb.actime = 1000;
utb.modtime = 2000;
+
+ //futime sets the last modification and access time of the file
result = yaffs_futime(h,&utb);
- printf("futime to a 1000 m 2000 result %d\n",result);
+ printf("setting times using the futime function to a 1000 m 2000 result %d\n",result);
+
+ //read the times from the file header
yaffs_fstat(h,&st);
- printf(" times %lu %lu %lu\n",
- st.yst_atime, st.yst_ctime, st.yst_mtime);
+ printf(" times %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
utb.actime = 5000;
result = yaffs_utime(name, &utb);
printf("utime to a 5000 m 8000 result %d\n",result);
yaffs_fstat(h,&st);
- printf(" times %lu %lu %lu\n",
- st.yst_atime, st.yst_ctime, st.yst_mtime);
+ printf(" times %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
result = yaffs_utime(name, NULL);
printf("utime to NULL result %d\n",result);
yaffs_fstat(h,&st);
- printf(" times %lu %lu %lu\n",
- st.yst_atime, st.yst_ctime, st.yst_mtime);
+ printf(" times %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
+
+}
+
+void print_binary(u64 val){
+ int count = 0;
+ for (int i= 63; i>=0; i --) {
+ if (count == 0){
+ printf(" ");
+ }
+ if ((((u64)1) << i) & val) {
+ printf("1");
+ } else {
+ printf("0");
+ }
+ count = (count +1) % 8;
+ }
+}
+
+void testing_swap_u64() {
+ int numberOfFailedTests = 0;
+ for (int i =0; i < 8; i ++) {
+ u64 startingNumber = (0xffLLu << (i*8));
+ u64 expected = (0xffLLu << (64 - (i*8) -8));
+ u64 converted = swap_u64(startingNumber);
+ if (converted != expected) {
+ numberOfFailedTests ++;
+ printf("numbers do not match.\n");
+ printf("0xff\t\t\t");
+ print_binary(0xff);
+ printf("\nStarting Number \t");
+ print_binary(startingNumber);
+ printf("\nExpecting \t\t");
+ print_binary(expected);
+ printf("\nConverted \t\t");
+ print_binary(converted);
+ printf("\n");
+ }
+ }
+ if (numberOfFailedTests){
+ printf("testing_swap failed %d tests\n", numberOfFailedTests);
+ } else {
+ printf("testing_swap_u64 passed all tests\n");
+ }
}
+
+void size_utime_test(const char *mountpt)
+{
+ char name[100];
+ int h;
+ int result;
+ struct yaffs_utimbuf utb;
+ struct yaffs_stat st;
+
+ //setup
+ yaffs_start_up();
+
+ yaffs_mount(mountpt);
+
+ strcpy(name,mountpt);
+ strcat(name,"/");
+ strcat(name,"xfile");
+
+ yaffs_unlink(name);
+
+ printf("created\n");
+ h = yaffs_open(name,O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE);
+
+ yaffs_fstat(h,&st);
+ printf(" times before %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
+
+ //first lets get the yaffs_object.
+
+ //then check that yaffs_stat also works.
+ //yaffs_stat already uses 64 bits for both wince and unix times.
+ //To see if we are using 32 or 64 bit time, save a large number into the time and
+ //see if it overflows.
+ long bitsInTime = 8*sizeof(st.yst_ctime);
+ printf("the times are %ld bits long\n", bitsInTime);
+
+ //two testcases
+ if (bitsInTime == 64) {
+ //no need to test the overflow. Just check that it can be retrieved intact.
+
+ //use u64 variables in case utb truncates the values to 32 bit time by accident.
+ u64 start = 0xfffff;
+ u64 end = 0xffffff;
+
+ utb.actime = start;
+ utb.modtime = end;
+
+ result = yaffs_futime(h,&utb);
+ yaffs_fstat(h,&st);
+ if (st.yst_atime == start && st.yst_mtime == end) {
+ printf("successfully stored and retrevied a 64 bit number for atime and modtime\n");
+ } else {
+ printf("failed to store and retrieve a 64 bit number for atime and modtime\n");
+
+ }
+ } else {
+ //it is a 32 bit number. Check to see that it overflowed.
+
+ }
+
+
+ //here are the last access and modification times.
+ utb.actime = 1000;
+ utb.modtime = 2000;
+
+ //futime sets the last modification and access time of the file
+ result = yaffs_futime(h,&utb);
+ printf("setting times using the futime function to a 1000 m 2000 result %d\n",result);
+
+ //read the times from the file header
+ yaffs_fstat(h,&st);
+ printf(" times %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
+
+
+ utb.actime = 5000;
+ utb.modtime = 8000;
+ result = yaffs_utime(name, &utb);
+ printf("utime to a 5000 m 8000 result %d\n",result);
+ yaffs_fstat(h,&st);
+ printf(" times %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
+
+ result = yaffs_utime(name, NULL);
+ printf("utime to NULL result %d\n",result);
+ yaffs_fstat(h,&st);
+ printf(" times %llu %llu %llu\n",
+ ( u64) st.yst_atime, ( u64) st.yst_ctime, ( u64) st.yst_mtime);
+
+
+}
+
+
void basic_xattr_test(const char *mountpt)
{
char name[100];
try_rmdir("/nand/z/");
}
+
+void dump_yaffs_malloc_usage(void)
+{
+ unsigned current;
+ unsigned high_water;
+
+ yaffsfs_get_malloc_values(¤t, &high_water);
+
+ printf("\n"
+ "***************************************\n"
+ "Dump of yaffs malloc usage during run\n"
+ "Currently allocated : %u bytes\n"
+ "High water allocated : %u bytes\n"
+ "Note, this is not accurate on all platforms\n",
+ current, high_water);
+
+}
+
+
int random_seed;
int simulate_power_failure;
int main(int argc, char *argv[])
{
+
+ //unlink("emfile-nand");
+
+
+ atexit(dump_yaffs_malloc_usage);
+
(void) argc;
(void) argv;
//link_test0("/nand");
//link_test1("yaffs2");
//scan_pattern_test("/flash",10000,10);
- short_scan_test("/yflash2",40000,200);
+ //short_scan_test("/yflash2",40000,200);
+ //short_scan_test("/nand128MB",40000,200);
//small_mount_test("/flash/flash",1000);
//small_overwrite_test("/flash/flash",1000);
//seek_overwrite_test("/flash/flash",1000);
//long_test_on_path("/ram2k");
// long_test_on_path("/flash");
//simple_rw_test("/flash/flash");
- //fill_disk_test("/flash/flash");
+ //fill_n_file_test("/nand128MB", 50, 128000000/50);
// rename_over_test("/flash");
//lookup_test("/flash");
//freespace_test("/flash/flash");
//large_file_test("/nand");
//readdir_test("/nand");
- //basic_utime_test("/nand");
+ basic_utime_test("/nand");
+ testing_swap_u64();
+ size_utime_test("/nand");
//case_insensitive_test("/nand");
//yy_test("/nand");
--- /dev/null
+/*
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2018 Aleph One Ltd.
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <ctype.h>
+
+
+#include "yaffsfs.h"
+
+#include "yaffs_guts.h" /* Only for dumping device innards */
+#include "yaffs_endian.h" /*For testing the swap_u64 macro */
+
+extern int yaffs_trace_mask;
+
+
+
+int call_all_reldev(struct yaffs_dev *dev)
+{
+ struct yaffs_stat buf;
+ struct yaffs_utimbuf utime;
+ unsigned char xbuffer[20];
+ char cbuffer[20];
+
+ yaffs_mount_reldev(dev);
+ yaffs_open_sharing_reldev(dev, "foo", 0, 0, 0);
+ yaffs_open_reldev(dev, "foo", 0, 0);
+ yaffs_truncate_reldev(dev, "foo", 99);
+ yaffs_unlink_reldev(dev, "foo");
+ yaffs_rename_reldev(dev, "foo", "foo_new");
+ yaffs_stat_reldev(dev, "foo", &buf);
+ yaffs_lstat_reldev(dev, "foo", &buf);
+ yaffs_utime_reldev(dev, "foo", &utime);
+ yaffs_setxattr_reldev(dev, "foo", "name", xbuffer, 20, 0);
+ yaffs_lsetxattr_reldev(dev, "foo", "name", xbuffer, 20, 0);
+ yaffs_getxattr_reldev(dev, "foo", "name", xbuffer, 20);
+ yaffs_lgetxattr_reldev(dev, "foo", "name", xbuffer, 20);
+
+ yaffs_listxattr_reldev(dev, "foo", cbuffer, 20);
+ yaffs_llistxattr_reldev(dev, "foo", cbuffer, 20);
+ yaffs_removexattr_reldev(dev, "foo", "name");
+ yaffs_lremovexattr_reldev(dev, "foo", "name");
+
+ yaffs_access_reldev(dev, "foo", 0);
+ yaffs_chmod_reldev(dev, "foo", 0);
+ yaffs_mkdir_reldev(dev, "foo", 0);
+ yaffs_rmdir_reldev(dev, "foo");
+
+
+ yaffs_opendir_reldev(dev, "foo");
+
+ //yaffs_symlink_reldev(dev, "foo", "foolink");
+ //yaffs_readlink_reldev(dev, "foo", cbuffer, 20);
+ //yaffs_link_reldev(dev, "foo", "foo_new");
+
+ yaffs_mknod_reldev(dev, "foo", 0, 0);
+ yaffs_freespace_reldev(dev);
+ yaffs_totalspace_reldev(dev);
+
+ yaffs_sync_reldev(dev);
+ yaffs_sync_files_reldev(dev);
+
+ yaffs_unmount_reldev(dev);
+ yaffs_unmount2_reldev(dev, 1);
+ yaffs_remount_reldev(dev, 1, 1);
+
+ return 0;
+}
+
+
+int random_seed;
+int simulate_power_failure;
+
+int main(int argc, char *argv[])
+{
+ (void) argc;
+ (void) argv;
+
+ call_all_reldev(NULL);
+
+ return 0;
+}
--- /dev/null
+handle_test
yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
+ gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) -lpthread
handle_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
+ gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) -lpthread
int output =0;
unsigned int total_number_of_tests_run=0;
yaffs_start_up();
- yaffs_mount("yaffs2");
+ yaffs_mount(YAFFS_MOUNT_POINT);
printf("running tests\n");
output=yaffs_lseek(handle,20,SEEK_SET);
if (output >= 0) {
output = yaffs_lseek(handle,0,SEEK_CUR);
- if (output = 20){
+ if (output == 20){
printf("dup is working\n");
return 1;
} else if (output <0){
#include <stdio.h>
#include "yaffsfs.h"
-#define FILE_PATH "/yaffs2/foo"
+#define YAFFS_MOUNT_POINT "/yflash2/"
+#define FILE_PATH "/yflash2/foo"
int open_close_handle_test(int num_of_tests);
int open_handle(void);
void get_error(void);
+int dup_test(void);
+
#endif
--- /dev/null
+yaffs_tester
YDI_FRAMEWORK_DIR = ../../
CLEAN_OBJS = yaffs_tester emfile-2k-0
-TESTFILES = yaffs_tester.o message_buffer.o error_handler.o
+TESTFILES = yaffs_tester.o message_buffer.o error_handler.o shared.o
all: yaffs_tester
yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
+ gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) -lpthread
yaffs_tester: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
+ gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) -lpthread
* error_handler.c contains code for checking yaffs function calls for errors.
*/
#include "error_handler.h"
-
+#include "shared.h"
typedef struct error_codes_template {
int code;
{ 0, NULL }
};
-const char * error_to_str(int err)
+char * error_to_str(int err)
{
- error_entry *e = error_list;
+ error_entry const *e = error_list;
if (err < 0)
err = -err;
while(e->code && e->text){
}
void yaffs_check_for_errors(char output, buffer *message_buffer,char error_message[],char success_message[]){
- char dummy[10];
- unsigned int x=0;
int yaffs_error=-1;
- char error_found=0;
+
if (output==-1)
{
add_to_buffer(message_buffer, "\nerror##########",MESSAGE_LEVEL_ERROR,PRINT);
--- /dev/null
+/*
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2018 Aleph One Ltd.
+ *
+ * Created by Timothy Manning <timothy@yaffs.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * error_handler.c contains code for checking yaffs function calls for errors.
+ */
+#include "shared.h"
+#include "yaffsfs.h"
+
+void quit_program(){
+ yaffs_unmount(YAFFS_MOUNT_DIR);
+ exit(1);
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2018 Aleph One Ltd.
+ *
+ * Created by Timothy Manning <timothy@yaffs.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __shared_h__
+#define __shared_h__
+
+#define YAFFS_TEST_DIR "/yflash2/test_dir" /*the path to the directory where all of the testing will take place*/
+#define YAFFS_MOUNT_DIR "/yflash2/" /*the path to the mount point which yaffs will mount*/
+
+void quit_program();
+#endif
#include "yaffs_tester.h"
+#include "shared.h"
buffer message_buffer; /*create message_buffer */
-char yaffs_test_dir[] ="/yaffs2/test_dir"; /*the path to the directory where all of the testing will take place*/
-char yaffs_mount_dir[]="/yaffs2/"; /*the path to the mount point which yaffs will mount*/
-
int main(int argc, char *argv[]){
- init(yaffs_test_dir,yaffs_mount_dir,argc,argv);
- test(yaffs_test_dir);
- yaffs_unmount(yaffs_mount_dir);
+ init(YAFFS_TEST_DIR, YAFFS_MOUNT_DIR, argc, argv);
+ test(YAFFS_TEST_DIR);
+ yaffs_unmount(YAFFS_MOUNT_DIR);
return 0;
}
}
-void quit_program(){
- yaffs_unmount(yaffs_mount_dir);
- exit(1);
-}
+
+
void join_paths(char *path1,char *path2,char *new_path ){
/* printf("strlen path1:%d\n",strlen(path1));
if (P_open_handles_array->number_of_open_handles<MAX_NUMBER_OF_OPENED_HANDLES)
{
generate_random_string(name,MAX_FILE_NAME_SIZE);
- printf("before %d %d %d\n",strlen(yaffs_test_dir),strlen(name),strlen(path));
+ //printf("before %d %d %d\n",strlen(yaffs_test_dir),strlen(name),strlen(path));
join_paths(yaffs_test_dir,name,path);
- printf("after %d %d %d\n",strlen(yaffs_test_dir),strlen(name),strlen(path));
+ //printf("after %d %d %d\n",strlen(yaffs_test_dir),strlen(name),strlen(path));
add_to_buffer(&message_buffer,"trying to open file: ",MESSAGE_LEVEL_BASIC_TASKS,NPRINT);
append_to_buffer(&message_buffer,path,MESSAGE_LEVEL_BASIC_TASKS,PRINT);
if (yaffs_access(path,0)==0){
}
void test(char*yaffs_test_dir){
- struct yaffs_stat stat;
- int output=0;
+
//char name[MAX_FILE_NAME_SIZE+3 ]="apple\0";
//char path[MAX_FILE_NAME_SIZE];
handle_regster open_handles_array;
void stat_file(char *path);
void write_to_random_file(handle_regster *P_open_handles_array);
void close_random_file(handle_regster *P_open_handles_array);
-void quit_program();
+
void truncate_random_file(handle_regster *P_open_handles_array);
#endif
RUNDIR=`pwd`/tmp
mkdir $RUNDIR
+# Check if RUNDIR is mounted, if not, mount as tmpfs
+# because we don't want to hammer the disk.
if [ -z "$(mount | grep $RUNDIR)" ]; then
-sudo mount -t tmpfs -osize=2G none $RUNDIR
+sudo mount -t tmpfs -osize=7G none $RUNDIR
sudo chmod a+wr $RUNDIR
fi
xterm -e "$LAUNCHDIR/manage_nand_test.sh 0 $iterations"&
xterm -e "$LAUNCHDIR/manage_nand_test.sh 1 $iterations"&
xterm -e "$LAUNCHDIR/manage_nand_test.sh 2 $iterations"&
+xterm -e "$LAUNCHDIR/manage_nand_test.sh 3 $iterations"&
+++ /dev/null
-# Makefile for linux_test
-#
-#
-# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
-#
-# Copyright (C) 2002-2018 Aleph One Ltd.
-#
-#
-# Created by Timothy Manning <timothy@aleph1.co.uk>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# NB Warning this Makefile does not include header dependencies.
-#
-
-YDI_DIR = ../../../
-YDI_FRAMEWORK_DIR = ../../
-CLEAN_OBJS = linux_test emfile-2k-0
-
-TESTFILES = linux_test.o lib.o
-
-all: linux_test
-
-YAFFS_TEST_OBJS = $(COMMONTESTOBJS) $(TESTFILES)
-
-
-ALL_UNSORTED_OBJS += $(YAFFS_TEST_OBJS) $(FUZZER_OBJS)
-
-include $(YDI_FRAMEWORK_DIR)/FrameworkRules.mk
-
-
-yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
-
-
-
-linux_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
-
+++ /dev/null
-
-linux_test.c tests yaffs running under linux using the nandsim generator.
-
-
-If a segmentation fault happens during the test then check that
-the nandsim has been initilised properly.
-
-How to initilise the nandsim
-
-$ make
-
-$ sudo -s
-...password..
-# now you have a root shell
-$ ./linux-tests/initnandsim 128MiB-2048
-$ insmod yaffs2multi.ko
-$ mkdir /mnt/y
-$ mount -t yaffs2 /dev/mtdblock0 /mnt/y
-
-
-
-How to change the permissions on the nandsim partition
-
-$ sudo chmod a+wr /mnt/y/
-#check the permission change
-$ touch /mnt/y/test_file
-
-How to clean the folder
-
-$ rm -rf /mnt/y
-
-
-The test must be run in sudo to work to allow the files to be
-created in the root folders.
-
-compile command: make
-run command: sudo ./linux_test
-
-command line options:
- -h display the command line options.
- -s [number] seeds the rand with the number.
- -p [number] sets the print level to the number.
- the higher the number the more low level commands are printed.
- the number should be between 0 and 5.
- -v verbose mode. everything is printed.
- -q quite mode. nothing is printed.
-
-
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "lib.h"
-static char message[200];
-static int PRINT_LEVEL = 3;
-static int exit_on_error_val =1;
-char string[FILE_NAME_LENGTH+1];
-
-
-int get_exit_on_error(void)
-{
- return exit_on_error_val;
-}
-
-void set_exit_on_error(int val)
-{
- exit_on_error_val=val;
-}
-
-node * linked_list_add_node(int pos,node *head_node)
-{
- node *new_node=NULL;
- if (pos==HEAD){
- new_node=malloc(sizeof(node));
- memset(new_node, 0, sizeof(node));
- new_node->string=NULL;
- new_node->next=head_node;
- return new_node;
- }
- return NULL;
-}
-
-void node_print_pointers(node *current_node)
-{
- while (current_node != NULL){
- sprintf(message,"current_node: %p, string: %s next_node: %p\n",current_node,current_node->string,current_node->next);
- print_message(3,message);
- current_node=current_node->next;
- }
-}
-
-int delete_linked_list(node *head_node)
-{
- node *next_node=NULL;
- node *current_node=head_node;
-
- while (current_node != NULL){
- next_node=current_node->next;
- free(current_node);
- current_node=next_node;
- }
-
- return 1;
-}
-
-char * generate_random_string(unsigned int length)
-{
-
- unsigned int x;
- for (x=0;x<(length-1);x++)
- {
- string[x]=(rand() % NAME_RANGE)+65;
- }
- string[x]='\0';
- return string;
-}
-
-void set_print_level(int new_level)
-{
- PRINT_LEVEL=new_level;
-}
-int get_print_level(void)
-{
- return PRINT_LEVEL;
-}
-void print_message(char print_level,char *message)
-{
- if (print_level <= PRINT_LEVEL){
- printf("%s",message);
- }
-}
-int random_int(void)
-{
- return (random()%1000000);
-}
-
-void check_function(int output)
-{
- if (output>=0){
- print_message(3,"test_passed\n");
- } else {
- print_message(3,"test_failed\n");
- get_error_linux();
- }
-}
-
-void get_error_linux(void)
-{
- int error_code=0;
- char message[30];
- message[0]='\0';
-
- error_code=errno;
- sprintf(message,"linux_error code %d\n",error_code);
- print_message(1,message);
-
- strcpy(message,"error is");
- perror(message);
-// sprintf(message,"error is : %s\n",yaffs_error_to_str(error_code));
- //perror(message);
- //print_message(1,message);
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __lib_h__
-#define __lib_h__
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define NAME_RANGE 10
-#define ROOT_PATH "/mnt/y/"
-#define FILE_NAME_LENGTH 3
-#define HEAD 0
-#define TAIL 1
-
-typedef struct node_temp{
- char *string;
- struct node_temp *next;
-}node;
-
-int get_exit_on_error(void);
-void set_exit_on_error(int val);
-int delete_linked_list(node *head_node);
-node * linked_list_add_node(int pos,node *head_node);
-int random_int(void);
-char * generate_random_string(unsigned int length);
-void get_error_linux(void);
-void check_function(int output);
-void print_message(char print_level, char *message);
-void set_print_level(int new_level);
-int get_print_level(void);
-void node_print_pointers(node *current_node);
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "linux_test.h"
-
-int random_seed;
-int simulate_power_failure = 1;
-
-char message[400]; //this is used for storing print messages.
-
-
-
-const struct option long_options[]={
- {"help", 0,NULL,'h'},
-
-
- {"print_level", 1,NULL,'p'},
- {"quiet", 0,NULL,'q'},
-
- {"seed", 1,NULL,'s'},
-
- {"verbose", 0,NULL,'v'}
-};
-
-const char short_options[]="hp:qs:v";
-
-
-void init(int argc, char *argv[])
-{
- char dir[200];
- dir[0]='\0';
- int x=-1;
- char message[100];
- int new_option;
-
- x=(unsigned)time(NULL);
- sprintf(message,"seeding srand with: %d\n",x);
- print_message(2,message);
- srand(x);
-
-
-
- do {
- new_option=getopt_long(argc,argv,short_options,long_options,NULL);
- if (new_option=='h'){
- printf("mirror_tests help\n");
- printf("arguments:\n");
- printf("\t-p [NUMBER] //sets the print level for mirror_tests.\n");
- printf("\t-v //verbose mode everything is printed\n");
- printf("\t-q //quiet mode nothing is printed.\n");
- printf("\t-s [number] //seeds rand with the number\n");
-
- exit(0);
-
- } else if (new_option=='p'){
- set_print_level(atoi(optarg));
- } else if (new_option=='v'){
- set_print_level(5);
- } else if (new_option=='q'){
- set_print_level(-1);
- } else if (new_option=='s'){
- srand(atoi(argv[x+1]));
-
- } else if (new_option==-1){
-
- } else if (new_option=='?') {
- printf("bad argument\n");
- exit(0);
- }
- }while(new_option!=-1);
-}
-
-int main(int argc, char *argv[])
-{
- dir_struct *scanned_dir=NULL;
- int output=0;
- int break_bool=0;
- int x=5;
-
- init(argc,argv);
- while( 1){
- while (break_bool!=1){
- //printf("x %d\n",x);
- x--;
- if (x<0 &&(break_bool!=1)){
- output=mkdir_test();
- break_bool=1;
- }
- x--;
- if (x<0 &&(break_bool!=1)){
- output=rmdir_test();
- break_bool=1;
- }
- x--;
- if (x<0 &&(break_bool!=1)){
- output=mknod_test();
- break_bool=1;
- }
- x--;
- if (x<0 &&(break_bool!=1)){
- output=symlink_test();
- break_bool=1;
- }
- x--;
- if (x<0 &&(break_bool!=1)){
- output=link_test();
- break_bool=1;
- }
- x--;
- if (x<0 &&(break_bool!=1)){
- output=rename_test();
- break_bool=1;
- }
- x--;
- if (x<0 &&(break_bool!=1)){
- scanned_dir=scan_dir();
-
- output=remount_test();
- check_dir(scanned_dir);
- scanned_dir=NULL; //the scanned dir has been freed in check_dir.
- break_bool=1;
- }
- }
- //printf("resetting x\n");
- check_function(output);
- break_bool=0;
- x=(rand()% 99);
- }
- return 0;
-}
-
-dir_struct * scan_dir(void)
-{
- struct dirent *dir_data;
- dir_struct *dir=NULL;
- dir=malloc(sizeof(dir_struct));
- memset(dir, 0, sizeof(dir_struct));
- DIR *open_dir=NULL;
-
-
- open_dir=opendir(ROOT_PATH);
- if (open_dir < 0){
- sprintf(message,"failed to find the directory: %s",ROOT_PATH);
- print_message(1,message);
- }
- dir_data=readdir(open_dir);
- while(dir_data){
- dir->path_list=linked_list_add_node(HEAD,dir->path_list);
- dir->path_list->string=malloc(strlen(dir_data->d_name)+1);
- strcpy(dir->path_list->string,dir_data->d_name);
- sprintf(message,"opened file: %s\n",dir->path_list->string);
- print_message(5,message);
- dir_data=readdir(open_dir);
- }
- closedir(open_dir);
- //node_print_pointers(dir->path_list);
- return dir;
-}
-
-int check_dir(dir_struct *old_dir)
-{
- print_message(3,"scanning new dir\n");
- dir_struct *new_dir=scan_dir();
- node *new_list=new_dir->path_list;
- node *old_list=old_dir->path_list;
- int exit_loop=0,error=0;
- print_message(3,"checking dir\n");
- for (;old_list!= NULL;old_list=old_list->next){
- //sprintf(message,"new_list=!NULL= %d, exit_loop !=1 = %d\n",(new_list!=NULL),(exit_loop !=1));
- //print_message(3,message);
- for (;(new_list!=NULL) && (exit_loop !=1);new_list=new_list->next){
- //sprintf(message,"comparing %s and %s\n",old_list->string,new_list->string);
- //print_message(3,message);
- if (strcmp( new_list->string ,old_list->string)==0){
- //files match -now compare the modes and contents of the files.
- //and set the paths to NULL.
- exit_loop=1;
- }
- /*if (new_list->next==NULL){
- print_message(3,"next is null\n");
-
- }*/
- }
- if (exit_loop !=1){
- //failed to find a matching file
- sprintf(message,"a file has disappeared: %s\n",old_list->string);
- print_message(3,message);
- error=1;
-
- }
- new_list=new_dir->path_list;
- exit_loop=0;
- }
- //now check if there are any old unmatched files
-
- //free both data structs
- delete_linked_list(old_dir->path_list);
- delete_linked_list(new_dir->path_list);
- new_dir->path_list=NULL;
- old_dir->path_list=NULL;
- free(old_dir);
- free(new_dir);
- if (error ==1){
- print_message(3,"checking dir failed\n");
- if (get_exit_on_error()==1){
- print_message(3,"exiting_program\n");
- exit(0);
- }
- }
-
- else if (error !=1){
- print_message(3,"checking dir passed\n");
- }
- return error;
-}
-
-int remount_test(void)
-{
- int output;
- print_message(3,"\nunmounting\n");
- output=umount2("/mnt/y",1);
- check_function(output);
- print_message(3,"mounting\n");
- mount("/dev/mtdblock0","/mnt/y","yaffs2",0,NULL);
- check_function(output);
- return output;
-}
-
-int mkdir_test(void)
-{
-
- char string[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- int mode=0,output=0;
- strcpy(string,ROOT_PATH);
- strcat(string,generate_random_string(FILE_NAME_LENGTH));
- mode = ((S_IREAD|S_IWRITE)&random_int());
- sprintf(message,"\nmaking directory: %s, with mode %d\n",string,mode);
- print_message(3,message);
- output= mkdir(string,mode);
- return output;
-}
-
-int rmdir_test(void)
-{
- char string[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- int output=0;
- strcpy(string,ROOT_PATH);
- strcat(string,generate_random_string(FILE_NAME_LENGTH));
-
- sprintf(message,"\nremoving directory: %s\n",string);
- print_message(3,message);
- output= rmdir(string);
- return output;
-}
-int symlink_test(void)
-{
- char string[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- char string2[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- int output;
- strcpy(string,ROOT_PATH);
- strcat(string,generate_random_string(FILE_NAME_LENGTH));
- strcpy(string2,ROOT_PATH);
- strcat(string2,generate_random_string(FILE_NAME_LENGTH));
- sprintf(message,"\nsymlink from: %s, to %s\n",string,string2);
- print_message(3,message);
- output= symlink(string,string2);
- return output;
-}
-int rename_test(void)
-{
- char string[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- char string2[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- int output;
- strcpy(string,ROOT_PATH);
- strcat(string,generate_random_string(FILE_NAME_LENGTH));
- strcpy(string2,ROOT_PATH);
- strcat(string2,generate_random_string(FILE_NAME_LENGTH));
- sprintf(message,"\nrenaming from: %s, to %s\n",string,string2);
- print_message(3,message);
- output= rename(string,string2);
- return output;
-}
-int link_test(void)
-{
- char string[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- char string2[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- int output=0;
- strcpy(string,ROOT_PATH);
- strcat(string,generate_random_string(FILE_NAME_LENGTH));
- strcpy(string2,ROOT_PATH);
- strcat(string2,generate_random_string(FILE_NAME_LENGTH));
- sprintf(message,"\nlink from: %s, to %s\n",string,string2);
- print_message(3,message);
- output= link(string,string2);
- return output;
-}
-int mknod_test(void)
-{
- char string[FILE_NAME_LENGTH+strlen(ROOT_PATH)];
- int mode=0,dev=0,output=0;
- strcpy(string,ROOT_PATH);
- strcat(string,generate_random_string(FILE_NAME_LENGTH));
- mode = ((S_IREAD|S_IWRITE)&random_int());
- dev = random_int();
- sprintf(message,"\nmaking node: %s, with mode %d, dev %d\n",string,mode,dev);
- print_message(3,message);
- output= mknod(string,mode,dev);
- return output;
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __linux_test_h__
-#define __linux_test_h__
-#include <stdio.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/mount.h>
-#include "lib.h"
-#include <fcntl.h>
-#include <time.h>
-#include <getopt.h>
-
-typedef struct dir_struct_temp{
- node *path_list;
- int number_of_items;
-}dir_struct;
-
-int check_dir(dir_struct *old_dir);
-dir_struct * scan_dir(void);
-int link_test(void);
-int symlink_test(void);
-int mknod_test(void);
-int mkdir_test(void);
-int rename_test(void);
-int rmdir_test(void);
-int remount_test(void);
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "test_yaffs_open_EISDIR.h"
-
-/*EISDIR is caused by trying to open a directory */
-
-static int handle = -1;
-
-int test_yaffs_open_EISDIR(void)
-{
- int error_code=0;
-
- handle=yaffs_open(YAFFS_MOUNT_POINT, O_CREAT | O_TRUNC| O_RDWR ,FILE_MODE );
- if (handle == -1){
- error_code=yaffs_get_error();
- if (abs(error_code)== EISDIR){
- return 1;
- } else {
- print_message("different error than expected\n", 2);
- return -1;
- }
- } else {
- print_message("non existant directory opened.(which is a bad thing)\n", 2);
- return -1;
- }
-
-}
-int test_yaffs_open_EISDIR_clean(void)
-{
- if (handle >=0){
- return yaffs_close(handle);
- } else {
- return 1; /* the file failed to open so there is no need to close it*/
- }
-}
-
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __test_yaffs_open_EISDIR_h__
-#define __test_yaffs_open_EISDIR_h__
-
-#include "lib.h"
-#include "yaffsfs.h"
-
-int test_yaffs_open_EISDIR(void);
-int test_yaffs_open_EISDIR_clean(void);
-
-#endif
+++ /dev/null
-# Makefile for mirror_tests
-#
-#
-# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
-#
-# Copyright (C) 2002-2018 Aleph One Ltd.
-#
-#
-# Created by Timothy Manning <timothy@aleph1.co.uk>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# NB Warning this Makefile does not include header dependencies.
-#
-
-YDI_DIR = ../../../
-YDI_FRAMEWORK_DIR = ../../
-CLEAN_OBJS = mirror_tests emfile-2k-0
-
-TESTFILES = mirror_tests.o lib.o\
- linux_test_open.o yaffs_test_open.o\
- linux_test_truncate.o yaffs_test_truncate.o \
- linux_test_unlink.o yaffs_test_unlink.o \
- linux_test_write.o yaffs_test_write.o
-
-all: mirror_tests
-
-YAFFS_TEST_OBJS = $(COMMONTESTOBJS) $(TESTFILES)
-
-
-ALL_UNSORTED_OBJS += $(YAFFS_TEST_OBJS) $(FUZZER_OBJS)
-
-include $(YDI_FRAMEWORK_DIR)/FrameworkRules.mk
-
-
-yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
-
-
-
-mirror_tests: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
-
+++ /dev/null
-Made by Timothy Manning on 24/12/2010 <timothy@yaffs.net>
-
-
- mirror_tests is designed to check that yaffs behaves the same way as linux.
- This is done by applying the same command to both linux and yaffs and
- then checking the output of the functions.
- The default place for creating linux files is direct/timothy_tests/mirror_tests/tests/
- This directory is removed and is recreated at the beginning of each test,
- However some of the files may be read only and cannot be deleted.
- It is much better to remove this directory via the command line.
-
- rm test/*;rmdir test/;./mirror_tests -n 100 -v
-
-compile command: make
-run command: mirror_tests
-
-Command line arguments
- -yaffs_path [PATH] sets the path for yaffs.
- -linux_path [PATH] sets the path for linux.
- -p [NUMBER] sets the print level for mirror_tests.
- -v verbose mode everything is printed
- -q quiet mode nothing is printed.
- -n [number] sets the number of random tests to run.
- -s [number] seeds rand with the number
- -t [number] sets yaffs_trace to the number
- -clean removes emfile and test dir
-
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "lib.h"
-
-static int EXIT_ON_ERROR = 1;
-static int PRINT_LEVEL = 2; //This sets the level of detail which is printed. There are 3 levels 0,1,2 and 3
- //0 just prints the number of tests passed and failed.
- //1 is the basic print level. it will print the details of a failed test.
- //2 will print if a test passes and cleans.
-void set_print_level(int new_level)
-{
- PRINT_LEVEL=new_level;
-}
-int get_print_level(void)
-{
- return PRINT_LEVEL;
-}
-
-void set_exit_on_error(int num)
-{
- EXIT_ON_ERROR=num;
-}
-
-int get_exit_on_error(void)
-{
- return EXIT_ON_ERROR;
-}
-
-void display_error(void)
-{
-
-}
-
-void get_error_yaffs(void)
-{
- int error_code=0;
- char message[30];
- message[0]='\0';
-
- error_code=yaffs_get_error();
- sprintf(message,"yaffs_error code %d\n",error_code);
- print_message(1,message);
- sprintf(message,"error is : %s\n",yaffs_error_to_str(error_code));
- print_message(1,message);
-}
-
-void get_error_linux(void)
-{
- int error_code=0;
- char message[30];
- message[0]='\0';
-
- error_code=errno;
- sprintf(message,"linux_error code %d\n",error_code);
- print_message(1,message);
- strcpy(message,"error code");
- sprintf(message,"error is : %s\n",yaffs_error_to_str(error_code));
- //perror(message);
- print_message(1,message);
-}
-void generate_random_string(char *ptr,int length_of_str){
- unsigned int x;
- unsigned int length=((rand() %(length_of_str-3))+3); /*creates a int with the number of charecters been between 1 and 51*/
- char letter='\0';
- strcpy(ptr,"");
- //printf("generating string\n");
- //printf("string length is %d\n",length);
- for (x=0; x <= (length-2) &&length>2 ; x++)
- {
- //printf("x=%d\n",x);
- /* keep generating a charecter until the charecter is legal*/
- while((letter=='\0' )||(letter=='/')||(letter=='\\')){
- letter=(rand() % 125-59)+58; /*generate a number between 32 and 126 and uses it as a charecter (letter) */
- }
- ptr[x]=letter;
- //printf("charecter generated is %c\n",ptr[x]);
- }
- ptr[x+1]='\0'; /*adds NULL charecter to turn it into a string*/
-
-}
-
-void join_paths(char *path1,char *path2,char *new_path )
-{
- char message[100];
- print_message(3,"joining paths\n");
- sprintf(message,"path1: %s\n",path1);
- print_message(3,message);
- sprintf(message,"path2: %s\n",path2);
- print_message(3,message);
- strcpy(new_path,"");
- //strcat(new_path,path1); /*since all functions have this then pull it out*/
- if ( (path1[(sizeof(path1)/sizeof(char))-2]=='/') && path2[0]!='/') {
- /*paths are compatiable. concatanate them. note -2 is because of \0*/
- strcat(new_path,path1);
- strcat(new_path,path2);
- //char new_path[(sizeof(path1)/sizeof(char))+(sizeof(path2)/sizeof(char))];
- //strcpy(new_path,strcat(path1,path2));
- //return new_path;
- } else if ((path1[(sizeof(path1)/sizeof(char))-2]!='/') && path2[0]=='/') {
- /*paths are compatiable. concatanate them*/
- strcat(new_path,path1);
- strcat(new_path,path2);
-
- } else if ((path1[(sizeof(path1)/sizeof(char))-2]!='/') && path2[0]!='/') {
- /*need to add a "/". */
- strcat(new_path,path1);
- strcat(new_path,"/");
- strcat(new_path,path2);
-
- } else if ((path1[(sizeof(path1)/sizeof(char))-2]=='/') && path2[0]=='/') {
- /*need to remove a "/". */
- /*yaffs does not mind the extra slash. */
- strcat(new_path,path1);
- strcat(new_path,path2);
-
- } else {
- //error
- //return -1;
- }
-}
-
-void print_message(char print_level,char *message)
-{
- if (print_level <= PRINT_LEVEL){
- printf(message);
- }
-}
-
-
-
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef _lib_h__
-#define _lib_h__
-
-#include <stdio.h>
-#include <string.h>
-#include "yaffsfs.h"
-#include <errno.h>
-
-typedef struct arg_temp2{
- char char1;
- char char2;
- char string1[100];
- char string2[100];
- int int1;
- int int2;
-} arg_temp;
-
-
-typedef struct test_dir_temp
-{
- int type_of_test; //used to tell if it is LINUX of YAFFS
- char root_path[200];
-} test_dir;
-test_dir yaffs_struct,linux_struct;
-
-
-
-void generate_random_string(char *ptr,int length_of_str);
-void join_paths(char *path1,char *path2,char *new_path );
-void print_message(char print_level, char *message);
-void set_print_level(int new_level);
-int get_print_level(void);
-void set_exit_on_error(int num);
-int get_exit_on_error(void);
-void display_error(void);
-void get_error_yaffs(void);
-void get_error_linux(void);
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "linux_test_open.h"
-
-int linux_test_open(arg_temp *args_struct)
-{
- char path[250];
- char message[150];
- int output;
- join_paths(linux_struct.root_path,args_struct->string1, path );
- sprintf(message,"file path: %s\n",path);
- print_message(3,message);
-
- output= open(path,args_struct->char1 & (O_TRUNC|O_EXCL|O_CREAT|O_APPEND) ,args_struct->char2& (S_IREAD|S_IWRITE));
- if (output>=0){
- output=close(output);
- if (output<0) {
- print_message(3,"failed to close handle\n");
- return -1;
- } else {
- return 1;
- }
- } else {
- print_message(3,"failed to open file\n");
- return -1;
- }
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __linux_test_open_h__
-#define __linux_test_open_h__
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "lib.h"
-
-int linux_test_open(arg_temp *args_struct);
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "linux_test_truncate.h"
-
-int linux_test_truncate(arg_temp *args_struct)
-{
- char path[200];
- char message[200];
- int output=0;
- join_paths(linux_struct.root_path,args_struct->string1, path );
- sprintf(message,"file path: %s\n",path);
- print_message(3,message);
-
- output=truncate(path,args_struct->int1);
- return output;
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __linux_test_truncate_h__
-#define __linux_test_truncate_h__
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "yaffsfs.h"
-#include "lib.h"
-
-int linux_test_truncate(arg_temp *args_struct);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "linux_test_unlink.h"
-
-int linux_test_unlink(arg_temp *args_struct)
-{
- char path[250];
- char message[150];
- int output;
- join_paths(linux_struct.root_path,args_struct->string1, path );
- sprintf(message,"file path: %s\n",path);
- print_message(3,message);
-
- output= unlink(path);
-
- if (output<0) {
- print_message(3,"failed to unlink file\n");
- return -1;
- } else {
- return 1;
- }
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __linux_test_unlink_h__
-#define __linux_test_unlink_h__
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "yaffsfs.h"
-#include "lib.h"
-
-int linux_test_unlink(arg_temp *args_struct);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "linux_test_write.h"
-
-int linux_test_write(arg_temp *args_struct)
-{
- char path[200];
- char message[200];
- int output=0;
- int handle=-1;
- join_paths(linux_struct.root_path,args_struct->string1, path );
- sprintf(message,"trying to write to: %s\nwith mode set to %o \n",path,args_struct->char1 );
- print_message(3,message);
- printf("mode S_IREAD %d S_IWRITE %d\n",(args_struct->char2 & S_IREAD),(args_struct->char2 & S_IWRITE));
- handle=open(path,((args_struct->char1 &(O_TRUNC|O_EXCL|O_CREAT|O_APPEND))|O_RDWR),(args_struct->char2&(S_IREAD|S_IWRITE)));
- printf("handle %d\n",handle);
- if (handle<0){
- print_message(3,"failed to open a handle\n");
- return -1; //handle failed to open
- }
- sprintf(message,"trying to write: %d bytes into the file\n",strlen(args_struct->string2));
- print_message(3,message);
- output=write(handle,args_struct->string2,strlen(args_struct->string2));
- close(handle);
- return output;
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __linux_test_write_h__
-#define __linux_test_write_h__
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "yaffsfs.h"
-#include "lib.h"
-
-int linux_test_write(arg_temp *args_struct);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "mirror_tests.h"
-
-int random_seed;
-int simulate_power_failure = 0;
-
-int num_of_random_tests=1;
-
-
-
-typedef struct test_list_temp2{
- char *test_name;
- int (*test_pointer)(arg_temp *args_struct);
-}test_list_temp;
-
-typedef struct test_temp2 {
- int num_of_tests;
- test_list_temp test_list[];
-}test_temp;
-
-test_temp yaffs_tests={
- 4,
- {{"yaffs_test_open",yaffs_test_open},
- {"yaffs_test_truncate",yaffs_test_truncate},
- {"yaffs_test_unlink",yaffs_test_unlink},
- {"yaffs_test_write",yaffs_test_write}
- }
-};
-
-test_temp linux_tests={
- 4,
- {{"linux_test_open",linux_test_open},
- {"linux_test_truncate",linux_test_truncate},
- {"linux_test_unlink",linux_test_unlink},
- {"linux_test_write",linux_test_write}
- }
-};
-
-const struct option long_options[]={
- {"help", 0,NULL,'h'},
- {"yaffs_path", 1,NULL,'y'},
- {"linux_path", 1,NULL,'l'},
- {"print_level", 1,NULL,'p'},
- {"quiet", 0,NULL,'q'},
- {"number", 1,NULL,'n'},
- {"seed", 1,NULL,'s'},
- {"trace", 1,NULL,'t'},
- {"clean", 0,NULL,'c'},
- {"verbose", 0,NULL,'v'}
-};
-
-const char short_options[]="hy:l:p:qn:s:t:cv";
-
-
-int main(int argc, char *argv[])
-{
- char message[100];
-
-// yaffs_tests.num_of_tests=(sizeof(yaffs_tests)/sizeof(test_temp));
-// linux_tests.num_of_tests=(sizeof(linux_tests)/sizeof(test_temp));
-
- init(argc,argv);
- print_message(1,"running mirror_tests\n");
- sprintf(message,"linux_root_path: %s\n",linux_struct.root_path);
- print_message(3,message);
- sprintf(message,"yaffs_root_path: %s\n",yaffs_struct.root_path);
- print_message(3,message);
- sprintf(message,"linux_num_of_tests: %d\n",linux_tests.num_of_tests);
- print_message(3,message);
- sprintf(message,"yaffs_num_of_tests: %d\n",yaffs_tests.num_of_tests);
- print_message(3,message);
-
- run_random_test(num_of_random_tests);
- //compare_linux_and_yaffs();
- yaffs_unmount("yaffs2");
- return 0;
-}
-
-void init(int argc, char *argv[])
-{
- char dir[200];
- dir[0]='\0';
- int x=-1;
- char message[100];
- int new_option;
-
- x=(unsigned)time(NULL);
- sprintf(message,"seeding srand with: %d\n",x);
- print_message(2,message);
- srand(x);
- yaffs_set_trace(0);
- linux_struct.type_of_test =LINUX;
- yaffs_struct.type_of_test =YAFFS;
-
- sprintf(message,"current absolute path is: %s\n",getcwd(dir,200));
- print_message(3,message);
- strcpy(dir,getcwd(dir,200));
-
- strcat(dir,"/test/");
- printf("dir: %s\n",dir);
- strcpy(linux_struct.root_path,dir);
- strcpy(yaffs_struct.root_path,"yaffs2/test/");
-
-
- do {
- new_option=getopt_long(argc,argv,short_options,long_options,NULL);
- if (new_option=='h'){
- printf("mirror_tests help\n");
- printf("arguments:\n");
- printf("\t-yaffs_path [PATH] //sets the path for yaffs.\n");
- printf("\t-linux_path [PATH] //sets the path for linux.\n");
- printf("\t-p [NUMBER] //sets the print level for mirror_tests.\n");
- printf("\t-v //verbose mode everything is printed\n");
- printf("\t-q //quiet mode nothing is printed.\n");
- printf("\t-n [number] //sets the number of random tests to run.\n");
- printf("\t-s [number] //seeds rand with the number\n");
- printf("\t-t [number] //sets yaffs_trace to the number\n");
- printf("\t-clean //removes emfile and test dir\n");
- exit(0);
- } else if (new_option=='y'){
- strcpy(yaffs_struct.root_path, optarg);
- } else if (new_option=='l'){
- strcpy(linux_struct.root_path, optarg);
- } else if (new_option=='p'){
- set_print_level(atoi(optarg));
- } else if (new_option=='v'){
- set_print_level(5);
- } else if (new_option=='q'){
- set_print_level(-1);
- } else if (new_option=='n'){
- num_of_random_tests=atoi(optarg);
- } else if (new_option=='s'){
- srand(atoi(argv[x+1]));
- } else if (new_option=='t'){
- yaffs_set_trace(atoi(optarg));
- } else if (new_option=='c'){
- clean_dir();
- exit(0);
- } else if (new_option==-1){
-
- } else if (new_option=='?') {
- printf("bad argument\n");
- exit(0);
- }
-
- } while(new_option!=-1);
- clean_dir();
- yaffs_start_up();
- print_message(2,"\nmounting yaffs\n");
- x=yaffs_mount("yaffs2");
- if (x<0) {
- print_message(3,"failed to mount yaffs\n");
- get_error_yaffs();
- } else {
- print_message(3,"mounted yaffs\n");
- }
-
-
- print_message(3,"\nmaking linux test dir\n");
- x=mkdir(linux_struct.root_path,0777);
- if (x<0) {
- print_message(1,"failed to make dir\n");
- get_error_linux();
- } else {
- print_message(3,"made dir\n");
- }
-
- print_message(3,"\nmaking yaffs test dir\n");
- x=yaffs_mkdir(yaffs_struct.root_path,0777);
- if (x<0) {
- print_message(1,"failed to make dir\n");
- get_error_yaffs();
- } else {
- print_message(3,"made dir\n");
- }
-}
-
-int run_random_test(int num_of_random_tests)
-{
- int y=0;
- int x=-1;
- int id=0;
- int test_id=-1;
- int num_of_tests_before_check=1;
- char message[200];
- arg_temp args_struct;
- for (y=0;(y*num_of_tests_before_check)<num_of_random_tests;y++){
- for (x=0;x<num_of_tests_before_check && (x+(y*num_of_tests_before_check)<num_of_random_tests);x++) {
- errno=0;
- yaffs_set_error(0);
- test_id = select_test_id(yaffs_tests.num_of_tests);
- sprintf(message,"running test_id %d\n",test_id);
- print_message(3,message);
- generate_random_numbers(&args_struct);
- run_yaffs_test(test_id, &args_struct);
-
- //check_mode(&args_struct);
-
- run_linux_test(test_id, &args_struct);
-
- if (get_print_level()>=4){
- get_error_yaffs();
- get_error_linux();
- }
-
- if ((abs(yaffs_get_error())!=abs(errno)) &&
- (abs(yaffs_get_error())!=EISDIR && abs(errno) != 0) &&
- (abs(yaffs_get_error())!=ENOENT && abs(errno) != EACCES)&&
- (abs(yaffs_get_error())!=EINVAL && abs(errno) != EBADF)
- ){
- print_message(2,"\ndifference in returned errors######################################\n");
- get_error_yaffs();
- get_error_linux();
- if (get_exit_on_error()){
- exit(0);
- }
- }
- }
- //check_mode(&args_struct);
- compare_linux_and_yaffs(&args_struct);
- //check_mode(&args_struct);
-
- }
- compare_linux_and_yaffs(&args_struct);
-}
-
-int select_test_id(int test_len)
-{
- int id=0;
- //printf("test_len = %d\n",test_len);
- id=(rand() % test_len );
- //printf("id %d\n",id);
- return id;
-
-}
-
-int check_mode(arg_temp *args_struct)
-{
- char path[200];
- char message[200];
- int output=0;
-
- struct yaffs_stat yaffs_stat_struct;
- join_paths(yaffs_struct.root_path,args_struct->string1, path );
- sprintf(message,"\ntrying to stat to: %s\n",path);
- print_message(3,message);
- output=yaffs_stat(path,&yaffs_stat_struct);
- if (output < 0){
- sprintf(message,"failed to stat the file\n");
- print_message(3,message);
- get_error_yaffs();
- } else {
- sprintf(message,"stated the file\n");
- print_message(3,message);
- sprintf(message," yaffs file mode is %d\n",(yaffs_stat_struct.st_mode & (S_IREAD| S_IWRITE)));
- print_message(3,message);
- sprintf(message,"mode S_IREAD %d S_IWRITE %d\n",(yaffs_stat_struct.st_mode & S_IREAD),(yaffs_stat_struct.st_mode & S_IWRITE));
- print_message(3,message);
- }
- return 1;
-}
-
-int check_mode_file(char *path)
-{
- char message[200];
- int output=0;
-
- struct yaffs_stat yaffs_stat_struct;
-
- sprintf(message,"\ntrying to stat to: %s\n",path);
- print_message(3,message);
- output=yaffs_stat(path,&yaffs_stat_struct);
- if (output < 0){
- sprintf(message,"failed to stat the file\n");
- print_message(3,message);
- get_error_yaffs();
- } else {
- sprintf(message,"stated the file\n");
- print_message(3,message);
- sprintf(message," yaffs file mode is %d\n",(yaffs_stat_struct.st_mode & (S_IREAD| S_IWRITE)));
- print_message(3,message);
- sprintf(message,"mode S_IREAD %d S_IWRITE %d\n\n",(yaffs_stat_struct.st_mode & S_IREAD),(yaffs_stat_struct.st_mode & S_IWRITE));
- print_message(3,message);
- }
- return 1;
-}
-
-int compare_linux_and_yaffs(arg_temp *args_struct)
-{
- int x=0,y=0;
- char l_path[200];
- char y_path[200];
- char file_name[200];
- int exit_bool=0;
- int number_of_files_in_yaffs=0;
- int number_of_files_in_linux=0;
- char message[200];
- char **yaffs_file_list=NULL;
- char **linux_file_list=NULL;
-
- struct yaffs_stat yaffs_stat_struct;
- struct stat linux_stat_struct;
- yaffs_DIR *yaffs_open_dir;
- struct yaffs_dirent *yaffs_current_file;
-
- DIR *linux_open_dir;
- struct dirent *linux_current_file;
-
- l_path[0]='\0';
- y_path[0]='\0';
- file_name[0]='\0';
- message[0]='\0';
- print_message(2,"\n\n\n comparing folders\n");
-// check_mode_file("yaffs2/test/YY");
- //find out the number of files in the directory
- yaffs_open_dir = yaffs_opendir(yaffs_struct.root_path);
- if (yaffs_open_dir) {
- for (x=0;yaffs_readdir(yaffs_open_dir);x++){}
- number_of_files_in_yaffs=x;
- sprintf(message,"number of files in yaffs dir= %d\n",number_of_files_in_yaffs);
- print_message(2,message);
- yaffs_rewinddir(yaffs_open_dir);
- } else {
- print_message(3,"failed to open yaffs test dir\n");
- }
- //create array
- yaffs_file_list= (char **)malloc(x*sizeof(char*));
- for (x=0;x<number_of_files_in_yaffs;x++) {
- yaffs_file_list[x]=malloc(200);
- }
-
- //check_mode_file("yaffs2/test/YY");
- //copy file names into array
- if (yaffs_open_dir){
- yaffs_current_file =yaffs_readdir(yaffs_open_dir);
- for (x=0 ;yaffs_current_file;x++)
- {
- printf("x= %d \n",x);
- printf("yaffs_current_file->d_name = %s\n",yaffs_current_file->d_name);
- if (yaffs_current_file){
- strcpy(yaffs_file_list[x],yaffs_current_file->d_name);
-
- }
- yaffs_current_file =yaffs_readdir(yaffs_open_dir);
- }
- yaffs_closedir(yaffs_open_dir);
- } else {
- print_message(3,"failed to populate yaffs test list\n");
- }
-
-
- //find out the number of files in the directory
- linux_open_dir = opendir(linux_struct.root_path);
- if (linux_open_dir){
- for (x=0;readdir(linux_open_dir);x++){}
- number_of_files_in_linux=(x-2);
- sprintf(message,"number of files in linux dir= %d\n",(number_of_files_in_linux));
- print_message(2,message);
- //the -2 is because linux shows 2 extra files which are automaticly created.
-
- rewinddir(linux_open_dir);
- } else {
- print_message(3,"failed to open linux test dir\n");
- }
-
- //create array
- linux_file_list= (char **)malloc(number_of_files_in_linux*sizeof(char*));
-
- for (x=0;x<number_of_files_in_linux;x++) {
- linux_file_list[x]=malloc(200);
- }
-
- //check_mode_file("yaffs2/test/YY");
- //copy file names into array
- if (linux_open_dir){
- linux_current_file =readdir(linux_open_dir);
- for (x=0, y=0 ;linux_current_file;x++)
- {
-
- if (linux_current_file){
- strcpy(message,linux_current_file->d_name);
- print_message(7,"opened file: ");
- print_message(7,message);
- print_message(7,"\n");
- }
- if (linux_current_file &&
- 0!=strcmp(message,".")&&
- 0!=strcmp(message,"..")){
- strcpy(file_name,linux_current_file->d_name);
- //sprintf("file opened: %s\n",linux_current_file->d_name);
- //print_message(3,message);
- print_message(7,"added file to list\n");
- strcpy(linux_file_list[y],file_name);
- sprintf(message,"file added to list: %s\n",linux_file_list[y]);
- print_message(7,message);
- y++;
- }
- linux_current_file =readdir(linux_open_dir);
- }
- closedir(linux_open_dir);
- } else {
- print_message(3,"failed to populate linux test dir\n");
- }
-
-
- //match the files in both folders
- for (x=0;x<number_of_files_in_yaffs;x++){
- sprintf(message,"\nsearching for yaffs file: %s\n",yaffs_file_list[x]);
- print_message(3,message);
- for (y=0;y<number_of_files_in_linux;y++){
- sprintf(message,"comparing to linux file: %s\n",linux_file_list[y]);
- print_message(7,message);
-
- if (0==strcmp(yaffs_file_list[x],linux_file_list[y])){
- sprintf(message,"file matched: %s\n",linux_file_list[y]);
- print_message(3,message);
- //check that the modes of both files are the same
- join_paths(yaffs_struct.root_path,yaffs_file_list[x],y_path);
- join_paths(linux_struct.root_path,linux_file_list[y],l_path);
- if (yaffs_stat(y_path,&yaffs_stat_struct)>=0&&
- stat(l_path,&linux_stat_struct)>=0){
- sprintf(message," yaffs file mode is %d\n",(yaffs_stat_struct.st_mode & (S_IREAD| S_IWRITE)));
- print_message(3,message);
- sprintf(message,"mode S_IREAD %d S_IWRITE %d\n",(yaffs_stat_struct.st_mode & S_IREAD),(yaffs_stat_struct.st_mode & S_IWRITE));
- print_message(3,message);
- sprintf(message," linux file mode is %d\n",(linux_stat_struct.st_mode & (S_IREAD|S_IWRITE)));
- print_message(3,message);
- sprintf(message,"mode S_IREAD %d S_IWRITE %d\n",(linux_stat_struct.st_mode & S_IREAD),(linux_stat_struct.st_mode & S_IWRITE));
- print_message(3,message);
- if ((yaffs_stat_struct.st_mode & (S_IREAD| S_IWRITE))==
- ( linux_stat_struct.st_mode & (S_IREAD|S_IWRITE))){
- print_message(2,"file modes match\n");
- } else {
- print_message(2,"file modes do not match\n");
- exit_bool=1;
- }
- linux_file_list[y][0]=NULL;
- yaffs_file_list[x][0]=NULL;
- } else {
- print_message(2,"failed to stat one of the files\n");
- get_error_yaffs();
- get_error_linux();
- }
-
- //read file contents
-
-
- break;
- }
- }
- }
-
- //print remaining files
- for (x=0;x<number_of_files_in_linux;x++){
- if (linux_file_list[x][0]){
- sprintf(message,"unmatched file in linux: %s\n",linux_file_list[x]);
- print_message(2,message);
- exit_bool=1;
- }
- }
- for (x=0;x<number_of_files_in_yaffs;x++){
- if (yaffs_file_list[x][0]){
- sprintf(message,"unmatched file in yaffs: %s\n",yaffs_file_list[x]);
- print_message(2,message);
- exit_bool=1;
- }
- }
- if (exit_bool==1&& get_exit_on_error()==1){
- print_message(2,"exiting program\n");
- exit(0);
- }
-
- for (x=0;x<number_of_files_in_yaffs;x++) {
- free(yaffs_file_list[x]);
- }
- free(yaffs_file_list);
-
- for (x=0;x<number_of_files_in_linux;x++) {
- free(linux_file_list[x]);
- }
- free(linux_file_list);
-
-
- //printf("file_name %s\n", yaffs_current_file->d_name);
-// generate_array_of_objects_in_yaffs();
-// generate_array_of_objects_in_linux();
- //first do a check to see if both sides have the same objects on both sides.
- //then stat all of the files and compare size and mode
- //read the text of each file and compare them.
-
- //show the diffrences by printing them.
- return 1;
-
-}
-
-void generate_random_numbers(arg_temp *args_struct)
-{
- char string[51];
- args_struct->char1= (rand() % 255);
- args_struct->char2= (rand() % 255);
- args_struct->int1= (rand() % 100000);
- args_struct->int2= (rand() % 100000);
- generate_random_string(string,50);
- strcpy(args_struct->string1, string);
- generate_random_string(string,50);
- strcpy(args_struct->string2, string);
-}
-
-void run_yaffs_test(int id,arg_temp *args_struct)
-{
- char message[200];
- int output =0;
- print_message(3,"\n");
- //printf("id = %d\n",id);
- sprintf(message,"running_test %s\n",yaffs_tests.test_list[id].test_name);
- print_message(3,message);
- output=yaffs_tests.test_list[id].test_pointer(args_struct);
- if (output<0) {
- sprintf(message,"test_failed %s\n",yaffs_tests.test_list[id].test_name);
- print_message(3,message);
- } else {
- print_message(3,"test_passed\n");
- }
-}
-
-void run_linux_test(int id,arg_temp *args_struct)
-{
- char message[200];
- int output =0;
- print_message(3,"\n");
- //printf("id = %d\n",id);
- sprintf(message,"running_test %s\n",linux_tests.test_list[id].test_name);
- print_message(3,message);
- output=linux_tests.test_list[id].test_pointer(args_struct);
- if (output<0) {
- sprintf(message,"test_failed %s\n",linux_tests.test_list[id].test_name);
- print_message(3,message);
- } else {
- print_message(3,"test_passed\n");
- }
-}
-
-
-void clean_dir(void)
-{
- char string[200];
- char file[200];
- char message[200];
- DIR *linux_open_dir;
- struct dirent *linux_current_file;
- int x=0,output=0;
-
- getcwd(string,200);
- strcat(string,"/emfile-2k-0");
- sprintf(message,"\n\nunlinking emfile at this path: %s\n",string);
- print_message(3,message);
- unlink(string);
-
-
- linux_open_dir = opendir(linux_struct.root_path);
- if (linux_open_dir){
-
- do
- {
-
- linux_current_file =readdir(linux_open_dir);
- if (NULL!=linux_current_file){
-
- strcpy(file,linux_struct.root_path);
- strcat(file,linux_current_file->d_name);
- sprintf(message,"unlinking file %s\n",file);
- print_message(3,message);
- print_message(3,"chmoding file\n");
- output=chmod(file,(S_IRUSR|S_IWUSR));
- if (output<0) {
- get_error_linux();
- }
- print_message(3,"unlinking file\n");
- output=unlink(file);
- if (output<0) {
- get_error_linux();
- }
- }
- } while(linux_current_file);
- closedir(linux_open_dir);
- rmdir(linux_struct.root_path);
- }
-
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __mirror_tests_h__
-#define __mirror_tests_h__
-
-#include <stdio.h>
-#include <dirent.h>
-#include <unistd.h> //used for getting the current directory.
-#include <string.h>
-#include <errno.h>
-#include "yaffsfs.h"
-#include "lib.h"
-#include <time.h>
-#include <getopt.h>
-#include <sys/stat.h>
-
-#include "linux_test_open.h"
-#include "yaffs_test_open.h"
-#include "linux_test_truncate.h"
-#include "yaffs_test_truncate.h"
-#include "linux_test_unlink.h"
-#include "yaffs_test_unlink.h"
-#include "linux_test_write.h"
-#include "yaffs_test_write.h"
-
-#define LINUX 1
-#define YAFFS 2
-
-
-
-
-
-void init(int argc, char *argv[]);
-int run_random_test(int num_of_random_tests);
-int compare_linux_and_yaffs(arg_temp *args_struct);
-
-int select_test_id(int test_len);
-void generate_random_numbers(arg_temp *args_struct);
-void run_yaffs_test(int id,arg_temp *args_struct);
-void run_linux_test(int id,arg_temp *args_struct);
-void clean_dir(void);
-int select_test_id(int test_len);
-int check_mode(arg_temp *args_struct);
-int check_mode_file(char *path);
-//void generate_array_of_objects_in_yaffs(void);
-//void generate_array_of_objects_in_linux(void);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "yaffs_test_open.h"
-
-int yaffs_test_open(arg_temp *args_struct)
-{
- char path[200];
- char message[100];
- int output=0;
- join_paths(yaffs_struct.root_path,args_struct->string1, path );
- sprintf(message,"file path: %s\n",path);
- print_message(3,message);
-
- output=yaffs_open(path,args_struct->char1 &(O_TRUNC|O_EXCL|O_CREAT|O_APPEND),args_struct->char2&(S_IREAD|S_IWRITE));
- if (output>=0){
- output= yaffs_close(output);
- if (output<0) {
- print_message(3,"failed to close handle\n");
- return -1;
- } else {
- return 1;
- }
- } else {
- print_message(3,"failed to open file\n");
- return -1;
- }
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __yaffs_test_open_h__
-#define __yaffs_test_open_h__
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "yaffsfs.h"
-#include "lib.h"
-
-int yaffs_test_open(arg_temp *args_struct);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "yaffs_test_truncate.h"
-
-int yaffs_test_truncate(arg_temp *args_struct)
-{
- char path[200];
- char message[200];
- int output=0;
- join_paths(yaffs_struct.root_path,args_struct->string1, path );
- sprintf(message,"file path: %s\n",path);
- print_message(3,message);
-
- output=yaffs_truncate(path,args_struct->int1);
- return output;
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __yaffs_test_truncate_h__
-#define __yaffs_test_truncate_h__
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "yaffsfs.h"
-#include "lib.h"
-
-int yaffs_test_truncate(arg_temp *args_struct);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "yaffs_test_unlink.h"
-
-int yaffs_test_unlink(arg_temp *args_struct)
-{
- char path[250];
- char message[150];
- int output;
- join_paths(yaffs_struct.root_path,args_struct->string1, path );
- sprintf(message,"file path: %s\n",path);
- print_message(3,message);
-
- output= yaffs_unlink(path);
-
- if (output<0) {
- print_message(3,"failed to unlink file\n");
- return -1;
- } else {
- return 1;
- }
-
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __yaffs_test_unlink_h__
-#define __yaffs_test_unlink_h__
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "yaffsfs.h"
-#include "lib.h"
-
-int yaffs_test_unlink(arg_temp *args_struct);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "yaffs_test_write.h"
-
-int yaffs_test_write(arg_temp *args_struct)
-{
- char path[200];
- char message[200];
- int output=0,output2=0;
- int handle;
- struct yaffs_stat yaffs_stat_struct;
- join_paths(yaffs_struct.root_path,args_struct->string1, path );
- sprintf(message,"trying to write to: %s\nwith mode set to %o \n",path,args_struct->char1);
- print_message(3,message);
- printf("mode S_IREAD %d S_IWRITE %d\n",(args_struct->char2 & S_IREAD),(args_struct->char2 & S_IWRITE));
- handle=yaffs_open(path,((args_struct->char1 &(O_TRUNC|O_EXCL|O_CREAT|O_APPEND))|O_RDWR),(args_struct->char2&(S_IREAD|S_IWRITE)));
- printf("handle %d\n",handle);
- if (handle<0){
- print_message(3,"failed to open a handle\n");
- return -1; //handle failed to open
- }
-
-/* output=yaffs_fstat(handle,&yaffs_stat_struct);
- if (output < 0){
- sprintf(message,"failed to stat the file\n");
- print_message(3,message);
- get_error_yaffs();
- } else {
- sprintf(message,"stated the file\n");
- print_message(3,message);
- sprintf(message," yaffs file mode is %d\n",(yaffs_stat_struct.st_mode & (S_IREAD| S_IWRITE)));
- print_message(3,message);
- sprintf(message,"mode S_IREAD %d S_IWRITE %d\n",(yaffs_stat_struct.st_mode & S_IREAD),(yaffs_stat_struct.st_mode & S_IWRITE));
- print_message(3,message);
- }
-
- sprintf(message,"trying to write: %d bytes into the file\n",strlen(args_struct->string2));
- print_message(3,message);
-*/
- output=yaffs_write(handle,&args_struct->string2,strlen(args_struct->string2));
-
-/* print_message(3,"\n wrote to the file\n");
- output2=yaffs_fstat(handle,&yaffs_stat_struct);
- if (output2 < 0){
- sprintf(message,"failed to stat the file\n");
- print_message(3,message);
- get_error_yaffs();
- } else {
- sprintf(message,"stated the file\n");
- print_message(3,message);
- sprintf(message," yaffs file mode is %d\n",(yaffs_stat_struct.st_mode & (S_IREAD| S_IWRITE)));
- print_message(3,message);
- sprintf(message,"mode S_IREAD %d S_IWRITE %d\n",(yaffs_stat_struct.st_mode & S_IREAD),(yaffs_stat_struct.st_mode & S_IWRITE));
- print_message(3,message);
- }
-*/ yaffs_close(handle);
-/* print_message(3,"\n closing the file\n");
- output2=yaffs_stat(path,&yaffs_stat_struct);
- if (output2 < 0){
- sprintf(message,"failed to stat the file\n");
- print_message(3,message);
- get_error_yaffs();
- } else {
- sprintf(message,"stated the file\n");
- print_message(3,message);
- sprintf(message," yaffs file mode is %d\n",(yaffs_stat_struct.st_mode & (S_IREAD| S_IWRITE)));
- print_message(3,message);
- sprintf(message,"mode S_IREAD %d S_IWRITE %d\n",(yaffs_stat_struct.st_mode & S_IREAD),(yaffs_stat_struct.st_mode & S_IWRITE));
- print_message(3,message);
- }
-*/
-
- return output;
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2018 Aleph One Ltd.
- *
- * Created by Timothy Manning <timothy@yaffs.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __yaffs_test_write_h__
-#define __yaffs_test_write_h__
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "yaffsfs.h"
-#include "lib.h"
-
-int yaffs_test_write(arg_temp *args_struct);
-
-#endif
--- /dev/null
+time_32_tests
--- /dev/null
+# Makefile for 64 bit time test.
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2002-2018 Aleph One Ltd.
+#
+#
+# Created by Timothy Manning <timothy@aleph1.co.uk>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+
+YDI_DIR = ../../../../
+YDI_FRAMEWORK_DIR = ../../../
+
+MAINFILES = time_32_tests create_32_bit validate_32_bit
+MAIN_OBJS = $(addsuffix .o,$(MAINFILES))
+
+EXTRA_OBJS = shared.o
+
+CLEAN_OBJS = $(MAINFILES)
+CFLAGS = -DCONFIG_YAFFS_USE_32_BIT_TIME_T
+
+YAFFS_TEST_OBJS = $(COMMONTESTOBJS) $(EXTRA_OBJS)
+ALL_UNSORTED_OBJS += $(YAFFS_TEST_OBJS) $(MAIN_OBJS)
+
+all: $(MAINFILES)
+
+include $(YDI_FRAMEWORK_DIR)/FrameworkRules.mk
+
+phony. test: time_32_tests
+ ./time_32_tests
+
+$(MAINFILES): $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS) $(MAIN_OBJS)
+ gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) $@.o -lpthread -DCONFIG_YAFFS_USE_32_BIT_TIME_T
+
--- /dev/null
+../shared/create_file.c
\ No newline at end of file
--- /dev/null
+../shared/shared.c
\ No newline at end of file
--- /dev/null
+../shared/shared.h
\ No newline at end of file
--- /dev/null
+#include "yaffsfs.h"
+#define YAFFS_MOUNT_POINT "/yflash2/"
+#define FILE_PATH "/yflash2/foo.txt"
+
+int random_seed;
+int simulate_power_failure = 0;
+
+
+int main()
+{
+ yaffs_start_up();
+
+ //test that ytime is 32 bits
+
+ if (sizeof(YTIME_T) != 4) {
+ printf("Error:size of YTIME_T is %lu, not 32 bits \n", sizeof(YTIME_T)*8);
+ return 1;
+ }
+
+
+ //create several times and save them
+ //
+
+ //extra tests
+ //save the time and get it to overflow.
+ printf("all tests pass\n");
+ return 0;
+}
--- /dev/null
+../shared/validate_file.c
\ No newline at end of file
--- /dev/null
+time_64_tests
--- /dev/null
+# Makefile for 64 bit time test.
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2002-2018 Aleph One Ltd.
+#
+#
+# Created by Timothy Manning <timothy@aleph1.co.uk>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+
+YDI_DIR = ../../../../
+YDI_FRAMEWORK_DIR = ../../../
+
+MAINFILES = time_64_tests create_64_bit validate_64_bit
+MAIN_OBJS = $(addsuffix .o,$(MAINFILES))
+
+EXTRA_OBJS = shared.o
+
+CLEAN_OBJS = $(MAINFILES)
+
+YAFFS_TEST_OBJS = $(COMMONTESTOBJS) $(EXTRA_OBJS)
+ALL_UNSORTED_OBJS += $(YAFFS_TEST_OBJS) $(MAIN_OBJS)
+
+all: $(MAINFILES)
+
+include $(YDI_FRAMEWORK_DIR)/FrameworkRules.mk
+
+phony. test: time_64_tests
+ ./time_64_tests
+
+$(MAINFILES): $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS) $(MAIN_OBJS)
+ gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) $@.o -lpthread
+
--- /dev/null
+../shared/create_file.c
\ No newline at end of file
--- /dev/null
+../shared/shared.c
\ No newline at end of file
--- /dev/null
+../shared/shared.h
\ No newline at end of file
--- /dev/null
+#include "yaffsfs.h"
+#include "yaffs_endian.h"
+
+#define YAFFS_MOUNT_POINT "/yflash2/"
+#define FILE_PATH "/yflash2/foo.txt"
+
+int random_seed;
+int simulate_power_failure = 0;
+
+
+int main()
+{
+ yaffs_start_up();
+
+ //test that ytime is 64 bits
+
+ if (sizeof(YTIME_T) != 8) {
+ printf("Error:size of YTIME_T is not 64 bits\n");
+ return 1;
+ }
+
+ struct yaffs_obj obj;
+ if (sizeof(obj.yst_atime) != 8) {
+ printf("Error: size of yaffs_obj.yst_atime is not 64 bits\n");
+ return 1;
+ }
+
+ //create several times and save them
+ //
+ struct yaffs_dev dev;
+
+ //need to set this to get the function to swap
+ //endianess of the values.
+
+ //remember that the first two bytes are swapped to the
+ //other end while still retaining their order.
+ // i.e. 0xfa..... becomes 0x...fa
+ dev.swap_endian = 1;
+
+ struct yaffs_obj_hdr oh;
+
+ oh.yst_atime = 0xaf1732b0;
+ oh.yst_mtime = 0xaf1732b0;
+ oh.yst_ctime = 0xaf1732b0;
+
+ yaffs_do_endian_oh(&dev,&oh);
+
+ //check that the endianess is correct
+ u32 expected = 0xb03217af;
+ if (oh.yst_atime != expected ) {
+ printf("endian test failed for yst_atime, got %x expected %x\n",oh.yst_atime,expected);
+ return 1;
+ }
+ if (oh.yst_mtime != expected) {
+ printf("endian test failed for yst_mtime, got %x, expected %x\n",oh.yst_mtime,expected);
+ return 1;
+ }
+ if (oh.yst_ctime != expected) {
+ printf("endian test failed for yst_ctime, got %x, expected %x\n",oh.yst_ctime,expected);
+ return 1;
+ }
+
+ printf("all tests pass\n");
+ return 0;
+}
--- /dev/null
+../shared/validate_file.c
\ No newline at end of file
--- /dev/null
+#include "shared.h"
+
+int random_seed;
+int simulate_power_failure = 0;
+
+int main(int argc, char *argv[] ){
+ int ret = shared_create(argc, argv);
+ ret = ret && shared_validate_file(argc, argv);
+ return ret;
+}
--- /dev/null
+#include <stdlib.h>
+#include "yaffsfs.h"
+#include "shared.h"
+
+void assert_exit_yaffs(char *fun_name, int fun_return_value){
+ if (fun_return_value < 0) {
+ printf("yaffs command: %s failed with error code %d \n", fun_name, fun_return_value);
+ int error_code = yaffsfs_GetLastError();
+ printf("error code is: %d, which is %s\n", error_code, yaffs_error_to_str(error_code));
+ printf("exiting program now\n");
+ exit(-1);
+ }
+}
+
+void setup_yaffs() {
+ yaffs_start_up();
+ yaffs_set_trace(0);
+ assert_exit_yaffs("yaffs_mount", yaffs_mount(YAFFS_MOUNT_POINT));
+}
+
+
+
+int shared_create(int argc, char *argv[]){
+ printf("YTIME_T size is %lu bits\n", sizeof(YTIME_T) *8);
+ #ifdef CONFIG_YAFFS_USE_32_BIT_TIME_T
+ if (sizeof(YTIME_T)*8 != 32) {
+ printf("YTIME_T size is incorrect. it is %lu and should be 32\n", sizeof(YTIME_T));
+ }
+ #endif
+ if (argc != 3) {
+ printf("wrong number of arguments\n");
+ printf("requires $ create file_name time\n");
+ return TEST_FAIL;
+ }
+
+ setup_yaffs();
+ char *file_path = argv[1];
+ int handle = yaffs_open(file_path, O_CREAT | O_RDWR, S_IREAD |S_IWRITE);
+ assert_exit_yaffs ( "yaffs_open", handle);
+
+ assert_exit_yaffs ( "yaffs_close", yaffs_close(handle));
+
+
+ //set the time.
+ uint time = atoi(argv[2]);
+
+ struct yaffs_utimbuf new_times;
+ new_times.actime = time;
+ int ret = yaffs_utime(file_path, &new_times);
+ assert_exit_yaffs("yaffs_utime", ret);
+
+ assert_exit_yaffs("yaffs_unmount", yaffs_unmount(YAFFS_MOUNT_POINT));
+ return 0;
+}
+
+int shared_validate_file(int argc, char *argv[]){
+
+ if (argc != 3) {
+ printf("wrong number of arguments\n");
+ printf("requires $ create file_name time\n");
+ return TEST_FAIL;
+ }
+
+ setup_yaffs();
+ char *file_path = argv[1];
+ int handle = yaffs_open(file_path, O_RDWR, S_IREAD |S_IWRITE);
+ assert_exit_yaffs ( "yaffs_open", handle);
+
+ //assert the file is the correct size and has the correct time.
+ uint expected_time = atoi(argv[2]);
+ struct yaffs_stat stat;
+ assert_exit_yaffs ( "yaffs_stat", yaffs_stat(file_path, &stat));
+ assert_exit_yaffs ( "yaffs_close", yaffs_close(handle));
+ if (stat.yst_atime != expected_time) {
+ printf("stat time is different from expected time\n");
+ exit(0);
+ }
+ assert_exit_yaffs("yaffs_unmount", yaffs_unmount(YAFFS_MOUNT_POINT));
+ return 0;
+}
--- /dev/null
+#ifndef __SHARED_H__
+#define __SHARED_H__
+
+#define TEST_PASS 0
+#define TEST_FAIL 1
+
+#define YAFFS_MOUNT_POINT "/yflash2/"
+#define FILE_PATH "/yflash2/foo.txt"
+
+void setup_yaffs();
+int shared_create();
+int shared_validate_file();
+#endif
--- /dev/null
+#include "shared.h"
+
+int random_seed;
+int simulate_power_failure = 0;
+
+int main(int argc, char *argv[] ){
+ return shared_validate_file(argc, argv);
+}
--- /dev/null
+make -C 32_bit/ && make -C 64_bit/ &&
+ rm emfile-* &&
+ ./32_bit/create_32_bit /yflash2/foo 100 &&
+ echo created 32 bit file &&
+ ./64_bit/validate_64_bit /yflash2/foo 100 &&
+ echo 32 bit file opened with 64 bit mode correctly
+
+ rm emfile-* &&
+ ./64_bit/create_64_bit /yflash2/foo 100 &&
+ echo created 64 bit file &&
+ ./32_bit/validate_32_bit /yflash2/foo 100 &&
+ echo 64 bit file opened with 32 bit mode correctly &&
+
+ echo All tests ran properly
--- /dev/null
+test_1_yaffs_mount
include $(YDI_FRAMEWORK_DIR)/FrameworkRules.mk
-
-yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
-
-
+phony. test: test_1_yaffs_mount
+ ./test_1_yaffs_mount
test_1_yaffs_mount: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS)
+ gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) -lpthread
#include "yaffsfs.h"
-#define YAFFS_MOUNT_POINT "/yaffs2/"
-#define FILE_PATH "/yaffs2/foo.txt"
+#define YAFFS_MOUNT_POINT "/yflash2/"
+#define FILE_PATH "/yflash2/foo.txt"
int random_seed;
int simulate_power_failure = 0;
output = yaffs_mount(YAFFS_MOUNT_POINT);
if (output>=0){
- printf("yaffs mounted: %s\n",YAFFS_MOUNT_POINT);
+ printf("yaffs correctly mounted: %s\n",YAFFS_MOUNT_POINT);
} else {
- printf("error\n yaffs failed to mount: %s\nerror\n",YAFFS_MOUNT_POINT);
- return (0);
+ printf("error\n yaffs failed to mount: %s\n with error code %d\n",YAFFS_MOUNT_POINT, yaffs_get_error());
+
+ return (-1);
}
//now create a file.
output = yaffs_open(FILE_PATH,O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
if (output>=0){
- printf("file created: %s\n",FILE_PATH);
+ printf("yaffs correctly created a the file: %s\n",FILE_PATH);
} else {
printf("error\n yaffs failed to create the file: %s\nerror\n",FILE_PATH);
- return (0);
+ return (-1);
}
output2 = yaffs_close(output);
if (output2>=0){
- printf("file closed: %s\n",FILE_PATH);
+ printf("yaffs correctly closed the file: %s\n",FILE_PATH);
} else {
printf("error\n yaffs failed to close the file: %s\nerror\n",FILE_PATH);
- return (0);
+ return (-1);
}
//unmount and remount the mount point.
output = yaffs_unmount(YAFFS_MOUNT_POINT);
if (output>=0){
- printf("yaffs unmounted: %s\n",YAFFS_MOUNT_POINT);
+ printf("yaffs correctly unmounted: %s\n",YAFFS_MOUNT_POINT);
} else {
printf("error\n yaffs failed to unmount: %s\nerror\n",YAFFS_MOUNT_POINT);
- return (0);
+ return (-1);
}
output = yaffs_mount(YAFFS_MOUNT_POINT);
if (output>=0){
- printf("yaffs mounted: %s\n",YAFFS_MOUNT_POINT);
+ printf("yaffs correctly mounted: %s\n",YAFFS_MOUNT_POINT);
} else {
printf("error\n yaffs failed to mount: %s\nerror\n",YAFFS_MOUNT_POINT);
- return (0);
+ return (-1);
}
//now open the existing file.
output = yaffs_open(FILE_PATH, O_RDWR, S_IREAD | S_IWRITE);
if (output>=0){
- printf("file created: %s\n",FILE_PATH);
+ printf("yaffs correctly opened the file: %s\n",FILE_PATH);
} else {
printf("error\n yaffs failed to create the file: %s\nerror\n",FILE_PATH);
- return (0);
+ return (-1);
}
//close the file.
output2 = yaffs_close(output);
if (output2>=0){
- printf("file closed: %s\n",FILE_PATH);
+ printf("yaffs correctly closed the file: %s\n",FILE_PATH);
} else {
printf("error\n yaffs failed to close the file: %s\nerror\n",FILE_PATH);
- return (0);
+ return (-1);
}
//unmount the mount point.
output = yaffs_unmount(YAFFS_MOUNT_POINT);
if (output>=0){
- printf("yaffs unmounted: %s\n",YAFFS_MOUNT_POINT);
+ printf("yaffs correctly unmounted: %s\n",YAFFS_MOUNT_POINT);
} else {
printf("error\n yaffs failed to unmount: %s\nerror\n",YAFFS_MOUNT_POINT);
- return (0);
+ return (-1);
}
printf("test passed. yay!\n");
+ return(0);
}
--- /dev/null
+quick_tests
test_yaffs_mount.o test_yaffs_mount_ENODEV.o test_yaffs_mount_ENAMETOOLONG.o test_yaffs_mount_EBUSY.o \
test_yaffs_mount_NULL.o \
test_yaffs_unmount.o test_yaffs_unmount_ENODEV.o test_yaffs_unmount_ENAMETOOLONG.o test_yaffs_unmount_EBUSY.o \
- test_yaffs_open.o test_yaffs_open_ENOENT.o test_yaffs_open_ENOTDIR.o test_yaffs_open_EEXIST.o test_yaffs_open_EISDIR.o \
+ test_yaffs_open.o test_yaffs_open_ENOENT.o test_yaffs_open_ENOTDIR.o test_yaffs_open_EEXIST.o \
test_yaffs_open_ENAMETOOLONG.o test_yaffs_open_EINVAL.o test_yaffs_open_EINVAL2.o test_yaffs_open_ELOOP.o \
test_yaffs_open_ELOOP_dir.o test_yaffs_open_EROFS.o test_yaffs_open_EACCES.o test_yaffs_open_NULL.o \
test_yaffs_unlink.o test_yaffs_unlink_EISDIR.o test_yaffs_unlink_ENOENT.o test_yaffs_unlink_ENAMETOOLONG.o \
include $(YDI_FRAMEWORK_DIR)/FrameworkRules.mk
-
-yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
- gcc $(CFLAGS) -o $@ $(YAFFS_TEST_OBJS) -lpthread
-
+phony. test: quick_tests
+ ./quick_tests
quick_tests: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
yaffs_DIR *d;
struct yaffs_dirent *de;
struct yaffs_stat s;
- char str[100];
+ char str[300];
d = yaffs_opendir(dir_name);
//printf("%s\n",dir_name);
if(!d)
run_random_test_loop();
}
/*this is where the loop should break to*/
- quit_quick_tests(0);
+ quit_quick_tests();
}
get_error();
print_message("\n\n",1);
if (get_exit_on_error()){
- quit_quick_tests(1);
+ quit_quick_tests();
}
}
output=0;
get_error();
printf("\n\n");
if (get_exit_on_error()){
- quit_quick_tests(1);
+ quit_quick_tests();
}
} else {
delete_dir(TEST_DIR);
}
-void quit_quick_tests(int exit_code)
+void quit_quick_tests()
{
/*char message[30];
message[0]='\0';
}
printf("out of %d tests, %d ran: %d passed and %d failed\n\n\n", total_number_of_tests,(num_of_tests_pass+num_of_tests_failed) ,num_of_tests_pass,num_of_tests_failed);
yaffs_unmount(YAFFS_MOUNT_POINT);
+
+ //remember that the exit_code needs to be 0 when all the tests pass.
+ int exit_code = num_of_tests_failed != 0;
exit(exit_code);
}
#include "test_yaffs_unmount_EBUSY.h"
#include "test_yaffs_open.h"
-#include "test_yaffs_open_EISDIR.h"
#include "test_yaffs_open_EEXIST.h"
#include "test_yaffs_open_ENOENT.h"
#include "test_yaffs_open_ENOTDIR.h"
{test_yaffs_unmount_EBUSY,test_yaffs_unmount_EBUSY_clean,"test_yaffs_unmount_EBUSY"},
{test_yaffs_open,test_yaffs_open_clean,"test_yaffs_open"},
- {test_yaffs_open_EISDIR,test_yaffs_open_EISDIR_clean,"test_yaffs_open_EISDIR"},
{test_yaffs_open_EEXIST,test_yaffs_open_EEXIST_clean,"test_yaffs_open_EEXIST"},
{test_yaffs_open_ENOTDIR,test_yaffs_open_ENOTDIR_clean,"test_yaffs_open_ENOTDIR"},
{test_yaffs_open_ENOENT,test_yaffs_open_ENOENT_clean,"test_yaffs_open_ENOENT"},
void logical_run_of_tests(void);
void init_quick_tests(int argc, char *argv[]);
-void quit_quick_tests(int exit_code);
+void quit_quick_tests();
void get_error(void);
void run_random_test_loop(void);
void run_test(int x);
--- /dev/null
+#!/usr/bin/env python3
+"""
+test_runner.py
+This file runs all of the yaffs unit tests and aggrates the outputs.
+
+To run this file you can use:
+
+$ python3 test_runner.py
+
+or
+
+$ ./test_runner.py
+
+To add a new test to this test runner, add the test dir path to the
+test_list below. Inside that folder there need to be a makefile with
+a "test" target that compiles and runs the test script. I.e. "make test"
+is called in every test directory.
+"""
+
+
+import subprocess, sys
+
+test_list = ["is_yaffs_working_tests",
+ "quick_tests",
+ "64_and_32_bit_time/64_bit",
+ "64_and_32_bit_time/32_bit",
+ ]
+
+
+TEST_FAILED = -1
+TEST_PASSED = 1
+
+def run(makefile_paths):
+ failed_tests =[]
+ for path in makefile_paths:
+ print("\nrunning test {}".format(path))
+ is_successful, test_output = run_makefile_test(path)
+ if is_successful != TEST_PASSED:
+ print('\033[41m' +'test {} failed'.format(path)+'\033[0m')
+ print(test_output)
+ failed_tests.append( (path, is_successful) )
+ else:
+ print('\033[42m' +"test passed"+'\033[0m')
+ return failed_tests
+
+def run_makefile_test(path):
+ try:
+ subprocess.check_output("make -j -C {} test".format(path), shell=True)
+ except subprocess.CalledProcessError as e:
+ return (TEST_FAILED, e.output.decode('UTF-8'))
+
+ return (TEST_PASSED, "test passed")
+
+def clean_tests(makefile_paths):
+ cmds = [("make -j -C {} clean".format(path), path) for path in makefile_paths]
+
+ failed = 0
+ passed = 0
+
+ for cmd, is_successful, cmd_text, debug_info in run_cmds(cmds):
+ if not is_successful:
+ print("\033[41mtest failed to clean\033[0m {}".format(debug_info[0]))
+ failed += 1
+ else :
+ print("\033[42mtest cleaned successfully\033[0m {}".format(debug_info[0]))
+ passed += 1
+ if not failed:
+ print ("\n\033[42mAll tests cleaned successfully\033[0m")
+ else :
+ print ("\n\033[42mTests failed to clean successfully\033[0m")
+ print("ran {}, passed {}, failed {}".format(len(cmds), passed, failed))
+
+def run_tests(makefile_paths):
+ cmds = [("make -j -C {} test".format(path), path) for path in makefile_paths]
+
+ failed = 0
+ passed = 0
+
+ print("running tests")
+ for cmd, is_successful, cmd_text, debug_info in run_cmds(cmds):
+ if not is_successful:
+ print("\033[41mtest failed\033[0m {}".format(debug_info[0]))
+ failed += 1
+ else :
+ print("\033[42mtest passed\033[0m {}".format(debug_info[0]))
+ passed += 1
+ if not failed:
+ print ("\n\033[42mAll tests passed\033[0m")
+ else :
+ print ("\n\033[41mTests failed\033[0m")
+ print("ran {}, passed {}, failed {}".format(len(cmds), passed, failed))
+
+def run_cmds(cmds):
+ output = []
+ for cmd, *debug_info in cmds:
+ try:
+ subprocess.check_output(cmd, shell=True)
+ output.append((cmd, True, "todo add getting text for non failing test", debug_info))
+ except subprocess.CalledProcessError as e:
+ output.append((cmd, False, e.output.decode('UTF-8'), debug_info))
+ return output
+if __name__ == "__main__":
+ if len(sys.argv) == 2 and sys.argv[1] == "clean":
+ clean_tests(test_list)
+ elif len(sys.argv) == 1:
+ #run the test runner.
+ failed_tests = run_tests(test_list)
+ else:
+ print("run with command ./test_runner.py [clean]")
--- /dev/null
+# Makefile for YAFFS direct test
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2002-2018 Aleph One Ltd.
+#
+#
+# Created by Charles Manning <charles@aleph1.co.uk>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+
+
+
+
+YDI_DIR = ../../
+YDI_FRAMEWORK_DIR = ../
+
+TARGETS = yaffs2_image_maker
+
+all: $(TARGETS)
+
+DIRECTTESTOBJS = $(COMMONTESTOBJS) yaffs2_image_maker.o
+
+ALL_UNSORTED_OBJS += $(DIRECTTESTOBJS)
+
+include ../FrameworkRules.mk
+
+
+yaffs2_image_maker: $(FRAMEWORK_SOURCES) $(DIRECTTESTOBJS)
+ gcc -o $@ $(DIRECTTESTOBJS) -lpthread
+
--- /dev/null
+How to use the image maker
+
+The purpose of this image maker is to create image files that can be burned into NAND.
+
+This image maker is set up to create image files for a flash that is:
+* 2k pages used ad "chunks"
+* 64 pages per block.
+* Inband tags
+
+If those are not the parameters that you require then it is easy enough to modify the tool.
+
+The image maker takes a sub-directory and copies all the files and directories over to a yaffs NAND simulation.
+The data from the NAND simulator simulates pages with 2k bytes of data area, then 64 bytes of spare.
+Since the spare is not used (because inband tags are used), the final step is to copy the data part of each page
+into the final image file.
+
+
+The resulting inmage file is a multiple of 2k bytes.
+
+To program this into a NAND flash:
+
+1. Erase the NAND flash.
+2. Put the flash device into ECC mode. The NAND will then write the ECC data into the spare area automatically.
+3. Starting at the first block to be used for Yaffs:
+ a. Check if the block is good. If it is bad skip over that block.
+ b. For 64 times (ie. each page in the block)
+ i. Read a 2k byte page of data from the image file.
+ ii. Write that 2k bytes into the page of flash.
+ iii. Verify if required.
+ iv. If the write fails, then mark the block as bad and rewrite the data in the next block.
+
+Note:
+ It is Ok if there are bad blocks. Yaffs is designed to handle bad blocks.
+
+
--- /dev/null
+/*
+ * An image maker that creates a file that creates a Yaffs2 image file
+ * can be programmed into NAND.
+ * This assumes that the device has the following properties:
+ * * 2k bytes per page
+ * * 64 pages per block
+ * * Yaffs is using inband tags.
+ *
+ * Note that this utility first generates a "working file" which is
+ * a simulation of the NAND. It then generates an output file which
+ * can be programmed into flash.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+
+#if 1
+#undef CONFIG_YAFFS_PROVIDE_DEFS
+#undef CONFIG_YAFFSFS_PROVIDE_VALUES
+#endif
+
+#include "yaffsfs.h"
+
+#include "yaffs_flexible_file_sim.h"
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yaffs_packedtags2.h"
+
+
+/*
+ * These are the sizes in the simulator file.
+ */
+
+#define MAX_BLOCKS 3000
+#define PAGES_PER_BLOCK_DEFAULT 64
+#define PAGE_DATA_SIZE_DEFAULT 2048
+#define PAGE_SPARE_SIZE 64
+#define FULL_PAGE_SIZE (chunk_size + PAGE_SPARE_SIZE)
+
+
+/* Some stub definitions to get building to work. */
+int simulate_power_failure = 0;
+int random_seed = 0;
+
+static char *input_dir;
+static char *output_file;
+static char *working_file;
+static char endian = 'l';
+static int no_tags_ecc = 0;
+static int inband_tags = 0;
+
+static int tags_size;
+static int record_size;
+static int total_written;
+static int chunk_size = PAGE_DATA_SIZE_DEFAULT;
+static int chunks_per_block = PAGES_PER_BLOCK_DEFAULT;
+
+static void usage(const char *prog_name)
+{
+ printf("Usage: %s options\n", prog_name);
+ printf("\t-i name input_directory\n");
+ printf("\t-o name output_file\n");
+ printf("\t-w name working_file\n");
+ printf("\t-b big endian output\n");
+ printf("\t-I store tags in flash data area (inband_tags)\n");
+ printf("\t-N do not apply ECC to tags in OOB area (no_tags_ecc)\n");
+ printf("\t-c val chunk size in bytes (default %d)\n", PAGE_DATA_SIZE_DEFAULT);
+ printf("\t-B val chunks per block(default %d)\n", PAGES_PER_BLOCK_DEFAULT);
+ exit(1);
+}
+
+static void parse_args(int argc, char *argv[])
+{
+ int c;
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, "bi:c:B:o:w:hIN")) != -1) {
+ switch (c) {
+ default:
+ case 'h': usage(argv[0]); break;
+ case 'i': input_dir = strdup(optarg); break;
+ case 'o': output_file = strdup(optarg); break;
+ case 'w': working_file = strdup(optarg); break;
+ case 'b': endian = 'b'; break;
+ case 'c': chunk_size = atoi(optarg); break;
+ case 'B': chunks_per_block = atoi(optarg); break;
+ case 'I': inband_tags = 1; break;
+ case 'N': no_tags_ecc = 1; break;
+ }
+ }
+}
+
+
+static int process_file(const char *from_path, const char *to_path, unsigned mode)
+{
+ int hin;
+ int hout;
+ unsigned char buffer[8000];
+ int nread;
+ int nwritten;
+ int nbytes = 0;
+ int ret;
+
+ hin = open(from_path, O_RDONLY);
+ if (hin < 0) {
+ perror ("opening input file");
+ return -1;
+ }
+ hout = yaffs_open(to_path, O_CREAT | O_TRUNC | O_RDWR, 0666);
+
+ if(hout < 0) {
+ printf("failed to create yaffs file %s\n", to_path);
+ return -1;
+ }
+
+ while ((nread = read(hin, buffer, sizeof(buffer))) > 0) {
+ nwritten = yaffs_write(hout, buffer, nread);
+
+ if (nwritten != nread) {
+ printf("Only wrote %d bytes out of %d\n", nwritten, nread);
+ return -1;
+ }
+ nbytes += nwritten;
+ }
+
+ ret = yaffs_fdatasync(hout);
+ if (ret < 0) {
+ printf("data sytnc failed\n");
+ return -1;
+ }
+
+ ret = yaffs_fchmod(hout, mode);
+ if (ret < 0) {
+ printf("chmod failed\n");
+ return -1;
+ }
+
+ ret = yaffs_close(hout);
+ if (ret < 0) {
+ printf("close failed\n");
+ return -1;
+ }
+
+ return nbytes;
+}
+
+static int process_directory(const char *from_dir, const char *to_dir)
+{
+ int error = 0;
+
+ DIR *dir;
+ struct dirent *entry;
+
+ printf("Processing directory %s into %s\n", from_dir, to_dir);
+
+ dir = opendir(from_dir);
+ if(!dir) {
+ printf("opendir failed on %s", from_dir);
+ return -1;
+ }
+
+ while((entry = readdir(dir)) != NULL && error >= 0) {
+ char from_path[500];
+ char to_path[500];
+ struct stat stats;
+ unsigned mode;
+ int ret;
+
+ //printf("Got entry %s\n", entry->d_name);
+
+ /* Ignore . and .. */
+ if(strcmp(entry->d_name, ".") == 0 ||
+ strcmp(entry->d_name, "..") == 0)
+ continue;
+
+ if (snprintf(from_path, sizeof(from_path),
+ "%s/%s", from_dir,entry->d_name) >= (int)sizeof(from_path)) {
+ printf("path too long for %s/%s\n", from_dir, entry->d_name);
+ error = -1;
+ continue;
+ }
+ if (snprintf(to_path, sizeof(to_path),
+ "%s/%s",to_dir,entry->d_name) >= (int)sizeof(to_path)) {
+ printf("path too long for %s/%s\n",to_dir,entry->d_name);
+ error = -1;
+ continue;
+ }
+
+ if (lstat(from_path,&stats) < 0)
+ {
+ perror("lstat");
+ error = -1;
+ continue;
+ }
+
+ mode = stats.st_mode & 0777;
+
+ if (S_ISDIR(stats.st_mode)) {
+ printf("Directory create %s, mode %03o\n", to_path, mode);
+ ret = yaffs_mkdir(to_path, mode);
+ printf("Directory create %s, mode %03o : result %d\n",
+ to_path, mode, ret);
+
+ if (ret < 0) {
+ printf("directory creation failed\n");
+ error = -1;
+ }
+ process_directory(from_path, to_path);
+ } else if (S_ISREG(stats.st_mode)) {
+ ret = process_file(from_path, to_path, mode);
+ printf("Copy file %s to %s, mode %03o : result %d\n",
+ from_path, to_path, mode, ret);
+ if (ret < 0) {
+ printf("file copy failed\n");
+ error = -1;
+ }
+
+ } else {
+ printf("Unhandled object type %d\n", stats.st_mode);
+ }
+ }
+
+ closedir(dir);
+
+ return 0;
+
+}
+
+int is_all_ff(unsigned char *buffer, int n)
+{
+ while (n > 0) {
+ if (*buffer != 0xff)
+ return 0;
+ buffer++;
+ n--;
+ }
+
+ return 1;
+}
+
+/*
+ * Write the data to output, skipping over the spare bytes.
+ * Stop writing when we get to blank flash.
+ */
+int generate_output_file(const char *working_file, const char *output_file)
+{
+ unsigned char *buffer;
+ int inh;
+ int outh;
+ int nread;
+ int nwritten;
+
+ buffer = malloc(FULL_PAGE_SIZE);
+
+ inh = open(working_file, O_RDONLY);
+ outh = open(output_file, O_CREAT | O_TRUNC | O_RDWR, 0666);
+
+ while ((nread = read(inh, buffer, FULL_PAGE_SIZE)) > 0) {
+ if (nread != FULL_PAGE_SIZE) {
+ printf("working file not properly sized\n");
+ return -1;
+ }
+
+ if(is_all_ff(buffer, chunk_size)) {
+ printf("End of data found\n");
+ break;
+ }
+
+ /* Write the data part. */
+ nwritten = write(outh, buffer, chunk_size);
+
+ if (nwritten != chunk_size) {
+ printf("short write\n");
+ return -1;
+ }
+
+ total_written += nwritten;
+
+ /* Now if there are OOB tags then write the OOB tags part too */
+ if (tags_size > 0) {
+ /* Read the oob bytes. In the simulator these are
+ * stored at offset 0 in the 64-byte spare area.
+ * We must therefore copy them from this location to
+ * the output file.
+ */
+ nwritten = write(outh, buffer + chunk_size, tags_size);
+
+ if (nwritten != tags_size) {
+ printf("short write\n");
+ return -1;
+ }
+
+ total_written += nwritten;
+ }
+ }
+
+ close(inh);
+ close(outh);
+
+ return total_written;
+}
+
+
+int main(int argc, char *argv[])
+{
+ struct yaffs_dev * dev;
+ int ret;
+
+ yaffs_trace_mask = 0;
+
+ parse_args(argc, argv);
+
+ if (!input_dir || !output_file || !working_file) {
+ printf("Need input directory , output file and working file\n");
+ exit(1);
+ }
+
+ printf("Generating image from %s into file %s using working file %s\n",
+ input_dir, output_file, working_file);
+ printf("Output file is in %s endian\n",
+ (endian == 'l') ? "little" : "big");
+
+ /*
+ * Determine oob tags_size.
+ */
+ if (inband_tags)
+ tags_size = 0;
+ else if (no_tags_ecc)
+ tags_size = sizeof(struct yaffs_packed_tags2_tags_only);
+ else
+ tags_size = sizeof(struct yaffs_packed_tags2);
+
+ record_size = chunk_size + tags_size;
+
+ printf("\n");
+ /*
+ * Create the Yaffs working file using the simulator.
+ */
+ unlink(working_file);
+
+ dev = yaffs_flexible_file_sim_create(
+ "yroot",
+ working_file,
+ MAX_BLOCKS,
+ 0, MAX_BLOCKS - 1,
+ chunks_per_block,
+ chunk_size,
+ PAGE_SPARE_SIZE);
+
+ if (!dev) {
+ printf("Failed to create yaffs working file\n");
+ exit(1);
+ }
+
+ /*
+ * Disable checkpointing to create an image without checkpoint data.
+ */
+ dev->param.skip_checkpt_rd = 1;
+ dev->param.skip_checkpt_wr = 1;
+
+ /*
+ * Set up stored endian: 1 = little endian, 2 = big endian.
+ * Set no_tags_ecc
+ */
+ dev->param.stored_endian = (endian == 'l') ? 1 : 2;
+ dev->param.no_tags_ecc = no_tags_ecc;
+
+ dev->param.inband_tags = inband_tags;
+
+ ret = yaffs_mount("yroot");
+
+ printf("yaffs_mount returned %d\n", ret);
+
+ if (ret < 0) {
+ printf("Mounting yaffs simulator failed - cannot continue\n");
+ exit(1);
+ }
+
+ process_directory(input_dir, "yroot");
+
+ yaffs_unmount("yroot");
+
+
+ printf("Generating output file: %s\n", output_file);
+
+ ret = generate_output_file(working_file, output_file);
+
+ printf("Done\n\n");
+ printf("Wrote %d bytes (%d pages of %d bytes each) to output file.\n",
+ total_written, total_written/record_size, record_size);
+ printf("This images has %d bytes per chunk, %d chunks per block.\n",
+ chunk_size, chunks_per_block);
+ if (inband_tags) {
+ printf("The image has inband tags.\n");
+ printf("This means it is structured a records of %d bytes per page\n", record_size);
+ printf("This should be written to the data portion of the page\n");
+ } else {
+ printf("The image has out of band tags with%s ECC on the tags\n",
+ no_tags_ecc ? " NO" : "");
+ printf("This means it has %d tags bytes per record to be written in the oob area\n", tags_size);
+ printf("Each record is %d bytes.\n"
+ "The first %d bytes are data for the data datea and\n"
+ "the last %d bytes are tags for the oob (spare) area\n",
+ record_size, chunk_size, tags_size);
+ }
+ if (ret < 0)
+ exit(1);
+
+ return 0;
+}
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2018 Aleph One Ltd.
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * NAND Simulator for testing YAFFS
+ */
+
+
+#include "yaffs_flexible_file_sim.h"
+
+#include "yaffs_guts.h"
+#include <string.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+
+struct sim_data {
+ char *file_name;
+ int handle;
+ uint32_t n_blocks;
+ uint32_t chunks_per_block;
+ uint32_t chunk_size;
+ uint32_t spare_size;
+ uint32_t total_chunk_size;
+ uint32_t total_bytes_per_block;
+ char *buffer;
+};
+
+static struct sim_data *dev_to_sim(struct yaffs_dev *dev)
+{
+ return (struct sim_data *)(dev->driver_context);
+}
+
+
+static int yflex_erase_internal(struct sim_data *sim, uint32_t block_id)
+{
+ int pos;
+
+ pos = sim->total_bytes_per_block * block_id;
+ memset(sim->buffer, 0xff, sim->total_bytes_per_block);
+
+ lseek(sim->handle, pos, SEEK_SET);
+ write(sim->handle, sim->buffer, sim->total_bytes_per_block);
+
+ return YAFFS_OK;
+}
+
+#if 0
+static int yflex_read_internal(struct sim_data *sim,
+ uint32_t page_id,
+ uint8_t *buffer)
+{
+ int page_pos = page_id * sim->total_chunk_size;
+
+ lseek(sim->handle, page_pos, SEEK_SET);
+ read(sim->handle, buffer, sim->total_chunk_size);
+
+ return YAFFS_OK;
+}
+
+#endif
+
+
+static int yflex_initialise(struct yaffs_dev *dev)
+{
+ (void) dev;
+
+ return YAFFS_OK;
+}
+
+
+static int yflex_deinitialise(struct yaffs_dev *dev)
+{
+ (void) dev;
+ return YAFFS_OK;
+}
+
+static int yflex_rd_chunk (struct yaffs_dev *dev, int page_id,
+ u8 *data, int data_length,
+ u8 *spare, int spare_length,
+ enum yaffs_ecc_result *ecc_result)
+{
+ struct sim_data *sim = dev_to_sim(dev);
+ uint32_t page_start;
+
+ page_start = page_id * sim->total_chunk_size;
+
+ if(data) {
+ lseek(sim->handle, page_start, SEEK_SET);
+ read(sim->handle, data,data_length);
+ }
+
+ if(spare) {
+ lseek(sim->handle, page_start + sim->chunk_size, SEEK_SET);
+ read(sim->handle, spare,spare_length);
+ }
+
+ if (ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+ return YAFFS_OK;
+}
+
+static int yflex_wr_chunk (struct yaffs_dev *dev, int page_id,
+ const u8 *data, int data_length,
+ const u8 *spare, int spare_length)
+{
+ struct sim_data *sim = dev_to_sim(dev);
+ uint32_t page_start;
+
+ page_start = page_id * sim->total_chunk_size;
+
+ if(data) {
+ lseek(sim->handle, page_start, SEEK_SET);
+ write(sim->handle, data,data_length);
+ }
+
+ if(spare) {
+ lseek(sim->handle, page_start + sim->chunk_size, SEEK_SET);
+ write(sim->handle, spare, spare_length);
+ }
+
+ return YAFFS_OK;
+}
+
+
+static int yflex_erase(struct yaffs_dev *dev, int block_id)
+{
+ struct sim_data *sim = dev_to_sim(dev);
+
+ return yflex_erase_internal(sim, block_id);
+}
+
+static int yflex_check_block_bad(struct yaffs_dev *dev, int block_id)
+{
+ (void) dev;
+ (void) block_id;
+
+ return YAFFS_OK;
+}
+
+static int yflex_mark_block_bad(struct yaffs_dev *dev, int block_id)
+{
+ (void) dev;
+ (void) block_id;
+
+ return YAFFS_OK;
+}
+
+static int yflex_sim_init(struct sim_data *sim)
+{
+ int h;
+ uint32_t fsize = 0;
+ uint32_t i;
+
+ sim->total_chunk_size = sim->chunk_size + sim->spare_size;
+ sim->total_bytes_per_block = sim->total_chunk_size * sim->chunks_per_block;
+
+ sim->buffer = malloc(sim->total_bytes_per_block);
+
+ h = open(sim->file_name, O_RDWR);
+ if (h >= 0) {
+ fsize = lseek(h, 0, SEEK_END);
+ lseek(h, 0, SEEK_SET);
+ }
+
+ if (fsize != sim->total_bytes_per_block * sim->n_blocks) {
+ /* Need to create the file. */
+ close(h);
+ unlink(sim->file_name);
+ h = open(sim->file_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ sim->handle = h;
+
+ for (i = 0; i < sim->n_blocks; i++)
+ yflex_erase_internal(sim, i);
+ } else {
+ sim->handle = h;
+ }
+
+ return YAFFS_OK;
+}
+
+
+struct yaffs_dev *yaffs_flexible_file_sim_create(
+ const char *name,
+ const char *sim_file_name,
+ uint32_t n_blocks,
+ uint32_t start_block, uint32_t end_block,
+ uint32_t chunks_per_block,
+ uint32_t bytes_per_chunk,
+ uint32_t bytes_per_spare)
+{
+ struct sim_data *sim;
+ struct yaffs_dev *dev;
+ struct yaffs_param *p;
+ struct yaffs_driver *d;
+
+ sim = malloc(sizeof(*sim));
+ dev = malloc(sizeof(*dev));
+
+ if(!sim || !dev){
+ free(sim);
+ free(dev);
+ return NULL;
+ }
+ memset(sim, 0, sizeof(*sim));
+ memset(dev, 0, sizeof(*dev));
+
+ /* Set up sim */
+ sim->file_name = strdup(sim_file_name);
+ sim->chunks_per_block = chunks_per_block;
+ sim->chunk_size = bytes_per_chunk;
+ sim->spare_size = bytes_per_spare;
+ sim->n_blocks = n_blocks;
+
+ dev->driver_context= (void *)sim;
+
+ yflex_sim_init(sim);
+
+
+
+ if(start_block >= sim->n_blocks)
+ start_block = 0;
+ if(end_block == 0 || end_block >= sim->n_blocks)
+ end_block = sim->n_blocks - 1;
+
+ p = &dev->param;
+ p->name = strdup(name);
+ p->start_block = start_block;
+ p->end_block = end_block;
+ p->total_bytes_per_chunk = bytes_per_chunk;
+ p->spare_bytes_per_chunk = bytes_per_spare;
+ p->chunks_per_block = chunks_per_block;
+ p->n_reserved_blocks = 2;
+ p->use_nand_ecc = 1;
+ p->inband_tags = 0;
+ p->is_yaffs2 = 1;
+ p->n_caches = 10;
+
+ d= &dev->drv;
+ d->drv_initialise_fn = yflex_initialise;
+ d->drv_deinitialise_fn = yflex_deinitialise;
+ d->drv_read_chunk_fn = yflex_rd_chunk;
+ d->drv_write_chunk_fn = yflex_wr_chunk;
+ d->drv_erase_fn = yflex_erase;
+ d->drv_check_bad_fn = yflex_check_block_bad;
+ d->drv_mark_bad_fn = yflex_mark_block_bad;
+
+ yaffs_add_device(dev);
+
+ return dev;
+}
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2018 Aleph One Ltd.
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Flexible simple file based NAND Simulator for testing YAFFS
+ */
+
+
+#ifndef __YAFFS_FLEXZIBLE_FILE_SIM_H__
+#define __YAFFS_FLEXZIBLE_FILE_SIM_H__
+
+#include <stdint.h>
+
+struct yaffs_dev;
+
+struct yaffs_dev *yaffs_flexible_file_sim_create(
+ const char *name,
+ const char *sim_file_name,
+ uint32_t n_blocks,
+ uint32_t start_block, uint32_t end_block,
+ uint32_t chunks_per_block,
+ uint32_t bytes_per_chunk,
+ uint32_t bytes_per_spare) ;
+#endif
struct nanddrv_transfer tr[2];
int i;
- if(!data || !oob)
+ if(!data)
return YAFFS_FAIL;
for(i = 0, e = buffer + 2; i < chip->data_bytes_per_page; i+=256, e+=3)
yaffs_ecc_calc(data + i, e);
- memcpy(buffer + 26, oob, oob_len);
+ if (oob)
+ memcpy(buffer + 26, oob, oob_len);
/* Set up and execute transfer */
struct yaffs_dev *yaffs_nandsim_install_drv(const char *dev_name,
const char *backing_file_name,
- int n_blocks)
+ int n_blocks,
+ int n_caches,
+ int inband_tags)
{
struct yaffs_dev *dev;
char *name_copy = NULL;
param->end_block = n_blocks - 1; // Last block
param->is_yaffs2 = 1;
param->use_nand_ecc = 1;
- param->n_caches = 10;
+ param->n_caches = n_caches;
param->stored_endian = 2;
+ param->inband_tags = inband_tags;
if(yaffs_nand_install_drv(dev, chip) != YAFFS_OK)
goto fail;
struct yaffs_dev *yaffs_nandsim_install_drv(const char *dev_name,
const char *backing_file_name,
- int n_blocks);
+ int n_blocks,
+ int n_caches,
+ int inband_tags);
#endif
while ((dev = yaffs_next_dev()) != NULL) {
result = yaffs_do_background_gc_reldev(dev, urgent);
- if (result > 0)
+
+ /* result is 1 if more than half the free space is
+ * erased.
+ * If less than half the free space is erased then it is
+ * worth doing another background_gc operation sooner.
+ */
+ if (result == 0)
next_urgent = 1;
}
* Functions to allocate and free memory.
*/
+
+static unsigned malloc_high_water;
+static unsigned malloc_currently_allocated;
+
+#ifdef CONFIG_YAFFS_MONITOR_MALLOC
+
+#include <malloc.h>
+static void yaffsfs_malloc_add(void *ptr)
+{
+ unsigned this_size = malloc_usable_size(ptr);
+ malloc_currently_allocated += this_size;
+
+ if (malloc_currently_allocated > malloc_high_water)
+ malloc_high_water = malloc_currently_allocated;
+}
+
+static void yaffsfs_malloc_remove(void *ptr)
+{
+ unsigned this_size = malloc_usable_size(ptr);
+ malloc_currently_allocated -= this_size;
+}
+#else
+static void yaffsfs_malloc_add(void *ptr)
+{
+ (void)ptr;
+}
+
+static void yaffsfs_malloc_remove(void *ptr)
+{
+ (void)ptr;
+}
+#endif
+
+void yaffsfs_get_malloc_values(unsigned *current, unsigned *high_water)
+{
+ if (current)
+ *current = malloc_currently_allocated;
+ if(high_water)
+ *high_water = malloc_high_water;
+}
+
+
#ifdef CONFIG_YAFFS_TEST_MALLOC
static int yaffs_kill_alloc = 0;
this = malloc(size);
if(this)
total_malloced += size;
+ yaffsfs_malloc_add(this);
return this;
}
void *yaffsfs_malloc(size_t size)
{
- return malloc(size);
+ void *this = malloc(size);
+ yaffsfs_malloc_add(this);
+ return this;
}
#endif
+
+
+
void yaffsfs_free(void *ptr)
{
+ yaffsfs_malloc_remove(ptr);
free(ptr);
}
}
kfree(ned.block);
+ (void) sizeInMB;
+
yaffs_trace(YAFFS_TRACE_ALWAYS,
"Allocation failed, could only allocate %dMB of %dMB requested.\n",
- nAllocated/64,sizeInMB);
+ nAllocated/64, sizeInMB);
return 0;
}
yflash2_install_drv("yflash2");
yaffs_m18_install_drv("M18-1");
yaffs_nor_install_drv("nor");
- yaffs_nandsim_install_drv("nand", "emfile-nand", 256);
+ yaffs_nandsim_install_drv("nand", "emfile-nand", 256, 4, 1);
+ yaffs_nandsim_install_drv("nand128MB", "emfile-nand128MB", 1024, 4, 1);
return 0;
}
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
{
+
#ifdef CONFIG_YAFFS_WINCE
obj->win_atime[0] = oh->win_atime[0];
obj->win_ctime[0] = oh->win_ctime[0];
#else
obj->yst_uid = oh->yst_uid;
obj->yst_gid = oh->yst_gid;
- obj->yst_atime = oh->yst_atime;
- obj->yst_mtime = oh->yst_mtime;
- obj->yst_ctime = oh->yst_ctime;
+
+ obj->yst_ctime = yaffs_oh_ctime_fetch(oh);
+ obj->yst_mtime = yaffs_oh_mtime_fetch(oh);
+ obj->yst_atime = yaffs_oh_atime_fetch(oh);
+
obj->yst_rdev = oh->yst_rdev;
#endif
}
#else
oh->yst_uid = obj->yst_uid;
oh->yst_gid = obj->yst_gid;
- oh->yst_atime = obj->yst_atime;
- oh->yst_mtime = obj->yst_mtime;
- oh->yst_ctime = obj->yst_ctime;
+
+ yaffs_oh_ctime_load(obj, oh);
+ yaffs_oh_mtime_load(obj, oh);
+ yaffs_oh_atime_load(obj, oh);
+
oh->yst_rdev = obj->yst_rdev;
#endif
}
obj->yst_mtime = Y_CURRENT_TIME;
if (do_a)
- obj->yst_atime = obj->yst_atime;
+ obj->yst_atime = obj->yst_mtime;
if (do_c)
- obj->yst_ctime = obj->yst_atime;
+ obj->yst_ctime = obj->yst_mtime;
#endif
}
void *yaffsfs_malloc(size_t size);
void yaffsfs_free(void *ptr);
+void yaffsfs_get_malloc_values(unsigned *current, unsigned *high_water);
+
+
int yaffsfs_CheckMemRegion(const void *addr, size_t size, int write_request);
void yaffsfs_OSInitialisation(void);
#include "yportenv.h"
+#ifdef CONFIG_YAFFS_SMALL_RAM
+#define YAFFSFS_N_HANDLES 10
+#define YAFFSFS_N_DSC 2
+#else
#define YAFFSFS_N_HANDLES 100
-
#define YAFFSFS_N_DSC 20
+#endif
struct yaffsfs_DeviceConfiguration {
}
#if !CONFIG_YAFFS_WINCE
+ // if the the buffer is null then create one with the fields set to the current time.
if (!buf) {
local.actime = Y_CURRENT_TIME;
local.modtime = local.actime;
buf = &local;
}
+ // copy the buffer's time into the obj.
if (obj) {
int result;
obj->yst_atime = buf->actime;
obj->yst_mtime = buf->modtime;
+
+ // set the obj to dirty to cause it to be written to flash during the next flush operation.
obj->dirty = 1;
result = yaffs_flush_file(obj, 0, 0, 0);
retVal = result == YAFFS_OK ? 0 : -1;
int force, int read_only)
{
int retVal = -1;
+ int was_read_only;
if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
if (force || !yaffsfs_IsDevBusy(dev)) {
if (read_only)
yaffs_checkpoint_save(dev);
+ was_read_only = dev->read_only;
dev->read_only = read_only ? 1 : 0;
+ if (was_read_only && !read_only) {
+ yaffs_guts_cleanup(dev);
+ }
retVal = 0;
} else
yaffsfs_SetError(-EBUSY);
{
int retVal = -1;
- if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
- yaffsfs_SetError(-EFAULT);
- return -1;
- }
- if (yaffsfs_CheckPath(path) < 0) {
- yaffsfs_SetError(-ENAMETOOLONG);
- return -1;
+ if (!dev) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
+ yaffsfs_SetError(-EFAULT);
+ return -1;
+ }
+
+ if (yaffsfs_CheckPath(path) < 0) {
+ yaffsfs_SetError(-ENAMETOOLONG);
+ return -1;
+ }
}
yaffsfs_Lock();
unsigned long yst_wince_mtime[2];
unsigned long yst_wince_ctime[2];
#else
- unsigned long yst_atime; /* time of last access */
- unsigned long yst_mtime; /* time of last modification */
- unsigned long yst_ctime; /* time of last change */
+ YTIME_T yst_atime; /* time of last access */
+ YTIME_T yst_mtime; /* time of last modification */
+ YTIME_T yst_ctime; /* time of last change */
#endif
};
struct yaffs_utimbuf {
- unsigned long actime;
- unsigned long modtime;
+ YTIME_T actime;
+ YTIME_T modtime;
};
/* Normal POSIX-style API functions */
#define BUG() do { yaffs_bug_fn(__FILE__, __LINE__); } while (0)
+#ifdef CONFIG_YAFFS_USE_32_BIT_TIME_T
+ #define YTIME_T u32
+#else
+ #define YTIME_T u64
+#endif
#define YCHAR char
#define YUCHAR unsigned char
#define cond_resched() do {} while (0)
+#ifdef CONFIG_YAFFS_NO_TRACE
+#define yaffs_trace(...) do { } while (0)
+#else
#define yaffs_trace(msk, fmt, ...) do { \
if (yaffs_trace_mask & (msk)) \
printf("yaffs: " fmt "\n", ##__VA_ARGS__); \
} while (0)
+#endif
#define YAFFS_LOSTNFOUND_NAME "lost+found"
#define YAFFS_LOSTNFOUND_PREFIX "obj"
#define __YPORTENV_H__
+#ifdef __rtems__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define CONFIG_YAFFS_DIRECT 1
+#define CONFIG_YAFFS_SHORT_NAMES_IN_RAM 1
+#define CONFIG_YAFFS_YAFFS2 1
+#define CONFIG_YAFFS_PROVIDE_DEFS 1
+#define CONFIG_YAFFSFS_PROVIDE_VALUES 1
+#define CONFIG_YAFFS_DEFINES_TYPES 1
+#define CONFIG_YAFFS_USE_32_BIT_TIME_T 1
+#define NO_Y_INLINE 1
+#define loff_t off_t
+
+#endif /* __rtems__ */
+
/* Definition of types */
#ifdef CONFIG_YAFFS_DEFINES_TYPES
typedef unsigned char u8;
typedef signed int s32;
#endif
-
#ifdef CONFIG_YAFFS_PROVIDE_DEFS
/* File types */
--- /dev/null
+#
+# This file was originally written to work from the yaffs2 base directory
+# which required deleting some of the Linux files.
+#
+# This is now modified to run from the yaffs2/rtems directory and copies in
+# all files as symbolic links.
+#
+
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+include $(RTEMS_MAKEFILE_PATH)/make/target.cfg
+
+INSTALL_BASE = $(RTEMS_MAKEFILE_PATH)/lib
+
+BUILDDIR = build-$(RTEMS_BSP)
+
+CPPFLAGS += -I.
+
+DEPFLAGS = -MT $@ -MD -MP -MF $(basename $@).d
+
+GCCFLAGS = -g -I . -B $(INSTALL_BASE) -specs bsp_specs -qrtems
+
+CFLAGS += $(DEPFLAGS) $(GCCFLAGS)
+
+# Files to be made into local symlinks
+YCORE_SYMLINKS = \
+ yaffs_ecc.c \
+ yaffs_cache.c \
+ yaffs_endian.c \
+ yaffs_guts.c \
+ yaffs_packedtags1.c \
+ yaffs_tagscompat.c \
+ yaffs_packedtags2.c \
+ yaffs_nand.c \
+ yaffs_checkptrw.c \
+ yaffs_nameval.c \
+ yaffs_allocator.c \
+ yaffs_bitmap.c \
+ yaffs_yaffs1.c \
+ yaffs_yaffs2.c \
+ yaffs_verify.c \
+ yaffs_summary.c \
+ yaffs_tagsmarshall.c\
+ yaffs_cache.h \
+ yaffs_ecc.h \
+ yaffs_guts.h \
+ yaffs_packedtags1.h \
+ yaffs_tagscompat.h \
+ yaffs_packedtags2.h \
+ yaffs_nand.h \
+ yaffs_checkptrw.h \
+ yaffs_nameval.h \
+ yaffs_attribs.h \
+ yaffs_allocator.h \
+ yaffs_bitmap.h \
+ yaffs_yaffs1.h \
+ yaffs_yaffs2.h \
+ yaffs_verify.h \
+ yaffs_summary.h \
+ yaffs_trace.h \
+ yaffs_endian.h \
+ yaffs_getblockinfo.h \
+ yaffs_tagsmarshall.h
+
+
+DIRECT_SYMLINKS = \
+ yaffs_attribs.c \
+ yaffs_hweight.c \
+ yaffs_hweight.h \
+ yportenv.h \
+ ydirectenv.h \
+ yaffscfg.h \
+ yaffs_osglue.h \
+ yaffs_list.h \
+ yaffsfs.h
+
+DIRECT_QSORT_SYMLINKS = \
+ qsort.c
+
+ALL_SYMLINKS = $(YCORE_SYMLINKS) $(DIRECT_SYMLINKS) $(DIRECT_QSORT_SYMLINKS)
+
+
+INCLUDES = rtems_yaffs.h \
+ yportenv.h \
+ ydirectenv.h \
+ yaffs_osglue.h \
+ yaffs_hweight.h \
+ yaffscfg.h \
+ yaffs_list.h \
+ yaffsfs.h \
+ yaffs_guts.h \
+ yaffs_packedtags2.h \
+ yaffs_ecc.h
+
+LIB = $(BUILDDIR)/libyaffs2.a
+LIB_PIECES = yaffs_ecc \
+ yaffs_endian \
+ yaffs_guts \
+ yaffs_cache \
+ yaffs_packedtags1 \
+ yaffs_tagscompat \
+ yaffs_tagsmarshall\
+ yaffs_packedtags2 \
+ yaffs_nand \
+ yaffs_checkptrw \
+ qsort \
+ yaffs_nameval \
+ yaffs_attribs \
+ yaffs_allocator \
+ yaffs_bitmap \
+ yaffs_yaffs1 \
+ yaffs_yaffs2 \
+ yaffs_verify \
+ yaffs_summary \
+ yaffs_hweight \
+ rtems_yaffs \
+ rtems_yaffs_os_context \
+ rtems_yaffs_os_glue
+LIB_OBJS = $(LIB_PIECES:%=$(BUILDDIR)/%.o)
+LIB_DEPS = $(LIB_PIECES:%=$(BUILDDIR)/%.d)
+
+all: $(BUILDDIR) $(ALL_SYMLINKS) $(LIB)
+
+symlinks:$(ALL_SYMLINKS)
+
+$(YCORE_SYMLINKS):
+ ln -s ../$@ $@
+
+$(DIRECT_SYMLINKS):
+ ln -s ../direct/$@ $@
+
+$(DIRECT_QSORT_SYMLINKS):
+ ln -s ../direct/optional_sort/$@ $@
+
+$(BUILDDIR):
+ mkdir $(BUILDDIR)
+
+$(LIB): $(LIB_OBJS)
+ $(AR) rcu $@ $^
+ $(RANLIB) $@
+
+$(BUILDDIR)/%.o: %.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+clean:
+ rm -rf $(BUILDDIR) $(ALL_SYMLINKS)
+
+install: all
+ mkdir -p $(INSTALL_BASE)/include/yaffs
+ install -m 644 $(LIB) $(INSTALL_BASE)
+ install -m 644 $(INCLUDES) $(INSTALL_BASE)/include/yaffs
+
+.PHONY: clean install
+
+-include $(LIB_DEPS)
--- /dev/null
+
+
+Building with Makeifle
+
+Assuming the BSP is the sparc erc32 BSP in:
+/home/charles/quick-start/rtems/5/sparc-rtems5/erc32/
+
+
+
+Set up environment variuables
+
+export RTEMS_MAKEFILE_PATH=/home/charles/quick-start/rtems/5/sparc-rtems5/erc32/
+export PATH=/home/charles/quick-start/rtems/5/bin/:$PATH
+
+Now we can build and install the Yaffs library:
+
+$cd /opt/y/git/yaffs2/rtems
+
+$make -f Makefile.rtems clean
+$make -f Makefile.rtems all
+ output is build-erc32/libyaffs2.a
+$make -f Makefile.rtems install
+ mkdir -p /home/charles/quick-start/rtems/5/sparc-rtems5/erc32/lib/include/yaffs
+ install -m 644 build-erc32/libyaffs2.a /home/charles/quick-start/rtems/5/sparc-rtems5/erc32/lib
+ install -m 644 rtems_yaffs.h yportenv.h ydirectenv.h yaffs_osglue.h yaffs_hweight.h yaffscfg.h yaffs_list.h yaffsfs.h yaffs_guts.h yaffs_packedtags2.h yaffs_ecc.h /home/charles/quick-start/rtems/5/sparc-rtems5/erc32/lib/include/yaffs
+
+
+Building test application
+
+
+$ cd rtems-y-test/basic-test
+$ make
+
+$ sparc-rtems5-sis o-optimize/yaffs-rtems-test.exe
+
+ SIS - SPARC/RISCV instruction simulator 2.20, copyright Jiri Gaisler 2019
+ Bug-reports to jiri@gaisler.se
+
+ ERC32 emulation enabled
+
+ Loaded o-optimize/yaffs-rtems-test.exe, entry 0x02000000
+sis> go
+resuming at 0x02000000
+Starting
+Created simulated flash device 0x2d203c8
+yaffs: 0 blocks to be sorted...
+....
+
+
+Running with GDB
+
+Open a second terminal to run sis in gdb mode
+
+$ sparc-rtems5-sis -gdb
+
+ SIS - SPARC/RISCV instruction simulator 2.20, copyright Jiri Gaisler 2019
+ Bug-reports to jiri@gaisler.se
+
+ ERC32 emulation enabled
+
+gdb: listening on port 1234 connected
+X2000000,0:#40
+
+
+*** HELLO WORLD TEST ***
+Hello World 123
+*** END OF HELLO WORLD TEST ***
+
+*** FATAL ***
+fatal source: 5 (RTEMS_FATAL_SOURCE_EXIT)
+fatal code: 0 (0x00000000)
+RTEMS version: 5.0.0.e22554535796fc29a7ed7c5e2338128e324a621d-modified
+RTEMS tools: 7.5.0 20191114 (RTEMS 5, RSB 5 (599c4d7c87fa), Newlib d14714c69)
+executing thread ID: 0x08a010001
+executing thread name: UI1
+
+
+
+
+
+
+From other window use gdb
+
+
+
+$ sparc-rtems5-gdb hello.exe
+GNU gdb (GDB) 8.3
+Copyright (C) 2019 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+Type "show copying" and "show warranty" for details.
+This GDB was configured as "--host=x86_64-linux-gnu --target=sparc-rtems5".
+Type "show configuration" for configuration details.
+For bug reporting instructions, please see:
+<http://www.gnu.org/software/gdb/bugs/>.
+Find the GDB manual and other documentation resources online at:
+ <http://www.gnu.org/software/gdb/documentation/>.
+
+For help, type "help".
+Type "apropos word" to search for commands related to "word"...
+Reading symbols from hello.exe...
+(gdb) target remote :1234
+:1234: Connection timed out.
+(gdb) target remote :1234
+Remote debugging using :1234
+0x00000000 in ?? ()
+(gdb) load
+Loading section .text, size 0x12880 lma 0x2000000
+Loading section .rtemsroset, size 0x40 lma 0x2012880
+Loading section .data, size 0x530 lma 0x20138c0
+Start address 0x2000000, load size 77296
+Transfer rate: 2434 KB/sec, 270 bytes/write.
+(gdb) c
+Continuing.
+
+Program received signal SIGTERM, Terminated.
+syscall () at /home/charles/quick-start/src/rtems/c/src/../../cpukit/score/cpu/sparc/syscall.S:44
+44 ta 0 ! syscall 1, halt with %g1,%g2,%g3 info
+(gdb)
+
--- /dev/null
+#
+# Makefile for yaffs-rtems-test.exe
+#
+
+#
+# RTEMS_MAKEFILE_PATH is typically set in an environment variable
+#
+
+EXEC=yaffs-rtems-test.exe
+PGM=${ARCH}/$(EXEC)
+
+# optional managers required
+MANAGERS=all
+
+# C source names
+CSRCS = yaffs-rtems-basic-test.c
+CSRCS += yaffs-rtems-test-wrapper.c yaffs-rtems-flashsim.c
+COBJS_ = $(CSRCS:.c=.o)
+COBJS = $(COBJS_:%=${ARCH}/%)
+
+# C++ source names
+CXXSRCS =
+CXXOBJS_ = $(CXXSRCS:.cc=.o)
+CXXOBJS = $(CXXOBJS_:%=${ARCH}/%)
+
+# AS source names
+ASSRCS =
+ASOBJS_ = $(ASSRCS:.s=.o)
+ASOBJS = $(ASOBJS_:%=${ARCH}/%)
+
+# Libraries
+#LIBS = -lrtemsall -lc -lyaffs2
+LINK_LIBS = -lyaffs2
+
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)
+
+all: ${ARCH} $(PGM)
+
+#Create symlinks
+yaffs-rtems-test-wrapper.c: ../common/yaffs-rtems-test-wrapper.c
+ ln -sf $^ $@
+
+yaffs-rtems-flashsim.c: ../common/yaffs-rtems-flashsim.c
+ ln -sf $^ $@
+
+yaffs-rtems-flashsim.h: ../common/yaffs-rtems-flashsim.h
+ ln -sf $^ $@
+
+$(OBJS): yaffs-rtems-flashsim.h
+
+$(PGM): $(OBJS)
+ $(make-exe)
+
--- /dev/null
+The basic tests test common fs operations such as open, close, read, write etc.
+
+Multiple files and directories are opened, created, read, deleted, truncated etc.
+
--- /dev/null
+/*
+ * Simple test program -- demonstrating use of IMFS
+ */
+
+#include <bsp.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <dirent.h>
+
+#include <rtems/libio.h>
+#include <yaffs/rtems_yaffs.h>
+
+void set_uint8_t_buffer(uint8_t *buf, uint32_t n, uint8_t start, uint8_t inc)
+{
+ while (n) {
+ *buf = start;
+ buf++;
+ start += inc;
+ n--;
+ }
+}
+
+void make_test_file_name(char *out, int out_size, char *root_path, char *dir, char *file, int index)
+{
+ if (index >= 0)
+ snprintf(out, out_size, "%s/%s/%s-%d",
+ root_path, dir, file, index);
+ else
+ snprintf(out, out_size, "%s/%s/%s",
+ root_path, dir, file);
+}
+
+void make_test_dir_name(char *out, int out_size, char *root_path, char *dir)
+{
+ snprintf(out, out_size, "%s/%s", root_path, dir);
+}
+
+void dump_directory_tree_worker(const char *dname,int recursive)
+{
+ DIR *d;
+ struct dirent *de;
+ struct stat s;
+ char str[1000];
+
+ d = opendir(dname);
+
+ if(!d) {
+ printf("opendir failed\n");
+ } else {
+ while((de = readdir(d)) != NULL) {
+ sprintf(str,"%s/%s",dname,de->d_name);
+
+ lstat(str,&s);
+
+ printf("%s inode %d length %d mode 0%o ",
+ str, (int)s.st_ino, (int)s.st_size, s.st_mode);
+ switch(s.st_mode & S_IFMT) {
+ case S_IFREG: printf("data file"); break;
+ case S_IFDIR: printf("directory"); break;
+ case S_IFLNK: printf("symlink -->");
+ if(readlink(str,str,100) < 0)
+ printf("no alias");
+ else
+ printf("\"%s\"",str);
+ break;
+ default: printf("unknown mode"); break;
+ }
+
+ printf("\n");
+
+ if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
+ dump_directory_tree_worker(str,1);
+ }
+ closedir(d);
+ }
+}
+
+static void dump_directory_tree(const char *dname)
+{
+ printf("Directory tree of %s\n", dname);
+ dump_directory_tree_worker(dname,1);
+}
+
+
+void recursively_delete(char *objname)
+{
+ struct stat s;
+ DIR *d;
+ struct dirent *de;
+ char str[500];
+
+
+ //printf("deleting %s\n", objname);
+ lstat(objname, &s);
+
+ switch(s.st_mode & S_IFMT) {
+ case S_IFREG:
+ printf("delete data file %s returns %d\n",
+ objname, unlink(objname));
+ break;
+ case S_IFLNK:
+ printf("delete symlink %s returns %d\n",
+ objname, unlink(objname));
+ break;
+ case S_IFDIR:
+ d = opendir(objname);
+ if(!d) {
+ printf("opendir failed\n");
+ } else {
+ while((de = readdir(d)) != NULL) {
+ snprintf(str, sizeof(str), "%s/%s",
+ objname, de->d_name);
+ recursively_delete(str);
+ }
+ closedir(d);
+ }
+ printf("delete directory %s returns %d\n",
+ objname, rmdir(objname));
+ break;
+ }
+}
+
+
+
+void dumpDir(const char *dname)
+{
+ dump_directory_tree_worker(dname,0);
+}
+
+int basic_file_test(char *root_path, char *test_path)
+{
+ char fname[100];
+ char dname[100];
+ int fd;
+ int ret;
+ uint8_t buf[100];
+ uint8_t buf2[100];
+
+ make_test_dir_name(dname, sizeof(dname), root_path, test_path);
+ make_test_file_name(fname, sizeof(fname), root_path, test_path, "file", -1);
+
+ ret = mkdir(dname, 0777);
+
+ if (ret < 0) {
+ perror("mkdir");
+ return ret;
+ }
+
+ fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0777);
+ printf("open %s = %d\n", fname, fd);
+ if (fd < 0) {
+ perror("opening test file");
+ return fd;
+ }
+
+ set_uint8_t_buffer(buf, sizeof(buf), 0xAA, 1);
+
+ ret = write(fd, buf, sizeof(buf));
+
+ printf("write returned %d\n", ret);
+
+ if (ret < 0) {
+ perror("writing file");
+ return ret;
+ }
+
+ ret = fdatasync(fd);
+
+ if (ret < 0) {
+ perror("fdatasync problem");
+ return ret;
+ }
+
+ ret = lseek(fd, 0, SEEK_END);
+
+ printf("lseek end ret = %d\n", ret);
+
+ ret = lseek(fd, 0, SEEK_SET);
+ printf("lseek start ret = %d\n", ret);
+
+ ret = read(fd, buf2, sizeof(buf2));
+
+ printf("reading file ret = %d\n", ret);
+
+ if (ret < 0) {
+ perror("reading file");
+ return ret;
+ }
+
+ dump_directory_tree(root_path);
+
+ if (memcmp(buf, buf2, sizeof(buf)) == 0) {
+ printf("buffers match\n");
+ return 0;
+ } else {
+ printf("buffers do not match\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+
+int create_delete_files_pass(char *root_path, char *test_path, int n_files, int del_when_done)
+{
+ char fname[100];
+ char lname[100];
+ char dname[100];
+ int *fds = NULL;
+ int ret;
+ int i;
+ uint8_t buf[100];
+ uint8_t buf2[100];
+
+ fds = malloc(n_files * sizeof (int));
+
+ if (!fds) {
+ printf("Failed to malloc\n");
+ ret = -1;
+ goto err;
+ }
+
+ make_test_dir_name(dname, sizeof(dname), root_path, test_path);
+
+ recursively_delete(dname);
+
+ ret = access(dname, F_OK);
+ printf("access of non-existing expects -1 returned %d\n", ret);
+
+ if (ret != -1) {
+ printf("access should have been -1, was %d\n", ret);
+ ret = -1;
+ goto err;
+ }
+
+ ret = mkdir(dname, 0777);
+
+ if (ret < 0) {
+ perror("mkdir");
+ goto err;
+ }
+
+ ret = access(dname, F_OK);
+ printf("access of existing returned %d\n", ret);
+
+ if (ret < 0) {
+ perror("access of existing directory");
+ goto err;
+ }
+
+ for (i = 0; i < n_files; i++) {
+ int link_fd;
+
+ make_test_file_name(fname, sizeof(fname), root_path, test_path, "file-", i);
+ make_test_file_name(lname, sizeof(lname), root_path, test_path, "link-", i);
+
+ ret = symlink(fname, lname);
+
+ if (ret < 0) {
+ perror("creating symlink");
+ goto err;
+ }
+
+ fds[i] = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0777);
+ printf("open %s = %d\n", fname, fds[i]);
+
+ if (fds[i] < 0) {
+ perror("opening test file");
+ ret = fds[i];
+ goto err;
+ }
+
+
+ link_fd = open(lname, O_RDWR, 0777);
+ printf("opening link %s = %d\n", lname, link_fd);
+
+ if (link_fd < 0) {
+ perror("opening symlink file");
+ ret = link_fd;
+ goto err;
+ }
+ close(link_fd);
+
+ }
+
+ set_uint8_t_buffer(buf, sizeof(buf), 0xAA, 1);
+
+ for(i = 0; i < n_files; i++) {
+ ret = write(fds[i], buf, sizeof(buf));
+ printf("write returned %d\n", ret);
+ if (ret < 0) {
+ perror("writing file");
+ goto err;
+ }
+ }
+
+ for(i = 0; i < n_files; i++) {
+ int trunc_size = sizeof(buf2)/2;
+
+ ret = lseek(fds[i], 0, SEEK_END);
+
+ printf("lseek end ret = %d\n", ret);
+
+ ret = lseek(fds[i], 0, SEEK_SET);
+ printf("lseek start ret = %d\n", ret);
+
+ ret = read(fds[i], buf2, sizeof(buf2));
+
+ printf("reading file ret = %d\n", ret);
+ if (ret < 0) {
+ perror("reading file");
+ goto err;
+ }
+ ret = ftruncate(fds[i], trunc_size);
+
+ if (ret < 0) {
+ perror("ftruncate");
+ goto err;
+ }
+
+ ret = lseek(fds[i], 0, SEEK_END);
+ if (ret != trunc_size) {
+ printf("truncated size is %d but lseek returned %d\n",
+ trunc_size, ret);
+ ret = -1;
+ goto err;
+ }
+
+
+ }
+
+ for(i = 0; i < n_files; i++) {
+ ret = close(fds[i]);
+ if (ret < 0) {
+ perror("closing file");
+ goto err;
+ }
+ }
+
+ dump_directory_tree(root_path);
+
+ if (memcmp(buf, buf2, sizeof(buf)) == 0) {
+ printf("buffers match\n");
+ ret = 0;
+ } else {
+ printf("buffers do not match\n");
+ ret = -1;
+ }
+
+ if (del_when_done)
+ recursively_delete(dname);
+err:
+ free(fds);
+
+ return ret;
+}
+
+int create_delete_files(char *root_path, char *test_path, int n_files, int n_passes)
+{
+ int i;
+ int ret;
+ for (i = 0; i < n_passes; i++) {
+ printf("\nCreate and Delete Files Pass %d\n", i);
+ ret = create_delete_files_pass(root_path, test_path, n_files, 1);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
+#define YPATH "/yaffs_mount_pt"
+#define FNAME YPATH"/test"
+#define DIRNAME YPATH"/dirtest"
+
+void check_fail(int ret)
+{
+ if (ret < 0)
+ printf("Test failed\n");
+}
+
+void run_the_test(void)
+{
+ check_fail(basic_file_test(YPATH, "basic-test-dir"));
+ check_fail(create_delete_files(YPATH, "create-del-test-dir", 15, 50));
+
+ printf("\n\n\nAll Yaffs Tests passed Ok\n\n\n");
+}
--- /dev/null
+/*
+ * Modified verion of yramsim.c.
+ */
+#include "yaffs-rtems-flashsim.h"
+
+#include <string.h>
+#include "../../yaffs_guts.h"
+
+
+
+#define N_RAM_SIM_DEVS 1
+
+#define DATA_SIZE 2048
+#define SPARE_SIZE 64
+#define PAGE_SIZE (DATA_SIZE + SPARE_SIZE)
+#define PAGES_PER_BLOCK 64
+
+
+#if 0
+#define dout printf
+#else
+#define dout(...) do { } while(0)
+#endif
+
+
+
+uint32_t stats_reads;
+uint32_t stats_writes;
+uint32_t stats_erases;
+
+typedef struct {
+ unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
+ unsigned blockOk;
+} Block;
+
+typedef struct {
+ Block **blockList;
+ int nBlocks;
+} SimData;
+
+
+SimData *simDevs[N_RAM_SIM_DEVS];
+
+static SimData *DevToSim(struct yaffs_dev *dev)
+{
+ return (SimData*)(dev->driver_context);
+}
+
+
+static void CheckInitialised(void)
+{
+
+}
+
+static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
+{
+ if(blockId < 0 || blockId >= sim->nBlocks){
+ return 0;
+ }
+
+ if(!sim->blockList[blockId]){
+ return 0;
+ }
+
+ if(!force && !sim->blockList[blockId]->blockOk){
+ return 0;
+ }
+
+ memset(sim->blockList[blockId],0xff,sizeof(Block));
+ sim->blockList[blockId]->blockOk = 1;
+
+ return 1;
+}
+
+
+
+
+static int yramsim_initialise(struct yaffs_dev *dev)
+{
+ SimData *sim = DevToSim(dev);
+ Block **blockList = sim->blockList;
+ return blockList != NULL;
+}
+
+
+static int yramsim_deinitialise(struct yaffs_dev *dev)
+{
+ return 1;
+}
+
+static int yramsim_rd_chunk (struct yaffs_dev *dev, int pageId,
+ u8 *data, int dataLength,
+ u8 *spare, int spareLength,
+ enum yaffs_ecc_result *ecc_result)
+{
+ SimData *sim = DevToSim(dev);
+ Block **blockList = sim->blockList;
+
+ unsigned blockId = pageId / PAGES_PER_BLOCK;
+ unsigned pageOffset = pageId % PAGES_PER_BLOCK;
+ unsigned char * d;
+ unsigned char *s;
+
+ stats_reads++;
+
+ if(blockId >= sim->nBlocks ||
+ pageOffset >= PAGES_PER_BLOCK ||
+ dataLength >DATA_SIZE ||
+ spareLength > SPARE_SIZE ||
+ !blockList[blockId]->blockOk){
+ return YAFFS_FAIL;
+ }
+
+ d = blockList[blockId]->page[pageOffset];
+ s = d + DATA_SIZE;
+
+ if(data)
+ memcpy(data,d,dataLength);
+
+ if(spare)
+ memcpy(spare,s,spareLength);
+
+ if (ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+ return YAFFS_OK;
+}
+
+static int yramsim_wr_chunk (struct yaffs_dev *dev, int pageId,
+ const u8 *data, int dataLength,
+ const u8 *spare, int spareLength)
+{
+ SimData *sim = DevToSim(dev);
+ Block **blockList = sim->blockList;
+
+ unsigned blockId = pageId / PAGES_PER_BLOCK;
+ unsigned pageOffset = pageId % PAGES_PER_BLOCK;
+ unsigned char * d;
+ unsigned char *s;
+
+ dout("wr_chunk\n");
+
+ stats_writes++;
+
+ if(blockId >= sim->nBlocks ||
+ pageOffset >= PAGES_PER_BLOCK ||
+ dataLength >DATA_SIZE ||
+ spareLength > SPARE_SIZE ||
+ !blockList[blockId]->blockOk){
+ return YAFFS_FAIL;
+ }
+
+ d = blockList[blockId]->page[pageOffset];
+ s = d + DATA_SIZE;
+
+ if(data)
+ memcpy(d,data,dataLength);
+
+ if(spare)
+ memcpy(s,spare,spareLength);
+
+ return YAFFS_OK;
+}
+
+
+static int yramsim_erase(struct yaffs_dev *dev, int blockId)
+{
+ SimData *sim = DevToSim(dev);
+
+ stats_erases++;
+
+ CheckInitialised();
+ return yramsim_erase_internal(sim,blockId,0);
+}
+
+static int yramsim_check_block_bad(struct yaffs_dev *dev, int blockId)
+{
+ SimData *sim = DevToSim(dev);
+ Block **blockList = sim->blockList;
+ if(blockId >= sim->nBlocks){
+ return YAFFS_FAIL;
+ }
+
+ return blockList[blockId]->blockOk ? YAFFS_OK : YAFFS_FAIL;
+}
+
+static int yramsim_mark_block_bad(struct yaffs_dev *dev, int blockId)
+{
+ SimData *sim = DevToSim(dev);
+ Block **blockList = sim->blockList;
+ if(blockId >= sim->nBlocks){
+ return YAFFS_FAIL;
+ }
+
+ blockList[blockId]->blockOk = 0;
+
+ return YAFFS_OK;
+}
+
+
+static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks)
+{
+ int ok = 1;
+
+ Block **blockList;
+ SimData *sim;
+ Block *b;
+ u32 i;
+
+ if(devId >= N_RAM_SIM_DEVS)
+ return NULL;
+
+ sim = simDevs[devId];
+
+ if(sim)
+ return sim;
+
+ sim = malloc(sizeof (SimData));
+ if(!sim)
+ return NULL;
+
+ simDevs[devId] = sim;
+
+ blockList = malloc(nBlocks * sizeof(Block *));
+
+ sim->blockList = blockList;
+ sim->nBlocks = nBlocks;
+ if(!blockList){
+ free(sim);
+ return NULL;
+ }
+
+ for(i = 0; i < nBlocks; i++)
+ blockList[i] = NULL;
+
+ for(i = 0; i < nBlocks && ok; i++){
+ b= malloc(sizeof(Block));
+ if(b){
+ blockList[i] = b;
+ yramsim_erase_internal(sim,i,1);
+ }
+ else
+ ok = 0;
+ }
+
+ if(!ok){
+ for(i = 0; i < nBlocks; i++)
+ if(blockList[i]){
+ free(blockList[i]);
+ blockList[i] = NULL;
+ }
+ free(blockList);
+ blockList = NULL;
+ free(sim);
+ sim = NULL;
+ }
+
+ return sim;
+}
+
+
+struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
+ u32 devId, u32 nBlocks,
+ u32 start_block, u32 end_block)
+{
+ SimData *sim;
+ struct yaffs_dev *dev;
+ struct yaffs_param *p;
+ struct yaffs_driver *d;
+
+ sim = yramsim_alloc_sim_data(devId, nBlocks);
+
+ dev = malloc(sizeof(*dev));
+
+ if(!sim || !dev){
+ free(sim);
+ free(dev);
+ printf("Flash Sim creation failed. sim = %p, dev = %p\n",
+ sim, dev);
+ return NULL;
+ }
+
+ memset(dev, 0, sizeof(*dev));
+
+ if(start_block >= sim->nBlocks)
+ start_block = 0;
+ if(end_block == 0 || end_block >= sim->nBlocks)
+ end_block = sim->nBlocks - 1;
+
+ p = &dev->param;
+ p->name = strdup(name);
+ p->start_block = start_block;
+ p->end_block = end_block;
+ p->total_bytes_per_chunk = DATA_SIZE;
+ p->spare_bytes_per_chunk= SPARE_SIZE;
+ p->chunks_per_block = PAGES_PER_BLOCK;
+ p->n_reserved_blocks = 2;
+ p->use_nand_ecc = 1;
+ p->inband_tags = 0;
+ p->is_yaffs2 = 1;
+
+ d= &dev->drv;
+ d->drv_initialise_fn = yramsim_initialise;
+ d->drv_deinitialise_fn = yramsim_deinitialise;
+ d->drv_read_chunk_fn = yramsim_rd_chunk;
+ d->drv_write_chunk_fn = yramsim_wr_chunk;
+ d->drv_erase_fn = yramsim_erase;
+ d->drv_check_bad_fn = yramsim_check_block_bad;
+ d->drv_mark_bad_fn = yramsim_mark_block_bad;
+
+ dev->driver_context= (void *)sim;
+
+ printf("Created simulated flash device %p\n", dev);
+ return dev;
+}
+
+struct yaffs_dev *yaffs_rtems_flashsim_setup(void)
+{
+ return yramsim_CreateRamSim("ramsim",
+ 0, 100,
+ 0, 99);
+}
+
+
+void yaffs_rtems_flashsim_dump_status(void)
+{
+ printf("\nFlashsim stats\n");
+ printf("reads.....%d\n", stats_reads);
+ printf("writes....%d\n", stats_writes);
+ printf("erases....%d\n", stats_erases);
+}
--- /dev/null
+#ifndef __YAFFS_FLASH_SIM_H__
+#define __YAFFS_FLASH_SIM_H__
+
+struct yaffs_dev;
+
+struct yaffs_dev *yaffs_rtems_flashsim_setup(void);
+
+void yaffs_rtems_flashsim_dump_status(void);
+
+#endif
+
--- /dev/null
+/*
+ * Simple test program -- demonstrating use of IMFS
+ */
+
+#include <bsp.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rtems/libio.h>
+#include <yaffs/rtems_yaffs.h>
+
+#include "yaffs-rtems-flashsim.h"
+
+#define YPATH "/yaffs_mount_pt"
+//#define YPATH ""
+
+void yaffs_bug_fn(const char *file_name, int line_no)
+{
+ printf("Yaffs bug at %s:%d\n", file_name, line_no);
+}
+
+int filesystem_init(const char *mount_target)
+{
+ struct yaffs_dev *device;
+ rtems_yaffs_default_os_context *os_context;
+ rtems_yaffs_mount_data mount_args;
+
+
+ rtems_filesystem_register(RTEMS_FILESYSTEM_TYPE_YAFFS,
+ rtems_yaffs_mount_handler);
+
+ // We mount the filesystem by passing an appropriate
+ // rtems_yaffs_mount_data as the last argument to mount(). mount_data is
+ // used to pass a yaffs_dev pointer by-value.
+
+
+ device = yaffs_rtems_flashsim_setup();
+
+ // Initialize callback storage for RTEMS's VFS inside the yaffs_dev.
+ os_context = malloc(sizeof(rtems_yaffs_default_os_context));
+ rtems_yaffs_initialize_default_os_context(os_context);
+
+ device->os_context = os_context;
+
+ mount_args.dev = device;
+
+ if (mount_and_make_target_path(NULL,
+ mount_target,
+ RTEMS_FILESYSTEM_TYPE_YAFFS,
+ RTEMS_FILESYSTEM_READ_WRITE,
+ &mount_args) < 0) {
+ perror("mount_and_make");
+ return errno;
+ } else {
+ chmod(mount_target, 0777); /* Make partition rw/modifiable */
+ return 0;
+ }
+}
+
+extern int run_the_test(void);
+
+rtems_task Init(
+ rtems_task_argument ignored
+)
+{
+ int err;
+
+ printf("Starting\n");
+
+ err = filesystem_init(YPATH);
+
+ printf("filesystem_init(\"%s\") returned %d\n", YPATH, err);
+
+ run_the_test();
+
+ yaffs_rtems_flashsim_dump_status();
+
+ exit(0);
+}
+
+
+
+
+#if 0
+So basically, we are registering our NAND-specific callbacks with YAFFS
+and registering the RTEMS-YAFFS filesystem callbacks with RTEMS.
+The rtems_filesystem_register() associates the mount() system call with
+a callback function to handle that system call, in this case
+rtems_yaffs_mount_handler(). rtems_yaffs_mount_handler() and
+RTEMS_FILESYSTEM_TYPE_YAFFS (just a string) are provided
+by the rtems-yaffs fork.
+
+mount_and_make_target_path() is provided by RTEMS: it combines a
+mkdir -p` with mount(), passing the mount_args to the
+previously-registered handler.
+#endif
+
+
+/* configuration information */
+
+/* NOTICE: the clock driver is explicitly disabled */
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 32
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 20
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
+/* end of file */
--- /dev/null
+#
+# Makefile for rtems-fsx.exe
+#
+
+#
+# RTEMS_MAKEFILE_PATH is typically set in an environment variable
+#
+
+EXEC=rtems-fsx.exe
+PGM=${ARCH}/$(EXEC)
+
+# optional managers required
+MANAGERS=all
+
+# C source names
+CSRCS = rtems-fsx.c
+CSRCS += yaffs-rtems-test-wrapper.c yaffs-rtems-flashsim.c
+COBJS_ = $(CSRCS:.c=.o)
+COBJS = $(COBJS_:%=${ARCH}/%)
+
+# C++ source names
+CXXSRCS =
+CXXOBJS_ = $(CXXSRCS:.cc=.o)
+CXXOBJS = $(CXXOBJS_:%=${ARCH}/%)
+
+# AS source names
+ASSRCS =
+ASOBJS_ = $(ASSRCS:.s=.o)
+ASOBJS = $(ASOBJS_:%=${ARCH}/%)
+
+# Libraries
+#LIBS = -lrtemsall -lc -lyaffs2
+LINK_LIBS = -lyaffs2
+
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)
+
+all: ${ARCH} $(PGM)
+
+#Create symlinks
+yaffs-rtems-test-wrapper.c: ../common/yaffs-rtems-test-wrapper.c
+ ln -sf $^ $@
+
+yaffs-rtems-flashsim.c: ../common/yaffs-rtems-flashsim.c
+ ln -sf $^ $@
+
+yaffs-rtems-flashsim.h: ../common/yaffs-rtems-flashsim.h
+ ln -sf $^ $@
+
+$(OBJS): yaffs-rtems-flashsim.h
+
+$(PGM): $(OBJS)
+ $(make-exe)
+
--- /dev/null
+FSX is a file system exerciser originally written at Apple for
+stress testing file system operations, particularly those related to
+seeking, truncating etc.
+
+A good output looks like:
+
+Starting
+Created simulated flash device 0x2d24348
+yaffs: 0 blocks to be sorted...
+filesystem_init("/yaffs_mount_pt") returned 0
+mkdir returned 0
+fsx_init done
+truncating to largest ever: 0x1cbf7
+truncating to largest ever: 0x27453
+truncating to largest ever: 0x2d9bd
+truncating to largest ever: 0x36c22
+truncating to largest ever: 0x3e9f5
+truncating to largest ever: 0x3eff0
+truncating to largest ever: 0x3fd22
+truncating to largest ever: 0x3fe0b
+truncating to largest ever: 0x3fe29
+truncating to largest ever: 0x3ff4b
+All operations completed A-OK!
+fsx wanted to exit with 0
+
+Flashsim stats
+reads.....44373
+writes....46000
+erases....644
+
+
+
+To run for longer or shorter periods modify this line:
+ return fsx_main(FSX_TEST_DIR, 10000);
+
+
+This program has been run overnight (using a very large value) and no
+problems were observed.
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.2 (the
+ * "License"). You may not use this file except in compliance with the
+ * License. Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ *
+ * WARNING--WARNING--WARNING
+ * This is not the original fsx.c. It has been modified to run with
+ * yaffs direct. Seek out the original fsx.c if you want to do anything
+ * else.
+ *
+ *
+ *
+ * File: fsx.c
+ * Author: Avadis Tevanian, Jr.
+ *
+ * File system exerciser.
+ *
+ * Rewrite and enhancements 1998-2001 Conrad Minshall -- conrad@mac.com
+ *
+ * Various features from Joe Sokol, Pat Dirks, and Clark Warner.
+ *
+ * Small changes to work under Linux -- davej@suse.de
+ *
+ * Sundry porting patches from Guy Harris 12/2001
+ *
+ * Checks for mmap last-page zero fill.
+ *
+ * Modified heavily by Charles Manning to exercise via the
+ * yaffs direct interface.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef _UWIN
+# include <sys/param.h>
+# include <limits.h>
+# include <time.h>
+# include <strings.h>
+#endif
+#include <fcntl.h>
+#include <sys/mman.h>
+#ifndef MAP_FILE
+# define MAP_FILE 0
+#endif
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <time.h>
+
+
+#define NUMPRINTCOLUMNS 32 /* # columns of data to print on each line */
+
+/*
+ * A log entry is an operation and a bunch of arguments.
+ */
+
+struct log_entry {
+ int operation;
+ int args[3];
+};
+
+#define LOGSIZE 1000
+
+struct log_entry oplog[LOGSIZE]; /* the log */
+int logptr = 0; /* current position in log */
+int logcount = 0; /* total ops */
+
+/*
+ * Define operations
+ */
+
+#define OP_READ 1
+#define OP_WRITE 2
+#define OP_TRUNCATE 3
+#define OP_CLOSEOPEN 4
+#define OP_MAPREAD 5
+#define OP_MAPWRITE 6
+#define OP_SKIPPED 7
+
+int page_size;
+int page_mask;
+
+char *original_buf; /* a pointer to the original data */
+char *good_buf; /* a pointer to the correct data */
+char *temp_buf; /* a pointer to the current data */
+
+char fname[200]; /* name of our test file */
+char mount_name[200];
+
+int fd; /* fd for our test file */
+
+off_t file_size = 0;
+off_t biggest = 0;
+char state[256];
+unsigned long testcalls = 0; /* calls to function "test" */
+
+unsigned long simulatedopcount = 0; /* -b flag */
+unsigned closeprob = 0; /* -c flag */
+int debug = 0; /* -d flag */
+unsigned long debugstart = 0; /* -D flag */
+unsigned long maxfilelen = 256 * 1024; /* -l flag */
+int sizechecks = 1; /* -n flag disables them */
+int maxoplen = 64 * 1024; /* -o flag */
+int quiet = 0; /* -q flag */
+unsigned long progressinterval = 0; /* -p flag */
+int readbdy = 1; /* -r flag */
+int style = 0; /* -s flag */
+int truncbdy = 1; /* -t flag */
+int writebdy = 1; /* -w flag */
+long monitorstart = -1; /* -m flag */
+long monitorend = -1; /* -m flag */
+int lite = 0; /* -L flag */
+int randomoplen = 1; /* -O flag disables it */
+int seed = 1; /* -S flag */
+
+int mapped_writes = 0; /* yaffs direct does not support mmapped files */
+int mapped_reads = 0;
+
+int fsxgoodfd = 0;
+FILE * fsxlogf = NULL;
+int badoff = -1;
+int closeopen = 0;
+
+
+
+void EXIT(int x)
+{
+ printf("fsx wanted to exit with %d\n",x);
+ while(x){}
+}
+
+char goodfile[1024];
+char logfile[1024];
+
+
+void
+vwarnc(code, fmt, ap)
+ int code;
+ const char *fmt;
+ va_list ap;
+{
+ fprintf(stderr, "fsx: ");
+ if (fmt != NULL) {
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ": ");
+ }
+ fprintf(stderr, "%s\n", strerror(code));
+}
+
+
+void
+warn(const char * fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(errno, fmt, ap);
+ va_end(ap);
+}
+
+
+void
+prt(char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ if (fsxlogf)
+ vfprintf(fsxlogf, fmt, args);
+ va_end(args);
+}
+
+void
+prterr(char *prefix)
+{
+ prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(errno));
+}
+
+
+void
+log4(int operation, int arg0, int arg1, int arg2)
+{
+ struct log_entry *le;
+
+ le = &oplog[logptr];
+ le->operation = operation;
+ if (closeopen)
+ le->operation = ~ le->operation;
+ le->args[0] = arg0;
+ le->args[1] = arg1;
+ le->args[2] = arg2;
+ logptr++;
+ logcount++;
+ if (logptr >= LOGSIZE)
+ logptr = 0;
+}
+
+
+void
+logdump(void)
+{
+ int i, count, down;
+ struct log_entry *lp;
+
+ prt("LOG DUMP (%d total operations):\n", logcount);
+ if (logcount < LOGSIZE) {
+ i = 0;
+ count = logcount;
+ } else {
+ i = logptr;
+ count = LOGSIZE;
+ }
+ for ( ; count > 0; count--) {
+ int opnum;
+
+ opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE;
+ prt("%d(%d mod 256): ", opnum, opnum%256);
+ lp = &oplog[i];
+ if ((closeopen = lp->operation < 0))
+ lp->operation = ~ lp->operation;
+
+ switch (lp->operation) {
+ case OP_MAPREAD:
+ prt("MAPREAD\t0x%x thru 0x%x\t(0x%x bytes)",
+ lp->args[0], lp->args[0] + lp->args[1] - 1,
+ lp->args[1]);
+ if (badoff >= lp->args[0] && badoff <
+ lp->args[0] + lp->args[1])
+ prt("\t***RRRR***");
+ break;
+ case OP_MAPWRITE:
+ prt("MAPWRITE 0x%x thru 0x%x\t(0x%x bytes)",
+ lp->args[0], lp->args[0] + lp->args[1] - 1,
+ lp->args[1]);
+ if (badoff >= lp->args[0] && badoff <
+ lp->args[0] + lp->args[1])
+ prt("\t******WWWW");
+ break;
+ case OP_READ:
+ prt("READ\t0x%x thru 0x%x\t(0x%x bytes)",
+ lp->args[0], lp->args[0] + lp->args[1] - 1,
+ lp->args[1]);
+ if (badoff >= lp->args[0] &&
+ badoff < lp->args[0] + lp->args[1])
+ prt("\t***RRRR***");
+ break;
+ case OP_WRITE:
+ prt("WRITE\t0x%x thru 0x%x\t(0x%x bytes)",
+ lp->args[0], lp->args[0] + lp->args[1] - 1,
+ lp->args[1]);
+ if (lp->args[0] > lp->args[2])
+ prt(" HOLE");
+ else if (lp->args[0] + lp->args[1] > lp->args[2])
+ prt(" EXTEND");
+ if ((badoff >= lp->args[0] || badoff >=lp->args[2]) &&
+ badoff < lp->args[0] + lp->args[1])
+ prt("\t***WWWW");
+ break;
+ case OP_TRUNCATE:
+ down = lp->args[0] < lp->args[1];
+ prt("TRUNCATE %s\tfrom 0x%x to 0x%x",
+ down ? "DOWN" : "UP", lp->args[1], lp->args[0]);
+ if (badoff >= lp->args[!down] &&
+ badoff < lp->args[!!down])
+ prt("\t******WWWW");
+ break;
+ case OP_SKIPPED:
+ prt("SKIPPED (no operation)");
+ break;
+ default:
+ prt("BOGUS LOG ENTRY (operation code = %d)!",
+ lp->operation);
+ }
+ if (closeopen)
+ prt("\n\t\tCLOSE/OPEN");
+ prt("\n");
+ i++;
+ if (i == LOGSIZE)
+ i = 0;
+ }
+}
+
+
+void
+save_buffer(char *buffer, off_t bufferlength, int fd)
+{
+ off_t ret;
+ ssize_t byteswritten;
+
+ if (fd <= 0 || bufferlength == 0)
+ return;
+
+ if (bufferlength > SSIZE_MAX) {
+ prt("fsx flaw: overflow in save_buffer\n");
+ EXIT(67);
+ }
+ if (lite) {
+ off_t size_by_seek = lseek(fd, (off_t)0, SEEK_END);
+ if (size_by_seek == (off_t)-1)
+ prterr("save_buffer: lseek eof");
+ else if (bufferlength > size_by_seek) {
+ warn("save_buffer: .fsxgood file too short... will save 0x%llx bytes instead of 0x%llx\n", (unsigned long long)size_by_seek,
+ (unsigned long long)bufferlength);
+ bufferlength = size_by_seek;
+ }
+ }
+
+ ret = lseek(fd, (off_t)0, SEEK_SET);
+ if (ret == (off_t)-1)
+ prterr("save_buffer: lseek 0");
+
+ byteswritten = write(fd, buffer, (size_t)bufferlength);
+ if (byteswritten != bufferlength) {
+ if (byteswritten == -1)
+ prterr("save_buffer write");
+ else
+ warn("save_buffer: short write, 0x%x bytes instead of 0x%llx\n",
+ (unsigned)byteswritten,
+ (unsigned long long)bufferlength);
+ }
+}
+
+
+void
+report_failure(int status)
+{
+ logdump();
+
+ if (fsxgoodfd) {
+ if (good_buf) {
+ save_buffer(good_buf, file_size, fsxgoodfd);
+ prt("Correct content saved for comparison\n");
+ prt("(maybe hexdump \"%s\" vs \"%s.fsxgood\")\n",
+ fname, fname);
+ }
+ close(fsxgoodfd);
+ }
+ prt("Exiting with %d\n",status);
+ EXIT(status);
+}
+
+
+#define short_at(cp) ((unsigned short)((*((unsigned char *)(cp)) << 8) | \
+ *(((unsigned char *)(cp)) + 1)))
+
+void
+check_buffers(unsigned offset, unsigned size)
+{
+ unsigned char c, t;
+ unsigned i = 0;
+ unsigned n = 0;
+ unsigned op = 0;
+ unsigned bad = 0;
+
+ if (memcmp(good_buf + offset, temp_buf, size) != 0) {
+ prt("READ BAD DATA: offset = 0x%x, size = 0x%x\n",
+ offset, size);
+ prt("OFFSET\tGOOD\tBAD\tRANGE\n");
+ while (size > 0) {
+ c = good_buf[offset];
+ t = temp_buf[i];
+ if (c != t) {
+ if (n == 0) {
+ bad = short_at(&temp_buf[i]);
+ prt("0x%5x\t0x%04x\t0x%04x", offset,
+ short_at(&good_buf[offset]), bad);
+ op = temp_buf[offset & 1 ? i+1 : i];
+ }
+ n++;
+ badoff = offset;
+ }
+ offset++;
+ i++;
+ size--;
+ }
+ if (n) {
+ prt("\t0x%5x\n", n);
+ if (bad)
+ prt("operation# (mod 256) for the bad data may be %u\n", ((unsigned)op & 0xff));
+ else
+ prt("operation# (mod 256) for the bad data unknown, check HOLE and EXTEND ops\n");
+ } else
+ prt("????????????????\n");
+ report_failure(110);
+ }
+}
+
+
+void
+check_size(void)
+{
+ struct stat statbuf;
+ off_t size_by_seek;
+
+ if (fstat(fd, &statbuf)) {
+ prterr("check_size: fstat");
+ statbuf.st_size = -1;
+ }
+ size_by_seek = lseek(fd, (off_t)0, SEEK_END);
+ if (file_size != statbuf.st_size ||
+ file_size != size_by_seek) {
+ prt("Size error: expected 0x%llx stat 0x%llx seek 0x%llx\n",
+ (unsigned long long)file_size,
+ (unsigned long long)statbuf.st_size,
+ (unsigned long long)size_by_seek);
+ report_failure(120);
+ }
+}
+
+
+void
+check_trunc_hack(void)
+{
+ struct stat statbuf;
+
+ ftruncate(fd, (off_t)0);
+ ftruncate(fd, (off_t)100000);
+ fstat(fd, &statbuf);
+ if (statbuf.st_size != (off_t)100000) {
+ prt("no extend on truncate! not posix!\n");
+ EXIT(130);
+ }
+ ftruncate(fd, (off_t)0);
+}
+
+
+void
+doread(unsigned offset, unsigned size)
+{
+ off_t ret;
+ unsigned iret;
+
+ offset -= offset % readbdy;
+ if (size == 0) {
+ if (!quiet && testcalls > simulatedopcount)
+ prt("skipping zero size read\n");
+ log4(OP_SKIPPED, OP_READ, offset, size);
+ return;
+ }
+ if ((off_t)(size + offset) > file_size) {
+ if (!quiet && testcalls > simulatedopcount)
+ prt("skipping seek/read past end of file\n");
+ log4(OP_SKIPPED, OP_READ, offset, size);
+ return;
+ }
+
+ log4(OP_READ, offset, size, 0);
+
+ if (testcalls <= simulatedopcount)
+ return;
+
+ if (!quiet && ((progressinterval &&
+ testcalls % progressinterval == 0) ||
+ (debug &&
+ (monitorstart == -1 ||
+ (offset + size > monitorstart &&
+ (monitorend == -1 || offset <= monitorend))))))
+ prt("%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
+ offset, offset + size - 1, size);
+ ret = lseek(fd, (off_t)offset, SEEK_SET);
+ if (ret == (off_t)-1) {
+ prterr("doread: lseek");
+ report_failure(140);
+ }
+ iret = read(fd, temp_buf, size);
+ if (iret != size) {
+ if (iret == (unsigned)(-1))
+ prterr("doread: read");
+ else
+ prt("short read: 0x%x bytes instead of 0x%x\n",
+ iret, size);
+ report_failure(141);
+ }
+ check_buffers(offset, size);
+}
+
+
+
+
+
+void
+gendata(char *original_buf, char *good_buf, unsigned offset, unsigned size)
+{
+ while (size--) {
+ good_buf[offset] = testcalls % 256;
+ if (offset % 2)
+ good_buf[offset] += original_buf[offset];
+ offset++;
+ }
+}
+
+
+void
+dowrite(unsigned offset, unsigned size)
+{
+ off_t ret;
+ unsigned iret;
+
+ offset -= offset % writebdy;
+ if (size == 0) {
+ if (!quiet && testcalls > simulatedopcount)
+ prt("skipping zero size write\n");
+ log4(OP_SKIPPED, OP_WRITE, offset, size);
+ return;
+ }
+
+ log4(OP_WRITE, offset, size, file_size);
+
+ gendata(original_buf, good_buf, offset, size);
+ if (file_size < offset + size) {
+ if (file_size < offset)
+ memset(good_buf + file_size, '\0', offset - file_size);
+ file_size = offset + size;
+ if (lite) {
+ warn("Lite file size bug in fsx!");
+ report_failure(149);
+ }
+ }
+
+ if (testcalls <= simulatedopcount)
+ return;
+
+ if (!quiet && ((progressinterval &&
+ testcalls % progressinterval == 0) ||
+ (debug &&
+ (monitorstart == -1 ||
+ (offset + size > monitorstart &&
+ (monitorend == -1 || offset <= monitorend))))))
+ prt("%lu write\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
+ offset, offset + size - 1, size);
+ ret = lseek(fd, (off_t)offset, SEEK_SET);
+ if (ret == (off_t)-1) {
+ prterr("dowrite: lseek");
+ report_failure(150);
+ }
+ iret = write(fd, good_buf + offset, size);
+ if (iret != size) {
+ if (iret == (unsigned)(-1))
+ prterr("dowrite: write");
+ else
+ prt("short write: 0x%x bytes instead of 0x%x\n",
+ iret, size);
+ report_failure(151);
+ }
+}
+
+
+
+void
+dotruncate(unsigned size)
+{
+ int oldsize = file_size;
+
+ size -= size % truncbdy;
+ if (size > biggest) {
+ biggest = size;
+ if (!quiet && testcalls > simulatedopcount)
+ prt("truncating to largest ever: 0x%x\n", size);
+ }
+
+ log4(OP_TRUNCATE, size, (unsigned)file_size, 0);
+
+ if (size > file_size)
+ memset(good_buf + file_size, '\0', size - file_size);
+ file_size = size;
+
+ if (testcalls <= simulatedopcount)
+ return;
+
+ if ((progressinterval && testcalls % progressinterval == 0) ||
+ (debug && (monitorstart == -1 || monitorend == -1 ||
+ size <= monitorend)))
+ prt("%lu trunc\tfrom 0x%x to 0x%x\n", testcalls, oldsize, size);
+ if (ftruncate(fd, (off_t)size) == -1) {
+ prt("ftruncate1: %x\n", size);
+ prterr("dotruncate: ftruncate");
+ report_failure(160);
+ }
+}
+
+
+void
+writefileimage()
+{
+ ssize_t iret;
+
+ if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
+ prterr("writefileimage: lseek");
+ report_failure(171);
+ }
+ iret = write(fd, good_buf, file_size);
+ if ((off_t)iret != file_size) {
+ if (iret == -1)
+ prterr("writefileimage: write");
+ else
+ prt("short write: 0x%x bytes instead of 0x%llx\n",
+ iret, (unsigned long long)file_size);
+ report_failure(172);
+ }
+ if (lite ? 0 : ftruncate(fd, file_size) == -1) {
+ prt("ftruncate2: %llx\n", (unsigned long long)file_size);
+ prterr("writefileimage: ftruncate");
+ report_failure(173);
+ }
+}
+
+
+void
+docloseopen(void)
+{
+ if (testcalls <= simulatedopcount)
+ return;
+
+ if (debug)
+ prt("%lu close/open\n", testcalls);
+ if (close(fd)) {
+ prterr("docloseopen: close");
+ report_failure(180);
+ }
+ fd = open(fname, O_RDWR, 0);
+ if (fd < 0) {
+ prterr("docloseopen: open");
+ report_failure(181);
+ }
+}
+
+
+void
+fsx_do_op(void)
+{
+ unsigned long offset;
+ unsigned long size = maxoplen;
+ unsigned long rv = random();
+ unsigned long op = rv % (3 + !lite + mapped_writes);
+
+ /* turn off the map read if necessary */
+
+ if (op == 2 && !mapped_reads)
+ op = 0;
+
+ if (simulatedopcount > 0 && testcalls == simulatedopcount)
+ writefileimage();
+
+ testcalls++;
+
+ if (closeprob)
+ closeopen = (rv >> 3) < (1U << 28) / closeprob;
+
+ if (debugstart > 0 && testcalls >= debugstart)
+ debug = 1;
+
+ if (!quiet && testcalls < simulatedopcount && testcalls % 100000 == 0)
+ prt("%lu...\n", testcalls);
+
+ /*
+ * READ: op = 0
+ * WRITE: op = 1
+ * MAPREAD: op = 2
+ * TRUNCATE: op = 3
+ * MAPWRITE: op = 3 or 4
+ */
+ if (lite ? 0 : op == 3 && (style & 1) == 0) /* vanilla truncate? */
+ dotruncate(random() % maxfilelen);
+ else {
+ if (randomoplen)
+ size = random() % (maxoplen+1);
+ if (lite ? 0 : op == 3)
+ dotruncate(size);
+ else {
+ offset = random();
+ if (op == 1 || op == (lite ? 3 : 4)) {
+ offset %= maxfilelen;
+ if (offset + size > maxfilelen)
+ size = maxfilelen - offset;
+ dowrite(offset, size);
+ } else {
+ if (file_size)
+ offset %= file_size;
+ else
+ offset = 0;
+ if ((ssize_t)(offset + size) > file_size)
+ size = file_size - offset;
+ doread(offset, size);
+ }
+ }
+ }
+ if (sizechecks && testcalls > simulatedopcount)
+ check_size();
+ if (closeopen)
+ docloseopen();
+}
+
+
+void
+cleanup(sig)
+ int sig;
+{
+ if (sig)
+ prt("signal %d\n", sig);
+ prt("testcalls = %lu\n", testcalls);
+ EXIT(sig);
+}
+
+
+void
+usage(void)
+{
+ fprintf(stdout, "usage: %s",
+ "fsx [-dnqLOW] [-b opnum] [-c Prob] [-l flen] [-m start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style] [-t truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed] fname\n\
+ -b opnum: beginning operation number (default 1)\n\
+ -c P: 1 in P chance of file close+open at each op (default infinity)\n\
+ -d: debug output for all operations\n\
+ -l flen: the upper bound on file size (default 262144)\n\
+ -m startop:endop: monitor (print debug output) specified byte range (default 0:infinity)\n\
+ -n: no verifications of file size\n\
+ -o oplen: the upper bound on operation size (default 65536)\n\
+ -p progressinterval: debug output at specified operation interval\n\
+ -q: quieter operation\n\
+ -r readbdy: 4096 would make reads page aligned (default 1)\n\
+ -s style: 1 gives smaller truncates (default 0)\n\
+ -t truncbdy: 4096 would make truncates page aligned (default 1)\n\
+ -w writebdy: 4096 would make writes page aligned (default 1)\n\
+ -D startingop: debug output starting at specified operation\n\
+ -L: fsxLite - no file creations & no file size changes\n\
+ -N numops: total # operations to do (default infinity)\n\
+ -O: use oplen (see -o flag) for every op (default random)\n\
+ -P dirpath: save .fsxlog and .fsxgood files in dirpath (default ./)\n\
+ -S seed: for random # generator (default 1) 0 gets timestamp\n\
+ fname: this filename is REQUIRED (no default)\n");
+ EXIT(90);
+}
+
+
+int
+getnum(char *s, char **e)
+{
+ int ret = -1;
+
+ *e = (char *) 0;
+ ret = strtol(s, e, 0);
+ if (*e)
+ switch (**e) {
+ case 'b':
+ case 'B':
+ ret *= 512;
+ *e = *e + 1;
+ break;
+ case 'k':
+ case 'K':
+ ret *= 1024;
+ *e = *e + 1;
+ break;
+ case 'm':
+ case 'M':
+ ret *= 1024*1024;
+ *e = *e + 1;
+ break;
+ case 'w':
+ case 'W':
+ ret *= 4;
+ *e = *e + 1;
+ break;
+ }
+ return (ret);
+}
+
+
+
+extern int random_seed;
+extern int simulate_power_failure;
+
+
+int mounted_by_fsx = 0;
+
+
+
+int
+fsx_init(const char *mount_pt)
+{
+ unsigned i;
+
+ goodfile[0] = 0;
+ logfile[0] = 0;
+
+ page_size = getpagesize();
+ page_mask = page_size - 1;
+
+ setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */
+
+ strcpy(mount_name,mount_pt);
+ strcpy(fname,mount_name);
+ strcat(fname,"/fsxdata");
+
+#if 0
+ signal(SIGHUP, cleanup);
+ signal(SIGINT, cleanup);
+ signal(SIGPIPE, cleanup);
+ signal(SIGALRM, cleanup);
+ signal(SIGTERM, cleanup);
+ signal(SIGXCPU, cleanup);
+ signal(SIGXFSZ, cleanup);
+ signal(SIGVTALRM, cleanup);
+ signal(SIGUSR1, cleanup);
+ signal(SIGUSR2, cleanup);
+#endif
+
+#if 0
+ initstate(seed, state, 256);
+ setstate(state);
+#endif
+
+ fd = open(fname, O_RDWR|(lite ? 0 : O_CREAT|O_TRUNC), 0666);
+ if (fd < 0) {
+ prterr(fname);
+ EXIT(91);
+ }
+ strncat(goodfile, fname, 256);
+ strcat (goodfile, ".fsxgood");
+ fsxgoodfd = open(goodfile, O_RDWR|O_CREAT|O_TRUNC, 0666);
+ if (fsxgoodfd < 0) {
+ prterr(goodfile);
+ EXIT(92);
+ }
+ strncat(logfile, "fsx", 256);
+ strcat (logfile, ".fsxlog");
+ fsxlogf = fopen(logfile, "w");
+ if (fsxlogf == NULL) {
+ prterr(logfile);
+ EXIT(93);
+ }
+ if (lite) {
+ off_t ret;
+ file_size = maxfilelen = lseek(fd, (off_t)0, SEEK_END);
+ if (file_size == (off_t)-1) {
+ prterr(fname);
+ warn("main: lseek eof");
+ EXIT(94);
+ }
+ ret = lseek(fd, (off_t)0, SEEK_SET);
+ if (ret == (off_t)-1) {
+ prterr(fname);
+ warn("main: lseek 0");
+ EXIT(95);
+ }
+ }
+ original_buf = (char *) malloc(maxfilelen);
+ for (i = 0; i < maxfilelen; i++)
+ original_buf[i] = random() % 256;
+ good_buf = (char *) malloc(maxfilelen);
+ memset(good_buf, '\0', maxfilelen);
+ temp_buf = (char *) malloc(maxoplen);
+ memset(temp_buf, '\0', maxoplen);
+ if (lite) { /* zero entire existing file */
+ ssize_t written;
+
+ written = write(fd, good_buf, (size_t)maxfilelen);
+ if (written != (ssize_t)maxfilelen) {
+ if (written == -1) {
+ prterr(fname);
+ warn("main: error on write");
+ } else
+ warn("main: short write, 0x%x bytes instead of 0x%x\n",
+ (unsigned)written, maxfilelen);
+ EXIT(98);
+ }
+ } else
+ check_trunc_hack();
+
+ printf("fsx_init done\n");
+
+ return 0;
+}
+
+
+int fsx_complete(void)
+{
+ if (close(fd)) {
+ prterr("close");
+ report_failure(99);
+ }
+
+ close(fsxgoodfd);
+
+ prt("All operations completed A-OK!\n");
+
+ EXIT(0);
+ return 0;
+}
+
+int fsx_main(const char *mount_pt, int numops)
+{
+ fsx_init(mount_pt);
+ while (numops == -1 || numops--)
+ fsx_do_op();
+ fsx_complete();
+
+ return 0;
+}
+
+
+#define YPATH "/yaffs_mount_pt"
+
+#define FSX_TEST_DIR YPATH"/fsx_mount"
+
+int run_the_test(void)
+{
+ int ret;
+ ret = mkdir(FSX_TEST_DIR, 0777);
+ printf("mkdir returned %d\n", ret);
+
+ if (ret < 0)
+ perror("mkdir");
+
+ return fsx_main(FSX_TEST_DIR, 10000);
+}
--- /dev/null
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ * Copyright (C) 2011 Stephan Hoffmann <sho@reLinux.de>
+ * Copyright (C) 2011-2012 embedded brains GmbH <rtems@embedded-brains.de>
+ * Copyright (C) 2019 Space Sciences and Engineering, LLC
+ * <jbrandmeyer@planetiq.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * As a special exception, linking other files with the object code from
+ * this one to produce an executable application does not by itself cause
+ * the resulting executable application to be covered by the GNU General
+ * Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+
+#include "yportenv.h"
+
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yaffs_packedtags2.h"
+
+#include "rtems_yaffs.h"
+
+/* RTEMS interface */
+
+static const rtems_filesystem_file_handlers_r yaffs_directory_handlers;
+static const rtems_filesystem_file_handlers_r yaffs_file_handlers;
+static const rtems_filesystem_file_handlers_r yaffs_link_handlers;
+static const rtems_filesystem_operations_table yaffs_ops;
+
+/* locking */
+
+static void ylock(struct yaffs_dev *dev)
+{
+ rtems_yaffs_os_context *os_context = dev->os_context;
+ (*os_context->lock)(dev, os_context);
+}
+
+static void yunlock(struct yaffs_dev *dev)
+{
+ rtems_yaffs_os_context *os_context = dev->os_context;
+ (*os_context->unlock)(dev, os_context);
+}
+
+static void rtems_yaffs_os_unmount(struct yaffs_dev *dev)
+{
+ rtems_yaffs_os_context *os_context = dev->os_context;
+ (*os_context->unmount)(dev, os_context);
+}
+
+static struct yaffs_obj *ryfs_get_object_by_location(
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ return loc->node_access;
+}
+
+static struct yaffs_obj *ryfs_get_object_by_iop(
+ const rtems_libio_t *iop
+)
+{
+ return iop->pathinfo.node_access;
+}
+
+static struct yaffs_dev *ryfs_get_device_by_mt_entry(
+ const rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ return mt_entry->fs_info;
+}
+
+static void ryfs_set_location(rtems_filesystem_location_info_t *loc, struct yaffs_obj *obj)
+{
+ loc->node_access = obj;
+
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ loc->handlers = &yaffs_file_handlers;
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ loc->handlers = &yaffs_directory_handlers;
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ loc->handlers = &yaffs_link_handlers;
+ break;
+ default:
+ loc->handlers = &rtems_filesystem_handlers_default;
+ break;
+ };
+}
+
+static bool ryfs_eval_is_directory(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg
+)
+{
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
+ struct yaffs_obj *obj = ryfs_get_object_by_location(currentloc);
+
+ obj = yaffs_get_equivalent_obj(obj);
+
+ return obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY;
+}
+
+static const char *ryfs_make_string(char *buf, const char *src, size_t len)
+{
+ buf [len] = '\0';
+
+ return memcpy(buf, src, len);
+}
+
+static struct yaffs_obj *ryfs_search_in_directory(
+ struct yaffs_obj *dir,
+ const char *token,
+ size_t tokenlen
+)
+{
+ if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
+ dir = dir->parent;
+ } else if (!rtems_filesystem_is_current_directory(token, tokenlen)) {
+ if (tokenlen < YAFFS_MAX_NAME_LENGTH) {
+ char buf [YAFFS_MAX_NAME_LENGTH + 1];
+
+ dir = yaffs_find_by_name(
+ dir,
+ ryfs_make_string(buf, token, tokenlen)
+ );
+ } else {
+ dir = NULL;
+ }
+ }
+
+ return dir;
+}
+
+static rtems_filesystem_eval_path_generic_status ryfs_eval_token(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const char *token,
+ size_t tokenlen
+)
+{
+ rtems_filesystem_eval_path_generic_status status =
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc(ctx);
+ struct yaffs_obj *dir = ryfs_get_object_by_location(currentloc);
+ bool access_ok = rtems_filesystem_eval_path_check_access(
+ ctx,
+ RTEMS_FS_PERMS_EXEC,
+ dir->yst_mode,
+ (uid_t) dir->yst_uid,
+ (gid_t) dir->yst_gid
+ );
+
+ if (access_ok) {
+ struct yaffs_obj *entry = ryfs_search_in_directory(dir, token, tokenlen);
+
+ if (entry != NULL) {
+ bool terminal = !rtems_filesystem_eval_path_has_path(ctx);
+ int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
+ bool follow_hard_link = (eval_flags & RTEMS_FS_FOLLOW_HARD_LINK) != 0;
+ bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
+ enum yaffs_obj_type type = entry->variant_type;
+
+ rtems_filesystem_eval_path_clear_token(ctx);
+
+ if (type == YAFFS_OBJECT_TYPE_HARDLINK && (follow_hard_link || !terminal)) {
+ entry = yaffs_get_equivalent_obj(entry);
+ }
+
+ if (type == YAFFS_OBJECT_TYPE_SYMLINK && (follow_sym_link || !terminal)) {
+ const char *target = entry->variant.symlink_variant.alias;
+
+ rtems_filesystem_eval_path_recursive(ctx, target, strlen(target));
+ } else {
+ ryfs_set_location(currentloc, entry);
+
+ if (!terminal) {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+ }
+ }
+ } else {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
+ }
+ }
+
+ return status;
+}
+
+static const rtems_filesystem_eval_path_generic_config ryfs_eval_config = {
+ .is_directory = ryfs_eval_is_directory,
+ .eval_token = ryfs_eval_token
+};
+
+static void ryfs_eval_path(rtems_filesystem_eval_path_context_t *ctx)
+{
+ rtems_filesystem_eval_path_generic(ctx, NULL, &ryfs_eval_config);
+}
+
+/* Helper functions */
+
+static int ryfs_mknod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const char *name,
+ size_t namelen,
+ mode_t mode,
+ dev_t dev
+)
+{
+ int rv = 0;
+ struct yaffs_obj *parent = ryfs_get_object_by_location(parentloc);
+ struct yaffs_obj *(*create)(
+ struct yaffs_obj *parent,
+ const YCHAR *name,
+ u32 mode,
+ u32 uid,
+ u32 gid
+ );
+
+ switch (mode & S_IFMT) {
+ case S_IFREG:
+ create = yaffs_create_file;
+ break;
+ case S_IFDIR:
+ create = yaffs_create_dir;
+ break;
+ default:
+ errno = EINVAL;
+ rv = -1;
+ break;
+ }
+
+ if (rv == 0) {
+ char buf [YAFFS_MAX_NAME_LENGTH + 1];
+ struct yaffs_obj *entry = (*create)(
+ parent,
+ ryfs_make_string(buf, name, namelen),
+ mode,
+ geteuid(),
+ getegid()
+ );
+
+ if (entry == NULL) {
+ errno = ENOSPC;
+ rv = -1;
+ }
+ }
+
+ return rv;
+}
+
+static int ryfs_utime(
+ const rtems_filesystem_location_info_t *loc,
+ time_t actime,
+ time_t modtime
+)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+
+ obj = yaffs_get_equivalent_obj(obj);
+ if (obj != NULL) {
+ obj->dirty = 1;
+ obj->yst_atime = actime;
+ obj->yst_mtime = modtime;
+ obj->yst_ctime = time(NULL);
+ } else {
+ errno = EIO;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+static int ryfs_rename(
+ const rtems_filesystem_location_info_t *old_parent_loc,
+ const rtems_filesystem_location_info_t *old_loc,
+ const rtems_filesystem_location_info_t *new_parent_loc,
+ const char *name,
+ size_t namelen
+)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_location(old_loc);
+ char old_name_buf [YAFFS_MAX_NAME_LENGTH + 1];
+ char new_name_buf [YAFFS_MAX_NAME_LENGTH + 1];
+ int yc;
+
+ yaffs_get_obj_name(obj, old_name_buf, sizeof(old_name_buf));
+ yc = yaffs_rename_obj(
+ obj->parent,
+ old_name_buf,
+ ryfs_get_object_by_location(new_parent_loc),
+ ryfs_make_string(new_name_buf, name, namelen)
+ );
+ if (yc != YAFFS_OK) {
+ errno = EIO;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+static ssize_t ryfs_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ struct dirent *de = (struct dirent *)buffer;
+ size_t i;
+ size_t maxcount;
+ struct list_head *next;
+ ssize_t readlen;
+
+ obj = (struct yaffs_obj *)iop->pathinfo.node_access;
+ dev = obj->my_dev;
+ maxcount = count / sizeof(struct dirent);
+
+ ylock(dev);
+
+ if(iop->offset == 0) {
+ if(list_empty(&obj->variant.dir_variant.children))
+ iop->data1 = NULL;
+ else
+ iop->data1 = list_entry(obj->variant.dir_variant.children.next, struct yaffs_obj, siblings);
+ }
+
+ i = 0;
+ while((i < maxcount) && (iop->data1 != NULL)) {
+ de[i].d_ino = (long)yaffs_get_equivalent_obj((struct yaffs_obj *)iop->data1)->obj_id;
+ de[i].d_off = 0;
+ yaffs_get_obj_name((struct yaffs_obj *)iop->data1, de[i].d_name, NAME_MAX);
+ de[i].d_reclen = sizeof(struct dirent);
+ de[i].d_namlen = (unsigned short)strnlen(de[i].d_name, NAME_MAX);
+
+ i++;
+ next = ((struct yaffs_obj *)iop->data1)->siblings.next;
+ if(next == &obj->variant.dir_variant.children)
+ iop->data1 = NULL; /* end of list */
+ else
+ iop->data1 = list_entry(next, struct yaffs_obj, siblings);
+ }
+
+ readlen = (ssize_t)(i * sizeof(struct dirent));
+ iop->offset = iop->offset + readlen;
+
+ yunlock(dev);
+
+ return readlen;
+}
+
+static int ryfs_fstat(const rtems_filesystem_location_info_t *loc, struct stat *buf)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+ struct yaffs_dev *dev = obj->my_dev;
+ rtems_yaffs_os_context *os_context = dev->os_context;
+
+ ylock(dev);
+
+ obj = yaffs_get_equivalent_obj(obj);
+ if (obj != NULL) {
+ buf->st_dev = os_context->dev;
+ buf->st_ino = obj->obj_id;
+ buf->st_mode = obj->yst_mode;
+ buf->st_nlink = (nlink_t) yaffs_get_obj_link_count(obj);
+ buf->st_rdev = obj->yst_rdev;
+ buf->st_size = yaffs_get_obj_length(obj);
+ buf->st_blksize = obj->my_dev->data_bytes_per_chunk;
+ buf->st_blocks = (blkcnt_t)
+ ((buf->st_size + buf->st_blksize - 1) / buf->st_blksize);
+ buf->st_uid = (uid_t) obj->yst_uid;
+ buf->st_gid = (gid_t) obj->yst_gid;
+ buf->st_atime = (time_t) obj->yst_atime;
+ buf->st_ctime = (time_t) obj->yst_ctime;
+ buf->st_mtime = (time_t) obj->yst_mtime;
+ } else {
+ errno = EIO;
+ rv = -1;
+ }
+
+ yunlock(dev);
+
+ return rv;
+}
+
+static int ryfs_fchmod(const rtems_filesystem_location_info_t *loc, mode_t mode)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+ int yc;
+
+ obj = yaffs_get_equivalent_obj(obj);
+ if (obj != NULL) {
+ obj->yst_mode = mode;
+ obj->dirty = 1;
+ yc = yaffs_flush_file(obj, 0, 0, 0);
+ } else {
+ yc = YAFFS_FAIL;
+ }
+
+ if (yc != YAFFS_OK) {
+ errno = EIO;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+static int ryfs_chown(
+ const rtems_filesystem_location_info_t *loc,
+ uid_t owner,
+ gid_t group
+)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+ int yc;
+
+ obj = yaffs_get_equivalent_obj(obj);
+ if (obj != NULL) {
+ obj->yst_uid = owner;
+ obj->yst_gid = group;
+ obj->dirty = 1;
+ yc = yaffs_flush_file(obj, 0, 0, 0);
+ } else {
+ yc = YAFFS_FAIL;
+ }
+
+ if (yc != YAFFS_OK) {
+ errno = EIO;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+static int ryfs_fsync_or_fdatasync(rtems_libio_t *iop)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+ struct yaffs_dev *dev = obj->my_dev;
+ int yc;
+
+ ylock(dev);
+ yc = yaffs_flush_file(obj, 0, 1, 0);
+ if (rtems_filesystem_location_is_instance_root(&iop->pathinfo)) {
+ yaffs_flush_whole_cache(dev, 0);
+ }
+ yunlock(dev);
+
+ if (yc != YAFFS_OK) {
+ errno = EIO;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+static int ryfs_rmnod(
+ const rtems_filesystem_location_info_t *parentloc,
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+ int yc = yaffs_del_obj(obj);
+
+ if (yc != YAFFS_OK) {
+ errno = ENOTEMPTY;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+static int ryfs_file_open(rtems_libio_t *iop, const char *pathname, int oflag, mode_t mode)
+{
+ struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+ struct yaffs_dev *dev = obj->my_dev;
+ int length = 0;
+
+ ylock(dev);
+ length = yaffs_get_obj_length(obj);
+ if ((iop->flags & LIBIO_FLAGS_APPEND) != 0) {
+ iop->offset = length;
+ }
+ yunlock(dev);
+
+ return 0;
+}
+
+static int ryfs_file_close(rtems_libio_t *iop)
+{
+ struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+ struct yaffs_dev *dev = obj->my_dev;
+
+ ylock(dev);
+ yaffs_flush_file(obj, 1, 0, 1);
+ yunlock(dev);
+
+ return 0;
+}
+
+static ssize_t ryfs_file_read(rtems_libio_t *iop, void *buffer, size_t count)
+{
+ struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+ struct yaffs_dev *dev = obj->my_dev;
+ ssize_t nr;
+ int ol;
+ size_t maxread;
+
+ ylock(dev);
+
+ ol = yaffs_get_obj_length(obj);
+ if(iop->offset >= ol)
+ maxread = 0;
+ else
+ maxread = (size_t)(ol - (int)iop->offset);
+ if(count > maxread)
+ count = maxread;
+
+ nr = yaffs_file_rd(obj, buffer, iop->offset, (int)count);
+ if (nr >= 0) {
+ iop->offset += nr;
+ } else {
+ errno = EIO;
+ nr = -1;
+ }
+
+ yunlock(dev);
+
+ return nr;
+}
+
+static ssize_t ryfs_file_write(rtems_libio_t *iop, const void *buffer, size_t count)
+{
+ struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+ struct yaffs_dev *dev = obj->my_dev;
+ ssize_t rv = -1;
+ int max_size = INT_MAX;
+ off_t offset;
+
+ if (count == 0) {
+ return 0;
+ }
+
+ ylock(dev);
+ offset = iop->offset;
+ if (offset < max_size) {
+ size_t max_count = max_size - (size_t) offset;
+
+ if (count > max_count) {
+ count = max_count;
+ }
+
+ rv = yaffs_wr_file(obj, buffer, offset, (int) count, 0);
+ if (rv > 0) {
+ iop->offset += rv;
+ } else {
+ errno = ENOSPC;
+ rv = -1;
+ }
+ } else {
+ errno = EFBIG;
+ }
+ yunlock(dev);
+
+ return rv;
+}
+
+static int ryfs_file_ftruncate(rtems_libio_t *iop, off_t length)
+{
+ int rv = 0;
+ struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+ struct yaffs_dev *dev = obj->my_dev;
+ int yc;
+
+ ylock(dev);
+ yc = yaffs_resize_file(obj, length);
+ yunlock(dev);
+
+ if (yc != YAFFS_OK) {
+ errno = EIO;
+ rv = -1;
+ }
+
+ return rv;
+}
+
+int rtems_yaffs_mount_handler(rtems_filesystem_mount_table_entry_t *mt_entry, const void *data)
+{
+ const rtems_yaffs_mount_data *mount_data = data;
+ struct yaffs_dev *dev = mount_data->dev;
+
+ if (dev->read_only && mt_entry->writeable) {
+ errno = EACCES;
+ return -1;
+ }
+
+ ylock(dev);
+ if (yaffs_guts_initialise(dev) == YAFFS_FAIL) {
+ yunlock(dev);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ mt_entry->fs_info = dev;
+ mt_entry->ops = &yaffs_ops;
+ mt_entry->mt_fs_root->location.node_access = dev->root_dir;
+ mt_entry->mt_fs_root->location.handlers = &yaffs_directory_handlers;
+
+ yaffs_flush_whole_cache(dev, 0);
+ yunlock(dev);
+
+ return 0;
+}
+
+static void ryfs_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry);
+
+ ylock(dev);
+ yaffs_flush_whole_cache(dev, 1);
+ yaffs_checkpoint_save(dev);
+ yaffs_deinitialise(dev);
+ yunlock(dev);
+ rtems_yaffs_os_unmount(dev);
+}
+
+static void ryfs_lock(const rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry);
+
+ ylock(dev);
+}
+
+static void ryfs_unlock(const rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry);
+
+ yunlock(dev);
+}
+
+/**
+ * Construct a link from parent/name to target.
+ */
+static int ryfs_symlink(const rtems_filesystem_location_info_t *parent_loc,
+ const char *name,
+ size_t namelen,
+ const char *target)
+{
+ struct yaffs_obj *parent_dir = ryfs_get_object_by_location(parent_loc);
+ struct yaffs_dev *dev = parent_dir->my_dev;
+ uint32_t mode;
+ struct yaffs_obj *created_link;
+ int ret;
+
+ ylock(dev);
+
+ mode = S_IFLNK |
+ ((S_IRWXU | S_IRWXG | S_IRWXO) & ~rtems_filesystem_umask);
+
+ created_link = yaffs_create_symlink(parent_dir, name, mode,
+ geteuid(), getegid(), target);
+
+ if (created_link != NULL) {
+ ret = 0;
+ } else {
+ errno = EINVAL;
+ ret = -1;
+ }
+
+ yunlock(dev);
+ return ret;
+}
+
+/**
+ * Read the target name of a symbolic link. Interpretation of the path name is
+ * up to the caller.
+ *
+ * @param loc The location of the symlink
+ * @param dst_buf A non-NULL pointer to the caller's buffer for the characters.
+ * @param dst_buf_size The size of the caller's buffer in characters.
+ *
+ * @retval -1 An error occurred, the error may be found via errno.
+ * @retval non-negative size of the actual contents in characters, including the
+ * terminating NULL.
+ */
+static ssize_t ryfs_readlink(const rtems_filesystem_location_info_t *loc,
+ char *dst_buf, size_t dst_buf_size)
+{
+ struct yaffs_obj *link = ryfs_get_object_by_location(loc);
+ struct yaffs_dev *dev = link->my_dev;
+
+ ylock(dev);
+ ssize_t chars_copied = -1;
+
+ link = yaffs_get_equivalent_obj(link);
+ if (!link) {
+ errno = EBADF;
+ goto error_locked;
+ }
+
+ if (link->variant_type != YAFFS_OBJECT_TYPE_SYMLINK) {
+ errno = EINVAL;
+ goto error_locked;
+ }
+
+ // Source string length including the terminating NULL.
+ size_t src_buf_size = strlen(link->variant.symlink_variant.alias) + 1;
+ if (src_buf_size > dst_buf_size)
+ src_buf_size = dst_buf_size;
+ memcpy(dst_buf, link->variant.symlink_variant.alias, src_buf_size);
+ chars_copied = src_buf_size;
+
+error_locked:
+ yunlock(dev);
+ return chars_copied;
+}
+
+static const rtems_filesystem_file_handlers_r yaffs_directory_handlers = {
+ .open_h = rtems_filesystem_default_open,
+ .close_h = rtems_filesystem_default_close,
+ .read_h = ryfs_dir_read,
+ .write_h = rtems_filesystem_default_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek_directory,
+ .fstat_h = ryfs_fstat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
+ .fsync_h = ryfs_fsync_or_fdatasync,
+ .fdatasync_h = ryfs_fsync_or_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
+};
+
+static const rtems_filesystem_file_handlers_r yaffs_file_handlers = {
+ .open_h = ryfs_file_open,
+ .close_h = ryfs_file_close,
+ .read_h = ryfs_file_read,
+ .write_h = ryfs_file_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek_file,
+ .fstat_h = ryfs_fstat,
+ .ftruncate_h = ryfs_file_ftruncate,
+ .fsync_h = ryfs_fsync_or_fdatasync,
+ .fdatasync_h = ryfs_fsync_or_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl
+};
+
+static const rtems_filesystem_file_handlers_r yaffs_link_handlers = {
+ .open_h = rtems_filesystem_default_open,
+ .close_h = rtems_filesystem_default_close,
+ .read_h = rtems_filesystem_default_read,
+ .write_h = rtems_filesystem_default_write,
+ .ioctl_h = rtems_filesystem_default_ioctl,
+ .lseek_h = rtems_filesystem_default_lseek_file,
+ .fstat_h = ryfs_fstat,
+ .ftruncate_h = rtems_filesystem_default_ftruncate,
+ .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl,
+};
+
+static const rtems_filesystem_operations_table yaffs_ops = {
+ .lock_h = ryfs_lock,
+ .unlock_h = ryfs_unlock,
+ .eval_path_h = ryfs_eval_path,
+ .link_h = rtems_filesystem_default_link,
+ .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
+ .mknod_h = ryfs_mknod,
+ .rmnod_h = ryfs_rmnod,
+ .fchmod_h = ryfs_fchmod,
+ .chown_h = ryfs_chown,
+ .clonenod_h = rtems_filesystem_default_clonenode,
+ .freenod_h = rtems_filesystem_default_freenode,
+ .mount_h = rtems_filesystem_default_mount,
+ .unmount_h = rtems_filesystem_default_unmount,
+ .fsunmount_me_h = ryfs_fsunmount,
+ .utime_h = ryfs_utime,
+ .symlink_h = ryfs_symlink,
+ .readlink_h = ryfs_readlink,
+ .rename_h = ryfs_rename,
+ .statvfs_h = rtems_filesystem_default_statvfs
+};
--- /dev/null
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (C) 2010 Sebastien Bourdeauducq
+ * Copyright (C) 2011 Stephan Hoffmann <sho@reLinux.de>
+ * Copyright (C) 2011 embedded brains GmbH <rtems@embedded-brains.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * As a special exception, including this header in a file does not by
+ * itself cause the resulting executable application to be covered by the
+ * GNU General Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#ifndef __RTEMS_YAFFS_H
+#define __RTEMS_YAFFS_H
+
+#include <rtems.h>
+#include <rtems/fs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Must be inside the extern "C" */
+#include "yportenv.h"
+#include "yaffs_guts.h"
+
+/**
+ * @defgroup rtems_yaffs YAFFS Support for RTEMS
+ *
+ *
+ * @{
+ */
+
+#define RTEMS_FILESYSTEM_TYPE_YAFFS "yaffs"
+
+typedef void (*rtems_yaffs_os_handler)(
+ struct yaffs_dev *dev,
+ void *os_context
+);
+
+/**
+ * @brief Per YAFFS file system instance context.
+ */
+typedef struct {
+ rtems_yaffs_os_handler lock;
+ rtems_yaffs_os_handler unlock;
+ rtems_yaffs_os_handler unmount;
+
+ /**
+ * @brief The device containing the file system instance.
+ *
+ * This will be used for the st_dev field in stat().
+ */
+ dev_t dev;
+} rtems_yaffs_os_context;
+
+/**
+ * @brief Default per YAFFS file system instance context.
+ */
+typedef struct {
+ rtems_yaffs_os_context os_context;
+ rtems_id semaphore_id;
+} rtems_yaffs_default_os_context;
+
+/**
+ * @brief Data for YAFFS mount handler.
+ *
+ * @see rtems_yaffs_mount_handler()
+ */
+typedef struct {
+ /**
+ * @brief YAFFS device of the file system instance.
+ *
+ * The @a param field has to be completely set up. The
+ * @a driver_context can point to arbitrary driver specific
+ * information. The @a os_context must point to an initialized
+ * structure that begins with a rtems_yaffs_os_context structure.
+ */
+ struct yaffs_dev *dev;
+} rtems_yaffs_mount_data;
+
+/**
+ * @brief YAFFS mount handler.
+ *
+ * The @a data pointer must point to a completely initialized
+ * rtems_yaffs_mount_data structure. The ownership of the YAFFS device
+ * structure changes. This structure is now owned by the file system layer.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occurred. The @c errno indicates the error.
+ */
+int rtems_yaffs_mount_handler(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ const void *data
+);
+
+/**
+ * @brief Initializes the default per file system context @a os_context.
+ *
+ * A binary semaphore with priority inheritance will be used to ensure mutual
+ * exclusion.
+ *
+ * The umount handler will release all resources of the default context.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occurred. The @c errno indicates the error.
+ */
+int rtems_yaffs_initialize_default_os_context(
+ rtems_yaffs_default_os_context *os_context
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __RTEMS_YAFFS_H */
--- /dev/null
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (c) 2011 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * As a special exception, linking other files with the object code from
+ * this one to produce an executable application does not by itself cause
+ * the resulting executable application to be covered by the GNU General
+ * Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#include "rtems_yaffs.h"
+
+#include <assert.h>
+#include <errno.h>
+
+static void rtems_yaffs_default_lock(struct yaffs_dev *dev, void *arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_yaffs_default_os_context *os_context = arg;
+
+ sc = rtems_semaphore_obtain(
+ os_context->semaphore_id,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT
+ );
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void rtems_yaffs_default_unlock(struct yaffs_dev *dev, void *arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_yaffs_default_os_context *os_context = arg;
+
+ sc = rtems_semaphore_release(os_context->semaphore_id);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void rtems_yaffs_default_unmount(struct yaffs_dev *dev, void *arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_yaffs_default_os_context *os_context = arg;
+
+ sc = rtems_semaphore_delete(os_context->semaphore_id);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+int rtems_yaffs_initialize_default_os_context(
+ rtems_yaffs_default_os_context *os_context
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ os_context->os_context.lock = rtems_yaffs_default_lock;
+ os_context->os_context.unlock = rtems_yaffs_default_unlock;
+ os_context->os_context.unmount = rtems_yaffs_default_unmount;
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('Y', 'A', 'F', 'S'),
+ 1,
+ RTEMS_LOCAL
+ | RTEMS_BINARY_SEMAPHORE
+ | RTEMS_INHERIT_PRIORITY
+ | RTEMS_PRIORITY,
+ 0,
+ &os_context->semaphore_id
+ );
+ if (sc == RTEMS_SUCCESSFUL) {
+ return 0;
+ } else {
+ errno = ENOMEM;
+
+ return -1;
+ }
+}
--- /dev/null
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ * Copyright (C) 2011 Stephan Hoffmann <sho@reLinux.de>
+ * Copyright (C) 2011 embedded brains GmbH <rtems@embedded-brains.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * As a special exception, linking other files with the object code from
+ * this one to produce an executable application does not by itself cause
+ * the resulting executable application to be covered by the GNU General
+ * Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+
+#include "yaffs_trace.h"
+#include "yaffs_osglue.h"
+
+unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS;
+
+unsigned int yaffs_wr_attempts;
+
+void *yaffsfs_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+void yaffsfs_free(void *ptr)
+{
+ free(ptr);
+}
+
+YTIME_T yaffsfs_CurrentTime(void)
+{
+ return time(NULL);
+}
{
obj->yst_uid = oh->yst_uid;
obj->yst_gid = oh->yst_gid;
- obj->yst_atime = oh->yst_atime;
- obj->yst_mtime = oh->yst_mtime;
- obj->yst_ctime = oh->yst_ctime;
+
+ obj->yst_ctime = yaffs_oh_ctime_fetch(oh);
+ obj->yst_mtime = yaffs_oh_mtime_fetch(oh);
+ obj->yst_atime = yaffs_oh_atime_fetch(oh);
+
obj->yst_rdev = oh->yst_rdev;
}
{
oh->yst_uid = obj->yst_uid;
oh->yst_gid = obj->yst_gid;
- oh->yst_atime = obj->yst_atime;
- oh->yst_mtime = obj->yst_mtime;
- oh->yst_ctime = obj->yst_ctime;
+
+ yaffs_oh_ctime_load(obj, oh);
+ yaffs_oh_mtime_load(obj, oh);
+ yaffs_oh_atime_load(obj, oh);
+
oh->yst_rdev = obj->yst_rdev;
}
yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
return YAFFS_OK;
-
}
int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2018 Aleph One Ltd.
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "yaffs_cache.h"
+
+/*------------------------ Short Operations Cache ------------------------------
+ * In many situations where there is no high level buffering a lot of
+ * reads might be short sequential reads, and a lot of writes may be short
+ * sequential writes. eg. scanning/writing a jpeg file.
+ * In these cases, a short read/write cache can provide a huge perfomance
+ * benefit with dumb-as-a-rock code.
+ * In Linux, the page cache provides read buffering and the short op cache
+ * provides write buffering.
+ *
+ * There are a small number (~10) of cache chunks per device so that we don't
+ * need a very intelligent search.
+ */
+
+int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
+{
+ struct yaffs_dev *dev = obj->my_dev;
+ int i;
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+
+ for (i = 0; i < mgr->n_caches; i++) {
+ struct yaffs_cache *cache = &mgr->cache[i];
+
+ if (cache->object == obj && cache->dirty)
+ return 1;
+ }
+
+ return 0;
+}
+
+void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard)
+{
+
+ if (!cache || cache->locked)
+ return;
+
+ /* Write it out and free it up if need be.*/
+ if (cache->dirty) {
+ yaffs_wr_data_obj(cache->object,
+ cache->chunk_id,
+ cache->data,
+ cache->n_bytes,
+ 1);
+
+ cache->dirty = 0;
+ }
+
+ if (discard)
+ cache->object = NULL;
+}
+
+void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard)
+{
+ struct yaffs_dev *dev = obj->my_dev;
+ int i;
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+
+ if (mgr->n_caches < 1)
+ return;
+
+
+ /* Find the chunks for this object and flush them. */
+ for (i = 0; i < mgr->n_caches; i++) {
+ struct yaffs_cache *cache = &mgr->cache[i];
+
+ if (cache->object == obj)
+ yaffs_flush_single_cache(cache, discard);
+ }
+
+}
+
+
+void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard)
+{
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+ struct yaffs_obj *obj;
+ int i;
+
+ /* Find a dirty object in the cache and flush it...
+ * until there are no further dirty objects.
+ */
+ do {
+ obj = NULL;
+ for (i = 0; i < mgr->n_caches && !obj; i++) {
+ struct yaffs_cache *cache = &mgr->cache[i];
+ if (cache->object && cache->dirty)
+ obj = cache->object;
+ }
+ if (obj)
+ yaffs_flush_file_cache(obj, discard);
+ } while (obj);
+
+}
+
+/* Grab us an unused cache chunk for use.
+ * First look for an empty one.
+ * Then look for the least recently used non-dirty one.
+ * Then look for the least recently used dirty one...., flush and look again.
+ */
+static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
+{
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+ int i;
+
+ for (i = 0; i < mgr->n_caches; i++) {
+ struct yaffs_cache *cache = &mgr->cache[i];
+ if (!cache->object)
+ return cache;
+ }
+
+ return NULL;
+}
+
+struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
+{
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+ struct yaffs_cache *cache;
+ int usage;
+ int i;
+
+ if (mgr->n_caches < 1)
+ return NULL;
+
+ /* First look for an unused cache */
+
+ cache = yaffs_grab_chunk_worker(dev);
+
+ if (cache)
+ return cache;
+
+ /*
+ * Thery were all in use.
+ * Find the LRU cache and flush it if it is dirty.
+ */
+
+ usage = -1;
+ cache = NULL;
+
+ for (i = 0; i < mgr->n_caches; i++) {
+ struct yaffs_cache *this_cache = &mgr->cache[i];
+
+ if (this_cache->object &&
+ !this_cache->locked &&
+ (this_cache->last_use < usage || !cache)) {
+ usage = this_cache->last_use;
+ cache = this_cache;
+ }
+ }
+
+#if 1
+ yaffs_flush_single_cache(cache, 1);
+#else
+ yaffs_flush_file_cache(cache->object, 1);
+ cache = yaffs_grab_chunk_worker(dev);
+#endif
+
+ return cache;
+}
+
+/* Find a cached chunk */
+struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
+ int chunk_id)
+{
+ struct yaffs_dev *dev = obj->my_dev;
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+ int i;
+
+ if (mgr->n_caches < 1)
+ return NULL;
+
+ for (i = 0; i < mgr->n_caches; i++) {
+ struct yaffs_cache *cache = &mgr->cache[i];
+
+ if (cache->object == obj &&
+ cache->chunk_id == chunk_id) {
+ dev->cache_hits++;
+ return cache;
+ }
+ }
+ return NULL;
+}
+
+/* Mark the chunk for the least recently used algorithym */
+void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
+ int is_write)
+{
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+ int i;
+
+ if (mgr->n_caches < 1)
+ return;
+
+ if (mgr->cache_last_use < 0 ||
+ mgr->cache_last_use > 100000000) {
+ /* Reset the cache usages */
+ for (i = 1; i < mgr->n_caches; i++)
+ mgr->cache[i].last_use = 0;
+
+ mgr->cache_last_use = 0;
+ }
+ mgr->cache_last_use++;
+ cache->last_use = mgr->cache_last_use;
+
+ if (is_write)
+ cache->dirty = 1;
+}
+
+/* Invalidate a single cache page.
+ * Do this when a whole page gets written,
+ * ie the short cache for this page is no longer valid.
+ */
+void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id)
+{
+ struct yaffs_cache *cache;
+
+ cache = yaffs_find_chunk_cache(object, chunk_id);
+ if (cache)
+ cache->object = NULL;
+}
+
+/* Invalidate all the cache pages associated with this object
+ * Do this whenever the file is deleted or resized.
+ */
+void yaffs_invalidate_file_cache(struct yaffs_obj *in)
+{
+ int i;
+ struct yaffs_dev *dev = in->my_dev;
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+
+ /* Invalidate it. */
+ for (i = 0; i < mgr->n_caches; i++) {
+ struct yaffs_cache *cache = &mgr->cache[i];
+
+ if (cache->object == in)
+ cache->object = NULL;
+ }
+}
+
+int yaffs_count_dirty_caches(struct yaffs_dev *dev)
+{
+ int n_dirty;
+ int i;
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+
+ for (n_dirty= 0, i = 0; i < mgr->n_caches; i++) {
+ if (mgr->cache[i].dirty)
+ n_dirty++;
+ }
+
+ return n_dirty;
+}
+
+int yaffs_cache_init(struct yaffs_dev *dev)
+{
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+ int init_failed = 0;
+
+ if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES)
+ dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES;
+
+ mgr->n_caches = dev->param.n_caches;
+ if (mgr->n_caches > 0) {
+ int i;
+ void *buf;
+ u32 cache_bytes =
+ mgr->n_caches * sizeof(struct yaffs_cache);
+
+
+
+ mgr->cache = kmalloc(cache_bytes, GFP_NOFS);
+
+ buf = (u8 *) mgr->cache;
+
+ if (mgr->cache)
+ memset(mgr->cache, 0, cache_bytes);
+
+ for (i = 0; i < mgr->n_caches && buf; i++) {
+ struct yaffs_cache *cache = &mgr->cache[i];
+
+ cache->object = NULL;
+ cache->last_use = 0;
+ cache->dirty = 0;
+ cache->data = buf =
+ kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
+ }
+ if (!buf)
+ init_failed = 1;
+
+ mgr->cache_last_use = 0;
+ }
+
+ return init_failed ? -1 : 0;
+}
+
+void yaffs_cache_deinit(struct yaffs_dev *dev)
+{
+ struct yaffs_cache_manager *mgr = &dev->cache_mgr;
+ int i;
+
+ if (mgr->n_caches < 1 || !mgr->cache)
+ return;
+
+ for (i = 0; i < mgr->n_caches; i++) {
+
+ struct yaffs_cache *cache = &mgr->cache[i];
+ kfree(cache->data);
+ cache->data = NULL;
+ }
+
+ kfree(mgr->cache);
+ mgr->cache = NULL;
+}
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2018 Aleph One Ltd.
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __YAFFS_CACHE_H__
+#define __YAFFS_CACHE_H__
+
+#include "yaffs_guts.h"
+
+
+/* Does the object have a dirty cache ? */
+int yaffs_obj_cache_dirty(struct yaffs_obj *obj);
+
+/* Flush the cache associated with a file, either discarding or keeping */
+void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard);
+
+/* Flush everything in the cache, either discarding or keeping */
+void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard);
+
+/* Grab a cache item during read or write. */
+struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev);
+
+/* Find a cached chunk */
+struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
+ int chunk_id);
+
+/* Mark the chunk for the least recently used algorithym */
+void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
+ int is_write);
+
+
+/* Invalidate a single cache page. The cache no longer holds valid data. */
+void yaffs_invalidate_chunk_cache(struct yaffs_obj *object,
+ int chunk_id);
+
+/* Invalidate all the cache pages associated with this object
+ * Do this whenever ther file is deleted or resized.
+ */
+void yaffs_invalidate_file_cache(struct yaffs_obj *in);
+
+
+int yaffs_count_dirty_caches(struct yaffs_dev *dev);
+
+/* Init/deinit. */
+int yaffs_cache_init(struct yaffs_dev *dev);
+void yaffs_cache_deinit(struct yaffs_dev *dev);
+
+#endif
if (dev->checkpt_open_write) {
if (dev->checkpt_byte_offs !=
- sizeof(sizeof(struct yaffs_checkpt_chunk_hdr)))
+ sizeof(struct yaffs_checkpt_chunk_hdr))
yaffs2_checkpt_flush_buffer(dev);
} else if (dev->checkpt_block_list) {
for (i = 0;
((val <<24) & 0xff000000);
}
+static inline u64 swap_u64(u64 val)
+{
+ return ((val >> 56) & 0x00000000000000ff) |
+ ((val >> 40) & 0x000000000000ff00) |
+ ((val >> 24) & 0x0000000000ff0000) |
+ ((val >> 8) & 0x00000000ff000000) |
+ ((val << 8) & 0x000000ff00000000) |
+ ((val << 24) & 0x0000ff0000000000) |
+ ((val << 40) & 0x00ff000000000000) |
+ ((val << 56) & 0xff00000000000000);
+}
+
+static inline YTIME_T swap_ytime_t(YTIME_T val)
+{
+
+ if (sizeof(YTIME_T) == sizeof(u64))
+ return swap_u64(val);
+ else
+ return swap_u32(val);
+}
+
+//swap a signed 32 bit integer.
#define swap_s32(val) \
(s32)(swap_u32((u32)(val)))
#include "yaffs_trace.h"
#include "yaffs_guts.h"
+
+#include "yaffs_cache.h"
#include "yaffs_endian.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_tagscompat.h"
/* Forward declarations */
-static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
- const u8 *buffer, int n_bytes, int use_reserve);
-
static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
int buffer_size);
}
+/* Frees all the temp_buffer objects in the yaffs_dev instance
+*/
void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer)
{
int i;
return YAFFS_FAIL;
}
-/*------------------------ Short Operations Cache ------------------------------
- * In many situations where there is no high level buffering a lot of
- * reads might be short sequential reads, and a lot of writes may be short
- * sequential writes. eg. scanning/writing a jpeg file.
- * In these cases, a short read/write cache can provide a huge perfomance
- * benefit with dumb-as-a-rock code.
- * In Linux, the page cache provides read buffering and the short op cache
- * provides write buffering.
- *
- * There are a small number (~10) of cache chunks per device so that we don't
- * need a very intelligent search.
- */
-
-static int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
-{
- struct yaffs_dev *dev = obj->my_dev;
- int i;
- struct yaffs_cache *cache;
- int n_caches = obj->my_dev->param.n_caches;
-
- for (i = 0; i < n_caches; i++) {
- cache = &dev->cache[i];
- if (cache->object == obj && cache->dirty)
- return 1;
- }
-
- return 0;
-}
-
-static void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard)
-{
-
- if (!cache || cache->locked)
- return;
-
- /* Write it out and free it up if need be.*/
- if (cache->dirty) {
- yaffs_wr_data_obj(cache->object,
- cache->chunk_id,
- cache->data,
- cache->n_bytes,
- 1);
-
- cache->dirty = 0;
- }
-
- if (discard)
- cache->object = NULL;
-}
-
-static void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard)
-{
- struct yaffs_dev *dev = obj->my_dev;
- int i;
- struct yaffs_cache *cache;
- int n_caches = obj->my_dev->param.n_caches;
-
- if (n_caches < 1)
- return;
-
-
- /* Find the chunks for this object and flush them. */
- for (i = 0; i < n_caches; i++) {
- cache = &dev->cache[i];
- if (cache->object == obj)
- yaffs_flush_single_cache(cache, discard);
- }
-
-}
-
-
-void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard)
-{
- struct yaffs_obj *obj;
- int n_caches = dev->param.n_caches;
- int i;
-
- /* Find a dirty object in the cache and flush it...
- * until there are no further dirty objects.
- */
- do {
- obj = NULL;
- for (i = 0; i < n_caches && !obj; i++) {
- if (dev->cache[i].object && dev->cache[i].dirty)
- obj = dev->cache[i].object;
- }
- if (obj)
- yaffs_flush_file_cache(obj, discard);
- } while (obj);
-
-}
-
-/* Grab us an unused cache chunk for use.
- * First look for an empty one.
- * Then look for the least recently used non-dirty one.
- * Then look for the least recently used dirty one...., flush and look again.
- */
-static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
-{
- u32 i;
-
- if (dev->param.n_caches > 0) {
- for (i = 0; i < dev->param.n_caches; i++) {
- if (!dev->cache[i].object)
- return &dev->cache[i];
- }
- }
-
- return NULL;
-}
-
-static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
-{
- struct yaffs_cache *cache;
- int usage;
- u32 i;
-
- if (dev->param.n_caches < 1)
- return NULL;
-
- /* First look for an unused cache */
-
- cache = yaffs_grab_chunk_worker(dev);
-
- if (cache)
- return cache;
-
- /*
- * Thery were all in use.
- * Find the LRU cache and flush it if it is dirty.
- */
-
- usage = -1;
- cache = NULL;
-
- for (i = 0; i < dev->param.n_caches; i++) {
- if (dev->cache[i].object &&
- !dev->cache[i].locked &&
- (dev->cache[i].last_use < usage || !cache)) {
- usage = dev->cache[i].last_use;
- cache = &dev->cache[i];
- }
- }
-
-#if 1
- yaffs_flush_single_cache(cache, 1);
-#else
- yaffs_flush_file_cache(cache->object, 1);
- cache = yaffs_grab_chunk_worker(dev);
-#endif
-
- return cache;
-}
-
-/* Find a cached chunk */
-static struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
- int chunk_id)
-{
- struct yaffs_dev *dev = obj->my_dev;
- u32 i;
-
- if (dev->param.n_caches < 1)
- return NULL;
-
- for (i = 0; i < dev->param.n_caches; i++) {
- if (dev->cache[i].object == obj &&
- dev->cache[i].chunk_id == chunk_id) {
- dev->cache_hits++;
-
- return &dev->cache[i];
- }
- }
- return NULL;
-}
-
-/* Mark the chunk for the least recently used algorithym */
-static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
- int is_write)
-{
- u32 i;
-
- if (dev->param.n_caches < 1)
- return;
-
- if (dev->cache_last_use < 0 ||
- dev->cache_last_use > 100000000) {
- /* Reset the cache usages */
- for (i = 1; i < dev->param.n_caches; i++)
- dev->cache[i].last_use = 0;
-
- dev->cache_last_use = 0;
- }
- dev->cache_last_use++;
- cache->last_use = dev->cache_last_use;
-
- if (is_write)
- cache->dirty = 1;
-}
-
-/* Invalidate a single cache page.
- * Do this when a whole page gets written,
- * ie the short cache for this page is no longer valid.
- */
-static void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id)
-{
- struct yaffs_cache *cache;
-
- if (object->my_dev->param.n_caches > 0) {
- cache = yaffs_find_chunk_cache(object, chunk_id);
-
- if (cache)
- cache->object = NULL;
- }
-}
-
-/* Invalidate all the cache pages associated with this object
- * Do this whenever ther file is deleted or resized.
- */
-static void yaffs_invalidate_whole_cache(struct yaffs_obj *in)
-{
- u32 i;
- struct yaffs_dev *dev = in->my_dev;
-
- if (dev->param.n_caches > 0) {
- /* Invalidate it. */
- for (i = 0; i < dev->param.n_caches; i++) {
- if (dev->cache[i].object == in)
- dev->cache[i].object = NULL;
- }
- }
-}
static void yaffs_unhash_obj(struct yaffs_obj *obj)
{
static int yaffs_generic_obj_del(struct yaffs_obj *in)
{
/* Iinvalidate the file's data in the cache, without flushing. */
- yaffs_invalidate_whole_cache(in);
+ yaffs_invalidate_file_cache(in);
if (in->my_dev->param.is_yaffs2 && in->parent != in->my_dev->del_dir) {
/* Move to unlinked directory so we have a deletion record */
int prioritised = 0;
int prioritised_exist = 0;
struct yaffs_block_info *bi;
- u32 threshold;
+ u32 threshold = dev->param.chunks_per_block;
+
+ (void) prioritised;
/* First let's see if we need to grab a prioritised block */
if (dev->has_pending_prioritised_gc && !aggressive) {
{
int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;
+ (void) urgency;
yaffs_trace(YAFFS_TRACE_BACKGROUND, "Background gc %u", urgency);
yaffs_check_gc(dev, 1);
struct yaffs_ext_tags tags;
struct yaffs_block_info *bi;
+ (void) lyn;
if (chunk_id <= 0)
return;
}
}
-static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
- const u8 *buffer, int n_bytes, int use_reserve)
+int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
+ const u8 *buffer, int n_bytes, int use_reserve)
{
/* Find old chunk Need to do this to get serial number
* Write new one and patch into tree.
result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
- if (result == YAFFS_FAIL)
+ if (result == YAFFS_FAIL) {
+ yaffs_release_temp_buffer(dev, buf);
return;
+ }
oh = (struct yaffs_obj_hdr *)buf;
bi->has_shrink_hdr = 1;
}
-
return new_chunk_id;
}
loff_t old_size = in->variant.file_variant.file_size;
yaffs_flush_file_cache(in, 1);
- yaffs_invalidate_whole_cache(in);
+ yaffs_invalidate_file_cache(in);
yaffs_check_gc(dev, 0);
return YAFFS_FAIL;
}
+ if (!yaffs_init_tmp_buffers(dev))
+ return YAFFS_FAIL;
+
if (yaffs_init_nand(dev) != YAFFS_OK) {
yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed");
return YAFFS_FAIL;
}
+ dev->ll_init = 1;
+
return YAFFS_OK;
}
return YAFFS_OK;
}
+/*
+ * If the dev is mounted r/w then the cleanup will happen during
+ * yaffs_guts_initialise. However if the dev is mounted ro then
+ * the cleanup will be dfered until yaffs is remounted r/w.
+ */
+void yaffs_guts_cleanup(struct yaffs_dev *dev)
+{
+ yaffs_strip_deleted_objs(dev);
+ yaffs_fix_hanging_objs(dev);
+ if (dev->param.empty_lost_n_found)
+ yaffs_empty_l_n_f(dev);
+}
int yaffs_guts_initialise(struct yaffs_dev *dev)
{
yaffs_endian_config(dev);
- /* Initialise temporary buffers and caches. */
- if (!yaffs_init_tmp_buffers(dev))
- init_failed = 1;
-
- dev->cache = NULL;
+ /* Initialise temporary caches. */
dev->gc_cleanup_list = NULL;
- if (!init_failed && dev->param.n_caches > 0) {
- u32 i;
- void *buf;
- u32 cache_bytes =
- dev->param.n_caches * sizeof(struct yaffs_cache);
-
- if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES)
- dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES;
-
- dev->cache = kmalloc(cache_bytes, GFP_NOFS);
-
- buf = (u8 *) dev->cache;
-
- if (dev->cache)
- memset(dev->cache, 0, cache_bytes);
-
- for (i = 0; i < dev->param.n_caches && buf; i++) {
- dev->cache[i].object = NULL;
- dev->cache[i].last_use = 0;
- dev->cache[i].dirty = 0;
- dev->cache[i].data = buf =
- kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
- }
- if (!buf)
- init_failed = 1;
-
- dev->cache_last_use = 0;
- }
+ if (!init_failed)
+ init_failed = yaffs_cache_init(dev) < 0;
dev->cache_hits = 0;
init_failed = 1;
}
- yaffs_strip_deleted_objs(dev);
- yaffs_fix_hanging_objs(dev);
- if (dev->param.empty_lost_n_found)
- yaffs_empty_l_n_f(dev);
+ yaffs_guts_cleanup(dev);
}
if (init_failed) {
yaffs_deinit_blocks(dev);
yaffs_deinit_tnodes_and_objs(dev);
yaffs_summary_deinit(dev);
-
- if (dev->param.n_caches > 0 && dev->cache) {
-
- for (i = 0; i < dev->param.n_caches; i++) {
- kfree(dev->cache[i].data);
- dev->cache[i].data = NULL;
- }
-
- kfree(dev->cache);
- dev->cache = NULL;
- }
+ yaffs_cache_deinit(dev);
kfree(dev->gc_cleanup_list);
kfree(dev->checkpt_block_list);
dev->checkpt_block_list = NULL;
+ dev->ll_init = 0;
dev->is_mounted = 0;
yaffs_deinit_nand(dev);
int n_free;
int n_dirty_caches;
int blocks_for_checkpt;
- u32 i;
n_free = dev->n_free_chunks;
n_free += dev->n_deleted_files;
/* Now count and subtract the number of dirty chunks in the cache. */
-
- for (n_dirty_caches = 0, i = 0; i < dev->param.n_caches; i++) {
- if (dev->cache[i].dirty)
- n_dirty_caches++;
- }
-
+ n_dirty_caches = yaffs_count_dirty_caches(dev);
n_free -= n_dirty_caches;
n_free -=
return n_free;
}
+/*
+ * Marshalling functions to get the appropriate time values saved
+ * and restored to/from obj headers.
+ *
+ * Note that the WinCE time fields are used to store the 32-bit values.
+ */
+
+static void yaffs_oh_time_load(u32 *yst_time, u32 *win_time, YTIME_T timeval)
+{
+ u32 upper;
+ u32 lower;
+
+ lower = timeval & 0xffffffff;
+ /* we have to use #defines here insted of an if statement
+ otherwise the compiler throws an error saying that
+ right shift count >= width of type when we are using 32 bit time.
+ */
+ #ifdef CONFIG_YAFFS_USE_32_BIT_TIME_T
+ upper = 0;
+ #else
+ upper = (timeval >> 32) & 0xffffffff;
+ #endif
+
+ *yst_time = lower;
+ win_time[0] = lower;
+ win_time[1] = upper;
+}
+
+static YTIME_T yaffs_oh_time_fetch(const u32 *yst_time, const u32 *win_time)
+{
+ u32 upper;
+ u32 lower;
+
+ if (win_time[1] == 0xffffffff) {
+ upper = 0;
+ lower = *yst_time;
+ } else {
+ upper = win_time[1];
+ lower = win_time[0];
+ }
+ if (sizeof(YTIME_T) > sizeof(u32)) {
+ u64 ret;
+ ret = (((u64)upper) << 32) | lower;
+ return (YTIME_T) ret;
+
+ } else
+ return (YTIME_T) lower;
+}
+
+YTIME_T yaffs_oh_ctime_fetch(struct yaffs_obj_hdr *oh)
+{
+ return yaffs_oh_time_fetch(&oh->yst_ctime, oh->win_ctime);
+}
+
+YTIME_T yaffs_oh_mtime_fetch(struct yaffs_obj_hdr *oh)
+{
+ return yaffs_oh_time_fetch(&oh->yst_mtime, oh->win_mtime);
+}
+
+YTIME_T yaffs_oh_atime_fetch(struct yaffs_obj_hdr *oh)
+{
+ return yaffs_oh_time_fetch(&oh->yst_atime, oh->win_atime);
+}
+
+void yaffs_oh_ctime_load(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
+{
+ yaffs_oh_time_load(&oh->yst_ctime, oh->win_ctime, obj->yst_ctime);
+}
+
+void yaffs_oh_mtime_load(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
+{
+ yaffs_oh_time_load(&oh->yst_mtime, oh->win_mtime, obj->yst_mtime);
+}
+
+void yaffs_oh_atime_load(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
+{
+ yaffs_oh_time_load(&oh->yst_atime, oh->win_atime, obj->yst_atime);
+}
+
/*
* Marshalling functions to get loff_t file sizes into and out of
/* Special sequence number for bad block that failed to be marked bad */
#define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000
-/* ChunkCache is used for short read/write operations.*/
+/* Chunk cache is used for short read/write operations.*/
struct yaffs_cache {
struct yaffs_obj *object;
int chunk_id;
u8 *data;
};
+struct yaffs_cache_manager {
+ struct yaffs_cache *cache;
+ int n_caches;
+ int cache_last_use;
+ int n_temp_buffers;
+};
+
/* yaffs1 tags structures in RAM
* NB This uses bitfield. Bitfields should not straddle a u32 boundary
* otherwise the structure size will get blown out.
u32 yst_rdev; /* stuff for block and char devices (major/min) */
+ /*
+ * WinCE times are no longer just used to store WinCE times.
+ * They are also used to store 64-bit times.
+ * We actually store and read the times in both places and use
+ * the best we can.
+ */
u32 win_ctime[2];
u32 win_atime[2];
u32 win_mtime[2];
YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1];
#ifdef CONFIG_YAFFS_WINCE
+ //these are always 64 bits
u32 win_ctime[2];
u32 win_mtime[2];
u32 win_atime[2];
#else
- u32 yst_uid;
- u32 yst_gid;
- u32 yst_atime;
- u32 yst_mtime;
- u32 yst_ctime;
+ //these can be 32 or 64 bits
+ YTIME_T yst_uid;
+ YTIME_T yst_gid;
+ YTIME_T yst_atime;
+ YTIME_T yst_mtime;
+ YTIME_T yst_ctime;
#endif
u32 yst_rdev;
int buffered_block; /* Which block is buffered here? */
int doing_buffered_block_rewrite;
- struct yaffs_cache *cache;
- int cache_last_use;
+ struct yaffs_cache_manager cache_mgr;
/* Stuff for background deletion and unlinked files. */
struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted
int yaffs_guts_initialise(struct yaffs_dev *dev);
void yaffs_deinitialise(struct yaffs_dev *dev);
+void yaffs_guts_cleanup(struct yaffs_dev *dev);
int yaffs_get_n_free_chunks(struct yaffs_dev *dev);
int do_endian);
loff_t yaffs_max_file_size(struct yaffs_dev *dev);
+
+/* yaffs_wr_data_obj needs to be exposed to allow the cache to access it. */
+int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
+ const u8 *buffer, int n_bytes, int use_reserve);
+
/*
* Debug function to count number of blocks in each state
* NB Needs to be called with correct number of integers
int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
struct yaffs_ext_tags *tags);
+/*
+ *Time marshalling functions
+ */
+
+YTIME_T yaffs_oh_ctime_fetch(struct yaffs_obj_hdr *oh);
+YTIME_T yaffs_oh_mtime_fetch(struct yaffs_obj_hdr *oh);
+YTIME_T yaffs_oh_atime_fetch(struct yaffs_obj_hdr *oh);
+
+void yaffs_oh_ctime_load(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
+void yaffs_oh_mtime_load(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
+void yaffs_oh_atime_load(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
+
/*
* Define LOFF_T_32_BIT if a 32-bit LOFF_T is being used.
* Not serious if you get this wrong - you might just get some warnings.
static void yaffs_dump_packed_tags2_tags_only(
const struct yaffs_packed_tags2_tags_only *ptt)
{
+ (void) ptt;
+
yaffs_trace(YAFFS_TRACE_MTD,
"packed tags obj %d chunk %d byte %d seq %d",
ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number);
static void yaffs_dump_tags2(const struct yaffs_ext_tags *t)
{
+
+ (void) t;
yaffs_trace(YAFFS_TRACE_MTD,
"ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d",
t->ecc_result, t->block_bad, t->chunk_used, t->obj_id,
* tags storage.
*/
-#include "yaffs_guts.h"
+#include "yaffs_tagsmarshall.h"
#include "yaffs_trace.h"
#include "yaffs_packedtags2.h"
BUG();
- if (retval == YAFFS_FAIL)
+ if (retval == YAFFS_FAIL) {
+ if (local_data)
+ yaffs_release_temp_buffer(dev, data);
+
return YAFFS_FAIL;
+ }
if (dev->param.inband_tags) {
if (tags) {
"block query returns seq %d state %d",
*seq_number, *state);
- if (retval == 0)
- return YAFFS_OK;
- else
- return YAFFS_FAIL;
+ return retval;
}
static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no)
}
static const char * const block_state_name[] = {
- "Unknown",
- "Needs scan",
- "Scanning",
- "Empty",
- "Allocating",
- "Full",
- "Dirty",
- "Checkpoint",
- "Collecting",
- "Dead"
+ [YAFFS_BLOCK_STATE_UNKNOWN] = "Unknown",
+ [YAFFS_BLOCK_STATE_NEEDS_SCAN] = "Needs scan",
+ [YAFFS_BLOCK_STATE_SCANNING] = "Scanning",
+ [YAFFS_BLOCK_STATE_EMPTY] = "Empty",
+ [YAFFS_BLOCK_STATE_ALLOCATING] = "Allocating",
+ [YAFFS_BLOCK_STATE_FULL] = "Full",
+ [YAFFS_BLOCK_STATE_DIRTY] = "Dirty",
+ [YAFFS_BLOCK_STATE_CHECKPOINT] = "Checkpoint",
+ [YAFFS_BLOCK_STATE_COLLECTING] = "Collecting",
+ [YAFFS_BLOCK_STATE_DEAD] = "Dead"
};
void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n)
int actually_used;
int in_use;
+ (void) block_state_name;
+
if (yaffs_skip_verification(dev))
return;
goto out;
}
- if (!dir_emit_dots(f, dc)) {
- yaffs_gross_unlock(dev);
- return 0;
- }
+ if (!dir_emit_dots(f, dc))
+ goto out;
curoffs = 1;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
inode->i_rdev = old_decode_dev(obj->yst_rdev);
- inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
+ inode->i_atime.tv_sec = (YTIME_T) (obj->yst_atime);
inode->i_atime.tv_nsec = 0;
- inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
+ inode->i_mtime.tv_sec = (YTIME_T) obj->yst_mtime;
inode->i_mtime.tv_nsec = 0;
- inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
+ inode->i_ctime.tv_sec = (YTIME_T) obj->yst_ctime;
inode->i_ctime.tv_nsec = 0;
#else
inode->i_rdev = obj->yst_rdev;
static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
{
int read_only = 0;
+ int was_read_only = 0;
struct mtd_info *mtd;
struct yaffs_dev *dev = 0;
}
dev = sb->s_fs_info;
+ was_read_only = dev->read_only;
dev->read_only = read_only;
+ if (was_read_only && !read_only) {
+ yaffs_gross_lock(dev);
+ yaffs_guts_cleanup(dev);
+ yaffs_gross_unlock(dev);
+ yaffs_bg_start(dev);
+ } else if (!was_read_only && read_only) {
+ yaffs_bg_stop(dev);
+ }
+
return 0;
}
.open = yaffs_proc_open,
.read = seq_read,
.write = yaffs_proc_write,
+ .release = single_release,
};
static int yaffs_procfs_init(void)
{
struct inode *iptr;
struct yaffs_obj *obj;
+ struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+ spin_lock(&sb->s_inode_list_lock);
list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
+ spin_lock(&inode->i_lock);
+ if (iptr->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) {
+ spin_unlock(&inode->i_lock);
+ continue;
+ }
+
+ __iget(iptr);
+ spin_unlock(&inode->i_lock);
+ spin_unlock(&sb->s_inode_list_lock);
+
obj = yaffs_inode_to_obj(iptr);
if (obj) {
yaffs_trace(YAFFS_TRACE_OS,
"flushing obj %d", obj->obj_id);
yaffs_flush_file(obj, 1, 0, 0);
}
+
+ yaffs_gross_unlock(dev);
+ iput(iptr);
+ yaffs_gross_lock(dev);
+
+ spin_lock(&sb->s_inode_list_lock);
}
+ spin_unlock(&sb->s_inode_list_lock);
}
static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
inode->i_rdev = old_decode_dev(obj->yst_rdev);
- inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
+ inode->i_atime.tv_sec = (YTIME_T) (obj->yst_atime);
inode->i_atime.tv_nsec = 0;
- inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
+ inode->i_mtime.tv_sec = (YTIME_T) obj->yst_mtime;
inode->i_mtime.tv_nsec = 0;
- inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
+ inode->i_ctime.tv_sec = (YTIME_T) obj->yst_ctime;
inode->i_ctime.tv_nsec = 0;
inode->i_size = yaffs_get_obj_length(obj);
inode->i_blocks = (inode->i_size + 511) >> 9;
int yaffs1_scan(struct yaffs_dev *dev)
{
+#ifdef CONFIG_YAFFS_NO_YAFFS1
+ return YAFFS_FAIL;
+#else
struct yaffs_ext_tags tags;
u32 blk;
int result;
yaffs_trace(YAFFS_TRACE_SCAN, "yaffs1_scan ends");
return YAFFS_OK;
+#endif
}
* dumping them to the checkpointing stream.
*/
+ (void) cp_variant_type;
+
for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) {
list_for_each(lh, &dev->obj_bucket[i].list) {
obj = list_entry(lh, struct yaffs_obj, hash_link);
#define YUCHAR unsigned char
#define _Y(x) x
+#define YTIME_T u64
+
#define YAFFS_LOSTNFOUND_NAME "lost+found"
#define YAFFS_LOSTNFOUND_PREFIX "obj"
#define YCHAR char
#define YUCHAR unsigned char
#define _Y(x) x
+#define YTIME_T u64
+
#define YAFFS_LOSTNFOUND_NAME "lost+found"
#define YAFFS_LOSTNFOUND_PREFIX "obj"