From 29d11a6d0d45c60498506003bdcd9e4b5b969472 Mon Sep 17 00:00:00 2001 From: yangjie Date: Thu, 11 Mar 2021 16:47:15 +0800 Subject: [PATCH 1/2] [components][dfs] remove jffs2 and uffs --- components/dfs/Kconfig | 37 - components/dfs/filesystems/jffs2/SConscript | 50 - .../filesystems/jffs2/cyg/compress/ChangeLog | 218 -- .../jffs2/cyg/compress/cdl/compress_zlib.cdl | 170 -- .../jffs2/cyg/compress/include/zconf.h | 349 --- .../jffs2/cyg/compress/include/zlib.h | 1358 ---------- .../jffs2/cyg/compress/src/ChangeLog | 854 ------- .../filesystems/jffs2/cyg/compress/src/FAQ | 339 --- .../filesystems/jffs2/cyg/compress/src/INDEX | 51 - .../jffs2/cyg/compress/src/Make_vms.com | 461 ---- .../jffs2/cyg/compress/src/Makefile | 154 -- .../jffs2/cyg/compress/src/Makefile.in | 154 -- .../jffs2/cyg/compress/src/Makefile.riscos | 151 -- .../filesystems/jffs2/cyg/compress/src/README | 125 - .../jffs2/cyg/compress/src/README.eCos | 27 - .../jffs2/cyg/compress/src/adler32.c | 153 -- .../jffs2/cyg/compress/src/algorithm.txt | 209 -- .../jffs2/cyg/compress/src/compress.c | 83 - .../jffs2/cyg/compress/src/configure | 459 ---- .../jffs2/cyg/compress/src/deflate.c | 1736 ------------- .../jffs2/cyg/compress/src/deflate.h | 331 --- .../jffs2/cyg/compress/src/descrip.mms | 48 - .../jffs2/cyg/compress/src/example.c | 565 ----- .../filesystems/jffs2/cyg/compress/src/gzio.c | 1026 -------- .../jffs2/cyg/compress/src/infback.c | 623 ----- .../jffs2/cyg/compress/src/infblock.c | 403 --- .../jffs2/cyg/compress/src/infblock.h | 39 - .../jffs2/cyg/compress/src/inffast.c | 318 --- .../jffs2/cyg/compress/src/inffast.h | 11 - .../jffs2/cyg/compress/src/inffixed.h | 94 - .../jffs2/cyg/compress/src/inflate.c | 1368 ----------- .../jffs2/cyg/compress/src/inflate.h | 115 - .../jffs2/cyg/compress/src/inftrees.c | 329 --- .../jffs2/cyg/compress/src/inftrees.h | 55 - .../jffs2/cyg/compress/src/infutil.c | 87 - .../jffs2/cyg/compress/src/infutil.h | 98 - .../jffs2/cyg/compress/src/maketree.c | 85 - .../jffs2/cyg/compress/src/minigzip.c | 322 --- .../jffs2/cyg/compress/src/trees.c | 1219 --------- .../jffs2/cyg/compress/src/trees.h | 128 - .../jffs2/cyg/compress/src/uncompr.c | 65 - .../filesystems/jffs2/cyg/compress/src/zlib.3 | 159 -- .../jffs2/cyg/compress/src/zutil.c | 318 --- .../jffs2/cyg/compress/src/zutil.h | 276 --- .../jffs2/cyg/compress/tests/zlib1.c | 232 -- .../jffs2/cyg/compress/tests/zlib2.c | 307 --- .../filesystems/jffs2/cyg/compress/zconf.h | 358 --- .../dfs/filesystems/jffs2/cyg/compress/zlib.h | 1358 ---------- .../dfs/filesystems/jffs2/cyg/crc/crc.h | 105 - .../dfs/filesystems/jffs2/cyg/crc/crc16.c | 104 - .../dfs/filesystems/jffs2/cyg/crc/crc32.c | 166 -- .../dfs/filesystems/jffs2/cyg/crc/posix_crc.c | 116 - .../dfs/filesystems/jffs2/cyg/fileio/fileio.h | 489 ---- .../dfs/filesystems/jffs2/cyg/hal/basetype.h | 91 - .../dfs/filesystems/jffs2/cyg/hal/drv_api.h | 250 -- .../filesystems/jffs2/cyg/infra/cyg_type.h | 544 ----- components/dfs/filesystems/jffs2/dfs_jffs2.c | 687 ------ components/dfs/filesystems/jffs2/dfs_jffs2.h | 14 - .../filesystems/jffs2/include/linux/jffs2.h | 229 -- .../jffs2/include/linux/jffs2_fs_i.h | 50 - .../jffs2/include/linux/jffs2_fs_sb.h | 120 - .../filesystems/jffs2/include/port/codes.h | 99 - .../filesystems/jffs2/include/port/fcntl.h | 31 - .../filesystems/jffs2/include/port/sys/stat.h | 294 --- .../jffs2/include/port/sys/types.h | 90 - .../dfs/filesystems/jffs2/jffs2_config.h | 53 - .../dfs/filesystems/jffs2/kernel/asm/atomic.h | 10 - .../dfs/filesystems/jffs2/kernel/asm/bug.h | 6 - .../dfs/filesystems/jffs2/kernel/asm/page.h | 12 - .../filesystems/jffs2/kernel/asm/semaphore.h | 120 - .../dfs/filesystems/jffs2/kernel/linux/TODO | 11 - .../filesystems/jffs2/kernel/linux/compiler.h | 7 - .../jffs2/kernel/linux/completion.h | 13 - .../filesystems/jffs2/kernel/linux/config.h | 12 - .../filesystems/jffs2/kernel/linux/crc32.h | 8 - .../filesystems/jffs2/kernel/linux/errno.h | 2 - .../dfs/filesystems/jffs2/kernel/linux/fs.h | 6 - .../dfs/filesystems/jffs2/kernel/linux/init.h | 3 - .../filesystems/jffs2/kernel/linux/kernel.h | 38 - .../dfs/filesystems/jffs2/kernel/linux/list.h | 147 -- .../jffs2/kernel/linux/mtd/compatmac.h | 5 - .../filesystems/jffs2/kernel/linux/mtd/mtd.h | 5 - .../filesystems/jffs2/kernel/linux/pagemap.h | 19 - .../filesystems/jffs2/kernel/linux/rbtree.h | 62 - .../filesystems/jffs2/kernel/linux/rwsem.h | 20 - .../filesystems/jffs2/kernel/linux/sched.h | 7 - .../dfs/filesystems/jffs2/kernel/linux/slab.h | 14 - .../filesystems/jffs2/kernel/linux/spinlock.h | 43 - .../dfs/filesystems/jffs2/kernel/linux/stat.h | 12 - .../filesystems/jffs2/kernel/linux/string.h | 6 - .../filesystems/jffs2/kernel/linux/timer.h | 15 - .../filesystems/jffs2/kernel/linux/types.h | 9 - .../filesystems/jffs2/kernel/linux/version.h | 6 - .../filesystems/jffs2/kernel/linux/vmalloc.h | 3 - .../dfs/filesystems/jffs2/kernel/linux/wait.h | 21 - .../jffs2/kernel/linux/workqueue.h | 18 - .../dfs/filesystems/jffs2/kernel/linux/zlib.h | 15 - .../filesystems/jffs2/kernel/linux/zutil.h | 6 - .../dfs/filesystems/jffs2/kernel/rbtree.c | 408 ---- components/dfs/filesystems/jffs2/porting.c | 29 - components/dfs/filesystems/jffs2/porting.h | 51 - components/dfs/filesystems/jffs2/src/LICENCE | 35 - components/dfs/filesystems/jffs2/src/build.c | 371 --- components/dfs/filesystems/jffs2/src/compr.c | 457 ---- components/dfs/filesystems/jffs2/src/compr.h | 107 - .../dfs/filesystems/jffs2/src/compr_rtime.c | 156 -- .../dfs/filesystems/jffs2/src/compr_rubin.c | 427 ---- .../dfs/filesystems/jffs2/src/compr_rubin.h | 21 - .../dfs/filesystems/jffs2/src/compr_zlib.c | 246 -- components/dfs/filesystems/jffs2/src/debug.c | 711 ------ components/dfs/filesystems/jffs2/src/debug.h | 276 --- .../dfs/filesystems/jffs2/src/dir-ecos.c | 369 --- components/dfs/filesystems/jffs2/src/dir.txt | 70 - components/dfs/filesystems/jffs2/src/erase.c | 469 ---- .../dfs/filesystems/jffs2/src/flashio.c | 151 -- .../dfs/filesystems/jffs2/src/fs-ecos.c | 2174 ----------------- components/dfs/filesystems/jffs2/src/gc.c | 1271 ---------- .../dfs/filesystems/jffs2/src/gcthread.c | 274 --- components/dfs/filesystems/jffs2/src/histo.h | 3 - .../dfs/filesystems/jffs2/src/histo_mips.h | 2 - .../dfs/filesystems/jffs2/src/malloc-ecos.c | 163 -- .../dfs/filesystems/jffs2/src/nodelist.c | 534 ---- .../dfs/filesystems/jffs2/src/nodelist.h | 415 ---- .../dfs/filesystems/jffs2/src/nodemgmt.c | 680 ------ .../dfs/filesystems/jffs2/src/os-ecos.h | 265 -- .../dfs/filesystems/jffs2/src/os-rtthread.h | 263 -- .../dfs/filesystems/jffs2/src/pushpull.h | 72 - components/dfs/filesystems/jffs2/src/read.c | 223 -- .../dfs/filesystems/jffs2/src/readinode.c | 895 ------- components/dfs/filesystems/jffs2/src/scan.c | 946 ------- components/dfs/filesystems/jffs2/src/write.c | 702 ------ components/dfs/filesystems/uffs/AUTHORS | 1 - .../dfs/filesystems/uffs/CMakeLists.txt | 27 - components/dfs/filesystems/uffs/COPYING | 339 --- components/dfs/filesystems/uffs/Doxyfile | 275 --- components/dfs/filesystems/uffs/README | 275 --- components/dfs/filesystems/uffs/SConscript | 38 - components/dfs/filesystems/uffs/TODO | 5 - components/dfs/filesystems/uffs/dfs_uffs.c | 660 ----- components/dfs/filesystems/uffs/dfs_uffs.h | 89 - .../uffs/doc/Understanding-UFFS.odp | Bin 369408 -> 0 bytes .../uffs/doc/Understanding-UFFS.pdf | Bin 326206 -> 0 bytes .../uffs/doc/uffs-serial-num-relationship.JPG | Bin 26858 -> 0 bytes .../dfs/filesystems/uffs/src/CMakeLists.txt | 7 - .../filesystems/uffs/src/emu/CMakeLists.txt | 24 - .../dfs/filesystems/uffs/src/emu/cmdline.c | 643 ----- .../dfs/filesystems/uffs/src/emu/cmdline.h | 83 - .../filesystems/uffs/src/emu/helper_cmds.c | 694 ------ .../dfs/filesystems/uffs/src/emu/test_cmds.c | 1186 --------- .../filesystems/uffs/src/emu/uffs_fileem.c | 113 - .../filesystems/uffs/src/emu/uffs_fileem.h | 88 - .../uffs/src/emu/uffs_fileem_ecc_hw.c | 236 -- .../uffs/src/emu/uffs_fileem_ecc_hw_auto.c | 356 --- .../uffs/src/emu/uffs_fileem_ecc_soft.c | 212 -- .../uffs/src/emu/uffs_fileem_share.c | 232 -- .../uffs/src/emu/uffs_fileem_wrap.c | 311 --- .../uffs/src/example/CMakeLists.txt | 22 - .../src/example/flash-interface-example.c | 434 ---- .../uffs/src/example/static-mem-allocate.c | 163 -- .../dfs/filesystems/uffs/src/inc/uffs/uffs.h | 101 - .../uffs/src/inc/uffs/uffs_badblock.h | 75 - .../uffs/src/inc/uffs/uffs_blockinfo.h | 107 - .../filesystems/uffs/src/inc/uffs/uffs_buf.h | 178 -- .../filesystems/uffs/src/inc/uffs/uffs_core.h | 59 - .../filesystems/uffs/src/inc/uffs/uffs_crc.h | 46 - .../uffs/src/inc/uffs/uffs_device.h | 211 -- .../filesystems/uffs/src/inc/uffs/uffs_ecc.h | 89 - .../filesystems/uffs/src/inc/uffs/uffs_fd.h | 151 -- .../filesystems/uffs/src/inc/uffs/uffs_find.h | 76 - .../uffs/src/inc/uffs/uffs_flash.h | 311 --- .../filesystems/uffs/src/inc/uffs/uffs_fs.h | 138 -- .../filesystems/uffs/src/inc/uffs/uffs_mem.h | 83 - .../filesystems/uffs/src/inc/uffs/uffs_mtb.h | 96 - .../filesystems/uffs/src/inc/uffs/uffs_os.h | 75 - .../filesystems/uffs/src/inc/uffs/uffs_pool.h | 94 - .../uffs/src/inc/uffs/uffs_public.h | 336 --- .../filesystems/uffs/src/inc/uffs/uffs_tree.h | 237 -- .../uffs/src/inc/uffs/uffs_types.h | 160 -- .../uffs/src/inc/uffs/uffs_utils.h | 64 - .../uffs/src/inc/uffs/uffs_version.h | 55 - .../uffs/src/platform/CMakeLists.txt | 13 - .../uffs/src/platform/posix/uffs_config.h | 322 --- .../uffs/src/platform/posix/uffs_os.c | 148 -- .../uffs/src/platform/win32/uffs_config.h | 317 --- .../uffs/src/platform/win32/uffs_os.c | 148 -- .../filesystems/uffs/src/uffs/CMakeLists.txt | 59 - .../filesystems/uffs/src/uffs/uffs_badblock.c | 249 -- .../uffs/src/uffs/uffs_blockinfo.c | 413 ---- .../dfs/filesystems/uffs/src/uffs/uffs_buf.c | 1799 -------------- .../dfs/filesystems/uffs/src/uffs/uffs_crc.c | 93 - .../filesystems/uffs/src/uffs/uffs_debug.c | 188 -- .../filesystems/uffs/src/uffs/uffs_device.c | 93 - .../dfs/filesystems/uffs/src/uffs/uffs_ecc.c | 384 --- .../dfs/filesystems/uffs/src/uffs/uffs_fd.c | 746 ------ .../dfs/filesystems/uffs/src/uffs/uffs_find.c | 378 --- .../filesystems/uffs/src/uffs/uffs_flash.c | 1034 -------- .../dfs/filesystems/uffs/src/uffs/uffs_fs.c | 1944 --------------- .../dfs/filesystems/uffs/src/uffs/uffs_init.c | 204 -- .../dfs/filesystems/uffs/src/uffs/uffs_mem.c | 92 - .../dfs/filesystems/uffs/src/uffs/uffs_mtb.c | 366 --- .../dfs/filesystems/uffs/src/uffs/uffs_pool.c | 386 --- .../filesystems/uffs/src/uffs/uffs_public.c | 448 ---- .../dfs/filesystems/uffs/src/uffs/uffs_tree.c | 1278 ---------- .../filesystems/uffs/src/uffs/uffs_utils.c | 402 --- .../filesystems/uffs/src/uffs/uffs_version.c | 73 - .../filesystems/uffs/src/utils/CMakeLists.txt | 20 - .../dfs/filesystems/uffs/src/utils/mkuffs.c | 493 ---- .../uffs/tools/chomp_uffs_perror.rb | 25 - .../dfs/filesystems/uffs/tools/format_code.rb | 24 - .../filesystems/uffs/tools/make_package.sh | 3 - components/dfs/filesystems/uffs/uffs_config.h | 322 --- components/dfs/filesystems/uffs/uffs_nandif.c | 359 --- .../dfs/filesystems/uffs/uffs_rtthread.c | 158 -- 213 files changed, 57160 deletions(-) delete mode 100644 components/dfs/filesystems/jffs2/SConscript delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/ChangeLog delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/cdl/compress_zlib.cdl delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/include/zconf.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/include/zlib.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/ChangeLog delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/FAQ delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/INDEX delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/Make_vms.com delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/Makefile delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.in delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.riscos delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/README delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/README.eCos delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/adler32.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/algorithm.txt delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/compress.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/configure delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/deflate.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/deflate.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/descrip.mms delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/example.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/gzio.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/infback.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/infblock.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/infblock.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/inffast.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/inffast.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/inffixed.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/inflate.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/inflate.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/infutil.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/infutil.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/maketree.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/minigzip.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/trees.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/trees.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/uncompr.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/zlib.3 delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/zutil.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/src/zutil.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/tests/zlib1.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/tests/zlib2.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/zconf.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/compress/zlib.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/crc/crc.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/crc/crc16.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/crc/crc32.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/crc/posix_crc.c delete mode 100644 components/dfs/filesystems/jffs2/cyg/fileio/fileio.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/hal/basetype.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/hal/drv_api.h delete mode 100644 components/dfs/filesystems/jffs2/cyg/infra/cyg_type.h delete mode 100644 components/dfs/filesystems/jffs2/dfs_jffs2.c delete mode 100644 components/dfs/filesystems/jffs2/dfs_jffs2.h delete mode 100644 components/dfs/filesystems/jffs2/include/linux/jffs2.h delete mode 100644 components/dfs/filesystems/jffs2/include/linux/jffs2_fs_i.h delete mode 100644 components/dfs/filesystems/jffs2/include/linux/jffs2_fs_sb.h delete mode 100644 components/dfs/filesystems/jffs2/include/port/codes.h delete mode 100644 components/dfs/filesystems/jffs2/include/port/fcntl.h delete mode 100644 components/dfs/filesystems/jffs2/include/port/sys/stat.h delete mode 100644 components/dfs/filesystems/jffs2/include/port/sys/types.h delete mode 100644 components/dfs/filesystems/jffs2/jffs2_config.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/asm/atomic.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/asm/bug.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/asm/page.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/asm/semaphore.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/TODO delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/compiler.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/completion.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/config.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/crc32.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/errno.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/fs.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/init.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/kernel.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/list.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/mtd/compatmac.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/mtd/mtd.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/pagemap.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/rbtree.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/rwsem.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/sched.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/slab.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/spinlock.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/stat.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/string.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/timer.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/types.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/version.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/vmalloc.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/wait.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/workqueue.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/zlib.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/linux/zutil.h delete mode 100644 components/dfs/filesystems/jffs2/kernel/rbtree.c delete mode 100644 components/dfs/filesystems/jffs2/porting.c delete mode 100644 components/dfs/filesystems/jffs2/porting.h delete mode 100644 components/dfs/filesystems/jffs2/src/LICENCE delete mode 100644 components/dfs/filesystems/jffs2/src/build.c delete mode 100644 components/dfs/filesystems/jffs2/src/compr.c delete mode 100644 components/dfs/filesystems/jffs2/src/compr.h delete mode 100644 components/dfs/filesystems/jffs2/src/compr_rtime.c delete mode 100644 components/dfs/filesystems/jffs2/src/compr_rubin.c delete mode 100644 components/dfs/filesystems/jffs2/src/compr_rubin.h delete mode 100644 components/dfs/filesystems/jffs2/src/compr_zlib.c delete mode 100644 components/dfs/filesystems/jffs2/src/debug.c delete mode 100644 components/dfs/filesystems/jffs2/src/debug.h delete mode 100644 components/dfs/filesystems/jffs2/src/dir-ecos.c delete mode 100644 components/dfs/filesystems/jffs2/src/dir.txt delete mode 100644 components/dfs/filesystems/jffs2/src/erase.c delete mode 100644 components/dfs/filesystems/jffs2/src/flashio.c delete mode 100644 components/dfs/filesystems/jffs2/src/fs-ecos.c delete mode 100644 components/dfs/filesystems/jffs2/src/gc.c delete mode 100644 components/dfs/filesystems/jffs2/src/gcthread.c delete mode 100644 components/dfs/filesystems/jffs2/src/histo.h delete mode 100644 components/dfs/filesystems/jffs2/src/histo_mips.h delete mode 100644 components/dfs/filesystems/jffs2/src/malloc-ecos.c delete mode 100644 components/dfs/filesystems/jffs2/src/nodelist.c delete mode 100644 components/dfs/filesystems/jffs2/src/nodelist.h delete mode 100644 components/dfs/filesystems/jffs2/src/nodemgmt.c delete mode 100644 components/dfs/filesystems/jffs2/src/os-ecos.h delete mode 100644 components/dfs/filesystems/jffs2/src/os-rtthread.h delete mode 100644 components/dfs/filesystems/jffs2/src/pushpull.h delete mode 100644 components/dfs/filesystems/jffs2/src/read.c delete mode 100644 components/dfs/filesystems/jffs2/src/readinode.c delete mode 100644 components/dfs/filesystems/jffs2/src/scan.c delete mode 100644 components/dfs/filesystems/jffs2/src/write.c delete mode 100644 components/dfs/filesystems/uffs/AUTHORS delete mode 100644 components/dfs/filesystems/uffs/CMakeLists.txt delete mode 100644 components/dfs/filesystems/uffs/COPYING delete mode 100644 components/dfs/filesystems/uffs/Doxyfile delete mode 100644 components/dfs/filesystems/uffs/README delete mode 100644 components/dfs/filesystems/uffs/SConscript delete mode 100644 components/dfs/filesystems/uffs/TODO delete mode 100644 components/dfs/filesystems/uffs/dfs_uffs.c delete mode 100644 components/dfs/filesystems/uffs/dfs_uffs.h delete mode 100644 components/dfs/filesystems/uffs/doc/Understanding-UFFS.odp delete mode 100644 components/dfs/filesystems/uffs/doc/Understanding-UFFS.pdf delete mode 100644 components/dfs/filesystems/uffs/doc/uffs-serial-num-relationship.JPG delete mode 100644 components/dfs/filesystems/uffs/src/CMakeLists.txt delete mode 100644 components/dfs/filesystems/uffs/src/emu/CMakeLists.txt delete mode 100644 components/dfs/filesystems/uffs/src/emu/cmdline.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/cmdline.h delete mode 100644 components/dfs/filesystems/uffs/src/emu/helper_cmds.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/test_cmds.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/uffs_fileem.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/uffs_fileem.h delete mode 100644 components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw_auto.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_soft.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/uffs_fileem_share.c delete mode 100644 components/dfs/filesystems/uffs/src/emu/uffs_fileem_wrap.c delete mode 100644 components/dfs/filesystems/uffs/src/example/CMakeLists.txt delete mode 100644 components/dfs/filesystems/uffs/src/example/flash-interface-example.c delete mode 100644 components/dfs/filesystems/uffs/src/example/static-mem-allocate.c delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_badblock.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_blockinfo.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_buf.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_core.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_crc.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_device.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_ecc.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_fd.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_find.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_flash.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_fs.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_mem.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_mtb.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_os.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_pool.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_public.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_tree.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_types.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_utils.h delete mode 100644 components/dfs/filesystems/uffs/src/inc/uffs/uffs_version.h delete mode 100644 components/dfs/filesystems/uffs/src/platform/CMakeLists.txt delete mode 100644 components/dfs/filesystems/uffs/src/platform/posix/uffs_config.h delete mode 100644 components/dfs/filesystems/uffs/src/platform/posix/uffs_os.c delete mode 100644 components/dfs/filesystems/uffs/src/platform/win32/uffs_config.h delete mode 100644 components/dfs/filesystems/uffs/src/platform/win32/uffs_os.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/CMakeLists.txt delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_badblock.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_blockinfo.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_buf.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_crc.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_debug.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_device.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_ecc.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_fd.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_find.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_flash.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_fs.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_init.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_mem.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_mtb.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_pool.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_public.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_tree.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_utils.c delete mode 100644 components/dfs/filesystems/uffs/src/uffs/uffs_version.c delete mode 100644 components/dfs/filesystems/uffs/src/utils/CMakeLists.txt delete mode 100644 components/dfs/filesystems/uffs/src/utils/mkuffs.c delete mode 100644 components/dfs/filesystems/uffs/tools/chomp_uffs_perror.rb delete mode 100644 components/dfs/filesystems/uffs/tools/format_code.rb delete mode 100644 components/dfs/filesystems/uffs/tools/make_package.sh delete mode 100644 components/dfs/filesystems/uffs/uffs_config.h delete mode 100644 components/dfs/filesystems/uffs/uffs_nandif.c delete mode 100644 components/dfs/filesystems/uffs/uffs_rtthread.c diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index c6b493f0d2..3d70820173 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -140,43 +140,6 @@ if RT_USING_DFS select RT_USING_MEMHEAP default n - config RT_USING_DFS_UFFS - bool "Enable UFFS file system: Ultra-low-cost Flash File System" - select RT_USING_MTD_NAND - default n - - if RT_USING_DFS_UFFS - choice - prompt "UFFS ECC mode" - default RT_UFFS_ECC_MODE_1 - - config RT_UFFS_ECC_MODE_0 - bool "0: Do not use ECC" - - config RT_UFFS_ECC_MODE_1 - bool "1: UFFS calculate the ECC" - - config RT_UFFS_ECC_MODE_2 - bool "2: Flash driver(or by hardware) calculate the ECC" - - config RT_UFFS_ECC_MODE_3 - bool "3: Hardware calculate the ECC and automatically write to spare." - endchoice - - config RT_UFFS_ECC_MODE - int - default 0 if RT_UFFS_ECC_MODE_0 - default 1 if RT_UFFS_ECC_MODE_1 - default 2 if RT_UFFS_ECC_MODE_2 - default 3 if RT_UFFS_ECC_MODE_3 - - endif - - config RT_USING_DFS_JFFS2 - bool "Enable JFFS2 file system" - select RT_USING_MTD_NOR - default n - config RT_USING_DFS_NFS bool "Using NFS v3 client file system" depends on RT_USING_LWIP diff --git a/components/dfs/filesystems/jffs2/SConscript b/components/dfs/filesystems/jffs2/SConscript deleted file mode 100644 index 47854393e3..0000000000 --- a/components/dfs/filesystems/jffs2/SConscript +++ /dev/null @@ -1,50 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() -src = Split(''' -dfs_jffs2.c -porting.c - -cyg/compress/src/adler32.c -cyg/compress/src/compress.c -cyg/compress/src/deflate.c -cyg/compress/src/infback.c -cyg/compress/src/inffast.c -cyg/compress/src/inflate.c -cyg/compress/src/inftrees.c -cyg/compress/src/trees.c -cyg/compress/src/uncompr.c -cyg/compress/src/zutil.c - -cyg/crc/crc16.c -cyg/crc/crc32.c -cyg/crc/posix_crc.c -kernel/rbtree.c -src/build.c -src/compr.c -src/compr_rtime.c -src/compr_rubin.c -src/compr_zlib.c -src/debug.c -src/dir-ecos.c -src/erase.c -src/flashio.c -src/fs-ecos.c -src/gc.c -src/gcthread.c -src/malloc-ecos.c -src/nodelist.c -src/nodemgmt.c -src/read.c -src/readinode.c -src/scan.c -src/write.c -''') - -CPPPATH = [cwd, cwd + '/include', cwd + '/src', cwd + '/cyg', cwd + '/kernel', cwd + '/cyg/compress'] - -group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_JFFS2'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/dfs/filesystems/jffs2/cyg/compress/ChangeLog b/components/dfs/filesystems/jffs2/cyg/compress/ChangeLog deleted file mode 100644 index 295e5cdd48..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/ChangeLog +++ /dev/null @@ -1,218 +0,0 @@ -2009-03-09 John Dallaway - - * cdl/compress_zlib.cdl: Reference test executable filenames for - compatibility with the eCos Configuration Tool. - -2005-10-16 Peter Korsgaard - - * cdl/compress_zlib.cdl (CYGFUN_COMPRESS_ZLIB_GZIO): New option to - include zlib stdio-like utility functions. - -2005-07-27 Peter Korsgaard - - * src/ChangeLog: - * src/configure: - * src/deflate.c: - * src/deflate.h: - * src/FAQ: - * src/gzio.c: - * src/Make_vms.com: - * src/adler32.c: - * src/compress.c: - * src/example.c: - * src/minigzip.c: - * src/infback.c: - * src/inffast.c: - * src/inflate.c: - * src/inflate.h: - * src/inftrees.c: - * src/inftrees.h: - * src/Makefile: - * src/Makefile.in: - * src/README: - * src/README.eCos: - * src/trees.c: - * src/zlib.3: - * src/zutil.c: - * src/zutil.h: - * include/zlib.h: - * include/zconf.h: Upgrade to zlib-1.2.3 - -2005-06-28 Peter Korsgaard - - * src/ChangeLog: - * src/configure: - * src/deflate.c: - * src/deflate.h: - * src/FAQ: - * src/gzio.c: - * src/INDEX: - * src/infback.c: - * src/inffast.c: - * src/inflate.c: - * src/Makefile: - * src/Makefile.in: - * src/README: - * src/trees.c: - * src/zlib.3: - * src/zutil.h: - * include/zlib.h: - * include/zconf.h: Upgrade to zlib-1.2.2 - -2005-03-27 Andrew Lunn - - * tests/zlib1.c: Include diag.h for diag_printf proto. - -2004-05-25 Gary Thomas - - * src/zutil.h: Fix redefine of 'crc32' - - * include/zconf.h: Force define of __ECOS__ to make it easier for - applications to use this library. Also define Z_PREFIX to minimize - namespace pollution. !CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP now - implies NO_GZCOMPRESS and NO_GZIP. - -2004-05-24 Gary Thomas - - * tests/zlib2.c: - * tests/zlib1.c: - * src/zutil.h: - * src/zutil.c: - * src/zlib.3: - * src/uncompr.c: - * src/trees.c: - * src/minigzip.c: - * src/inftrees.h: - * src/inftrees.c: - * src/inflate.h: - * src/inflate.c: - * src/inffixed.h: - * src/inffast.h: - * src/inffast.c: - * src/infback.c: - * src/gzio.c: - * src/example.c: - * src/deflate.h: - * src/deflate.c: - * src/configure: - * src/compress.c: - * src/algorithm.txt: - * src/adler32.c: - * src/README.eCos: - * src/README: - * src/Makefile.in: - * src/Makefile: - * src/INDEX: - * src/FAQ: - * include/zlib.h: - * include/zconf.h: - * cdl/compress_zlib.cdl: Upgrade to zlib-1.2.1 - -2004-04-29 Oyvind Harboe - - * src/inffixed.h: added "const" to tables that do not - change in order to save RAM. Ca. 4k. - -2003-11-20 Andrew Lunn - - * tests/zlib[12].c: Modified the text to the gcc3.3 friendly. - -2003-11-13 Daniel Néri - - * Upgrade to zlib 1.1.4 and additional fix for inflate bug on - machines with 16-bit pointers. - -2003-09-08 Thomas Koeller - - * cdl/compress_zlib.cdl : Displayed package name was wrong. - -2002-10-10 Andrew Lunn - - * include/zutil.h: - * include/zlib.h: - * src/inflate.c (inflate): Use the CRC function from the CRC - package. - * src/crc32.c: Removed. - -2002-09-09 Mark Salter - - * inflate.c (inflate): Fix CRC calculation over multiple invocations - with same output buffer. - -2002-02-18 Jesper Skov - - * src/infblock.c: Applied fix for double-free which could cause a - zlib crash. Fixed indentation. - -2001-10-15 Gary Thomas - - * include/zconf.h: - * cdl/compress_zlib.cdl: - Define new interface CYGINT_COMPRESS_ZLIB_LOCAL_ALLOC which allows - users of this code (applications) to provide their own allocators. - -2001-04-02 Jesper Skov - - * tests/zlib2.c: Removed BAD_CRC state. - -2001-03-12 Jesper Skov - - * src/inflate.c: Remove BAD_CRC state. Do separate CRC for - gzippped data. - * include/zlib.h: Removed Z_BAD_CRC hack. Rename crc32 function. - * src/crc32.c: Include zlib.h header from - include/cyg/compress. Rename function. - * cdl/compress_zlib.cdl: Build the crc32.c file. - -2001-03-09 Jesper Skov - - * src/compress.c: Include zlib.h header from include/cyg/compress. - * src/uncompr.c: Same. - * tests/zlib1.c: Added. - * tests/zlib2.c: Added. - * cdl/compress_zlib.cdl: Compile tests. Compile - files holding compress/uncompress functions. - - * cdl/compress_zlib.cdl: Don't warn about prototypes when building. - -2001-03-08 Jesper Skov - - * cdl/compress_zlib.cdl: Add isoinfra requirement. - - * include/zconf.h: Override STDC check. - - * include/zlib.h: Added new BAD_CRC return type. Comment out crc32 - declaration. - - * src/inflate.c: Added additional states to allow for gzip header - decoding. - - * src/adler32.c: Include zlib.h header from include/cyg/compress. - * src/zutil.h: Same. - - * Import zlib 1.1.3 sources, but leave out some sub - directories. See src/README.eCos for details. - -//=========================================================================== -// ####GPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 or (at your option) any -// later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the -// Free Software Foundation, Inc., 51 Franklin Street, -// Fifth Floor, Boston, MA 02110-1301, USA. -// ------------------------------------------- -// ####GPLCOPYRIGHTEND#### -//=========================================================================== diff --git a/components/dfs/filesystems/jffs2/cyg/compress/cdl/compress_zlib.cdl b/components/dfs/filesystems/jffs2/cyg/compress/cdl/compress_zlib.cdl deleted file mode 100644 index d5787570b7..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/cdl/compress_zlib.cdl +++ /dev/null @@ -1,170 +0,0 @@ -# ==================================================================== -# -# compress_zlib.cdl -# -# Zlib compress/decompress configuration data -# -# ==================================================================== -## ####ECOSGPLCOPYRIGHTBEGIN#### -## ------------------------------------------- -## This file is part of eCos, the Embedded Configurable Operating System. -## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc. -## -## eCos is free software; you can redistribute it and/or modify it under -## the terms of the GNU General Public License as published by the Free -## Software Foundation; either version 2 or (at your option) any later -## version. -## -## eCos is distributed in the hope that it will be useful, but WITHOUT -## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -## for more details. -## -## You should have received a copy of the GNU General Public License -## along with eCos; if not, write to the Free Software Foundation, Inc., -## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -## -## As a special exception, if other files instantiate templates or use -## macros or inline functions from this file, or you compile this file -## and link it with other works to produce a work based on this file, -## this file does not by itself cause the resulting work to be covered by -## the GNU General Public License. However the source code for this file -## must still be made available in accordance with section (3) of the GNU -## General Public License v2. -## -## This exception does not invalidate any other reasons why a work based -## on this file might be covered by the GNU General Public License. -## ------------------------------------------- -## ####ECOSGPLCOPYRIGHTEND#### -# ==================================================================== -######DESCRIPTIONBEGIN#### -# -# Author(s): jskov -# Contributors: -# Date: 2001-03-06 -# -#####DESCRIPTIONEND#### -# -# ==================================================================== - -cdl_package CYGPKG_COMPRESS_ZLIB { - display "Zlib compress and decompress package" - description " - This package provides support for compression and - decompression." - include_dir cyg/compress - - requires CYGPKG_ISOINFRA - requires CYGPKG_CRC - - compile adler32.c compress.c uncompr.c zutil.c trees.c - compile deflate.c infback.c inffast.c inflate.c inftrees.c - - cdl_interface CYGINT_COMPRESS_ZLIB_LOCAL_ALLOC { - display "Override memory allocation routines." - } - - cdl_option CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP { - display "Should deflate() produce 'gzip' compatible output?" - flavor bool - default_value 1 - description " - If this option is set then the output of calling deflate() - will be wrapped up as a 'gzip' compatible file." - } - - cdl_option CYGSEM_COMPRESS_ZLIB_NEEDS_MALLOC { - display "Does this library need malloc?" - flavor bool - active_if { CYGINT_COMPRESS_ZLIB_LOCAL_ALLOC == 0 } - requires CYGPKG_MEMALLOC - no_define - default_value 1 - description " - This pseudo-option will force the memalloc library to be - required iff the application does not provide it's own - infrastructure." - } - - cdl_option CYGFUN_COMPRESS_ZLIB_GZIO { - display "Include stdio-like utility functions" - flavor bool - requires CYGINT_ISO_STDIO_FILEPOS - requires CYGINT_ISO_STRING_STRFUNCS - requires CYGINT_ISO_STDIO_FORMATTED_IO - requires CYGINT_ISO_STDIO_FILEACCESS - default_value { CYGPKG_LIBC_STDIO_OPEN ? 1 : 0 } - compile gzio.c - description " - This option enables the stdio-like zlib utility functions - (gzread/gzwrite and friends) provided in gzio.c." - } - - -# ==================================================================== - - cdl_component CYGPKG_COMPRESS_ZLIB_OPTIONS { - display "Zlib compress and decompress package build options" - flavor none - no_define - description " - Package specific build options including control over - compiler flags used only in building this package, - and details of which tests are built." - - cdl_option CYGPKG_COMPRESS_ZLIB_CFLAGS_ADD { - display "Additional compiler flags" - flavor data - no_define - default_value { "-D__ECOS__ -DNO_ERRNO_H" } - description " - This option modifies the set of compiler flags for - building this package. These flags are used in addition - to the set of global flags." - } - - cdl_option CYGPKG_COMPRESS_ZLIB_CFLAGS_REMOVE { - display "Suppressed compiler flags" - flavor data - no_define - default_value { "-Wstrict-prototypes" } - description " - This option modifies the set of compiler flags for - building this package. These flags are removed from - the set of global flags if present." - } - - cdl_option CYGPKG_COMPRESS_ZLIB_LDFLAGS_ADD { - display "Additional compiler flags" - flavor data - no_define - default_value { "" } - description " - This option modifies the set of compiler flags for - building this package. These flags are used in addition - to the set of global flags." - } - - cdl_option CYGPKG_COMPRESS_ZLIB_LDFLAGS_REMOVE { - display "Suppressed compiler flags" - flavor data - no_define - default_value { "" } - description " - This option modifies the set of compiler flags for - building this package. These flags are removed from - the set of global flags if present." - } - - } - - cdl_option CYGPKG_COMPRESS_ZLIB_TESTS { - display "zlib tests" - flavor data - no_define - calculated { "tests/zlib1 tests/zlib2" } - } -} - -# ==================================================================== -# EOF compress_zlib.cdl diff --git a/components/dfs/filesystems/jffs2/cyg/compress/include/zconf.h b/components/dfs/filesystems/jffs2/cyg/compress/include/zconf.h deleted file mode 100644 index 09608dcc34..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/include/zconf.h +++ /dev/null @@ -1,349 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -// #ifdef __ECOS__ -#undef __ECOS__ -#define __ECOS__ -#define Z_PREFIX -#include -#if CYGINT_COMPRESS_ZLIB_LOCAL_ALLOC != 0 -#define MY_ZCALLOC -#endif -#ifdef CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP -#undef MAX_WBITS -#define MAX_WBITS 15+16 /* 32K LZ77 window */ -#else -#define NO_GZIP -#define NO_GZCOMPRESS -#endif -// #endif - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define deflateBound z_deflateBound -# define deflatePrime z_deflatePrime -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateCopy z_inflateCopy -# define inflateReset z_inflateReset -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table -# define zError z_zError - -# define alloc_func z_alloc_func -# define free_func z_free_func -# define in_func z_in_func -# define out_func z_out_func -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# define z_off_t off_t -#endif -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif -#ifndef z_off_t -# define z_off_t long -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -# ifdef FAR -# undef FAR -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(deflateBound,"DEBND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(compressBound,"CMBND") -# pragma map(inflate_table,"INTABL") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/include/zlib.h b/components/dfs/filesystems/jffs2/cyg/compress/include/zlib.h deleted file mode 100644 index 081e7c912f..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/include/zlib.h +++ /dev/null @@ -1,1358 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.3, July 18th, 2005 - - Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.3" -#define ZLIB_VERNUM 0x1230 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumualte before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - the value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, - Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it gets to the next deflate block boundary. When decoding the - zlib or gzip format, this will cause inflate() to return immediately after - the header and before the first block. When doing a raw inflate, inflate() - will go ahead and process the first block, and will return when it gets to - the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 - if inflate() is currently decoding the last block in the deflate stream, - plus 128 if inflate() returned immediately after decoding an end-of-block - code or decoding the complete header up to just before the first byte of the - deflate stream. The end-of-block will not be indicated until all of the - uncompressed data from that block has been written to strm->next_out. The - number of unused bits may in general be greater than seven, except when - bit 7 of data_type is set, in which case the number of unused bits will be - less than eight. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster approach - may be used for the single inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() will decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically. Any information - contained in the gzip header is not retained, so applications that need that - information should instead use raw inflate, see inflateInit2() below, or - inflateBack() and perform their own processing of the gzip header and - trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may then - call inflateSync() to look for a good compression block if a partial recovery - of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as - Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy - parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. Z_FIXED prevents the - use of dynamic Huffman codes, allowing for a simpler decoder for special - applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. In addition, the - current implementation of deflate will use at most the window size minus - 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() - or deflateInit2(). This would be used to allocate an output buffer - for deflation in a single pass, and so would be called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the - bits leftover from a previous deflate stream when appending to it. As such, - this function can only be used for raw deflate, and must be used before the - first deflate() call after a deflateInit2() or deflateReset(). bits must be - less than or equal to 16, and that many of the least significant bits of - value will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is - a crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg - is set to null if there is no error message. inflateInit2 does not perform - any decompression apart from reading the zlib header if present: this will - be done by inflate(). (So next_in and avail_in may be modified, but next_out - and avail_out are unchanged.) -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK can be used to - force inflate() to return immediately after header processing is complete - and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When - any of extra, name, or comment are not Z_NULL and the respective field is - not present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not - be allocated, or Z_VERSION_ERROR if the version of the library does not - match the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free - the allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects - only the raw deflate stream to decompress. This is different from the - normal behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format - error in the deflate stream (in which case strm->msg is set to indicate the - nature of the error), or Z_STREAM_ERROR if the stream was not properly - initialized. In the case of Z_BUF_ERROR, an input or output error can be - distinguished using strm->next_in which will be Z_NULL only if in() returned - an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to - out() returning non-zero. (in() will always be called before out(), so - strm->next_in is assured to be defined if out() returns non-zero.) Note - that inflateBack() cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least the value returned - by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before - a compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - -typedef voidp gzFile; - -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h", or 'R' for run-length encoding - as in "wb1R". (See the description of deflateInit2 for more information - about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). The number of - uncompressed bytes written is limited to 4095. The caller should assure that - this limit is not exceeded. If it is exceeded, then gzprintf() will return - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read again later. - Only one character of push-back is allowed. gzungetc() returns the - character pushed, or -1 on failure. gzungetc() will fail if a - character has been pushed but not read yet, or if c is -1. The pushed - character will be discarded if the stream is repositioned with gzseek() - or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns 1 if file is being read directly without decompression, otherwise - zero. -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -#ifndef __ECOS__ -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required initial - value for the for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ -#endif // __ECOS__ - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/ChangeLog b/components/dfs/filesystems/jffs2/cyg/compress/src/ChangeLog deleted file mode 100644 index dfdd0295e8..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/ChangeLog +++ /dev/null @@ -1,854 +0,0 @@ - ChangeLog file for zlib - -Changes in 1.2.2 (3 October 2004) -Changes in 1.2.3 (18 July 2005) -- Apply security vulnerability fixes to contrib/infback9 as well -- Clean up some text files (carriage returns, trailing space) -- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] - -Changes in 1.2.2.4 (11 July 2005) -- Add inflatePrime() function for starting inflation at bit boundary -- Avoid some Visual C warnings in deflate.c -- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit - compile -- Fix some spelling errors in comments [Betts] -- Correct inflateInit2() error return documentation in zlib.h -- Added zran.c example of compressed data random access to examples - directory, shows use of inflatePrime() -- Fix cast for assignments to strm->state in inflate.c and infback.c -- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] -- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] -- Add cast in trees.c t avoid a warning [Oberhumer] -- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] -- Update make_vms.com [Zinser] -- Initialize state->write in inflateReset() since copied in inflate_fast() -- Be more strict on incomplete code sets in inflate_table() and increase - ENOUGH and MAXD -- this repairs a possible security vulnerability for - invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for - discovering the vulnerability and providing test cases. -- Add ia64 support to configure for HP-UX [Smith] -- Add error return to gzread() for format or i/o error [Levin] -- Use malloc.h for OS/2 [Necasek] - -Changes in 1.2.2.3 (27 May 2005) -- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile -- Typecast fread() return values in gzio.c [Vollant] -- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) -- Fix crc check bug in gzread() after gzungetc() [Heiner] -- Add the deflateTune() function to adjust internal compression parameters -- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) -- Remove an incorrect assertion in examples/zpipe.c -- Add C++ wrapper in infback9.h [Donais] -- Fix bug in inflateCopy() when decoding fixed codes -- Note in zlib.h how much deflateSetDictionary() actually uses -- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) -- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] -- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] -- Add gzdirect() function to indicate transparent reads -- Update contrib/minizip [Vollant] -- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] -- Add casts in crc32.c to avoid warnings [Oberhumer] -- Add contrib/masmx64 [Vollant] -- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] - -Changes in 1.2.2.2 (30 December 2004) -- Replace structure assignments in deflate.c and inflate.c with zmemcpy to - avoid implicit memcpy calls (portability for no-library compilation) -- Increase sprintf() buffer size in gzdopen() to allow for large numbers -- Add INFLATE_STRICT to check distances against zlib header -- Improve WinCE errno handling and comments [Chang] -- Remove comment about no gzip header processing in FAQ -- Add Z_FIXED strategy option to deflateInit2() to force fixed trees -- Add updated make_vms.com [Coghlan], update README -- Create a new "examples" directory, move gzappend.c there, add zpipe.c, - fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. -- Add FAQ entry and comments in deflate.c on uninitialized memory access -- Add Solaris 9 make options in configure [Gilbert] -- Allow strerror() usage in gzio.c for STDC -- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] -- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] -- Use z_off_t for adler32_combine() and crc32_combine() lengths -- Make adler32() much faster for small len -- Use OS_CODE in deflate() default gzip header - -Changes in 1.2.2.1 (31 October 2004) -- Allow inflateSetDictionary() call for raw inflate -- Fix inflate header crc check bug for file names and comments -- Add deflateSetHeader() and gz_header structure for custom gzip headers -- Add inflateGetheader() to retrieve gzip headers -- Add crc32_combine() and adler32_combine() functions -- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list -- Use zstreamp consistently in zlib.h (inflate_back functions) -- Remove GUNZIP condition from definition of inflate_mode in inflate.h - and in contrib/inflate86/inffast.S [Truta, Anderson] -- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] -- Update projects/README.projects and projects/visualc6 [Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] -- Deprecate Z_ASCII; use Z_TEXT instead [Truta] -- Use a new algorithm for setting strm->data_type in trees.c [Truta] -- Do not define an exit() prototype in zutil.c unless DEBUG defined -- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] -- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() -- Fix Darwin build version identification [Peterson] - -- Update zlib.h comments on gzip in-memory processing -- Set adler to 1 in inflateReset() to support Java test suite [Walles] -- Add contrib/dotzlib [Ravn] -- Update win32/DLL_FAQ.txt [Truta] -- Update contrib/minizip [Vollant] -- Move contrib/visual-basic.txt to old/ [Truta] -- Fix assembler builds in projects/visualc6/ [Truta] - -Changes in 1.2.1.2 (9 September 2004) -- Update INDEX file -- Fix trees.c to update strm->data_type (no one ever noticed!) -- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] -- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) -- Add limited multitasking protection to DYNAMIC_CRC_TABLE -- Add NO_vsnprintf for VMS in zutil.h [Mozilla] -- Don't declare strerror() under VMS [Mozilla] -- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize -- Update contrib/ada [Anisimkov] -- Update contrib/minizip [Vollant] -- Fix configure to not hardcode directories for Darwin [Peterson] -- Fix gzio.c to not return error on empty files [Brown] -- Fix indentation; update version in contrib/delphi/ZLib.pas and - contrib/pascal/zlibpas.pas [Truta] -- Update mkasm.bat in contrib/masmx86 [Truta] -- Update contrib/untgz [Truta] -- Add projects/README.projects [Truta] -- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] -- Remove an unnecessary assignment to curr in inftrees.c [Truta] -- Add OS/2 to exe builds in configure [Poltorak] -- Remove err dummy parameter in zlib.h [Kientzle] - -Changes in 1.2.1.1 (9 January 2004) -- Update email address in README -- Several FAQ updates -- Fix a big fat bug in inftrees.c that prevented decoding valid - dynamic blocks with only literals and no distance codes -- - Thanks to "Hot Emu" for the bug report and sample file -- Add a note to puff.c on no distance codes case. - -Changes in 1.2.1 (17 November 2003) -- Remove a tab in contrib/gzappend/gzappend.c -- Update some interfaces in contrib for new zlib functions -- Update zlib version number in some contrib entries -- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] -- Support shared libraries on Hurd and KFreeBSD [Brown] -- Fix error in NO_DIVIDE option of adler32.c - -Changes in 1.2.0.8 (4 November 2003) -- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas -- Add experimental NO_DIVIDE #define in adler32.c - - Possibly faster on some processors (let me know if it is) -- Correct Z_BLOCK to not return on first inflate call if no wrap -- Fix strm->data_type on inflate() return to correctly indicate EOB -- Add deflatePrime() function for appending in the middle of a byte -- Add contrib/gzappend for an example of appending to a stream -- Update win32/DLL_FAQ.txt [Truta] -- Delete Turbo C comment in README [Truta] -- Improve some indentation in zconf.h [Truta] -- Fix infinite loop on bad input in configure script [Church] -- Fix gzeof() for concatenated gzip files [Johnson] -- Add example to contrib/visual-basic.txt [Michael B.] -- Add -p to mkdir's in Makefile.in [vda] -- Fix configure to properly detect presence or lack of printf functions -- Add AS400 support [Monnerat] -- Add a little Cygwin support [Wilson] - -Changes in 1.2.0.7 (21 September 2003) -- Correct some debug formats in contrib/infback9 -- Cast a type in a debug statement in trees.c -- Change search and replace delimiter in configure from % to # [Beebe] -- Update contrib/untgz to 0.2 with various fixes [Truta] -- Add build support for Amiga [Nikl] -- Remove some directories in old that have been updated to 1.2 -- Add dylib building for Mac OS X in configure and Makefile.in -- Remove old distribution stuff from Makefile -- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X -- Update links in README - -Changes in 1.2.0.6 (13 September 2003) -- Minor FAQ updates -- Update contrib/minizip to 1.00 [Vollant] -- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] -- Update POSTINC comment for 68060 [Nikl] -- Add contrib/infback9 with deflate64 decoding (unsupported) -- For MVS define NO_vsnprintf and undefine FAR [van Burik] -- Add pragma for fdopen on MVS [van Burik] - -Changes in 1.2.0.5 (8 September 2003) -- Add OF to inflateBackEnd() declaration in zlib.h -- Remember start when using gzdopen in the middle of a file -- Use internal off_t counters in gz* functions to properly handle seeks -- Perform more rigorous check for distance-too-far in inffast.c -- Add Z_BLOCK flush option to return from inflate at block boundary -- Set strm->data_type on return from inflate - - Indicate bits unused, if at block boundary, and if in last block -- Replace size_t with ptrdiff_t in crc32.c, and check for correct size -- Add condition so old NO_DEFLATE define still works for compatibility -- FAQ update regarding the Windows DLL [Truta] -- INDEX update: add qnx entry, remove aix entry [Truta] -- Install zlib.3 into mandir [Wilson] -- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] -- Adapt the zlib interface to the new DLL convention guidelines [Truta] -- Introduce ZLIB_WINAPI macro to allow the export of functions using - the WINAPI calling convention, for Visual Basic [Vollant, Truta] -- Update msdos and win32 scripts and makefiles [Truta] -- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] -- Add contrib/ada [Anisimkov] -- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] -- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] -- Add contrib/masm686 [Truta] -- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm - [Truta, Vollant] -- Update contrib/delphi; rename to contrib/pascal; add example [Truta] -- Remove contrib/delphi2; add a new contrib/delphi [Truta] -- Avoid inclusion of the nonstandard in contrib/iostream, - and fix some method prototypes [Truta] -- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip - [Truta] -- Avoid the use of backslash (\) in contrib/minizip [Vollant] -- Fix file time handling in contrib/untgz; update makefiles [Truta] -- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines - [Vollant] -- Remove contrib/vstudio/vc15_16 [Vollant] -- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] -- Update README.contrib [Truta] -- Invert the assignment order of match_head and s->prev[...] in - INSERT_STRING [Truta] -- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings - [Truta] -- Compare function pointers with 0, not with NULL or Z_NULL [Truta] -- Fix prototype of syncsearch in inflate.c [Truta] -- Introduce ASMINF macro to be enabled when using an ASM implementation - of inflate_fast [Truta] -- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] -- Modify test_gzio in example.c to take a single file name as a - parameter [Truta] -- Exit the example.c program if gzopen fails [Truta] -- Add type casts around strlen in example.c [Truta] -- Remove casting to sizeof in minigzip.c; give a proper type - to the variable compared with SUFFIX_LEN [Truta] -- Update definitions of STDC and STDC99 in zconf.h [Truta] -- Synchronize zconf.h with the new Windows DLL interface [Truta] -- Use SYS16BIT instead of __32BIT__ to distinguish between - 16- and 32-bit platforms [Truta] -- Use far memory allocators in small 16-bit memory models for - Turbo C [Truta] -- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in - zlibCompileFlags [Truta] -- Cygwin has vsnprintf [Wilson] -- In Windows16, OS_CODE is 0, as in MSDOS [Truta] -- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] - -Changes in 1.2.0.4 (10 August 2003) -- Minor FAQ updates -- Be more strict when checking inflateInit2's windowBits parameter -- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well -- Add gzip wrapper option to deflateInit2 using windowBits -- Add updated QNX rule in configure and qnx directory [Bonnefoy] -- Make inflate distance-too-far checks more rigorous -- Clean up FAR usage in inflate -- Add casting to sizeof() in gzio.c and minigzip.c - -Changes in 1.2.0.3 (19 July 2003) -- Fix silly error in gzungetc() implementation [Vollant] -- Update contrib/minizip and contrib/vstudio [Vollant] -- Fix printf format in example.c -- Correct cdecl support in zconf.in.h [Anisimkov] -- Minor FAQ updates - -Changes in 1.2.0.2 (13 July 2003) -- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons -- Attempt to avoid warnings in crc32.c for pointer-int conversion -- Add AIX to configure, remove aix directory [Bakker] -- Add some casts to minigzip.c -- Improve checking after insecure sprintf() or vsprintf() calls -- Remove #elif's from crc32.c -- Change leave label to inf_leave in inflate.c and infback.c to avoid - library conflicts -- Remove inflate gzip decoding by default--only enable gzip decoding by - special request for stricter backward compatibility -- Add zlibCompileFlags() function to return compilation information -- More typecasting in deflate.c to avoid warnings -- Remove leading underscore from _Capital #defines [Truta] -- Fix configure to link shared library when testing -- Add some Windows CE target adjustments [Mai] -- Remove #define ZLIB_DLL in zconf.h [Vollant] -- Add zlib.3 [Rodgers] -- Update RFC URL in deflate.c and algorithm.txt [Mai] -- Add zlib_dll_FAQ.txt to contrib [Truta] -- Add UL to some constants [Truta] -- Update minizip and vstudio [Vollant] -- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h -- Expand use of NO_DUMMY_DECL to avoid all dummy structures -- Added iostream3 to contrib [Schwardt] -- Replace rewind() with fseek() for WinCE [Truta] -- Improve setting of zlib format compression level flags - - Report 0 for huffman and rle strategies and for level == 0 or 1 - - Report 2 only for level == 6 -- Only deal with 64K limit when necessary at compile time [Truta] -- Allow TOO_FAR check to be turned off at compile time [Truta] -- Add gzclearerr() function [Souza] -- Add gzungetc() function - -Changes in 1.2.0.1 (17 March 2003) -- Add Z_RLE strategy for run-length encoding [Truta] - - When Z_RLE requested, restrict matches to distance one - - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE -- Correct FASTEST compilation to allow level == 0 -- Clean up what gets compiled for FASTEST -- Incorporate changes to zconf.in.h [Vollant] - - Refine detection of Turbo C need for dummy returns - - Refine ZLIB_DLL compilation - - Include additional header file on VMS for off_t typedef -- Try to use _vsnprintf where it supplants vsprintf [Vollant] -- Add some casts in inffast.c -- Enchance comments in zlib.h on what happens if gzprintf() tries to - write more than 4095 bytes before compression -- Remove unused state from inflateBackEnd() -- Remove exit(0) from minigzip.c, example.c -- Get rid of all those darn tabs -- Add "check" target to Makefile.in that does the same thing as "test" -- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in -- Update contrib/inflate86 [Anderson] -- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] -- Add msdos and win32 directories with makefiles [Truta] -- More additions and improvements to the FAQ - -Changes in 1.2.0 (9 March 2003) -- New and improved inflate code - - About 20% faster - - Does not allocate 32K window unless and until needed - - Automatically detects and decompresses gzip streams - - Raw inflate no longer needs an extra dummy byte at end - - Added inflateBack functions using a callback interface--even faster - than inflate, useful for file utilities (gzip, zip) - - Added inflateCopy() function to record state for random access on - externally generated deflate streams (e.g. in gzip files) - - More readable code (I hope) -- New and improved crc32() - - About 50% faster, thanks to suggestions from Rodney Brown -- Add deflateBound() and compressBound() functions -- Fix memory leak in deflateInit2() -- Permit setting dictionary for raw deflate (for parallel deflate) -- Fix const declaration for gzwrite() -- Check for some malloc() failures in gzio.c -- Fix bug in gzopen() on single-byte file 0x1f -- Fix bug in gzread() on concatenated file with 0x1f at end of buffer - and next buffer doesn't start with 0x8b -- Fix uncompress() to return Z_DATA_ERROR on truncated input -- Free memory at end of example.c -- Remove MAX #define in trees.c (conflicted with some libraries) -- Fix static const's in deflate.c, gzio.c, and zutil.[ch] -- Declare malloc() and free() in gzio.c if STDC not defined -- Use malloc() instead of calloc() in zutil.c if int big enough -- Define STDC for AIX -- Add aix/ with approach for compiling shared library on AIX -- Add HP-UX support for shared libraries in configure -- Add OpenUNIX support for shared libraries in configure -- Use $cc instead of gcc to build shared library -- Make prefix directory if needed when installing -- Correct Macintosh avoidance of typedef Byte in zconf.h -- Correct Turbo C memory allocation when under Linux -- Use libz.a instead of -lz in Makefile (assure use of compiled library) -- Update configure to check for snprintf or vsnprintf functions and their - return value, warn during make if using an insecure function -- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that - is lost when library is used--resolution is to build new zconf.h -- Documentation improvements (in zlib.h): - - Document raw deflate and inflate - - Update RFCs URL - - Point out that zlib and gzip formats are different - - Note that Z_BUF_ERROR is not fatal - - Document string limit for gzprintf() and possible buffer overflow - - Note requirement on avail_out when flushing - - Note permitted values of flush parameter of inflate() -- Add some FAQs (and even answers) to the FAQ -- Add contrib/inflate86/ for x86 faster inflate -- Add contrib/blast/ for PKWare Data Compression Library decompression -- Add contrib/puff/ simple inflate for deflate format description - -Changes in 1.1.4 (11 March 2002) -- ZFREE was repeated on same allocation on some error conditions. - This creates a security problem described in - http://www.zlib.org/advisory-2002-03-11.txt -- Returned incorrect error (Z_MEM_ERROR) on some invalid data -- Avoid accesses before window for invalid distances with inflate window - less than 32K. -- force windowBits > 8 to avoid a bug in the encoder for a window size - of 256 bytes. (A complete fix will be available in 1.1.5). - -Changes in 1.1.3 (9 July 1998) -- fix "an inflate input buffer bug that shows up on rare but persistent - occasions" (Mark) -- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) -- fix gzseek(..., SEEK_SET) in write mode -- fix crc check after a gzeek (Frank Faubert) -- fix miniunzip when the last entry in a zip file is itself a zip file - (J Lillge) -- add contrib/asm586 and contrib/asm686 (Brian Raiter) - See http://www.muppetlabs.com/~breadbox/software/assembly.html -- add support for Delphi 3 in contrib/delphi (Bob Dellaca) -- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) -- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) -- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) -- added a FAQ file - -- Support gzdopen on Mac with Metrowerks (Jason Linhart) -- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) -- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) -- avoid some warnings with Borland C (Tom Tanner) -- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) -- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) -- allow several arguments to configure (Tim Mooney, Frodo Looijaard) -- use libdir and includedir in Makefile.in (Tim Mooney) -- support shared libraries on OSF1 V4 (Tim Mooney) -- remove so_locations in "make clean" (Tim Mooney) -- fix maketree.c compilation error (Glenn, Mark) -- Python interface to zlib now in Python 1.5 (Jeremy Hylton) -- new Makefile.riscos (Rich Walker) -- initialize static descriptors in trees.c for embedded targets (Nick Smith) -- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) -- add the OS/2 files in Makefile.in too (Andrew Zabolotny) -- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) -- fix maketree.c to allow clean compilation of inffixed.h (Mark) -- fix parameter check in deflateCopy (Gunther Nikl) -- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) -- Many portability patches by Christian Spieler: - . zutil.c, zutil.h: added "const" for zmem* - . Make_vms.com: fixed some typos - . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists - . msdos/Makefile.msc: remove "default rtl link library" info from obj files - . msdos/Makefile.*: use model-dependent name for the built zlib library - . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: - new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) -- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) -- replace __far with _far for better portability (Christian Spieler, Tom Lane) -- fix test for errno.h in configure (Tim Newsham) - -Changes in 1.1.2 (19 March 98) -- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) - See http://www.winimage.com/zLibDll/unzip.html -- preinitialize the inflate tables for fixed codes, to make the code - completely thread safe (Mark) -- some simplifications and slight speed-up to the inflate code (Mark) -- fix gzeof on non-compressed files (Allan Schrum) -- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) -- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) -- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) -- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) -- do not wrap extern "C" around system includes (Tom Lane) -- mention zlib binding for TCL in README (Andreas Kupries) -- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) -- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) -- allow "configure --prefix $HOME" (Tim Mooney) -- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) -- move Makefile.sas to amiga/Makefile.sas - -Changes in 1.1.1 (27 Feb 98) -- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) -- remove block truncation heuristic which had very marginal effect for zlib - (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the - compression ratio on some files. This also allows inlining _tr_tally for - matches in deflate_slow. -- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) - -Changes in 1.1.0 (24 Feb 98) -- do not return STREAM_END prematurely in inflate (John Bowler) -- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) -- compile with -DFASTEST to get compression code optimized for speed only -- in minigzip, try mmap'ing the input file first (Miguel Albrecht) -- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain - on Sun but significant on HP) - -- add a pointer to experimental unzip library in README (Gilles Vollant) -- initialize variable gcc in configure (Chris Herborth) - -Changes in 1.0.9 (17 Feb 1998) -- added gzputs and gzgets functions -- do not clear eof flag in gzseek (Mark Diekhans) -- fix gzseek for files in transparent mode (Mark Diekhans) -- do not assume that vsprintf returns the number of bytes written (Jens Krinke) -- replace EXPORT with ZEXPORT to avoid conflict with other programs -- added compress2 in zconf.h, zlib.def, zlib.dnt -- new asm code from Gilles Vollant in contrib/asm386 -- simplify the inflate code (Mark): - . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() - . ZALLOC the length list in inflate_trees_fixed() instead of using stack - . ZALLOC the value area for huft_build() instead of using stack - . Simplify Z_FINISH check in inflate() - -- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 -- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) -- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles VOllant) -- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) -- read_buf buf parameter of type Bytef* instead of charf* -- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) -- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) -- fix check for presence of directories in "make install" (Ian Willis) - -Changes in 1.0.8 (27 Jan 1998) -- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) -- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) -- added compress2() to allow setting the compression level -- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) -- use constant arrays for the static trees in trees.c instead of computing - them at run time (thanks to Ken Raeburn for this suggestion). To create - trees.h, compile with GEN_TREES_H and run "make test". -- check return code of example in "make test" and display result -- pass minigzip command line options to file_compress -- simplifying code of inflateSync to avoid gcc 2.8 bug - -- support CC="gcc -Wall" in configure -s (QingLong) -- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) -- fix test for shared library support to avoid compiler warnings -- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) -- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) -- do not use fdopen for Metrowerks on Mac (Brad Pettit)) -- add checks for gzputc and gzputc in example.c -- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) -- use const for the CRC table (Ken Raeburn) -- fixed "make uninstall" for shared libraries -- use Tracev instead of Trace in infblock.c -- in example.c use correct compressed length for test_sync -- suppress +vnocompatwarnings in configure for HPUX (not always supported) - -Changes in 1.0.7 (20 Jan 1998) -- fix gzseek which was broken in write mode -- return error for gzseek to negative absolute position -- fix configure for Linux (Chun-Chung Chen) -- increase stack space for MSC (Tim Wegner) -- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) -- define EXPORTVA for gzprintf (Gilles Vollant) -- added man page zlib.3 (Rick Rodgers) -- for contrib/untgz, fix makedir() and improve Makefile - -- check gzseek in write mode in example.c -- allocate extra buffer for seeks only if gzseek is actually called -- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) -- add inflateSyncPoint in zconf.h -- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def - -Changes in 1.0.6 (19 Jan 1998) -- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) -- Fix a deflate bug occurring only with compression level 0 (thanks to - Andy Buckler for finding this one). -- In minigzip, pass transparently also the first byte for .Z files. -- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() -- check Z_FINISH in inflate (thanks to Marc Schluper) -- Implement deflateCopy (thanks to Adam Costello) -- make static libraries by default in configure, add --shared option. -- move MSDOS or Windows specific files to directory msdos -- suppress the notion of partial flush to simplify the interface - (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) -- suppress history buffer provided by application to simplify the interface - (this feature was not implemented anyway in 1.0.4) -- next_in and avail_in must be initialized before calling inflateInit or - inflateInit2 -- add EXPORT in all exported functions (for Windows DLL) -- added Makefile.nt (thanks to Stephen Williams) -- added the unsupported "contrib" directory: - contrib/asm386/ by Gilles Vollant - 386 asm code replacing longest_match(). - contrib/iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - contrib/iostream2/ by Tyge Lřvset - Another C++ I/O streams interface - contrib/untgz/ by "Pedro A. Aranda Guti\irrez" - A very simple tar.gz file extractor using zlib - contrib/visual-basic.txt by Carlos Rios - How to use compress(), uncompress() and the gz* functions from VB. -- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression - level) in minigzip (thanks to Tom Lane) - -- use const for rommable constants in deflate -- added test for gzseek and gztell in example.c -- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) -- add undocumented function zError to convert error code to string - (for Tim Smithers) -- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. -- Use default memcpy for Symantec MSDOS compiler. -- Add EXPORT keyword for check_func (needed for Windows DLL) -- add current directory to LD_LIBRARY_PATH for "make test" -- create also a link for libz.so.1 -- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) -- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) -- added -soname for Linux in configure (Chun-Chung Chen, -- assign numbers to the exported functions in zlib.def (for Windows DLL) -- add advice in zlib.h for best usage of deflateSetDictionary -- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) -- allow compilation with ANSI keywords only enabled for TurboC in large model -- avoid "versionString"[0] (Borland bug) -- add NEED_DUMMY_RETURN for Borland -- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). -- allow compilation with CC -- defined STDC for OS/2 (David Charlap) -- limit external names to 8 chars for MVS (Thomas Lund) -- in minigzip.c, use static buffers only for 16-bit systems -- fix suffix check for "minigzip -d foo.gz" -- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) -- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) -- added makelcc.bat for lcc-win32 (Tom St Denis) -- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. -- check for unistd.h in configure (for off_t) -- remove useless check parameter in inflate_blocks_free -- avoid useless assignment of s->check to itself in inflate_blocks_new -- do not flush twice in gzclose (thanks to Ken Raeburn) -- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h -- use NO_ERRNO_H instead of enumeration of operating systems with errno.h -- work around buggy fclose on pipes for HP/UX -- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) -- fix configure if CC is already equal to gcc - -Changes in 1.0.5 (3 Jan 98) -- Fix inflate to terminate gracefully when fed corrupted or invalid data -- Use const for rommable constants in inflate -- Eliminate memory leaks on error conditions in inflate -- Removed some vestigial code in inflate -- Update web address in README - -Changes in 1.0.4 (24 Jul 96) -- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF - bit, so the decompressor could decompress all the correct data but went - on to attempt decompressing extra garbage data. This affected minigzip too. -- zlibVersion and gzerror return const char* (needed for DLL) -- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) -- use z_error only for DEBUG (avoid problem with DLLs) - -Changes in 1.0.3 (2 Jul 96) -- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS - small and medium models; this makes the library incompatible with previous - versions for these models. (No effect in large model or on other systems.) -- return OK instead of BUF_ERROR if previous deflate call returned with - avail_out as zero but there is nothing to do -- added memcmp for non STDC compilers -- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) -- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) -- better check for 16-bit mode MSC (avoids problem with Symantec) - -Changes in 1.0.2 (23 May 96) -- added Windows DLL support -- added a function zlibVersion (for the DLL support) -- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) -- Bytef is define's instead of typedef'd only for Borland C -- avoid reading uninitialized memory in example.c -- mention in README that the zlib format is now RFC1950 -- updated Makefile.dj2 -- added algorithm.doc - -Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] -- fix array overlay in deflate.c which sometimes caused bad compressed data -- fix inflate bug with empty stored block -- fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generated bad compressed data. -- Bytef is define'd instead of typedef'ed (work around Borland bug) -- added an INDEX file -- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), - Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) -- speed up adler32 for modern machines without auto-increment -- added -ansi for IRIX in configure -- static_init_done in trees.c is an int -- define unlink as delete for VMS -- fix configure for QNX -- add configure branch for SCO and HPUX -- avoid many warnings (unused variables, dead assignments, etc...) -- no fdopen for BeOS -- fix the Watcom fix for 32 bit mode (define FAR as empty) -- removed redefinition of Byte for MKWERKS -- work around an MWKERKS bug (incorrect merge of all .h files) - -Changes in 0.99 (27 Jan 96) -- allow preset dictionary shared between compressor and decompressor -- allow compression level 0 (no compression) -- add deflateParams in zlib.h: allow dynamic change of compression level - and compression strategy. -- test large buffers and deflateParams in example.c -- add optional "configure" to build zlib as a shared library -- suppress Makefile.qnx, use configure instead -- fixed deflate for 64-bit systems (detected on Cray) -- fixed inflate_blocks for 64-bit systems (detected on Alpha) -- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) -- always return Z_BUF_ERROR when deflate() has nothing to do -- deflateInit and inflateInit are now macros to allow version checking -- prefix all global functions and types with z_ with -DZ_PREFIX -- make falloc completely reentrant (inftrees.c) -- fixed very unlikely race condition in ct_static_init -- free in reverse order of allocation to help memory manager -- use zlib-1.0/* instead of zlib/* inside the tar.gz -- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith - -Wconversion -Wstrict-prototypes -Wmissing-prototypes" -- allow gzread on concatenated .gz files -- deflateEnd now returns Z_DATA_ERROR if it was premature -- deflate is finally (?) fully deterministic (no matches beyond end of input) -- Document Z_SYNC_FLUSH -- add uninstall in Makefile -- Check for __cpluplus in zlib.h -- Better test in ct_align for partial flush -- avoid harmless warnings for Borland C++ -- initialize hash_head in deflate.c -- avoid warning on fdopen (gzio.c) for HP cc -Aa -- include stdlib.h for STDC compilers -- include errno.h for Cray -- ignore error if ranlib doesn't exist -- call ranlib twice for NeXTSTEP -- use exec_prefix instead of prefix for libz.a -- renamed ct_* as _tr_* to avoid conflict with applications -- clear z->msg in inflateInit2 before any error return -- initialize opaque in example.c, gzio.c, deflate.c and inflate.c -- fixed typo in zconf.h (_GNUC__ => __GNUC__) -- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) -- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) -- in fcalloc, normalize pointer if size > 65520 bytes -- don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... -- use Z_BINARY instead of BINARY -- document that gzclose after gzdopen will close the file -- allow "a" as mode in gzopen. -- fix error checking in gzread -- allow skipping .gz extra-field on pipes -- added reference to Perl interface in README -- put the crc table in FAR data (I dislike more and more the medium model :) -- added get_crc_table -- added a dimension to all arrays (Borland C can't count). -- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast -- guard against multiple inclusion of *.h (for precompiled header on Mac) -- Watcom C pretends to be Microsoft C small model even in 32 bit mode. -- don't use unsized arrays to avoid silly warnings by Visual C++: - warning C4746: 'inflate_mask' : unsized array treated as '__far' - (what's wrong with far data in far model?). -- define enum out of inflate_blocks_state to allow compilation with C++ - -Changes in 0.95 (16 Aug 95) -- fix MSDOS small and medium model (now easier to adapt to any compiler) -- inlined send_bits -- fix the final (:-) bug for deflate with flush (output was correct but - not completely flushed in rare occasions). -- default window size is same for compression and decompression - (it's now sufficient to set MAX_WBITS in zconf.h). -- voidp -> voidpf and voidnp -> voidp (for consistency with other - typedefs and because voidnp was not near in large model). - -Changes in 0.94 (13 Aug 95) -- support MSDOS medium model -- fix deflate with flush (could sometimes generate bad output) -- fix deflateReset (zlib header was incorrectly suppressed) -- added support for VMS -- allow a compression level in gzopen() -- gzflush now calls fflush -- For deflate with flush, flush even if no more input is provided. -- rename libgz.a as libz.a -- avoid complex expression in infcodes.c triggering Turbo C bug -- work around a problem with gcc on Alpha (in INSERT_STRING) -- don't use inline functions (problem with some gcc versions) -- allow renaming of Byte, uInt, etc... with #define. -- avoid warning about (unused) pointer before start of array in deflate.c -- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c -- avoid reserved word 'new' in trees.c - -Changes in 0.93 (25 June 95) -- temporarily disable inline functions -- make deflate deterministic -- give enough lookahead for PARTIAL_FLUSH -- Set binary mode for stdin/stdout in minigzip.c for OS/2 -- don't even use signed char in inflate (not portable enough) -- fix inflate memory leak for segmented architectures - -Changes in 0.92 (3 May 95) -- don't assume that char is signed (problem on SGI) -- Clear bit buffer when starting a stored block -- no memcpy on Pyramid -- suppressed inftest.c -- optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks. -- untabify all sources to simplify patches - -Changes in 0.91 (2 May 95) -- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h -- Document the memory requirements in zconf.h -- added "make install" -- fix sync search logic in inflateSync -- deflate(Z_FULL_FLUSH) now works even if output buffer too short -- after inflateSync, don't scare people with just "lo world" -- added support for DJGPP - -Changes in 0.9 (1 May 95) -- don't assume that zalloc clears the allocated memory (the TurboC bug - was Mark's bug after all :) -- let again gzread copy uncompressed data unchanged (was working in 0.71) -- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented -- added a test of inflateSync in example.c -- moved MAX_WBITS to zconf.h because users might want to change that. -- document explicitly that zalloc(64K) on MSDOS must return a normalized - pointer (zero offset) -- added Makefiles for Microsoft C, Turbo C, Borland C++ -- faster crc32() - -Changes in 0.8 (29 April 95) -- added fast inflate (inffast.c) -- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - is incompatible with previous versions of zlib which returned Z_OK. -- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) - (actually that was not a compiler bug, see 0.81 above) -- gzread no longer reads one extra byte in certain cases -- In gzio destroy(), don't reference a freed structure -- avoid many warnings for MSDOS -- avoid the ERROR symbol which is used by MS Windows - -Changes in 0.71 (14 April 95) -- Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model. - -Changes in 0.7 (14 April 95) -- Added full inflate support. -- Simplified the crc32() interface. The pre- and post-conditioning - (one's complement) is now done inside crc32(). WARNING: this is - incompatible with previous versions; see zlib.h for the new usage. - -Changes in 0.61 (12 April 95) -- workaround for a bug in TurboC. example and minigzip now work on MSDOS. - -Changes in 0.6 (11 April 95) -- added minigzip.c -- added gzdopen to reopen a file descriptor as gzFile -- added transparent reading of non-gziped files in gzread. -- fixed bug in gzread (don't read crc as data) -- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). -- don't allocate big arrays in the stack (for MSDOS) -- fix some MSDOS compilation problems - -Changes in 0.5: -- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - not yet Z_FULL_FLUSH. -- support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree. -- added deflateReset and inflateReset -- added a variable zlib_version for consistency checking. -- renamed the 'filter' parameter of deflateInit2 as 'strategy'. - Added Z_FILTERED and Z_HUFFMAN_ONLY constants. - -Changes in 0.4: -- avoid "zip" everywhere, use zlib instead of ziplib. -- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8. -- added adler32 and crc32 -- renamed deflateOptions as deflateInit2, call one or the other but not both -- added the method parameter for deflateInit2. -- added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting - user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2. - -Changes in 0.3: -- prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression. -- added Z_HUFFMAN_ONLY -- added gzerror() diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/FAQ b/components/dfs/filesystems/jffs2/cyg/compress/src/FAQ deleted file mode 100644 index 441d910daa..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/FAQ +++ /dev/null @@ -1,339 +0,0 @@ - - Frequently Asked Questions about zlib - - -If your question is not there, please check the zlib home page -http://www.zlib.org which may have more recent information. -The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html - - - 1. Is zlib Y2K-compliant? - - Yes. zlib doesn't handle dates. - - 2. Where can I get a Windows DLL version? - - The zlib sources can be compiled without change to produce a DLL. - See the file win32/DLL_FAQ.txt in the zlib distribution. - Pointers to the precompiled DLL are found in the zlib web site at - http://www.zlib.org. - - 3. Where can I get a Visual Basic interface to zlib? - - See - * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm - * contrib/visual-basic.txt in the zlib distribution - * win32/DLL_FAQ.txt in the zlib distribution - - 4. compress() returns Z_BUF_ERROR. - - Make sure that before the call of compress, the length of the compressed - buffer is equal to the total size of the compressed buffer and not - zero. For Visual Basic, check that this parameter is passed by reference - ("as any"), not by value ("as long"). - - 5. deflate() or inflate() returns Z_BUF_ERROR. - - Before making the call, make sure that avail_in and avail_out are not - zero. When setting the parameter flush equal to Z_FINISH, also make sure - that avail_out is big enough to allow processing all pending input. - Note that a Z_BUF_ERROR is not fatal--another call to deflate() or - inflate() can be made with more input or output space. A Z_BUF_ERROR - may in fact be unavoidable depending on how the functions are used, since - it is not possible to tell whether or not there is more output pending - when strm.avail_out returns with zero. - - 6. Where's the zlib documentation (man pages, etc.)? - - It's in zlib.h for the moment, and Francis S. Lin has converted it to a - web page zlib.html. Volunteers to transform this to Unix-style man pages, - please contact us (zlib@gzip.org). Examples of zlib usage are in the files - example.c and minigzip.c. - - 7. Why don't you use GNU autoconf or libtool or ...? - - Because we would like to keep zlib as a very small and simple - package. zlib is rather portable and doesn't need much configuration. - - 8. I found a bug in zlib. - - Most of the time, such problems are due to an incorrect usage of - zlib. Please try to reproduce the problem with a small program and send - the corresponding source to us at zlib@gzip.org . Do not send - multi-megabyte data files without prior agreement. - - 9. Why do I get "undefined reference to gzputc"? - - If "make test" produces something like - - example.o(.text+0x154): undefined reference to `gzputc' - - check that you don't have old files libz.* in /usr/lib, /usr/local/lib or - /usr/X11R6/lib. Remove any old versions, then do "make install". - -10. I need a Delphi interface to zlib. - - See the contrib/delphi directory in the zlib distribution. - -11. Can zlib handle .zip archives? - - Not by itself, no. See the directory contrib/minizip in the zlib - distribution. - -12. Can zlib handle .Z files? - - No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt - the code of uncompress on your own. - -13. How can I make a Unix shared library? - - make clean - ./configure -s - make - -14. How do I install a shared zlib library on Unix? - - After the above, then: - - make install - - However, many flavors of Unix come with a shared zlib already installed. - Before going to the trouble of compiling a shared version of zlib and - trying to install it, you may want to check if it's already there! If you - can #include , it's there. The -lz option will probably link to it. - -15. I have a question about OttoPDF. - - We are not the authors of OttoPDF. The real author is on the OttoPDF web - site: Joel Hainley, jhainley@myndkryme.com. - -16. Can zlib decode Flate data in an Adobe PDF file? - - Yes. See http://www.fastio.com/ (ClibPDF), or http://www.pdflib.com/ . - To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ . - -17. Why am I getting this "register_frame_info not found" error on Solaris? - - After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib - generates an error such as: - - ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: - symbol __register_frame_info: referenced symbol not found - - The symbol __register_frame_info is not part of zlib, it is generated by - the C compiler (cc or gcc). You must recompile applications using zlib - which have this problem. This problem is specific to Solaris. See - http://www.sunfreeware.com for Solaris versions of zlib and applications - using zlib. - -18. Why does gzip give an error on a file I make with compress/deflate? - - The compress and deflate functions produce data in the zlib format, which - is different and incompatible with the gzip format. The gz* functions in - zlib on the other hand use the gzip format. Both the zlib and gzip - formats use the same compressed data format internally, but have different - headers and trailers around the compressed data. - -19. Ok, so why are there two different formats? - - The gzip format was designed to retain the directory information about - a single file, such as the name and last modification date. The zlib - format on the other hand was designed for in-memory and communication - channel applications, and has a much more compact header and trailer and - uses a faster integrity check than gzip. - -20. Well that's nice, but how do I make a gzip file in memory? - - You can request that deflate write the gzip format instead of the zlib - format using deflateInit2(). You can also request that inflate decode - the gzip format using inflateInit2(). Read zlib.h for more details. - -21. Is zlib thread-safe? - - Yes. However any library routines that zlib uses and any application- - provided memory allocation routines must also be thread-safe. zlib's gz* - functions use stdio library routines, and most of zlib's functions use the - library memory allocation routines by default. zlib's Init functions allow - for the application to provide custom memory allocation routines. - - Of course, you should only operate on any given zlib or gzip stream from a - single thread at a time. - -22. Can I use zlib in my commercial application? - - Yes. Please read the license in zlib.h. - -23. Is zlib under the GNU license? - - No. Please read the license in zlib.h. - -24. The license says that altered source versions must be "plainly marked". So - what exactly do I need to do to meet that requirement? - - You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In - particular, the final version number needs to be changed to "f", and an - identification string should be appended to ZLIB_VERSION. Version numbers - x.x.x.f are reserved for modifications to zlib by others than the zlib - maintainers. For example, if the version of the base zlib you are altering - is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and - ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also - update the version strings in deflate.c and inftrees.c. - - For altered source distributions, you should also note the origin and - nature of the changes in zlib.h, as well as in ChangeLog and README, along - with the dates of the alterations. The origin should include at least your - name (or your company's name), and an email address to contact for help or - issues with the library. - - Note that distributing a compiled zlib library along with zlib.h and - zconf.h is also a source distribution, and so you should change - ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes - in zlib.h as you would for a full source distribution. - -25. Will zlib work on a big-endian or little-endian architecture, and can I - exchange compressed data between them? - - Yes and yes. - -26. Will zlib work on a 64-bit machine? - - It should. It has been tested on 64-bit machines, and has no dependence - on any data types being limited to 32-bits in length. If you have any - difficulties, please provide a complete problem report to zlib@gzip.org - -27. Will zlib decompress data from the PKWare Data Compression Library? - - No. The PKWare DCL uses a completely different compressed data format - than does PKZIP and zlib. However, you can look in zlib's contrib/blast - directory for a possible solution to your problem. - -28. Can I access data randomly in a compressed stream? - - No, not without some preparation. If when compressing you periodically - use Z_FULL_FLUSH, carefully write all the pending data at those points, - and keep an index of those locations, then you can start decompression - at those points. You have to be careful to not use Z_FULL_FLUSH too - often, since it can significantly degrade compression. - -29. Does zlib work on MVS, OS/390, CICS, etc.? - - We don't know for sure. We have heard occasional reports of success on - these systems. If you do use it on one of these, please provide us with - a report, instructions, and patches that we can reference when we get - these questions. Thanks. - -30. Is there some simpler, easier to read version of inflate I can look at - to understand the deflate format? - - First off, you should read RFC 1951. Second, yes. Look in zlib's - contrib/puff directory. - -31. Does zlib infringe on any patents? - - As far as we know, no. In fact, that was originally the whole point behind - zlib. Look here for some more information: - - http://www.gzip.org/#faq11 - -32. Can zlib work with greater than 4 GB of data? - - Yes. inflate() and deflate() will process any amount of data correctly. - Each call of inflate() or deflate() is limited to input and output chunks - of the maximum value that can be stored in the compiler's "unsigned int" - type, but there is no limit to the number of chunks. Note however that the - strm.total_in and strm_total_out counters may be limited to 4 GB. These - counters are provided as a convenience and are not used internally by - inflate() or deflate(). The application can easily set up its own counters - updated after each call of inflate() or deflate() to count beyond 4 GB. - compress() and uncompress() may be limited to 4 GB, since they operate in a - single call. gzseek() and gztell() may be limited to 4 GB depending on how - zlib is compiled. See the zlibCompileFlags() function in zlib.h. - - The word "may" appears several times above since there is a 4 GB limit - only if the compiler's "long" type is 32 bits. If the compiler's "long" - type is 64 bits, then the limit is 16 exabytes. - -33. Does zlib have any security vulnerabilities? - - The only one that we are aware of is potentially in gzprintf(). If zlib - is compiled to use sprintf() or vsprintf(), then there is no protection - against a buffer overflow of a 4K string space, other than the caller of - gzprintf() assuring that the output will not exceed 4K. On the other - hand, if zlib is compiled to use snprintf() or vsnprintf(), which should - normally be the case, then there is no vulnerability. The ./configure - script will display warnings if an insecure variation of sprintf() will - be used by gzprintf(). Also the zlibCompileFlags() function will return - information on what variant of sprintf() is used by gzprintf(). - - If you don't have snprintf() or vsnprintf() and would like one, you can - find a portable implementation here: - - http://www.ijs.si/software/snprintf/ - - Note that you should be using the most recent version of zlib. Versions - 1.1.3 and before were subject to a double-free vulnerability. - -34. Is there a Java version of zlib? - - Probably what you want is to use zlib in Java. zlib is already included - as part of the Java SDK in the java.util.zip package. If you really want - a version of zlib written in the Java language, look on the zlib home - page for links: http://www.zlib.org/ - -35. I get this or that compiler or source-code scanner warning when I crank it - up to maximally-pedantic. Can't you guys write proper code? - - Many years ago, we gave up attempting to avoid warnings on every compiler - in the universe. It just got to be a waste of time, and some compilers - were downright silly. So now, we simply make sure that the code always - works. - -36. Valgrind (or some similar memory access checker) says that deflate is - performing a conditional jump that depends on an uninitialized value. - Isn't that a bug? - - No. That is intentional for performance reasons, and the output of - deflate is not affected. This only started showing up recently since - zlib 1.2.x uses malloc() by default for allocations, whereas earlier - versions used calloc(), which zeros out the allocated memory. - -37. Will zlib read the (insert any ancient or arcane format here) compressed - data format? - - Probably not. Look in the comp.compression FAQ for pointers to various - formats and associated software. - -38. How can I encrypt/decrypt zip files with zlib? - - zlib doesn't support encryption. The original PKZIP encryption is very weak - and can be broken with freely available programs. To get strong encryption, - use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. - For PKZIP compatible "encryption", look at http://www.info-zip.org/ - -39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? - - "gzip" is the gzip format, and "deflate" is the zlib format. They should - probably have called the second one "zlib" instead to avoid confusion - with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 - correctly points to the zlib specification in RFC 1950 for the "deflate" - transfer encoding, there have been reports of servers and browsers that - incorrectly produce or expect raw deflate data per the deflate - specficiation in RFC 1951, most notably Microsoft. So even though the - "deflate" transfer encoding using the zlib format would be the more - efficient approach (and in fact exactly what the zlib format was designed - for), using the "gzip" transfer encoding is probably more reliable due to - an unfortunate choice of name on the part of the HTTP 1.1 authors. - - Bottom line: use the gzip format for HTTP 1.1 encoding. - -40. Does zlib support the new "Deflate64" format introduced by PKWare? - - No. PKWare has apparently decided to keep that format proprietary, since - they have not documented it as they have previous compression formats. - In any case, the compression improvements are so modest compared to other - more modern approaches, that it's not worth the effort to implement. - -41. Can you please sign these lengthy legal documents and fax them back to us - so that we can use your software in our product? - - No. Go away. Shoo. diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/INDEX b/components/dfs/filesystems/jffs2/cyg/compress/src/INDEX deleted file mode 100644 index 0587e5902b..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/INDEX +++ /dev/null @@ -1,51 +0,0 @@ -ChangeLog history of changes -FAQ Frequently Asked Questions about zlib -INDEX this file -Makefile makefile for Unix (generated by configure) -Makefile.in makefile for Unix (template for configure) -README guess what -algorithm.txt description of the (de)compression algorithm -configure configure script for Unix -zconf.in.h template for zconf.h (used by configure) - -amiga/ makefiles for Amiga SAS C -as400/ makefiles for IBM AS/400 -msdos/ makefiles for MSDOS -old/ makefiles for various architectures and zlib documentation - files that have not yet been updated for zlib 1.2.x -projects/ projects for various Integrated Development Environments -qnx/ makefiles for QNX -win32/ makefiles for Windows - - zlib public header files (must be kept): -zconf.h -zlib.h - - private source files used to build the zlib library: -adler32.c -compress.c -crc32.c -crc32.h -deflate.c -deflate.h -gzio.c -infback.c -inffast.c -inffast.h -inffixed.h -inflate.c -inflate.h -inftrees.c -inftrees.h -trees.c -trees.h -uncompr.c -zutil.c -zutil.h - - source files for sample programs: -example.c -minigzip.c - - unsupported contribution by third parties -See contrib/README.contrib diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/Make_vms.com b/components/dfs/filesystems/jffs2/cyg/compress/src/Make_vms.com deleted file mode 100644 index c2a1fb54b2..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/Make_vms.com +++ /dev/null @@ -1,461 +0,0 @@ -$! make libz under VMS written by -$! Martin P.J. Zinser -$! -$! -$ on error then goto err_exit -$! -$! -$! Just some general constants... -$! -$ true = 1 -$ false = 0 -$ tmpnam = "temp_" + f$getjpi("","pid") -$ SAY = "WRITE SYS$OUTPUT" -$! -$! Setup variables holding "config" information -$! -$ Make = "" -$ name = "Zlib" -$ version = "?.?.?" -$ v_string = "ZLIB_VERSION" -$ v_file = "zlib.h" -$ ccopt = "" -$ lopts = "" -$ linkonly = false -$ optfile = name + ".opt" -$ its_decc = false -$ its_vaxc = false -$ its_gnuc = false -$ axp = f$getsyi("HW_MODEL").ge.1024 -$ s_case = false -$! Check for MMK/MMS -$! -$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" -$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" -$! -$! -$ gosub find_version -$! -$ gosub check_opts -$! -$! Look for the compiler used -$! -$ gosub check_compiler -$ if its_decc -$ then -$ ccopt = "/prefix=all" + ccopt -$ if f$trnlnm("SYS") .eqs. "" -$ then -$ if axp -$ then -$ define sys sys$library: -$ else -$ ccopt = "/decc" + ccopt -$ define sys decc$library_include: -$ endif -$ endif -$ endif -$ if its_vaxc .or. its_gnuc -$ then -$ if f$trnlnm("SYS").eqs."" then define sys sys$library: -$ endif -$! -$! Build the thing plain or with mms -$! -$ write sys$output "Compiling Zlib sources ..." -$ if make.eqs."" -$ then -$ dele example.obj;*,minigzip.obj;* -$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - - adler32.c zlib.h zconf.h -$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - - compress.c zlib.h zconf.h -$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - - crc32.c zlib.h zconf.h -$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - - deflate.c deflate.h zutil.h zlib.h zconf.h -$ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" - - gzio.c zutil.h zlib.h zconf.h -$ CALL MAKE infback.OBJ "CC ''CCOPT' infback" - - infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h -$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - - inffast.c zutil.h zlib.h zconf.h inffast.h -$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - - inflate.c zutil.h zlib.h zconf.h infblock.h -$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - - inftrees.c zutil.h zlib.h zconf.h inftrees.h -$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - - trees.c deflate.h zutil.h zlib.h zconf.h -$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - - uncompr.c zlib.h zconf.h -$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - - zutil.c zutil.h zlib.h zconf.h -$ write sys$output "Building Zlib ..." -$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ -$ write sys$output "Building example..." -$ CALL MAKE example.OBJ "CC ''CCOPT' example" - - example.c zlib.h zconf.h -$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb -$ if f$search("x11vms:xvmsutils.olb") .nes. "" -$ then -$ write sys$output "Building minigzip..." -$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" - - minigzip.c zlib.h zconf.h -$ call make minigzip.exe - - "LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" - - minigzip.obj libz.olb -$ endif -$ else -$ gosub crea_mms -$ SAY "Make ''name' ''version' with ''Make' " -$ 'make' -$ endif -$! -$! Alpha gets a shareable image -$! -$ If axp -$ Then -$ gosub crea_olist -$ write sys$output "Creating libzshr.exe" -$ call anal_obj_axp modules.opt _link.opt -$ if s_case -$ then -$ open/append optf modules.opt -$ write optf "case_sensitive=YES" -$ close optf -$ endif -$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,_link.opt/opt -$ endif -$ write sys$output "Zlib build completed" -$ exit -$CC_ERR: -$ write sys$output "C compiler required to build ''name'" -$ goto err_exit -$ERR_EXIT: -$ set message/facil/ident/sever/text -$ write sys$output "Exiting..." -$ exit 2 -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 - P8 What it depends on -$ -$ If F$Search(P1) .Eqs. "" Then Goto Makeit -$ Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(0) -$ write sys$output P2 -$ 'P2 -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE -$!------------------------------------------------------------------------------ -$! -$! Check command line options and set symbols accordingly -$! -$ CHECK_OPTS: -$ i = 1 -$ OPT_LOOP: -$ if i .lt. 9 -$ then -$ cparm = f$edit(p'i',"upcase") -$ if cparm .eqs. "DEBUG" -$ then -$ ccopt = ccopt + "/noopt/deb" -$ lopts = lopts + "/deb" -$ endif -$ if f$locate("CCOPT=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ ccopt = ccopt + f$extract(start,len,cparm) -$ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) - - then s_case = true -$ endif -$ if cparm .eqs. "LINK" then linkonly = true -$ if f$locate("LOPTS=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ lopts = lopts + f$extract(start,len,cparm) -$ endif -$ if f$locate("CC=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ cc_com = f$extract(start,len,cparm) - if (cc_com .nes. "DECC") .and. - - (cc_com .nes. "VAXC") .and. - - (cc_com .nes. "GNUC") -$ then -$ write sys$output "Unsupported compiler choice ''cc_com' ignored" -$ write sys$output "Use DECC, VAXC, or GNUC instead" -$ else -$ if cc_com .eqs. "DECC" then its_decc = true -$ if cc_com .eqs. "VAXC" then its_vaxc = true -$ if cc_com .eqs. "GNUC" then its_gnuc = true -$ endif -$ endif -$ if f$locate("MAKE=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ mmks = f$extract(start,len,cparm) -$ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS") -$ then -$ make = mmks -$ else -$ write sys$output "Unsupported make choice ''mmks' ignored" -$ write sys$output "Use MMK or MMS instead" -$ endif -$ endif -$ i = i + 1 -$ goto opt_loop -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Look for the compiler used -$! -$CHECK_COMPILER: -$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) -$ then -$ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "") -$ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "") -$ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "") -$ endif -$! -$! Exit if no compiler available -$! -$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) -$ then goto CC_ERR -$ else -$ if its_decc then write sys$output "CC compiler check ... Compaq C" -$ if its_vaxc then write sys$output "CC compiler check ... VAX C" -$ if its_gnuc then write sys$output "CC compiler check ... GNU C" -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! If MMS/MMK are available dump out the descrip.mms if required -$! -$CREA_MMS: -$ write sys$output "Creating descrip.mms..." -$ create descrip.mms -$ open/append out descrip.mms -$ copy sys$input: out -$ deck -# descrip.mms: MMS description file for building zlib on VMS -# written by Martin P.J. Zinser -# - -OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj, infback.obj\ - deflate.obj, trees.obj, zutil.obj, inflate.obj, \ - inftrees.obj, inffast.obj - -$ eod -$ write out "CFLAGS=", ccopt -$ write out "LOPTS=", lopts -$ copy sys$input: out -$ deck - -all : example.exe minigzip.exe libz.olb - @ write sys$output " Example applications available" - -libz.olb : libz.olb($(OBJS)) - @ write sys$output " libz available" - -example.exe : example.obj libz.olb - link $(LOPTS) example,libz.olb/lib - -minigzip.exe : minigzip.obj libz.olb - link $(LOPTS) minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib - -clean : - delete *.obj;*,libz.olb;*,*.opt;*,*.exe;* - - -# Other dependencies. -adler32.obj : adler32.c zutil.h zlib.h zconf.h -compress.obj : compress.c zlib.h zconf.h -crc32.obj : crc32.c zutil.h zlib.h zconf.h -deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h -example.obj : example.c zlib.h zconf.h -gzio.obj : gzio.c zutil.h zlib.h zconf.h -inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h -inflate.obj : inflate.c zutil.h zlib.h zconf.h -inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h -minigzip.obj : minigzip.c zlib.h zconf.h -trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h -uncompr.obj : uncompr.c zlib.h zconf.h -zutil.obj : zutil.c zutil.h zlib.h zconf.h -infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h -$ eod -$ close out -$ return -$!------------------------------------------------------------------------------ -$! -$! Read list of core library sources from makefile.in and create options -$! needed to build shareable image -$! -$CREA_OLIST: -$ open/read min makefile.in -$ open/write mod modules.opt -$ src_check = "OBJS =" -$MRLOOP: -$ read/end=mrdone min rec -$ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop -$ rec = rec - src_check -$ gosub extra_filnam -$ if (f$element(1,"\",rec) .eqs. "\") then goto mrdone -$MRSLOOP: -$ read/end=mrdone min rec -$ gosub extra_filnam -$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop -$MRDONE: -$ close min -$ close mod -$ return -$!------------------------------------------------------------------------------ -$! -$! Take record extracted in crea_olist and split it into single filenames -$! -$EXTRA_FILNAM: -$ myrec = f$edit(rec - "\", "trim,compress") -$ i = 0 -$FELOOP: -$ srcfil = f$element(i," ", myrec) -$ if (srcfil .nes. " ") -$ then -$ write mod f$parse(srcfil,,,"NAME"), ".obj" -$ i = i + 1 -$ goto feloop -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Find current Zlib version number -$! -$FIND_VERSION: -$ open/read h_in 'v_file' -$hloop: -$ read/end=hdone h_in rec -$ rec = f$edit(rec,"TRIM") -$ if (f$extract(0,1,rec) .nes. "#") then goto hloop -$ rec = f$edit(rec - "#", "TRIM") -$ if f$element(0," ",rec) .nes. "define" then goto hloop -$ if f$element(1," ",rec) .eqs. v_string -$ then -$ version = 'f$element(2," ",rec)' -$ goto hdone -$ endif -$ goto hloop -$hdone: -$ close h_in -$ return -$!------------------------------------------------------------------------------ -$! -$! Analyze Object files for OpenVMS AXP to extract Procedure and Data -$! information to build a symbol vector for a shareable image -$! All the "brains" of this logic was suggested by Hartmut Becker -$! (Hartmut.Becker@compaq.com). All the bugs were introduced by me -$! (zinser@decus.de), so if you do have problem reports please do not -$! bother Hartmut/HP, but get in touch with me -$! -$ ANAL_OBJ_AXP: Subroutine -$ V = 'F$Verify(0) -$ SAY := "WRITE_ SYS$OUTPUT" -$ -$ IF F$SEARCH("''P1'") .EQS. "" -$ THEN -$ SAY "ANAL_OBJ_AXP-E-NOSUCHFILE: Error, inputfile ''p1' not available" -$ goto exit_aa -$ ENDIF -$ IF "''P2'" .EQS. "" -$ THEN -$ SAY "ANAL_OBJ_AXP: Error, no output file provided" -$ goto exit_aa -$ ENDIF -$ -$ open/read in 'p1 -$ create a.tmp -$ open/append atmp a.tmp -$ loop: -$ read/end=end_loop in line -$ f= f$search(line) -$ if f .eqs. "" -$ then -$ write sys$output "ANAL_OBJ_AXP-w-nosuchfile, ''line'" -$ goto loop -$ endif -$ define/user sys$output nl: -$ define/user sys$error nl: -$ anal/obj/gsd 'f /out=x.tmp -$ open/read xtmp x.tmp -$ XLOOP: -$ read/end=end_xloop xtmp xline -$ xline = f$edit(xline,"compress") -$ write atmp xline -$ goto xloop -$ END_XLOOP: -$ close xtmp -$ goto loop -$ end_loop: -$ close in -$ close atmp -$ if f$search("a.tmp") .eqs. "" - - then $ exit -$ ! all global definitions -$ search a.tmp "symbol:","EGSY$V_DEF 1","EGSY$V_NORM 1"/out=b.tmp -$ ! all procedures -$ search b.tmp "EGSY$V_NORM 1"/wind=(0,1) /out=c.tmp -$ search c.tmp "symbol:"/out=d.tmp -$ define/user sys$output nl: -$ edito/edt/command=sys$input d.tmp -sub/symbol: "/symbol_vector=(/whole -sub/"/=PROCEDURE)/whole -exit -$ ! all data -$ search b.tmp "EGSY$V_DEF 1"/wind=(0,1) /out=e.tmp -$ search e.tmp "symbol:"/out=f.tmp -$ define/user sys$output nl: -$ edito/edt/command=sys$input f.tmp -sub/symbol: "/symbol_vector=(/whole -sub/"/=DATA)/whole -exit -$ sort/nodupl d.tmp,f.tmp 'p2' -$ delete a.tmp;*,b.tmp;*,c.tmp;*,d.tmp;*,e.tmp;*,f.tmp;* -$ if f$search("x.tmp") .nes. "" - - then $ delete x.tmp;* -$! -$ EXIT_AA: -$ if V then set verify -$ endsubroutine -$!------------------------------------------------------------------------------ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile b/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile deleted file mode 100644 index 2fd6e45c48..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2005 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile and test, type: -# ./configure; make test -# The call of configure is optional if you don't have special requirements -# If you wish to build zlib as a shared library, use: ./configure -s - -# To use the asm code, type: -# cp contrib/asm?86/match.S ./match.S -# make LOC=-DASMV OBJA=match.o - -# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: -# make install -# To install in $HOME instead of /usr/local, use: -# make install prefix=$HOME - -CC=cc - -CFLAGS=-O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DDEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -LDFLAGS=libz.a -LDSHARED=$(CC) -CPP=$(CC) -E - -LIBS=libz.a -SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.2.3 -SHAREDLIBM=libz.so.1 - -AR=ar rc -RANLIB=ranlib -TAR=tar -SHELL=/bin/sh -EXE= - -prefix = /usr/local -exec_prefix = ${prefix} -libdir = ${exec_prefix}/lib -includedir = ${prefix}/include -mandir = ${prefix}/share/man -man3dir = ${mandir}/man3 - -OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ - zutil.o inflate.o infback.o inftrees.o inffast.o - -OBJA = -# to use the asm code: make OBJA=match.o - -TEST_OBJS = example.o minigzip.o - -all: example$(EXE) minigzip$(EXE) - -check: test -test: all - @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ - echo hello world | ./minigzip | ./minigzip -d || \ - echo ' *** minigzip test FAILED ***' ; \ - if ./example; then \ - echo ' *** zlib test OK ***'; \ - else \ - echo ' *** zlib test FAILED ***'; \ - fi - -libz.a: $(OBJS) $(OBJA) - $(AR) $@ $(OBJS) $(OBJA) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -match.o: match.S - $(CPP) match.S > _match.s - $(CC) -c _match.s - mv _match.o match.o - rm -f _match.s - -$(SHAREDLIBV): $(OBJS) - $(LDSHARED) -o $@ $(OBJS) - rm -f $(SHAREDLIB) $(SHAREDLIBM) - ln -s $@ $(SHAREDLIB) - ln -s $@ $(SHAREDLIBM) - -example$(EXE): example.o $(LIBS) - $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) - -minigzip$(EXE): minigzip.o $(LIBS) - $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) - -install: $(LIBS) - -@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi - -@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi - -@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi - -@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi - cp zlib.h zconf.h $(includedir) - chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h - cp $(LIBS) $(libdir) - cd $(libdir); chmod 755 $(LIBS) - -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 - cd $(libdir); if test -f $(SHAREDLIBV); then \ - rm -f $(SHAREDLIB) $(SHAREDLIBM); \ - ln -s $(SHAREDLIBV) $(SHAREDLIB); \ - ln -s $(SHAREDLIBV) $(SHAREDLIBM); \ - (ldconfig || true) >/dev/null 2>&1; \ - fi - cp zlib.3 $(man3dir) - chmod 644 $(man3dir)/zlib.3 -# The ranlib in install is needed on NeXTSTEP which checks file times -# ldconfig is for Linux - -uninstall: - cd $(includedir); \ - cd $(libdir); rm -f libz.a; \ - if test -f $(SHAREDLIBV); then \ - rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ - fi - cd $(man3dir); rm -f zlib.3 - -mostlyclean: clean -clean: - rm -f *.o *~ example$(EXE) minigzip$(EXE) \ - libz.* foo.gz so_locations \ - _match.s maketree contrib/infback9/*.o - -maintainer-clean: distclean -distclean: clean - cp -p Makefile.in Makefile - cp -p zconf.in.h zconf.h - rm -f .DS_Store - -tags: - etags *.[ch] - -depend: - makedepend -- $(CFLAGS) -- *.[ch] - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: crc32.h zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -example.o: zlib.h zconf.h -gzio.o: zutil.h zlib.h zconf.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -minigzip.o: zlib.h zconf.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.in b/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.in deleted file mode 100644 index 2fd6e45c48..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.in +++ /dev/null @@ -1,154 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2005 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile and test, type: -# ./configure; make test -# The call of configure is optional if you don't have special requirements -# If you wish to build zlib as a shared library, use: ./configure -s - -# To use the asm code, type: -# cp contrib/asm?86/match.S ./match.S -# make LOC=-DASMV OBJA=match.o - -# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: -# make install -# To install in $HOME instead of /usr/local, use: -# make install prefix=$HOME - -CC=cc - -CFLAGS=-O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DDEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -LDFLAGS=libz.a -LDSHARED=$(CC) -CPP=$(CC) -E - -LIBS=libz.a -SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.2.3 -SHAREDLIBM=libz.so.1 - -AR=ar rc -RANLIB=ranlib -TAR=tar -SHELL=/bin/sh -EXE= - -prefix = /usr/local -exec_prefix = ${prefix} -libdir = ${exec_prefix}/lib -includedir = ${prefix}/include -mandir = ${prefix}/share/man -man3dir = ${mandir}/man3 - -OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ - zutil.o inflate.o infback.o inftrees.o inffast.o - -OBJA = -# to use the asm code: make OBJA=match.o - -TEST_OBJS = example.o minigzip.o - -all: example$(EXE) minigzip$(EXE) - -check: test -test: all - @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ - echo hello world | ./minigzip | ./minigzip -d || \ - echo ' *** minigzip test FAILED ***' ; \ - if ./example; then \ - echo ' *** zlib test OK ***'; \ - else \ - echo ' *** zlib test FAILED ***'; \ - fi - -libz.a: $(OBJS) $(OBJA) - $(AR) $@ $(OBJS) $(OBJA) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -match.o: match.S - $(CPP) match.S > _match.s - $(CC) -c _match.s - mv _match.o match.o - rm -f _match.s - -$(SHAREDLIBV): $(OBJS) - $(LDSHARED) -o $@ $(OBJS) - rm -f $(SHAREDLIB) $(SHAREDLIBM) - ln -s $@ $(SHAREDLIB) - ln -s $@ $(SHAREDLIBM) - -example$(EXE): example.o $(LIBS) - $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) - -minigzip$(EXE): minigzip.o $(LIBS) - $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) - -install: $(LIBS) - -@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi - -@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi - -@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi - -@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi - cp zlib.h zconf.h $(includedir) - chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h - cp $(LIBS) $(libdir) - cd $(libdir); chmod 755 $(LIBS) - -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 - cd $(libdir); if test -f $(SHAREDLIBV); then \ - rm -f $(SHAREDLIB) $(SHAREDLIBM); \ - ln -s $(SHAREDLIBV) $(SHAREDLIB); \ - ln -s $(SHAREDLIBV) $(SHAREDLIBM); \ - (ldconfig || true) >/dev/null 2>&1; \ - fi - cp zlib.3 $(man3dir) - chmod 644 $(man3dir)/zlib.3 -# The ranlib in install is needed on NeXTSTEP which checks file times -# ldconfig is for Linux - -uninstall: - cd $(includedir); \ - cd $(libdir); rm -f libz.a; \ - if test -f $(SHAREDLIBV); then \ - rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ - fi - cd $(man3dir); rm -f zlib.3 - -mostlyclean: clean -clean: - rm -f *.o *~ example$(EXE) minigzip$(EXE) \ - libz.* foo.gz so_locations \ - _match.s maketree contrib/infback9/*.o - -maintainer-clean: distclean -distclean: clean - cp -p Makefile.in Makefile - cp -p zconf.in.h zconf.h - rm -f .DS_Store - -tags: - etags *.[ch] - -depend: - makedepend -- $(CFLAGS) -- *.[ch] - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: crc32.h zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -example.o: zlib.h zconf.h -gzio.o: zutil.h zlib.h zconf.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -minigzip.o: zlib.h zconf.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.riscos b/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.riscos deleted file mode 100644 index d97f449237..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/Makefile.riscos +++ /dev/null @@ -1,151 +0,0 @@ -# Project: zlib_1_03 -# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 -# test works out-of-the-box, installs `somewhere' on demand - -# Toolflags: -CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah -C++flags = -c -depend !Depend -IC: -throwback -Linkflags = -aif -c++ -o $@ -ObjAsmflags = -throwback -NoCache -depend !Depend -CMHGflags = -LibFileflags = -c -l -o $@ -Squeezeflags = -o $@ - -# change the line below to where _you_ want the library installed. -libdest = lib:zlib - -# Final targets: -@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ - @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ - @.o.uncompr @.o.zutil - LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ - @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ - @.o.trees @.o.uncompr @.o.zutil -test: @.minigzip @.example @.lib - @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV - @echo running tests: hang on. - @/@.minigzip -f -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -f -1 libc - @/@.minigzip -d libc-gz - @/@.minigzip -h -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -h -1 libc - @/@.minigzip -d libc-gz - @/@.minigzip -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -1 libc - @/@.minigzip -d libc-gz - @diff @.lib @.libc - @echo that should have reported '@.lib and @.libc identical' if you have diff. - @/@.example @.fred @.fred - @echo that will have given lots of hello!'s. - -@.minigzip: @.o.minigzip @.lib C:o.Stubs - Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs -@.example: @.o.example @.lib C:o.Stubs - Link $(Linkflags) @.o.example @.lib C:o.Stubs - -install: @.lib - cdir $(libdest) - cdir $(libdest).h - @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV - @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV - @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV - @echo okay, installed zlib in $(libdest) - -clean:; remove @.minigzip - remove @.example - remove @.libc - -wipe @.o.* F~r~cV - remove @.fred - -# User-editable dependencies: -.c.o: - cc $(ccflags) -o $@ $< - -# Static dependencies: - -# Dynamic dependencies: -o.example: c.example -o.example: h.zlib -o.example: h.zconf -o.minigzip: c.minigzip -o.minigzip: h.zlib -o.minigzip: h.zconf -o.adler32: c.adler32 -o.adler32: h.zlib -o.adler32: h.zconf -o.compress: c.compress -o.compress: h.zlib -o.compress: h.zconf -o.crc32: c.crc32 -o.crc32: h.zlib -o.crc32: h.zconf -o.deflate: c.deflate -o.deflate: h.deflate -o.deflate: h.zutil -o.deflate: h.zlib -o.deflate: h.zconf -o.gzio: c.gzio -o.gzio: h.zutil -o.gzio: h.zlib -o.gzio: h.zconf -o.infblock: c.infblock -o.infblock: h.zutil -o.infblock: h.zlib -o.infblock: h.zconf -o.infblock: h.infblock -o.infblock: h.inftrees -o.infblock: h.infcodes -o.infblock: h.infutil -o.infcodes: c.infcodes -o.infcodes: h.zutil -o.infcodes: h.zlib -o.infcodes: h.zconf -o.infcodes: h.inftrees -o.infcodes: h.infblock -o.infcodes: h.infcodes -o.infcodes: h.infutil -o.infcodes: h.inffast -o.inffast: c.inffast -o.inffast: h.zutil -o.inffast: h.zlib -o.inffast: h.zconf -o.inffast: h.inftrees -o.inffast: h.infblock -o.inffast: h.infcodes -o.inffast: h.infutil -o.inffast: h.inffast -o.inflate: c.inflate -o.inflate: h.zutil -o.inflate: h.zlib -o.inflate: h.zconf -o.inflate: h.infblock -o.inftrees: c.inftrees -o.inftrees: h.zutil -o.inftrees: h.zlib -o.inftrees: h.zconf -o.inftrees: h.inftrees -o.inftrees: h.inffixed -o.infutil: c.infutil -o.infutil: h.zutil -o.infutil: h.zlib -o.infutil: h.zconf -o.infutil: h.infblock -o.infutil: h.inftrees -o.infutil: h.infcodes -o.infutil: h.infutil -o.trees: c.trees -o.trees: h.deflate -o.trees: h.zutil -o.trees: h.zlib -o.trees: h.zconf -o.trees: h.trees -o.uncompr: c.uncompr -o.uncompr: h.zlib -o.uncompr: h.zconf -o.zutil: c.zutil -o.zutil: h.zutil -o.zutil: h.zlib -o.zutil: h.zconf diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/README b/components/dfs/filesystems/jffs2/cyg/compress/src/README deleted file mode 100644 index 758cc50020..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/README +++ /dev/null @@ -1,125 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.3 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). These documents are also available in other -formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file example.c which also tests that the library -is working correctly. Another example is given in the file minigzip.c. The -compression library itself is composed of all source files except example.c and -minigzip.c. - -To compile all files and run the test program, follow the instructions given at -the top of Makefile. In short "make test; make install" should work for most -machines. For Unix: "./configure; make test; make install". For MSDOS, use one -of the special makefiles such as Makefile.msc. For VMS, use make_vms.com. - -Questions about zlib should be sent to , or to Gilles Vollant - for the Windows DLL version. The zlib home page is -http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, -please check this site to verify that you have the latest version of zlib; -otherwise get the latest version and check whether the problem still exists or -not. - -PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking -for help. - -Mark Nelson wrote an article about zlib for the Jan. 1997 -issue of Dr. Dobb's Journal; a copy of the article is available in -http://dogma.net/markn/articles/zlibtool/zlibtool.htm - -The changes made in version 1.2.3 are documented in the file ChangeLog. - -Unsupported third party contributions are provided in directory "contrib". - -A Java implementation of zlib is available in the Java Development Kit -http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html -See the zlib home page http://www.zlib.org for details. - -A Perl interface to zlib written by Paul Marquess is in the -CPAN (Comprehensive Perl Archive Network) sites -http://www.cpan.org/modules/by-module/Compress/ - -A Python interface to zlib written by A.M. Kuchling is -available in Python 1.5 and later versions, see -http://www.python.org/doc/lib/module-zlib.html - -A zlib binding for TCL written by Andreas Kupries is -availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html - -An experimental package to read and write files in .zip format, written on top -of zlib by Gilles Vollant , is available in the -contrib/minizip directory of zlib. - - -Notes for some targets: - -- For Windows DLL versions, please see win32/DLL_FAQ.txt - -- For 64-bit Irix, deflate.c must be compiled without any optimization. With - -O, one libpng test fails. The test works in 32 bit mode (with the -n32 - compiler flag). The compiler bug has been reported to SGI. - -- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works - when compiled with cc. - -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is - necessary to get gzprintf working correctly. This is done by configure. - -- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - other compilers. Use "make test" to check your compiler. - -- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. - -- For PalmOs, see http://palmzlib.sourceforge.net/ - -- When building a shared, i.e. dynamic library on Mac OS X, the library must be - installed before testing (do "make install" before "make test"), since the - library location is specified in the library. - - -Acknowledgments: - - The deflate format used by zlib was defined by Phil Katz. The deflate - and zlib specifications were written by L. Peter Deutsch. Thanks to all the - people who reported problems and suggested various improvements in zlib; - they are too numerous to cite here. - -Copyright notice: - - (C) 1995-2004 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* -receiving lengthy legal documents to sign. The sources are provided -for free but without warranty of any kind. The library has been -entirely written by Jean-loup Gailly and Mark Adler; it does not -include third-party code. - -If you redistribute modified sources, we would appreciate that you include -in the file ChangeLog history information documenting your changes. Please -read the FAQ for more information on the distribution of modified source -versions. diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/README.eCos b/components/dfs/filesystems/jffs2/cyg/compress/src/README.eCos deleted file mode 100644 index 88011312f9..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/README.eCos +++ /dev/null @@ -1,27 +0,0 @@ -See the main site http://www.gzip.org/zlib/ for places to download the -complete sources. Currently based on zlib-1.2.3 - -Note that these are not the complete zlib sources - the following -directories have been deleted since they are irrelevant for the -eCos support: - -amiga/ -as400/ -contrib/ -msdos/ -old/ -projects/ -qnx/ -win32/ - -Additionally, local changes has been made to the remaining files. Code -changes are marked by __ECOS__ (comments or definitions). Finally, the -headers zlib.h and zconf.h have been moved out of the directory into -../include. - -crc32.c + crc32.h has also been removed as it is provided by services/crc/. - -Note: zconf.h always defines __ECOS__. This is necessary to support -programs built outside of the eCos tree which may wish to use this -library (so those programs needn't worry about defining __ECOS__) - diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/adler32.c b/components/dfs/filesystems/jffs2/cyg/compress/src/adler32.c deleted file mode 100644 index 2522ee2120..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/adler32.c +++ /dev/null @@ -1,153 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#ifdef __ECOS__ -#include -#else -#include "zlib.h" -#endif // __ECOS__ - -#define BASE 65521UL /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* use NO_DIVIDE if your processor does not do division in hardware */ -#ifdef NO_DIVIDE -# define MOD(a) \ - do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD4(a) \ - do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD4(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 > BASE) sum1 -= BASE; - if (sum1 > BASE) sum1 -= BASE; - if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); - if (sum2 > BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/algorithm.txt b/components/dfs/filesystems/jffs2/cyg/compress/src/algorithm.txt deleted file mode 100644 index b022dde312..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/algorithm.txt +++ /dev/null @@ -1,209 +0,0 @@ -1. Compression algorithm (deflate) - -The deflation algorithm used by gzip (also zip and zlib) is a variation of -LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in -the input data. The second occurrence of a string is replaced by a -pointer to the previous string, in the form of a pair (distance, -length). Distances are limited to 32K bytes, and lengths are limited -to 258 bytes. When a string does not occur anywhere in the previous -32K bytes, it is emitted as a sequence of literal bytes. (In this -description, `string' must be taken as an arbitrary sequence of bytes, -and is not restricted to printable characters.) - -Literals or match lengths are compressed with one Huffman tree, and -match distances are compressed with another tree. The trees are stored -in a compact form at the start of each block. The blocks can have any -size (except that the compressed data for one block must fit in -available memory). A block is terminated when deflate() determines that -it would be useful to start another block with fresh trees. (This is -somewhat similar to the behavior of LZW-based _compress_.) - -Duplicated strings are found using a hash table. All input strings of -length 3 are inserted in the hash table. A hash index is computed for -the next 3 bytes. If the hash chain for this index is not empty, all -strings in the chain are compared with the current input string, and -the longest match is selected. - -The hash chains are searched starting with the most recent strings, to -favor small distances and thus take advantage of the Huffman encoding. -The hash chains are singly linked. There are no deletions from the -hash chains, the algorithm simply discards matches that are too old. - -To avoid a worst-case situation, very long hash chains are arbitrarily -truncated at a certain length, determined by a runtime option (level -parameter of deflateInit). So deflate() does not always find the longest -possible match but generally finds a match which is long enough. - -deflate() also defers the selection of matches with a lazy evaluation -mechanism. After a match of length N has been found, deflate() searches for -a longer match at the next input byte. If a longer match is found, the -previous match is truncated to a length of one (thus producing a single -literal byte) and the process of lazy evaluation begins again. Otherwise, -the original match is kept, and the next match search is attempted only N -steps later. - -The lazy match evaluation is also subject to a runtime parameter. If -the current match is long enough, deflate() reduces the search for a longer -match, thus speeding up the whole process. If compression ratio is more -important than speed, deflate() attempts a complete second search even if -the first match is already long enough. - -The lazy match evaluation is not performed for the fastest compression -modes (level parameter 1 to 3). For these fast modes, new strings -are inserted in the hash table only when no match was found, or -when the match is not too long. This degrades the compression ratio -but saves time since there are both fewer insertions and fewer searches. - - -2. Decompression algorithm (inflate) - -2.1 Introduction - -The key question is how to represent a Huffman code (or any prefix code) so -that you can decode fast. The most important characteristic is that shorter -codes are much more common than longer codes, so pay attention to decoding the -short codes fast, and let the long codes take longer to decode. - -inflate() sets up a first level table that covers some number of bits of -input less than the length of longest code. It gets that many bits from the -stream, and looks it up in the table. The table will tell if the next -code is that many bits or less and how many, and if it is, it will tell -the value, else it will point to the next level table for which inflate() -grabs more bits and tries to decode a longer code. - -How many bits to make the first lookup is a tradeoff between the time it -takes to decode and the time it takes to build the table. If building the -table took no time (and if you had infinite memory), then there would only -be a first level table to cover all the way to the longest code. However, -building the table ends up taking a lot longer for more bits since short -codes are replicated many times in such a table. What inflate() does is -simply to make the number of bits in the first table a variable, and then -to set that variable for the maximum speed. - -For inflate, which has 286 possible codes for the literal/length tree, the size -of the first table is nine bits. Also the distance trees have 30 possible -values, and the size of the first table is six bits. Note that for each of -those cases, the table ended up one bit longer than the ``average'' code -length, i.e. the code length of an approximately flat code which would be a -little more than eight bits for 286 symbols and a little less than five bits -for 30 symbols. - - -2.2 More details on the inflate table lookup - -Ok, you want to know what this cleverly obfuscated inflate tree actually -looks like. You are correct that it's not a Huffman tree. It is simply a -lookup table for the first, let's say, nine bits of a Huffman symbol. The -symbol could be as short as one bit or as long as 15 bits. If a particular -symbol is shorter than nine bits, then that symbol's translation is duplicated -in all those entries that start with that symbol's bits. For example, if the -symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a -symbol is nine bits long, it appears in the table once. - -If the symbol is longer than nine bits, then that entry in the table points -to another similar table for the remaining bits. Again, there are duplicated -entries as needed. The idea is that most of the time the symbol will be short -and there will only be one table look up. (That's whole idea behind data -compression in the first place.) For the less frequent long symbols, there -will be two lookups. If you had a compression method with really long -symbols, you could have as many levels of lookups as is efficient. For -inflate, two is enough. - -So a table entry either points to another table (in which case nine bits in -the above example are gobbled), or it contains the translation for the symbol -and the number of bits to gobble. Then you start again with the next -ungobbled bit. - -You may wonder: why not just have one lookup table for how ever many bits the -longest symbol is? The reason is that if you do that, you end up spending -more time filling in duplicate symbol entries than you do actually decoding. -At least for deflate's output that generates new trees every several 10's of -kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code -would take too long if you're only decoding several thousand symbols. At the -other extreme, you could make a new table for every bit in the code. In fact, -that's essentially a Huffman tree. But then you spend two much time -traversing the tree while decoding, even for short symbols. - -So the number of bits for the first lookup table is a trade of the time to -fill out the table vs. the time spent looking at the second level and above of -the table. - -Here is an example, scaled down: - -The code being decoded, with 10 symbols, from 1 to 6 bits long: - -A: 0 -B: 10 -C: 1100 -D: 11010 -E: 11011 -F: 11100 -G: 11101 -H: 11110 -I: 111110 -J: 111111 - -Let's make the first table three bits long (eight entries): - -000: A,1 -001: A,1 -010: A,1 -011: A,1 -100: B,2 -101: B,2 -110: -> table X (gobble 3 bits) -111: -> table Y (gobble 3 bits) - -Each entry is what the bits decode as and how many bits that is, i.e. how -many bits to gobble. Or the entry points to another table, with the number of -bits to gobble implicit in the size of the table. - -Table X is two bits long since the longest code starting with 110 is five bits -long: - -00: C,1 -01: C,1 -10: D,2 -11: E,2 - -Table Y is three bits long since the longest code starting with 111 is six -bits long: - -000: F,2 -001: F,2 -010: G,2 -011: G,2 -100: H,2 -101: H,2 -110: I,3 -111: J,3 - -So what we have here are three tables with a total of 20 entries that had to -be constructed. That's compared to 64 entries for a single table. Or -compared to 16 entries for a Huffman tree (six two entry tables and one four -entry table). Assuming that the code ideally represents the probability of -the symbols, it takes on the average 1.25 lookups per symbol. That's compared -to one lookup for the single table, or 1.66 lookups per symbol for the -Huffman tree. - -There, I think that gives you a picture of what's going on. For inflate, the -meaning of a particular symbol is often more than just a letter. It can be a -byte (a "literal"), or it can be either a length or a distance which -indicates a base value and a number of bits to fetch after the code that is -added to the base value. Or it might be the special end-of-block code. The -data structures created in inftrees.c try to encode all that information -compactly in the tables. - - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -References: - -[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data -Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, -pp. 337-343. - -``DEFLATE Compressed Data Format Specification'' available in -http://www.ietf.org/rfc/rfc1951.txt diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/compress.c b/components/dfs/filesystems/jffs2/cyg/compress/src/compress.c deleted file mode 100644 index f94974537f..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/compress.c +++ /dev/null @@ -1,83 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#ifdef __ECOS__ -#include -#else -#include "zlib.h" -#endif // __ECOS__ - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; - int level; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = deflateInit(&stream, level); - if (err != Z_OK) return err; - - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = deflateEnd(&stream); - return err; -} - -/* =========================================================================== - */ -int ZEXPORT compress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} - -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ -uLong ZEXPORT compressBound (sourceLen) - uLong sourceLen; -{ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/configure b/components/dfs/filesystems/jffs2/cyg/compress/src/configure deleted file mode 100644 index d7ffdc3458..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/configure +++ /dev/null @@ -1,459 +0,0 @@ -#!/bin/sh -# configure script for zlib. This script is needed only if -# you wish to build a shared library and your system supports them, -# of if you need special compiler, flags or install directory. -# Otherwise, you can just use directly "make test; make install" -# -# To create a shared library, use "configure --shared"; by default a static -# library is created. If the primitive shared library support provided here -# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz -# -# To impose specific compiler or flags or install directory, use for example: -# prefix=$HOME CC=cc CFLAGS="-O4" ./configure -# or for csh/tcsh users: -# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) -# LDSHARED is the command to be used to create a shared library - -# Incorrect settings of CC or CFLAGS may prevent creating a shared library. -# If you have problems, try without defining CC and CFLAGS before reporting -# an error. - -LIBS=libz.a -LDFLAGS="-L. ${LIBS}" -VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h` -VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h` -VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h` -AR=${AR-"ar rc"} -RANLIB=${RANLIB-"ranlib"} -prefix=${prefix-/usr/local} -exec_prefix=${exec_prefix-'${prefix}'} -libdir=${libdir-'${exec_prefix}/lib'} -includedir=${includedir-'${prefix}/include'} -mandir=${mandir-'${prefix}/share/man'} -shared_ext='.so' -shared=0 -gcc=0 -old_cc="$CC" -old_cflags="$CFLAGS" - -while test $# -ge 1 -do -case "$1" in - -h* | --h*) - echo 'usage:' - echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]' - echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR]' - exit 0;; - -p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; - -e*=* | --e*=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; - -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; - -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;; - -p* | --p*) prefix="$2"; shift; shift;; - -e* | --e*) exec_prefix="$2"; shift; shift;; - -l* | --l*) libdir="$2"; shift; shift;; - -i* | --i*) includedir="$2"; shift; shift;; - -s* | --s*) shared=1; shift;; - *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;; - esac -done - -test=ztest$$ -cat > $test.c </dev/null; then - CC="$cc" - SFLAGS=${CFLAGS-"-fPIC -O3"} - CFLAGS="$cflags" - case `(uname -s || echo unknown) 2>/dev/null` in - Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1"};; - CYGWIN* | Cygwin* | cygwin* | OS/2* ) - EXE='.exe';; - QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 - # (alain.bonnefoy@icbt.com) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};; - HP-UX*) - LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so';; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl';; - esac;; - Darwin*) shared_ext='.dylib' - SHAREDLIB=libz$shared_ext - SHAREDLIBV=libz.$VER$shared_ext - SHAREDLIBM=libz.$VER1$shared_ext - LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"};; - *) LDSHARED=${LDSHARED-"$cc -shared"};; - esac -else - # find system name and corresponding cc options - CC=${CC-cc} - case `(uname -sr || echo unknown) 2>/dev/null` in - HP-UX*) SFLAGS=${CFLAGS-"-O +z"} - CFLAGS=${CFLAGS-"-O"} -# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} - LDSHARED=${LDSHARED-"ld -b"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so';; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl';; - esac;; - IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} - CFLAGS=${CFLAGS-"-ansi -O2"} - LDSHARED=${LDSHARED-"cc -shared"};; - OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} - CFLAGS=${CFLAGS-"-O -std1"} - LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};; - OSF1*) SFLAGS=${CFLAGS-"-O -std1"} - CFLAGS=${CFLAGS-"-O -std1"} - LDSHARED=${LDSHARED-"cc -shared"};; - QNX*) SFLAGS=${CFLAGS-"-4 -O"} - CFLAGS=${CFLAGS-"-4 -O"} - LDSHARED=${LDSHARED-"cc"} - RANLIB=${RANLIB-"true"} - AR="cc -A";; - SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} - CFLAGS=${CFLAGS-"-O3"} - LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};; - SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."} - CFLAGS=${CFLAGS-"-fast -xcg89"} - LDSHARED=${LDSHARED-"cc -G"};; - SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} - CFLAGS=${CFLAGS-"-O2"} - LDSHARED=${LDSHARED-"ld"};; - SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} - CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"} - LDSHARED=${LDSHARED-"cc -xarch=v9b"};; - UNIX_System_V\ 4.2.0) - SFLAGS=${CFLAGS-"-KPIC -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"};; - UNIX_SV\ 4.2MP) - SFLAGS=${CFLAGS-"-Kconform_pic -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"};; - OpenUNIX\ 5) - SFLAGS=${CFLAGS-"-KPIC -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"};; - AIX*) # Courtesy of dbakker@arrayasolutions.com - SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - LDSHARED=${LDSHARED-"xlc -G"};; - # send working options for other systems to support@gzip.org - *) SFLAGS=${CFLAGS-"-O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -shared"};; - esac -fi - -SHAREDLIB=${SHAREDLIB-"libz$shared_ext"} -SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"} -SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} - -if test $shared -eq 1; then - echo Checking for shared library support... - # we must test in two steps (cc then ld), required at least on SunOS 4.x - if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" && - test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then - CFLAGS="$SFLAGS" - LIBS="$SHAREDLIBV" - echo Building shared library $SHAREDLIBV with $CC. - elif test -z "$old_cc" -a -z "$old_cflags"; then - echo No shared library support. - shared=0; - else - echo 'No shared library support; try without defining CC and CFLAGS' - shared=0; - fi -fi -if test $shared -eq 0; then - LDSHARED="$CC" - echo Building static library $LIBS version $VER with $CC. -else - LDFLAGS="-L. ${SHAREDLIBV}" -fi - -cat > $test.c < -int main() { return 0; } -EOF -if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - sed < zconf.in.h "/HAVE_UNISTD_H/s%0%1%" > zconf.h - echo "Checking for unistd.h... Yes." -else - cp -p zconf.in.h zconf.h - echo "Checking for unistd.h... No." -fi - -cat > $test.c < -#include -#include "zconf.h" - -int main() -{ -#ifndef STDC - choke me -#endif - - return 0; -} -EOF - -if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()" - - cat > $test.c < -#include - -int mytest(char *fmt, ...) -{ - char buf[20]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return 0; -} - -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - - if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then - echo "Checking for vsnprintf() in stdio.h... Yes." - - cat >$test.c < -#include - -int mytest(char *fmt, ...) -{ - int n; - char buf[20]; - va_list ap; - - va_start(ap, fmt); - n = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return n; -} - -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - - if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - echo "Checking for return value of vsnprintf()... Yes." - else - CFLAGS="$CFLAGS -DHAS_vsnprintf_void" - echo "Checking for return value of vsnprintf()... No." - echo " WARNING: apparently vsnprintf() does not return a value. zlib" - echo " can build but will be open to possible string-format security" - echo " vulnerabilities." - fi - else - CFLAGS="$CFLAGS -DNO_vsnprintf" - echo "Checking for vsnprintf() in stdio.h... No." - echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" - echo " can build but will be open to possible buffer-overflow security" - echo " vulnerabilities." - - cat >$test.c < -#include - -int mytest(char *fmt, ...) -{ - int n; - char buf[20]; - va_list ap; - - va_start(ap, fmt); - n = vsprintf(buf, fmt, ap); - va_end(ap); - return n; -} - -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - - if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - echo "Checking for return value of vsprintf()... Yes." - else - CFLAGS="$CFLAGS -DHAS_vsprintf_void" - echo "Checking for return value of vsprintf()... No." - echo " WARNING: apparently vsprintf() does not return a value. zlib" - echo " can build but will be open to possible string-format security" - echo " vulnerabilities." - fi - fi -else - echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()" - - cat >$test.c < - -int mytest() -{ - char buf[20]; - - snprintf(buf, sizeof(buf), "%s", "foo"); - return 0; -} - -int main() -{ - return (mytest()); -} -EOF - - if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then - echo "Checking for snprintf() in stdio.h... Yes." - - cat >$test.c < - -int mytest() -{ - char buf[20]; - - return snprintf(buf, sizeof(buf), "%s", "foo"); -} - -int main() -{ - return (mytest()); -} -EOF - - if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - echo "Checking for return value of snprintf()... Yes." - else - CFLAGS="$CFLAGS -DHAS_snprintf_void" - echo "Checking for return value of snprintf()... No." - echo " WARNING: apparently snprintf() does not return a value. zlib" - echo " can build but will be open to possible string-format security" - echo " vulnerabilities." - fi - else - CFLAGS="$CFLAGS -DNO_snprintf" - echo "Checking for snprintf() in stdio.h... No." - echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" - echo " can build but will be open to possible buffer-overflow security" - echo " vulnerabilities." - - cat >$test.c < - -int mytest() -{ - char buf[20]; - - return sprintf(buf, "%s", "foo"); -} - -int main() -{ - return (mytest()); -} -EOF - - if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - echo "Checking for return value of sprintf()... Yes." - else - CFLAGS="$CFLAGS -DHAS_sprintf_void" - echo "Checking for return value of sprintf()... No." - echo " WARNING: apparently sprintf() does not return a value. zlib" - echo " can build but will be open to possible string-format security" - echo " vulnerabilities." - fi - fi -fi - -cat >$test.c < -int main() { return 0; } -EOF -if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - echo "Checking for errno.h... Yes." -else - echo "Checking for errno.h... No." - CFLAGS="$CFLAGS -DNO_ERRNO_H" -fi - -cat > $test.c < -#include -#include -caddr_t hello() { - return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0); -} -EOF -if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then - CFLAGS="$CFLAGS -DUSE_MMAP" - echo Checking for mmap support... Yes. -else - echo Checking for mmap support... No. -fi - -CPP=${CPP-"$CC -E"} -case $CFLAGS in - *ASMV*) - if test "`nm $test.o | grep _hello`" = ""; then - CPP="$CPP -DNO_UNDERLINE" - echo Checking for underline in external names... No. - else - echo Checking for underline in external names... Yes. - fi;; -esac - -rm -f $test.[co] $test $test$shared_ext - -# udpate Makefile -sed < Makefile.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^CPP *=/s#=.*#=$CPP# -/^LDSHARED *=/s#=.*#=$LDSHARED# -/^LIBS *=/s#=.*#=$LIBS# -/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# -/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# -/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# -/^AR *=/s#=.*#=$AR# -/^RANLIB *=/s#=.*#=$RANLIB# -/^EXE *=/s#=.*#=$EXE# -/^prefix *=/s#=.*#=$prefix# -/^exec_prefix *=/s#=.*#=$exec_prefix# -/^libdir *=/s#=.*#=$libdir# -/^includedir *=/s#=.*#=$includedir# -/^mandir *=/s#=.*#=$mandir# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -" > Makefile diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/deflate.c b/components/dfs/filesystems/jffs2/cyg/compress/src/deflate.c deleted file mode 100644 index 29ce1f64a5..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/deflate.c +++ /dev/null @@ -1,1736 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://www.ietf.org/rfc/rfc1951.txt - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id$ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -#ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifndef FASTEST -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif -#endif -local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); - -#ifdef DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -#ifdef FASTEST -local const config configuration_table[2] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ -#else -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ -#endif - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } -#ifdef GZIP - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } -#endif - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ - deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->wrap == 2 || - (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) - return Z_STREAM_ERROR; - - s = strm->state; - if (s->wrap) - strm->adler = adler32(strm->adler, dictionary, dictLength); - - if (length < MIN_MATCH) return Z_OK; - if (length > MAX_DIST(s)) { - length = MAX_DIST(s); - dictionary += dictLength - length; /* use the tail of the dictionary */ - } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); - } - if (hash_head) hash_head = 0; /* to make compiler happy */ - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset (strm) - z_streamp strm; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { - return Z_STREAM_ERROR; - } - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; - strm->adler = -#ifdef GZIP - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : -#endif - adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - lm_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) - z_streamp strm; - gz_headerp head; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) - z_streamp strm; - int bits; - int value; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - strm->state->bi_valid = bits; - strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if (func != configuration_table[level].func && strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_PARTIAL_FLUSH); - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= */ -int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) - z_streamp strm; - int good_length; - int max_lazy; - int nice_length; - int max_chain; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; - s->nice_match = nice_length; - s->max_chain_length = max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds - * for every combination of windowBits and memLevel, as well as wrap. - * But even the conservative upper bound of about 14% expansion does not - * seem onerous for output buffer allocation. - */ -uLong ZEXPORT deflateBound(strm, sourceLen) - z_streamp strm; - uLong sourceLen; -{ - deflate_state *s; - uLong destLen; - - /* conservative upper bound */ - destLen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; - - /* if can't get parameters, return conservative bound */ - if (strm == Z_NULL || strm->state == Z_NULL) - return destLen; - - /* if not default parameters, return conservative bound */ - s = strm->state; - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return destLen; - - /* default settings: return tight bound for that case */ - return compressBound(sourceLen); -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -local void flush_pending(strm) - z_streamp strm; -{ - unsigned len = strm->state->pending; - - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, strm->state->pending_out, len); - strm->next_out += len; - strm->state->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; - } -} - -/* ========================================================================= */ -int ZEXPORT deflate (strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_FINISH || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && flush <= old_flush && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; - - /* Write the trailer */ -#ifdef GZIP - if (s->wrap == 2) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); - put_byte(s, (Byte)(strm->total_in & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); - } - else -#endif - { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd (strm) - z_streamp strm; -{ - int status; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy (dest, source) - z_streamp dest; - z_streamp source; -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - zmemcpy(dest, source, sizeof(z_stream)); - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - zmemcpy(ds, ss, sizeof(deflate_state)); - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif /* MAXSEG_64K */ -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, strm->next_in, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, strm->next_in, len); - } -#endif - zmemcpy(buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif -} - -#ifndef FASTEST -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} -#endif /* ASMV */ -#endif /* FASTEST */ - -/* --------------------------------------------------------------------------- - * Optimized version for level == 1 or strategy == Z_RLE only - */ -local uInt longest_match_fast(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; -} - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - /* %%% avoid this when Z_RLE */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif - more += wsize; - } - if (s->strm->avail_in == 0) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, eof) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (eof)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, eof) { \ - FLUSH_BLOCK_ONLY(s, eof); \ - if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ -#ifdef FASTEST - if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || - (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { - s->match_length = longest_match_fast (s, hash_head); - } -#else - if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { - s->match_length = longest_match (s, hash_head); - } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { - s->match_length = longest_match_fast (s, hash_head); - } -#endif - /* longest_match() or longest_match_fast() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -#ifndef FASTEST -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { - s->match_length = longest_match (s, hash_head); - } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { - s->match_length = longest_match_fast (s, hash_head); - } - /* longest_match() or longest_match_fast() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED -#if TOO_FAR <= 32767 - || (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR) -#endif - )) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} -#endif /* FASTEST */ - -#if 0 -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -local block_state deflate_rle(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - uInt run; /* length of run */ - uInt max; /* maximum length of run */ - uInt prev; /* byte at distance one to match */ - Bytef *scan; /* scan for end of run */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest encodable run. - */ - if (s->lookahead < MAX_MATCH) { - fill_window(s); - if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - run = 0; - if (s->strstart > 0) { /* if there is a previous byte, that is */ - max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; - scan = s->window + s->strstart - 1; - prev = *scan++; - do { - if (*scan++ != prev) - break; - } while (++run < max); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (run >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, run); - _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); - s->lookahead -= run; - s->strstart += run; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} -#endif diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/deflate.h b/components/dfs/filesystems/jffs2/cyg/compress/src/deflate.h deleted file mode 100644 index 05a5ab3a2c..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/deflate.h +++ /dev/null @@ -1,331 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2004 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef DEFLATE_H -#define DEFLATE_H - -#include "zutil.h" - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ -#ifndef NO_GZIP -# define GZIP -#endif - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ - -#ifdef DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - - /* in trees.c */ -void _tr_init OF((deflate_state *s)); -int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); -void _tr_align OF((deflate_state *s)); -void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch _length_code[]; - extern uch _dist_code[]; -#else - extern const uch _length_code[]; - extern const uch _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif /* DEFLATE_H */ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/descrip.mms b/components/dfs/filesystems/jffs2/cyg/compress/src/descrip.mms deleted file mode 100644 index 9d364598a2..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/descrip.mms +++ /dev/null @@ -1,48 +0,0 @@ -# descrip.mms: MMS description file for building zlib on VMS -# written by Martin P.J. Zinser - -cc_defs = -c_deb = - -.ifdef __DECC__ -pref = /prefix=all -.endif - -OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ - deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ - inftrees.obj, infcodes.obj, infutil.obj, inffast.obj - -CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) - -all : example.exe minigzip.exe - @ write sys$output " Example applications available" -libz.olb : libz.olb($(OBJS)) - @ write sys$output " libz available" - -example.exe : example.obj libz.olb - link example,libz.olb/lib - -minigzip.exe : minigzip.obj libz.olb - link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib - -clean : - delete *.obj;*,libz.olb;* - - -# Other dependencies. -adler32.obj : zutil.h zlib.h zconf.h -compress.obj : zlib.h zconf.h -crc32.obj : zutil.h zlib.h zconf.h -deflate.obj : deflate.h zutil.h zlib.h zconf.h -example.obj : zlib.h zconf.h -gzio.obj : zutil.h zlib.h zconf.h -infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h -infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h -inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h -inflate.obj : zutil.h zlib.h zconf.h infblock.h -inftrees.obj : zutil.h zlib.h zconf.h inftrees.h -infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h -minigzip.obj : zlib.h zconf.h -trees.obj : deflate.h zutil.h zlib.h zconf.h -uncompr.obj : zlib.h zconf.h -zutil.obj : zutil.h zlib.h zconf.h diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/example.c b/components/dfs/filesystems/jffs2/cyg/compress/src/example.c deleted file mode 100644 index 6c8a0ee763..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/example.c +++ /dev/null @@ -1,565 +0,0 @@ -/* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2004 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include -#include "zlib.h" - -#ifdef STDC -# include -# include -#endif - -#if defined(VMS) || defined(RISCOS) -# define TESTFILE "foo-gz" -#else -# define TESTFILE "foo.gz" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ - -const char dictionary[] = "hello"; -uLong dictId; /* Adler32 value of the dictionary */ - -void test_compress OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_gzio OF((const char *fname, - Byte *uncompr, uLong uncomprLen)); -void test_deflate OF((Byte *compr, uLong comprLen)); -void test_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_deflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong *comprLen)); -void test_sync OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_dict_deflate OF((Byte *compr, uLong comprLen)); -void test_dict_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Test compress() and uncompress() - */ -void test_compress(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - uLong len = (uLong)strlen(hello)+1; - - err = compress(compr, &comprLen, (const Bytef*)hello, len); - CHECK_ERR(err, "compress"); - - strcpy((char*)uncompr, "garbage"); - - err = uncompress(uncompr, &uncomprLen, compr, comprLen); - CHECK_ERR(err, "uncompress"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { - printf("uncompress(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test read/write of .gz files - */ -void test_gzio(fname, uncompr, uncomprLen) - const char *fname; /* compressed file name */ - Byte *uncompr; - uLong uncomprLen; -{ -#ifdef NO_GZCOMPRESS - fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); -#else - int err; - int len = (int)strlen(hello)+1; - gzFile file; - z_off_t pos; - - file = gzopen(fname, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - gzputc(file, 'h'); - if (gzputs(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); - exit(1); - } - if (gzprintf(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); - exit(1); - } - gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ - gzclose(file); - - file = gzopen(fname, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - strcpy((char*)uncompr, "garbage"); - - if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { - fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { - printf("gzread(): %s\n", (char*)uncompr); - } - - pos = gzseek(file, -8L, SEEK_CUR); - if (pos != 6 || gztell(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)gztell(file)); - exit(1); - } - - if (gzgetc(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - - if (gzungetc(' ', file) != ' ') { - fprintf(stderr, "gzungetc error\n"); - exit(1); - } - - gzgets(file, (char*)uncompr, (int)uncomprLen); - if (strlen((char*)uncompr) != 7) { /* " hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello + 6)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { - printf("gzgets() after gzseek: %s\n", (char*)uncompr); - } - - gzclose(file); -#endif -} - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uLong len = (uLong)strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = deflate(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { - printf("inflate(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_SPEED); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - /* Switch back to compressing mode: */ - deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (uInt)uncomprLen; - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "large inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { - fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); - exit(1); - } else { - printf("large_inflate(): OK\n"); - } -} - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uInt len = (uInt)strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (uInt)*comprLen; - err = deflate(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate"); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - inflate(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ - err = inflateSync(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = inflate(&d_stream, Z_FINISH); - if (err != Z_DATA_ERROR) { - fprintf(stderr, "inflate should report DATA_ERROR\n"); - /* Because of incorrect adler32 */ - exit(1); - } - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - printf("after inflateSync(): hel%s\n", (char *)uncompr); -} - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = deflateSetDictionary(&c_stream, - (const Bytef*)dictionary, sizeof(dictionary)); - CHECK_ERR(err, "deflateSetDictionary"); - - dictId = c_stream.adler; - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - c_stream.next_in = (Bytef*)hello; - c_stream.avail_in = (uInt)strlen(hello)+1; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - for (;;) { - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, - sizeof(dictionary)); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { - printf("inflate with dictionary: %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Usage: example [output.gz [input.gz]] - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; - static const char* myVersion = ZLIB_VERSION; - - if (zlibVersion()[0] != myVersion[0]) { - fprintf(stderr, "incompatible zlib version\n"); - exit(1); - - } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { - fprintf(stderr, "warning: different zlib version\n"); - } - - printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", - ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); - - compr = (Byte*)calloc((uInt)comprLen, 1); - uncompr = (Byte*)calloc((uInt)uncomprLen, 1); - /* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - */ - if (compr == Z_NULL || uncompr == Z_NULL) { - printf("out of memory\n"); - exit(1); - } - test_compress(compr, comprLen, uncompr, uncomprLen); - - test_gzio((argc > 1 ? argv[1] : TESTFILE), - uncompr, uncomprLen); - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; - - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - return 0; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/gzio.c b/components/dfs/filesystems/jffs2/cyg/compress/src/gzio.c deleted file mode 100644 index 7e90f4928f..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/gzio.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* gzio.c -- IO on .gz files - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. - */ - -/* @(#) $Id$ */ - -#include - -#include "zutil.h" - -#ifdef NO_DEFLATE /* for compatibility with old definition */ -# define NO_GZCOMPRESS -#endif - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -#ifndef Z_BUFSIZE -# ifdef MAXSEG_64K -# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ -# else -# define Z_BUFSIZE 16384 -# endif -#endif -#ifndef Z_PRINTF_BUFSIZE -# define Z_PRINTF_BUFSIZE 4096 -#endif - -#ifdef __MVS__ -# pragma map (fdopen , "\174\174FDOPEN") - FILE *fdopen(int, const char *); -#endif - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern void free OF((voidpf ptr)); -#endif - -#define ALLOC(size) malloc(size) -#define TRYFREE(p) {if (p) free(p);} - -static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -typedef struct gz_stream { - z_stream stream; - int z_err; /* error code for last stream operation */ - int z_eof; /* set if end of input file */ - FILE *file; /* .gz file */ - Byte *inbuf; /* input buffer */ - Byte *outbuf; /* output buffer */ - uLong crc; /* crc32 of uncompressed data */ - char *msg; /* error message */ - char *path; /* path name for debugging only */ - int transparent; /* 1 if input file is not a .gz file */ - char mode; /* 'w' or 'r' */ - z_off_t start; /* start of compressed data in file (header skipped) */ - z_off_t in; /* bytes into deflate or inflate */ - z_off_t out; /* bytes out of deflate or inflate */ - int back; /* one character push-back */ - int last; /* true if push-back is last character */ -} gz_stream; - - -local gzFile gz_open OF((const char *path, const char *mode, int fd)); -local int do_flush OF((gzFile file, int flush)); -local int get_byte OF((gz_stream *s)); -local void check_header OF((gz_stream *s)); -local int destroy OF((gz_stream *s)); -local void putLong OF((FILE *file, uLong x)); -local uLong getLong OF((gz_stream *s)); - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb"). The file is given either by file descriptor - or path name (if fd == -1). - gz_open returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). -*/ -local gzFile gz_open (path, mode, fd) - const char *path; - const char *mode; - int fd; -{ - int err; - int level = Z_DEFAULT_COMPRESSION; /* compression level */ - int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ - char *p = (char*)mode; - gz_stream *s; - char fmode[80]; /* copy of mode, without the compression level */ - char *m = fmode; - - if (!path || !mode) return Z_NULL; - - s = (gz_stream *)ALLOC(sizeof(gz_stream)); - if (!s) return Z_NULL; - - s->stream.zalloc = (alloc_func)0; - s->stream.zfree = (free_func)0; - s->stream.opaque = (voidpf)0; - s->stream.next_in = s->inbuf = Z_NULL; - s->stream.next_out = s->outbuf = Z_NULL; - s->stream.avail_in = s->stream.avail_out = 0; - s->file = NULL; - s->z_err = Z_OK; - s->z_eof = 0; - s->in = 0; - s->out = 0; - s->back = EOF; - s->crc = crc32(0L, Z_NULL, 0); - s->msg = NULL; - s->transparent = 0; - - s->path = (char*)ALLOC(strlen(path)+1); - if (s->path == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - strcpy(s->path, path); /* do this early for debugging */ - - s->mode = '\0'; - do { - if (*p == 'r') s->mode = 'r'; - if (*p == 'w' || *p == 'a') s->mode = 'w'; - if (*p >= '0' && *p <= '9') { - level = *p - '0'; - } else if (*p == 'f') { - strategy = Z_FILTERED; - } else if (*p == 'h') { - strategy = Z_HUFFMAN_ONLY; - } else if (*p == 'R') { - strategy = Z_RLE; - } else { - *m++ = *p; /* copy the mode */ - } - } while (*p++ && m != fmode + sizeof(fmode)); - if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - err = Z_STREAM_ERROR; -#else - err = deflateInit2(&(s->stream), level, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); - /* windowBits is passed < 0 to suppress zlib header */ - - s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); -#endif - if (err != Z_OK || s->outbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } else { - s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); - - err = inflateInit2(&(s->stream), -MAX_WBITS); - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are - * present after the compressed stream. - */ - if (err != Z_OK || s->inbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } - s->stream.avail_out = Z_BUFSIZE; - - errno = 0; - s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); - - if (s->file == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - if (s->mode == 'w') { - /* Write a very simple .gz header: - */ - fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], - Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); - s->start = 10L; - /* We use 10L instead of ftell(s->file) to because ftell causes an - * fflush on some systems. This version of the library doesn't use - * start anyway in write mode, so this initialization is not - * necessary. - */ - } else { - check_header(s); /* skip the .gz header */ - s->start = ftell(s->file) - s->stream.avail_in; - } - - return (gzFile)s; -} - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. -*/ -gzFile ZEXPORT gzopen (path, mode) - const char *path; - const char *mode; -{ - return gz_open (path, mode, -1); -} - -/* =========================================================================== - Associate a gzFile with the file descriptor fd. fd is not dup'ed here - to mimic the behavio(u)r of fdopen. -*/ -gzFile ZEXPORT gzdopen (fd, mode) - int fd; - const char *mode; -{ - char name[46]; /* allow for up to 128-bit integers */ - - if (fd < 0) return (gzFile)Z_NULL; - sprintf(name, "", fd); /* for debugging */ - - return gz_open (name, mode, fd); -} - -/* =========================================================================== - * Update the compression level and strategy - */ -int ZEXPORT gzsetparams (file, level, strategy) - gzFile file; - int level; - int strategy; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - /* Make room to allow flushing */ - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - } - s->stream.avail_out = Z_BUFSIZE; - } - - return deflateParams (&(s->stream), level, strategy); -} - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ -local int get_byte(s) - gz_stream *s; -{ - if (s->z_eof) return EOF; - if (s->stream.avail_in == 0) { - errno = 0; - s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (ferror(s->file)) s->z_err = Z_ERRNO; - return EOF; - } - s->stream.next_in = s->inbuf; - } - s->stream.avail_in--; - return *(s->stream.next_in)++; -} - -/* =========================================================================== - Check the gzip header of a gz_stream opened for reading. Set the stream - mode to transparent if the gzip magic header is not present; set s->err - to Z_DATA_ERROR if the magic header is present but the rest of the header - is incorrect. - IN assertion: the stream s has already been created sucessfully; - s->stream.avail_in is zero for the first time, but may be non-zero - for concatenated .gz files. -*/ -local void check_header(s) - gz_stream *s; -{ - int method; /* method byte */ - int flags; /* flags byte */ - uInt len; - int c; - - /* Assure two bytes in the buffer so we can peek ahead -- handle case - where first byte of header is at the end of the buffer after the last - gzip segment */ - len = s->stream.avail_in; - if (len < 2) { - if (len) s->inbuf[0] = s->stream.next_in[0]; - errno = 0; - len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); - if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; - s->stream.avail_in += len; - s->stream.next_in = s->inbuf; - if (s->stream.avail_in < 2) { - s->transparent = s->stream.avail_in; - return; - } - } - - /* Peek ahead to check the gzip magic header */ - if (s->stream.next_in[0] != gz_magic[0] || - s->stream.next_in[1] != gz_magic[1]) { - s->transparent = 1; - return; - } - s->stream.avail_in -= 2; - s->stream.next_in += 2; - - /* Check the rest of the gzip header */ - method = get_byte(s); - flags = get_byte(s); - if (method != Z_DEFLATED || (flags & RESERVED) != 0) { - s->z_err = Z_DATA_ERROR; - return; - } - - /* Discard time, xflags and OS code: */ - for (len = 0; len < 6; len++) (void)get_byte(s); - - if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - len = (uInt)get_byte(s); - len += ((uInt)get_byte(s))<<8; - /* len is garbage if EOF but the loop below will quit anyway */ - while (len-- != 0 && get_byte(s) != EOF) ; - } - if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - for (len = 0; len < 2; len++) (void)get_byte(s); - } - s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; -} - - /* =========================================================================== - * Cleanup then free the given gz_stream. Return a zlib error code. - Try freeing in the reverse order of allocations. - */ -local int destroy (s) - gz_stream *s; -{ - int err = Z_OK; - - if (!s) return Z_STREAM_ERROR; - - TRYFREE(s->msg); - - if (s->stream.state != NULL) { - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - err = Z_STREAM_ERROR; -#else - err = deflateEnd(&(s->stream)); -#endif - } else if (s->mode == 'r') { - err = inflateEnd(&(s->stream)); - } - } - if (s->file != NULL && fclose(s->file)) { -#ifdef ESPIPE - if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ -#endif - err = Z_ERRNO; - } - if (s->z_err < 0) err = s->z_err; - - TRYFREE(s->inbuf); - TRYFREE(s->outbuf); - TRYFREE(s->path); - TRYFREE(s); - return err; -} - -/* =========================================================================== - Reads the given number of uncompressed bytes from the compressed file. - gzread returns the number of bytes actually read (0 for end of file). -*/ -int ZEXPORT gzread (file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - Bytef *start = (Bytef*)buf; /* starting point for crc computation */ - Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ - - if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; - - if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; - if (s->z_err == Z_STREAM_END) return 0; /* EOF */ - - next_out = (Byte*)buf; - s->stream.next_out = (Bytef*)buf; - s->stream.avail_out = len; - - if (s->stream.avail_out && s->back != EOF) { - *next_out++ = s->back; - s->stream.next_out++; - s->stream.avail_out--; - s->back = EOF; - s->out++; - start++; - if (s->last) { - s->z_err = Z_STREAM_END; - return 1; - } - } - - while (s->stream.avail_out != 0) { - - if (s->transparent) { - /* Copy first the lookahead bytes: */ - uInt n = s->stream.avail_in; - if (n > s->stream.avail_out) n = s->stream.avail_out; - if (n > 0) { - zmemcpy(s->stream.next_out, s->stream.next_in, n); - next_out += n; - s->stream.next_out = next_out; - s->stream.next_in += n; - s->stream.avail_out -= n; - s->stream.avail_in -= n; - } - if (s->stream.avail_out > 0) { - s->stream.avail_out -= - (uInt)fread(next_out, 1, s->stream.avail_out, s->file); - } - len -= s->stream.avail_out; - s->in += len; - s->out += len; - if (len == 0) s->z_eof = 1; - return (int)len; - } - if (s->stream.avail_in == 0 && !s->z_eof) { - - errno = 0; - s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (ferror(s->file)) { - s->z_err = Z_ERRNO; - break; - } - } - s->stream.next_in = s->inbuf; - } - s->in += s->stream.avail_in; - s->out += s->stream.avail_out; - s->z_err = inflate(&(s->stream), Z_NO_FLUSH); - s->in -= s->stream.avail_in; - s->out -= s->stream.avail_out; - - if (s->z_err == Z_STREAM_END) { - /* Check CRC and original size */ - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - start = s->stream.next_out; - - if (getLong(s) != s->crc) { - s->z_err = Z_DATA_ERROR; - } else { - (void)getLong(s); - /* The uncompressed length returned by above getlong() may be - * different from s->out in case of concatenated .gz files. - * Check for such files: - */ - check_header(s); - if (s->z_err == Z_OK) { - inflateReset(&(s->stream)); - s->crc = crc32(0L, Z_NULL, 0); - } - } - } - if (s->z_err != Z_OK || s->z_eof) break; - } - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - - if (len == s->stream.avail_out && - (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) - return -1; - return (int)(len - s->stream.avail_out); -} - - -/* =========================================================================== - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ -int ZEXPORT gzgetc(file) - gzFile file; -{ - unsigned char c; - - return gzread(file, &c, 1) == 1 ? c : -1; -} - - -/* =========================================================================== - Push one byte back onto the stream. -*/ -int ZEXPORT gzungetc(c, file) - int c; - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; - s->back = c; - s->out--; - s->last = (s->z_err == Z_STREAM_END); - if (s->last) s->z_err = Z_OK; - s->z_eof = 0; - return c; -} - - -/* =========================================================================== - Reads bytes from the compressed file until len-1 characters are - read, or a newline character is read and transferred to buf, or an - end-of-file condition is encountered. The string is then terminated - with a null character. - gzgets returns buf, or Z_NULL in case of error. - - The current implementation is not optimized at all. -*/ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ - char *b = buf; - if (buf == Z_NULL || len <= 0) return Z_NULL; - - while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; - *buf = '\0'; - return b == buf && len > 0 ? Z_NULL : b; -} - - -#ifndef NO_GZCOMPRESS -/* =========================================================================== - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of bytes actually written (0 in case of error). -*/ -int ZEXPORT gzwrite (file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.next_in = (Bytef*)buf; - s->stream.avail_in = len; - - while (s->stream.avail_in != 0) { - - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - break; - } - s->stream.avail_out = Z_BUFSIZE; - } - s->in += s->stream.avail_in; - s->out += s->stream.avail_out; - s->z_err = deflate(&(s->stream), Z_NO_FLUSH); - s->in -= s->stream.avail_in; - s->out -= s->stream.avail_out; - if (s->z_err != Z_OK) break; - } - s->crc = crc32(s->crc, (const Bytef *)buf, len); - - return (int)(len - s->stream.avail_in); -} - - -/* =========================================================================== - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). -*/ -#ifdef STDC -#include - -int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) -{ - char buf[Z_PRINTF_BUFSIZE]; - va_list va; - int len; - - buf[sizeof(buf) - 1] = 0; - va_start(va, format); -#ifdef NO_vsnprintf -# ifdef HAS_vsprintf_void - (void)vsprintf(buf, format, va); - va_end(va); - for (len = 0; len < sizeof(buf); len++) - if (buf[len] == 0) break; -# else - len = vsprintf(buf, format, va); - va_end(va); -# endif -#else -# ifdef HAS_vsnprintf_void - (void)vsnprintf(buf, sizeof(buf), format, va); - va_end(va); - len = strlen(buf); -# else - len = vsnprintf(buf, sizeof(buf), format, va); - va_end(va); -# endif -#endif - if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) - return 0; - return gzwrite(file, buf, (unsigned)len); -} -#else /* not ANSI C */ - -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ - char buf[Z_PRINTF_BUFSIZE]; - int len; - - buf[sizeof(buf) - 1] = 0; -#ifdef NO_snprintf -# ifdef HAS_sprintf_void - sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - for (len = 0; len < sizeof(buf); len++) - if (buf[len] == 0) break; -# else - len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#else -# ifdef HAS_snprintf_void - snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(buf); -# else - len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#endif - if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) - return 0; - return gzwrite(file, buf, len); -} -#endif - -/* =========================================================================== - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ -int ZEXPORT gzputc(file, c) - gzFile file; - int c; -{ - unsigned char cc = (unsigned char) c; /* required for big endian systems */ - - return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; -} - - -/* =========================================================================== - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ -int ZEXPORT gzputs(file, s) - gzFile file; - const char *s; -{ - return gzwrite(file, (char*)s, (unsigned)strlen(s)); -} - - -/* =========================================================================== - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. -*/ -local int do_flush (file, flush) - gzFile file; - int flush; -{ - uInt len; - int done = 0; - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.avail_in = 0; /* should be zero already anyway */ - - for (;;) { - len = Z_BUFSIZE - s->stream.avail_out; - - if (len != 0) { - if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { - s->z_err = Z_ERRNO; - return Z_ERRNO; - } - s->stream.next_out = s->outbuf; - s->stream.avail_out = Z_BUFSIZE; - } - if (done) break; - s->out += s->stream.avail_out; - s->z_err = deflate(&(s->stream), flush); - s->out -= s->stream.avail_out; - - /* Ignore the second of two consecutive flushes: */ - if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; - - /* deflate has finished flushing only when it hasn't used up - * all the available space in the output buffer: - */ - done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); - - if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; - } - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} - -int ZEXPORT gzflush (file, flush) - gzFile file; - int flush; -{ - gz_stream *s = (gz_stream*)file; - int err = do_flush (file, flush); - - if (err) return err; - fflush(s->file); - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} -#endif /* NO_GZCOMPRESS */ - -/* =========================================================================== - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error. - SEEK_END is not implemented, returns error. - In this version of the library, gzseek can be extremely slow. -*/ -z_off_t ZEXPORT gzseek (file, offset, whence) - gzFile file; - z_off_t offset; - int whence; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || whence == SEEK_END || - s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { - return -1L; - } - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - return -1L; -#else - if (whence == SEEK_SET) { - offset -= s->in; - } - if (offset < 0) return -1L; - - /* At this point, offset is the number of zero bytes to write. */ - if (s->inbuf == Z_NULL) { - s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ - if (s->inbuf == Z_NULL) return -1L; - zmemzero(s->inbuf, Z_BUFSIZE); - } - while (offset > 0) { - uInt size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (uInt)offset; - - size = gzwrite(file, s->inbuf, size); - if (size == 0) return -1L; - - offset -= size; - } - return s->in; -#endif - } - /* Rest of function is for reading only */ - - /* compute absolute position */ - if (whence == SEEK_CUR) { - offset += s->out; - } - if (offset < 0) return -1L; - - if (s->transparent) { - /* map to fseek */ - s->back = EOF; - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; - - s->in = s->out = offset; - return offset; - } - - /* For a negative seek, rewind and use positive seek */ - if (offset >= s->out) { - offset -= s->out; - } else if (gzrewind(file) < 0) { - return -1L; - } - /* offset is now the number of bytes to skip. */ - - if (offset != 0 && s->outbuf == Z_NULL) { - s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); - if (s->outbuf == Z_NULL) return -1L; - } - if (offset && s->back != EOF) { - s->back = EOF; - s->out++; - offset--; - if (s->last) s->z_err = Z_STREAM_END; - } - while (offset > 0) { - int size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (int)offset; - - size = gzread(file, s->outbuf, (uInt)size); - if (size <= 0) return -1L; - offset -= size; - } - return s->out; -} - -/* =========================================================================== - Rewinds input file. -*/ -int ZEXPORT gzrewind (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r') return -1; - - s->z_err = Z_OK; - s->z_eof = 0; - s->back = EOF; - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - s->crc = crc32(0L, Z_NULL, 0); - if (!s->transparent) (void)inflateReset(&s->stream); - s->in = 0; - s->out = 0; - return fseek(s->file, s->start, SEEK_SET); -} - -/* =========================================================================== - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. -*/ -z_off_t ZEXPORT gztell (file) - gzFile file; -{ - return gzseek(file, 0L, SEEK_CUR); -} - -/* =========================================================================== - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ -int ZEXPORT gzeof (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - /* With concatenated compressed files that can have embedded - * crc trailers, z_eof is no longer the only/best indicator of EOF - * on a gz_stream. Handle end-of-stream error explicitly here. - */ - if (s == NULL || s->mode != 'r') return 0; - if (s->z_eof) return 1; - return s->z_err == Z_STREAM_END; -} - -/* =========================================================================== - Returns 1 if reading and doing so transparently, otherwise zero. -*/ -int ZEXPORT gzdirect (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r') return 0; - return s->transparent; -} - -/* =========================================================================== - Outputs a long in LSB order to the given file -*/ -local void putLong (file, x) - FILE *file; - uLong x; -{ - int n; - for (n = 0; n < 4; n++) { - fputc((int)(x & 0xff), file); - x >>= 8; - } -} - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets z_err in case - of error. -*/ -local uLong getLong (s) - gz_stream *s; -{ - uLong x = (uLong)get_byte(s); - int c; - - x += ((uLong)get_byte(s))<<8; - x += ((uLong)get_byte(s))<<16; - c = get_byte(s); - if (c == EOF) s->z_err = Z_DATA_ERROR; - x += ((uLong)c)<<24; - return x; -} - -/* =========================================================================== - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. -*/ -int ZEXPORT gzclose (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return Z_STREAM_ERROR; - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - return Z_STREAM_ERROR; -#else - if (do_flush (file, Z_FINISH) != Z_OK) - return destroy((gz_stream*)file); - - putLong (s->file, s->crc); - putLong (s->file, (uLong)(s->in & 0xffffffff)); -#endif - } - return destroy((gz_stream*)file); -} - -#ifdef STDC -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -/* =========================================================================== - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ -const char * ZEXPORT gzerror (file, errnum) - gzFile file; - int *errnum; -{ - char *m; - gz_stream *s = (gz_stream*)file; - - if (s == NULL) { - *errnum = Z_STREAM_ERROR; - return (const char*)ERR_MSG(Z_STREAM_ERROR); - } - *errnum = s->z_err; - if (*errnum == Z_OK) return (const char*)""; - - m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); - - if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); - - TRYFREE(s->msg); - s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); - if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); - strcpy(s->msg, s->path); - strcat(s->msg, ": "); - strcat(s->msg, m); - return (const char*)s->msg; -} - -/* =========================================================================== - Clear the error and end-of-file flags, and do the same for the real file. -*/ -void ZEXPORT gzclearerr (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return; - if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; - s->z_eof = 0; - clearerr(s->file); -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/infback.c b/components/dfs/filesystems/jffs2/cyg/compress/src/infback.c deleted file mode 100644 index 455dbc9ee8..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/infback.c +++ /dev/null @@ -1,623 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) -z_streamp strm; -int windowBits; -unsigned char FAR *window; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL || - windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->dmax = 32768U; - state->wbits = windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->write = 0; - state->whave = 0; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -/* Macros for inflateBack(): */ - -/* Load returned state from inflate_fast() */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Set state from registers for inflate_fast() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) -z_streamp strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ - struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code this; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.val < 16) { - NEEDBITS(this.bits); - DROPBITS(this.bits); - state->lens[state->have++] = this.val; - } - else { - if (this.val == 16) { - NEEDBITS(this.bits + 2); - DROPBITS(this.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (this.val == 17) { - NEEDBITS(this.bits + 3); - DROPBITS(this.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(this.bits + 7); - DROPBITS(this.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* build code tables */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.op && (this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - state->length = (unsigned)this.val; - - /* process literal */ - if (this.op == 0) { - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (this.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (this.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (unsigned)(this.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - this = state->distcode[BITS(state->distbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if ((this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - if (this.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)this.val; - - /* get distance extra bits, if any */ - state->extra = (unsigned)(this.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } - if (state->offset > state->wsize - (state->whave < state->wsize ? - left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBackEnd(strm) -z_streamp strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/infblock.c b/components/dfs/filesystems/jffs2/cyg/compress/src/infblock.c deleted file mode 100644 index c2521d5a87..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/infblock.c +++ /dev/null @@ -1,403 +0,0 @@ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -//#include "infcodes.h" //no such file! -#include "infutil.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* Table for deflate from PKZIP's appnote.txt. */ -local const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -void inflate_blocks_reset(s, z, c) -inflate_blocks_statef *s; -z_streamp z; -uLongf *c; -{ - if (c != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); - Tracev((stderr, "inflate: blocks reset\n")); -} - - -inflate_blocks_statef *inflate_blocks_new(z, c, w) -z_streamp z; -check_func c; -uInt w; -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Tracev((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; -} - - -int inflate_blocks(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Tracev((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Tracev((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - ZFREE(z, s->sub.trees.blens); - s->mode = CODES; - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONE; - case DONE: - r = Z_STREAM_END; - LEAVE - case BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -int inflate_blocks_free(s, z) -inflate_blocks_statef *s; -z_streamp z; -{ - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - Tracev((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - - -void inflate_set_dictionary(s, d, n) -inflate_blocks_statef *s; -const Bytef *d; -uInt n; -{ - zmemcpy(s->window, d, n); - s->read = s->write = s->window + n; -} - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. - * IN assertion: s != Z_NULL - */ -int inflate_blocks_sync_point(s) -inflate_blocks_statef *s; -{ - return s->mode == LENS; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/infblock.h b/components/dfs/filesystems/jffs2/cyg/compress/src/infblock.h deleted file mode 100644 index 17ffbda2f8..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/infblock.h +++ /dev/null @@ -1,39 +0,0 @@ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; -typedef uLong (*check_func) OF((uLong check, const Bytef *buf, uInt len)); // add by prife -extern inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -extern int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -extern void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLongf *)); /* check value on output */ - -extern int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp)); - -extern void inflate_set_dictionary OF(( - inflate_blocks_statef *s, - const Bytef *d, /* dictionary */ - uInt n)); /* dictionary length */ - -extern int inflate_blocks_sync_point OF(( - inflate_blocks_statef *s)); diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/inffast.c b/components/dfs/filesystems/jffs2/cyg/compress/src/inffast.c deleted file mode 100644 index bbee92ed1e..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/inffast.c +++ /dev/null @@ -1,318 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ -#else -# define OFF 1 -# define PUP(a) *++(a) -#endif - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code this; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; - last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - write = state->write; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - this = lcode[hold & lmask]; - dolen: - op = (unsigned)(this.bits); - hold >>= op; - bits -= op; - op = (unsigned)(this.op); - if (op == 0) { /* literal */ - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - PUP(out) = (unsigned char)(this.val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(this.val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - this = dcode[hold & dmask]; - dodist: - op = (unsigned)(this.bits); - hold >>= op; - bits -= op; - op = (unsigned)(this.op); - if (op & 16) { /* distance base */ - dist = (unsigned)(this.val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); -#ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - from = window - OFF; - if (write == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (write < op) { /* wrap around window */ - from += wsize + write - op; - op -= write; - if (op < len) { /* some from end of window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = window - OFF; - if (write < len) { /* some from start of window */ - op = write; - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += write - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } while (len > 2); - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - this = dcode[this.val + (hold & ((1U << op) - 1))]; - goto dodist; - } - else { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - this = lcode[this.val + (hold & ((1U << op) - 1))]; - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; - - /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and write == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - -#endif /* !ASMINF */ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/inffast.h b/components/dfs/filesystems/jffs2/cyg/compress/src/inffast.h deleted file mode 100644 index 1e88d2d97b..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/inffast.h +++ /dev/null @@ -1,11 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/inffixed.h b/components/dfs/filesystems/jffs2/cyg/compress/src/inffixed.h deleted file mode 100644 index 75ed4b5978..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/inffixed.h +++ /dev/null @@ -1,94 +0,0 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - - /* WARNING: this file should *not* be used by applications. It - is part of the implementation of the compression library and - is subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/inflate.c b/components/dfs/filesystems/jffs2/cyg/compress/src/inflate.c deleted file mode 100644 index 792fdee8e9..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/inflate.c +++ /dev/null @@ -1,1368 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common write == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, - unsigned len)); - -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->dmax = 32768U; - state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->write = 0; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; - return Z_OK; -} - -int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) -z_streamp strm; -int windowBits; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - if (windowBits < 0) { - state->wrap = 0; - windowBits = -windowBits; - } - else { - state->wrap = (windowBits >> 4) + 1; -#ifdef GUNZIP - if (windowBits < 48) windowBits &= 15; -#endif - } - if (windowBits < 8 || windowBits > 15) { - ZFREE(strm, state); - strm->state = Z_NULL; - return Z_STREAM_ERROR; - } - state->wbits = (unsigned)windowBits; - state->window = Z_NULL; - return inflateReset(strm); -} - -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ - return inflateInit2_(strm, DEF_WBITS, version, stream_size); -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -local int updatewindow(strm, out) -z_streamp strm; -unsigned out; -{ - struct inflate_state FAR *state; - unsigned copy, dist; - - state = (struct inflate_state FAR *)strm->state; - - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->write = 0; - state->whave = 0; - } - - /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; - if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); - state->write = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->write; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->write, strm->next_out - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); - state->write = copy; - state->whave = state->wsize; - } - else { - state->write += dist; - if (state->write == state->wsize) state->write = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; -} - -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) -#else -# define UPDATE(check, buf, len) adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int ZEXPORT inflate(strm, flush) -z_streamp strm; -int flush; -{ - struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code this; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - state->flags = 0; /* expect zlib header */ - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); - INITBITS(); - state->mode = DICT; - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - case TYPE: - if (flush == Z_BLOCK) goto inf_leave; - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY; - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.val < 16) { - NEEDBITS(this.bits); - DROPBITS(this.bits); - state->lens[state->have++] = this.val; - } - else { - if (this.val == 16) { - NEEDBITS(this.bits + 2); - DROPBITS(this.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (this.val == 17) { - NEEDBITS(this.bits + 3); - DROPBITS(this.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(this.bits + 7); - DROPBITS(this.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* build code tables */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - break; - } - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.op && (this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - state->length = (unsigned)this.val; - if ((int)(this.op) == 0) { - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - state->mode = LIT; - break; - } - if (this.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - if (this.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(this.op) & 15; - state->mode = LENEXT; - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->mode = DIST; - case DIST: - for (;;) { - this = state->distcode[BITS(state->distbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if ((this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - if (this.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)this.val; - state->extra = (unsigned)(this.op) & 15; - state->mode = DISTEXT; - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - if (state->offset > state->whave + out - left) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->write) { - copy -= state->write; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->write - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if (out) - strm->adler = state->check = - UPDATE(state->check, put - out, out); - out = left; - if (( -#ifdef GUNZIP - state->flags ? hold : -#endif - REVERSE(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - default: - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) - if (updatewindow(strm, out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if (state->wrap && out) - strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ - struct inflate_state FAR *state; - unsigned long id; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary id */ - if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ - struct inflate_state FAR *state; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -local unsigned syncsearch(have, buf, len) -unsigned FAR *have; -unsigned char FAR *buf; -unsigned len; -{ - unsigned got; - unsigned next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ - unsigned len; /* number of bytes to look at or looked at */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; - - /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->mode = TYPE; - return Z_OK; -} - -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int ZEXPORT inflateCopy(dest, source) -z_streamp dest; -z_streamp source; -{ - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; - - /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; - - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - zmemcpy(dest, source, sizeof(z_stream)); - zmemcpy(copy, state, sizeof(struct inflate_state)); - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/inflate.h b/components/dfs/filesystems/jffs2/cyg/compress/src/inflate.h deleted file mode 100644 index 07bd3e78a7..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/inflate.h +++ /dev/null @@ -1,115 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN, /* i: waiting for length/lit code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to the BAD or MEM mode -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME - NAME -> COMMENT -> HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - Read deflate blocks: - TYPE -> STORED or TABLE or LEN or CHECK - STORED -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN - Read deflate codes: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* state maintained between inflate() calls. Approximately 7K bytes. */ -struct inflate_state { - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ -}; diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.c b/components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.c deleted file mode 100644 index 8a9c13ff03..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.c +++ /dev/null @@ -1,329 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code this; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)1; - this.val = (unsigned short)0; - *(*table)++ = this; /* make a table to force an error */ - *(*table)++ = this; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min <= MAXBITS; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked when a LENS table is being made - against the space in *table, ENOUGH, minus the maximum space needed by - the worst case distance code, MAXD. This should never happen, but the - sufficiency of ENOUGH has not been proven exhaustively, hence the check. - This assumes that when type == LENS, bits == 9. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if (type == LENS && used >= ENOUGH - MAXD) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - this.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - this.op = (unsigned char)0; - this.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - this.op = (unsigned char)(extra[work[sym]]); - this.val = base[work[sym]]; - } - else { - this.op = (unsigned char)(32 + 64); /* end of block */ - this.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = this; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if (type == LENS && used >= ENOUGH - MAXD) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)(len - drop); - this.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - this.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = this; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.h b/components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.h deleted file mode 100644 index b1104c87e7..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/inftrees.h +++ /dev/null @@ -1,55 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1444 code structures (852 for length/literals - and 592 for distances, the latter actually the result of an - exhaustive search). The true maximum is not known, but the value - below is more than safe. */ -#define ENOUGH 2048 -#define MAXD 592 - -/* Type of code to build for inftable() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -extern int inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/infutil.c b/components/dfs/filesystems/jffs2/cyg/compress/src/infutil.c deleted file mode 100644 index 9a076221f2..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/infutil.c +++ /dev/null @@ -1,87 +0,0 @@ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* And'ing with mask[n] masks the lower n bits */ -uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -int inflate_flush(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt n; - Bytef *p; - Bytef *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/infutil.h b/components/dfs/filesystems/jffs2/cyg/compress/src/infutil.h deleted file mode 100644 index 4401df82fc..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/infutil.h +++ /dev/null @@ -1,98 +0,0 @@ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFUTIL_H -#define _INFUTIL_H - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONE, /* finished last block, done */ - BAD} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - inflate_huft *hufts; /* single malloc for tree space */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -extern uInt inflate_mask[17]; - -/* copy as much as possible from the sliding window to the output area */ -extern int inflate_flush OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -struct internal_state {int dummy;}; /* for buggy compilers */ - -#endif diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/maketree.c b/components/dfs/filesystems/jffs2/cyg/compress/src/maketree.c deleted file mode 100644 index a16d4b1460..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/maketree.c +++ /dev/null @@ -1,85 +0,0 @@ -/* maketree.c -- make inffixed.h table for decoding fixed codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* This program is included in the distribution for completeness. - You do not need to compile or run this program since inffixed.h - is already included in the distribution. To use this program - you need to compile zlib with BUILDFIXED defined and then compile - and link this program with the zlib library. Then the output of - this program can be piped to inffixed.h. */ - -#include -#include -#include "zutil.h" -#include "inftrees.h" - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* generate initialization table for an inflate_huft structure array */ -void maketree(uInt b, inflate_huft *t) -{ - int i, e; - - i = 0; - while (1) - { - e = t[i].exop; - if (e && (e & (16+64)) == 0) /* table pointer */ - { - fprintf(stderr, "maketree: cannot initialize sub-tables!\n"); - exit(1); - } - if (i % 4 == 0) - printf("\n "); - printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base); - if (++i == (1< -#include "zlib.h" - -#ifdef STDC -# include -# include -#endif - -#ifdef USE_MMAP -# include -# include -# include -#endif - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#ifdef VMS -# define unlink delete -# define GZ_SUFFIX "-gz" -#endif -#ifdef RISCOS -# define unlink remove -# define GZ_SUFFIX "-gz" -# define fileno(file) file->__file -#endif -#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fileno */ -#endif - -#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ - extern int unlink OF((const char *)); -#endif - -#ifndef GZ_SUFFIX -# define GZ_SUFFIX ".gz" -#endif -#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) - -#define BUFLEN 16384 -#define MAX_NAME_LEN 1024 - -#ifdef MAXSEG_64K -# define local static - /* Needed for systems with limitation on stack size. */ -#else -# define local -#endif - -char *prog; - -void error OF((const char *msg)); -void gz_compress OF((FILE *in, gzFile out)); -#ifdef USE_MMAP -int gz_compress_mmap OF((FILE *in, gzFile out)); -#endif -void gz_uncompress OF((gzFile in, FILE *out)); -void file_compress OF((char *file, char *mode)); -void file_uncompress OF((char *file)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Display error message and exit - */ -void error(msg) - const char *msg; -{ - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(in, out) - FILE *in; - gzFile out; -{ - local char buf[BUFLEN]; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - for (;;) { - len = (int)fread(buf, 1, sizeof(buf), in); - if (ferror(in)) { - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); - } - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); -} - -#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ - -/* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. - */ -int gz_compress_mmap(in, out) - FILE *in; - gzFile out; -{ - int len; - int err; - int ifd = fileno(in); - caddr_t buf; /* mmap'ed buffer for the entire input file */ - off_t buf_len; /* length of the input file */ - struct stat sb; - - /* Determine the size of the file, needed for mmap: */ - if (fstat(ifd, &sb) < 0) return Z_ERRNO; - buf_len = sb.st_size; - if (buf_len <= 0) return Z_ERRNO; - - /* Now do the actual mmap: */ - buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); - if (buf == (caddr_t)(-1)) return Z_ERRNO; - - /* Compress the whole file at once: */ - len = gzwrite(out, (char *)buf, (unsigned)buf_len); - - if (len != (int)buf_len) error(gzerror(out, &err)); - - munmap(buf, buf_len); - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); - return Z_OK; -} -#endif /* USE_MMAP */ - -/* =========================================================================== - * Uncompress input to output then close both files. - */ -void gz_uncompress(in, out) - gzFile in; - FILE *out; -{ - local char buf[BUFLEN]; - int len; - int err; - - for (;;) { - len = gzread(in, buf, sizeof(buf)); - if (len < 0) error (gzerror(in, &err)); - if (len == 0) break; - - if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { - error("failed fwrite"); - } - } - if (fclose(out)) error("failed fclose"); - - if (gzclose(in) != Z_OK) error("failed gzclose"); -} - - -/* =========================================================================== - * Compress the given file: create a corresponding .gz file and remove the - * original. - */ -void file_compress(file, mode) - char *file; - char *mode; -{ - local char outfile[MAX_NAME_LEN]; - FILE *in; - gzFile out; - - strcpy(outfile, file); - strcat(outfile, GZ_SUFFIX); - - in = fopen(file, "rb"); - if (in == NULL) { - perror(file); - exit(1); - } - out = gzopen(outfile, mode); - if (out == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); - exit(1); - } - gz_compress(in, out); - - unlink(file); -} - - -/* =========================================================================== - * Uncompress the given file and remove the original. - */ -void file_uncompress(file) - char *file; -{ - local char buf[MAX_NAME_LEN]; - char *infile, *outfile; - FILE *out; - gzFile in; - uInt len = (uInt)strlen(file); - - strcpy(buf, file); - - if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { - infile = file; - outfile = buf; - outfile[len-3] = '\0'; - } else { - outfile = file; - infile = buf; - strcat(infile, GZ_SUFFIX); - } - in = gzopen(infile, "rb"); - if (in == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); - exit(1); - } - out = fopen(outfile, "wb"); - if (out == NULL) { - perror(file); - exit(1); - } - - gz_uncompress(in, out); - - unlink(infile); -} - - -/* =========================================================================== - * Usage: minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...] - * -d : decompress - * -f : compress with Z_FILTERED - * -h : compress with Z_HUFFMAN_ONLY - * -r : compress with Z_RLE - * -1 to -9 : compression level - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - int uncompr = 0; - gzFile file; - char outmode[20]; - - strcpy(outmode, "wb6 "); - - prog = argv[0]; - argc--, argv++; - - while (argc > 0) { - if (strcmp(*argv, "-d") == 0) - uncompr = 1; - else if (strcmp(*argv, "-f") == 0) - outmode[3] = 'f'; - else if (strcmp(*argv, "-h") == 0) - outmode[3] = 'h'; - else if (strcmp(*argv, "-r") == 0) - outmode[3] = 'R'; - else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && - (*argv)[2] == 0) - outmode[2] = (*argv)[1]; - else - break; - argc--, argv++; - } - if (outmode[3] == ' ') - outmode[3] = 0; - if (argc == 0) { - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - if (uncompr) { - file = gzdopen(fileno(stdin), "rb"); - if (file == NULL) error("can't gzdopen stdin"); - gz_uncompress(file, stdout); - } else { - file = gzdopen(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - gz_compress(stdin, file); - } - } else { - do { - if (uncompr) { - file_uncompress(*argv); - } else { - file_compress(*argv, outmode); - } - } while (argv++, --argc); - } - return 0; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/trees.c b/components/dfs/filesystems/jffs2/cyg/compress/src/trees.c deleted file mode 100644 index 395e4e1681..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/trees.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2005 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id$ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef DEBUG -# include -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); -local void set_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (value << s->bi_valid); - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (val << s->bi_valid);\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* DEBUG */ - - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef DEBUG -# include -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ -#ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void _tr_stored_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ -#ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; -#endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. - */ -void _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; -#endif - bi_flush(s); - } - s->last_eob_len = 7; -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -void _tr_flush_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is binary or text */ - if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) - set_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, eof); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+eof, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (eof) { - bi_windup(s); -#ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*eof)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int _tr_tally (s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; -} - -/* =========================================================================== - * Set the data type to BINARY or TEXT, using a crude approximation: - * set it to Z_TEXT if all symbols are either printable characters (33 to 255) - * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local void set_data_type(s) - deflate_state *s; -{ - int n; - - for (n = 0; n < 9; n++) - if (s->dyn_ltree[n].Freq != 0) - break; - if (n == 9) - for (n = 14; n < 32; n++) - if (s->dyn_ltree[n].Freq != 0) - break; - s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/trees.h b/components/dfs/filesystems/jffs2/cyg/compress/src/trees.h deleted file mode 100644 index 72facf900f..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/trees.h +++ /dev/null @@ -1,128 +0,0 @@ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/uncompr.c b/components/dfs/filesystems/jffs2/cyg/compress/src/uncompr.c deleted file mode 100644 index 52040203bc..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/uncompr.c +++ /dev/null @@ -1,65 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#ifdef __ECOS__ -#include -#else -#include "zlib.h" -#endif // __ECOS__ - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ -int ZEXPORT uncompress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - return Z_DATA_ERROR; - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; -} diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/zlib.3 b/components/dfs/filesystems/jffs2/cyg/compress/src/zlib.3 deleted file mode 100644 index 90b8162870..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/zlib.3 +++ /dev/null @@ -1,159 +0,0 @@ -.TH ZLIB 3 "18 July 2005" -.SH NAME -zlib \- compression/decompression library -.SH SYNOPSIS -[see -.I zlib.h -for full description] -.SH DESCRIPTION -The -.I zlib -library is a general purpose data compression library. -The code is thread safe. -It provides in-memory compression and decompression functions, -including integrity checks of the uncompressed data. -This version of the library supports only one compression method (deflation) -but other algorithms will be added later -and will have the same stream interface. -.LP -Compression can be done in a single step if the buffers are large enough -(for example if an input file is mmap'ed), -or can be done by repeated calls of the compression function. -In the latter case, -the application must provide more input and/or consume the output -(providing more output space) before each call. -.LP -The library also supports reading and writing files in -.IR gzip (1) -(.gz) format -with an interface similar to that of stdio. -.LP -The library does not install any signal handler. -The decoder checks the consistency of the compressed data, -so the library should never crash even in case of corrupted input. -.LP -All functions of the compression library are documented in the file -.IR zlib.h . -The distribution source includes examples of use of the library -in the files -.I example.c -and -.IR minigzip.c . -.LP -Changes to this version are documented in the file -.I ChangeLog -that accompanies the source, -and are concerned primarily with bug fixes and portability enhancements. -.LP -A Java implementation of -.I zlib -is available in the Java Development Kit 1.1: -.IP -http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html -.LP -A Perl interface to -.IR zlib , -written by Paul Marquess (pmqs@cpan.org), -is available at CPAN (Comprehensive Perl Archive Network) sites, -including: -.IP -http://www.cpan.org/modules/by-module/Compress/ -.LP -A Python interface to -.IR zlib , -written by A.M. Kuchling (amk@magnet.com), -is available in Python 1.5 and later versions: -.IP -http://www.python.org/doc/lib/module-zlib.html -.LP -A -.I zlib -binding for -.IR tcl (1), -written by Andreas Kupries (a.kupries@westend.com), -is availlable at: -.IP -http://www.westend.com/~kupries/doc/trf/man/man.html -.LP -An experimental package to read and write files in .zip format, -written on top of -.I zlib -by Gilles Vollant (info@winimage.com), -is available at: -.IP -http://www.winimage.com/zLibDll/unzip.html -and also in the -.I contrib/minizip -directory of the main -.I zlib -web site. -.SH "SEE ALSO" -The -.I zlib -web site can be found at either of these locations: -.IP -http://www.zlib.org -.br -http://www.gzip.org/zlib/ -.LP -The data format used by the zlib library is described by RFC -(Request for Comments) 1950 to 1952 in the files: -.IP -http://www.ietf.org/rfc/rfc1950.txt (concerning zlib format) -.br -http://www.ietf.org/rfc/rfc1951.txt (concerning deflate format) -.br -http://www.ietf.org/rfc/rfc1952.txt (concerning gzip format) -.LP -These documents are also available in other formats from: -.IP -ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html -.LP -Mark Nelson (markn@ieee.org) wrote an article about -.I zlib -for the Jan. 1997 issue of Dr. Dobb's Journal; -a copy of the article is available at: -.IP -http://dogma.net/markn/articles/zlibtool/zlibtool.htm -.SH "REPORTING PROBLEMS" -Before reporting a problem, -please check the -.I zlib -web site to verify that you have the latest version of -.IR zlib ; -otherwise, -obtain the latest version and see if the problem still exists. -Please read the -.I zlib -FAQ at: -.IP -http://www.gzip.org/zlib/zlib_faq.html -.LP -before asking for help. -Send questions and/or comments to zlib@gzip.org, -or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). -.SH AUTHORS -Version 1.2.3 -Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org) -and Mark Adler (madler@alumni.caltech.edu). -.LP -This software is provided "as-is," -without any express or implied warranty. -In no event will the authors be held liable for any damages -arising from the use of this software. -See the distribution directory with respect to requirements -governing redistribution. -The deflate format used by -.I zlib -was defined by Phil Katz. -The deflate and -.I zlib -specifications were written by L. Peter Deutsch. -Thanks to all the people who reported problems and suggested various -improvements in -.IR zlib ; -who are too numerous to cite here. -.LP -UNIX manual page by R. P. C. Rodgers, -U.S. National Library of Medicine (rodgers@nlm.nih.gov). -.\" end of man page diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/zutil.c b/components/dfs/filesystems/jffs2/cyg/compress/src/zutil.c deleted file mode 100644 index d55f5948a3..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/zutil.c +++ /dev/null @@ -1,318 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch (sizeof(uInt)) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch (sizeof(uLong)) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch (sizeof(voidpf)) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch (sizeof(z_off_t)) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef DEBUG - flags += 1 << 8; -#endif -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#ifdef STDC -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} - -#ifdef DEBUG - -# ifndef verbose -# define verbose 0 -# endif -int z_verbose = verbose; - -void z_error (m) - char *m; -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError(err) - int err; -{ - return ERR_MSG(err); -} - -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - int errno = 0; -#endif - -#ifndef HAVE_MEMCPY - -void zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void zmemzero(dest, len) - Bytef* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - - -#ifdef SYS16BIT - -#ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ - -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); -} - -#endif /* __TURBOC__ */ - - -#ifdef M_I86 -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); -} - -#endif /* M_I86 */ - -#endif /* SYS16BIT */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - if (opaque) items += size - size; /* make compiler happy */ - return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (voidpf)calloc(items, size); -} - -void zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - -#endif /* MY_ZCALLOC */ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/src/zutil.h b/components/dfs/filesystems/jffs2/cyg/compress/src/zutil.h deleted file mode 100644 index 013754a1f7..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/src/zutil.h +++ /dev/null @@ -1,276 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#define ZLIB_INTERNAL -#ifdef __ECOS__ -#include -#include -#undef crc32 -#define crc32 cyg_ether_crc32_accumulate -#else -#include "zlib.h" -#endif // __ECOS__ - -#ifdef STDC -# ifndef _WIN32_WCE -# include -# endif -# include -# include -#endif -#ifdef NO_ERRNO_H -# ifdef _WIN32_WCE - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. We rename it to - * avoid conflict with other libraries that use the same workaround. - */ -# define errno z_errno -# endif - extern int errno; -#else -# ifndef _WIN32_WCE -# include -# endif -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) -# define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include -# endif -# else /* MSC or DJGPP */ -# include -# endif -#endif - -#ifdef AMIGA -# define OS_CODE 0x01 -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -# ifdef M_I86 - #include -# endif -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -#endif - -#ifdef TOPS20 -# define OS_CODE 0x0a -#endif - -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif -#endif - - /* common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS - /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 - /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# define vsnprintf _vsnprintf -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -#endif -#ifdef VMS -# define NO_vsnprintf -#endif - -#if defined(pyr) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - extern void zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG -# include - extern int z_verbose; - extern void z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -void zcfree OF((voidpf opaque, voidpf ptr)); - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -#endif /* ZUTIL_H */ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/tests/zlib1.c b/components/dfs/filesystems/jffs2/cyg/compress/tests/zlib1.c deleted file mode 100644 index 22b2d397b5..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/tests/zlib1.c +++ /dev/null @@ -1,232 +0,0 @@ -//================================================================= -// -// zlib1.c -// -// zlib compression/decompression test 1 -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): jskov -// Contributors: jskov -// Date: 2001-03-09 -// Description: Tests zlib compress/decompress functionality. -//####DESCRIPTIONEND#### - - -#include // CYGNUM_HAL_STACK_SIZE_TYPICAL - -#include - -#include -#include - -#ifdef CYGFUN_KERNEL_API_C - -#include -#include - -#define NTHREADS 1 -#define STACKSIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL > 8192 ? CYGNUM_HAL_STACK_SIZE_TYPICAL : 8192) - -static cyg_handle_t thread[NTHREADS]; - -static cyg_thread thread_obj[NTHREADS]; -static char stack[NTHREADS][STACKSIZE]; - -static char license_txt[] = -"Red Hat eCos Public License v1.1\n" -"\n" -"\n" -"1. DEFINITIONS\n" -"\n" -"1.1. \"Contributor\" means each entity that creates or\n" -"contributes to the creation of Modifications.\n" -"\n" -"1.2. \"Contributor Version\" means the combination of the\n" -"Original Code, prior Modifications used by a\n" -"Contributor, and the Modifications made by that\n" -"particular Contributor.\n" -"\n" -"1.3. \"Covered Code\" means the Original Code or\n" -"Modifications or the combination of the Original Code\n" -"and Modifications, in each case including portions\n" -"thereof.\n" -"\n" -"1.4. \"Electronic Distribution Mechanism\" means a\n" -"mechanism generally accepted in the software development\n" -"community for the electronic transfer of data.\n" -"\n" -"1.5. \"Executable\" means Covered Code in any form other\n" -"than Source Code.\n" -"1.6. \"Initial Developer\" means the individual or entity\n" -"identified as the Initial Developer in the Source Code\n" -"notice required by Exhibit A.\n" -"\n" -"1.7. \"Larger Work\" means a work which combines Covered\n" -"Code or portions thereof with code not governed by the\n" -"terms of this License.\n" -"\n" -"1.8. \"License\" means this document.\n" -"\n" -"1.9. \"Modifications\" means any addition to or deletion\n" -"from the substance or structure of either the Original\n" -"Code or any previous Modifications. When Covered Code is\n" -"released as a series of files, a Modification is:\n" -"\n" -" A. Any addition to or deletion from the\n" -" contents of a file containing Original Code or\n" -" previous Modifications.\n" -"\n" -" B. Any new file that contains any part of the\n" -" Original Code or previous Modifications.\n" -"\n" -"1.10. \"Original Code\" means Source Code of computer\n" -"software code which is described in the Source Code\n" -"notice required by Exhibit A as Original Code, and\n" -"which, at the time of its release under this License is\n" -"not already Covered Code governed by this License.\n" -"\n" -"1.11. \"Source Code\" means the preferred form of the\n" -"Covered Code for making modifications to it, including\n" -"all modules it contains, plus any associated interface\n" -"definition files, scripts used to control compilation\n" -"and installation of an Executable, or a list of source\n" -"code differential comparisons against either the\n" -"Original Code or another well known, available Covered\n" -"Code of the Contributor's choice. The Source Code can be\n" -"in a compressed or archival form, provided the\n" -"appropriate decompression or de-archiving software is\n" -"widely available for no charge.\n" -"\n" -"1.12. \"You\" means an individual or a legal entity\n" -"exercising rights under, and complying with all of the\n" -"terms of, this License or a future version of this\n" -"License issued under Section 6.1. For legal entities,\n" -"\"You\" includes any entity which controls, is controlled\n" -"by, or is under common control with You. For purposes of\n" -"this definition, \"control\" means (a) the power, direct\n" -"or indirect, to cause the direction or management of\n" -"such entity, whether by contract or otherwise, or (b)\n" -"ownership of fifty percent (50%) or more of the\n" -"outstanding shares or beneficial ownership of such\n" -"entity.\n" -"\n" -"1.13. \"Red Hat Branded Code\" is code that Red Hat\n" -"distributes and/or permits others to distribute under\n" -"different terms than the Red Hat eCos Public License.\n" -"Red Hat's Branded Code may contain part or all of the\n" -"Covered Code.\n"; - -static void entry0( cyg_addrword_t data ) -{ - int i; - unsigned long len; - int err; - int buf_size = sizeof(license_txt)+512; - unsigned char* packed = malloc(buf_size); - unsigned char* unpacked = malloc(buf_size); - - if (NULL == packed || NULL == unpacked) - CYG_TEST_NA("Not enough memory for buffers"); - - CYG_TEST_INFO("Compressing"); - - len = buf_size; - err = compress(packed, &len, license_txt, sizeof(license_txt)); - diag_printf("len = %d", len); - diag_dump_buf(packed, len); - - if (Z_OK != err) - CYG_TEST_NA("Not enough memory for compression"); - - - CYG_TEST_INFO("Decompressing"); - err = uncompress(unpacked, &buf_size, packed, len); - - switch (err) { - case Z_OK: - break; - case Z_MEM_ERROR: - CYG_TEST_NA("Not enough memory for decompression"); - break; - case Z_BUF_ERROR: - CYG_TEST_FAIL_FINISH("Decompressed data larger than original"); - break; - case Z_DATA_ERROR: - CYG_TEST_FAIL_FINISH("Decompression failed"); - break; - default: - CYG_TEST_FAIL_FINISH("Unknown decompression error"); - break; - } - - for (i = 0; i < sizeof(license_txt)-1; i++) { - if (license_txt[i] != unpacked[i]) - CYG_TEST_FAIL_FINISH("Verify failed"); - } - - CYG_TEST_PASS_FINISH("zlib1 OK"); -} - -void zlib1_main( void ) -{ - CYG_TEST_INIT(); - - cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "zlib1", - (void *)stack[0], STACKSIZE,&thread[0], &thread_obj[0]); - cyg_thread_resume(thread[0]); - - cyg_scheduler_start(); - - CYG_TEST_FAIL_FINISH("Not reached"); -} - -externC void -cyg_start( void ) -{ - zlib1_main(); -} - -#else /* def CYGFUN_KERNEL_API_C */ -externC void -cyg_start( void ) -{ - CYG_TEST_INIT(); - CYG_TEST_NA("Kernel C API layer disabled"); -} -#endif /* def CYGFUN_KERNEL_API_C */ - -// EOF zlib1.c diff --git a/components/dfs/filesystems/jffs2/cyg/compress/tests/zlib2.c b/components/dfs/filesystems/jffs2/cyg/compress/tests/zlib2.c deleted file mode 100644 index 11e36e1369..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/tests/zlib2.c +++ /dev/null @@ -1,307 +0,0 @@ -//================================================================= -// -// zlib2.c -// -// zlib decompression test 2 -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): jskov -// Contributors: jskov -// Date: 2001-03-09 -// Description: Tests zlib compression of gz compressed image. -//####DESCRIPTIONEND#### - - -#include // CYGNUM_HAL_STACK_SIZE_TYPICAL - -#include - -#include - -#ifdef CYGFUN_KERNEL_API_C - -#include -#include - -#define NTHREADS 1 -#define STACKSIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL > 8192 ? CYGNUM_HAL_STACK_SIZE_TYPICAL : 8192) - -static cyg_handle_t thread[NTHREADS]; - -static cyg_thread thread_obj[NTHREADS]; -static char stack[NTHREADS][STACKSIZE]; - - -unsigned char gzip_test[] = { -0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x8d, 0x56, 0xdb, 0x6e, 0xe3, 0x36, -0x10, 0xed, 0x33, 0xbf, 0x82, 0x08, 0x50, 0x74, 0x03, 0xb8, 0xee, 0xa6, 0xed, 0x6e, 0x2f, 0x6f, -0xd9, 0x24, 0x8b, 0x06, 0xd8, 0x4b, 0x91, 0x2c, 0xba, 0xe8, 0x23, 0x4d, 0x8d, 0x6c, 0x22, 0x12, -0xa9, 0x92, 0x94, 0x9d, 0xfc, 0x7d, 0xcf, 0x0c, 0x25, 0x59, 0x72, 0x1a, 0xa0, 0x7e, 0x32, 0x45, -0x72, 0xe6, 0xcc, 0xcc, 0x99, 0x33, 0xbc, 0xa3, 0x4a, 0xff, 0x61, 0xb2, 0xa6, 0xab, 0x90, 0xf4, -0x9f, 0xfd, 0xa6, 0x71, 0x56, 0x7f, 0x70, 0x96, 0x7c, 0x22, 0xbd, 0xbf, 0x58, 0x5f, 0x28, 0xfc, -0x2e, 0xd6, 0xfa, 0xfa, 0xe6, 0xfd, 0xed, 0xa7, 0xdb, 0x2f, 0xb7, 0x9f, 0x3f, 0xdd, 0xf3, 0x1a, -0x5f, 0xce, 0xae, 0x82, 0xcf, 0xd1, 0x6d, 0xfa, 0x1c, 0xe2, 0x99, 0x6e, 0xc9, 0xf8, 0xa4, 0xc9, -0xd8, 0x9d, 0x26, 0x9f, 0x5d, 0x7e, 0xd2, 0x79, 0x07, 0xab, 0x36, 0x92, 0xc9, 0x94, 0x74, 0x88, -0xca, 0x8e, 0xc7, 0xb1, 0xcc, 0x01, 0xdb, 0x54, 0x76, 0x5d, 0xf0, 0x3a, 0xd4, 0xfa, 0x63, 0xa8, -0x5c, 0xed, 0xac, 0xac, 0xd3, 0x9a, 0x7d, 0xfc, 0xb8, 0xf4, 0xa1, 0xff, 0xa2, 0x98, 0xb0, 0x39, -0xfa, 0x12, 0x03, 0xa1, 0xdd, 0x38, 0x3f, 0xd9, 0xc0, 0x27, 0xf5, 0x39, 0xba, 0x2d, 0x3e, 0x35, -0xfa, 0x2a, 0x54, 0xb4, 0xd2, 0x5d, 0x74, 0xb8, 0xba, 0x30, 0xae, 0xfb, 0x84, 0x98, 0x37, 0x4f, -0xda, 0xa8, 0x99, 0xf9, 0x95, 0x36, 0xbe, 0x12, 0xa3, 0xcb, 0xc3, 0xad, 0xa9, 0x88, 0x0f, 0x73, -0x38, 0xaa, 0x33, 0x31, 0x3b, 0xdb, 0x37, 0x26, 0xea, 0xd9, 0x55, 0x41, 0xfb, 0x93, 0xa0, 0xdd, -0x53, 0x84, 0x6d, 0x76, 0x3d, 0x87, 0xb9, 0xc0, 0xc4, 0xb9, 0x58, 0xba, 0x00, 0xc0, 0xff, 0x0e, -0x66, 0x79, 0x51, 0x31, 0xc0, 0xc5, 0xcd, 0x95, 0x76, 0xbe, 0xe4, 0xdc, 0x1a, 0x94, 0xcb, 0x79, -0xdb, 0xf4, 0x95, 0xf3, 0x5b, 0xdd, 0x85, 0x28, 0x07, 0x14, 0x8c, 0x44, 0x0a, 0xb5, 0x20, 0xfc, -0x19, 0x08, 0x6f, 0x1a, 0xb2, 0x39, 0x06, 0x8f, 0x22, 0x5f, 0xbb, 0x54, 0x02, 0x60, 0x7f, 0x1f, -0xc9, 0xee, 0x8c, 0x77, 0xa9, 0x1d, 0x61, 0x1b, 0xd5, 0x8e, 0x9f, 0xf4, 0x96, 0x3c, 0x45, 0xd3, -0x34, 0xc8, 0x98, 0xb5, 0xd4, 0x65, 0x44, 0x08, 0xbf, 0x8c, 0x2f, 0x85, 0x3a, 0x1f, 0x4c, 0x24, -0x5d, 0xd1, 0x9e, 0x9a, 0xd0, 0xb5, 0xa8, 0x3d, 0x0a, 0xdd, 0xb6, 0xbd, 0x67, 0x0a, 0xd4, 0x43, -0x64, 0x74, 0xf4, 0x9a, 0x23, 0xac, 0xd7, 0x14, 0x39, 0xc2, 0xca, 0x64, 0x23, 0xc8, 0xde, 0x30, -0xb2, 0x47, 0xb2, 0x7d, 0x36, 0x9b, 0x66, 0xca, 0xdc, 0x3c, 0x9b, 0xec, 0xd0, 0x78, 0xb1, 0xd8, -0xea, 0xc0, 0x51, 0x21, 0x34, 0xe3, 0xf5, 0x7d, 0xe8, 0xa3, 0x25, 0x39, 0xb2, 0x86, 0xa1, 0xb7, -0x30, 0x74, 0x0b, 0xd7, 0x0e, 0x29, 0xbb, 0x2e, 0x90, 0x28, 0xce, 0x2b, 0xe1, 0x7c, 0xe5, 0xf6, -0xae, 0xea, 0xb1, 0x0f, 0x6c, 0x85, 0xa9, 0xca, 0x55, 0xfc, 0xa7, 0x76, 0xf0, 0x65, 0xca, 0xb1, -0x67, 0x36, 0xc6, 0x80, 0x67, 0xfe, 0x94, 0x0f, 0xe0, 0x02, 0xe9, 0x48, 0xff, 0xf4, 0x2e, 0x16, -0x46, 0xdd, 0x3c, 0xee, 0xdc, 0xc6, 0x65, 0x7d, 0x29, 0x61, 0xfd, 0x02, 0x34, 0x1f, 0x4c, 0xdc, -0xe2, 0xfa, 0xd7, 0x10, 0x1f, 0xa6, 0xd4, 0xea, 0x03, 0x56, 0xfa, 0xb0, 0x73, 0x5c, 0x38, 0x29, -0x3a, 0x4d, 0xd1, 0xaa, 0x81, 0x22, 0x53, 0x09, 0xf5, 0x50, 0x42, 0x7d, 0x70, 0x99, 0x8f, 0x63, -0x17, 0x8e, 0xf5, 0x96, 0x8f, 0xfb, 0xe2, 0x95, 0x69, 0x9f, 0x29, 0xb6, 0xa9, 0xd0, 0xc6, 0xa5, -0xb1, 0x81, 0x05, 0xc5, 0xaf, 0x8c, 0xa2, 0xac, 0x8f, 0x99, 0xc0, 0x99, 0x2a, 0xd8, 0x9e, 0xeb, -0x25, 0x87, 0x7e, 0xc3, 0xa1, 0x05, 0xb5, 0x26, 0xb0, 0x48, 0xba, 0xa9, 0x2a, 0x27, 0x2c, 0x41, -0xdb, 0x02, 0x59, 0x85, 0x72, 0xf2, 0x52, 0xd5, 0x31, 0xb4, 0x85, 0x06, 0xfd, 0x26, 0x65, 0xe3, -0xad, 0x00, 0x07, 0xab, 0x7a, 0x9b, 0x7b, 0x90, 0x02, 0x68, 0xc8, 0x31, 0xfc, 0x05, 0x97, 0xa7, -0x08, 0xd9, 0x74, 0x17, 0x69, 0xef, 0x42, 0x9f, 0x4e, 0xda, 0x5f, 0x7f, 0xdd, 0x91, 0x3f, 0x21, -0x40, 0x52, 0x11, 0x8e, 0x4d, 0x2a, 0x55, 0x32, 0x3a, 0x51, 0x74, 0x24, 0x21, 0xd7, 0xae, 0x21, -0xf4, 0x82, 0x59, 0x18, 0xc1, 0x85, 0xdf, 0x95, 0xd2, 0xfc, 0xbb, 0x5c, 0xeb, 0xcb, 0x97, 0xc3, -0xd0, 0x63, 0x18, 0xe5, 0x30, 0xcb, 0x14, 0xb2, 0x22, 0x86, 0x8d, 0x98, 0x96, 0x4f, 0xc6, 0x79, -0x6e, 0xac, 0x67, 0x9d, 0x2c, 0x77, 0x5e, 0x88, 0x62, 0x70, 0xff, 0xae, 0xb8, 0xf7, 0x74, 0x28, -0xe6, 0x8a, 0x30, 0x16, 0x9b, 0x25, 0xc1, 0x2c, 0x2b, 0xa3, 0x7e, 0xc9, 0x95, 0x53, 0x37, 0x2f, -0x7b, 0x80, 0x14, 0xbf, 0x46, 0xed, 0x16, 0x17, 0xc6, 0xda, 0xcd, 0xc8, 0xca, 0xd6, 0x41, 0xb5, -0x0e, 0xea, 0x1b, 0xd5, 0xd4, 0xb5, 0xc2, 0xa6, 0xc2, 0x43, 0x26, 0x04, 0x25, 0x0b, 0x41, 0x38, -0x76, 0xf7, 0xff, 0x25, 0x3b, 0xd7, 0xe3, 0x44, 0x76, 0x21, 0x55, 0x4a, 0x0c, 0xe3, 0x6f, 0x16, -0x63, 0xd9, 0xb5, 0x82, 0xc2, 0x21, 0xb5, 0x43, 0x21, 0x75, 0xef, 0x2b, 0x21, 0xc7, 0x91, 0xb1, -0x5c, 0x66, 0xa6, 0xb7, 0x69, 0x30, 0x1a, 0xaa, 0xa7, 0x25, 0x05, 0x96, 0x9c, 0x3f, 0xa1, 0xf9, -0x05, 0x8f, 0xa4, 0x19, 0xe2, 0x79, 0xd7, 0x23, 0x7b, 0x90, 0x1c, 0xb6, 0x53, 0xf4, 0xa3, 0x64, -0x7a, 0x61, 0x9b, 0xa5, 0xaa, 0x35, 0x0f, 0x5c, 0xe3, 0x76, 0x21, 0xce, 0x20, 0x8b, 0xcb, 0xab, -0xa3, 0xb6, 0x2a, 0x08, 0x21, 0x1f, 0xe9, 0xc1, 0x39, 0xec, 0x4c, 0x85, 0xc4, 0xa8, 0x69, 0xfa, -0xa1, 0x5f, 0x52, 0x0a, 0xd6, 0x99, 0xa2, 0x93, 0x48, 0x78, 0x6d, 0x2c, 0xa9, 0x8a, 0x6a, 0xe7, -0x0b, 0xff, 0x06, 0xbe, 0x72, 0xb6, 0xbb, 0x3c, 0x8c, 0x23, 0xb8, 0x91, 0x01, 0x19, 0x1a, 0xa9, -0x93, 0x6b, 0xc4, 0xbd, 0x48, 0x3e, 0x8c, 0x67, 0x38, 0x9d, 0x06, 0x03, 0x64, 0xef, 0x28, 0x96, -0x2b, 0xe9, 0x24, 0xdd, 0x40, 0xcc, 0x79, 0x2f, 0x49, 0x02, 0x94, 0x14, 0x16, 0x51, 0x20, 0x6a, -0x96, 0x36, 0x53, 0x8c, 0x9a, 0xe8, 0x12, 0x87, 0x64, 0xb6, 0x0c, 0x38, 0xcf, 0x9a, 0x53, 0x3d, -0x23, 0x9c, 0xf1, 0xa2, 0xb2, 0xfa, 0x40, 0x08, 0xf7, 0xc1, 0x87, 0x83, 0x47, 0x25, 0xf7, 0x06, -0xb8, 0xe0, 0xf4, 0x44, 0xac, 0xca, 0xac, 0x9a, 0x0d, 0xc4, 0xef, 0x92, 0xb6, 0xbb, 0x80, 0xe2, -0xac, 0xf5, 0x97, 0x25, 0x8f, 0x30, 0xa8, 0xbc, 0xde, 0x90, 0x62, 0x39, 0x17, 0x4c, 0x91, 0x12, -0x87, 0xcf, 0x1e, 0xa3, 0xdd, 0xb9, 0x3d, 0x20, 0x70, 0x8d, 0x78, 0x70, 0x07, 0x08, 0x35, 0xc9, -0x48, 0x56, 0xa6, 0xc3, 0x12, 0xa3, 0x1c, 0x39, 0x05, 0x4d, 0xc7, 0x7b, 0x92, 0x0f, 0x6e, 0xe4, -0xef, 0xcb, 0x5d, 0x2e, 0xde, 0xc4, 0x6d, 0x10, 0xe9, 0x80, 0xfb, 0x3c, 0xb4, 0x26, 0xd8, 0x5c, -0x64, 0x8f, 0x44, 0xef, 0x58, 0x94, 0x0b, 0x6b, 0xf8, 0x91, 0xf1, 0x77, 0xe8, 0x8f, 0x72, 0x77, -0x32, 0x22, 0x90, 0x5a, 0xda, 0xe2, 0xef, 0x30, 0x2a, 0xe8, 0x91, 0xa2, 0x75, 0x89, 0x3d, 0x21, -0x63, 0x3b, 0xae, 0x1e, 0x73, 0xb8, 0x3c, 0x1e, 0x18, 0x57, 0xf3, 0xc4, 0x7b, 0xa2, 0xd5, 0x4c, -0x94, 0x81, 0x6a, 0xa3, 0x3a, 0xaf, 0x96, 0x64, 0x17, 0xfb, 0x75, 0x2f, 0x62, 0xb9, 0x2f, 0xaf, -0x9b, 0x51, 0xc2, 0xd5, 0xb1, 0x21, 0x52, 0x8f, 0x2c, 0x94, 0x56, 0xb9, 0xc7, 0x1c, 0xe5, 0x43, -0x6f, 0xf9, 0x01, 0xf6, 0x1e, 0xd7, 0x67, 0xe0, 0x20, 0x86, 0x2b, 0x55, 0x62, 0x29, 0x64, 0xa5, -0xc2, 0xc6, 0xe1, 0x39, 0x36, 0x8e, 0x1b, 0xe1, 0x18, 0xbf, 0x1c, 0xd2, 0xb8, 0x68, 0x50, 0xc8, -0xcd, 0x93, 0x10, 0xc9, 0x0d, 0xf1, 0x70, 0x28, 0x2d, 0xfc, 0x8c, 0x94, 0x94, 0x78, 0x60, 0xba, -0x38, 0xed, 0xfa, 0xd8, 0x85, 0x24, 0xda, 0xab, 0xca, 0x28, 0x99, 0xb8, 0xbd, 0xd2, 0x67, 0xc3, -0x9d, 0x31, 0xa3, 0xaf, 0xcc, 0x79, 0xe9, 0xc1, 0x70, 0xe0, 0x3c, 0x55, 0x50, 0x0f, 0x9b, 0x15, -0xfb, 0xf2, 0xe5, 0xff, 0x4a, 0xb8, 0x6f, 0xd0, 0x05, 0x72, 0xae, 0x7c, 0x1c, 0x4a, 0xdb, 0x1a, -0x6f, 0xb6, 0xc4, 0x53, 0x8a, 0x7d, 0xa5, 0x7e, 0x7a, 0x5d, 0xae, 0x10, 0x0f, 0x09, 0x41, 0xa1, -0x05, 0xe2, 0xd1, 0xd8, 0xcc, 0x37, 0x84, 0xb5, 0x07, 0x97, 0x4a, 0x63, 0xbc, 0xda, 0x9c, 0x2b, -0x50, 0x17, 0xa9, 0xdd, 0xb9, 0xae, 0x8c, 0x8a, 0x1a, 0xb9, 0xc0, 0x40, 0xb7, 0x6c, 0xf3, 0xd5, -0x9b, 0xd7, 0xdf, 0x9e, 0x8b, 0x9f, 0x10, 0x47, 0x1e, 0xab, 0xd0, 0x67, 0x1e, 0x66, 0xf2, 0x8e, -0x4a, 0x60, 0x8a, 0xbc, 0x5e, 0xc1, 0x59, 0x8f, 0x20, 0x2d, 0xb7, 0xd2, 0xc2, 0x20, 0x63, 0x52, -0x05, 0x53, 0x21, 0x14, 0xbf, 0x03, 0xef, 0x86, 0x37, 0xf5, 0x3b, 0x3c, 0x76, 0xaa, 0xe9, 0x3d, -0x28, 0x19, 0xaf, 0x06, 0xfd, 0x1f, 0x8e, 0xa8, 0x6a, 0x7c, 0x85, 0x49, 0xb5, 0xaa, 0x1f, 0x38, -0xbd, 0x20, 0x0b, 0xab, 0xa4, 0x84, 0x22, 0x02, 0x74, 0x3c, 0x54, 0xca, 0xa3, 0xa6, 0xd6, 0xd6, -0x85, 0x59, 0xf2, 0x16, 0xe2, 0xec, 0xdd, 0xbd, 0xfc, 0x9a, 0x5f, 0xab, 0x61, 0x13, 0xdd, 0x39, -0x07, 0x86, 0x24, 0x3f, 0x8d, 0x2a, 0x36, 0x4c, 0xa2, 0x38, 0xe7, 0xee, 0x5c, 0x26, 0xd7, 0xea, -0x9b, 0x7f, 0x01, 0x21, 0xe0, 0xda, 0x98, 0x30, 0x0c, 0x00, 0x00}; - -unsigned char gzip_test_ref[] = -"Red Hat eCos Public License v1.1\n" -"\n" -"\n" -"\n" -"1. DEFINITIONS\n" -"\n" -"1.1. \"Contributor\" means each entity that creates or\n" -"contributes to the creation of Modifications.\n" -"\n" -"1.2. \"Contributor Version\" means the combination of the\n" -"Original Code, prior Modifications used by a\n" -"Contributor, and the Modifications made by that\n" -"particular Contributor.\n" -"\n" -"1.3. \"Covered Code\" means the Original Code or\n" -"Modifications or the combination of the Original Code\n" -"and Modifications, in each case including portions\n" -"thereof.\n" -"\n" -"1.4. \"Electronic Distribution Mechanism\" means a\n" -"mechanism generally accepted in the software development\n" -"community for the electronic transfer of data.\n" -"\n" -"1.5. \"Executable\" means Covered Code in any form other\n" -"than Source Code.\n" -"1.6. \"Initial Developer\" means the individual or entity\n" -"identified as the Initial Developer in the Source Code\n" -"notice required by Exhibit A.\n" -"\n" -"1.7. \"Larger Work\" means a work which combines Covered\n" -"Code or portions thereof with code not governed by the\n" -"terms of this License.\n" -"\n" -"1.8. \"License\" means this document.\n" -"\n" -"1.9. \"Modifications\" means any addition to or deletion\n" -"from the substance or structure of either the Original\n" -"Code or any previous Modifications. When Covered Code is\n" -"released as a series of files, a Modification is:\n" -"\n" -" A. Any addition to or deletion from the\n" -" contents of a file containing Original Code or\n" -" previous Modifications.\n" -"\n" -" B. Any new file that contains any part of the\n" -" Original Code or previous Modifications.\n" -"\n" -"1.10. \"Original Code\" means Source Code of computer\n" -"software code which is described in the Source Code\n" -"notice required by Exhibit A as Original Code, and\n" -"which, at the time of its release under this License is\n" -"not already Covered Code governed by this License.\n" -"\n" -"1.11. \"Source Code\" means the preferred form of the\n" -"Covered Code for making modifications to it, including\n" -"all modules it contains, plus any associated interface\n" -"definition files, scripts used to control compilation\n" -"and installation of an Executable, or a list of source\n" -"code differential comparisons against either the\n" -"Original Code or another well known, available Covered\n" -"Code of the Contributor's choice. The Source Code can be\n" -"in a compressed or archival form, provided the\n" -"appropriate decompression or de-archiving software is\n" -"widely available for no charge.\n" -"\n" -"1.12. \"You\" means an individual or a legal entity\n" -"exercising rights under, and complying with all of the\n" -"terms of, this License or a future version of this\n" -"License issued under Section 6.1. For legal entities,\n" -"\"You\" includes any entity which controls, is controlled\n" -"by, or is under common control with You. For purposes of\n" -"this definition, \"control\" means (a) the power, direct\n" -"or indirect, to cause the direction or management of\n" -"such entity, whether by contract or otherwise, or (b)\n" -"ownership of fifty percent (50%) or more of the\n" -"outstanding shares or beneficial ownership of such\n" -"entity.\n" -"\n" -"1.13. \"Red Hat Branded Code\" is code that Red Hat\n" -"distributes and/or permits others to distribute under\n" -"different terms than the Red Hat eCos Public License.\n" -"Red Hat's Branded Code may contain part or all of the\n" -"Covered Code.\n"; - -static void entry0( cyg_addrword_t data ) -{ - int i; - unsigned long len; - int err; - int buf_size = sizeof(gzip_test_ref)+512; - unsigned char* unpacked = malloc(buf_size); - - if (NULL == unpacked) - CYG_TEST_NA("Not enough memory for buffers"); - - CYG_TEST_INFO("Decompressing"); - len = buf_size; - err = uncompress(unpacked, &len, gzip_test, sizeof(gzip_test)); - - switch (err) { - case Z_OK: - break; - case Z_MEM_ERROR: - CYG_TEST_NA("Not enough memory for decompression"); - break; - case Z_BUF_ERROR: - CYG_TEST_FAIL_FINISH("Decompressed data larger than original"); - break; - case Z_DATA_ERROR: - CYG_TEST_FAIL_FINISH("Decompression failed"); - break; - default: - CYG_TEST_FAIL_FINISH("Unknown decompression error"); - break; - } - - for (i = 0; i < sizeof(gzip_test_ref)-1; i++) { - if (gzip_test_ref[i] != unpacked[i]) - CYG_TEST_FAIL_FINISH("Verify failed"); - } - - CYG_TEST_PASS_FINISH("zlib2 OK"); -} - -void zlib2_main( void ) -{ - CYG_TEST_INIT(); - - cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "zlib1", - (void *)stack[0], STACKSIZE,&thread[0], &thread_obj[0]); - cyg_thread_resume(thread[0]); - - cyg_scheduler_start(); - - CYG_TEST_FAIL_FINISH("Not reached"); -} - -externC void -cyg_start( void ) -{ - zlib2_main(); -} - -#else /* def CYGFUN_KERNEL_API_C */ -externC void -cyg_start( void ) -{ - CYG_TEST_INIT(); - CYG_TEST_NA("Kernel C API layer disabled"); -} -#endif /* def CYGFUN_KERNEL_API_C */ - -// EOF zlib1.c diff --git a/components/dfs/filesystems/jffs2/cyg/compress/zconf.h b/components/dfs/filesystems/jffs2/cyg/compress/zconf.h deleted file mode 100644 index dc360d8ff6..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/zconf.h +++ /dev/null @@ -1,358 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -// #ifdef __ECOS__ -#undef __ECOS__ -#define __ECOS__ -#include - -#ifndef RT_USING_LIBC -#define malloc rt_malloc -#define free rt_free -#define printf rt_kprintf -#endif - -//#define Z_PREFIX //by prife -//#include //prife no such file. - -#if CYGINT_COMPRESS_ZLIB_LOCAL_ALLOC != 0 -#define MY_ZCALLOC -#endif -#ifdef CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP -#undef MAX_WBITS -#define MAX_WBITS 15+16 /* 32K LZ77 window */ -#else -#define NO_GZIP -#define NO_GZCOMPRESS -#endif -// #endif - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define deflateBound z_deflateBound -# define deflatePrime z_deflatePrime -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateCopy z_inflateCopy -# define inflateReset z_inflateReset -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table -# define zError z_zError - -# define alloc_func z_alloc_func -# define free_func z_free_func -# define in_func z_in_func -# define out_func z_out_func -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# define z_off_t off_t -#endif -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif -#ifndef z_off_t -# define z_off_t long -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -# ifdef FAR -# undef FAR -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(deflateBound,"DEBND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(compressBound,"CMBND") -# pragma map(inflate_table,"INTABL") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/components/dfs/filesystems/jffs2/cyg/compress/zlib.h b/components/dfs/filesystems/jffs2/cyg/compress/zlib.h deleted file mode 100644 index 081e7c912f..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/compress/zlib.h +++ /dev/null @@ -1,1358 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.3, July 18th, 2005 - - Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.3" -#define ZLIB_VERNUM 0x1230 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumualte before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - the value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, - Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it gets to the next deflate block boundary. When decoding the - zlib or gzip format, this will cause inflate() to return immediately after - the header and before the first block. When doing a raw inflate, inflate() - will go ahead and process the first block, and will return when it gets to - the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 - if inflate() is currently decoding the last block in the deflate stream, - plus 128 if inflate() returned immediately after decoding an end-of-block - code or decoding the complete header up to just before the first byte of the - deflate stream. The end-of-block will not be indicated until all of the - uncompressed data from that block has been written to strm->next_out. The - number of unused bits may in general be greater than seven, except when - bit 7 of data_type is set, in which case the number of unused bits will be - less than eight. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster approach - may be used for the single inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() will decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically. Any information - contained in the gzip header is not retained, so applications that need that - information should instead use raw inflate, see inflateInit2() below, or - inflateBack() and perform their own processing of the gzip header and - trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may then - call inflateSync() to look for a good compression block if a partial recovery - of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as - Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy - parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. Z_FIXED prevents the - use of dynamic Huffman codes, allowing for a simpler decoder for special - applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. In addition, the - current implementation of deflate will use at most the window size minus - 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() - or deflateInit2(). This would be used to allocate an output buffer - for deflation in a single pass, and so would be called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the - bits leftover from a previous deflate stream when appending to it. As such, - this function can only be used for raw deflate, and must be used before the - first deflate() call after a deflateInit2() or deflateReset(). bits must be - less than or equal to 16, and that many of the least significant bits of - value will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is - a crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg - is set to null if there is no error message. inflateInit2 does not perform - any decompression apart from reading the zlib header if present: this will - be done by inflate(). (So next_in and avail_in may be modified, but next_out - and avail_out are unchanged.) -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK can be used to - force inflate() to return immediately after header processing is complete - and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When - any of extra, name, or comment are not Z_NULL and the respective field is - not present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not - be allocated, or Z_VERSION_ERROR if the version of the library does not - match the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free - the allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects - only the raw deflate stream to decompress. This is different from the - normal behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format - error in the deflate stream (in which case strm->msg is set to indicate the - nature of the error), or Z_STREAM_ERROR if the stream was not properly - initialized. In the case of Z_BUF_ERROR, an input or output error can be - distinguished using strm->next_in which will be Z_NULL only if in() returned - an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to - out() returning non-zero. (in() will always be called before out(), so - strm->next_in is assured to be defined if out() returns non-zero.) Note - that inflateBack() cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least the value returned - by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before - a compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - -typedef voidp gzFile; - -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h", or 'R' for run-length encoding - as in "wb1R". (See the description of deflateInit2 for more information - about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). The number of - uncompressed bytes written is limited to 4095. The caller should assure that - this limit is not exceeded. If it is exceeded, then gzprintf() will return - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read again later. - Only one character of push-back is allowed. gzungetc() returns the - character pushed, or -1 on failure. gzungetc() will fail if a - character has been pushed but not read yet, or if c is -1. The pushed - character will be discarded if the stream is repositioned with gzseek() - or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns 1 if file is being read directly without decompression, otherwise - zero. -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -#ifndef __ECOS__ -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required initial - value for the for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ -#endif // __ECOS__ - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/components/dfs/filesystems/jffs2/cyg/crc/crc.h b/components/dfs/filesystems/jffs2/cyg/crc/crc.h deleted file mode 100644 index 7b7db10e9e..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/crc/crc.h +++ /dev/null @@ -1,105 +0,0 @@ -//========================================================================== -// -// crc.h -// -// Interface for the CRC algorithms. -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 2002, 2009 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): Andrew Lunn -// Contributors: Andrew Lunn -// Date: 2002-08-06 -// Purpose: -// Description: -// -// This code is part of eCos (tm). -// -//####DESCRIPTIONEND#### -// -//========================================================================== - -#ifndef _SERVICES_CRC_CRC_H_ -#define _SERVICES_CRC_CRC_H_ - -#include - -#ifndef __externC -# ifdef __cplusplus -# define __externC extern "C" -# else -# define __externC extern -# endif -#endif - -// Compute a CRC, using the POSIX 1003 definition - -__externC cyg_uint32 -cyg_posix_crc32(unsigned char *s, int len); - -// Gary S. Brown's 32 bit CRC - -__externC cyg_uint32 -cyg_crc32(unsigned char *s, int len); - -// Gary S. Brown's 32 bit CRC, but accumulate the result from a -// previous CRC calculation - -__externC cyg_uint32 -cyg_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len); - -// Ethernet FCS Algorithm - -__externC cyg_uint32 -cyg_ether_crc32(unsigned char *s, int len); - -// Ethernet FCS algorithm, but accumulate the result from a previous -// CRC calculation. - -__externC cyg_uint32 -cyg_ether_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len); - -// 16 bit CRC with polynomial x^16+x^12+x^5+1 - -__externC cyg_uint16 -cyg_crc16(unsigned char *s, int len); - -__externC cyg_uint16 -cyg_crc16_accumulate(cyg_uint16 crc, unsigned char *s, int len); - -#endif // _SERVICES_CRC_CRC_H_ - - - diff --git a/components/dfs/filesystems/jffs2/cyg/crc/crc16.c b/components/dfs/filesystems/jffs2/cyg/crc/crc16.c deleted file mode 100644 index 7d6fa38105..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/crc/crc16.c +++ /dev/null @@ -1,104 +0,0 @@ -//========================================================================== -// -// crc16.c -// -// 16 bit CRC with polynomial x^16+x^12+x^5+1 -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): gthomas -// Contributors: gthomas,asl -// Date: 2001-01-31 -// Purpose: -// Description: -// -// This code is part of eCos (tm). -// -//####DESCRIPTIONEND#### -// -//========================================================================== - -#include - -// Table of CRC constants - implements x^16+x^12+x^5+1 -static const cyg_uint16 crc16_tab[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, -}; - -cyg_uint16 -cyg_crc16(unsigned char *buf, int len) -{ - int i; - cyg_uint16 cksum; - - cksum = 0; - for (i = 0; i < len; i++) { - cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xFF] ^ (cksum << 8); - } - return cksum; -} - diff --git a/components/dfs/filesystems/jffs2/cyg/crc/crc32.c b/components/dfs/filesystems/jffs2/cyg/crc/crc32.c deleted file mode 100644 index 7e4ea269f2..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/crc/crc32.c +++ /dev/null @@ -1,166 +0,0 @@ -//========================================================================== -// -// crc32.c -// -// Gary S. Brown's 32 bit CRC -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): gthomas -// Contributors: gthomas,asl -// Date: 2001-01-31 -// Purpose: -// Description: -// -// This code is part of eCos (tm). -// -//####DESCRIPTIONEND#### -// -//========================================================================== - -#include - - /* ====================================================================== */ - /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ - /* code or tables extracted from it, as desired without restriction. */ - /* */ - /* First, the polynomial itself and its table of feedback terms. The */ - /* polynomial is */ - /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ - /* */ - /* ====================================================================== */ - -static const cyg_uint32 crc32_tab[] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL - }; - -/* This is the standard Gary S. Brown's 32 bit CRC algorithm, but - accumulate the CRC into the result of a previous CRC. */ -cyg_uint32 -cyg_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len) -{ - int i; - - for (i = 0; i < len; i++) { - crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8); - } - return crc32val; -} - -/* This is the standard Gary S. Brown's 32 bit CRC algorithm */ -cyg_uint32 -cyg_crc32(unsigned char *s, int len) -{ - return (cyg_crc32_accumulate(0,s,len)); -} - -/* Return a 32-bit CRC of the contents of the buffer accumulating the - result from a previous CRC calculation. This uses the Ethernet FCS - algorithm.*/ -cyg_uint32 -cyg_ether_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len) -{ - int i; - - if (s == 0) return 0L; - - crc32val = crc32val ^ 0xffffffff; - for (i = 0; i < len; i++) { - crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8); - } - return crc32val ^ 0xffffffff; -} - -/* Return a 32-bit CRC of the contents of the buffer, using the - Ethernet FCS algorithm. */ -cyg_uint32 -cyg_ether_crc32(unsigned char *s, int len) -{ - return cyg_ether_crc32_accumulate(0,s,len); -} - - diff --git a/components/dfs/filesystems/jffs2/cyg/crc/posix_crc.c b/components/dfs/filesystems/jffs2/cyg/crc/posix_crc.c deleted file mode 100644 index 0da50e9a40..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/crc/posix_crc.c +++ /dev/null @@ -1,116 +0,0 @@ -//========================================================================== -// -// posix_crc.c -// -// POSIX CRC calculation -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): gthomas -// Contributors: gthomas,asl -// Date: 2001-01-31 -// Purpose: -// Description: -// -// This code is part of eCos (tm). -// -//####DESCRIPTIONEND#### -// -//========================================================================== - -#include - -// Compute a CRC, using the POSIX 1003 definition - -// Same basic algorithm as CRC-16, but the bits are defined in the -// opposite order. This computation matches the output of the -// Linux 'cksum' program. - -static const cyg_uint32 posix_crc32_tab[] = { - 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, - 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, - 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, - 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, - 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, - 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, - 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, - 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, - 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, - 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, - 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, - 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, - 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, - 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, - 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, - 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, - 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, - 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, - 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, - 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, - 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, - 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, - 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, - 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, - 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, - 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, - 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, - 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, - 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, - 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, - 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, - 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 - }; - -cyg_uint32 -cyg_posix_crc32(unsigned char *s, int len) -{ - int i; - cyg_uint32 crc32val; - unsigned long length; - - crc32val = 0; - for (i = 0; i < len; i++) { - crc32val = (crc32val << 8) ^ posix_crc32_tab[((crc32val >> 24) ^ *s++) & 0xFF]; - } - length = len; - while (length > 0) { - crc32val = (crc32val << 8) ^ posix_crc32_tab[((crc32val >> 24) ^ length) & 0xFF]; - length >>= 8; - } - crc32val = ~crc32val; - return crc32val; -} - diff --git a/components/dfs/filesystems/jffs2/cyg/fileio/fileio.h b/components/dfs/filesystems/jffs2/cyg/fileio/fileio.h deleted file mode 100644 index d364ae3b45..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/fileio/fileio.h +++ /dev/null @@ -1,489 +0,0 @@ -#ifndef CYGONCE_FILEIO_H -#define CYGONCE_FILEIO_H -//============================================================================= -// -// fileio.h -// -// Fileio header -// -//============================================================================= -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//============================================================================= -//#####DESCRIPTIONBEGIN#### -// -// Author(s): nickg -// Contributors: nickg -// Date: 2000-05-25 -// Purpose: Fileio header -// Description: This header contains the external definitions of the general file -// IO subsystem for POSIX and EL/IX compatability. -// -// Usage: -// #include -// ... -// -// -//####DESCRIPTIONEND#### -// -//============================================================================= - -//#include -//#include - -//#include -//#include -#ifdef CYGFUN_IO_FILEIO_SELECT -#include -#endif - -#include // NULL, size_t -#include -#if defined(__GNUC__) && !defined(__CC_ARM) -#include -#include -#else -#include -#include -#endif -//#include "os_sys_stat.h"//#include - -//============================================================================= -// forward definitions - -struct cyg_mtab_entry; -typedef struct cyg_mtab_entry cyg_mtab_entry; - -struct cyg_fstab_entry; -typedef struct cyg_fstab_entry cyg_fstab_entry; - -struct CYG_FILEOPS_TAG; -typedef struct CYG_FILEOPS_TAG cyg_fileops; - -struct CYG_FILE_TAG; -typedef struct CYG_FILE_TAG cyg_file; - -struct CYG_IOVEC_TAG; -typedef struct CYG_IOVEC_TAG cyg_iovec; - -struct CYG_UIO_TAG; -typedef struct CYG_UIO_TAG cyg_uio; - -struct CYG_SELINFO_TAG; -typedef struct CYG_SELINFO_TAG cyg_selinfo; - -//============================================================================= -// Directory pointer - -typedef CYG_ADDRWORD cyg_dir; - -#define CYG_DIR_NULL 0 - -//============================================================================= -// Filesystem table entry - -typedef int cyg_fsop_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ); -typedef int cyg_fsop_umount ( cyg_mtab_entry *mte ); -typedef int cyg_fsop_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, - int mode, cyg_file *fte ); -typedef int cyg_fsop_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); -typedef int cyg_fsop_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); -typedef int cyg_fsop_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); -typedef int cyg_fsop_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, - cyg_dir dir2, const char *name2 ); -typedef int cyg_fsop_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, - cyg_dir dir2, const char *name2, int type ); -typedef int cyg_fsop_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, - cyg_file *fte ); -typedef int cyg_fsop_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, - cyg_dir *dir_out ); -typedef int cyg_fsop_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, - struct stat *buf); -typedef int cyg_fsop_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, - int key, void *buf, int len ); -typedef int cyg_fsop_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, - int key, void *buf, int len ); - - -struct cyg_fstab_entry -{ - const char *name; // filesystem name - CYG_ADDRWORD data; // private data value -//#ifdef CYGOPT_FS_JFFS2_GCTHREAD -// struct rt_mutex syncmode; // synchronization mode -//#endif - cyg_uint32 syncmode; // synchronization mode - cyg_fsop_mount *mount; - cyg_fsop_umount *umount; - cyg_fsop_open *open; - cyg_fsop_unlink *unlink; - cyg_fsop_mkdir *mkdir; - cyg_fsop_rmdir *rmdir; - cyg_fsop_rename *rename; - cyg_fsop_link *link; - cyg_fsop_opendir *opendir; - cyg_fsop_chdir *chdir; - cyg_fsop_stat *stat; - cyg_fsop_getinfo *getinfo; - cyg_fsop_setinfo *setinfo; -} ;// CYG_HAL_TABLE_TYPE; //prife - -//----------------------------------------------------------------------------- -// Keys for getinfo() and setinfo() - -#define FS_INFO_CONF 1 /* pathconf() */ -#define FS_INFO_ACCESS 2 /* access() */ -#define FS_INFO_GETCWD 3 /* getcwd() */ -#define FS_INFO_SYNC 4 /* cyg_fs_fssync() */ -#define FS_INFO_ATTRIB 5 /* cyg_fs_(get|set)_attrib() */ -#ifdef CYGSEM_FILEIO_INFO_DISK_USAGE -#define FS_INFO_DISK_USAGE 6 /* get_disk_usage() */ -#endif -#define FS_INFO_CHMOD 7 /* chmod() */ - -//----------------------------------------------------------------------------- -// Types for link() - -#define CYG_FSLINK_HARD 1 /* form a hard link */ -#define CYG_FSLINK_SOFT 2 /* form a soft link */ - -//----------------------------------------------------------------------------- -// getinfo() and setinfo() buffers structures. - -struct cyg_getcwd_info -{ - char *buf; /* buffer for cwd string */ - size_t size; /* size of buffer */ -}; - -struct cyg_fs_disk_usage{ - cyg_uint64 total_blocks; - cyg_uint64 free_blocks; - cyg_uint32 block_size; -}; - -typedef cyg_uint32 cyg_fs_attrib_t; - -//----------------------------------------------------------------------------- -// Macro to define an initialized fstab entry - -#define FSTAB_ENTRY( _l, _name, _data, _syncmode, _mount, _umount, \ - _open, _unlink, _mkdir, _rmdir, _rename, _link, \ - _opendir, _chdir, _stat, _getinfo, _setinfo) \ -struct cyg_fstab_entry _l /*CYG_HAL_TABLE_ENTRY(fstab) prife*/ = \ -{ \ - _name, \ - _data, \ - _syncmode, \ - _mount, \ - _umount, \ - _open, \ - _unlink, \ - _mkdir, \ - _rmdir, \ - _rename, \ - _link, \ - _opendir, \ - _chdir, \ - _stat, \ - _getinfo, \ - _setinfo \ -}; - -//============================================================================= -// Mount table entry - -struct cyg_mtab_entry -{ - const char *name; // name of mount point - const char *fsname; // name of implementing filesystem - const char *devname; // name of hardware device - CYG_ADDRWORD data; // private data value - - // The following are filled in after a successful mount operation - cyg_bool valid; // Valid entry? - cyg_fstab_entry *fs; // pointer to fstab entry - cyg_dir root; // root directory pointer -} ; // CYG_HAL_TABLE_TYPE; // prife - - -// This macro defines an initialized mtab entry - -#define MTAB_ENTRY( _l, _name, _fsname, _devname, _data ) \ -struct cyg_mtab_entry _l /*CYG_HAL_TABLE_ENTRY(mtab) prife */ = \ -{ \ - _name, \ - _fsname, \ - _devname, \ - _data, \ - false, \ - NULL, \ - CYG_DIR_NULL \ -}; - -//============================================================================= -// IO vector descriptors - -struct CYG_IOVEC_TAG -{ - void *iov_base; /* Base address. */ - ssize_t iov_len; /* Length. */ -}; - -enum cyg_uio_rw { UIO_READ, UIO_WRITE }; - -/* Segment flag values. */ -enum cyg_uio_seg -{ - UIO_USERSPACE, /* from user data space */ - UIO_SYSSPACE /* from system space */ -}; - -struct CYG_UIO_TAG -{ - struct CYG_IOVEC_TAG *uio_iov; /* pointer to array of iovecs */ - int uio_iovcnt; /* number of iovecs in array */ - off_t uio_offset; /* offset into file this uio corresponds to */ - ssize_t uio_resid; /* residual i/o count */ - enum cyg_uio_seg uio_segflg; /* see above */ - enum cyg_uio_rw uio_rw; /* see above */ -}; - -// Limits -#define UIO_SMALLIOV 8 /* 8 on stack, else malloc */ - -//============================================================================= -// Description of open file - -typedef int cyg_fileop_readwrite (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); -typedef cyg_fileop_readwrite cyg_fileop_read; -typedef cyg_fileop_readwrite cyg_fileop_write; -typedef int cyg_fileop_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence ); -typedef int cyg_fileop_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, - CYG_ADDRWORD data); -typedef cyg_bool cyg_fileop_select (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info); -typedef int cyg_fileop_fsync (struct CYG_FILE_TAG *fp, int mode ); -typedef int cyg_fileop_close (struct CYG_FILE_TAG *fp); -typedef int cyg_fileop_fstat (struct CYG_FILE_TAG *fp, struct stat *buf ); -typedef int cyg_fileop_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); -typedef int cyg_fileop_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len ); - -struct CYG_FILEOPS_TAG -{ - cyg_fileop_read *fo_read; - cyg_fileop_write *fo_write; - cyg_fileop_lseek *fo_lseek; - cyg_fileop_ioctl *fo_ioctl; - cyg_fileop_select *fo_select; - cyg_fileop_fsync *fo_fsync; - cyg_fileop_close *fo_close; - cyg_fileop_fstat *fo_fstat; - cyg_fileop_getinfo *fo_getinfo; - cyg_fileop_setinfo *fo_setinfo; -}; - -struct CYG_FILE_TAG -{ - cyg_uint32 f_flag; /* file state */ - cyg_uint16 f_ucount; /* use count */ - cyg_uint16 f_type; /* descriptor type */ - cyg_uint32 f_syncmode; /* synchronization protocol */ - struct CYG_FILEOPS_TAG *f_ops; /* file operations */ - off_t f_offset; /* current offset */ - CYG_ADDRWORD f_data; /* file or socket */ - CYG_ADDRWORD f_xops; /* extra type specific ops */ - cyg_mtab_entry *f_mte; /* mount table entry */ -}; - -//----------------------------------------------------------------------------- -// File flags - -// Allocation here is that bits 0..15 are copies of bits from the open -// flags, bits 16..23 are extra bits that are visible to filesystems but -// are not derived from the open call, and bits 24..31 are reserved for -// the fileio infrastructure. -#define CYG_FREAD O_RDONLY -#define CYG_FWRITE O_WRONLY -#define CYG_FNONBLOCK O_NONBLOCK -#define CYG_FAPPEND O_APPEND -#define CYG_FASYNC 0x00010000 -#define CYG_FDIR 0x00020000 - -#define CYG_FLOCKED 0x01000000 // Set if file is locked -#define CYG_FLOCK 0x02000000 // Lock during file ops -#define CYG_FALLOC 0x80000000 // File is "busy", i.e. allocated - -// Mask for open mode bits stored in file object -#define CYG_FILE_MODE_MASK (CYG_FREAD|CYG_FWRITE|CYG_FNONBLOCK|CYG_FAPPEND) - -//----------------------------------------------------------------------------- -// Type of file - -#define CYG_FILE_TYPE_FILE 1 /* file */ -#define CYG_FILE_TYPE_SOCKET 2 /* communications endpoint */ -#define CYG_FILE_TYPE_DEVICE 3 /* device */ - -//----------------------------------------------------------------------------- -// Keys for getinfo() and setinfo() - -#define FILE_INFO_CONF 1 /* fpathconf() */ - -//----------------------------------------------------------------------------- -// Modes for fsync() - -#define CYG_FSYNC 1 -#define CYG_FDATASYNC 2 - -//----------------------------------------------------------------------------- -// Get/set info buffer structures - -// This is used for pathconf() and fpathconf() -struct cyg_pathconf_info -{ - int name; // POSIX defined variable name - long value; // Returned variable value -}; - -//============================================================================= -// Synchronization modes -// These values are filled into the syncmode fields of the above structures -// and define the synchronization protocol used when accessing the object in -// question. - -#define CYG_SYNCMODE_NONE (0) // no locking required - -#define CYG_SYNCMODE_FILE_FILESYSTEM 0x0002 // lock fs during file ops -#define CYG_SYNCMODE_FILE_MOUNTPOINT 0x0004 // lock mte during file ops -#define CYG_SYNCMODE_IO_FILE 0x0010 // lock file during io ops -#define CYG_SYNCMODE_IO_FILESYSTEM 0x0020 // lock fs during io ops -#define CYG_SYNCMODE_IO_MOUNTPOINT 0x0040 // lock mte during io ops -#define CYG_SYNCMODE_SOCK_FILE 0x0100 // lock socket during socket ops -#define CYG_SYNCMODE_SOCK_NETSTACK 0x0800 // lock netstack during socket ops - -#define CYG_SYNCMODE_IO_SHIFT (4) // shift for IO to file bits -#define CYG_SYNCMODE_SOCK_SHIFT (8) // shift for sock to file bits - -//============================================================================= -// Mount and umount functions - -__externC int mount( const char *devname, - const char *dir, - const char *fsname); - -__externC int umount( const char *name); - -//============================================================================= -// Get/Set info functions - -__externC int cyg_fs_getinfo( const char *path, int key, void *buf, int len ); -__externC int cyg_fs_setinfo( const char *path, int key, void *buf, int len ); -__externC int cyg_fs_fgetinfo( int fd, int key, void *buf, int len ); -__externC int cyg_fs_fsetinfo( int fd, int key, void *buf, int len ); - -#ifdef CYGFUN_IO_FILEIO_SELECT -//============================================================================= -// Select support - -//----------------------------------------------------------------------------- -// Data structure for embedding in client data structures. A pointer to this -// must be passed to cyg_selrecord() and cyg_selwakeup(). - -struct CYG_SELINFO_TAG -{ - CYG_ADDRWORD si_info; // info passed through from fo_select() - cyg_flag_value_t si_waitFlag; // select wait flags -}; - -//----------------------------------------------------------------------------- -// Select support functions. - -// cyg_selinit() is used to initialize a selinfo structure. -__externC void cyg_selinit( struct CYG_SELINFO_TAG *sip ); - -// cyg_selrecord() is called when a client device needs to register -// the current thread for selection. -__externC void cyg_selrecord( CYG_ADDRWORD info, struct CYG_SELINFO_TAG *sip ); - -// cyg_selwakeup() is called when the client device matches the select -// criterion, and needs to wake up a selector. -__externC void cyg_selwakeup( struct CYG_SELINFO_TAG *sip ); -#endif -//============================================================================= -// Timestamp support - -// Provides the current time as a time_t timestamp for use in filesystem -// data strucures. - -__externC time_t jffs2_get_timestamp(void); - -//============================================================================= -// Miscellaneous functions. - -// Provide a function to synchronize an individual file system. (ie write -// file and directory information to disk) -__externC int cyg_fs_fssync(const char *path); - -// Functions to set and get attributes of a file, eg FAT attributes -// like hidden and system. -__externC int cyg_fs_set_attrib( const char *fname, - const cyg_fs_attrib_t new_attrib ); -__externC int cyg_fs_get_attrib( const char *fname, - cyg_fs_attrib_t * const file_attrib ); - -// Functions to lock and unlock a filesystem. These are normally used -// internally by the fileio layer, but the file system might need to -// use them when it needs to lock itself, eg when performing garbage -// collect. -__externC void cyg_fs_lock( cyg_mtab_entry *mte, cyg_uint32 syncmode ); - -__externC void cyg_fs_unlock( cyg_mtab_entry *mte, cyg_uint32 syncmode ); - -// To be able to lock the filesystem you need the mte. This function -// allows the table of mounted filesystems to be searched to find an -// mte which uses the give filesystem root. - -__externC cyg_mtab_entry * cyg_fs_root_lookup( cyg_dir *root ); - -//============================================================================= -// Default functions. -// Cast to the appropriate type, these functions can be put into any of -// the operation table slots to provide the defined error code. - -__externC int cyg_fileio_enosys(void); -__externC int cyg_fileio_erofs(void); -__externC int cyg_fileio_enoerr(void); -__externC int cyg_fileio_enotdir(void); -__externC cyg_fileop_select cyg_fileio_seltrue; - -//----------------------------------------------------------------------------- -#endif // ifndef CYGONCE_FILEIO_H -// End of fileio.h diff --git a/components/dfs/filesystems/jffs2/cyg/hal/basetype.h b/components/dfs/filesystems/jffs2/cyg/hal/basetype.h deleted file mode 100644 index 6f3455c0df..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/hal/basetype.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef CYGONCE_HAL_BASETYPE_H -#define CYGONCE_HAL_BASETYPE_H - -//============================================================================= -// -// basetype.h -// -// Standard types for this architecture. -// -//============================================================================= -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//============================================================================= -//#####DESCRIPTIONBEGIN#### -// -// Author(s): nickg, gthomas -// Contributors: nickg, gthomas -// Date: 1998-09-11 -// Purpose: Define architecture base types. -// Usage: Included by "cyg_type.h", do not use directly - -// -//####DESCRIPTIONEND#### -// - -//----------------------------------------------------------------------------- -// Characterize the architecture - -#ifdef __ARMEB__ -# define CYG_BYTEORDER CYG_MSBFIRST // Big endian -#else -# define CYG_BYTEORDER CYG_LSBFIRST // Little endian -#endif - -#if defined(__ARMEL__) && defined(__VFP_FP__) -# define CYG_DOUBLE_BYTEORDER CYG_LSBFIRST -#else -# define CYG_DOUBLE_BYTEORDER CYG_MSBFIRST // Big? endian -#endif - -//----------------------------------------------------------------------------- -// ARM does not usually use labels with underscores. - -#define CYG_LABEL_NAME(_name_) _name_ -#define CYG_LABEL_DEFN(_name_) _name_ - -//----------------------------------------------------------------------------- -// Override the alignment definitions from cyg_type.h. ARM only allows 4 -// byte alignment whereas the default is 8 byte. - -#define CYGARC_ALIGNMENT 4 -#define CYGARC_P2ALIGNMENT 2 - -//----------------------------------------------------------------------------- -// Define the standard variable sizes - -// The ARM architecture uses the default definitions of the base types, -// so we do not need to define any here. - -//----------------------------------------------------------------------------- -#endif // CYGONCE_HAL_BASETYPE_H -// End of basetype.h diff --git a/components/dfs/filesystems/jffs2/cyg/hal/drv_api.h b/components/dfs/filesystems/jffs2/cyg/hal/drv_api.h deleted file mode 100644 index de4346673c..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/hal/drv_api.h +++ /dev/null @@ -1,250 +0,0 @@ -#ifndef CYGONCE_HAL_DRV_API_H -#define CYGONCE_HAL_DRV_API_H - -/*========================================================================== -// -// drv_api.h -// -// Native API for Kernel -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): nickg -// Date: 1999-02-24 -// Purpose: Driver API -// Description: This file defines the API used by device drivers to access -// system services. When the kernel is present it maps directly -// to the Kernel C API. When the kernel is absent, it is provided -// by a set of HAL functions. -// -// Usage: #include -// -//####DESCRIPTIONEND#### -// -//========================================================================*/ - -//#include //mod by prife -#include - -#ifdef CYGPKG_KERNEL - -/*------------------------------------------------------------------------*/ -/* Kernel co-resident version of API */ - -#include - -#ifndef CYGFUN_KERNEL_API_C -#error Driver API requres Kernel API to be present -#endif - -#include - -#define cyg_drv_isr_lock cyg_interrupt_disable -#define cyg_drv_isr_unlock cyg_interrupt_enable - -#define cyg_drv_dsr_lock cyg_scheduler_lock -#define cyg_drv_dsr_unlock cyg_scheduler_unlock - -#define cyg_drv_mutex_t cyg_mutex_t -#define cyg_drv_mutex_init cyg_mutex_init -#define cyg_drv_mutex_destroy cyg_mutex_destroy -#define cyg_drv_mutex_lock cyg_mutex_lock -#define cyg_drv_mutex_trylock cyg_mutex_trylock -#define cyg_drv_mutex_unlock cyg_mutex_unlock -#define cyg_drv_mutex_release cyg_mutex_release - -#define cyg_drv_cond_t cyg_cond_t -#define cyg_drv_cond_init cyg_cond_init -#define cyg_drv_cond_destroy cyg_cond_destroy -#define cyg_drv_cond_wait cyg_cond_wait -#define cyg_drv_cond_signal cyg_cond_signal -#define cyg_drv_cond_broadcast cyg_cond_broadcast - -#define cyg_drv_interrupt_create cyg_interrupt_create -#define cyg_drv_interrupt_delete cyg_interrupt_delete -#define cyg_drv_interrupt_attach cyg_interrupt_attach -#define cyg_drv_interrupt_detach cyg_interrupt_detach -#define cyg_drv_interrupt_mask cyg_interrupt_mask -#define cyg_drv_interrupt_unmask cyg_interrupt_unmask -#define cyg_drv_interrupt_mask_intunsafe cyg_interrupt_mask_intunsafe -#define cyg_drv_interrupt_unmask_intunsafe cyg_interrupt_unmask_intunsafe -#define cyg_drv_interrupt_acknowledge cyg_interrupt_acknowledge -#define cyg_drv_interrupt_configure cyg_interrupt_configure -#define cyg_drv_interrupt_level cyg_interrupt_level -#define cyg_drv_interrupt_set_cpu cyg_interrupt_set_cpu -#define cyg_drv_interrupt_get_cpu cyg_interrupt_get_cpu - -#define cyg_drv_spinlock_t cyg_spinlock_t -#define cyg_drv_spinlock_init cyg_spinlock_init -#define cyg_drv_spinlock_spin cyg_spinlock_spin -#define cyg_drv_spinlock_clear cyg_spinlock_clear -#define cyg_drv_spinlock_try cyg_spinlock_try -#define cyg_drv_spinlock_test cyg_spinlock_test -#define cyg_drv_spinlock_spin_intsave cyg_spinlock_spin_intsave -#define cyg_drv_spinlock_clear_intsave cyg_spinlock_clear_intsave - -#else /* CYGPKG_KERNEL */ - -/*------------------------------------------------------------------------*/ -/* Non-kernel version of API */ - -typedef CYG_ADDRWORD cyg_addrword_t; /* May hold pointer or word */ -typedef cyg_addrword_t cyg_handle_t; /* Object handle */ -typedef cyg_uint32 cyg_priority_t; /* type for priorities */ -typedef cyg_uint32 cyg_vector_t; /* Interrupt vector id */ -typedef cyg_uint32 cyg_cpu_t; /* CPU id */ -typedef int cyg_bool_t; -typedef cyg_int32 cyg_code_t; /* type for various codes */ - -typedef cyg_uint32 cyg_ISR_t( cyg_vector_t vector, cyg_addrword_t data); -typedef void cyg_DSR_t(cyg_vector_t vector, - cyg_ucount32 count, - cyg_addrword_t data); - - -externC void cyg_drv_isr_lock(void); -externC void cyg_drv_isr_unlock(void); - -externC void cyg_drv_dsr_lock(void); -externC void cyg_drv_dsr_unlock(void); - -typedef struct -{ - cyg_atomic lock; -} cyg_drv_mutex_t; - -externC void cyg_drv_mutex_init( cyg_drv_mutex_t *mutex ); -externC void cyg_drv_mutex_destroy( cyg_drv_mutex_t *mutex ); -externC cyg_bool_t cyg_drv_mutex_lock( cyg_drv_mutex_t *mutex ); -externC cyg_bool_t cyg_drv_mutex_trylock( cyg_drv_mutex_t *mutex ); -externC void cyg_drv_mutex_unlock( cyg_drv_mutex_t *mutex ); -externC void cyg_drv_mutex_release( cyg_drv_mutex_t *mutex ); - -typedef struct -{ - cyg_atomic wait; - cyg_drv_mutex_t *mutex; -} cyg_drv_cond_t; - -externC void cyg_drv_cond_init( cyg_drv_cond_t *cond, cyg_drv_mutex_t *mutex ); -externC void cyg_drv_cond_destroy( cyg_drv_cond_t *cond ); -externC cyg_bool_t cyg_drv_cond_wait( cyg_drv_cond_t *cond ); -externC void cyg_drv_cond_signal( cyg_drv_cond_t *cond ); -externC void cyg_drv_cond_broadcast( cyg_drv_cond_t *cond ); - -typedef struct cyg_interrupt -{ - cyg_vector_t vector; - cyg_priority_t priority; - cyg_ISR_t *isr; - cyg_DSR_t *dsr; - CYG_ADDRWORD data; - - struct cyg_interrupt* volatile next_dsr; - volatile cyg_int32 dsr_count; - -#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN - struct cyg_interrupt *next; -#endif - -} cyg_interrupt; - -externC void cyg_drv_interrupt_create( - cyg_vector_t vector, - cyg_priority_t priority, - cyg_addrword_t data, - cyg_ISR_t *isr, - cyg_DSR_t *dsr, - cyg_handle_t *handle, - cyg_interrupt *intr - ); -externC void cyg_drv_interrupt_delete( cyg_handle_t interrupt ); -externC void cyg_drv_interrupt_attach( cyg_handle_t interrupt ); -externC void cyg_drv_interrupt_detach( cyg_handle_t interrupt ); - -externC void cyg_drv_interrupt_mask( cyg_vector_t vector ); -externC void cyg_drv_interrupt_mask_intunsafe( cyg_vector_t vector ); -externC void cyg_drv_interrupt_unmask( cyg_vector_t vector ); -externC void cyg_drv_interrupt_unmask_intunsafe( cyg_vector_t vector ); -externC void cyg_drv_interrupt_acknowledge( cyg_vector_t vector ); -externC void cyg_drv_interrupt_configure( - cyg_vector_t vector, - cyg_bool_t level, - cyg_bool_t up - ); -externC void cyg_drv_interrupt_level( cyg_vector_t vector, cyg_priority_t level ); -externC void cyg_drv_interrupt_set_cpu( cyg_vector_t vector, cyg_cpu_t cpu ); -externC cyg_cpu_t cyg_drv_interrupt_get_cpu( cyg_vector_t vector ); - - -enum cyg_ISR_results -{ - CYG_ISR_HANDLED = 1, /* Interrupt was handled */ - CYG_ISR_CALL_DSR = 2 /* Schedule DSR */ -}; - - -typedef struct -{ - cyg_atomic lock; -} cyg_drv_spinlock_t; - -void cyg_drv_spinlock_init( - cyg_drv_spinlock_t *lock, /* spinlock to initialize */ - cyg_bool_t locked /* init locked or unlocked */ -); - -void cyg_drv_spinlock_destroy( cyg_drv_spinlock_t *lock ); - -void cyg_drv_spinlock_spin( cyg_drv_spinlock_t *lock ); - -void cyg_drv_spinlock_clear( cyg_drv_spinlock_t *lock ); - -cyg_bool_t cyg_drv_spinlock_try( cyg_drv_spinlock_t *lock ); - -cyg_bool_t cyg_drv_spinlock_test( cyg_drv_spinlock_t *lock ); - -void cyg_drv_spinlock_spin_intsave( cyg_drv_spinlock_t *lock, - cyg_addrword_t *istate ); - -void cyg_drv_spinlock_clear_intsave( cyg_drv_spinlock_t *lock, - cyg_addrword_t istate ); - -#endif /* CYGPKG_KERNEL */ - -/*------------------------------------------------------------------------*/ -/* EOF drv_api.h */ -#endif // CYGONCE_HAL_DRV_API_H diff --git a/components/dfs/filesystems/jffs2/cyg/infra/cyg_type.h b/components/dfs/filesystems/jffs2/cyg/infra/cyg_type.h deleted file mode 100644 index 01b60c5099..0000000000 --- a/components/dfs/filesystems/jffs2/cyg/infra/cyg_type.h +++ /dev/null @@ -1,544 +0,0 @@ -#ifndef CYGONCE_INFRA_CYG_TYPE_H -#define CYGONCE_INFRA_CYG_TYPE_H - -//========================================================================== -// -// cyg_type.h -// -// Standard types, and some useful coding macros. -// -//========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): nickg from an original by hmt -// Contributors: nickg -// Date: 1997-09-08 -// Purpose: share unambiguously sized types. -// Description: we typedef [cyg_][u]int8,16,32 &c for general use. -// Usage: #include "cyg/infra/cyg_type.h" -// ... -// cyg_int32 my_32bit_integer; -// -//####DESCRIPTIONEND#### -// - -#include // Definition of NULL from the compiler - -// ------------------------------------------------------------------------- -// Some useful macros. These are defined here by default. - -// __externC is used in mixed C/C++ headers to force C linkage on an external -// definition. It avoids having to put all sorts of ifdefs in. - -#ifdef __cplusplus -# define __externC extern "C" -#else -# define __externC extern -#endif -// Also define externC for now - but it is deprecated -#define externC __externC - -// Compiler version. -#ifdef __GNUC__ -# if defined(__GNU_PATCHLEVEL__) -# define __GNUC_VERSION__ (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100 \ - + __GNUC_PATCHLEVEL__) -# else -# define __GNUC_VERSION__ (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100) -# endif -#endif - -// ------------------------------------------------------------------------- -// The header defines the base types used here. It is -// supplied either by the target architecture HAL, or by the host -// porting kit. They are all defined as macros, and only those that -// make choices other than the defaults given below need be defined. - -#define CYG_LSBFIRST 1234 -#define CYG_MSBFIRST 4321 - -#include - -#if (CYG_BYTEORDER != CYG_LSBFIRST) && (CYG_BYTEORDER != CYG_MSBFIRST) -# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST -#endif - -#ifndef CYG_DOUBLE_BYTEORDER -#define CYG_DOUBLE_BYTEORDER CYG_BYTEORDER -#endif - -#ifndef cyg_halint8 -# define cyg_halint8 char -#endif -#ifndef cyg_halint16 -# define cyg_halint16 short -#endif -#ifndef cyg_halint32 -# define cyg_halint32 int -#endif -#ifndef cyg_halint64 -# define cyg_halint64 long long -#endif - -#ifndef cyg_halcount8 -# define cyg_halcount8 int -#endif -#ifndef cyg_halcount16 -# define cyg_halcount16 int -#endif -#ifndef cyg_halcount32 -# define cyg_halcount32 int -#endif -#ifndef cyg_halcount64 -# define cyg_halcount64 long long -#endif - -#ifndef cyg_haladdress -# define cyg_haladdress cyg_uint32 -#endif -#ifndef cyg_haladdrword -# define cyg_haladdrword cyg_uint32 -#endif - -#ifndef cyg_halbool -# define cyg_halbool int -#endif - -#ifndef cyg_halatomic -# define cyg_halatomic cyg_halint8 -#endif - -// ------------------------------------------------------------------------- -// Provide a default architecture alignment -// This may be overridden in basetype.h if necessary. -// These should be straightforward numbers to allow use in assembly. - -#ifndef CYGARC_ALIGNMENT -# define CYGARC_ALIGNMENT 8 -#endif -// And corresponding power of two alignment -#ifndef CYGARC_P2ALIGNMENT -# define CYGARC_P2ALIGNMENT 3 -#endif -#if (CYGARC_ALIGNMENT) != (1 << CYGARC_P2ALIGNMENT) -# error "Inconsistent CYGARC_ALIGNMENT and CYGARC_P2ALIGNMENT values" -#endif - -// ------------------------------------------------------------------------- -// The obvious few that compilers may define for you. -// But in case they don't: - -#ifndef NULL -# define NULL 0 -#endif - -#ifndef __cplusplus - -typedef cyg_halbool bool; - -# ifndef false -# define false 0 -# endif - -# ifndef true -# define true (!false) -# endif - -#endif - -// ------------------------------------------------------------------------- -// Allow creation of procedure-like macros that are a single statement, -// and must be followed by a semi-colon - -#define CYG_MACRO_START do { -#define CYG_MACRO_END } while (0) - -#define CYG_EMPTY_STATEMENT CYG_MACRO_START CYG_MACRO_END - -#define CYG_UNUSED_PARAM( _type_, _name_ ) CYG_MACRO_START \ - _type_ __tmp1 = (_name_); \ - _type_ __tmp2 = __tmp1; \ - __tmp1 = __tmp2; \ -CYG_MACRO_END - - -//---------------------------------------------------------------------------- -// The unused attribute stops the compiler warning about the variable -// not being used. -// The used attribute prevents the compiler from optimizing it away. - -#define CYG_REFERENCE_OBJECT(__object__) \ - CYG_MACRO_START \ - static const void* __cygvar_discard_me__ \ - __attribute__ ((unused, used)) = (const void*)&(__object__); \ - CYG_MACRO_END - -// ------------------------------------------------------------------------- -// Define basic types for using integers in memory and structures; -// depends on compiler defaults and CPU type. - -typedef unsigned cyg_halint8 cyg_uint8 ; -typedef signed cyg_halint8 cyg_int8 ; - -typedef unsigned cyg_halint16 cyg_uint16 ; -typedef signed cyg_halint16 cyg_int16 ; - -typedef unsigned cyg_halint32 cyg_uint32 ; -typedef signed cyg_halint32 cyg_int32 ; - -typedef unsigned cyg_halint64 cyg_uint64 ; -typedef signed cyg_halint64 cyg_int64 ; - -typedef cyg_halbool cyg_bool ; - -// ------------------------------------------------------------------------- -// Define types for using integers in registers for looping and the like; -// depends on CPU type, choose what it is most comfortable with, with at -// least the range required. - -typedef unsigned cyg_halcount8 cyg_ucount8 ; -typedef signed cyg_halcount8 cyg_count8 ; - -typedef unsigned cyg_halcount16 cyg_ucount16 ; -typedef signed cyg_halcount16 cyg_count16 ; - -typedef unsigned cyg_halcount32 cyg_ucount32 ; -typedef signed cyg_halcount32 cyg_count32 ; - -typedef unsigned cyg_halcount64 cyg_ucount64 ; -typedef signed cyg_halcount64 cyg_count64 ; - -// ------------------------------------------------------------------------- -// Define a type to be used for atomic accesses. This type is guaranteed -// to be read or written in a single uninterruptible operation. This type -// is at least a single byte. - -typedef volatile unsigned cyg_halatomic cyg_atomic; -typedef volatile unsigned cyg_halatomic CYG_ATOMIC; - -// ------------------------------------------------------------------------- -// Define types for access plain, on-the-metal memory or devices. - -typedef cyg_uint32 CYG_WORD; -typedef cyg_uint8 CYG_BYTE; -typedef cyg_uint16 CYG_WORD16; -typedef cyg_uint32 CYG_WORD32; -typedef cyg_uint64 CYG_WORD64; - -typedef cyg_haladdress CYG_ADDRESS; -typedef cyg_haladdrword CYG_ADDRWORD; - -// ------------------------------------------------------------------------- -// Number of elements in a (statically allocated) array. - -#define CYG_NELEM(a) (sizeof(a) / sizeof((a)[0])) - -// ------------------------------------------------------------------------- -// Constructor ordering macros. These are added as annotations to all -// static objects to order the constuctors appropriately. - -#if defined(__cplusplus) && defined(__GNUC__) && \ - !defined(CYGBLD_ATTRIB_INIT_PRI) -# define CYGBLD_ATTRIB_INIT_PRI( _pri_ ) __attribute__((init_priority(_pri_))) -#elif !defined(CYGBLD_ATTRIB_INIT_PRI) -// FIXME: should maybe just bomb out if this is attempted anywhere else? -// Not sure -# define CYGBLD_ATTRIB_INIT_PRI( _pri_ ) -#endif - -// The following will be removed eventually as it doesn't allow the use of -// e.g. pri+5 format -#define CYG_INIT_PRIORITY( _pri_ ) CYGBLD_ATTRIB_INIT_PRI( CYG_INIT_##_pri_ ) - -#define CYGBLD_ATTRIB_INIT_BEFORE( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_-100) -#define CYGBLD_ATTRIB_INIT_AFTER( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_+100) - -#if defined(__GNUC__) && !defined(__cplusplus) && (__GNUC_VERSION__ >= 40300) -// Equivalents of the above for C functions, available from gcc 4.3 onwards. -# define CYGBLD_ATTRIB_C_INIT_PRI( _pri_) __attribute__((constructor (_pri_))) -# define CYGBLD_ATTRIB_C_INIT_BEFORE( _pri_ ) __attribute__((constructor (_pri_-100))) -# define CYGBLD_ATTRIB_C_INIT_AFTER( _pri_ ) __attribute__((constructor (_pri_+100))) -#endif - -// Start with initializing everything inside the cpu and the main memory. -#define CYG_INIT_HAL 10000 -#define CYG_INIT_SCHEDULER 11000 -#define CYG_INIT_IDLE_THREAD 11100 -#define CYG_INIT_INTERRUPTS 12000 -#define CYG_INIT_CLOCK 14000 -#define CYG_INIT_THREADS 16000 -#define CYG_INIT_KERNEL 19000 -#define CYG_INIT_MEMALLOC 20000 -// Now move on to I/O subsystems and device drivers. These can make use of -// kernel and HAL functionality, and can dynamically allocate memory if -// absolutely needed. For now they can also assume that diag_printf() -// functionality is available, but that may change in future. -// -// Primary buses are ones very closely tied to the processor, e.g. PCI. -#define CYG_INIT_BUS_PRIMARY 30000 -// Not yet: on some targets cyg_pci_init() has to be called very early -// on for HAL diagnostics to work. -// #define CYG_INIT_BUS_PCI CYG_INIT_BUS_PRIMARY -// -// Secondary buses may hang off primary buses, e.g. USB host. -#define CYG_INIT_BUS_SECONDARY 31000 -// Tertiary buses are everything else. -#define CYG_INIT_BUS_TERTIARY 32000 -#define CYG_INIT_BUS_I2C CYG_INIT_BUS_TERTIARY -#define CYG_INIT_BUS_SPI CYG_INIT_BUS_TERTIARY -// -// In future HAL diag initialization may happen at this point. -// -// Watchdogs and wallclocks often hang off a tertiary bus but -// have no dependencies -#define CYG_INIT_DEV_WATCHDOG 35000 -#define CYG_INIT_DEV_WALLCLOCK 36000 -// A primary block configuration can be initialized with no need -// for per-unit configuration information. -#define CYG_INIT_DEV_BLOCK_PRIMARY 37000 -#define CYG_INIT_DEV_FLASH CYG_INIT_DEV_BLOCK_PRIMARY -// Per-unit configuration data extracted from primary storage. -// NOTE: for future use, not implemented yet. -#define CYG_INIT_CONFIG 38000 -// Secondary block devices may use per-unit configuration data -// for e.g. interpreting partition layout. Few devices are expected -// to fall into this category. Note that these devices, as well as -// some char devices, may not actually be usable until interrupts -// are enabled. -#define CYG_INIT_DEV_BLOCK_SECONDARY 40000 -// Char devices are everything else: serial, ethernet, CAN, ... -#define CYG_INIT_DEV_CHAR 41000 -// For backwards compatibility. Subject to change in future so -// a CYG_INIT_DEV_ priority should be used instead. -#define CYG_INIT_DRIVERS 48000 -// CYG_INIT_IO and CYG_INIT_IO_FS are poorly defined at present, -// and may get reorganized in future. -#define CYG_INIT_IO 49000 -#define CYG_INIT_IO_FS 50000 -// The I/O subsystems and device drivers have been initialized. -#define CYG_INIT_LIBC 56000 -#define CYG_INIT_COMPAT 58000 -#define CYG_INIT_APPLICATION 60000 -#define CYG_INIT_PREDEFAULT 65534 -#define CYG_INIT_DEFAULT 65535 - -// ------------------------------------------------------------------------- -// Label name macros. Some toolsets generate labels with initial -// underscores and others don't. CYG_LABEL_NAME should be used on -// labels in C/C++ code that are defined in assembly code or linker -// scripts. CYG_LABEL_DEFN is for use in assembly code and linker -// scripts where we need to manufacture labels that can be used from -// C/C++. -// These are default implementations that should work for most targets. -// They may be overridden in basetype.h if necessary. - -#ifndef CYG_LABEL_NAME - -#define CYG_LABEL_NAME(_name_) _name_ - -#endif - -#ifndef CYG_LABEL_DEFN - -#define CYG_LABEL_DEFN(_label) _label - -#endif - -// ------------------------------------------------------------------------- -// COMPILER-SPECIFIC STUFF - -#ifdef __GNUC__ -// Force a 'C' routine to be called like a 'C++' contructor -# if !defined(CYGBLD_ATTRIB_CONSTRUCTOR) -# define CYGBLD_ATTRIB_CONSTRUCTOR __attribute__((constructor)) -# endif - -// Define a compiler-specific rune for saying a function doesn't return -# if !defined(CYGBLD_ATTRIB_NORET) -# define CYGBLD_ATTRIB_NORET __attribute__((noreturn)) -# endif - -// How to define weak symbols - this is only relevant for ELF and a.out, -// but that won't be a problem for eCos -# if !defined(CYGBLD_ATTRIB_WEAK) -# define CYGBLD_ATTRIB_WEAK __attribute__ ((weak)) -# endif - -// How to define alias to symbols. Just pass in the symbol itself, not -// the string name of the symbol -# if !defined(CYGBLD_ATTRIB_ALIAS) -# define CYGBLD_ATTRIB_ALIAS(__symbol__) \ - __attribute__ ((alias (#__symbol__))) -# endif - -// This effectively does the reverse of the previous macro. It defines -// a name that the attributed variable or function will actually have -// in assembler. -# if !defined(CYGBLD_ATTRIB_ASM_ALIAS) -# define __Str(x) #x -# define __Xstr(x) __Str(x) -# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) \ - __asm__ ( __Xstr( CYG_LABEL_DEFN( __symbol__ ) ) ) -# endif - -// Shows that a function returns the same value when given the same args, but -// note this can't be used if there are pointer args -# if !defined(CYGBLD_ATTRIB_CONST) -# define CYGBLD_ATTRIB_CONST __attribute__((const)) -#endif - -// Assign a defined variable to a specific section -# if !defined(CYGBLD_ATTRIB_SECTION) -# define CYGBLD_ATTRIB_SECTION(__sect__) __attribute__((section (__sect__))) -# endif - -// Give a type or object explicit minimum alignment -# if !defined(CYGBLD_ATTRIB_ALIGN) -# define CYGBLD_ATTRIB_ALIGN(__align__) __attribute__((aligned(__align__))) -# endif - -# if !defined(CYGBLD_ATTRIB_ALIGN_MAX) -# define CYGBLD_ATTRIB_ALIGN_MAX __attribute__((aligned)) -# endif - -# if !defined(CYGBLD_ATTRIB_ALIGNOFTYPE) -# define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) \ - __attribute__((aligned(__alignof__( _type_ )))) -# endif - -// Teach compiler how to check format of printf-like functions -# define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__) \ - __attribute__((format (printf, __format__, __args__))) - -// Teach compiler how to check format of scanf-like functions -# define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__) \ - __attribute__((format (scanf, __format__, __args__))) - -// Teach compiler how to check format of strftime-like functions -# define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__) \ - __attribute__((format (strftime, __format__, __args__))) - -// Tell the compiler not to throw away a variable or function. Only known -// available on 3.3.2 or above. Old version's didn't throw them away, -// but using the unused attribute should stop warnings. -# if !defined(CYGBLD_ATTRIB_USED) -# if __GNUC_VERSION__ >= 30302 -# define CYGBLD_ATTRIB_USED __attribute__((used)) -# else -# define CYGBLD_ATTRIB_USED __attribute__((unused)) -# endif -# endif -#else // non-GNU - -# define CYGBLD_ATTRIB_CONSTRUCTOR - -# define CYGBLD_ATTRIB_NORET - // This intentionally gives an error only if we actually try to - // use it. #error would give an error if we simply can't. -// FIXME: Had to disarm the bomb - the CYGBLD_ATTRIB_WEAK macro is now -// (indirectly) used in host tools. -# define CYGBLD_ATTRIB_WEAK /* !!!-- Attribute weak not defined --!!! */ - -# define CYGBLD_ATTRIB_ALIAS(__x__) !!!-- Attribute alias not defined --!!! - -# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) !!!-- Asm alias not defined --!!! - -# define CYGBLD_ATTRIB_CONST - -# define CYGBLD_ATTRIB_ALIGN(__align__) !!!-- Alignment alias not defined --!!! - -# define CYGBLD_ATTRIB_ALIGN_MAX !!!-- Alignment alias not defined --!!! - -# define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) !!!-- Alignment alias not defined --!!! - -# define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__) - -# define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__) - -# define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__) - - -#endif - -// How to define weak aliases. Currently this is simply a mixture of the -// above - -# define CYGBLD_ATTRIB_WEAK_ALIAS(__symbol__) \ - CYGBLD_ATTRIB_WEAK CYGBLD_ATTRIB_ALIAS(__symbol__) - -#ifdef __cplusplus -# define __THROW throw() -#else -# define __THROW -#endif - -// ------------------------------------------------------------------------- -// Variable annotations -// These annotations may be added to various static variables in the -// HAL and kernel to indicate which component they belong to. These -// are used by some targets to optimize memory placement of these -// variables. - -#ifndef CYGBLD_ANNOTATE_VARIABLE_HAL -#define CYGBLD_ANNOTATE_VARIABLE_HAL -#endif -#ifndef CYGBLD_ANNOTATE_VARIABLE_SCHED -#define CYGBLD_ANNOTATE_VARIABLE_SCHED -#endif -#ifndef CYGBLD_ANNOTATE_VARIABLE_CLOCK -#define CYGBLD_ANNOTATE_VARIABLE_CLOCK -#endif -#ifndef CYGBLD_ANNOTATE_VARIABLE_INTR -#define CYGBLD_ANNOTATE_VARIABLE_INTR -#endif - -// ------------------------------------------------------------------------- -// Various "flavours" of memory regions that can be described by the -// Memory Layout Tool (MLT). - -#define CYGMEM_REGION_ATTR_R 0x01 // Region can be read -#define CYGMEM_REGION_ATTR_W 0x02 // Region can be written - -#if defined (__GNUC__) -#elif defined (MSVC) -#define __inline__ __inline -#define inline __inline -#else -#endif -// ------------------------------------------------------------------------- -#endif // CYGONCE_INFRA_CYG_TYPE_H multiple inclusion protection -// EOF cyg_type.h diff --git a/components/dfs/filesystems/jffs2/dfs_jffs2.c b/components/dfs/filesystems/jffs2/dfs_jffs2.c deleted file mode 100644 index c082c21d73..0000000000 --- a/components/dfs/filesystems/jffs2/dfs_jffs2.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-1-7 prife the first version - */ - -#include -#include - -#include "cyg/infra/cyg_type.h" -#include "cyg/fileio/fileio.h" -#include "port/codes.h" -#include "port/fcntl.h" -#undef mode_t - -#include -#include - -#include "dfs_jffs2.h" -#include "jffs2_config.h" -#include "porting.h" -#include - -#if DEVICE_PART_MAX > 1 - #error "support only one jffs2 partition on a flash device!" -#endif - -/* make sure the following struct var had been initilased to 0! */ -struct device_part -{ - struct cyg_mtab_entry * mte; - struct rt_mtd_nor_device *dev; -}; -static struct device_part device_partition[DEVICE_PART_MAX] = {0}; -static struct rt_mutex jffs2_lock; - -#define jffs2_mount jffs2_fste.mount -#define jffs2_umount jffs2_fste.umount -#define jffs2_open jffs2_fste.open -#define jffs2_file_unlink jffs2_fste.unlink -#define jffs2_mkdir jffs2_fste.mkdir -#define jffs2_rmdir jffs2_fste.rmdir -#define jffs2_rename jffs2_fste.rename -#define jffs2_link jffs2_fste.link -#define jffs2_opendir jffs2_fste.opendir -#define jffs2_chdir jffs2_fste.chdir -#define jffs2_ops_stat jffs2_fste.stat -#define jffs2_getinfo jffs2_fste.getinfo -#define jffs2_setinfo jffs2_fste.setinfo - -#define jffs2_file_read jffs2_fileops.fo_read -#define jffs2_file_write jffs2_fileops.fo_write -#define jffs2_file_lseek jffs2_fileops.fo_lseek -#define jffs2_file_ioctl jffs2_fileops.fo_ioctl -#define jffs2_file_select jffs2_fileops.fo_select -#define jffs2_file_fsync jffs2_fileops.fo_fsync -#define jffs2_file_colse jffs2_fileops.fo_close -#define jffs2_file_fstat jffs2_fileops.fo_fstat -#define jffs2_file_getinfo jffs2_fileops.fo_getinfo -#define jffs2_file_setinfo jffs2_fileops.fo_setinfo - -#define jffs2_dir_read jffs2_dirops.fo_read -//#define jffs2_dir_write jffs2_dirops.fo_write -#define jffs2_dir_lseek jffs2_dirops.fo_lseek -//#define jffs2_dir_ioctl jffs2_dirops.fo_ioctl -#define jffs2_dir_select jffs2_dirops.fo_select -//#define jffs2_dir_fsync jffs2_dirops.fo_fsync -#define jffs2_dir_colse jffs2_dirops.fo_close -//#define jffs2_dir_fstat jffs2_dirops.fo_fstat -//#define jffs2_dir_getinfo jffs2_dirops.fo_getinfo -//#define jffs2_dir_setinfo jffs2_dirops.fo_setinfo - -/* - * RT-Thread Device Interface for jffs2 - */ - -/* these code is in src/flashio.c */ -static int jffs2_result_to_dfs(int result) -{ - if (result < 0) return result; - if (result > 0) return -result; - - return 0; -} - -/* - * RT-Thread DFS Interface for jffs2 - */ -static int dfs_jffs2_mount(struct dfs_filesystem* fs, - unsigned long rwflag, - const void* data) -{ - unsigned index; - struct cyg_mtab_entry * mte; - int result; - - /* find a empty entry in partition table */ - for (index = 0; index < DEVICE_PART_MAX; index ++) - { - if (device_partition[index].dev == RT_NULL) - break; - } - if (index == DEVICE_PART_MAX) - return -ENOSPC; - - mte = rt_malloc(sizeof(struct cyg_mtab_entry)); - if (mte == RT_NULL) - return -ENOMEM; - - mte->name = fs->path; - mte->fsname = "jffs2"; - mte->devname = NULL; - /* note that, i use mte->data to store rtt's device - * while, in jffs2_mount, mte->data will be copy into - * s_dev in struct super_block, and mte->data will be - * filled with jffs2_sb(see the source of jffs2_mount. - */ - mte->data = (CYG_ADDRWORD)fs->dev_id; - - device_partition[index].dev = RT_MTD_NOR_DEVICE(fs->dev_id); - /* after jffs2_mount, mte->data will not be dev_id any more */ - result = jffs2_mount(NULL, mte); - if (result != 0) - { - device_partition[index].dev = NULL; - return jffs2_result_to_dfs(result); - } - - /* save this pointer */ - device_partition[index].mte = mte; - return 0; -} - -static int _find_fs(struct cyg_mtab_entry ** mte, rt_device_t dev_id) -{ - unsigned index; - - /* find device index */ - for (index = 0; index < DEVICE_PART_MAX; index++) - { - if (device_partition[index].dev == RT_MTD_NOR_DEVICE(dev_id)) - { - *mte = device_partition[index].mte; - return 0; - } - } - - rt_kprintf("error, could not found the fs!"); - return -1; -} - -static int dfs_jffs2_unmount(struct dfs_filesystem* fs) -{ - int result; - unsigned index; - - /* find device index, then umount it */ - for (index = 0; index < DEVICE_PART_MAX; index++) - { - if (device_partition[index].dev == RT_MTD_NOR_DEVICE(fs->dev_id)) - { - result = jffs2_umount(device_partition[index].mte); - if (result) return jffs2_result_to_dfs(result); - - rt_free(device_partition[index].mte); - device_partition[index].dev = NULL; - device_partition[index].mte = NULL; - return RT_EOK; - } - } - - return -ENOENT; -} - -static int dfs_jffs2_mkfs(rt_device_t dev_id) -{ - /* just erase all blocks on this nand partition */ - return -ENOSYS; -} - -static int dfs_jffs2_statfs(struct dfs_filesystem* fs, - struct statfs *buf) -{ - /* since the limit of unsigned long, so the max size of flash device is 4G */ - struct cyg_mtab_entry * mte; - struct jffs2_fs_info info; - int result; - - result = _find_fs(&mte, fs->dev_id); - if (result) - return -ENOENT; - - RT_ASSERT(mte->data != 0); - - jffs2_get_info_from_sb((void *)mte->data, &info); - buf->f_bsize = info.sector_size; - buf->f_blocks = info.nr_blocks; - buf->f_bfree = info.free_size / info.sector_size; - - return 0; -} - -static const char jffs2_root_path[] = "."; - -static int dfs_jffs2_open(struct dfs_fd* file) -{ - int result; - int oflag, mode; - const char * name; - cyg_file * jffs2_file; - struct dfs_filesystem *fs; - struct cyg_mtab_entry * mte; - - oflag = file->flags; - fs = (struct dfs_filesystem *)file->data; - RT_ASSERT(fs != RT_NULL); - - jffs2_file = rt_malloc(sizeof(cyg_file)); - if (jffs2_file == RT_NULL) - return -ENOMEM; - - /* just escape '/' provided by dfs code */ - name = file->path; - if ((name[0] == '/') && (name[1] == 0)) - name = jffs2_root_path; - else /* name[0] still will be '/' */ - name ++; - - result = _find_fs(&mte, fs->dev_id); - if (result) - { - rt_free(jffs2_file); - return -ENOENT; - } - - /* set mount table */ - jffs2_file->f_mte = mte; - - if (oflag & O_DIRECTORY) /* operations about dir */ - { - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - if (oflag & O_CREAT) /* create a dir*/ - { - /* fixme, should test file->path can end with '/' */ - result = jffs2_mkdir(mte, mte->root, name); - if (result) - { - rt_mutex_release(&jffs2_lock); - rt_free(jffs2_file); - return jffs2_result_to_dfs(result); - } - } - - /* open dir */ - result = jffs2_opendir(mte, mte->root, name, jffs2_file); - rt_mutex_release(&jffs2_lock); - if (result) - { - rt_free(jffs2_file); - return jffs2_result_to_dfs(result); - } -#ifdef CONFIG_JFFS2_NO_RELATIVEDIR - jffs2_file->f_offset = 2; -#endif - /* save this pointer, it will be used by dfs_jffs2_getdents*/ - file->data = jffs2_file; - return 0; - } - /* regular file operations */ - mode = JFFS2_O_RDONLY; - if (oflag & O_WRONLY) mode |= JFFS2_O_WRONLY; - if (oflag & O_RDWR) mode |= JFFS2_O_RDWR; - /* Opens the file, if it is existing. If not, a new file is created. */ - if (oflag & O_CREAT) mode |= JFFS2_O_CREAT; - /* Creates a new file. If the file is existing, it is truncated and overwritten. */ - if (oflag & O_TRUNC) mode |= JFFS2_O_TRUNC; - /* Creates a new file. The function fails if the file is already existing. */ - if (oflag & O_EXCL) mode |= JFFS2_O_EXCL; - - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_open(mte, 0, name, mode, jffs2_file); - if (result != 0) - { - rt_mutex_release(&jffs2_lock); - rt_free(jffs2_file); - return jffs2_result_to_dfs(result); - } - - /* save this pointer, it will be used when calling read(), write(), - flush(), lessk(), and will be rt_free when calling close()*/ - file->data = jffs2_file; - file->pos = jffs2_file->f_offset; - file->size = 0; - jffs2_file_lseek(jffs2_file, (off_t *)(&(file->size)), SEEK_END); - jffs2_file->f_offset = (off_t)file->pos; - rt_mutex_release(&jffs2_lock); - - if (oflag & O_APPEND) - { - file->pos = file->size; - jffs2_file->f_offset = file->size; - } - - return 0; -} - -static int dfs_jffs2_close(struct dfs_fd* file) -{ - int result; - cyg_file * jffs2_file; - - RT_ASSERT(file->data != NULL); - jffs2_file = (cyg_file *)(file->data); - - if (file->flags & O_DIRECTORY) /* operations about dir */ - { - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_dir_colse(jffs2_file); - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - - rt_free(jffs2_file); - return 0; - } - /* regular file operations */ - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_file_colse(jffs2_file); - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - - /* release memory */ - rt_free(jffs2_file); - return 0; -} - -static int dfs_jffs2_ioctl(struct dfs_fd* file, int cmd, void* args) -{ - return -ENOSYS; -} - -static int dfs_jffs2_read(struct dfs_fd* file, void* buf, size_t len) -{ - cyg_file * jffs2_file; - struct CYG_UIO_TAG uio_s; - struct CYG_IOVEC_TAG iovec; - int char_read; - int result; - - RT_ASSERT(file->data != NULL); - jffs2_file = (cyg_file *)(file->data); - uio_s.uio_iov = &iovec; - uio_s.uio_iov->iov_base = buf; - uio_s.uio_iov->iov_len = len; - uio_s.uio_iovcnt = 1; //must be 1 - //uio_s.uio_offset //not used... - uio_s.uio_resid = uio_s.uio_iov->iov_len; //seem no use in jffs2; - - char_read = jffs2_file->f_offset; /* the current offset */ - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_file_read(jffs2_file, &uio_s); - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - - /* update position */ - file->pos = jffs2_file->f_offset; - char_read = jffs2_file->f_offset - char_read; - return char_read; -} - -static int dfs_jffs2_write(struct dfs_fd* file, - const void* buf, - size_t len) -{ - cyg_file * jffs2_file; - struct CYG_UIO_TAG uio_s; - struct CYG_IOVEC_TAG iovec; - int char_write; - int result; - - RT_ASSERT(file->data != NULL); - jffs2_file = (cyg_file *)(file->data); - uio_s.uio_iov = &iovec; - uio_s.uio_iov->iov_base = (void *)buf; - uio_s.uio_iov->iov_len = len; - uio_s.uio_iovcnt = 1; //must be 1 - //uio_s.uio_offset //not used... - uio_s.uio_resid = uio_s.uio_iov->iov_len; //seem no use in jffs2; - - char_write = jffs2_file->f_offset; - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_file_write(jffs2_file, &uio_s); - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - - /* update position */ - file->pos = jffs2_file->f_offset; - char_write = jffs2_file->f_offset - char_write; - return char_write; -} - -static int dfs_jffs2_flush(struct dfs_fd* file) -{ - /* infact, jffs2 not support, jffs2_fo_sync just return ok */ - return -ENOSYS; -} - -/* fixme warning: the offset is rt_off_t, so maybe the size of a file is must <= 2G*/ -static int dfs_jffs2_lseek(struct dfs_fd* file, - rt_off_t offset) -{ - cyg_file * jffs2_file; - int result; - - RT_ASSERT(file->data != NULL); - jffs2_file = (cyg_file *)(file->data); - - /* set offset as current offset */ - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_file_lseek(jffs2_file, &offset, SEEK_SET); - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - /* update file position */ - file->pos = offset; - return offset; -} - -/* return the size of struct dirent*/ -static int dfs_jffs2_getdents(struct dfs_fd* file, - struct dirent* dirp, - rt_uint32_t count) -{ - cyg_file * jffs2_file; - struct CYG_UIO_TAG uio_s; - struct CYG_IOVEC_TAG iovec; - struct jffs2_dirent jffs2_d; - struct dirent * d; - rt_uint32_t index; -#if !defined (CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE) - struct jffs2_stat s; - cyg_mtab_entry * mte; - char * fullname; -#endif - int result; - - RT_ASSERT(file->data != RT_NULL); - jffs2_file = (cyg_file*)(file->data); - mte = jffs2_file->f_mte; - - //set jffs2_d - memset(&jffs2_d, 0, sizeof(struct jffs2_dirent)); - //set CYG_UIO_TAG uio_s - uio_s.uio_iov = &iovec; - uio_s.uio_iov->iov_base = &jffs2_d; - uio_s.uio_iov->iov_len = sizeof(struct jffs2_dirent);; - uio_s.uio_iovcnt = 1; //must be 1 - uio_s.uio_offset = 0;//not used... - uio_s.uio_resid = uio_s.uio_iov->iov_len; //seem no use in jffs2; - - /* make integer count, usually count is 1 */ - count = (count / sizeof(struct dirent)) * sizeof(struct dirent); - if (count == 0) return -EINVAL; - - index = 0; - /* usually, the while loop should only be looped only once! */ - while (1) - { - d = dirp + index; - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_dir_read(jffs2_file, &uio_s); - rt_mutex_release(&jffs2_lock); - /* if met a error or all entry are read over, break while*/ - if (result || jffs2_d.d_name[0] == 0) - break; - -#if defined (CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE) - switch(jffs2_d.d_type & JFFS2_S_IFMT) - { - case JFFS2_S_IFREG: d->d_type = DT_REG; break; - case JFFS2_S_IFDIR: d->d_type = DT_DIR; break; - default: d->d_type = DT_UNKNOWN; break; - } -#else - fullname = rt_malloc(FILE_PATH_MAX); - if(fullname == RT_NULL) - return -ENOMEM; - - /* make a right entry */ - if ((file->path[0] == '/') ) - { - if (file->path[1] == 0) - strcpy(fullname, jffs2_d.d_name); - else - rt_sprintf(fullname, "%s/%s", file->path+1, jffs2_d.d_name); - } - else - rt_sprintf(fullname, "%s/%s", file->path, jffs2_d.d_name); - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_porting_stat(mte, mte->root, fullname, (void *)&s); - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - - rt_free(fullname); - /* convert to dfs stat structure */ - switch(s.st_mode & JFFS2_S_IFMT) - { - case JFFS2_S_IFREG: d->d_type = DT_REG; break; - case JFFS2_S_IFDIR: d->d_type = DT_DIR; break; - default: d->d_type = DT_UNKNOWN; break; - } -#endif - /* write the rest fields of struct dirent* dirp */ - d->d_namlen = rt_strlen(jffs2_d.d_name); - d->d_reclen = (rt_uint16_t)sizeof(struct dirent); - rt_strncpy(d->d_name, jffs2_d.d_name, d->d_namlen + 1); - - index ++; - if (index * sizeof(struct dirent) >= count) - break; - } - if (result) - return jffs2_result_to_dfs(result); - return index * sizeof(struct dirent); -} - -static int dfs_jffs2_unlink(struct dfs_filesystem* fs, const char* path) -{ - int result; - struct jffs2_stat s; - cyg_mtab_entry * mte; - - result = _find_fs(&mte, fs->dev_id); - if (result) - return -ENOENT; - - /* deal path */ - if (path[0] == '/') - path++; - - /* judge file type, dir is to be delete by rmdir, others by unlink */ - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_porting_stat(mte, mte->root, path, (void *)&s); - if (result) - { - rt_mutex_release(&jffs2_lock); - return jffs2_result_to_dfs(result); - } - - switch(s.st_mode & JFFS2_S_IFMT) - { - case JFFS2_S_IFREG: - result = jffs2_file_unlink(mte, mte->root, path); - break; - case JFFS2_S_IFDIR: - result = jffs2_rmdir(mte, mte->root, path); - break; - default: - /* unknown file type */ - rt_mutex_release(&jffs2_lock); - return -1; - } - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - return 0; -} - -static int dfs_jffs2_rename(struct dfs_filesystem* fs, - const char* oldpath, - const char* newpath) -{ - int result; - cyg_mtab_entry * mte; - - result = _find_fs(&mte, fs->dev_id); - if (result) - return -ENOENT; - - if (*oldpath == '/') - oldpath += 1; - if (*newpath == '/') - newpath += 1; - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_rename(mte, mte->root, oldpath, mte->root, newpath); - rt_mutex_release(&jffs2_lock); - if (result) - return jffs2_result_to_dfs(result); - return 0; -} - -static int dfs_jffs2_stat(struct dfs_filesystem* fs, const char *path, struct stat *st) -{ - int result; - struct jffs2_stat s; - cyg_mtab_entry * mte; - - /* deal the path for jffs2 */ - RT_ASSERT(!((path[0] == '/') && (path[1] == 0))); - - if (path[0] == '/') - path++; - - result = _find_fs(&mte, fs->dev_id); - if (result) - return -ENOENT; - - rt_mutex_take(&jffs2_lock, RT_WAITING_FOREVER); - result = jffs2_porting_stat(mte, mte->root, path, (void *)&s); - rt_mutex_release(&jffs2_lock); - - if (result) - return jffs2_result_to_dfs(result); - /* convert to dfs stat structure */ - switch(s.st_mode & JFFS2_S_IFMT) - { - case JFFS2_S_IFREG: - st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP | S_IWOTH; - break; - - case JFFS2_S_IFDIR: - st->st_mode = S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; - break; - - default: - st->st_mode = DT_UNKNOWN; //fixme - break; - } - - st->st_dev = 0; - st->st_size = s.st_size; - st->st_mtime = s.st_mtime; - - return 0; -} - -static const struct dfs_file_ops _jffs2_fops = -{ - dfs_jffs2_open, - dfs_jffs2_close, - dfs_jffs2_ioctl, - dfs_jffs2_read, - dfs_jffs2_write, - dfs_jffs2_flush, - dfs_jffs2_lseek, - dfs_jffs2_getdents, -}; - -static const struct dfs_filesystem_ops _jffs2_ops = -{ - "jffs2", - DFS_FS_FLAG_DEFAULT, - &_jffs2_fops, - - dfs_jffs2_mount, - dfs_jffs2_unmount, - dfs_jffs2_mkfs, - dfs_jffs2_statfs, - - dfs_jffs2_unlink, - dfs_jffs2_stat, - dfs_jffs2_rename, -}; - -int dfs_jffs2_init(void) -{ - /* register fatfs file system */ - dfs_register(&_jffs2_ops); - - /* initialize mutex */ - if (rt_mutex_init(&jffs2_lock, "jffs2lock", RT_IPC_FLAG_FIFO) != RT_EOK) - { - rt_kprintf("init jffs2 lock mutex failed\n"); - } - rt_kprintf("init jffs2 lock mutex okay\n"); - return 0; -} -INIT_COMPONENT_EXPORT(dfs_jffs2_init); diff --git a/components/dfs/filesystems/jffs2/dfs_jffs2.h b/components/dfs/filesystems/jffs2/dfs_jffs2.h deleted file mode 100644 index 1be403a19c..0000000000 --- a/components/dfs/filesystems/jffs2/dfs_jffs2.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#ifndef __DFS_JFFS2_H__ -#define __DFS_JFFS2_H__ - -int dfs_jffs2_init(void); - -#endif diff --git a/components/dfs/filesystems/jffs2/include/linux/jffs2.h b/components/dfs/filesystems/jffs2/include/linux/jffs2.h deleted file mode 100644 index ab034effe6..0000000000 --- a/components/dfs/filesystems/jffs2/include/linux/jffs2.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in the - * jffs2 directory. - * - * $Id: jffs2.h,v 1.36 2005/07/26 13:19:36 havasi Exp $ - * - */ - -#ifndef __LINUX_JFFS2_H__ -#define __LINUX_JFFS2_H__ - -/* You must include something which defines the C99 uintXX_t types. - We don't do it from here because this file is used in too many - different environments. */ - -#define JFFS2_SUPER_MAGIC 0x72b6 - -/* Values we may expect to find in the 'magic' field */ -#define JFFS2_OLD_MAGIC_BITMASK 0x1984 -#define JFFS2_MAGIC_BITMASK 0x1985 -#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */ -#define JFFS2_EMPTY_BITMASK 0xffff -#define JFFS2_DIRTY_BITMASK 0x0000 - -/* We only allow a single char for length, and 0xFF is empty flash so - we don't want it confused with a real length. Hence max 254. -*/ -#define JFFS2_MAX_NAME_LEN 254 - -/* How small can we sensibly write nodes? */ -#define JFFS2_MIN_DATA_LEN 128 - -#define JFFS2_COMPR_NONE 0x00 -#define JFFS2_COMPR_ZERO 0x01 -#define JFFS2_COMPR_RTIME 0x02 -#define JFFS2_COMPR_RUBINMIPS 0x03 -#define JFFS2_COMPR_COPY 0x04 -#define JFFS2_COMPR_DYNRUBIN 0x05 -#define JFFS2_COMPR_ZLIB 0x06 -/* Compatibility flags. */ -#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ -#define JFFS2_NODE_ACCURATE 0x2000 -/* INCOMPAT: Fail to mount the filesystem */ -#define JFFS2_FEATURE_INCOMPAT 0xc000 -/* ROCOMPAT: Mount read-only */ -#define JFFS2_FEATURE_ROCOMPAT 0x8000 -/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */ -#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000 -/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */ -#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000 - -#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1) -#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2) -#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) -#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) - -// Maybe later... -//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) -//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) - - -#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at - mount time, don't wait for it to - happen later */ -#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific - compression type */ - - -/* These can go once we've made sure we've caught all uses without - byteswapping */ -#include - -#if defined(__GNUC__) || (__CC_ARM) -typedef struct { - uint32_t v32; -} __attribute__((packed)) jint32_t; - -typedef struct { - uint32_t m; -} __attribute__((packed)) jmode_t; - -typedef struct { - uint16_t v16; -} __attribute__((packed)) jint16_t; - -struct jffs2_unknown_node -{ - /* All start like this */ - jint16_t magic; - jint16_t nodetype; - jint32_t totlen; /* So we can skip over nodes we don't grok */ - jint32_t hdr_crc; -} __attribute__((packed)); - -struct jffs2_raw_dirent -{ - jint16_t magic; - jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ - jint32_t totlen; - jint32_t hdr_crc; - jint32_t pino; - jint32_t version; - jint32_t ino; /* == zero for unlink */ - jint32_t mctime; - uint8_t nsize; - uint8_t type; - uint8_t unused[2]; - jint32_t node_crc; - jint32_t name_crc; - uint8_t name[0]; -} __attribute__((packed)); - -/* The JFFS2 raw inode structure: Used for storage on physical media. */ -/* The uid, gid, atime, mtime and ctime members could be longer, but - are left like this for space efficiency. If and when people decide - they really need them extended, it's simple enough to add support for - a new type of raw node. -*/ -struct jffs2_raw_inode -{ - jint16_t magic; /* A constant magic number. */ - jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ - jint32_t totlen; /* Total length of this node (inc data, etc.) */ - jint32_t hdr_crc; - jint32_t ino; /* Inode number. */ - jint32_t version; /* Version number. */ - jmode_t mode; /* The file's type or mode. */ - jint16_t uid; /* The file's owner. */ - jint16_t gid; /* The file's group. */ - jint32_t isize; /* Total resultant size of this inode (used for truncations) */ - jint32_t atime; /* Last access time. */ - jint32_t mtime; /* Last modification time. */ - jint32_t ctime; /* Change time. */ - jint32_t offset; /* Where to begin to write. */ - jint32_t csize; /* (Compressed) data size */ - jint32_t dsize; /* Size of the node's data. (after decompression) */ - uint8_t compr; /* Compression algorithm used */ - uint8_t usercompr; /* Compression algorithm requested by the user */ - jint16_t flags; /* See JFFS2_INO_FLAG_* */ - jint32_t data_crc; /* CRC for the (compressed) data. */ - jint32_t node_crc; /* CRC for the raw inode (excluding data) */ - uint8_t data[0]; -} __attribute__((packed)); - -#elif defined (MSVC) -typedef uint32_t jint32_t; -//typedef uint32_t jmode_t; -typedef struct { - uint32_t m; -} jmode_t; -typedef uint16_t jint16_t; - -#pragma pack(1) -struct jffs2_unknown_node -{ - /* All start like this */ - jint16_t magic; - jint16_t nodetype; - jint32_t totlen; /* So we can skip over nodes we don't grok */ - jint32_t hdr_crc; -}; - -struct jffs2_raw_dirent -{ - jint16_t magic; - jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ - jint32_t totlen; - jint32_t hdr_crc; - jint32_t pino; - jint32_t version; - jint32_t ino; /* == zero for unlink */ - jint32_t mctime; - uint8_t nsize; - uint8_t type; - uint8_t unused[2]; - jint32_t node_crc; - jint32_t name_crc; - uint8_t name[0]; -}; - -/* The JFFS2 raw inode structure: Used for storage on physical media. */ -/* The uid, gid, atime, mtime and ctime members could be longer, but - are left like this for space efficiency. If and when people decide - they really need them extended, it's simple enough to add support for - a new type of raw node. -*/ -struct jffs2_raw_inode -{ - jint16_t magic; /* A constant magic number. */ - jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ - jint32_t totlen; /* Total length of this node (inc data, etc.) */ - jint32_t hdr_crc; - jint32_t ino; /* Inode number. */ - jint32_t version; /* Version number. */ - jmode_t mode; /* The file's type or mode. */ - jint16_t uid; /* The file's owner. */ - jint16_t gid; /* The file's group. */ - jint32_t isize; /* Total resultant size of this inode (used for truncations) */ - jint32_t atime; /* Last access time. */ - jint32_t mtime; /* Last modification time. */ - jint32_t ctime; /* Change time. */ - jint32_t offset; /* Where to begin to write. */ - jint32_t csize; /* (Compressed) data size */ - jint32_t dsize; /* Size of the node's data. (after decompression) */ - uint8_t compr; /* Compression algorithm used */ - uint8_t usercompr; /* Compression algorithm requested by the user */ - jint16_t flags; /* See JFFS2_INO_FLAG_* */ - jint32_t data_crc; /* CRC for the (compressed) data. */ - jint32_t node_crc; /* CRC for the raw inode (excluding data) */ - uint8_t data[0]; -}; -#pragma pack() -#else -#endif - - -union jffs2_node_union { - struct jffs2_raw_inode i; - struct jffs2_raw_dirent d; - struct jffs2_unknown_node u; -}; - -#endif /* __LINUX_JFFS2_H__ */ diff --git a/components/dfs/filesystems/jffs2/include/linux/jffs2_fs_i.h b/components/dfs/filesystems/jffs2/include/linux/jffs2_fs_i.h deleted file mode 100644 index 7f30282653..0000000000 --- a/components/dfs/filesystems/jffs2/include/linux/jffs2_fs_i.h +++ /dev/null @@ -1,50 +0,0 @@ -/* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ - -#ifndef _JFFS2_FS_I -#define _JFFS2_FS_I - -#include -#include -#include - -struct jffs2_inode_info { - /* We need an internal semaphore similar to inode->i_sem. - Unfortunately, we can't used the existing one, because - either the GC would deadlock, or we'd have to release it - before letting GC proceed. Or we'd have to put ugliness - into the GC code so it didn't attempt to obtain the i_sem - for the inode(s) which are already locked */ - struct semaphore sem; - - /* The highest (datanode) version number used for this ino */ - uint32_t highest_version; - - /* List of data fragments which make up the file */ - struct rb_root fragtree; - - /* There may be one datanode which isn't referenced by any of the - above fragments, if it contains a metadata update but no actual - data - or if this is a directory inode */ - /* This also holds the _only_ dnode for symlinks/device nodes, - etc. */ - struct jffs2_full_dnode *metadata; - - /* Directory entries */ - struct jffs2_full_dirent *dents; - - /* The target path if this is the inode of a symlink */ - unsigned char *target; - - /* Some stuff we just have to keep in-core at all times, for each inode. */ - struct jffs2_inode_cache *inocache; - - uint16_t flags; - uint8_t usercompr; -#if !defined (__ECOS) && !defined(RT_THREAD) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) - struct inode vfs_inode; -#endif -#endif -}; - -#endif /* _JFFS2_FS_I */ diff --git a/components/dfs/filesystems/jffs2/include/linux/jffs2_fs_sb.h b/components/dfs/filesystems/jffs2/include/linux/jffs2_fs_sb.h deleted file mode 100644 index 066e9400bc..0000000000 --- a/components/dfs/filesystems/jffs2/include/linux/jffs2_fs_sb.h +++ /dev/null @@ -1,120 +0,0 @@ -/* $Id: jffs2_fs_sb.h,v 1.52 2005/05/19 16:12:17 gleixner Exp $ */ - -#ifndef _JFFS2_FS_SB -#define _JFFS2_FS_SB - -#include "jffs2_config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define JFFS2_SB_FLAG_RO 1 -#define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */ -#define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */ - -struct jffs2_inodirty; - -/* A struct for the overall file system control. Pointers to - jffs2_sb_info structs are named `c' in the source code. - Nee jffs_control -*/ -struct jffs2_sb_info { - struct mtd_info *mtd; - - uint32_t highest_ino; - uint32_t checked_ino; - - unsigned int flags; - - struct task_struct *gc_task; /* GC task struct */ - struct completion gc_thread_start; /* GC thread start completion */ - struct completion gc_thread_exit; /* GC thread exit completion port */ - - struct semaphore alloc_sem; /* Used to protect all the following - fields, and also to protect against - out-of-order writing of nodes. And GC. */ - uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER - (i.e. zero for OOB CLEANMARKER */ - - uint32_t flash_size; - uint32_t used_size; - uint32_t dirty_size; - uint32_t wasted_size; - uint32_t free_size; - uint32_t erasing_size; - uint32_t bad_size; - uint32_t sector_size; - uint32_t unchecked_size; - - uint32_t nr_free_blocks; - uint32_t nr_erasing_blocks; - - /* Number of free blocks there must be before we... */ - uint8_t resv_blocks_write; /* ... allow a normal filesystem write */ - uint8_t resv_blocks_deletion; /* ... allow a normal filesystem deletion */ - uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */ - uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */ - uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */ - - uint32_t nospc_dirty_size; - - uint32_t nr_blocks; - struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks - * from the offset (blocks[ofs / sector_size]) */ - struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ - - struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */ - - struct list_head clean_list; /* Blocks 100% full of clean data */ - struct list_head very_dirty_list; /* Blocks with lots of dirty space */ - struct list_head dirty_list; /* Blocks with some dirty space */ - struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ - struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ - struct list_head erasing_list; /* Blocks which are currently erasing */ - struct list_head erase_pending_list; /* Blocks which need erasing now */ - struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */ - struct list_head free_list; /* Blocks which are free and ready to be used */ - struct list_head bad_list; /* Bad blocks. */ - struct list_head bad_used_list; /* Bad blocks with valid data in. */ - - spinlock_t erase_completion_lock; /* Protect free_list and erasing_list - against erase completion handler */ - wait_queue_head_t erase_wait; /* For waiting for erases to complete */ - - wait_queue_head_t inocache_wq; - struct jffs2_inode_cache **inocache_list; - spinlock_t inocache_lock; - - /* Sem to allow jffs2_garbage_collect_deletion_dirent to - drop the erase_completion_lock while it's holding a pointer - to an obsoleted node. I don't like this. Alternatives welcomed. */ - struct semaphore erase_free_sem; - -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER - /* Write-behind buffer for NAND flash */ - unsigned char *wbuf; - uint32_t wbuf_ofs; - uint32_t wbuf_len; - uint32_t wbuf_pagesize; - struct jffs2_inodirty *wbuf_inodes; - - struct rw_semaphore wbuf_sem; /* Protects the write buffer */ - - /* Information about out-of-band area usage... */ - struct nand_oobinfo *oobinfo; - uint32_t badblock_pos; - uint32_t fsdata_pos; - uint32_t fsdata_len; -#endif - - /* OS-private pointer for getting back to master superblock info */ - void *os_priv; -}; - -#endif /* _JFFS2_FB_SB */ diff --git a/components/dfs/filesystems/jffs2/include/port/codes.h b/components/dfs/filesystems/jffs2/include/port/codes.h deleted file mode 100644 index 2426465c84..0000000000 --- a/components/dfs/filesystems/jffs2/include/port/codes.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef CYGONCE_ERROR_CODES_H -#define CYGONCE_ERROR_CODES_H -/*=========================================================================== -// -// codes.h -// -// Common error code definitions -// -//=========================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//=========================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): jlarmour -// Contributors: jlarmour -// Date: 2000-04-14 -// Purpose: To provide a common set of error codes -// Description: This provides a common set of error codes that all -// packages can agree on. It doesn't preclude them defining -// their own error return system, but this is a preferable -// system to use to help error support be as general as -// possible. -// -// We try and conform to the ANSI/POSIX error code format, -// namely starting with the character 'E' -// -// Usage: #include -// -// Example: -// -// err=myfun(); -// if (err != ENOERR) -// { -// str=strerror(err); -// printf("myfun returned error: %s\n", str); -// } -// else .... -// -//####DESCRIPTIONEND#### -// -//=========================================================================*/ - -/* CONFIGURATION */ - -//#include prife // Configuration header - -#ifdef __cplusplus -extern "C" { -#endif - -/* TYPE DEFINITIONS */ - -/* A type for error codes which may be useful to explain the purpose of - * a variable or return code. It shows that it contains an error code - * of the type defined below */ - -typedef int Cyg_ErrNo; - -#include - -#define ENOERR RT_EOK - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* CYGONCE_ERROR_CODES_H multiple inclusion protection */ - -/* EOF codes.h */ diff --git a/components/dfs/filesystems/jffs2/include/port/fcntl.h b/components/dfs/filesystems/jffs2/include/port/fcntl.h deleted file mode 100644 index fcc3088fc7..0000000000 --- a/components/dfs/filesystems/jffs2/include/port/fcntl.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CYGONCE_ISO_FCNTL_H -#define CYGONCE_ISO_FCNTL_H - -/*------------------------------------------------------------------------*/ -/* for dfs_jffs2.c */ -/*------------------------------------------------------------------------*/ -/* File access modes used for open() and fnctl() */ -#define JFFS2_O_RDONLY (O_RDONLY) /* Open for reading only */ -#define JFFS2_O_WRONLY (O_WRONLY) /* Open for writing only */ -#define JFFS2_O_RDWR (O_RDONLY|O_WRONLY) /* Open for reading and writing */ - -/* File access mode mask */ -#define JFFS2_O_ACCMODE (O_RDONLY|O_RDWR|O_WRONLY) - -/* open() mode flags */ - -#define JFFS2_O_CREAT (O_CREAT) /* Create file it it does not exist */ -#define JFFS2_O_EXCL (O_EXCL) /* Exclusive use */ -#define JFFS2_O_NOCTTY (O_NOCTTY) /* Do not assign a controlling terminal */ -#define JFFS2_O_TRUNC (O_TRUNC) /* Truncate */ - -/* File status flags used for open() and fcntl() */ -#define JFFS2_O_APPEND (O_APPEND) /* Set append mode */ -#define JFFS2_O_DSYNC (O_DSYNC) /* Synchronized I/O data integrity writes */ -#define JFFS2_O_NONBLOCK (O_NONBLOCK)/* No delay */ -#define JFFS2_O_RSYNC (O_RSYNC) /* Synchronized read I/O */ -#define JFFS2_O_SYNC (O_SYNC) /* Synchronized I/O file integrity writes */ - -#endif - -/* EOF fcntl.h */ diff --git a/components/dfs/filesystems/jffs2/include/port/sys/stat.h b/components/dfs/filesystems/jffs2/include/port/sys/stat.h deleted file mode 100644 index 43958a752f..0000000000 --- a/components/dfs/filesystems/jffs2/include/port/sys/stat.h +++ /dev/null @@ -1,294 +0,0 @@ -#ifndef CYGONCE_ISO_SYS_TYPES_H -#define CYGONCE_ISO_SYS_TYPES_H -/*======================================================================== -// -// sys/types.h -// -// POSIX types -// -//======================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//======================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): jlarmour -// Contributors: -// Date: 2000-04-14 -// Purpose: This file provides various types required by POSIX 1003.1. -// Description: The real contents of this file get set from the -// configuration (set by the implementation) -// Usage: #include -// -//####DESCRIPTIONEND#### -// -//====================================================================== -*/ - -/* CONFIGURATION */ - -//#include -//#include /* Configuration header */ - -/* INCLUDES */ - -/* This is the "standard" way to get size_t from stddef.h, - * which is the canonical location of the definition. - */ -//#define __need_size_t -//#include -#include "port/codes.h" - -/* -#ifndef dev_t -typedef short dev_t; -#endif - -#ifndef ino_t -typedef unsigned int ino_t; -#endif - -#ifndef mode_t -typedef unsigned int mode_t; -#endif -*/ - -typedef unsigned short nlink_t; -typedef long off_t; - -typedef unsigned short gid_t; -typedef unsigned short uid_t; -typedef int pid_t; - -// -typedef void *cyg_io_handle_t; - -/* Variable names for pathconf() */ -#define _PC_ASYNC_IO 1 -#define _PC_CHOWN_RESTRICTED 2 -#define _PC_LINK_MAX 3 -#define _PC_MAX_CANON 4 -#define _PC_MAX_INPUT 5 -#define _PC_NAME_MAX 6 -#define _PC_NO_TRUNC 7 -#define _PC_PATH_MAX 8 -#define _PC_PIPE_BUF 9 -#define _PC_PRIO_IO 10 -#define _PC_SYNC_IO 11 -#define _PC_VDISABLE 12 - -//limit.h -/* DEFINES */ - -/*----------------------------------------------------------------------------- - * Minimum values from POSIX.1 tables 2-3, 2-7 and 2-7a. - - * These are the standard-mandated minimum values. - * These values do not vary with the implementation - they may - * simply be defined - */ - -/* Minimum number of operations in one list I/O call. */ -#define _POSIX_AIO_LISTIO_MAX 2 - -/* Minimal number of outstanding asynchronous I/O operations. */ -#define _POSIX_AIO_MAX 1 - -/* Maximum length of arguments to `execve', including environment. */ -#define _POSIX_ARG_MAX 4096 - -/* Maximum simultaneous processes per real user ID. */ -#define _POSIX_CHILD_MAX 6 - -/* Minimal number of timer expiration overruns. */ -#define _POSIX_DELAYTIMER_MAX 32 - -/* Maximum link count of a file. */ -#define _POSIX_LINK_MAX 8 - -/* Size of storage required for a login name */ -#define _POSIX_LOGIN_NAME_MAX 9 - -/* Number of bytes in a terminal canonical input queue. */ -#define _POSIX_MAX_CANON 255 - -/* Number of bytes for which space will be - available in a terminal input queue. */ -#define _POSIX_MAX_INPUT 255 - -/* Maximum number of message queues open for a process. */ -#define _POSIX_MQ_OPEN_MAX 8 - -/* Maximum number of supported message priorities. */ -#define _POSIX_MQ_PRIO_MAX 32 - -/* Number of bytes in a filename. */ -#define _POSIX_NAME_MAX 14 - -/* Number of simultaneous supplementary group IDs per process. */ -#define _POSIX_NGROUPS_MAX 0 - -/* Number of files one process can have open at once. */ -#define _POSIX_OPEN_MAX 16 - -/* Number of bytes in a pathname. */ -#define _POSIX_PATH_MAX 255 - -/* Number of bytes than can be written atomically to a pipe. */ -#define _POSIX_PIPE_BUF 512 - -/* Minimal number of realtime signals reserved for the application. */ -#define _POSIX_RTSIG_MAX 8 - -/* Number of semaphores a process can have. */ -#define _POSIX_SEM_NSEMS_MAX 256 - -/* Maximal value of a semaphore. */ -#define _POSIX_SEM_VALUE_MAX 32767 - -/* Number of pending realtime signals. */ -#define _POSIX_SIGQUEUE_MAX 32 - -/* Largest value of a `ssize_t'. */ -#define _POSIX_SSIZE_MAX 32767 - -/* Number of streams a process can have open at once. */ -#define _POSIX_STREAM_MAX 8 - -/* Controlling the iterations of destructors for thread-specific data. */ -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 - -/* The number of data keys per process. */ -#define _POSIX_THREAD_KEYS_MAX 128 - -/* The number of threads per process. */ -#define _POSIX_THREAD_THREADS_MAX 64 - -/* Maximum number of characters in a tty name. */ -#define _POSIX_TTY_NAME_MAX 9 - -/* Number of timer for a process. */ -#define _POSIX_TIMER_MAX 32 - -/* Maximum length of a timezone name (element of `tzname'). */ -#define _POSIX_TZNAME_MAX 3 - -/* Maximum clock resolution in nanoseconds. */ -#define _POSIX_CLOCKRES_MIN 20000000 - - -#ifdef CYGBLD_ISO_SSIZET_HEADER -# include CYGBLD_ISO_SSIZET_HEADER -#else -# ifndef __STRICT_ANSI__ -# define SSIZE_MAX LONG_MAX -# endif -#endif - -/* INCLUDES */ - -#ifdef CYGBLD_ISO_OPEN_MAX_HEADER -# include CYGBLD_ISO_OPEN_MAX_HEADER -#else -# ifndef __STRICT_ANSI__ -# define OPEN_MAX _POSIX_OPEN_MAX -# endif -#endif - -#ifdef CYGBLD_ISO_LINK_MAX_HEADER -# include CYGBLD_ISO_LINK_MAX_HEADER -#else -# ifndef __STRICT_ANSI__ -# define LINK_MAX _POSIX_LINK_MAX -# endif -#endif - -#ifdef CYGBLD_ISO_NAME_MAX_HEADER -# include CYGBLD_ISO_NAME_MAX_HEADER -#else -# ifndef __STRICT_ANSI__ -# define NAME_MAX _POSIX_NAME_MAX -# endif -#endif - -#ifdef CYGBLD_ISO_PATH_MAX_HEADER -# include CYGBLD_ISO_PATH_MAX_HEADER -#else -# ifndef __STRICT_ANSI__ -# define PATH_MAX _POSIX_PATH_MAX -# endif -#endif - -#if CYGINT_ISO_POSIX_LIMITS -# ifdef CYGBLD_ISO_POSIX_LIMITS_HEADER -# include CYGBLD_ISO_POSIX_LIMITS_HEADER -# endif -#endif - - -#define CYGNUM_FILEIO_MTAB_MAX 16 - -//----------------------------------------------- -// stat.h need by fs-ecos.h -//----------------------------------------------- -#define __stat_mode_DIR (1<<0) -#define __stat_mode_CHR (1<<1) -#define __stat_mode_BLK (1<<2) -#define __stat_mode_REG (1<<3) -#define __stat_mode_FIFO (1<<4) -#define __stat_mode_MQ (1<<5) -#define __stat_mode_SEM (1<<6) -#define __stat_mode_SHM (1<<7) -#define __stat_mode_LNK (1<<8) -#define __stat_mode_SOCK (1<<9) - -#if defined(MSVC) -/* for time_t */ -#include -typedef unsigned long mode_t; -typedef unsigned int ino_t; -typedef unsigned int dev_t; -typedef long ssize_t; -#elif defined(__CC_ARM) -#define mode_t unsigned long -typedef unsigned int ino_t; -typedef unsigned int dev_t; -typedef long ssize_t; -typedef long time_t; -#elif defined(__GNUC__) && !defined(__CC_ARM) -#include -#endif - -#endif /* CYGONCE_ISO_SYS_TYPES_H multiple inclusion protection */ - -/* EOF sys/types.h */ - diff --git a/components/dfs/filesystems/jffs2/include/port/sys/types.h b/components/dfs/filesystems/jffs2/include/port/sys/types.h deleted file mode 100644 index ab195a57ea..0000000000 --- a/components/dfs/filesystems/jffs2/include/port/sys/types.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef CYGONCE_ISO_SYS_TYPES_H -#define CYGONCE_ISO_SYS_TYPES_H -/*======================================================================== -// -// sys/types.h -// -// POSIX types -// -//======================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//======================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): jlarmour -// Contributors: -// Date: 2000-04-14 -// Purpose: This file provides various types required by POSIX 1003.1. -// Description: The real contents of this file get set from the -// configuration (set by the implementation) -// Usage: #include -// -//####DESCRIPTIONEND#### -// -//====================================================================== -*/ - -/* CONFIGURATION */ - -//#include -//#include /* Configuration header */ - -/* INCLUDES */ - -/* This is the "standard" way to get size_t from stddef.h, - * which is the canonical location of the definition. - */ -//#define __need_size_t -//#include - -typedef long ssize_t; - -typedef short dev_t; -typedef unsigned int ino_t; -typedef unsigned short nlink_t; -typedef long off_t; - -typedef unsigned short gid_t; -typedef unsigned short uid_t; -typedef int pid_t; - -#if defined(MSVC) -#include -#else -typedef int time_t; -#endif -//#include "os_sys_stat.h" -#endif /* CYGONCE_ISO_SYS_TYPES_H multiple inclusion protection */ - -/* EOF sys/types.h */ - diff --git a/components/dfs/filesystems/jffs2/jffs2_config.h b/components/dfs/filesystems/jffs2/jffs2_config.h deleted file mode 100644 index 3340f1ff17..0000000000 --- a/components/dfs/filesystems/jffs2/jffs2_config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef JFFS2_CONFIG_H -#define JFFS2_CONFIG_H - -#define __ECOS /* must be defined */ - -#define FILE_PATH_MAX 128 /* the longest file path */ -#define CONFIG_JFFS2_ENTRY_NAME_MAX 23 -#define JFFS2_NAME_MAX CONFIG_JFFS2_ENTRY_NAME_MAX -#define JFFS2_PATH_MAX FILE_PATH_MAX - -#define DEVICE_PART_MAX 1 /* the max partions on a nand deivce*/ - -/* memory page size in kernel/asm/page.h, it is correspond with flash read/write - * option, so this size has a great impact on reading/writing speed */ -#define CONFIG_JFFS2_PAGE_SHIFT 12 /* (1<<12) 4096bytes*/ - -/* jffs2 support relative dir, command "ls" will get - * +-------------------------------+ - * | finsh>>ls("/") | - * | Directory /: | - * | . | - * | .. | - * | dir1 | - * +-------------------------------+ - */ -#define CONFIG_JFFS2_NO_RELATIVEDIR - -//#define CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE -#if defined(CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE) - #define CYGPKG_FILEIO_DIRENT_DTYPE -#endif - -#define CYGOPT_FS_JFFS2_WRITE /* if not defined, jffs2 is read only*/ - -/* jffs2 debug output opion */ -#define CONFIG_JFFS2_FS_DEBUG 0 /* 1 or 2 */ - -/* jffs2 gc thread section */ -//#define CYGOPT_FS_JFFS2_GCTHREAD -#define CYGNUM_JFFS2_GC_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX-2) /* GC thread's priority */ -#define CYGNUM_JFFS2_GS_THREAD_TICKS 20 /* event timeout ticks */ -#define CYGNUM_JFFS2_GC_THREAD_TICKS 20 /* GC thread's running ticks */ - -//#define CONFIG_JFFS2_FS_WRITEBUFFER /* should not be enabled */ - -/* zlib section*/ -//#define CONFIG_JFFS2_ZLIB -//#define CONFIG_JFFS2_RTIME -//#define CONFIG_JFFS2_RUBIN -//#define CONFIG_JFFS2_CMODE_NONE -//#define CONFIG_JFFS2_CMODE_SIZE - -#endif diff --git a/components/dfs/filesystems/jffs2/kernel/asm/atomic.h b/components/dfs/filesystems/jffs2/kernel/asm/atomic.h deleted file mode 100644 index 5cb72ff8ce..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/asm/atomic.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __ASM_ATOMIC_H__ -#define __ASM_ATOMIC_H__ - -#define atomic_t int -#define atomic_inc(atom) (*atom)++ -#define atomic_dec(atom) (*atom)-- -#define atomic_read(atom) (*atom) - - -#endif /* __ASM_ATOMIC_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/asm/bug.h b/components/dfs/filesystems/jffs2/kernel/asm/bug.h deleted file mode 100644 index 054dedc3d3..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/asm/bug.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_BUG_H__ -#define __ASM_BUG_H__ - -#define BUG() do { printf("BUG() at %s %d\n", __FILE__, __LINE__); *(int *)0=0; } while (0) - -#endif /* __ASM_BUG_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/asm/page.h b/components/dfs/filesystems/jffs2/kernel/asm/page.h deleted file mode 100644 index af3081164f..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/asm/page.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __ASM_PAGE_H__ -#define __ASM_PAGE_H__ - -//#include //mod by prife -#include "jffs2_config.h" -#define PAGE_SHIFT CONFIG_JFFS2_PAGE_SHIFT -/* These aren't used by much yet. If that changes, you might want - to make them actually correct :) */ -#define PAGE_SIZE (0x1 << PAGE_SHIFT) - - -#endif /* __ASM_PAGE_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/asm/semaphore.h b/components/dfs/filesystems/jffs2/kernel/asm/semaphore.h deleted file mode 100644 index 94a4f3abd9..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/asm/semaphore.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef __ASM_SEMAPHORE_H__ -#define __ASM_SEMAPHORE_H__ - -#define CONFIG_JFFS2_SEMAPHORE 0 // no mutex, 1 use static, 2 use dynamic -#if CONFIG_JFFS2_SEMAPHORE == 0 -//#include - -struct semaphore { - int x; -}; - -#define DECLARE_MUTEX(x) -#define DECLARE_MUTEX_LOCKED(x) - -#define init_MUTEX(sem) -#define init_MUTEX_LOCKED(sem) -#define down(sem) -#define down_interruptible(sem) 0 -#define down_trylock(sem) -#define up(sem) - -#elif CONFIG_JFFS2_SEMAPHORE == 1 -#include - -struct semaphore { - struct rt_mutex mutex; -}; - -#define DECLARE_MUTEX(x) -#define DECLARE_MUTEX_LOCKED(x) -rt_inline void init_MUTEX(struct semaphore * sem) -{ - if (rt_mutex_init((rt_mutex_t)sem, "mutex", RT_IPC_FLAG_FIFO) == RT_EOK) - { - /* detach the object from system object container */ - rt_object_detach(&(((rt_mutex_t)sem)->parent.parent)); - return; - } - rt_kprintf("get an error at %s:%d \n", __FUNCTION__, __LINE__); - RT_ASSERT(0); -} - -rt_inline void init_MUTEX_LOCKED(struct semaphore * sem) -{ - rt_enter_critical(); - if (rt_mutex_init((rt_mutex_t)sem, "mutex", RT_IPC_FLAG_FIFO) == RT_EOK) - { - /* detach the object from system object container */ - rt_object_detach(&(((rt_mutex_t)sem)->parent.parent)); - rt_exit_critical(); - rt_mutex_take((rt_mutex_t)sem, RT_WAITING_FOREVER); - return; - } - rt_exit_critical(); - - rt_kprintf("get an error at %s:%d \n", __FUNCTION__, __LINE__); - RT_ASSERT(0); -} - -rt_inline down(struct semaphore * sem) -{ - rt_mutex_take((rt_mutex_t)sem, RT_WAITING_FOREVER); -} -rt_inline int down_interruptible(struct semaphore* sem) -{ - rt_mutex_take((rt_mutex_t)sem, RT_WAITING_FOREVER); - return 0; -} -rt_inline up(struct semaphore * sem) -{ - rt_mutex_release((rt_mutex_t)sem); -} -#elif CONFIG_JFFS2_SEMAPHORE == 2 - -#include - -struct semaphore { - rt_mutex_t mutex; -}; - -#define DECLARE_MUTEX(x) -#define DECLARE_MUTEX_LOCKED(x) - -rt_inline void init_MUTEX(struct semaphore * sem) -{ - sem->mutex = rt_mutex_create("mutex", RT_IPC_FLAG_FIFO); -} -rt_inline init_MUTEX_LOCKED(struct semaphore * sem) -{ - sem->mutex = rt_mutex_create("mutex", RT_IPC_FLAG_FIFO); - rt_mutex_take(sem->mutex, RT_WAITING_FOREVER); -} -rt_inline down(struct semaphore * sem) -{ - rt_mutex_take(sem->mutex, RT_WAITING_FOREVER); -} -rt_inline int down_interruptible(struct semaphore* sem) -{ - rt_mutex_take(sem->mutex, RT_WAITING_FOREVER); - return 0; -} -/* -Attempt to lock the mutex pointed to by the mutex argument without waiting. -If the mutex is already locked by some other thread then this function -returns FALSE. If the function can lock the mutex without waiting, then -TRUE is returned. -void cyg_drv_mutex_unlock( cyg_drv_mutex *mutex ) -*/ - -//#define down_trylock(struct semaphore * sem) rt_mutex_take((rt_mutex_t)sem, RT_WAITING_NO) -rt_inline up(struct semaphore * sem) -{ - rt_mutex_release(sem->mutex); -} - -#else -#error "CONFIG_JFFS2_SEMAPHORE should be 0, 1 or 2" -#endif - -#endif /* __ASM_SEMAPHORE_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/TODO b/components/dfs/filesystems/jffs2/kernel/linux/TODO deleted file mode 100644 index df8a6d1a51..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/TODO +++ /dev/null @@ -1,11 +0,0 @@ - -This contains a very limited set of Linux-compatibility headers, initially -just for getting JFFS2 to build. - -Some things are simply stubs which don't _work_, to allow the JFFS2 code -to compile. Note that you may need to implement these _properly_ in order -to use these for making other Linux code work, or indeed for making the -JFFS2 NAND support work. - -The non-working parts include, but are not limited to: - workqueue.h, wait.h, timer.h, spinlock.h, sched.h, compiler.h diff --git a/components/dfs/filesystems/jffs2/kernel/linux/compiler.h b/components/dfs/filesystems/jffs2/kernel/linux/compiler.h deleted file mode 100644 index fb253651a3..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/compiler.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __LINUX_COMPILER_H__ -#define __LINUX_COMPILER_H__ - -#define likely(x) (x) -#define unlikely(x) (x) - -#endif /* __LINUX_COMPILER_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/completion.h b/components/dfs/filesystems/jffs2/kernel/linux/completion.h deleted file mode 100644 index d2493b2710..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/completion.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __LINUX_COMPLETION_H__ -#define __LINUX_COMPLETION_H__ - -#if defined (__GNUC__) -struct completion { } ; -#elif defined (MSVC) -struct completion {int no; } ; -#else -#error "please use a right C compiler" -#endif - -#endif /* __LINUX_COMPLETION_H__ */ - diff --git a/components/dfs/filesystems/jffs2/kernel/linux/config.h b/components/dfs/filesystems/jffs2/kernel/linux/config.h deleted file mode 100644 index 355e175f65..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/config.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __LINUX_CONFIG_H__ -#define __LINUX_CONFIG_H__ - -#define GFP_KERNEL 0 - -/* #define CONFIG_JFFS2_FS_WRITEBUFFER 0 */ -/* #define CONFIG_JFFS2_PROC */ -/* #define CONFIG_JFFS2_RTIME */ -/* #define CONFIG_JFFS2_RUBIN */ -/* #define CONFIG_JFFS2_ZLIB */ - -#endif /* __LINUX_CONFIG_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/crc32.h b/components/dfs/filesystems/jffs2/kernel/linux/crc32.h deleted file mode 100644 index 8d19a1eb62..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/crc32.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CRC32_H -#define CRC32_H - -#include - -#define crc32(val, s, len) cyg_crc32_accumulate(val, (unsigned char *)s, len) - -#endif diff --git a/components/dfs/filesystems/jffs2/kernel/linux/errno.h b/components/dfs/filesystems/jffs2/kernel/linux/errno.h deleted file mode 100644 index 2938632411..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/errno.h +++ /dev/null @@ -1,2 +0,0 @@ -//#include -#include "port/codes.h" //fixme diff --git a/components/dfs/filesystems/jffs2/kernel/linux/fs.h b/components/dfs/filesystems/jffs2/kernel/linux/fs.h deleted file mode 100644 index 94f493c91a..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/fs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __LINUX_FS_H__ -#define __LINUX_FS_H__ - -#include - -#endif /* __LINUX_FS_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/init.h b/components/dfs/filesystems/jffs2/kernel/linux/init.h deleted file mode 100644 index e4c702f996..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/init.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef __LINUX_INIT_H__ -#define __LINUX_INIT_H__ -#endif diff --git a/components/dfs/filesystems/jffs2/kernel/linux/kernel.h b/components/dfs/filesystems/jffs2/kernel/linux/kernel.h deleted file mode 100644 index a0c94a1996..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/kernel.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __LINUX_KERNEL_H__ -#define __LINUX_KERNEL_H__ -//#include -//#include //mod by prife @ 2011/11/20 -#include "jffs2_config.h" - -#define jiffies 100 - -#define ERR_PTR(err) ((void*)(err)) -#define PTR_ERR(err) ((unsigned long)(err)) -#define IS_ERR(err) ((unsigned long)err > (unsigned long)-1000L) - -#define CURRENT_TIME jffs2_get_timestamp() - -#define KERN_EMERG "<0>" // system is unusable -#define KERN_ALERT "<1>" // action must be taken immediately -#define KERN_CRIT "<2>" // critical conditions -#define KERN_ERR "<3>" // error conditions -#define KERN_WARNING "<4>" // warning conditions -#define KERN_NOTICE "<5>" // normal but significant condition -#define KERN_INFO "<6>" // informational -#define KERN_DEBUG "<7>" // debug-level messages -#define printk rt_kprintf//diag_printf //mod by prife - -#ifndef min //mod by prife -#define min(x,y) (x - * - *=========================================================================== - * ####ECOSGPLCOPYRIGHTBEGIN#### - * ------------------------------------------- - * This file is part of eCos, the Embedded Configurable Operating System. - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. - * - * eCos is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 or (at your option) any later - * version. - * - * eCos is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with eCos; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * As a special exception, if other files instantiate templates or use - * macros or inline functions from this file, or you compile this file - * and link it with other works to produce a work based on this file, - * this file does not by itself cause the resulting work to be covered by - * the GNU General Public License. However the source code for this file - * must still be made available in accordance with section (3) of the GNU - * General Public License v2. - * - * This exception does not invalidate any other reasons why a work based - * on this file might be covered by the GNU General Public License. - * ------------------------------------------- - * ####ECOSGPLCOPYRIGHTEND#### - *=========================================================================== - * - */ - -#ifndef CYGONCE_FS_JFFS2_LIST_H -#define CYGONCE_FS_JFFS2_LIST_H - - -/* -----------------------------------------------------------------------*/ - -/* Doubly linked list implementation to replace the GPL'd one used in - the Linux kernel. */ - -#include -#include - -/* TYPES */ - -struct list_head { - struct list_head *next; - struct list_head *prev; -}; - -/* MACROS */ - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD( _list_ ) \ -CYG_MACRO_START \ -(_list_)->next = (_list_)->prev = (_list_); \ -CYG_MACRO_END - -/* FUNCTIONS */ - -/* Insert an entry _after_ the specified entry */ -static __inline__ void -list_add( struct list_head *newent, struct list_head *afterthisent ) -{ - struct list_head *next = afterthisent->next; - newent->next = next; - newent->prev = afterthisent; - afterthisent->next = newent; - next->prev = newent; -} /* list_add() */ - -/* Insert an entry _before_ the specified entry */ -static __inline__ void -list_add_tail( struct list_head *newent, struct list_head *beforethisent ) -{ - struct list_head *prev = beforethisent->prev; - newent->prev = prev; - newent->next = beforethisent; - beforethisent->prev = newent; - prev->next = newent; -} /* list_add_tail() */ - -/* Delete the specified entry */ -static __inline__ void -list_del( struct list_head *ent ) -{ - ent->prev->next = ent->next; - ent->next->prev = ent->prev; -} /* list_del() */ - -/* Is this list empty? */ -static __inline__ int -list_empty( struct list_head *list ) -{ - return ( list->next == list ); -} /* list_empty() */ - -/* list_entry - Assuming you have a struct of type _type_ that contains a - list which has the name _member_ in that struct type, then given the - address of that list in the struct, _list_, this returns the address - of the container structure */ - -#define list_entry( _list_, _type_, _member_ ) \ - ((_type_ *)((char *)(_list_)-(char *)(offsetof(_type_,_member_)))) - -/* list_for_each - using _ent_, iterate through list _list_ */ - -#define list_for_each( _ent_, _list_ ) \ - for ( (_ent_) = (_list_)->next; \ - (_ent_) != (_list_); \ - (_ent_) = (_ent_)->next ) - -/* - * list_for_each_entry - this function can be use to iterate over all - * items in a list* _list_ with it's head at _head_ and link _item_ - */ -#if defined (__GNUC__) -#define list_for_each_entry(_list_, _head_, _item_) \ -for ((_list_) = list_entry((_head_)->next, typeof(*_list_), _item_); \ - &((_list_)->_item_) != (_head_); \ - (_list_) = list_entry((_list_)->_item_.next, typeof(*_list_), _item_)) - -#elif defined (MSVC) -#define list_for_each_entry(_list_, _head_, _item_) \ -for ((_list_) = list_entry((_head_)->next, struct jffs2_compressor, _item_); \ - &((_list_)->_item_) != (_head_); \ - (_list_) = list_entry((_list_)->_item_.next, struct jffs2_compressor, _item_)) -#else -#endif -/* -----------------------------------------------------------------------*/ -#endif /* #ifndef CYGONCE_FS_JFFS2_LIST_H */ -/* EOF list.h */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/mtd/compatmac.h b/components/dfs/filesystems/jffs2/kernel/linux/mtd/compatmac.h deleted file mode 100644 index cee3749250..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/mtd/compatmac.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __LINUX_MTD_COMPATMAC_H__ -#define __LINUX_MTD_COMPATMAC_H__ - - -#endif /* __LINUX_MTD_COMPATMAC_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/mtd/mtd.h b/components/dfs/filesystems/jffs2/kernel/linux/mtd/mtd.h deleted file mode 100644 index 817d31cf6f..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/mtd/mtd.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __LINUX_MTD_MTD_H__ -#define __LINUX_MTD_MTD_H__ - - -#endif /* __LINUX_MTD_MTD_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/pagemap.h b/components/dfs/filesystems/jffs2/kernel/linux/pagemap.h deleted file mode 100644 index fccf9c4061..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/pagemap.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __LINUX_PAGEMAP_H__ -#define __LINUX_PAGEMAP_H__ - -#include -#include - -#define PAGE_CACHE_SHIFT PAGE_SHIFT -#define PAGE_CACHE_SIZE PAGE_SIZE - -#define PageLocked(pg) 1 -#define Page_Uptodate(pg) 0 -#define UnlockPage(pg) -#define PAGE_BUG(pg) BUG() -#define ClearPageUptodate(pg) -#define SetPageError(pg) -#define ClearPageError(pg) -#define SetPageUptodate(pg) - -#endif /* __LINUX_PAGEMAP_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/rbtree.h b/components/dfs/filesystems/jffs2/kernel/linux/rbtree.h deleted file mode 100644 index ffda277e88..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/rbtree.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _LINUX_RBTREE_H -#define _LINUX_RBTREE_H - -#if defined (__GNUC__) -#elif defined (MSVC) -#define __inline__ __inline -#define inline __inline -#else -#endif - -struct rb_node { - struct rb_node *rb_left; /* left element */ - struct rb_node *rb_right; /* right element */ - struct rb_node *rb_parent; /* parent element */ - int rb_color; /* node color */ -}; - -struct rb_root { - struct rb_node *rb_node; /* root of the tree */ -}; - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#if defined (__GNUC__) -#define RB_ROOT ((struct rb_root){NULL}) -#elif defined (MSVC) -#define RB_ROOT {NULL}//{struct rb_root _x = {NULL};} -#else -#endif - -#define rb_entry(p, container, field) \ - ((container *) ((char *)p - ((char *)&(((container *)0)->field)))) - -#define RB_BLACK 0 -#define RB_RED 1 - - -extern void rb_insert_color(struct rb_node *, struct rb_root *); -extern void rb_erase(struct rb_node *, struct rb_root *); - -/* Find logical next and previous nodes in a tree */ -extern struct rb_node *rb_next(struct rb_node *); -extern struct rb_node *rb_prev(struct rb_node *); -extern struct rb_node *rb_first(struct rb_root *); - -/* Fast replacement of a single node without remove/rebalance/add/rebalance */ -extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root); - -static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, - struct rb_node ** rb_link) -{ - node->rb_parent = parent; - node->rb_color = RB_RED; - node->rb_left = node->rb_right = NULL; - - *rb_link = node; -} - -#endif /* _LINUX_RBTREE_H */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/rwsem.h b/components/dfs/filesystems/jffs2/kernel/linux/rwsem.h deleted file mode 100644 index d648a150ca..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/rwsem.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __LINUX_RWSEM_H__ -#define __LINUX_RWSEM_H__ - -// eCos does not have the concept of a read/write semaphore. So just -// map them onto normal semaphores and hope we don't deadlock -// somewhere. - -#include - -struct rw_semaphore; - -#define down_read(sem) cyg_drv_mutex_lock((cyg_drv_mutex_t *)sem) -#define down_read_trylock(sem) cyg_drv_mutex_trylock((cyg_drv_mutex_t *)sem) -#define down_write(sem) cyg_drv_mutex_lock((cyg_drv_mutex_t *)sem) -#define down_write_trylock(sem) cyg_drv_mutex_trylock((cyg_drv_mutex_t *)sem) -#define up_read(sem) cyg_drv_mutex_unlock((cyg_drv_mutex_t *)sem) -#define up_write(sem) cyg_drv_mutex_unlock((cyg_drv_mutex_t *)sem) -#define downgrade_write(sem) - -#endif // __LINUX_RWSEM_H__ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/sched.h b/components/dfs/filesystems/jffs2/kernel/linux/sched.h deleted file mode 100644 index 14a7359754..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/sched.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __LINUX_SCHED_H__ -#define __LINUX_SCHED_H__ - -#define cond_resched() do { } while(0) -#define signal_pending(x) (0) - -#endif /* __LINUX_SCHED_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/slab.h b/components/dfs/filesystems/jffs2/kernel/linux/slab.h deleted file mode 100644 index f5c5745b0e..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/slab.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __LINUX_SLAB_H__ -#define __LINUX_SLAB_H__ - -//#include //prife - -#include /* Don't ask. Linux headers are a mess. */ - -#define kmalloc(x, y) rt_malloc(x) -#define kfree(x) rt_free(x) -#define vmalloc(x) rt_malloc(x) -#define vfree(x) rt_free(x) - -#endif /* __LINUX_SLAB_H__ */ - diff --git a/components/dfs/filesystems/jffs2/kernel/linux/spinlock.h b/components/dfs/filesystems/jffs2/kernel/linux/spinlock.h deleted file mode 100644 index db3f4d4502..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/spinlock.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef __LINUX_SPINLOCK_H__ -#define __LINUX_SPINLOCK_H__ - -#if defined (__GNUC__) -typedef struct { } spinlock_t; - -#define SPIN_LOCK_UNLOCKED (spinlock_t) { } -#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED -#elif defined (MSVC) -typedef struct {int no; } spinlock_t; - -#define SPIN_LOCK_UNLOCKED (spinlock_t) ( 0) -#define DEFINE_SPINLOCK(x) spinlock_t x -#else -#error "please use a right C compiler" -#endif - -#define spin_lock_init(lock) \ -CYG_MACRO_START; \ -CYG_UNUSED_PARAM(spinlock_t *, lock); \ -CYG_MACRO_END - -#define spin_lock(lock) \ -CYG_MACRO_START; \ -CYG_UNUSED_PARAM(spinlock_t *, lock); \ -CYG_MACRO_END - -#define spin_unlock(lock) \ -CYG_MACRO_START; \ -CYG_UNUSED_PARAM(spinlock_t *, lock); \ -CYG_MACRO_END - -#define spin_lock_bh(lock) \ -CYG_MACRO_START; \ -CYG_UNUSED_PARAM(spinlock_t *, lock); \ -CYG_MACRO_END - -#define spin_unlock_bh(lock) \ -CYG_MACRO_START; \ -CYG_UNUSED_PARAM(spinlock_t *, lock); \ -CYG_MACRO_END - -#endif /* __LINUX_SPINLOCK_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/stat.h b/components/dfs/filesystems/jffs2/kernel/linux/stat.h deleted file mode 100644 index 8c79205229..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/stat.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __LINUX_STAT_H__ -#define __LINUX_STAT_H__ - - -#include "port/sys/stat.h" //mod by prife - -#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) -#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) -#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) -#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) - -#endif /* __LINUX_STAT_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/string.h b/components/dfs/filesystems/jffs2/kernel/linux/string.h deleted file mode 100644 index fc14ba607f..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/string.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __LINUX_STRING_H__ -#define __LINUX_STRING_H__ - -#include - -#endif /* __LINUX_STRING_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/timer.h b/components/dfs/filesystems/jffs2/kernel/linux/timer.h deleted file mode 100644 index d6f91a68bc..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/timer.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __LINUX_TIMER_H__ -#define __LINUX_TIMER_H__ - -/* Not yet */ - -#if defined (__GNUC__) -struct timer_list { } ; -#elif defined (MSVC) -struct timer_list {int no; } ; -#else -#error "please use a right C compiler" -#endif - -#endif /* __LINUX_TIMER_H__ */ - diff --git a/components/dfs/filesystems/jffs2/kernel/linux/types.h b/components/dfs/filesystems/jffs2/kernel/linux/types.h deleted file mode 100644 index bfa09c14c0..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/types.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __LINUX_TYPES_H__ -#define __LINUX_TYPES_H__ - -#include "cyg/infra/cyg_type.h" - -#define loff_t off_t - -#define kvec iovec -#endif /* __LINUX_TYPES_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/version.h b/components/dfs/filesystems/jffs2/kernel/linux/version.h deleted file mode 100644 index cd3a45aa38..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/version.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __LINUX_VERSION_H__ -#define __LINUX_VERSION_H__ - -#include - -#endif /* __LINUX_VERSION_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/vmalloc.h b/components/dfs/filesystems/jffs2/kernel/linux/vmalloc.h deleted file mode 100644 index 6f18ab2255..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/vmalloc.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef __LINUX_VMALLOC_H__ -#define __LINUX_VMALLOC_H__ -#endif diff --git a/components/dfs/filesystems/jffs2/kernel/linux/wait.h b/components/dfs/filesystems/jffs2/kernel/linux/wait.h deleted file mode 100644 index db3fd7a608..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/wait.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __LINUX_WAIT_H__ -#define __LINUX_WAIT_H__ - - -#if defined (__GNUC__) -typedef struct { } wait_queue_head_t; -#elif defined (MSVC) -typedef struct {int no; } wait_queue_head_t; -#else -#error "please use a right C compiler" -#endif - -#define init_waitqueue_head(wait) do{} while (0) -#define add_wait_queue(wait,new_wait) do{} while (0) -#define remove_wait_queue(wait,old_wait) do{} while (0) -#define DECLARE_WAITQUEUE(wait,current) do{} while (0) - -static inline void wake_up(wait_queue_head_t *erase_wait) -{ /* Only used for waking up threads blocks on erases. Not used in eCos */ } - -#endif /* __LINUX_WAIT_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/workqueue.h b/components/dfs/filesystems/jffs2/kernel/linux/workqueue.h deleted file mode 100644 index 8b334d5593..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/workqueue.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __LINUX_WORKQUEUE_H__ -#define __LINUX_WORKQUEUE_H__ - -/* We don't do this yet */ -#if defined (__GNUC__) -struct work_struct { } ; -#elif defined (MSVC) -struct work_struct {int no; } ; -#else -#error "please use a right C compiler" -#endif - - -#define INIT_WORK(x,y,z) /* */ -#define schedule_work(x) do { } while(0) -#define flush_scheduled_work() do { } while(0) - -#endif /* __LINUX_WORKQUEUE_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/zlib.h b/components/dfs/filesystems/jffs2/kernel/linux/zlib.h deleted file mode 100644 index 4c32b68c9c..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/zlib.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __LINUX_ZLIB_H__ -#define __LINUX_ZLIB_H__ - -#include - -#define zlib_deflateInit(x,y) deflateInit(x,y) -#define zlib_deflate(x,y) deflate(x,y) -#define zlib_deflateEnd(x) deflateEnd(x) -#define zlib_inflateInit(x) inflateInit(x) -#define zlib_inflateInit2(x,y) inflateInit2(x,y) -#define zlib_inflate(x,y) inflate(x,y) -#define zlib_inflateEnd(x) inflateEnd(x) - - -#endif /* __LINUX_ZLIB_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/linux/zutil.h b/components/dfs/filesystems/jffs2/kernel/linux/zutil.h deleted file mode 100644 index c3774baf9e..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/linux/zutil.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __LINUX_ZUTIL_H__ -#define __LINUX_ZUTIL_H__ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - -#endif /* __LINUX_ZUTIL_H__ */ diff --git a/components/dfs/filesystems/jffs2/kernel/rbtree.c b/components/dfs/filesystems/jffs2/kernel/rbtree.c deleted file mode 100644 index 5bc1cc53e2..0000000000 --- a/components/dfs/filesystems/jffs2/kernel/rbtree.c +++ /dev/null @@ -1,408 +0,0 @@ -/*======================================================================== -// -// rbtree.c -// -// Red Black tree implementation -// -//======================================================================== -// ####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -// -// eCos is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 2 or (at your option) any later -// version. -// -// eCos is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License -// along with eCos; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// As a special exception, if other files instantiate templates or use -// macros or inline functions from this file, or you compile this file -// and link it with other works to produce a work based on this file, -// this file does not by itself cause the resulting work to be covered by -// the GNU General Public License. However the source code for this file -// must still be made available in accordance with section (3) of the GNU -// General Public License v2. -// -// This exception does not invalidate any other reasons why a work based -// on this file might be covered by the GNU General Public License. -// ------------------------------------------- -// ####ECOSGPLCOPYRIGHTEND#### -//======================================================================== -//#####DESCRIPTIONBEGIN#### -// -// Author(s): Niels Provos/OpenBSD -// Contributors: dwmw2 -// Date: 2003-01-21 -// Purpose: This file provides an implementation of red-black trees. -// Description: Derived from OpenBSD src/sys/sys/tree.h -// Usage: -// -//####DESCRIPTIONEND#### -// -//====================================================================== -*/ - -/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ -/* - * Copyright 2002 Niels Provos - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Fields renamed to match Linux ones. */ -#include - - -#define RB_HEAD(head) (head)->rb_node -#define RB_LEFT(elm) (elm)->rb_left -#define RB_RIGHT(elm) (elm)->rb_right -#define RB_PARENT(elm) (elm)->rb_parent -#define RB_COLOR(elm) (elm)->rb_color - - -#define RB_SET(elm, parent) do { \ - RB_PARENT(elm) = parent; \ - RB_LEFT(elm) = RB_RIGHT(elm) = NULL; \ - RB_COLOR(elm) = RB_RED; \ -} while (0) - -#define RB_SET_BLACKRED(black, red) do { \ - RB_COLOR(black) = RB_BLACK; \ - RB_COLOR(red) = RB_RED; \ -} while (0) - -#ifndef RB_AUGMENT -#define RB_AUGMENT(x) -#endif - -#define RB_ROTATE_LEFT(head, elm, tmp) do { \ - (tmp) = RB_RIGHT(elm); \ - if ((RB_RIGHT(elm) = RB_LEFT(tmp))) { \ - RB_PARENT(RB_LEFT(tmp)) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp) = RB_PARENT(elm))) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm))) \ - RB_LEFT(RB_PARENT(elm)) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm)) = (tmp); \ - } else \ - (head)->rb_node = (tmp); \ - RB_LEFT(tmp) = (elm); \ - RB_PARENT(elm) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp))) \ - RB_AUGMENT(RB_PARENT(tmp)); \ -} while (0) - -#define RB_ROTATE_RIGHT(head, elm, tmp) do { \ - (tmp) = RB_LEFT(elm); \ - if ((RB_LEFT(elm) = RB_RIGHT(tmp))) { \ - RB_PARENT(RB_RIGHT(tmp)) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp) = RB_PARENT(elm))) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm))) \ - RB_LEFT(RB_PARENT(elm)) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm)) = (tmp); \ - } else \ - (head)->rb_node = (tmp); \ - RB_RIGHT(tmp) = (elm); \ - RB_PARENT(elm) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp))) \ - RB_AUGMENT(RB_PARENT(tmp)); \ -} while(0) - -/* Note args swapped to match Linux */ -void rb_insert_color(struct rb_node *elm, struct rb_root *head) -{ - struct rb_node *parent, *gparent, *tmp; - while ((parent = RB_PARENT(elm)) && - RB_COLOR(parent) == RB_RED) { - gparent = RB_PARENT(parent); - if (parent == RB_LEFT(gparent)) { - tmp = RB_RIGHT(gparent); - if (tmp && RB_COLOR(tmp) == RB_RED) { - RB_COLOR(tmp) = RB_BLACK; - RB_SET_BLACKRED(parent, gparent); - elm = gparent; - continue; - } - if (RB_RIGHT(parent) == elm) { - RB_ROTATE_LEFT(head, parent, tmp); - tmp = parent; - parent = elm; - elm = tmp; - } - RB_SET_BLACKRED(parent, gparent); - RB_ROTATE_RIGHT(head, gparent, tmp); - } else { - tmp = RB_LEFT(gparent); - if (tmp && RB_COLOR(tmp) == RB_RED) { - RB_COLOR(tmp) = RB_BLACK; - RB_SET_BLACKRED(parent, gparent); - elm = gparent; - continue; - } - if (RB_LEFT(parent) == elm) { - RB_ROTATE_RIGHT(head, parent, tmp); - tmp = parent; - parent = elm; - elm = tmp; - } - RB_SET_BLACKRED(parent, gparent); - RB_ROTATE_LEFT(head, gparent, tmp); - } - } - RB_COLOR(head->rb_node) = RB_BLACK; -} - - -static void rb_remove_color(struct rb_root *head, struct rb_node *parent, - struct rb_node *elm) -{ - struct rb_node *tmp; - while ((elm == NULL || RB_COLOR(elm) == RB_BLACK) && - elm != RB_HEAD(head)) { - if (RB_LEFT(parent) == elm) { - tmp = RB_RIGHT(parent); - if (RB_COLOR(tmp) == RB_RED) { - RB_SET_BLACKRED(tmp, parent); - RB_ROTATE_LEFT(head, parent, tmp); - tmp = RB_RIGHT(parent); - } - if ((RB_LEFT(tmp) == NULL || - RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) && - (RB_RIGHT(tmp) == NULL || - RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) { - RB_COLOR(tmp) = RB_RED; - elm = parent; - parent = RB_PARENT(elm); - } else { - if (RB_RIGHT(tmp) == NULL || - RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK) { - struct rb_node *oleft; - if ((oleft = RB_LEFT(tmp))) - RB_COLOR(oleft) = RB_BLACK; - RB_COLOR(tmp) = RB_RED; - RB_ROTATE_RIGHT(head, tmp, oleft); - tmp = RB_RIGHT(parent); - } - RB_COLOR(tmp) = RB_COLOR(parent); - RB_COLOR(parent) = RB_BLACK; - if (RB_RIGHT(tmp)) - RB_COLOR(RB_RIGHT(tmp)) = RB_BLACK; - RB_ROTATE_LEFT(head, parent, tmp); - elm = RB_HEAD(head); - break; - } - } else { - tmp = RB_LEFT(parent); - if (RB_COLOR(tmp) == RB_RED) { - RB_SET_BLACKRED(tmp, parent); - RB_ROTATE_RIGHT(head, parent, tmp); - tmp = RB_LEFT(parent); - } - if ((RB_LEFT(tmp) == NULL || - RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) && - (RB_RIGHT(tmp) == NULL || - RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) { - RB_COLOR(tmp) = RB_RED; - elm = parent; - parent = RB_PARENT(elm); - } else { - if (RB_LEFT(tmp) == NULL || - RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) { - struct rb_node *oright; - if ((oright = RB_RIGHT(tmp))) - RB_COLOR(oright) = RB_BLACK; - RB_COLOR(tmp) = RB_RED; - RB_ROTATE_LEFT(head, tmp, oright); - tmp = RB_LEFT(parent); - } - RB_COLOR(tmp) = RB_COLOR(parent); - RB_COLOR(parent) = RB_BLACK; - if (RB_LEFT(tmp)) - RB_COLOR(RB_LEFT(tmp)) = RB_BLACK; - RB_ROTATE_RIGHT(head, parent, tmp); - elm = RB_HEAD(head); - break; - } - } - } - if (elm) - RB_COLOR(elm) = RB_BLACK; -} - -/* Note name changed. Guess why :) */ -void rb_erase(struct rb_node *elm, struct rb_root *head) -{ - struct rb_node *child, *parent, *old = elm; - int color; - if (RB_LEFT(elm) == NULL) - child = RB_RIGHT(elm); - else if (RB_RIGHT(elm) == NULL) - child = RB_LEFT(elm); - else { - struct rb_node *left; - elm = RB_RIGHT(elm); - while ((left = RB_LEFT(elm))) - elm = left; - child = RB_RIGHT(elm); - parent = RB_PARENT(elm); - color = RB_COLOR(elm); - if (child) - RB_PARENT(child) = parent; - if (parent) { - if (RB_LEFT(parent) == elm) - RB_LEFT(parent) = child; - else - RB_RIGHT(parent) = child; - RB_AUGMENT(parent); - } else - RB_HEAD(head) = child; - if (RB_PARENT(elm) == old) - parent = elm; - *(elm) = *(old); - if (RB_PARENT(old)) { - if (RB_LEFT(RB_PARENT(old)) == old) - RB_LEFT(RB_PARENT(old)) = elm; - else - RB_RIGHT(RB_PARENT(old)) = elm; - RB_AUGMENT(RB_PARENT(old)); - } else - RB_HEAD(head) = elm; - RB_PARENT(RB_LEFT(old)) = elm; - if (RB_RIGHT(old)) - RB_PARENT(RB_RIGHT(old)) = elm; - if (parent) { - left = parent; - do { - RB_AUGMENT(left); - } while ((left = RB_PARENT(left))); - } - goto color; - } - parent = RB_PARENT(elm); - color = RB_COLOR(elm); - if (child) - RB_PARENT(child) = parent; - if (parent) { - if (RB_LEFT(parent) == elm) - RB_LEFT(parent) = child; - else - RB_RIGHT(parent) = child; - RB_AUGMENT(parent); - } else - RB_HEAD(head) = child; -color: - if (color == RB_BLACK) - rb_remove_color(head, parent, child); -} - -struct rb_node *rb_next(struct rb_node *elm) -{ - if (RB_RIGHT(elm)) { - elm = RB_RIGHT(elm); - while (RB_LEFT(elm)) - elm = RB_LEFT(elm); - } else { - if (RB_PARENT(elm) && - (elm == RB_LEFT(RB_PARENT(elm)))) - elm = RB_PARENT(elm); - else { - while (RB_PARENT(elm) && - (elm == RB_RIGHT(RB_PARENT(elm)))) - elm = RB_PARENT(elm); - elm = RB_PARENT(elm); - } - } - return (elm); -} - -struct rb_node *rb_prev(struct rb_node *elm) -{ - if (RB_LEFT(elm)) { - elm = RB_LEFT(elm); - while (RB_RIGHT(elm)) - elm = RB_RIGHT(elm); - } else { - if (RB_PARENT(elm) && - (elm == RB_RIGHT(RB_PARENT(elm)))) - elm = RB_PARENT(elm); - else { - while (RB_PARENT(elm) && - (elm == RB_LEFT(RB_PARENT(elm)))) - elm = RB_PARENT(elm); - elm = RB_PARENT(elm); - } - } - return (elm); -} - -/* These ones are lifted from Linux -- but that's OK because I - wrote them. dwmw2. */ -struct rb_node *rb_first(struct rb_root *root) -{ - struct rb_node *n; - - n = root->rb_node; - if (!n) - return 0; - while (n->rb_left) - n = n->rb_left; - return n; -} - -void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root) -{ - struct rb_node *parent = victim->rb_parent; - - /* Set the surrounding nodes to point to the replacement */ - if (parent) { - if (victim == parent->rb_left) - parent->rb_left = new; - else - parent->rb_right = new; - } else { - root->rb_node = new; - } - if (victim->rb_left) - victim->rb_left->rb_parent = new; - if (victim->rb_right) - victim->rb_right->rb_parent = new; - - /* Copy the pointers/colour from the victim to the replacement */ - *new = *victim; -} diff --git a/components/dfs/filesystems/jffs2/porting.c b/components/dfs/filesystems/jffs2/porting.c deleted file mode 100644 index 81290bdc32..0000000000 --- a/components/dfs/filesystems/jffs2/porting.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include "nodelist.h" - -#include "porting.h" - -time_t jffs2_get_timestamp(void) -{ - return 0; -} - -void jffs2_get_info_from_sb(void * data, struct jffs2_fs_info * info) -{ - struct jffs2_fs_info; - struct super_block *jffs2_sb; - struct jffs2_sb_info *c; - - jffs2_sb = (struct super_block *)(data); - c = JFFS2_SB_INFO(jffs2_sb); - - info->sector_size = c->sector_size; - info->nr_blocks = c->nr_blocks; - info->free_size = c->free_size + c->dirty_size; //fixme need test! -} - -int jffs2_porting_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - void * stat_buf) -{ - return jffs2_fste.stat(mte, mte->root, name, (struct stat *)stat_buf); -} diff --git a/components/dfs/filesystems/jffs2/porting.h b/components/dfs/filesystems/jffs2/porting.h deleted file mode 100644 index 2671f46dde..0000000000 --- a/components/dfs/filesystems/jffs2/porting.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _PORTING_H -#define _PORTING_H - -#include "jffs2_config.h" -/* the following should be same with os_sys_stat.h */ -#define JFFS2_S_IFMT 0x000003FF -#define JFFS2_S_IFDIR (1<<0) -#define JFFS2_S_IFREG (1<<3) - -struct jffs2_fs_info -{ - unsigned sector_size; /* a erasing block size*/ - unsigned nr_blocks; /* number of blocks in flash */ - unsigned free_size; -}; - -struct jffs2_stat { - unsigned long st_mode; /* File mode */ - unsigned int st_ino; /* File serial number */ - unsigned int st_dev; /* ID of device containing file */ - unsigned short st_nlink; /* Number of hard links */ - unsigned short st_uid; /* User ID of the file owner */ - unsigned short st_gid; /* Group ID of the file's group */ - long st_size; /* File size (regular files only) */ - long st_atime; /* Last access time */ - long st_mtime; /* Last data modification time */ - long st_ctime; /* Last file status change time */ -}; - -struct jffs2_dirent -{ -#ifdef CYGPKG_FILEIO_DIRENT_DTYPE - - unsigned long d_type; // Only supported with FATFS, RAMFS, ROMFS, - // and JFFS2. - // d_type is not part of POSIX so - // should be used with caution. -#endif - char d_name[JFFS2_NAME_MAX+1]; -}; - -extern cyg_fileops jffs2_fileops; -extern cyg_fileops jffs2_dirops; -extern struct cyg_fstab_entry jffs2_fste; - -time_t jffs2_get_timestamp(void); -void jffs2_get_info_from_sb(void * data, struct jffs2_fs_info * info); -int jffs2_porting_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - void * stat_buf); - -#endif diff --git a/components/dfs/filesystems/jffs2/src/LICENCE b/components/dfs/filesystems/jffs2/src/LICENCE deleted file mode 100644 index f3f9a6f6ec..0000000000 --- a/components/dfs/filesystems/jffs2/src/LICENCE +++ /dev/null @@ -1,35 +0,0 @@ -The files in this directory and elsewhere which refer to this LICENCE -file are part of JFFS2, the Journalling Flash File System v2. - - Copyright (C) 2001-2003 Red Hat, Inc. - -JFFS2 is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 or (at your option) any later -version. - -JFFS2 is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License along -with JFFS2; if not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - -As a special exception, if other files instantiate templates or use -macros or inline functions from these files, or you compile these -files and link them with other works to produce a work based on these -files, these files do not by themselves cause the resulting work to be -covered by the GNU General Public License. However the source code for -these files must still be made available in accordance with section (3) -of the GNU General Public License. - -This exception does not invalidate any other reasons why a work based on -this file might be covered by the GNU General Public License. - -For information on obtaining alternative licences for JFFS2, see -http://sources.redhat.com/jffs2/jffs2-licence.html - - - $Id: LICENCE,v 1.2 2003/10/04 08:33:05 dwmw2 Exp $ diff --git a/components/dfs/filesystems/jffs2/src/build.c b/components/dfs/filesystems/jffs2/src/build.c deleted file mode 100644 index 158b01a829..0000000000 --- a/components/dfs/filesystems/jffs2/src/build.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: build.c,v 1.75 2005/07/22 10:32:07 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include -#include "nodelist.h" - -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **); - -static inline struct jffs2_inode_cache * -first_inode_chain(int *i, struct jffs2_sb_info *c) -{ - for (; *i < INOCACHE_HASHSIZE; (*i)++) { - if (c->inocache_list[*i]) - return c->inocache_list[*i]; - } - return NULL; -} - -static inline struct jffs2_inode_cache * -next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) -{ - /* More in this chain? */ - if (ic->next) - return ic->next; - (*i)++; - return first_inode_chain(i, c); -} - -#define for_each_inode(i, c, ic) \ - for (i = 0, ic = first_inode_chain(&i, (c)); \ - ic; \ - ic = next_inode(&i, ic, (c))) - - -static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -{ - struct jffs2_full_dirent *fd; - - D1(printk(KERN_DEBUG "jffs2_build_inode building directory inode #%u\n", ic->ino)); - - /* For each child, increase nlink */ - for(fd = ic->scan_dents; fd; fd = fd->next) { - struct jffs2_inode_cache *child_ic; - if (!fd->ino) - continue; - - /* XXX: Can get high latency here with huge directories */ - - child_ic = jffs2_get_ino_cache(c, fd->ino); - if (!child_ic) { - printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", - fd->name, fd->ino, ic->ino); - jffs2_mark_node_obsolete(c, fd->raw); - continue; - } - - if (child_ic->nlink++ && fd->type == DT_DIR) { - printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); - if (fd->ino == 1 && ic->ino == 1) { - printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); - printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); - } - /* What do we do about it? */ - } - D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); - /* Can't free them. We might need them in pass 2 */ - } -} - -/* Scan plan: - - Scan physical nodes. Build map of inodes/dirents. Allocate inocaches as we go - - Scan directory tree from top down, setting nlink in inocaches - - Scan inocaches for inodes with nlink==0 -*/ -static int jffs2_build_filesystem(struct jffs2_sb_info *c) -{ - int ret; - int i; - struct jffs2_inode_cache *ic; - struct jffs2_full_dirent *fd; - struct jffs2_full_dirent *dead_fds = NULL; - - /* First, scan the medium and build all the inode caches with - lists of physical nodes */ - - c->flags |= JFFS2_SB_FLAG_SCANNING; - ret = jffs2_scan_medium(c); - c->flags &= ~JFFS2_SB_FLAG_SCANNING; - if (ret) - goto exit; - - D1(printk(KERN_DEBUG "Scanned flash completely\n")); - jffs2_dbg_dump_block_lists_nolock(c); - - c->flags |= JFFS2_SB_FLAG_BUILDING; - /* Now scan the directory tree, increasing nlink according to every dirent found. */ - for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); - - D1(BUG_ON(ic->ino > c->highest_ino)); - - if (ic->scan_dents) { - jffs2_build_inode_pass1(c, ic); - cond_resched(); - } - } - - D1(printk(KERN_DEBUG "Pass 1 complete\n")); - - /* Next, scan for inodes with nlink == 0 and remove them. If - they were directories, then decrement the nlink of their - children too, and repeat the scan. As that's going to be - a fairly uncommon occurrence, it's not so evil to do it this - way. Recursion bad. */ - D1(printk(KERN_DEBUG "Pass 2 starting\n")); - - for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes)); - if (ic->nlink) - continue; - - jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); - cond_resched(); - } - - D1(printk(KERN_DEBUG "Pass 2a starting\n")); - - while (dead_fds) { - fd = dead_fds; - dead_fds = fd->next; - - ic = jffs2_get_ino_cache(c, fd->ino); - D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic)); - - if (ic) - jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); - jffs2_free_full_dirent(fd); - } - - D1(printk(KERN_DEBUG "Pass 2 complete\n")); - - /* Finally, we can scan again and free the dirent structs */ - for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); - - while(ic->scan_dents) { - fd = ic->scan_dents; - ic->scan_dents = fd->next; - jffs2_free_full_dirent(fd); - } - ic->scan_dents = NULL; - cond_resched(); - } - c->flags &= ~JFFS2_SB_FLAG_BUILDING; - - D1(printk(KERN_DEBUG "Pass 3 complete\n")); - jffs2_dbg_dump_block_lists_nolock(c); - - /* Rotate the lists by some number to ensure wear levelling */ - jffs2_rotate_lists(c); - - ret = 0; - -exit: - if (ret) { - for_each_inode(i, c, ic) { - while(ic->scan_dents) { - fd = ic->scan_dents; - ic->scan_dents = fd->next; - jffs2_free_full_dirent(fd); - } - } - } - - return ret; -} - -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds) -{ - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; - - D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); - - raw = ic->nodes; - while (raw != (void *)ic) { - struct jffs2_raw_node_ref *next = raw->next_in_ino; - D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw))); - jffs2_mark_node_obsolete(c, raw); - raw = next; - } - - if (ic->scan_dents) { - int whinged = 0; - D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino)); - - while(ic->scan_dents) { - struct jffs2_inode_cache *child_ic; - - fd = ic->scan_dents; - ic->scan_dents = fd->next; - - if (!fd->ino) { - /* It's a deletion dirent. Ignore it */ - D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name)); - jffs2_free_full_dirent(fd); - continue; - } - if (!whinged) { - whinged = 1; - printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); - } - - D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", - fd->name, fd->ino)); - - child_ic = jffs2_get_ino_cache(c, fd->ino); - if (!child_ic) { - printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); - jffs2_free_full_dirent(fd); - continue; - } - - /* Reduce nlink of the child. If it's now zero, stick it on the - dead_fds list to be cleaned up later. Else just free the fd */ - - child_ic->nlink--; - - if (!child_ic->nlink) { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n", - fd->ino, fd->name)); - fd->next = *dead_fds; - *dead_fds = fd; - } else { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", - fd->ino, fd->name, child_ic->nlink)); - jffs2_free_full_dirent(fd); - } - } - } - - /* - We don't delete the inocache from the hash list and free it yet. - The erase code will do that, when all the nodes are completely gone. - */ -} - -static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) -{ - uint32_t size; - - /* Deletion should almost _always_ be allowed. We're fairly - buggered once we stop allowing people to delete stuff - because there's not enough free space... */ - c->resv_blocks_deletion = 2; - - /* Be conservative about how much space we need before we allow writes. - On top of that which is required for deletia, require an extra 2% - of the medium to be available, for overhead caused by nodes being - split across blocks, etc. */ - - size = c->flash_size / 50; /* 2% of flash size */ - size += c->nr_blocks * 100; /* And 100 bytes per eraseblock */ - size += c->sector_size - 1; /* ... and round up */ - - c->resv_blocks_write = c->resv_blocks_deletion + (size / c->sector_size); - - /* When do we let the GC thread run in the background */ - - c->resv_blocks_gctrigger = c->resv_blocks_write + 1; - - /* When do we allow garbage collection to merge nodes to make - long-term progress at the expense of short-term space exhaustion? */ - c->resv_blocks_gcmerge = c->resv_blocks_deletion + 1; - - /* When do we allow garbage collection to eat from bad blocks rather - than actually making progress? */ - c->resv_blocks_gcbad = 0;//c->resv_blocks_deletion + 2; - - /* If there's less than this amount of dirty space, don't bother - trying to GC to make more space. It'll be a fruitless task */ - c->nospc_dirty_size = c->sector_size + (c->flash_size / 100); - - D1(printk(KERN_DEBUG "JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", - c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks)); - D1(printk(KERN_DEBUG "Blocks required to allow deletion: %d (%d KiB)\n", - c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow writes: %d (%d KiB)\n", - c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to quiesce GC thread: %d (%d KiB)\n", - c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow GC merges: %d (%d KiB)\n", - c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to GC bad blocks: %d (%d KiB)\n", - c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Amount of dirty space required to GC: %d bytes\n", - c->nospc_dirty_size)); -} - -int jffs2_do_mount_fs(struct jffs2_sb_info *c) -{ - int i; - - c->free_size = c->flash_size; - c->nr_blocks = c->flash_size / c->sector_size; -#ifndef __ECOS - if (c->mtd->flags & MTD_NO_VIRTBLOCKS) - c->blocks = vmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks); - else -#endif - c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); - if (!c->blocks) - return -ENOMEM; - for (i=0; inr_blocks; i++) { - INIT_LIST_HEAD(&c->blocks[i].list); - c->blocks[i].offset = i * c->sector_size; - c->blocks[i].free_size = c->sector_size; - c->blocks[i].dirty_size = 0; - c->blocks[i].wasted_size = 0; - c->blocks[i].unchecked_size = 0; - c->blocks[i].used_size = 0; - c->blocks[i].first_node = NULL; - c->blocks[i].last_node = NULL; - c->blocks[i].bad_count = 0; - } - - INIT_LIST_HEAD(&c->clean_list); - INIT_LIST_HEAD(&c->very_dirty_list); - INIT_LIST_HEAD(&c->dirty_list); - INIT_LIST_HEAD(&c->erasable_list); - INIT_LIST_HEAD(&c->erasing_list); - INIT_LIST_HEAD(&c->erase_pending_list); - INIT_LIST_HEAD(&c->erasable_pending_wbuf_list); - INIT_LIST_HEAD(&c->erase_complete_list); - INIT_LIST_HEAD(&c->free_list); - INIT_LIST_HEAD(&c->bad_list); - INIT_LIST_HEAD(&c->bad_used_list); - c->highest_ino = 1; - - if (jffs2_build_filesystem(c)) { - D1(printk(KERN_DEBUG "build_fs failed\n")); - jffs2_free_ino_caches(c); - jffs2_free_raw_node_refs(c); -#ifndef __ECOS - if (c->mtd->flags & MTD_NO_VIRTBLOCKS) - vfree(c->blocks); - else -#endif - kfree(c->blocks); - - return -EIO; - } - - jffs2_calc_trigger_levels(c); - - return 0; -} diff --git a/components/dfs/filesystems/jffs2/src/compr.c b/components/dfs/filesystems/jffs2/src/compr.c deleted file mode 100644 index c9e54b97db..0000000000 --- a/components/dfs/filesystems/jffs2/src/compr.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * Created by Arjan van de Ven - * - * Copyright (C) 2004 Ferenc Havasi , - * University of Szeged, Hungary - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $ - * - */ - -#include "compr.h" - -static DEFINE_SPINLOCK(jffs2_compressor_list_lock); - -/* Available compressors are on this list */ -static LIST_HEAD(jffs2_compressor_list); - -/* Actual compression mode */ -static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; - -/* Statistics for blocks stored without compression */ -static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; - -/* jffs2_compress: - * @data: Pointer to uncompressed data - * @cdata: Pointer to returned pointer to buffer for compressed data - * @datalen: On entry, holds the amount of data available for compression. - * On exit, expected to hold the amount of data actually compressed. - * @cdatalen: On entry, holds the amount of space available for compressed - * data. On exit, expected to hold the actual size of the compressed - * data. - * - * Returns: Lower byte to be stored with data indicating compression type used. - * Zero is used to show that the data could not be compressed - the - * compressed version was actually larger than the original. - * Upper byte will be used later. (soon) - * - * If the cdata buffer isn't large enough to hold all the uncompressed data, - * jffs2_compress should compress as much as will fit, and should set - * *datalen accordingly to show the amount of data which were compressed. - */ -uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned char *data_in, unsigned char **cpage_out, - uint32_t *datalen, uint32_t *cdatalen) -{ - int ret = JFFS2_COMPR_NONE; - int compr_ret; - struct jffs2_compressor *this, *best=NULL; - unsigned char *output_buf = NULL, *tmp_buf; - uint32_t orig_slen, orig_dlen; - uint32_t best_slen=0, best_dlen=0; - - switch (jffs2_compression_mode) { - case JFFS2_COMPR_MODE_NONE: - break; - case JFFS2_COMPR_MODE_PRIORITY: - output_buf = kmalloc(*cdatalen,GFP_KERNEL); - if (!output_buf) { - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); - goto out; - } - orig_slen = *datalen; - orig_dlen = *cdatalen; - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - /* Skip decompress-only backwards-compatibility and disabled modules */ - if ((!this->compress)||(this->disabled)) - continue; - - this->usecount++; - spin_unlock(&jffs2_compressor_list_lock); - *datalen = orig_slen; - *cdatalen = orig_dlen; - compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); - spin_lock(&jffs2_compressor_list_lock); - this->usecount--; - if (!compr_ret) { - ret = this->compr; - this->stat_compr_blocks++; - this->stat_compr_orig_size += *datalen; - this->stat_compr_new_size += *cdatalen; - break; - } - } - spin_unlock(&jffs2_compressor_list_lock); - if (ret == JFFS2_COMPR_NONE) kfree(output_buf); - break; - case JFFS2_COMPR_MODE_SIZE: - orig_slen = *datalen; - orig_dlen = *cdatalen; - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - /* Skip decompress-only backwards-compatibility and disabled modules */ - if ((!this->compress)||(this->disabled)) - continue; - /* Allocating memory for output buffer if necessary */ - if ((this->compr_buf_sizecompr_buf)) { - spin_unlock(&jffs2_compressor_list_lock); - kfree(this->compr_buf); - spin_lock(&jffs2_compressor_list_lock); - this->compr_buf_size=0; - this->compr_buf=NULL; - } - if (!this->compr_buf) { - spin_unlock(&jffs2_compressor_list_lock); - tmp_buf = kmalloc(orig_dlen,GFP_KERNEL); - spin_lock(&jffs2_compressor_list_lock); - if (!tmp_buf) { - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen); - continue; - } - else { - this->compr_buf = tmp_buf; - this->compr_buf_size = orig_dlen; - } - } - this->usecount++; - spin_unlock(&jffs2_compressor_list_lock); - *datalen = orig_slen; - *cdatalen = orig_dlen; - compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); - spin_lock(&jffs2_compressor_list_lock); - this->usecount--; - if (!compr_ret) { - if ((!best_dlen)||(best_dlen>*cdatalen)) { - best_dlen = *cdatalen; - best_slen = *datalen; - best = this; - } - } - } - if (best_dlen) { - *cdatalen = best_dlen; - *datalen = best_slen; - output_buf = best->compr_buf; - best->compr_buf = NULL; - best->compr_buf_size = 0; - best->stat_compr_blocks++; - best->stat_compr_orig_size += best_slen; - best->stat_compr_new_size += best_dlen; - ret = best->compr; - } - spin_unlock(&jffs2_compressor_list_lock); - break; - default: - printk(KERN_ERR "JFFS2: unknow compression mode.\n"); - } - out: - if (ret == JFFS2_COMPR_NONE) { - *cpage_out = data_in; - *datalen = *cdatalen; - none_stat_compr_blocks++; - none_stat_compr_size += *datalen; - } - else { - *cpage_out = output_buf; - } - return ret; -} - -int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint16_t comprtype, unsigned char *cdata_in, - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) -{ - struct jffs2_compressor *this; - int ret; - - /* Older code had a bug where it would write non-zero 'usercompr' - fields. Deal with it. */ - if ((comprtype & 0xff) <= JFFS2_COMPR_ZLIB) - comprtype &= 0xff; - - switch (comprtype & 0xff) { - case JFFS2_COMPR_NONE: - /* This should be special-cased elsewhere, but we might as well deal with it */ - memcpy(data_out, cdata_in, datalen); - none_stat_decompr_blocks++; - break; - case JFFS2_COMPR_ZERO: - memset(data_out, 0, datalen); - break; - default: - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (comprtype == this->compr) { - this->usecount++; - spin_unlock(&jffs2_compressor_list_lock); - ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL); - spin_lock(&jffs2_compressor_list_lock); - if (ret) { - printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); - } - else { - this->stat_decompr_blocks++; - } - this->usecount--; - spin_unlock(&jffs2_compressor_list_lock); - return ret; - } - } - printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype); - spin_unlock(&jffs2_compressor_list_lock); - return -EIO; - } - return 0; -} - -int jffs2_register_compressor(struct jffs2_compressor *comp) -{ - struct jffs2_compressor *this; - - if (!comp->name) { - printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n"); - return -1; - } - comp->compr_buf_size=0; - comp->compr_buf=NULL; - comp->usecount=0; - comp->stat_compr_orig_size=0; - comp->stat_compr_new_size=0; - comp->stat_compr_blocks=0; - comp->stat_decompr_blocks=0; - D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name)); - - spin_lock(&jffs2_compressor_list_lock); - - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (this->priority < comp->priority) { - list_add(&comp->list, this->list.prev); - goto out; - } - } - list_add_tail(&comp->list, &jffs2_compressor_list); -out: - D2(list_for_each_entry(this, &jffs2_compressor_list, list) { - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); - }) - - spin_unlock(&jffs2_compressor_list_lock); - - return 0; -} - -int jffs2_unregister_compressor(struct jffs2_compressor *comp) -{ - D2(struct jffs2_compressor *this;) - - D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name)); - - spin_lock(&jffs2_compressor_list_lock); - - if (comp->usecount) { - spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n"); - return -1; - } - list_del(&comp->list); - - D2(list_for_each_entry(this, &jffs2_compressor_list, list) { - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); - }) - spin_unlock(&jffs2_compressor_list_lock); - return 0; -} - -#ifdef CONFIG_JFFS2_PROC - -#define JFFS2_STAT_BUF_SIZE 16000 - -char *jffs2_list_compressors(void) -{ - struct jffs2_compressor *this; - char *buf, *act_buf; - - act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); - list_for_each_entry(this, &jffs2_compressor_list, list) { - act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority); - if ((this->disabled)||(!this->compress)) - act_buf += sprintf(act_buf,"disabled"); - else - act_buf += sprintf(act_buf,"enabled"); - act_buf += sprintf(act_buf,"\n"); - } - return buf; -} - -char *jffs2_stats(void) -{ - struct jffs2_compressor *this; - char *buf, *act_buf; - - act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); - - act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); - act_buf += sprintf(act_buf,"%10s ","none"); - act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, - none_stat_compr_size, none_stat_decompr_blocks); - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - act_buf += sprintf(act_buf,"%10s ",this->name); - if ((this->disabled)||(!this->compress)) - act_buf += sprintf(act_buf,"- "); - else - act_buf += sprintf(act_buf,"+ "); - act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, - this->stat_compr_new_size, this->stat_compr_orig_size, - this->stat_decompr_blocks); - act_buf += sprintf(act_buf,"\n"); - } - spin_unlock(&jffs2_compressor_list_lock); - - return buf; -} - -char *jffs2_get_compression_mode_name(void) -{ - switch (jffs2_compression_mode) { - case JFFS2_COMPR_MODE_NONE: - return "none"; - case JFFS2_COMPR_MODE_PRIORITY: - return "priority"; - case JFFS2_COMPR_MODE_SIZE: - return "size"; - } - return "unkown"; -} - -int jffs2_set_compression_mode_name(const char *name) -{ - if (!strcmp("none",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; - return 0; - } - if (!strcmp("priority",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; - return 0; - } - if (!strcmp("size",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; - return 0; - } - return 1; -} - -static int jffs2_compressor_Xable(const char *name, int disabled) -{ - struct jffs2_compressor *this; - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (!strcmp(this->name, name)) { - this->disabled = disabled; - spin_unlock(&jffs2_compressor_list_lock); - return 0; - } - } - spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); - return 1; -} - -int jffs2_enable_compressor_name(const char *name) -{ - return jffs2_compressor_Xable(name, 0); -} - -int jffs2_disable_compressor_name(const char *name) -{ - return jffs2_compressor_Xable(name, 1); -} - -int jffs2_set_compressor_priority(const char *name, int priority) -{ - struct jffs2_compressor *this,*comp; - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (!strcmp(this->name, name)) { - this->priority = priority; - comp = this; - goto reinsert; - } - } - spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); - return 1; -reinsert: - /* list is sorted in the order of priority, so if - we change it we have to reinsert it into the - good place */ - list_del(&comp->list); - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (this->priority < comp->priority) { - list_add(&comp->list, this->list.prev); - spin_unlock(&jffs2_compressor_list_lock); - return 0; - } - } - list_add_tail(&comp->list, &jffs2_compressor_list); - spin_unlock(&jffs2_compressor_list_lock); - return 0; -} - -#endif - -void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) -{ - if (orig != comprbuf) - kfree(comprbuf); -} - -int jffs2_compressors_init(void) -{ -/* Registering compressors */ -#ifdef CONFIG_JFFS2_ZLIB - jffs2_zlib_init(); -#endif -#ifdef CONFIG_JFFS2_RTIME - jffs2_rtime_init(); -#endif -#ifdef CONFIG_JFFS2_RUBIN - jffs2_rubinmips_init(); - jffs2_dynrubin_init(); -#endif -/* Setting default compression mode */ -#ifdef CONFIG_JFFS2_CMODE_NONE - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; - D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");) -#else -#ifdef CONFIG_JFFS2_CMODE_SIZE - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; - D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");) -#else - D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");) -#endif -#endif - return 0; -} - -int jffs2_compressors_exit(void) -{ -/* Unregistering compressors */ -#ifdef CONFIG_JFFS2_RUBIN - jffs2_dynrubin_exit(); - jffs2_rubinmips_exit(); -#endif -#ifdef CONFIG_JFFS2_RTIME - jffs2_rtime_exit(); -#endif -#ifdef CONFIG_JFFS2_ZLIB - jffs2_zlib_exit(); -#endif - return 0; -} diff --git a/components/dfs/filesystems/jffs2/src/compr.h b/components/dfs/filesystems/jffs2/src/compr.h deleted file mode 100644 index 9ec6e37d38..0000000000 --- a/components/dfs/filesystems/jffs2/src/compr.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2004 Ferenc Havasi , - * University of Szeged, Hungary - * - * For licensing information, see the file 'LICENCE' in the - * jffs2 directory. - * - * $Id: compr.h,v 1.8 2005/07/26 13:24:40 havasi Exp $ - * - */ - -#ifndef __JFFS2_COMPR_H__ -#define __JFFS2_COMPR_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "nodelist.h" - -#define JFFS2_RUBINMIPS_PRIORITY 10 -#define JFFS2_DYNRUBIN_PRIORITY 20 -#define JFFS2_LZARI_PRIORITY 30 -#define JFFS2_LZO_PRIORITY 40 -#define JFFS2_RTIME_PRIORITY 50 -#define JFFS2_ZLIB_PRIORITY 60 - -#define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */ -#define JFFS2_DYNRUBIN_DISABLED /* for decompression */ - -#define JFFS2_COMPR_MODE_NONE 0 -#define JFFS2_COMPR_MODE_PRIORITY 1 -#define JFFS2_COMPR_MODE_SIZE 2 - -struct jffs2_compressor { - struct list_head list; - int priority; /* used by prirority comr. mode */ - char *name; - char compr; /* JFFS2_COMPR_XXX */ - int (*compress)(unsigned char *data_in, unsigned char *cpage_out, - uint32_t *srclen, uint32_t *destlen, void *model); - int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, - uint32_t cdatalen, uint32_t datalen, void *model); - int usecount; - int disabled; /* if seted the compressor won't compress */ - unsigned char *compr_buf; /* used by size compr. mode */ - uint32_t compr_buf_size; /* used by size compr. mode */ - uint32_t stat_compr_orig_size; - uint32_t stat_compr_new_size; - uint32_t stat_compr_blocks; - uint32_t stat_decompr_blocks; -}; - -int jffs2_register_compressor(struct jffs2_compressor *comp); -int jffs2_unregister_compressor(struct jffs2_compressor *comp); - -int jffs2_compressors_init(void); -int jffs2_compressors_exit(void); - -uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned char *data_in, unsigned char **cpage_out, - uint32_t *datalen, uint32_t *cdatalen); - -int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint16_t comprtype, unsigned char *cdata_in, - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); - -void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); - -#ifdef CONFIG_JFFS2_PROC -int jffs2_enable_compressor_name(const char *name); -int jffs2_disable_compressor_name(const char *name); -int jffs2_set_compression_mode_name(const char *mode_name); -char *jffs2_get_compression_mode_name(void); -int jffs2_set_compressor_priority(const char *mode_name, int priority); -char *jffs2_list_compressors(void); -char *jffs2_stats(void); -#endif - -/* Compressor modules */ -/* These functions will be called by jffs2_compressors_init/exit */ - -#ifdef CONFIG_JFFS2_RUBIN -int jffs2_rubinmips_init(void); -void jffs2_rubinmips_exit(void); -int jffs2_dynrubin_init(void); -void jffs2_dynrubin_exit(void); -#endif -#ifdef CONFIG_JFFS2_RTIME -int jffs2_rtime_init(void); -void jffs2_rtime_exit(void); -#endif -#ifdef CONFIG_JFFS2_ZLIB -int jffs2_zlib_init(void); -void jffs2_zlib_exit(void); -#endif - -#endif /* __JFFS2_COMPR_H__ */ diff --git a/components/dfs/filesystems/jffs2/src/compr_rtime.c b/components/dfs/filesystems/jffs2/src/compr_rtime.c deleted file mode 100644 index c7f6b2914e..0000000000 --- a/components/dfs/filesystems/jffs2/src/compr_rtime.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by Arjan van de Ven - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: compr_rtime.c,v 1.15 2005/03/17 20:23:06 gleixner Exp $ - * - * - * Very simple lz77-ish encoder. - * - * Theory of operation: Both encoder and decoder have a list of "last - * occurrences" for every possible source-value; after sending the - * first source-byte, the second byte indicated the "run" length of - * matches - * - * The algorithm is intended to only send "whole bytes", no bit-messing. - * - */ - -#include -#include -#include -#include -#include -#include "compr.h" - -/* _compress returns the compressed size, -1 if bigger */ -static int jffs2_rtime_compress(unsigned char *data_in, - unsigned char *cpage_out, - uint32_t *sourcelen, uint32_t *dstlen, - void *model) -{ - short positions[256]; - int outpos = 0; - int pos=0; - - memset(positions,0,sizeof(positions)); - - while (pos < (*sourcelen) && outpos <= (*dstlen)-2) { - int backpos, runlen=0; - unsigned char value; - - value = data_in[pos]; - - cpage_out[outpos++] = data_in[pos++]; - - backpos = positions[value]; - positions[value]=pos; - - while ((backpos < pos) && (pos < (*sourcelen)) && - (data_in[pos]==data_in[backpos++]) && (runlen<255)) { - pos++; - runlen++; - } - cpage_out[outpos++] = runlen; - } - - if (outpos >= pos) { - /* We failed */ - return -1; - } - - /* Tell the caller how much we managed to compress, and how much space it took */ - *sourcelen = pos; - *dstlen = outpos; - return 0; -} - - -static int jffs2_rtime_decompress(unsigned char *data_in, - unsigned char *cpage_out, - uint32_t srclen, uint32_t destlen, - void *model) -{ - short positions[256]; - int outpos = 0; - int pos=0; - - memset(positions,0,sizeof(positions)); - - while (outpos= outpos) { - while(repeat) { - cpage_out[outpos++] = cpage_out[backoffs++]; - repeat--; - } - } else { - memcpy(&cpage_out[outpos],&cpage_out[backoffs],repeat); - outpos+=repeat; - } - } - } - return 0; -} - -#if defined (__GNUC__) -static struct jffs2_compressor jffs2_rtime_comp = { - .priority = JFFS2_RTIME_PRIORITY, - .name = "rtime", - .compr = JFFS2_COMPR_RTIME, - .compress = &jffs2_rtime_compress, - .decompress = &jffs2_rtime_decompress, -#ifdef JFFS2_RTIME_DISABLED - .disabled = 1, -#else - .disabled = 0, -#endif -}; -#elif defined (MSVC) -static struct jffs2_compressor jffs2_rtime_comp = { - {NULL}, - JFFS2_RTIME_PRIORITY,//.priority = - "rtime",//.name = - JFFS2_COMPR_RTIME,//.compr = - &jffs2_rtime_compress,//.compress = - &jffs2_rtime_decompress,//.decompress = - 0, -#ifdef JFFS2_RTIME_DISABLED - 1,//.disabled = -#else - 0,//.disabled = -#endif - NULL, - 0, - 0, - 0, - 0, - 0 -}; -#else -#endif - -int jffs2_rtime_init(void) -{ - return jffs2_register_compressor(&jffs2_rtime_comp); -} - -void jffs2_rtime_exit(void) -{ - jffs2_unregister_compressor(&jffs2_rtime_comp); -} diff --git a/components/dfs/filesystems/jffs2/src/compr_rubin.c b/components/dfs/filesystems/jffs2/src/compr_rubin.c deleted file mode 100644 index e1030d6778..0000000000 --- a/components/dfs/filesystems/jffs2/src/compr_rubin.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001, 2002 Red Hat, Inc. - * - * Created by Arjan van de Ven - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: compr_rubin.c,v 1.21 2005/05/20 15:39:54 gleixner Exp $ - * - */ - - -#include -#include -#include -#include "compr_rubin.h" -#include "histo_mips.h" -#include "compr.h" - -static void init_rubin(struct rubin_state *rs, int div, int *bits) -{ - int c; - - rs->q = 0; - rs->p = (long) (2 * UPPER_BIT_RUBIN); - rs->bit_number = (long) 0; - rs->bit_divider = div; - for (c=0; c<8; c++) - rs->bits[c] = bits[c]; -} - - -static int encode(struct rubin_state *rs, long A, long B, int symbol) -{ - - long i0, i1; - int ret; - - while ((rs->q >= UPPER_BIT_RUBIN) || ((rs->p + rs->q) <= UPPER_BIT_RUBIN)) { - rs->bit_number++; - - ret = pushbit(&rs->pp, (rs->q & UPPER_BIT_RUBIN) ? 1 : 0, 0); - if (ret) - return ret; - rs->q &= LOWER_BITS_RUBIN; - rs->q <<= 1; - rs->p <<= 1; - } - i0 = A * rs->p / (A + B); - if (i0 <= 0) { - i0 = 1; - } - if (i0 >= rs->p) { - i0 = rs->p - 1; - } - i1 = rs->p - i0; - - if (symbol == 0) - rs->p = i0; - else { - rs->p = i1; - rs->q += i0; - } - return 0; -} - - -static void end_rubin(struct rubin_state *rs) -{ - - int i; - - for (i = 0; i < RUBIN_REG_SIZE; i++) { - pushbit(&rs->pp, (UPPER_BIT_RUBIN & rs->q) ? 1 : 0, 1); - rs->q &= LOWER_BITS_RUBIN; - rs->q <<= 1; - } -} - - -static void init_decode(struct rubin_state *rs, int div, int *bits) -{ - init_rubin(rs, div, bits); - - /* behalve lower */ - rs->rec_q = 0; - - for (rs->bit_number = 0; rs->bit_number++ < RUBIN_REG_SIZE; rs->rec_q = rs->rec_q * 2 + (long) (pullbit(&rs->pp))) - ; -} - -static void __do_decode(struct rubin_state *rs, unsigned long p, unsigned long q) -{ - register unsigned long lower_bits_rubin = LOWER_BITS_RUBIN; - unsigned long rec_q; - int c, bits = 0; - - /* - * First, work out how many bits we need from the input stream. - * Note that we have already done the initial check on this - * loop prior to calling this function. - */ - do { - bits++; - q &= lower_bits_rubin; - q <<= 1; - p <<= 1; - } while ((q >= UPPER_BIT_RUBIN) || ((p + q) <= UPPER_BIT_RUBIN)); - - rs->p = p; - rs->q = q; - - rs->bit_number += bits; - - /* - * Now get the bits. We really want this to be "get n bits". - */ - rec_q = rs->rec_q; - do { - c = pullbit(&rs->pp); - rec_q &= lower_bits_rubin; - rec_q <<= 1; - rec_q += c; - } while (--bits); - rs->rec_q = rec_q; -} - -static int decode(struct rubin_state *rs, long A, long B) -{ - unsigned long p = rs->p, q = rs->q; - long i0, threshold; - int symbol; - - if (q >= UPPER_BIT_RUBIN || ((p + q) <= UPPER_BIT_RUBIN)) - __do_decode(rs, p, q); - - i0 = A * rs->p / (A + B); - if (i0 <= 0) { - i0 = 1; - } - if (i0 >= rs->p) { - i0 = rs->p - 1; - } - - threshold = rs->q + i0; - symbol = rs->rec_q >= threshold; - if (rs->rec_q >= threshold) { - rs->q += i0; - i0 = rs->p - i0; - } - - rs->p = i0; - - return symbol; -} - - - -static int out_byte(struct rubin_state *rs, unsigned char byte) -{ - int i, ret; - struct rubin_state rs_copy; - rs_copy = *rs; - - for (i=0;i<8;i++) { - ret = encode(rs, rs->bit_divider-rs->bits[i],rs->bits[i],byte&1); - if (ret) { - /* Failed. Restore old state */ - *rs = rs_copy; - return ret; - } - byte=byte>>1; - } - return 0; -} - -static int in_byte(struct rubin_state *rs) -{ - int i, result = 0, bit_divider = rs->bit_divider; - - for (i = 0; i < 8; i++) - result |= decode(rs, bit_divider - rs->bits[i], rs->bits[i]) << i; - - return result; -} - - - -static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, - unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) - { - int outpos = 0; - int pos=0; - struct rubin_state rs; - - init_pushpull(&rs.pp, (char *)cpage_out, *dstlen * 8, 0, 32); - - init_rubin(&rs, bit_divider, bits); - - while (pos < (*sourcelen) && !out_byte(&rs, data_in[pos])) - pos++; - - end_rubin(&rs); - - if (outpos > pos) { - /* We failed */ - return -1; - } - - /* Tell the caller how much we managed to compress, - * and how much space it took */ - - outpos = (pushedbits(&rs.pp)+7)/8; - - if (outpos >= pos) - return -1; /* We didn't actually compress */ - *sourcelen = pos; - *dstlen = outpos; - return 0; -} -#if 0 -/* _compress returns the compressed size, -1 if bigger */ -int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, - uint32_t *sourcelen, uint32_t *dstlen, void *model) -{ - return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); -} -#endif -static int jffs2_dynrubin_compress(unsigned char *data_in, - unsigned char *cpage_out, - uint32_t *sourcelen, uint32_t *dstlen, - void *model) -{ - int bits[8]; - unsigned char histo[256]; - int i; - int ret; - uint32_t mysrclen, mydstlen; - - mysrclen = *sourcelen; - mydstlen = *dstlen - 8; - - if (*dstlen <= 12) - return -1; - - memset(histo, 0, 256); - for (i=0; i 255) bits[i] = 255; - cpage_out[i] = bits[i]; - } - - ret = rubin_do_compress(256, bits, data_in, cpage_out+8, &mysrclen, &mydstlen); - if (ret) - return ret; - - /* Add back the 8 bytes we took for the probabilities */ - mydstlen += 8; - - if (mysrclen <= mydstlen) { - /* We compressed */ - return -1; - } - - *sourcelen = mysrclen; - *dstlen = mydstlen; - return 0; -} - -static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, - unsigned char *page_out, uint32_t srclen, uint32_t destlen) -{ - int outpos = 0; - struct rubin_state rs; - - init_pushpull(&rs.pp, (char *)cdata_in, srclen, 0, 0); - init_decode(&rs, bit_divider, bits); - - while (outpos < destlen) { - page_out[outpos++] = in_byte(&rs); - } -} - - -static int jffs2_rubinmips_decompress(unsigned char *data_in, - unsigned char *cpage_out, - uint32_t sourcelen, uint32_t dstlen, - void *model) -{ - rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); - return 0; -} - -static int jffs2_dynrubin_decompress(unsigned char *data_in, - unsigned char *cpage_out, - uint32_t sourcelen, uint32_t dstlen, - void *model) -{ - int bits[8]; - int c; - - for (c=0; c<8; c++) - bits[c] = data_in[c]; - - rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen); - return 0; -} - -#if defined (__GNUC__) -static struct jffs2_compressor jffs2_rubinmips_comp = { - .priority = JFFS2_RUBINMIPS_PRIORITY, - .name = "rubinmips", - .compr = JFFS2_COMPR_DYNRUBIN, - .compress = NULL, /*&jffs2_rubinmips_compress,*/ - .decompress = &jffs2_rubinmips_decompress, -#ifdef JFFS2_RUBINMIPS_DISABLED - .disabled = 1, -#else - .disabled = 0, -#endif -}; -#elif defined (MSVC) -static struct jffs2_compressor jffs2_rubinmips_comp = { - {NULL}, - JFFS2_RUBINMIPS_PRIORITY, - "rubinmips", - JFFS2_COMPR_DYNRUBIN, - NULL, /*&jffs2_rubinmips_compress,*/ - &jffs2_rubinmips_decompress, - 0, -#ifdef JFFS2_RUBINMIPS_DISABLED - 1, -#else - 0, -#endif - NULL, - 0, - 0, - 0, - 0, - 0 -}; -#else -#endif - -int jffs2_rubinmips_init(void) -{ - return jffs2_register_compressor(&jffs2_rubinmips_comp); -} - -void jffs2_rubinmips_exit(void) -{ - jffs2_unregister_compressor(&jffs2_rubinmips_comp); -} - -#if defined (__GNUC__) -static struct jffs2_compressor jffs2_dynrubin_comp = { - .priority = JFFS2_DYNRUBIN_PRIORITY, - .name = "dynrubin", - .compr = JFFS2_COMPR_RUBINMIPS, - .compress = jffs2_dynrubin_compress, - .decompress = &jffs2_dynrubin_decompress, -#ifdef JFFS2_DYNRUBIN_DISABLED - .disabled = 1, -#else - .disabled = 0, -#endif -}; -#elif defined (MSVC) -static struct jffs2_compressor jffs2_dynrubin_comp = { - {NULL}, - JFFS2_DYNRUBIN_PRIORITY, - "dynrubin", - JFFS2_COMPR_RUBINMIPS, - jffs2_dynrubin_compress, - &jffs2_dynrubin_decompress, - 0, -#ifdef JFFS2_DYNRUBIN_DISABLED - 1, -#else - 0, -#endif - NULL, - 0, - 0, - 0, - 0, - 0 -}; -#else -#endif - -int jffs2_dynrubin_init(void) -{ - return jffs2_register_compressor(&jffs2_dynrubin_comp); -} - -void jffs2_dynrubin_exit(void) -{ - jffs2_unregister_compressor(&jffs2_dynrubin_comp); -} diff --git a/components/dfs/filesystems/jffs2/src/compr_rubin.h b/components/dfs/filesystems/jffs2/src/compr_rubin.h deleted file mode 100644 index cf51e34f65..0000000000 --- a/components/dfs/filesystems/jffs2/src/compr_rubin.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Rubin encoder/decoder header */ -/* work started at : aug 3, 1994 */ -/* last modification : aug 15, 1994 */ -/* $Id: compr_rubin.h,v 1.6 2002/01/25 01:49:26 dwmw2 Exp $ */ - -#include "pushpull.h" - -#define RUBIN_REG_SIZE 16 -#define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1)) -#define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1) - - -struct rubin_state { - unsigned long p; - unsigned long q; - unsigned long rec_q; - long bit_number; - struct pushpull pp; - int bit_divider; - int bits[8]; -}; diff --git a/components/dfs/filesystems/jffs2/src/compr_zlib.c b/components/dfs/filesystems/jffs2/src/compr_zlib.c deleted file mode 100644 index 7fe18e088c..0000000000 --- a/components/dfs/filesystems/jffs2/src/compr_zlib.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: compr_zlib.c,v 1.31 2005/05/20 19:30:06 gleixner Exp $ - * - */ -#include "jffs2_config.h" -#if !defined(__KERNEL__) && !defined(__ECOS) -#error "The userspace support got too messy and was removed. Update your mkfs.jffs2" -#endif - -#include -#include -#include -#include -#include -#include -#include "nodelist.h" -#include "compr.h" - - /* Plan: call deflate() with avail_in == *sourcelen, - avail_out = *dstlen - 12 and flush == Z_FINISH. - If it doesn't manage to finish, call it again with - avail_in == 0 and avail_out set to the remaining 12 - bytes for it to clean up. - Q: Is 12 bytes sufficient? - */ -#define STREAM_END_SPACE 12 - -static DECLARE_MUTEX(deflate_sem); -static DECLARE_MUTEX(inflate_sem); -static z_stream inf_strm, def_strm; - -#ifdef __KERNEL__ /* Linux-only */ -#include -#include - -static int __init alloc_workspaces(void) -{ - def_strm.workspace = vmalloc(zlib_deflate_workspacesize()); - if (!def_strm.workspace) { - printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); - return -ENOMEM; - } - D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); - inf_strm.workspace = vmalloc(zlib_inflate_workspacesize()); - if (!inf_strm.workspace) { - printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); - vfree(def_strm.workspace); - return -ENOMEM; - } - D1(printk(KERN_DEBUG "Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize())); - return 0; -} - -static void free_workspaces(void) -{ - vfree(def_strm.workspace); - vfree(inf_strm.workspace); -} -#else -#define alloc_workspaces() (0) -#define free_workspaces() do { } while(0) -#endif /* __KERNEL__ */ - -static int jffs2_zlib_compress(unsigned char *data_in, - unsigned char *cpage_out, - uint32_t *sourcelen, uint32_t *dstlen, - void *model) -{ - int ret; - - if (*dstlen <= STREAM_END_SPACE) - return -1; - - down(&deflate_sem); - - if (Z_OK != zlib_deflateInit(&def_strm, 3)) { - printk(KERN_WARNING "deflateInit failed\n"); - up(&deflate_sem); - return -1; - } - - def_strm.next_in = data_in; - def_strm.total_in = 0; - - def_strm.next_out = cpage_out; - def_strm.total_out = 0; - - while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) { - def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE); - def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out); - D1(printk(KERN_DEBUG "calling deflate with avail_in %d, avail_out %d\n", - def_strm.avail_in, def_strm.avail_out)); - ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); - D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", - def_strm.avail_in, def_strm.avail_out, def_strm.total_in, def_strm.total_out)); - if (ret != Z_OK) { - D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret)); - zlib_deflateEnd(&def_strm); - up(&deflate_sem); - return -1; - } - } - def_strm.avail_out += STREAM_END_SPACE; - def_strm.avail_in = 0; - ret = zlib_deflate(&def_strm, Z_FINISH); - zlib_deflateEnd(&def_strm); - - if (ret != Z_STREAM_END) { - D1(printk(KERN_DEBUG "final deflate returned %d\n", ret)); - ret = -1; - goto out; - } - - if (def_strm.total_out >= def_strm.total_in) { - D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld; failing\n", - def_strm.total_in, def_strm.total_out)); - ret = -1; - goto out; - } - - D1(printk(KERN_DEBUG "zlib compressed %ld bytes into %ld\n", - def_strm.total_in, def_strm.total_out)); - - *dstlen = def_strm.total_out; - *sourcelen = def_strm.total_in; - ret = 0; - out: - up(&deflate_sem); - return ret; -} - -static int jffs2_zlib_decompress(unsigned char *data_in, - unsigned char *cpage_out, - uint32_t srclen, uint32_t destlen, - void *model) -{ - int ret; - int wbits = MAX_WBITS; - - down(&inflate_sem); - - inf_strm.next_in = data_in; - inf_strm.avail_in = srclen; - inf_strm.total_in = 0; - - inf_strm.next_out = cpage_out; - inf_strm.avail_out = destlen; - inf_strm.total_out = 0; - - /* If it's deflate, and it's got no preset dictionary, then - we can tell zlib to skip the adler32 check. */ - if (srclen > 2 && !(data_in[1] & PRESET_DICT) && - ((data_in[0] & 0x0f) == Z_DEFLATED) && - !(((data_in[0]<<8) + data_in[1]) % 31)) { - - D2(printk(KERN_DEBUG "inflate skipping adler32\n")); - wbits = -((data_in[0] >> 4) + 8); - inf_strm.next_in += 2; - inf_strm.avail_in -= 2; - } else { - /* Let this remain D1 for now -- it should never happen */ - D1(printk(KERN_DEBUG "inflate not skipping adler32\n")); - } - - - if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) { - printk(KERN_WARNING "inflateInit failed\n"); - up(&inflate_sem); - return 1; - } - - while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK) - ; - if (ret != Z_STREAM_END) { - printk(KERN_NOTICE "inflate returned %d\n", ret); - } - zlib_inflateEnd(&inf_strm); - up(&inflate_sem); - return 0; -} - -#if defined (__GNUC__) -static struct jffs2_compressor jffs2_zlib_comp = { - .priority = JFFS2_ZLIB_PRIORITY, - .name = "zlib", - .compr = JFFS2_COMPR_ZLIB, - .compress = &jffs2_zlib_compress, - .decompress = &jffs2_zlib_decompress, -#ifdef JFFS2_ZLIB_DISABLED - .disabled = 1, -#else - .disabled = 0, -#endif -}; -#elif defined (MSVC) -static struct jffs2_compressor jffs2_zlib_comp = { - {NULL}, - JFFS2_ZLIB_PRIORITY,//.priority = - "zlib",//.name = - JFFS2_COMPR_ZLIB,//.compr = - &jffs2_zlib_compress,//.compress = - &jffs2_zlib_decompress,//.decompress = - 0, -#ifdef JFFS2_ZLIB_DISABLED - 1,//.disabled = -#else - 0,//.disabled = -#endif - NULL, - 0, - 0, - 0, - 0, - 0 -}; -#else -#endif - -int __init jffs2_zlib_init(void) -{ - int ret; - - ret = alloc_workspaces(); - if (ret) - return ret; - - ret = jffs2_register_compressor(&jffs2_zlib_comp); - if (ret) - free_workspaces(); - - return ret; -} - -void jffs2_zlib_exit(void) -{ - jffs2_unregister_compressor(&jffs2_zlib_comp); - free_workspaces(); -} diff --git a/components/dfs/filesystems/jffs2/src/debug.c b/components/dfs/filesystems/jffs2/src/debug.c deleted file mode 100644 index 3a7c5ea6fc..0000000000 --- a/components/dfs/filesystems/jffs2/src/debug.c +++ /dev/null @@ -1,711 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: debug.c,v 1.1 2005/07/30 15:30:42 asl Exp $ - * - */ -#include -#include -#include -#include -#include -#include -#include "nodelist.h" -#include "debug.h" - -#ifdef JFFS2_DBG_PARANOIA_CHECKS -/* - * Check the fragtree. - */ -void -__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) -{ - down(&f->sem); - __jffs2_dbg_fragtree_paranoia_check_nolock(f); - up(&f->sem); -} - -void -__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) -{ - struct jffs2_node_frag *frag; - int bitched = 0; - - for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { - struct jffs2_full_dnode *fn = frag->node; - - if (!fn || !fn->raw) - continue; - - if (ref_flags(fn->raw) == REF_PRISTINE) { - if (fn->frags > 1) { - JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n", - ref_offset(fn->raw), fn->frags); - bitched = 1; - } - - /* A hole node which isn't multi-page should be garbage-collected - and merged anyway, so we just check for the frag size here, - rather than mucking around with actually reading the node - and checking the compression type, which is the real way - to tell a hole node. */ - if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) - && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { - JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag " - "in the same page. Tell dwmw2.\n", ref_offset(fn->raw)); - bitched = 1; - } - - if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) - && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { - JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following " - "non-hole frag in the same page. Tell dwmw2.\n", - ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); - bitched = 1; - } - } - } - - if (bitched) { - JFFS2_ERROR("fragtree is corrupted.\n"); - __jffs2_dbg_dump_fragtree_nolock(f); - BUG(); - } -} - -/* - * Check if the flash contains all 0xFF before we start writing. - */ -void -__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, - uint32_t ofs, int len) -{ - size_t retlen; - int ret, i; - unsigned char *buf; - - buf = kmalloc(len, GFP_KERNEL); - if (!buf) - return; - - ret = jffs2_flash_read(c, ofs, len, &retlen, buf); - if (ret || (retlen != len)) { - JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n", - len, ret, retlen); - kfree(buf); - return; - } - - ret = 0; - for (i = 0; i < len; i++) - if (buf[i] != 0xff) - ret = 1; - - if (ret) { - JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data " - "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i); - __jffs2_dbg_dump_buffer(buf, len, ofs); - kfree(buf); - BUG(); - } - - kfree(buf); -} - -/* - * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'. - */ -void -__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - spin_lock(&c->erase_completion_lock); - __jffs2_dbg_acct_paranoia_check_nolock(c, jeb); - spin_unlock(&c->erase_completion_lock); -} - -void -__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - uint32_t my_used_size = 0; - uint32_t my_unchecked_size = 0; - uint32_t my_dirty_size = 0; - struct jffs2_raw_node_ref *ref2 = jeb->first_node; - - while (ref2) { - uint32_t totlen = ref_totlen(c, jeb, ref2); - - if (ref2->flash_offset < jeb->offset || - ref2->flash_offset > jeb->offset + c->sector_size) { - JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", - ref_offset(ref2), jeb->offset); - goto error; - - } - if (ref_flags(ref2) == REF_UNCHECKED) - my_unchecked_size += totlen; - else if (!ref_obsolete(ref2)) - my_used_size += totlen; - else - my_dirty_size += totlen; - - if ((!ref2->next_phys) != (ref2 == jeb->last_node)) { - JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), " - "last_node is at %#08x (mem %p).\n", - ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, - ref_offset(jeb->last_node), jeb->last_node); - goto error; - } - ref2 = ref2->next_phys; - } - - if (my_used_size != jeb->used_size) { - JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n", - my_used_size, jeb->used_size); - goto error; - } - - if (my_unchecked_size != jeb->unchecked_size) { - JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n", - my_unchecked_size, jeb->unchecked_size); - goto error; - } - -#if 0 - /* This should work when we implement ref->__totlen elemination */ - if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) { - JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n", - my_dirty_size, jeb->dirty_size + jeb->wasted_size); - goto error; - } - - if (jeb->free_size == 0 - && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) { - JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n", - my_used_size + my_unchecked_size + my_dirty_size, - c->sector_size); - goto error; - } -#endif - - return; - -error: - __jffs2_dbg_dump_node_refs_nolock(c, jeb); - __jffs2_dbg_dump_jeb_nolock(jeb); - __jffs2_dbg_dump_block_lists_nolock(c); - BUG(); - -} -#endif /* JFFS2_DBG_PARANOIA_CHECKS */ - -#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) -/* - * Dump the node_refs of the 'jeb' JFFS2 eraseblock. - */ -void -__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - spin_lock(&c->erase_completion_lock); - __jffs2_dbg_dump_node_refs_nolock(c, jeb); - spin_unlock(&c->erase_completion_lock); -} - -void -__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - struct jffs2_raw_node_ref *ref; - int i = 0; - - JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset); - if (!jeb->first_node) { - JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset); - return; - } - - printk(JFFS2_DBG_LVL); - for (ref = jeb->first_node; ; ref = ref->next_phys) { - printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); - if (ref->next_phys) - printk("->"); - else - break; - if (++i == 4) { - i = 0; - printk("\n" JFFS2_DBG_LVL); - } - } - printk("\n"); -} - -/* - * Dump an eraseblock's space accounting. - */ -void -__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -{ - spin_lock(&c->erase_completion_lock); - __jffs2_dbg_dump_jeb_nolock(jeb); - spin_unlock(&c->erase_completion_lock); -} - -void -__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb) -{ - if (!jeb) - return; - - JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n", - jeb->offset); - - printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size); - printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size); - printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size); - printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size); - printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size); -} - -void -__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) -{ - spin_lock(&c->erase_completion_lock); - __jffs2_dbg_dump_block_lists_nolock(c); - spin_unlock(&c->erase_completion_lock); -} - -void -__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) -{ - JFFS2_DEBUG("dump JFFS2 blocks lists:\n"); - - printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size); - printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size); - printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size); - printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size); - printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size); - printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size); - printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size); - printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size); - printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size); - printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n", - c->sector_size * c->resv_blocks_write); - - if (c->nextblock) - printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - c->nextblock->offset, c->nextblock->used_size, - c->nextblock->dirty_size, c->nextblock->wasted_size, - c->nextblock->unchecked_size, c->nextblock->free_size); - else - printk(JFFS2_DBG_LVL "nextblock: NULL\n"); - - if (c->gcblock) - printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, - c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); - else - printk(JFFS2_DBG_LVL "gcblock: NULL\n"); - - if (list_empty(&c->clean_list)) { - printk(JFFS2_DBG_LVL "clean_list: empty\n"); - } else { - struct list_head *this; - int numblocks = 0; - uint32_t dirty = 0; - - list_for_each(this, &c->clean_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - numblocks ++; - dirty += jeb->wasted_size; - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - - printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n", - numblocks, dirty, dirty / numblocks); - } - - if (list_empty(&c->very_dirty_list)) { - printk(JFFS2_DBG_LVL "very_dirty_list: empty\n"); - } else { - struct list_head *this; - int numblocks = 0; - uint32_t dirty = 0; - - list_for_each(this, &c->very_dirty_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - numblocks ++; - dirty += jeb->dirty_size; - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - - printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n", - numblocks, dirty, dirty / numblocks); - } - - if (list_empty(&c->dirty_list)) { - printk(JFFS2_DBG_LVL "dirty_list: empty\n"); - } else { - struct list_head *this; - int numblocks = 0; - uint32_t dirty = 0; - - list_for_each(this, &c->dirty_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - numblocks ++; - dirty += jeb->dirty_size; - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - - printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n", - numblocks, dirty, dirty / numblocks); - } - - if (list_empty(&c->erasable_list)) { - printk(JFFS2_DBG_LVL "erasable_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasable_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - } - - if (list_empty(&c->erasing_list)) { - printk(JFFS2_DBG_LVL "erasing_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasing_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - } - - if (list_empty(&c->erase_pending_list)) { - printk(JFFS2_DBG_LVL "erase_pending_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erase_pending_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - } - - if (list_empty(&c->erasable_pending_wbuf_list)) { - printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasable_pending_wbuf_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, " - "wasted %#08x, unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - } - - if (list_empty(&c->free_list)) { - printk(JFFS2_DBG_LVL "free_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->free_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - } - - if (list_empty(&c->bad_list)) { - printk(JFFS2_DBG_LVL "bad_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->bad_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - } - - if (list_empty(&c->bad_used_list)) { - printk(JFFS2_DBG_LVL "bad_used_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->bad_used_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - - if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); - } - } - } -} - -void -__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) -{ - down(&f->sem); - jffs2_dbg_dump_fragtree_nolock(f); - up(&f->sem); -} - -void -__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f) -{ - struct jffs2_node_frag *this = frag_first(&f->fragtree); - uint32_t lastofs = 0; - int buggy = 0; - - JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino); - while(this) { - if (this->node) - printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), " - "right (%p), parent (%p)\n", - this->ofs, this->ofs+this->size, ref_offset(this->node->raw), - ref_flags(this->node->raw), this, frag_left(this), frag_right(this), - frag_parent(this)); - else - printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", - this->ofs, this->ofs+this->size, this, frag_left(this), - frag_right(this), frag_parent(this)); - if (this->ofs != lastofs) - buggy = 1; - lastofs = this->ofs + this->size; - this = frag_next(this); - } - - if (f->metadata) - printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); - - if (buggy) { - JFFS2_ERROR("frag tree got a hole in it.\n"); - BUG(); - } -} - -#define JFFS2_BUFDUMP_BYTES_PER_LINE 32 -void -__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) -{ - int skip; - int i; - - JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n", - offs, offs + len, len); - i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; - offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); - - if (skip != 0) - printk(JFFS2_DBG_LVL "%#08x: ", offs); - - while (skip--) - printk(" "); - - while (i < len) { - if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) { - if (i != 0) - printk("\n"); - offs += JFFS2_BUFDUMP_BYTES_PER_LINE; - printk(JFFS2_DBG_LVL "%0#8x: ", offs); - } - - printk("%02x ", buf[i]); - - i += 1; - } - - printk("\n"); -} - -/* - * Dump a JFFS2 node. - */ -void -__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) -{ - union jffs2_node_union node; - int len = sizeof(union jffs2_node_union); - size_t retlen; - uint32_t crc; - int ret; - - JFFS2_DEBUG("dump node at offset %#08x.\n", ofs); - - ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); - if (ret || (retlen != len)) { - JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n", - len, ret, retlen); - return; - } - - printk(JFFS2_DBG_LVL "magic:\t%#04x\n", - je16_to_cpu(node.u.magic)); - printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n", - je16_to_cpu(node.u.nodetype)); - printk(JFFS2_DBG_LVL "totlen:\t%#08x\n", - je32_to_cpu(node.u.totlen)); - printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n", - je32_to_cpu(node.u.hdr_crc)); - - crc = crc32(0, &node.u, sizeof(node.u) - 4); - if (crc != je32_to_cpu(node.u.hdr_crc)) { - JFFS2_ERROR("wrong common header CRC.\n"); - return; - } - - if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK && - je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK) - { - JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n", - je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK); - return; - } - - switch(je16_to_cpu(node.u.nodetype)) { - - case JFFS2_NODETYPE_INODE: - - printk(JFFS2_DBG_LVL "the node is inode node\n"); - printk(JFFS2_DBG_LVL "ino:\t%#08x\n", - je32_to_cpu(node.i.ino)); - printk(JFFS2_DBG_LVL "version:\t%#08x\n", - je32_to_cpu(node.i.version)); - printk(JFFS2_DBG_LVL "mode:\t%#08x\n", - node.i.mode.m); - printk(JFFS2_DBG_LVL "uid:\t%#04x\n", - je16_to_cpu(node.i.uid)); - printk(JFFS2_DBG_LVL "gid:\t%#04x\n", - je16_to_cpu(node.i.gid)); - printk(JFFS2_DBG_LVL "isize:\t%#08x\n", - je32_to_cpu(node.i.isize)); - printk(JFFS2_DBG_LVL "atime:\t%#08x\n", - je32_to_cpu(node.i.atime)); - printk(JFFS2_DBG_LVL "mtime:\t%#08x\n", - je32_to_cpu(node.i.mtime)); - printk(JFFS2_DBG_LVL "ctime:\t%#08x\n", - je32_to_cpu(node.i.ctime)); - printk(JFFS2_DBG_LVL "offset:\t%#08x\n", - je32_to_cpu(node.i.offset)); - printk(JFFS2_DBG_LVL "csize:\t%#08x\n", - je32_to_cpu(node.i.csize)); - printk(JFFS2_DBG_LVL "dsize:\t%#08x\n", - je32_to_cpu(node.i.dsize)); - printk(JFFS2_DBG_LVL "compr:\t%#02x\n", - node.i.compr); - printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n", - node.i.usercompr); - printk(JFFS2_DBG_LVL "flags:\t%#04x\n", - je16_to_cpu(node.i.flags)); - printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n", - je32_to_cpu(node.i.data_crc)); - printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", - je32_to_cpu(node.i.node_crc)); - crc = crc32(0, &node.i, sizeof(node.i) - 8); - if (crc != je32_to_cpu(node.i.node_crc)) { - JFFS2_ERROR("wrong node header CRC.\n"); - return; - } - break; - - case JFFS2_NODETYPE_DIRENT: - - printk(JFFS2_DBG_LVL "the node is dirent node\n"); - printk(JFFS2_DBG_LVL "pino:\t%#08x\n", - je32_to_cpu(node.d.pino)); - printk(JFFS2_DBG_LVL "version:\t%#08x\n", - je32_to_cpu(node.d.version)); - printk(JFFS2_DBG_LVL "ino:\t%#08x\n", - je32_to_cpu(node.d.ino)); - printk(JFFS2_DBG_LVL "mctime:\t%#08x\n", - je32_to_cpu(node.d.mctime)); - printk(JFFS2_DBG_LVL "nsize:\t%#02x\n", - node.d.nsize); - printk(JFFS2_DBG_LVL "type:\t%#02x\n", - node.d.type); - printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", - je32_to_cpu(node.d.node_crc)); - printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n", - je32_to_cpu(node.d.name_crc)); - - node.d.name[node.d.nsize] = '\0'; - printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name); - - crc = crc32(0, &node.d, sizeof(node.d) - 8); - if (crc != je32_to_cpu(node.d.node_crc)) { - JFFS2_ERROR("wrong node header CRC.\n"); - return; - } - break; - - default: - printk(JFFS2_DBG_LVL "node type is unknown\n"); - break; - } -} -#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */ diff --git a/components/dfs/filesystems/jffs2/src/debug.h b/components/dfs/filesystems/jffs2/src/debug.h deleted file mode 100644 index 652f59068d..0000000000 --- a/components/dfs/filesystems/jffs2/src/debug.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: debug.h,v 1.1 2005/07/30 15:30:42 asl Exp $ - * - */ -#ifndef _JFFS2_DEBUG_H_ -#define _JFFS2_DEBUG_H_ -#include "jffs2_config.h" -#include - -#ifndef CONFIG_JFFS2_FS_DEBUG -#define CONFIG_JFFS2_FS_DEBUG 0 -#endif - -#if CONFIG_JFFS2_FS_DEBUG == 1 -/* Enable "paranoia" checks and dumps */ -#define JFFS2_DBG_PARANOIA_CHECKS -#define JFFS2_DBG_DUMPS -#define JFFS2_DBG_READINODE_MESSAGES -#define JFFS2_DBG_FRAGTREE_MESSAGES -#define JFFS2_DBG_DENTLIST_MESSAGES -#define JFFS2_DBG_NODEREF_MESSAGES -#define JFFS2_DBG_INOCACHE_MESSAGES -#endif - -#if CONFIG_JFFS2_FS_DEBUG == 2 -#define JFFS2_DBG_FRAGTREE2_MESSAGES -#endif - -/* Enable JFFS2 sanity checks by default */ -#define JFFS2_DBG_SANITY_CHECKS - -/* - * Dx() are mainly used for debugging messages, they must go away and be - * superseded by nicer JFFS2_DBG_XXX() macros... - */ -#if CONFIG_JFFS2_FS_DEBUG > 0 -#define D1(x) x -#else -#define D1(x) -#endif - -#if CONFIG_JFFS2_FS_DEBUG > 1 -#define D2(x) x -#else -#define D2(x) -#endif - -/* The prefixes of JFFS2 messages */ -#define JFFS2_DBG_MSG_PREFIX "[JFFS2 DBG]" -#define JFFS2_ERR_MSG_PREFIX "JFFS2 error: " -#define JFFS2_WARN_MSG_PREFIX "JFFS2 warning: " -#define JFFS2_NOTICE_MSG_PREFIX "JFFS2 notice: " - -#define JFFS2_ERR_LVL KERN_ERR -#define JFFS2_WARN_LVL KERN_WARNING -#define JFFS2_NOTICE_LVL KERN_NOTICE -#define JFFS2_DBG_LVL KERN_DEBUG - -/* JFFS2 message macros */ -#define JFFS2_ERROR(fmt, ...) \ - do { \ - printk(JFFS2_ERR_LVL JFFS2_ERR_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ - } while(0) - -#define JFFS2_WARNING(fmt, ...) \ - do { \ - printk(JFFS2_WARN_LVL JFFS2_WARN_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ - } while(0) - -#define JFFS2_NOTICE(fmt, ...) \ - do { \ - printk(JFFS2_NOTICE_LVL JFFS2_NOTICE_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ - } while(0) - -#define JFFS2_DEBUG(fmt, ...) \ - do { \ - printk(JFFS2_DBG_LVL JFFS2_DBG_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ - } while(0) - -/* - * We split our debugging messages on several parts, depending on the JFFS2 - * subsystem the message belongs to. - */ -/* Read inode debugging messages */ -#ifdef JFFS2_DBG_READINODE_MESSAGES -#define JFFS2_DBG_READINODE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_READINODE(fmt, ...) -#endif - -/* Fragtree build debugging messages */ -#ifdef JFFS2_DBG_FRAGTREE_MESSAGES -#define JFFS2_DBG_FRAGTREE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_FRAGTREE(fmt, ...) -#endif - -/* Directory entry list manilulation debugging messages */ -#ifdef JFFS2_DBG_DENTLIST_MESSAGES -#define JFFS2_DBG_DENTLIST(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_DENTLIST(fmt, ...) -#endif -#ifdef JFFS2_DBG_FRAGTREE2_MESSAGES -#define JFFS2_DBG_FRAGTREE2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_FRAGTREE2(fmt, ...) -#endif - -/* Print the messages about manipulating node_refs */ -#ifdef JFFS2_DBG_NODEREF_MESSAGES -#define JFFS2_DBG_NODEREF(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_NODEREF(fmt, ...) -#endif - -/* Manipulations with the list of inodes (JFFS2 inocache) */ -#ifdef JFFS2_DBG_INOCACHE_MESSAGES -#define JFFS2_DBG_INOCACHE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_INOCACHE(fmt, ...) -#endif - -/* Watch the object allocations */ -#ifdef JFFS2_DBG_MEMALLOC_MESSAGES -#define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_MEMALLOC(fmt, ...) -#endif - - -/* "Paranoia" checks */ -void -__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f); -void -__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f); -void -__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb); -void -__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb); -void -__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, - uint32_t ofs, int len); - -/* "Dump" functions */ -void -__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -void -__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb); -void -__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c); -void -__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c); -void -__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb); -void -__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb); -void -__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f); -void -__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f); -void -__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs); -void -__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs); - -#ifdef JFFS2_DBG_PARANOIA_CHECKS -#define jffs2_dbg_fragtree_paranoia_check(f) \ - __jffs2_dbg_fragtree_paranoia_check(f) -#define jffs2_dbg_fragtree_paranoia_check_nolock(f) \ - __jffs2_dbg_fragtree_paranoia_check_nolock(f) -#define jffs2_dbg_acct_paranoia_check(c, jeb) \ - __jffs2_dbg_acct_paranoia_check(c,jeb) -#define jffs2_dbg_acct_paranoia_check_nolock(c, jeb) \ - __jffs2_dbg_acct_paranoia_check_nolock(c,jeb) -#define jffs2_dbg_prewrite_paranoia_check(c, ofs, len) \ - __jffs2_dbg_prewrite_paranoia_check(c, ofs, len) -#else -#define jffs2_dbg_fragtree_paranoia_check(f) -#define jffs2_dbg_fragtree_paranoia_check_nolock(f) -#define jffs2_dbg_acct_paranoia_check(c, jeb) -#define jffs2_dbg_acct_paranoia_check_nolock(c, jeb) -#define jffs2_dbg_prewrite_paranoia_check(c, ofs, len) -#endif /* !JFFS2_PARANOIA_CHECKS */ - -#ifdef JFFS2_DBG_DUMPS -#define jffs2_dbg_dump_jeb(c, jeb) \ - __jffs2_dbg_dump_jeb(c, jeb); -#define jffs2_dbg_dump_jeb_nolock(jeb) \ - __jffs2_dbg_dump_jeb_nolock(jeb); -#define jffs2_dbg_dump_block_lists(c) \ - __jffs2_dbg_dump_block_lists(c) -#define jffs2_dbg_dump_block_lists_nolock(c) \ - __jffs2_dbg_dump_block_lists_nolock(c) -#define jffs2_dbg_dump_fragtree(f) \ - __jffs2_dbg_dump_fragtree(f); -#define jffs2_dbg_dump_fragtree_nolock(f) \ - __jffs2_dbg_dump_fragtree_nolock(f); -#define jffs2_dbg_dump_buffer(buf, len, offs) \ - __jffs2_dbg_dump_buffer(*buf, len, offs); -#define jffs2_dbg_dump_node(c, ofs) \ - __jffs2_dbg_dump_node(c, ofs); -#else -#define jffs2_dbg_dump_jeb(c, jeb) -#define jffs2_dbg_dump_jeb_nolock(jeb) -#define jffs2_dbg_dump_block_lists(c) -#define jffs2_dbg_dump_block_lists_nolock(c) -#define jffs2_dbg_dump_fragtree(f) -#define jffs2_dbg_dump_fragtree_nolock(f) -#define jffs2_dbg_dump_buffer(buf, len, offs) -#define jffs2_dbg_dump_node(c, ofs) -#endif /* !JFFS2_DBG_DUMPS */ - -/* - * Sanity checks are supposed to be light-weight and enabled by default. - */ -#ifdef JFFS2_DBG_SANITY_CHECKS -/* - * Check the space accounting of the file system and of - * the JFFS2 erasable block 'jeb'. - */ -static inline void -jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - if (unlikely(jeb && jeb->used_size + jeb->dirty_size + - jeb->free_size + jeb->wasted_size + - jeb->unchecked_size != c->sector_size)) { - JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset); - JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked " - "%#08x != total %#08x.\n", jeb->free_size, jeb->dirty_size, jeb->used_size, - jeb->wasted_size, jeb->unchecked_size, c->sector_size); - BUG(); - } - - if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size - + c->wasted_size + c->unchecked_size != c->flash_size)) { - JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n"); - JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + " - "wasted %#08x + unchecked %#08x != total %#08x.\n", - c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, - c->wasted_size, c->unchecked_size, c->flash_size); - BUG(); - } -} - -static inline void -jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - spin_lock(&c->erase_completion_lock); - jffs2_dbg_acct_sanity_check_nolock(c, jeb); - spin_unlock(&c->erase_completion_lock); -} -#else -#define jffs2_dbg_acct_sanity_check(c, jeb) -#define jffs2_dbg_acct_sanity_check_nolock(c, jeb) -#endif /* !JFFS2_DBG_SANITY_CHECKS */ - -#endif /* _JFFS2_DEBUG_H_ */ diff --git a/components/dfs/filesystems/jffs2/src/dir-ecos.c b/components/dfs/filesystems/jffs2/src/dir-ecos.c deleted file mode 100644 index b52b89928f..0000000000 --- a/components/dfs/filesystems/jffs2/src/dir-ecos.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Free Software Foundation, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: dir-ecos.c,v 1.11 2005/02/08 19:36:27 lunn Exp $ - * - */ - -#include -#include -#include "nodelist.h" - -/***********************************************************************/ - -/* Takes length argument because it can be either NUL-terminated or '/'-terminated */ -struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, int namelen) -{ - struct jffs2_inode_info *dir_f; - struct jffs2_full_dirent *fd = NULL, *fd_list; - uint32_t ino = 0; - uint32_t hash = full_name_hash(d_name, namelen); - struct _inode *inode = NULL; - - D1(printk("jffs2_lookup()\n")); - - dir_f = JFFS2_INODE_INFO(dir_i); - - down(&dir_f->sem); - - /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ - for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= hash; fd_list = fd_list->next) { - if (fd_list->nhash == hash && - (!fd || fd_list->version > fd->version) && - strlen((char *)fd_list->name) == namelen && - !strncmp((char *)fd_list->name, (char *)d_name, namelen)) { - fd = fd_list; - } - } - if (fd) - ino = fd->ino; - up(&dir_f->sem); - if (ino) { - inode = jffs2_iget(dir_i->i_sb, ino); - if (IS_ERR(inode)) { - printk("jffs2_iget() failed for ino #%u\n", ino); - return inode; - } - } - - return inode; -} - -/***********************************************************************/ - - - -int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode, - struct _inode **new_i) -{ - struct jffs2_raw_inode *ri; - struct jffs2_inode_info *f, *dir_f; - struct jffs2_sb_info *c; - struct _inode *inode; - int ret; - - ri = jffs2_alloc_raw_inode(); - if (!ri) - return -ENOMEM; - - c = JFFS2_SB_INFO(dir_i->i_sb); - - D1(printk(KERN_DEBUG "jffs2_create()\n")); - - inode = jffs2_new_inode(dir_i, mode, ri); - - if (IS_ERR(inode)) { - D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n")); - jffs2_free_raw_inode(ri); - return PTR_ERR(inode); - } - - f = JFFS2_INODE_INFO(inode); - dir_f = JFFS2_INODE_INFO(dir_i); - - ret = jffs2_do_create(c, dir_f, f, ri, - (const char *)d_name, - strlen((char *)d_name)); - - if (ret) { - inode->i_nlink = 0; - jffs2_iput(inode); - jffs2_free_raw_inode(ri); - return ret; - } - - jffs2_free_raw_inode(ri); - - D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n", - inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink)); - *new_i = inode; - return 0; -} - -/***********************************************************************/ - - -int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name) -{ - struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); - struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); - struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode); - int ret; - - ret = jffs2_do_unlink(c, dir_f, (const char *)d_name, - strlen((char *)d_name), dead_f); - if (dead_f->inocache) - d_inode->i_nlink = dead_f->inocache->nlink; - return ret; -} -/***********************************************************************/ - - -int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name) -{ - struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb); - struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode); - struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); - int ret; - - /* XXX: This is ugly */ - uint8_t type = (old_d_inode->i_mode & S_IFMT) >> 12; - if (!type) type = DT_REG; - - ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, - (const char * )d_name, - strlen((char *)d_name)); - - if (!ret) { - down(&f->sem); - old_d_inode->i_nlink = ++f->inocache->nlink; - up(&f->sem); - } - return ret; -} - -int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode) -{ - struct jffs2_inode_info *f, *dir_f; - struct jffs2_sb_info *c; - struct _inode *inode; - struct jffs2_raw_inode *ri; - struct jffs2_raw_dirent *rd; - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - int namelen; - uint32_t alloclen, phys_ofs; - int ret; - - mode |= S_IFDIR; - - ri = jffs2_alloc_raw_inode(); - if (!ri) - return -ENOMEM; - - c = JFFS2_SB_INFO(dir_i->i_sb); - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though - */ - namelen = strlen((char *)d_name); - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); - - if (ret) { - jffs2_free_raw_inode(ri); - return ret; - } - - inode = jffs2_new_inode(dir_i, mode, ri); - - if (IS_ERR(inode)) { - jffs2_free_raw_inode(ri); - jffs2_complete_reservation(c); - return PTR_ERR(inode); - } - - f = JFFS2_INODE_INFO(inode); - - ri->data_crc = cpu_to_je32(0); - ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - - fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_inode(ri); - - if (IS_ERR(fn)) { - /* Eeek. Wave bye bye */ - up(&f->sem); - jffs2_complete_reservation(c); - inode->i_nlink = 0; - jffs2_iput(inode); - return PTR_ERR(fn); - } - /* No data here. Only a metadata node, which will be - obsoleted by the first data write - */ - f->metadata = fn; - up(&f->sem); - - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { - /* Eep. */ - inode->i_nlink = 0; - jffs2_iput(inode); - return ret; - } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { - /* Argh. Now we treat it like a normal delete */ - jffs2_complete_reservation(c); - inode->i_nlink = 0; - jffs2_iput(inode); - return -ENOMEM; - } - - dir_f = JFFS2_INODE_INFO(dir_i); - down(&dir_f->sem); - - rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); - rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - - rd->pino = cpu_to_je32(dir_i->i_ino); - rd->version = cpu_to_je32(++dir_f->highest_version); - rd->ino = cpu_to_je32(inode->i_ino); - rd->mctime = cpu_to_je32(jffs2_get_timestamp()); - rd->nsize = namelen; - rd->type = DT_DIR; - rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); - rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen)); - - fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL); - - jffs2_complete_reservation(c); - jffs2_free_raw_dirent(rd); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ - up(&dir_f->sem); - inode->i_nlink = 0; - jffs2_iput(inode); - return PTR_ERR(fd); - } - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); - up(&dir_f->sem); - - jffs2_iput(inode); - return 0; -} - -int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name) -{ - struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode); - struct jffs2_full_dirent *fd; - - for (fd = f->dents ; fd; fd = fd->next) { - if (fd->ino) - return EPERM; //-ENOTEMPTY; - } - return jffs2_unlink(dir_i, d_inode, d_name); -} - -int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, - struct _inode *new_dir_i, const unsigned char *new_d_name) -{ - int ret; - struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); - struct jffs2_inode_info *victim_f = NULL; - uint8_t type; - -#if 0 /* FIXME -- this really doesn't belong in individual file systems. - The fileio code ought to do this for us, or at least part of it */ - if (new_dentry->d_inode) { - if (S_ISDIR(d_inode->i_mode) && - !S_ISDIR(new_dentry->d_inode->i_mode)) { - /* Cannot rename directory over non-directory */ - return -EINVAL; - } - - victim_f = JFFS2_INODE_INFO(new_dentry->d_inode); - - if (S_ISDIR(new_dentry->d_inode->i_mode)) { - struct jffs2_full_dirent *fd; - - if (!S_ISDIR(d_inode->i_mode)) { - /* Cannot rename non-directory over directory */ - return -EINVAL; - } - down(&victim_f->sem); - for (fd = victim_f->dents; fd; fd = fd->next) { - if (fd->ino) { - up(&victim_f->sem); - return -ENOTEMPTY; - } - } - up(&victim_f->sem); - } - } -#endif - - /* XXX: We probably ought to alloc enough space for - both nodes at the same time. Writing the new link, - then getting -ENOSPC, is quite bad :) - */ - - /* Make a hard link */ - - /* XXX: This is ugly */ - type = (d_inode->i_mode & S_IFMT) >> 12; - if (!type) type = DT_REG; - - ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), - d_inode->i_ino, type, - (const char *)new_d_name, - strlen((char *)new_d_name)); - - if (ret) - return ret; - - if (victim_f) { - /* There was a victim. Kill it off nicely */ - /* Don't oops if the victim was a dirent pointing to an - inode which didn't exist. */ - if (victim_f->inocache) { - down(&victim_f->sem); - victim_f->inocache->nlink--; - up(&victim_f->sem); - } - } - - /* Unlink the original */ - ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), - (const char *)old_d_name, - strlen((char *)old_d_name), NULL); - - if (ret) { - /* Oh shit. We really ought to make a single node which can do both atomically */ - struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode); - down(&f->sem); - if (f->inocache) - d_inode->i_nlink = f->inocache->nlink++; - up(&f->sem); - - printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); - } - return ret; -} - diff --git a/components/dfs/filesystems/jffs2/src/dir.txt b/components/dfs/filesystems/jffs2/src/dir.txt deleted file mode 100644 index 93767aa2ba..0000000000 --- a/components/dfs/filesystems/jffs2/src/dir.txt +++ /dev/null @@ -1,70 +0,0 @@ -ÎÄĽţĽĐ PATH Áбí -ľíĐňÁĐşĹÎŞ 00000200 38BE:1B05 -F:. -jffs2/dfs_jffs2.c -jffs2/porting.c - -adler32.c - -compress.c -configure -deflate.c - -example.c - -gzio.c - -infback.c -infblock.c - -inffast.c - - -inflate.c - -inftrees.c - -infutil.c - - - - -maketree.c - -minigzip.c - - -trees.c - -uncompr.c - -zutil.c - - -jffs2/crc/crcd -jffs2/crc/crc16.c -jffs2/crc/crc32.c -jffs2/crc/posix_crc.c - -jffs2/kernel/rbtree.c - -jffs2/src/build.c -jffs2/src/compr.c -jffs2/src/compr_rtime.c -jffs2/src/compr_rubin.c -jffs2/src/compr_zlib.c -jffs2/src/debug.c -jffs2/src/dir-ecos.c -jffs2/src/erase.c -jffs2/src/flashio.c -jffs2/src/fs-ecos.c -jffs2/src/gc.c -jffs2/src/gcthread.c -jffs2/src/malloc-ecos.c -jffs2/src/nodelist.c -jffs2/src/nodemgmt.c -jffs2/src/read.c -jffs2/src/readinode.c -jffs2/src/scan.c -jffs2/src/write.c - diff --git a/components/dfs/filesystems/jffs2/src/erase.c b/components/dfs/filesystems/jffs2/src/erase.c deleted file mode 100644 index 3844e1d389..0000000000 --- a/components/dfs/filesystems/jffs2/src/erase.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: erase.c,v 1.83 2005/07/22 10:32:08 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "nodelist.h" - -struct erase_priv_struct { - struct jffs2_eraseblock *jeb; - struct jffs2_sb_info *c; -}; - -#ifndef __ECOS -static void jffs2_erase_callback(struct erase_info *); -#endif -static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); -static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); - -static void jffs2_erase_block(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - int ret; - uint32_t bad_offset; -#ifdef __ECOS - ret = jffs2_flash_erase(c, jeb); - if (!ret) { - jffs2_erase_succeeded(c, jeb); - return; - } - bad_offset = jeb->offset; -#else /* Linux */ - struct erase_info *instr; - - D1(printk(KERN_DEBUG "jffs2_erase_block(): erase block %#08x (range %#08x-%#08x)\n", - jeb->offset, jeb->offset, jeb->offset + c->sector_size)); - instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL); - if (!instr) { - printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); - spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add(&jeb->list, &c->erase_pending_list); - c->erasing_size -= c->sector_size; - c->dirty_size += c->sector_size; - jeb->dirty_size = c->sector_size; - spin_unlock(&c->erase_completion_lock); - return; - } - - memset(instr, 0, sizeof(*instr)); - - instr->mtd = c->mtd; - instr->addr = jeb->offset; - instr->len = c->sector_size; - instr->callback = jffs2_erase_callback; - instr->priv = (unsigned long)(&instr[1]); - instr->fail_addr = 0xffffffff; - - ((struct erase_priv_struct *)instr->priv)->jeb = jeb; - ((struct erase_priv_struct *)instr->priv)->c = c; - - ret = c->mtd->erase(c->mtd, instr); - if (!ret) - return; - - bad_offset = instr->fail_addr; - kfree(instr); -#endif /* __ECOS */ - - if (ret == -ENOMEM || ret == -EAGAIN) { - /* Erase failed immediately. Refile it on the list */ - D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret)); - spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add(&jeb->list, &c->erase_pending_list); - c->erasing_size -= c->sector_size; - c->dirty_size += c->sector_size; - jeb->dirty_size = c->sector_size; - spin_unlock(&c->erase_completion_lock); - return; - } - - if (ret == -EROFS) - printk(KERN_WARNING "Erase at 0x%08x failed immediately: -EROFS. Is the sector locked?\n", jeb->offset); - else - printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); - - jffs2_erase_failed(c, jeb, bad_offset); -} - -void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) -{ - struct jffs2_eraseblock *jeb; - - down(&c->erase_free_sem); - - spin_lock(&c->erase_completion_lock); - - while (!list_empty(&c->erase_complete_list) || - !list_empty(&c->erase_pending_list)) { - - if (!list_empty(&c->erase_complete_list)) { - jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); - list_del(&jeb->list); - spin_unlock(&c->erase_completion_lock); - jffs2_mark_erased_block(c, jeb); - - if (!--count) { - D1(printk(KERN_DEBUG "Count reached. jffs2_erase_pending_blocks leaving\n")); - goto done; - } - - } else if (!list_empty(&c->erase_pending_list)) { - jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); - D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); - list_del(&jeb->list); - c->erasing_size += c->sector_size; - c->wasted_size -= jeb->wasted_size; - c->free_size -= jeb->free_size; - c->used_size -= jeb->used_size; - c->dirty_size -= jeb->dirty_size; - jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0; - jffs2_free_all_node_refs(c, jeb); - list_add(&jeb->list, &c->erasing_list); - spin_unlock(&c->erase_completion_lock); - - jffs2_erase_block(c, jeb); - - } else { - BUG(); - } - - /* Be nice */ - cond_resched(); - spin_lock(&c->erase_completion_lock); - } - - spin_unlock(&c->erase_completion_lock); - done: - D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); - - up(&c->erase_free_sem); -} - -static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -{ - D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); - spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add_tail(&jeb->list, &c->erase_complete_list); - spin_unlock(&c->erase_completion_lock); - /* Ensure that kupdated calls us again to mark them clean */ - jffs2_erase_pending_trigger(c); -} - -static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset) -{ - /* For NAND, if the failure did not occur at the device level for a - specific physical page, don't bother updating the bad block table. */ - if (jffs2_cleanmarker_oob(c) && (bad_offset != 0xffffffff)) { - /* We had a device-level failure to erase. Let's see if we've - failed too many times. */ - if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) { - /* We'd like to give this block another try. */ - spin_lock(&c->erase_completion_lock); - list_del(&jeb->list); - list_add(&jeb->list, &c->erase_pending_list); - c->erasing_size -= c->sector_size; - c->dirty_size += c->sector_size; - jeb->dirty_size = c->sector_size; - spin_unlock(&c->erase_completion_lock); - return; - } - } - - spin_lock(&c->erase_completion_lock); - c->erasing_size -= c->sector_size; - c->bad_size += c->sector_size; - list_del(&jeb->list); - list_add(&jeb->list, &c->bad_list); - c->nr_erasing_blocks--; - spin_unlock(&c->erase_completion_lock); - wake_up(&c->erase_wait); -} - -#ifndef __ECOS -static void jffs2_erase_callback(struct erase_info *instr) -{ - struct erase_priv_struct *priv = (void *)instr->priv; - - if(instr->state != MTD_ERASE_DONE) { - printk(KERN_WARNING "Erase at 0x%08x finished, but state != MTD_ERASE_DONE. State is 0x%x instead.\n", instr->addr, instr->state); - jffs2_erase_failed(priv->c, priv->jeb, instr->fail_addr); - } else { - jffs2_erase_succeeded(priv->c, priv->jeb); - } - kfree(instr); -} -#endif /* !__ECOS */ - -/* Hmmm. Maybe we should accept the extra space it takes and make - this a standard doubly-linked list? */ -static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, struct jffs2_eraseblock *jeb) -{ - struct jffs2_inode_cache *ic = NULL; - struct jffs2_raw_node_ref **prev; - - prev = &ref->next_in_ino; - - /* Walk the inode's list once, removing any nodes from this eraseblock */ - while (1) { - if (!(*prev)->next_in_ino) { - /* We're looking at the jffs2_inode_cache, which is - at the end of the linked list. Stash it and continue - from the beginning of the list */ - ic = (struct jffs2_inode_cache *)(*prev); - prev = &ic->nodes; - continue; - } - - if (SECTOR_ADDR((*prev)->flash_offset) == jeb->offset) { - /* It's in the block we're erasing */ - struct jffs2_raw_node_ref *this; - - this = *prev; - *prev = this->next_in_ino; - this->next_in_ino = NULL; - - if (this == ref) - break; - - continue; - } - /* Not to be deleted. Skip */ - prev = &((*prev)->next_in_ino); - } - - /* PARANOIA */ - if (!ic) { - printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n"); - return; - } - - D1(printk(KERN_DEBUG "Removed nodes in range 0x%08x-0x%08x from ino #%u\n", - jeb->offset, jeb->offset + c->sector_size, ic->ino)); - - D2({ - int i=0; - struct jffs2_raw_node_ref *this; - printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); - - this = ic->nodes; - - while(this) { - printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); - if (++i == 5) { - printk("\n" KERN_DEBUG); - i=0; - } - this = this->next_in_ino; - } - printk("\n"); - }); - - if (ic->nodes == (void *)ic && ic->nlink == 0) - jffs2_del_ino_cache(c, ic); -} - -static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) -{ - struct jffs2_raw_node_ref *ref; - D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset)); - while(jeb->first_node) { - ref = jeb->first_node; - jeb->first_node = ref->next_phys; - - /* Remove from the inode-list */ - if (ref->next_in_ino) - jffs2_remove_node_refs_from_ino_list(c, ref, jeb); - /* else it was a non-inode node or already removed, so don't bother */ - - jffs2_free_raw_node_ref(ref); - } - jeb->last_node = NULL; -} - -static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset) -{ - void *ebuf; - uint32_t ofs; - size_t retlen; - int ret = -EIO; - - ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ebuf) { - printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset); - return -EAGAIN; - } - - D1(printk(KERN_DEBUG "Verifying erase at 0x%08x\n", jeb->offset)); - - for (ofs = jeb->offset; ofs < jeb->offset + c->sector_size; ) { - uint32_t readlen = min((uint32_t)PAGE_SIZE, jeb->offset + c->sector_size - ofs); - int i; - - *bad_offset = ofs; - - ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); - if (ret) { - printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); - goto fail; - } - if (retlen != readlen) { - printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen); - goto fail; - } - for (i=0; ioffset)); - bad_offset = jeb->offset; - - /* Cleanmarker in oob area or no cleanmarker at all ? */ - if (jffs2_cleanmarker_oob(c) || c->cleanmarker_size == 0) { - - if (jffs2_cleanmarker_oob(c)) { - if (jffs2_write_nand_cleanmarker(c, jeb)) - goto filebad; - } - - jeb->first_node = jeb->last_node = NULL; - jeb->free_size = c->sector_size; - jeb->used_size = 0; - jeb->dirty_size = 0; - jeb->wasted_size = 0; - - } else { - - struct kvec vecs[1]; - #if defined (__GNUC__) - struct jffs2_unknown_node marker = { - .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), - .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), - .totlen = cpu_to_je32(c->cleanmarker_size) - }; - #elif defined (MSVC) - struct jffs2_unknown_node marker = { - cpu_to_je16(JFFS2_MAGIC_BITMASK), - cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), - cpu_to_je32(c->cleanmarker_size), - 0 - }; - #else - #endif - - marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { - printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n"); - goto refile; - } - - marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); - - vecs[0].iov_base = (unsigned char *) ▮ - vecs[0].iov_len = sizeof(marker); - ret = jffs2_flash_direct_writev(c, vecs, 1, jeb->offset, &retlen); - - if (ret || retlen != sizeof(marker)) { - if (ret) - printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", - jeb->offset, ret); - else - printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", - jeb->offset, sizeof(marker), retlen); - - jffs2_free_raw_node_ref(marker_ref); - goto filebad; - } - - marker_ref->next_in_ino = NULL; - marker_ref->next_phys = NULL; - marker_ref->flash_offset = jeb->offset | REF_NORMAL; - marker_ref->__totlen = c->cleanmarker_size; - - jeb->first_node = jeb->last_node = marker_ref; - - jeb->free_size = c->sector_size - c->cleanmarker_size; - jeb->used_size = c->cleanmarker_size; - jeb->dirty_size = 0; - jeb->wasted_size = 0; - } - - spin_lock(&c->erase_completion_lock); - c->erasing_size -= c->sector_size; - c->free_size += jeb->free_size; - c->used_size += jeb->used_size; - - jffs2_dbg_acct_sanity_check_nolock(c,jeb); - jffs2_dbg_acct_paranoia_check_nolock(c, jeb); - - list_add_tail(&jeb->list, &c->free_list); - c->nr_erasing_blocks--; - c->nr_free_blocks++; - spin_unlock(&c->erase_completion_lock); - wake_up(&c->erase_wait); - return; - -filebad: - spin_lock(&c->erase_completion_lock); - /* Stick it on a list (any list) so erase_failed can take it - right off again. Silly, but shouldn't happen often. */ - list_add(&jeb->list, &c->erasing_list); - spin_unlock(&c->erase_completion_lock); - jffs2_erase_failed(c, jeb, bad_offset); - return; - -refile: - /* Stick it back on the list from whence it came and come back later */ - jffs2_erase_pending_trigger(c); - spin_lock(&c->erase_completion_lock); - list_add(&jeb->list, &c->erase_complete_list); - spin_unlock(&c->erase_completion_lock); - return; -} diff --git a/components/dfs/filesystems/jffs2/src/flashio.c b/components/dfs/filesystems/jffs2/src/flashio.c deleted file mode 100644 index 37c332de70..0000000000 --- a/components/dfs/filesystems/jffs2/src/flashio.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by Dominic Ostrowski - * Contributors: David Woodhouse, Nick Garnett, Richard Panton. - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: flashio.c,v 1.1 2003/11/26 14:09:29 dwmw2 Exp $ - * - */ - -#include -#include "nodelist.h" -#include - -int jffs2_flash_read(struct jffs2_sb_info * c, cyg_uint32 offset, - const size_t size, - size_t * return_size, - unsigned char *buffer) -{ - uint32_t len; - struct super_block *sb = OFNI_BS_2SFFJ(c); - - len = rt_mtd_nor_read(RT_MTD_NOR_DEVICE(sb->s_dev), offset, buffer, size); - if (len != size) - return -EIO; - - * return_size = len; - return ENOERR; -} - -int jffs2_flash_write(struct jffs2_sb_info * c, - cyg_uint32 offset, const size_t size, - size_t * return_size, unsigned char *buffer) -{ - uint32_t len; - struct super_block *sb = OFNI_BS_2SFFJ(c); - - len = rt_mtd_nor_write(RT_MTD_NOR_DEVICE(sb->s_dev), offset, buffer, size); - if (len != size) - return -EIO; - - * return_size = len; - return ENOERR; -} - -int jffs2_flash_erase(struct jffs2_sb_info * c, - struct jffs2_eraseblock * jeb) -{ - rt_err_t result; - struct super_block *sb = OFNI_BS_2SFFJ(c); - - result = rt_mtd_nor_erase_block(RT_MTD_NOR_DEVICE(sb->s_dev), jeb->offset, c->sector_size); - if (result != RT_EOK) - return -EIO; - - return ENOERR; -} - -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, - const struct iovec *vecs, unsigned long count, loff_t to, - size_t * retlen) -{ - unsigned long i; - size_t totlen = 0, thislen; - int ret = 0; - - for (i = 0; i < count; i++) - { - // writes need to be aligned but the data we're passed may not be - // Observation suggests most unaligned writes are small, so we - // optimize for that case. - - if (((vecs[i].iov_len & (sizeof(int) - 1))) || - (((unsigned long) vecs[i].iov_base & (sizeof(unsigned long) - 1)))) - { - // are there iov's after this one? Or is it so much we'd need - // to do multiple writes anyway? - if ((i + 1) < count || vecs[i].iov_len > 256) - { - // cop out and malloc - unsigned long j; - ssize_t sizetomalloc = 0, totvecsize = 0; - char *cbuf, *cbufptr; - - for (j = i; j < count; j++) - totvecsize += vecs[j].iov_len; - - // pad up in case unaligned - sizetomalloc = totvecsize + sizeof(int) - 1; - sizetomalloc &= ~(sizeof(int) - 1); - cbuf = (char *) rt_malloc(sizetomalloc); - // malloc returns aligned memory - if (!cbuf) - { - ret = -ENOMEM; - goto writev_out; - } - cbufptr = cbuf; - for (j = i; j < count; j++) - { - memcpy(cbufptr, vecs[j].iov_base, vecs[j].iov_len); - cbufptr += vecs[j].iov_len; - } - //rt_kprintf("direct_write: offset %d, size %d\n", to, sizetomalloc); - ret = jffs2_flash_write(c, to, sizetomalloc, &thislen, - (unsigned char *) cbuf); - if (thislen > totvecsize) // in case it was aligned up - thislen = totvecsize; - totlen += thislen; - rt_free(cbuf); - goto writev_out; - } - else - { - // otherwise optimize for the common case - int buf[256/sizeof(int)]; // int, so int aligned - size_t lentowrite; - - lentowrite = vecs[i].iov_len; - // pad up in case its unaligned - lentowrite += sizeof(int) - 1; - lentowrite &= ~(sizeof(int) - 1); - memcpy(buf, vecs[i].iov_base, lentowrite); - - //rt_kprintf("direct_write: offset %d, size %d\n", to, lentowrite); - ret = jffs2_flash_write(c, to, lentowrite, &thislen, - (unsigned char *) &buf); - if (thislen > vecs[i].iov_len) - thislen = vecs[i].iov_len; - } - } - else - { - //rt_kprintf("direct_writev: offset %d, size %d\n", to, vecs[i].iov_len); - ret = jffs2_flash_write(c, to, vecs[i].iov_len, &thislen, - vecs[i].iov_base); - } - totlen += thislen; - if (ret || thislen != vecs[i].iov_len) break; - to += vecs[i].iov_len; - } - -writev_out: - if (retlen) *retlen = totlen; - - return ret; -} diff --git a/components/dfs/filesystems/jffs2/src/fs-ecos.c b/components/dfs/filesystems/jffs2/src/fs-ecos.c deleted file mode 100644 index 814d2e3010..0000000000 --- a/components/dfs/filesystems/jffs2/src/fs-ecos.c +++ /dev/null @@ -1,2174 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Free Software Foundation, Inc. - * - * Created by Dominic Ostrowski - * Contributors: David Woodhouse, Nick Garnett, Richard Panton. - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: fs-ecos.c,v 1.44 2005/07/24 15:29:57 dedekind Exp $ - * - */ - -#include //prife for SEEK_SET SEEK_CUR SEEK_END -#include -#include "nodelist.h" -#include -#include -#include "compr.h" -#include - -#include - -//-------------------------------------------- -cyg_mtab_entry *cyg_cdir_mtab_entry = NULL; -cyg_dir cyg_cdir_dir = CYG_DIR_NULL; -//========================================================================== -// Default functions - -__externC int cyg_fileio_enosys() { return ENOSYS; } -__externC int cyg_fileio_erofs() { return EROFS; } -__externC int cyg_fileio_enoerr() { return ENOERR; } -__externC int cyg_fileio_enotdir() { return ENOTDIR; } - -__externC cyg_bool cyg_fileio_seltrue (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info) -{ return 1; } - -//-------------------------------------------- -//========================================================================== -// Forward definitions - -// Filesystem operations -int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte); -static int jffs2_umount(cyg_mtab_entry * mte); -int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - int mode, cyg_file * fte); -#ifdef CYGOPT_FS_JFFS2_WRITE -static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, - const char *name); -static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name); -static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name); -static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1, - const char *name1, cyg_dir dir2, const char *name2); -static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1, - cyg_dir dir2, const char *name2, int type); -#endif -static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - cyg_file * fte); -static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - cyg_dir * dir_out); -static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - struct stat *buf); -static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - int key, void *buf, int len); -static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - int key, void *buf, int len); - -// File operations -int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); -#ifdef CYGOPT_FS_JFFS2_WRITE -static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); -#endif -static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence); -static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, - CYG_ADDRWORD data); -static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode); -static int jffs2_fo_close(struct CYG_FILE_TAG *fp); -static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf); -static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, - int len); -static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, - int len); - -// Directory operations -static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); -static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence); - - -static int jffs2_read_inode (struct _inode *inode); -static void jffs2_clear_inode (struct _inode *inode); -static int jffs2_truncate_file (struct _inode *inode); - -//========================================================================== -// Filesystem table entries - -// ------------------------------------------------------------------------- -// Fstab entry. -// This defines the entry in the filesystem table. -// For simplicity we use _FILESYSTEM synchronization for all accesses since -// we should never block in any filesystem operations. - -#ifdef CYGOPT_FS_JFFS2_WRITE -FSTAB_ENTRY(jffs2_fste, "jffs2", 0, - CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM, - jffs2_mount, - jffs2_umount, - jffs2_open, - jffs2_ops_unlink, - jffs2_ops_mkdir, - jffs2_ops_rmdir, - jffs2_ops_rename, - jffs2_ops_link, - jffs2_opendir, - jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo); -#else -FSTAB_ENTRY(jffs2_fste, "jffs2", 0, - CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM, - jffs2_mount, - jffs2_umount, - jffs2_open, - (cyg_fsop_unlink *)cyg_fileio_erofs, - (cyg_fsop_mkdir *)cyg_fileio_erofs, - (cyg_fsop_rmdir *)cyg_fileio_erofs, - (cyg_fsop_rename *)cyg_fileio_erofs, - (cyg_fsop_link *)cyg_fileio_erofs, - jffs2_opendir, - jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo); -#endif - -// ------------------------------------------------------------------------- -// File operations. -// This set of file operations are used for normal open files. - -cyg_fileops jffs2_fileops = { - jffs2_fo_read, -#ifdef CYGOPT_FS_JFFS2_WRITE - jffs2_fo_write, -#else - (cyg_fileop_write *) cyg_fileio_erofs, -#endif - jffs2_fo_lseek, - jffs2_fo_ioctl, - cyg_fileio_seltrue, - jffs2_fo_fsync, - jffs2_fo_close, - jffs2_fo_fstat, - jffs2_fo_getinfo, - jffs2_fo_setinfo -}; - -// ------------------------------------------------------------------------- -// Directory file operations. -// This set of operations are used for open directories. Most entries -// point to error-returning stub functions. Only the read, lseek and -// close entries are functional. - -cyg_fileops jffs2_dirops = { - jffs2_fo_dirread, - (cyg_fileop_write *) cyg_fileio_enosys, - jffs2_fo_dirlseek, - (cyg_fileop_ioctl *) cyg_fileio_enosys, - cyg_fileio_seltrue, - (cyg_fileop_fsync *) cyg_fileio_enosys, - jffs2_fo_close, - (cyg_fileop_fstat *) cyg_fileio_enosys, - (cyg_fileop_getinfo *) cyg_fileio_enosys, - (cyg_fileop_setinfo *) cyg_fileio_enosys -}; - -//========================================================================== -// STATIC VARIABLES !!! - -static unsigned char gc_buffer[PAGE_CACHE_SIZE]; //avoids malloc when user may be under memory pressure -static unsigned char n_fs_mounted = 0; // a counter to track the number of jffs2 instances mounted - -//========================================================================== -// Directory operations - -struct jffs2_dirsearch { - struct _inode *dir; // directory to search - const unsigned char *path; // path to follow - struct _inode *node; // Node found - const unsigned char *name; // last name fragment used - int namelen; // name fragment length - cyg_bool last; // last name in path? -}; - -typedef struct jffs2_dirsearch jffs2_dirsearch; - -//========================================================================== -// Ref count and nlink management - - -// FIXME: This seems like real cruft. Wouldn't it be better just to do the -// right thing? -static void icache_evict(struct _inode *root_i, struct _inode *i) -{ - struct _inode *this = root_i, *next; - - restart: - D2(printf("icache_evict\n")); - // If this is an absolute search path from the root, - // remove all cached inodes with i_count of zero (these are only - // held where needed for dotdot filepaths) - while (this) { - next = this->i_cache_next; - if (this != i && this->i_count == 0) { - struct _inode *parent = this->i_parent; - if (this->i_cache_next) - this->i_cache_next->i_cache_prev = this->i_cache_prev; - if (this->i_cache_prev) - this->i_cache_prev->i_cache_next = this->i_cache_next; - jffs2_clear_inode(this); - memset(this, 0x5a, sizeof(*this)); - rt_free(this); - if (parent && parent != this) { - parent->i_count--; - this = root_i; - goto restart; - } - } - this = next; - } -} - -//========================================================================== -// Directory search - -// ------------------------------------------------------------------------- -// init_dirsearch() -// Initialize a dirsearch object to start a search - -static void init_dirsearch(jffs2_dirsearch * ds, - struct _inode *dir, const unsigned char *name) -{ - D2(printf("init_dirsearch name = %s\n", name)); - D2(printf("init_dirsearch dir = %x\n", dir)); - - dir->i_count++; - ds->dir = dir; - ds->path = name; - ds->node = dir; - ds->name = name; - ds->namelen = 0; - ds->last = false; -} - -// ------------------------------------------------------------------------- -// find_entry() -// Search a single directory for the next name in a path and update the -// dirsearch object appropriately. - -static int find_entry(jffs2_dirsearch * ds) -{ - struct _inode *dir = ds->dir; - const unsigned char *name = ds->path; - const unsigned char *n = name; - char namelen = 0; - struct _inode *d; - - D2(printf("find_entry\n")); - - // check that we really have a directory - if (!S_ISDIR(dir->i_mode)) - return ENOTDIR; - - // Isolate the next element of the path name. - while (*n != '\0' && *n != '/') - n++, namelen++; - - // Check if this is the last path element. - while( *n == '/') n++; - if (*n == '\0') - ds->last = true; - - // update name in dirsearch object - ds->name = name; - ds->namelen = namelen; - - if (name[0] == '.') - switch (namelen) { - default: - break; - case 2: - // Dot followed by not Dot, treat as any other name - if (name[1] != '.') - break; - // Dot Dot - // Move back up the search path - D2(printf("find_entry found ..\n")); - ds->dir = ds->node; - ds->node = ds->dir->i_parent; - ds->node->i_count++; - return ENOERR; - case 1: - // Dot is consumed - D2(printf("find_entry found .\n")); - ds->node = ds->dir; - ds->dir->i_count++; - return ENOERR; - } - - // Here we have the name and its length set up. - // Search the directory for a matching entry - - D2(printf("find_entry for name = %s\n", ds->path)); - d = jffs2_lookup(dir, name, namelen); - D2(printf("find_entry got dir = %x\n", d)); - - if (d == NULL) - return ENOENT; - if (IS_ERR(d)) - return -PTR_ERR(d); - - // If it's a new directory inode, increase refcount on its parent - if (S_ISDIR(d->i_mode) && !d->i_parent) { - d->i_parent = dir; - dir->i_count++; - } - - // pass back the node we have found - ds->node = d; - return ENOERR; - -} - -// ------------------------------------------------------------------------- -// jffs2_find() -// Main interface to directory search code. This is used in all file -// level operations to locate the object named by the pathname. - -// Returns with use count incremented on both the sought object and -// the directory it was found in -static int jffs2_find(jffs2_dirsearch * d) -{ - int err; - - D2(printf("jffs2_find for path =%s\n", d->path)); - - // Short circuit empty paths - if (*(d->path) == '\0') { - d->node->i_count++; - return ENOERR; - } - - // iterate down directory tree until we find the object - // we want. - for (;;) { - err = find_entry(d); - - if (err != ENOERR) - return err; - - if (d->last) - return ENOERR; - - /* We're done with it, although it we found a subdir that - will have caused the refcount to have been increased */ - jffs2_iput(d->dir); - - // Update dirsearch object to search next directory. - d->dir = d->node; - d->path += d->namelen; - while (*(d->path) == '/') - d->path++; // skip dirname separators - } -} - -//========================================================================== -// Pathconf support -// This function provides support for pathconf() and fpathconf(). - -static int jffs2_pathconf(struct _inode *node, struct cyg_pathconf_info *info) -{ - int err = ENOERR; - D2(printf("jffs2_pathconf\n")); - - switch (info->name) { - case _PC_LINK_MAX: - info->value = LINK_MAX; - break; - - case _PC_MAX_CANON: - info->value = -1; // not supported - err = EINVAL; - break; - - case _PC_MAX_INPUT: - info->value = -1; // not supported - err = EINVAL; - break; - - case _PC_NAME_MAX: - info->value = JFFS2_NAME_MAX; - break; - - case _PC_PATH_MAX: - info->value = JFFS2_PATH_MAX; - break; - - case _PC_PIPE_BUF: - info->value = -1; // not supported - err = EINVAL; - break; - - case _PC_ASYNC_IO: - info->value = -1; // not supported - err = EINVAL; - break; - - case _PC_CHOWN_RESTRICTED: - info->value = -1; // not supported - err = EINVAL; - break; - - case _PC_NO_TRUNC: - info->value = 0; - break; - - case _PC_PRIO_IO: - info->value = 0; - break; - - case _PC_SYNC_IO: - info->value = 0; - break; - - case _PC_VDISABLE: - info->value = -1; // not supported - err = EINVAL; - break; - - default: - err = EINVAL; - break; - } - - return err; -} - -//========================================================================== -// Filesystem operations -// ------------------------------------------------------------------------- -// jffs2_mount() -// Process a mount request. This mainly creates a root for the -// filesystem. -static int jffs2_read_super(struct super_block *sb) -{ - Cyg_ErrNo err; - struct jffs2_sb_info *c; - struct rt_mtd_nor_device *device; - - c = JFFS2_SB_INFO(sb); - device = RT_MTD_NOR_DEVICE(sb->s_dev); - - /* initialize mutex lock */ - init_MUTEX(&c->alloc_sem); - init_MUTEX(&c->erase_free_sem); - - /* sector size is the erase block size */ - c->sector_size = device->block_size; - c->flash_size = (device->block_end - device->block_start) * device->block_size; - c->cleanmarker_size = sizeof(struct jffs2_unknown_node); - - err = jffs2_do_mount_fs(c); - if (err) return -err; - - D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n")); - sb->s_root = jffs2_iget(sb, 1); - if (IS_ERR(sb->s_root)) { - D1(printk(KERN_WARNING "get root inode failed\n")); - err = PTR_ERR(sb->s_root); - sb->s_root = NULL; - goto out_nodes; - } - return 0; - -out_nodes: - jffs2_free_ino_caches(c); - jffs2_free_raw_node_refs(c); - rt_free(c->blocks); - - return err; -} - -int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte) -{ -// extern cyg_mtab_entry cyg_mtab[], cyg_mtab_end; - struct super_block *jffs2_sb = NULL; - struct jffs2_sb_info *c; -// cyg_mtab_entry *m; - cyg_io_handle_t t; - Cyg_ErrNo err; - - D2(printf("jffs2_mount\n")); - -//prife -// err = cyg_io_lookup(mte->devname, &t); -// if (err != ENOERR) -// return -err; - -// // Iterate through the mount table to see if we're mounted -// // FIXME: this should be done better - perhaps if the superblock -// // can be stored as an inode in the icache. -// for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) { -// // stop if there are more than the configured maximum -// if (m - &cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) { -// m = &cyg_mtab_end; -// break; -// } -// if (m->valid && strcmp(m->fsname, "jffs2") == 0 && -// strcmp(m->devname, mte->devname) == 0) { -// jffs2_sb = (struct super_block *) m->data; -// } -// } - jffs2_sb = NULL; - t = (cyg_io_handle_t)mte->data; //get from dfs_jffs2; - if (jffs2_sb == NULL) { - jffs2_sb = rt_malloc(sizeof (struct super_block)); - - if (jffs2_sb == NULL) - return ENOMEM; - - c = JFFS2_SB_INFO(jffs2_sb); - memset(jffs2_sb, 0, sizeof (struct super_block)); - jffs2_sb->s_dev = t; - - c->inocache_list = rt_malloc(sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE); - if (!c->inocache_list) { - rt_free(jffs2_sb); - return ENOMEM; - } - memset(c->inocache_list, 0, sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE); - if (n_fs_mounted++ == 0) { - jffs2_create_slab_caches(); // No error check, cannot fail - jffs2_compressors_init(); - } - - err = jffs2_read_super(jffs2_sb); - - if (err) { - if (--n_fs_mounted == 0) { - jffs2_destroy_slab_caches(); - jffs2_compressors_exit(); - } - - rt_free(jffs2_sb); - rt_free(c->inocache_list); - return err; - } - - jffs2_sb->s_root->i_parent = jffs2_sb->s_root; // points to itself, no dotdot paths above mountpoint - jffs2_sb->s_root->i_cache_prev = NULL; // root inode, so always null - jffs2_sb->s_root->i_cache_next = NULL; - jffs2_sb->s_root->i_count = 1; // Ensures the root inode is always in ram until umount - - D2(printf("jffs2_mount erasing pending blocks\n")); -#ifdef CYGOPT_FS_JFFS2_WRITE - if (!jffs2_is_readonly(c)) - jffs2_erase_pending_blocks(c,0); -#endif -#ifdef CYGOPT_FS_JFFS2_GCTHREAD - jffs2_start_garbage_collect_thread(c); -#endif - } - mte->data = (CYG_ADDRWORD) jffs2_sb; - - jffs2_sb->s_mount_count++; - mte->root = (cyg_dir) jffs2_sb->s_root; - D2(printf("jffs2_mounted superblock at %x\n", mte->root)); - - return ENOERR; -} - -extern cyg_dir cyg_cdir_dir; -extern cyg_mtab_entry *cyg_cdir_mtab_entry; - -// ------------------------------------------------------------------------- -// jffs2_umount() -// Unmount the filesystem. - -static int jffs2_umount(cyg_mtab_entry * mte) -{ - struct _inode *root = (struct _inode *) mte->root; - struct super_block *jffs2_sb = root->i_sb; - struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb); - struct jffs2_full_dirent *fd, *next; - - D2(printf("jffs2_umount\n")); - - // Only really umount if this is the only mount - if (jffs2_sb->s_mount_count == 1) { - icache_evict(root, NULL); - if (root->i_cache_next != NULL) { - struct _inode *inode = root; - printf("Refuse to unmount.\n"); - while (inode) { - printf("Ino #%u has use count %d\n", - inode->i_ino, inode->i_count); - inode = inode->i_cache_next; - } - // root icount was set to 1 on mount - return EBUSY; - } - if (root->i_count == 2 && - cyg_cdir_mtab_entry == mte && - cyg_cdir_dir == (cyg_dir)root && - !strcmp(mte->name, "/")) { - /* If we were mounted on root, there's no - way for the cwd to change out and free - the file system for unmounting. So we hack - it -- if cwd is '/' we unset it. Perhaps - we should allow chdir(NULL) to unset - cyg_cdir_dir? */ - cyg_cdir_dir = CYG_DIR_NULL; - jffs2_iput(root); - } - /* Argh. The fileio code sets this; never clears it */ - if (cyg_cdir_mtab_entry == mte) - cyg_cdir_mtab_entry = NULL; - - if (root->i_count != 1) { - printf("Ino #1 has use count %d\n", - root->i_count); - return EBUSY; - } -#ifdef CYGOPT_FS_JFFS2_GCTHREAD - jffs2_stop_garbage_collect_thread(c); -#endif - jffs2_iput(root); // Time to free the root inode - - // free directory entries - for (fd = root->jffs2_i.dents; fd; fd = next) { - next=fd->next; - jffs2_free_full_dirent(fd); - } - - rt_free(root); - //Clear root inode - //root_i = NULL; - - // Clean up the super block and root inode - jffs2_free_ino_caches(c); - jffs2_free_raw_node_refs(c); - rt_free(c->blocks); - rt_free(c->inocache_list); - rt_free(jffs2_sb); - // Clear superblock & root pointer - mte->root = CYG_DIR_NULL; - mte->data = 0; - mte->fs->data = 0; // fstab entry, visible to all mounts. No current mount - // That's all folks. - D2(printf("jffs2_umount No current mounts\n")); - } else { - jffs2_sb->s_mount_count--; - } - if (--n_fs_mounted == 0) { - jffs2_destroy_slab_caches(); - jffs2_compressors_exit(); - } - return ENOERR; -} - -// ------------------------------------------------------------------------- -// jffs2_open() -// Open a file for reading or writing. - -int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - int mode, cyg_file * file) -{ - - jffs2_dirsearch ds; - struct _inode *node = NULL; - int err; - - D2(printf("jffs2_open\n")); - - /* If no chdir has been called and we were the first file system - mounted, we get called with dir == NULL. Deal with it */ - if (!dir) - dir = mte->root; - -#ifndef CYGOPT_FS_JFFS2_WRITE - if (mode & (O_CREAT|O_TRUNC|O_WRONLY)) - return EROFS; -#endif - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *) name); - - err = jffs2_find(&ds); - - if (err == ENOENT) { -#ifdef CYGOPT_FS_JFFS2_WRITE - if (ds.last && (mode & O_CREAT)) { - - // No node there, if the O_CREAT bit is set then we must - // create a new one. The dir and name fields of the dirsearch - // object will have been updated so we know where to put it. - - err = jffs2_create(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR|S_IFREG, &node); - - if (err != 0) { - //Possible orphaned inode on the flash - but will be gc'd - jffs2_iput(ds.dir); - return -err; - } - - err = ENOERR; - } -#endif - } else if (err == ENOERR) { - // The node exists. If the O_CREAT and O_EXCL bits are set, we - // must fail the open. - - if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { - jffs2_iput(ds.node); - err = EEXIST; - } else - node = ds.node; - } - - // Finished with the directory now - jffs2_iput(ds.dir); - - if (err != ENOERR) - return err; - - // Check that we actually have a file here - if (S_ISDIR(node->i_mode)) { - jffs2_iput(node); - return EISDIR; - } - - // If the O_TRUNC bit is set we must clean out the file data. - if (mode & O_TRUNC) { -#ifdef CYGOPT_FS_JFFS2_WRITE - err = jffs2_truncate_file(node); - if (err) { - jffs2_iput(node); - return err; - } -#else - jffs2_iput(node); - return EROFS; -#endif - } - - // Initialise the file object - file->f_flag = mode & CYG_FILE_MODE_MASK; - file->f_type = CYG_FILE_TYPE_FILE; - file->f_ops = &jffs2_fileops; - file->f_offset = (mode & O_APPEND) ? node->i_size : 0; - file->f_data = (CYG_ADDRWORD) node; - file->f_xops = 0; - - return ENOERR; -} - -#ifdef CYGOPT_FS_JFFS2_WRITE -// ------------------------------------------------------------------------- -// jffs2_ops_unlink() -// Remove a file link from its directory. - -static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, const char *name) -{ - jffs2_dirsearch ds; - int err; - - D2(printf("jffs2_ops_unlink\n")); - - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *)name); - - err = jffs2_find(&ds); - - if (err != ENOERR) { - jffs2_iput(ds.dir); - return err; - } - - // Cannot unlink directories, use rmdir() instead - if (S_ISDIR(ds.node->i_mode)) { - jffs2_iput(ds.dir); - jffs2_iput(ds.node); - return EPERM; - } - - // Delete it from its directory - - err = jffs2_unlink(ds.dir, ds.node, ds.name); - jffs2_iput(ds.dir); - jffs2_iput(ds.node); - - return -err; -} - -// ------------------------------------------------------------------------- -// jffs2_ops_mkdir() -// Create a new directory. - -static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name) -{ - jffs2_dirsearch ds; - int err; - - D2(printf("jffs2_ops_mkdir\n")); - - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *)name); - - err = jffs2_find(&ds); - - if (err == ENOENT) { - if (ds.last) { - // The entry does not exist, and it is the last element in - // the pathname, so we can create it here. - - err = -jffs2_mkdir(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR); - } - // If this was not the last element, then an intermediate - // directory does not exist. - } else { - // If there we no error, something already exists with that - // name, so we cannot create another one. - if (err == ENOERR) { - jffs2_iput(ds.node); - err = EEXIST; - } - } - jffs2_iput(ds.dir); - return err; -} - -// ------------------------------------------------------------------------- -// jffs2_ops_rmdir() -// Remove a directory. - -static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name) -{ - jffs2_dirsearch ds; - int err; - - D2(printf("jffs2_ops_rmdir\n")); - - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *)name); - - err = jffs2_find(&ds); - - if (err != ENOERR) { - jffs2_iput(ds.dir); - return err; - } - - // Check that this is actually a directory. - if (!S_ISDIR(ds.node->i_mode)) { - jffs2_iput(ds.dir); - jffs2_iput(ds.node); - return EPERM; - } - - err = jffs2_rmdir(ds.dir, ds.node, ds.name); - - jffs2_iput(ds.dir); - jffs2_iput(ds.node); - return -err; -} - -// ------------------------------------------------------------------------- -// jffs2_ops_rename() -// Rename a file/dir. - -static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1, - const char *name1, cyg_dir dir2, const char *name2) -{ - jffs2_dirsearch ds1, ds2; - int err; - - D2(printf("jffs2_ops_rename\n")); - - init_dirsearch(&ds1, (struct _inode *) dir1, - (const unsigned char *)name1); - - err = jffs2_find(&ds1); - - if (err != ENOERR) { - jffs2_iput(ds1.dir); - return err; - } - - init_dirsearch(&ds2, (struct _inode *) dir2, - (const unsigned char *)name2); - - err = jffs2_find(&ds2); - - // Allow through renames to non-existent objects. - if (ds2.last && err == ENOENT) { - ds2.node = NULL; - err = ENOERR; - } - - if (err != ENOERR) { - jffs2_iput(ds1.dir); - jffs2_iput(ds1.node); - jffs2_iput(ds2.dir); - return err; - } - - // Null rename, just return - if (ds1.node == ds2.node) { - err = ENOERR; - goto out; - } - - // First deal with any entry that is at the destination - if (ds2.node) { - // Check that we are renaming like-for-like - - if (!S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode)) { - err = EISDIR; - goto out; - } - - if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode)) { - err = ENOTDIR; - goto out; - } - - // Now delete the destination directory entry - /* Er, what happened to atomicity of rename()? */ - err = -jffs2_unlink(ds2.dir, ds2.node, ds2.name); - - if (err != 0) - goto out; - - } - // Now we know that there is no clashing node at the destination, - // make a new direntry at the destination and delete the old entry - // at the source. - - err = -jffs2_rename(ds1.dir, ds1.node, ds1.name, ds2.dir, ds2.name); - - // Update directory times - if (!err) - ds1.dir->i_ctime = - ds1.dir->i_mtime = - ds2.dir->i_ctime = ds2.dir->i_mtime = jffs2_get_timestamp(); - out: - jffs2_iput(ds1.dir); - if (S_ISDIR(ds1.node->i_mode)) { - /* Renamed a directory to elsewhere... so fix up its - i_parent pointer and the i_counts of its old and - new parents. */ - jffs2_iput(ds1.node->i_parent); - ds1.node->i_parent = ds2.dir; - /* We effectively increase its use count by not... */ - } else { - jffs2_iput(ds2.dir); /* ... doing this */ - } - jffs2_iput(ds1.node); - if (ds2.node) - jffs2_iput(ds2.node); - - return err; -} - -// ------------------------------------------------------------------------- -// jffs2_ops_link() -// Make a new directory entry for a file. - -static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1, - cyg_dir dir2, const char *name2, int type) -{ - jffs2_dirsearch ds1, ds2; - int err; - - D2(printf("jffs2_ops_link\n")); - - // Only do hard links for now in this filesystem - if (type != CYG_FSLINK_HARD) - return EINVAL; - - init_dirsearch(&ds1, (struct _inode *) dir1, - (const unsigned char *) name1); - - err = jffs2_find(&ds1); - - if (err != ENOERR) { - jffs2_iput(ds1.dir); - return err; - } - - init_dirsearch(&ds2, (struct _inode *) dir2, - (const unsigned char *) name2); - - err = jffs2_find(&ds2); - - // Don't allow links to existing objects - if (err == ENOERR) { - jffs2_iput(ds1.dir); - jffs2_iput(ds1.node); - jffs2_iput(ds2.dir); - jffs2_iput(ds2.node); - return EEXIST; - } - - // Allow through links to non-existing terminal objects - if (ds2.last && err == ENOENT) { - ds2.node = NULL; - err = ENOERR; - } - - if (err != ENOERR) { - jffs2_iput(ds1.dir); - jffs2_iput(ds1.node); - jffs2_iput(ds2.dir); - return err; - } - - // Now we know that there is no existing node at the destination, - // make a new direntry at the destination. - - err = jffs2_link(ds1.node, ds2.dir, ds2.name); - - if (err == 0) - ds1.node->i_ctime = - ds2.dir->i_ctime = ds2.dir->i_mtime = jffs2_get_timestamp(); - - jffs2_iput(ds1.dir); - jffs2_iput(ds1.node); - jffs2_iput(ds2.dir); - - return -err; -} -#endif /* CYGOPT_FS_JFFS2_WRITE */ -// ------------------------------------------------------------------------- -// jffs2_opendir() -// Open a directory for reading. - -static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - cyg_file * file) -{ - jffs2_dirsearch ds; - int err; - - D2(printf("jffs2_opendir\n")); - - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *) name); - - err = jffs2_find(&ds); - - jffs2_iput(ds.dir); - - if (err != ENOERR) - return err; - - // check it is really a directory. - if (!S_ISDIR(ds.node->i_mode)) { - jffs2_iput(ds.node); - return ENOTDIR; - } - - // Initialize the file object, setting the f_ops field to a - // special set of file ops. - - file->f_flag = 0; - file->f_type = CYG_FILE_TYPE_FILE; - file->f_ops = &jffs2_dirops; - file->f_offset = 0; - file->f_data = (CYG_ADDRWORD) ds.node; - file->f_xops = 0; - - return ENOERR; - -} - -// ------------------------------------------------------------------------- -// jffs2_chdir() -// Change directory support. - -static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - cyg_dir * dir_out) -{ - D2(printf("jffs2_chdir\n")); - - if (dir_out != NULL) { - // This is a request to get a new directory pointer in - // *dir_out. - - jffs2_dirsearch ds; - int err; - - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *) name); - - err = jffs2_find(&ds); - jffs2_iput(ds.dir); - - if (err != ENOERR) - return err; - - // check it is a directory - if (!S_ISDIR(ds.node->i_mode)) { - jffs2_iput(ds.node); - return ENOTDIR; - } - - // Pass it out - *dir_out = (cyg_dir) ds.node; - } else { - // If no output dir is required, this means that the mte and - // dir arguments are the current cdir setting and we should - // forget this fact. - - struct _inode *node = (struct _inode *) dir; - - // Just decrement directory reference count. - jffs2_iput(node); - } - - return ENOERR; -} - -// ------------------------------------------------------------------------- -// jffs2_stat() -// Get struct stat info for named object. - -static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - struct stat *buf) -{ - jffs2_dirsearch ds; - int err; - - D2(printf("jffs2_stat\n")); - - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *) name); - - err = jffs2_find(&ds); - jffs2_iput(ds.dir); - - if (err != ENOERR) - return err; - - // Fill in the status - buf->st_mode = ds.node->i_mode; - buf->st_ino = ds.node->i_ino; - buf->st_dev = 0; - buf->st_nlink = ds.node->i_nlink; - buf->st_uid = ds.node->i_uid; - buf->st_gid = ds.node->i_gid; - buf->st_size = ds.node->i_size; - buf->st_atime = ds.node->i_atime; - buf->st_mtime = ds.node->i_mtime; - buf->st_ctime = ds.node->i_ctime; - - jffs2_iput(ds.node); - - return ENOERR; -} - -// ------------------------------------------------------------------------- -// jffs2_getinfo() -// Getinfo. Currently only support pathconf(). - -static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - int key, void *buf, int len) -{ - jffs2_dirsearch ds; - int err; - - D2(printf("jffs2_getinfo\n")); - - init_dirsearch(&ds, (struct _inode *) dir, - (const unsigned char *) name); - - err = jffs2_find(&ds); - jffs2_iput(ds.dir); - - if (err != ENOERR) - return err; - - switch (key) { - case FS_INFO_CONF: - err = jffs2_pathconf(ds.node, (struct cyg_pathconf_info *) buf); - break; - - default: - err = EINVAL; - } - - jffs2_iput(ds.node); - return err; -} - -// ------------------------------------------------------------------------- -// jffs2_setinfo() -// Setinfo. Nothing to support here at present. - -static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, - int key, void *buf, int len) -{ - // No setinfo keys supported at present - - D2(printf("jffs2_setinfo\n")); - - return EINVAL; -} - -//========================================================================== -// File operations - -// ------------------------------------------------------------------------- -// jffs2_fo_read() -// Read data from the file. - -int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) -{ - struct _inode *inode = (struct _inode *) fp->f_data; - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - int i; - ssize_t resid = uio->uio_resid; - off_t pos = fp->f_offset; - - down(&f->sem); - - // Loop over the io vectors until there are none left - for (i = 0; i < uio->uio_iovcnt && pos < inode->i_size; i++) { - int ret; - cyg_iovec *iov = &uio->uio_iov[i]; - off_t len = min(iov->iov_len, inode->i_size - pos); - - D2(printf("jffs2_fo_read inode size %d\n", inode->i_size)); - - ret = - jffs2_read_inode_range(c, f, - (unsigned char *) iov->iov_base, pos, - len); - if (ret) { - D1(printf - ("jffs2_fo_read(): read_inode_range failed %d\n", - ret)); - uio->uio_resid = resid; - up(&f->sem); - return -ret; - } - resid -= len; - pos += len; - } - - // We successfully read some data, update the node's access time - // and update the file offset and transfer residue. - - inode->i_atime = jffs2_get_timestamp(); - - uio->uio_resid = resid; - fp->f_offset = pos; - - up(&f->sem); - - return ENOERR; -} - - -#ifdef CYGOPT_FS_JFFS2_WRITE -// ------------------------------------------------------------------------- -// jffs2_fo_write() -// Write data to file. -static int jffs2_extend_file (struct _inode *inode, struct jffs2_raw_inode *ri, - unsigned long offset) -{ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_full_dnode *fn; - uint32_t phys_ofs, alloc_len; - int ret = 0; - - /* Make new hole frag from old EOF to new page */ - D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", - (unsigned int)inode->i_size, offset)); - - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloc_len, ALLOC_NORMAL); - if (ret) - return ret; - - down(&f->sem); - - ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); - ri->totlen = cpu_to_je32(sizeof(*ri)); - ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - - ri->version = cpu_to_je32(++f->highest_version); - ri->isize = cpu_to_je32(max((uint32_t)inode->i_size, offset)); - - ri->offset = cpu_to_je32(inode->i_size); - ri->dsize = cpu_to_je32(offset - inode->i_size); - ri->csize = cpu_to_je32(0); - ri->compr = JFFS2_COMPR_ZERO; - ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - ri->data_crc = cpu_to_je32(0); - - fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); - jffs2_complete_reservation(c); - if (IS_ERR(fn)) { - ret = PTR_ERR(fn); - up(&f->sem); - return ret; - } - ret = jffs2_add_full_dnode_to_inode(c, f, fn); - if (f->metadata) { - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - } - if (ret) { - D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret)); - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); - up(&f->sem); - return ret; - } - inode->i_size = offset; - up(&f->sem); - return 0; -} - -// jffs2_fo_open() -// Truncate a file -static int jffs2_truncate_file (struct _inode *inode) -{ - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_full_dnode *new_metadata, * old_metadata; - struct jffs2_raw_inode *ri; - uint32_t phys_ofs, alloclen; - int err; - - ri = jffs2_alloc_raw_inode(); - if (!ri) { - return ENOMEM; - } - err = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); - - if (err) { - jffs2_free_raw_inode(ri); - return err; - } - down(&f->sem); - ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); - ri->totlen = cpu_to_je32(sizeof(*ri)); - ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - - ri->ino = cpu_to_je32(inode->i_ino); - ri->version = cpu_to_je32(++f->highest_version); - - ri->uid = cpu_to_je16(inode->i_uid); - ri->gid = cpu_to_je16(inode->i_gid); - ri->mode = cpu_to_jemode(inode->i_mode); - ri->isize = cpu_to_je32(0); - ri->atime = cpu_to_je32(inode->i_atime); - ri->mtime = cpu_to_je32(jffs2_get_timestamp()); - ri->offset = cpu_to_je32(0); - ri->csize = ri->dsize = cpu_to_je32(0); - ri->compr = JFFS2_COMPR_NONE; - ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - ri->data_crc = cpu_to_je32(0); - new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0, - phys_ofs, ALLOC_NORMAL); - if (IS_ERR(new_metadata)) { - jffs2_complete_reservation(c); - jffs2_free_raw_inode(ri); - up(&f->sem); - return PTR_ERR(new_metadata); - } - - /* It worked. Update the inode */ - inode->i_mtime = jffs2_get_timestamp(); - inode->i_size = 0; - old_metadata = f->metadata; - jffs2_truncate_fragtree (c, &f->fragtree, 0); - f->metadata = new_metadata; - if (old_metadata) { - jffs2_mark_node_obsolete(c, old_metadata->raw); - jffs2_free_full_dnode(old_metadata); - } - jffs2_free_raw_inode(ri); - - up(&f->sem); - jffs2_complete_reservation(c); - - return 0; -} - -static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) -{ - struct _inode *inode = (struct _inode *) fp->f_data; - off_t pos = fp->f_offset; - ssize_t resid = uio->uio_resid; - struct jffs2_raw_inode ri; - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - int i; - - // If the APPEND mode bit was supplied, force all writes to - // the end of the file. - if (fp->f_flag & CYG_FAPPEND) - pos = fp->f_offset = inode->i_size; - - if (pos < 0) - return EINVAL; - - memset(&ri, 0, sizeof(ri)); - - ri.ino = cpu_to_je32(f->inocache->ino); - ri.mode = cpu_to_jemode(inode->i_mode); - ri.uid = cpu_to_je16(inode->i_uid); - ri.gid = cpu_to_je16(inode->i_gid); - ri.atime = ri.ctime = ri.mtime = cpu_to_je32(jffs2_get_timestamp()); - - if (pos > inode->i_size) { - int err; - ri.version = cpu_to_je32(++f->highest_version); - err = jffs2_extend_file(inode, &ri, pos); - if (err) - return -err; - } - ri.isize = cpu_to_je32(inode->i_size); - - // Now loop over the iovecs until they are all done, or - // we get an error. - for (i = 0; i < uio->uio_iovcnt; i++) { - cyg_iovec *iov = &uio->uio_iov[i]; - unsigned char *buf = iov->iov_base; - off_t len = iov->iov_len; - - uint32_t writtenlen; - int err; - - D2(printf("jffs2_fo_write page_start_pos %d\n", pos)); - D2(printf("jffs2_fo_write transfer size %d\n", len)); - - err = jffs2_write_inode_range(c, f, &ri, buf, - pos, len, &writtenlen); - if (err) - return -err; - - if (writtenlen != len) - return ENOSPC; - - pos += len; - resid -= len; - } - - // We wrote some data successfully, update the modified and access - // times of the inode, increase its size appropriately, and update - // the file offset and transfer residue. - inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime); - if (pos > inode->i_size) - inode->i_size = pos; - - uio->uio_resid = resid; - fp->f_offset = pos; - - return ENOERR; -} -#endif /* CYGOPT_FS_JFFS2_WRITE */ - -// ------------------------------------------------------------------------- -// jffs2_fo_lseek() -// Seek to a new file position. - -static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * apos, int whence) -{ - struct _inode *node = (struct _inode *) fp->f_data; - off_t pos = *apos; - - D2(printf("jffs2_fo_lseek\n")); - - switch (whence) { - case SEEK_SET: - // Pos is already where we want to be. - break; - - case SEEK_CUR: - // Add pos to current offset. - pos += fp->f_offset; - break; - - case SEEK_END: - // Add pos to file size. - pos += node->i_size; - break; - - default: - return EINVAL; - } - - if (pos < 0 ) - return EINVAL; - - // All OK, set fp offset and return new position. - *apos = fp->f_offset = pos; - - return ENOERR; -} - -// ------------------------------------------------------------------------- -// jffs2_fo_ioctl() -// Handle ioctls. Currently none are defined. - -static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, - CYG_ADDRWORD data) -{ - // No Ioctls currenly defined. - - D2(printf("jffs2_fo_ioctl\n")); - - return EINVAL; -} - -// ------------------------------------------------------------------------- -// jffs2_fo_fsync(). -// Force the file out to data storage. - -static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode) -{ - // Data is always permanently where it belongs, nothing to do - // here. - - D2(printf("jffs2_fo_fsync\n")); - - return ENOERR; -} - -// ------------------------------------------------------------------------- -// jffs2_fo_close() -// Close a file. We just decrement the refcnt and let it go away if -// that is all that is keeping it here. - -static int jffs2_fo_close(struct CYG_FILE_TAG *fp) -{ - struct _inode *node = (struct _inode *) fp->f_data; - - D2(printf("jffs2_fo_close\n")); - - jffs2_iput(node); - - fp->f_data = 0; // zero data pointer - - return ENOERR; -} - -// ------------------------------------------------------------------------- -//jffs2_fo_fstat() -// Get file status. - -static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf) -{ - struct _inode *node = (struct _inode *) fp->f_data; - - D2(printf("jffs2_fo_fstat\n")); - - // Fill in the status - buf->st_mode = node->i_mode; - buf->st_ino = node->i_ino; - buf->st_dev = 0; - buf->st_nlink = node->i_nlink; - buf->st_uid = node->i_uid; - buf->st_gid = node->i_gid; - buf->st_size = node->i_size; - buf->st_atime = node->i_atime; - buf->st_mtime = node->i_mtime; - buf->st_ctime = node->i_ctime; - - return ENOERR; -} - -// ------------------------------------------------------------------------- -// jffs2_fo_getinfo() -// Get info. Currently only supports fpathconf(). - -static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, - int len) -{ - struct _inode *node = (struct _inode *) fp->f_data; - int err; - - D2(printf("jffs2_fo_getinfo\n")); - - switch (key) { - case FS_INFO_CONF: - err = jffs2_pathconf(node, (struct cyg_pathconf_info *) buf); - break; - - default: - err = EINVAL; - } - return err; -} - -// ------------------------------------------------------------------------- -// jffs2_fo_setinfo() -// Set info. Nothing supported here. - -static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, - int len) -{ - // No setinfo key supported at present - - D2(printf("jffs2_fo_setinfo\n")); - - return ENOERR; -} - -//========================================================================== -// Directory operations - -// ------------------------------------------------------------------------- -// jffs2_fo_dirread() -// Read a single directory entry from a file. - -static __inline void filldir(char *nbuf, int nlen, const unsigned char *name, int namlen) -{ - int len = nlen < namlen ? nlen : namlen; - memcpy(nbuf, name, len); - nbuf[len] = '\0'; -} - -static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) -{ - struct _inode *d_inode = (struct _inode *) fp->f_data; - struct dirent *ent = (struct dirent *) uio->uio_iov[0].iov_base; - char *nbuf = ent->d_name; -#ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE - struct _inode *c_ino; -#endif - int nlen = sizeof (ent->d_name) - 1; - off_t len = uio->uio_iov[0].iov_len; - struct jffs2_inode_info *f; - struct _inode *inode = d_inode; - struct jffs2_full_dirent *fd; - unsigned long offset, curofs; - int found = 1; - - if (len < sizeof (struct dirent)) - return EINVAL; - - D1(printk - (KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino)); - - f = JFFS2_INODE_INFO(inode); - - offset = fp->f_offset; - - if (offset == 0) { - D1(printk - (KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino)); - filldir(nbuf, nlen, (const unsigned char *) ".", 1); -#ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE - // Flags here are the same as jffs2_mkdir. Make sure - // d_type is the same as st_mode of calling stat. - ent->d_type = - jemode_to_cpu(cpu_to_jemode(S_IRUGO|S_IXUGO|S_IWUSR|S_IFDIR)); -#endif - goto out; - } - if (offset == 1) { - filldir(nbuf, nlen, (const unsigned char *) "..", 2); -#ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE - // Flags here are the same as jffs2_mkdir. Make sure - // d_type is the same as st_mode of calling stat. - ent->d_type = - jemode_to_cpu(cpu_to_jemode(S_IRUGO|S_IXUGO|S_IWUSR|S_IFDIR)); -#endif - goto out; - } - - curofs = 1; - down(&f->sem); - for (fd = f->dents; fd; fd = fd->next) { - - curofs++; - /* First loop: curofs = 2; offset = 2 */ - if (curofs < offset) { - D2(printk - (KERN_DEBUG - "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", - fd->name, fd->ino, fd->type, curofs, offset)); - continue; - } - if (!fd->ino) { - D2(printk - (KERN_DEBUG "Skipping deletion dirent \"%s\"\n", - fd->name)); - offset++; - continue; - } - D2(printk - (KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset, - fd->name, fd->ino, fd->type)); - filldir(nbuf, nlen, fd->name, strlen((char *)fd->name)); -#ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE - c_ino = jffs2_iget(inode->i_sb, fd->ino); - if(IS_ERR(c_ino)) { - D1(printk(KERN_WARNING "get entry inode failed\n")); - // fileio already set it to zero, so not needed here - // ent->d_type = 0; - } - else { - ent->d_type = c_ino->i_mode; - jffs2_iput(c_ino); - } -#endif - goto out_sem; - } - /* Reached the end of the directory */ - found = 0; - out_sem: - up(&f->sem); - out: - fp->f_offset = ++offset; - if (found) { - uio->uio_resid -= sizeof (struct dirent); - } - return ENOERR; -} - -// ------------------------------------------------------------------------- -// jffs2_fo_dirlseek() -// Seek directory to start. - -static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence) -{ - // Only allow SEEK_SET to zero - - D2(printf("jffs2_fo_dirlseek\n")); - - if (whence != SEEK_SET || *pos != 0) - return EINVAL; - - *pos = fp->f_offset = 0; - - return ENOERR; -} - -//========================================================================== -// -// Called by JFFS2 -// =============== -// -// -//========================================================================== - -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, - unsigned long offset, - unsigned long *priv) -{ - /* FIXME: This works only with one file system mounted at a time */ - int ret; - - ret = jffs2_read_inode_range(c, f, gc_buffer, - offset & ~(PAGE_CACHE_SIZE-1), PAGE_CACHE_SIZE); - if (ret) - return ERR_PTR(ret); - - return gc_buffer; -} - -void jffs2_gc_release_page(struct jffs2_sb_info *c, - unsigned char *ptr, - unsigned long *priv) -{ - /* Do nothing */ -} - -static struct _inode *new_inode(struct super_block *sb) -{ - struct _inode *inode; - struct _inode *cached_inode; - - inode = rt_malloc(sizeof (struct _inode)); - if (inode == NULL) - return 0; - - D2(printf("malloc new_inode %x ####################################\n", - inode)); - - memset(inode, 0, sizeof (struct _inode)); - inode->i_sb = sb; - inode->i_ino = 1; - inode->i_count = 1; - inode->i_nlink = 1; // Let JFFS2 manage the link count - inode->i_size = 0; - - inode->i_cache_next = NULL; // Newest inode, about to be cached - - // Add to the icache - for (cached_inode = sb->s_root; cached_inode != NULL; - cached_inode = cached_inode->i_cache_next) { - if (cached_inode->i_cache_next == NULL) { - cached_inode->i_cache_next = inode; // Current last in cache points to newcomer - inode->i_cache_prev = cached_inode; // Newcomer points back to last - break; - } - } - return inode; -} - -static struct _inode *ilookup(struct super_block *sb, cyg_uint32 ino) -{ - struct _inode *inode = NULL; - - D2(printf("ilookup\n")); - // Check for this inode in the cache - for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) { - if (inode->i_ino == ino) { - inode->i_count++; - break; - } - } - return inode; -} - -struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino) -{ - // Called in super.c jffs2_read_super, dir.c jffs2_lookup, - // and gc.c jffs2_garbage_collect_pass - - // Must first check for cached inode - // If this fails let new_inode create one - - struct _inode *inode; - int err; - - D2(printf("jffs2_iget\n")); - - inode = ilookup(sb, ino); - if (inode) - return inode; - - // Not cached, so malloc it - inode = new_inode(sb); - if (inode == NULL) - return ERR_PTR(-ENOMEM); - - inode->i_ino = ino; - - err = jffs2_read_inode(inode); - if (err) { - printf("jffs2_read_inode() failed\n"); - inode->i_nlink = 0; // free _this_ bad inode right now - jffs2_iput(inode); - inode = NULL; - return ERR_PTR(err); - } - return inode; -} - -// ------------------------------------------------------------------------- -// Decrement the reference count on an inode. If this makes the ref count -// zero, then this inode can be freed. - -void jffs2_iput(struct _inode *i) -{ - // Called in jffs2_find - // (and jffs2_open and jffs2_ops_mkdir?) - // super.c jffs2_read_super, - // and gc.c jffs2_garbage_collect_pass - recurse: - if (!i) { - printf("jffs2_iput() called with NULL inode\n"); - // and let it fault... - } - - i->i_count--; - - if (i->i_count < 0) - BUG(); - - if (i->i_count) - return; - - if (!i->i_nlink) { - struct _inode *parent; - - // Remove from the icache linked list and free immediately - if (i->i_cache_prev) - i->i_cache_prev->i_cache_next = i->i_cache_next; - if (i->i_cache_next) - i->i_cache_next->i_cache_prev = i->i_cache_prev; - - parent = i->i_parent; - jffs2_clear_inode(i); - memset(i, 0x5a, sizeof(*i)); - rt_free(i); - - if (parent && parent != i) { - i = parent; - goto recurse; - } - - } else { - // Evict some _other_ inode with i_count zero, leaving - // this latest one in the cache for a while - icache_evict(i->i_sb->s_root, i); - } -} - - -// ------------------------------------------------------------------------- -// EOF jffs2.c - - -static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) -{ - memset(f, 0, sizeof(*f)); - init_MUTEX_LOCKED(&f->sem); -} - -static void jffs2_clear_inode (struct _inode *inode) -{ - /* We can forget about this inode for now - drop all - * the nodelists associated with it, etc. - */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - - D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); - - jffs2_do_clear_inode(c, f); -} - - -/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, - fill in the raw_inode while you're at it. */ -struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri) -{ - struct _inode *inode; - struct super_block *sb = dir_i->i_sb; - struct jffs2_sb_info *c; - struct jffs2_inode_info *f; - int ret; - - D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); - - c = JFFS2_SB_INFO(sb); - - inode = new_inode(sb); - - if (!inode) - return ERR_PTR(-ENOMEM); - - f = JFFS2_INODE_INFO(inode); - jffs2_init_inode_info(f); - - memset(ri, 0, sizeof(*ri)); - /* Set OS-specific defaults for new inodes */ - ri->uid = ri->gid = cpu_to_je16(0); - ri->mode = cpu_to_jemode(mode); - ret = jffs2_do_new_inode (c, f, mode, ri); - if (ret) { - // forceful evict: f->sem is locked already, and the - // inode is bad. - if (inode->i_cache_prev) - inode->i_cache_prev->i_cache_next = inode->i_cache_next; - if (inode->i_cache_next) - inode->i_cache_next->i_cache_prev = inode->i_cache_prev; - up(&(f->sem)); - jffs2_clear_inode(inode); - memset(inode, 0x6a, sizeof(*inode)); - rt_free(inode); - return ERR_PTR(ret); - } - inode->i_nlink = 1; - inode->i_ino = je32_to_cpu(ri->ino); - inode->i_mode = jemode_to_cpu(ri->mode); - inode->i_gid = je16_to_cpu(ri->gid); - inode->i_uid = je16_to_cpu(ri->uid); - inode->i_atime = inode->i_ctime = inode->i_mtime = jffs2_get_timestamp(); - ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime); - - inode->i_size = 0; - - return inode; -} - - -static int jffs2_read_inode (struct _inode *inode) -{ - struct jffs2_inode_info *f; - struct jffs2_sb_info *c; - struct jffs2_raw_inode latest_node; - int ret; - - D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); - - f = JFFS2_INODE_INFO(inode); - c = JFFS2_SB_INFO(inode->i_sb); - - jffs2_init_inode_info(f); - - ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); - - if (ret) { - up(&f->sem); - return ret; - } - inode->i_mode = jemode_to_cpu(latest_node.mode); - inode->i_uid = je16_to_cpu(latest_node.uid); - inode->i_gid = je16_to_cpu(latest_node.gid); - inode->i_size = je32_to_cpu(latest_node.isize); - inode->i_atime = je32_to_cpu(latest_node.atime); - inode->i_mtime = je32_to_cpu(latest_node.mtime); - inode->i_ctime = je32_to_cpu(latest_node.ctime); - - inode->i_nlink = f->inocache->nlink; - up(&f->sem); - - D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); - return 0; -} - - -void jffs2_gc_release_inode(struct jffs2_sb_info *c, - struct jffs2_inode_info *f) -{ - jffs2_iput(OFNI_EDONI_2SFFJ(f)); -} - -struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, - int inum, int nlink) -{ - struct _inode *inode; - struct jffs2_inode_cache *ic; - if (!nlink) { - /* The inode has zero nlink but its nodes weren't yet marked - obsolete. This has to be because we're still waiting for - the final (close() and) jffs2_iput() to happen. - - There's a possibility that the final jffs2_iput() could have - happened while we were contemplating. In order to ensure - that we don't cause a new read_inode() (which would fail) - for the inode in question, we use ilookup() in this case - instead of jffs2_iget(). - - The nlink can't _become_ zero at this point because we're - holding the alloc_sem, and jffs2_do_unlink() would also - need that while decrementing nlink on any inode. - */ - inode = ilookup(OFNI_BS_2SFFJ(c), inum); - if (!inode) { - D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n", - inum)); - - spin_lock(&c->inocache_lock); - ic = jffs2_get_ino_cache(c, inum); - if (!ic) { - D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum)); - spin_unlock(&c->inocache_lock); - return NULL; - } - if (ic->state != INO_STATE_CHECKEDABSENT) { - /* Wait for progress. Don't just loop */ - D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n", - ic->ino, ic->state)); - sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - } else { - spin_unlock(&c->inocache_lock); - } - - return NULL; - } - } else { - /* Inode has links to it still; they're not going away because - jffs2_do_unlink() would need the alloc_sem and we have it. - Just jffs2_iget() it, and if read_inode() is necessary that's OK. - */ - inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum); - if (IS_ERR(inode)) - return (void *)inode; - } - - return JFFS2_INODE_INFO(inode); -} - - - -uint32_t jffs2_from_os_mode(uint32_t osmode) -{ - uint32_t jmode = ((osmode & S_IRUSR)?00400:0) | - ((osmode & S_IWUSR)?00200:0) | - ((osmode & S_IXUSR)?00100:0) | - ((osmode & S_IRGRP)?00040:0) | - ((osmode & S_IWGRP)?00020:0) | - ((osmode & S_IXGRP)?00010:0) | - ((osmode & S_IROTH)?00004:0) | - ((osmode & S_IWOTH)?00002:0) | - ((osmode & S_IXOTH)?00001:0); - - switch (osmode & S_IFMT) { -// case S_IFSOCK: -// return jmode | 0140000; -// case S_IFLNK: -// return jmode | 0120000; - case S_IFREG: - return jmode | 0100000; - case S_IFBLK: - return jmode | 0060000; - case S_IFDIR: - return jmode | 0040000; - case S_IFCHR: - return jmode | 0020000; - case S_IFIFO: - return jmode | 0010000; - case S_ISUID: - return jmode | 0004000; - case S_ISGID: - return jmode | 0002000; -#ifdef S_ISVTX - case S_ISVTX: - return jmode | 0001000; -#endif - } - printf("os_to_jffs2_mode() cannot convert 0x%x\n", osmode); - BUG(); - return 0; -} - -uint32_t jffs2_to_os_mode (uint32_t jmode) -{ - uint32_t osmode = ((jmode & 00400)?S_IRUSR:0) | - ((jmode & 00200)?S_IWUSR:0) | - ((jmode & 00100)?S_IXUSR:0) | - ((jmode & 00040)?S_IRGRP:0) | - ((jmode & 00020)?S_IWGRP:0) | - ((jmode & 00010)?S_IXGRP:0) | - ((jmode & 00004)?S_IROTH:0) | - ((jmode & 00002)?S_IWOTH:0) | - ((jmode & 00001)?S_IXOTH:0); - - switch(jmode & 00170000) { -// case 0140000: prife -// return osmode | S_IFSOCK; prife -// case 0120000: prife -// return osmode | S_IFLNK; prife - case 0100000: - return osmode | S_IFREG; - case 0060000: - return osmode | S_IFBLK; - case 0040000: - return osmode | S_IFDIR; - case 0020000: - return osmode | S_IFCHR; - case 0010000: - return osmode | S_IFIFO; - case 0004000: - return osmode | S_ISUID; - case 0002000: - return osmode | S_ISGID; -#ifdef S_ISVTX - case 0001000: - return osmode | S_ISVTX; -#endif - } - printf("jffs2_to_os_mode() cannot convert 0x%x\n", osmode); - BUG(); - return 0; -} diff --git a/components/dfs/filesystems/jffs2/src/gc.c b/components/dfs/filesystems/jffs2/src/gc.c deleted file mode 100644 index 34ad6ca547..0000000000 --- a/components/dfs/filesystems/jffs2/src/gc.c +++ /dev/null @@ -1,1271 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: gc.c,v 1.152 2005/07/24 15:14:14 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "nodelist.h" -#include "compr.h" - -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, - struct jffs2_inode_cache *ic, - struct jffs2_raw_node_ref *raw); -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dnode *fd); -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); -static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, - uint32_t start, uint32_t end); -static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, - uint32_t start, uint32_t end); -static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f); - -/* Called with erase_completion_lock held */ -static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) -{ - struct jffs2_eraseblock *ret; - struct list_head *nextlist = NULL; - int n = jiffies % 128; - - /* Pick an eraseblock to garbage collect next. This is where we'll - put the clever wear-levelling algorithms. Eventually. */ - /* We possibly want to favour the dirtier blocks more when the - number of free blocks is low. */ -again: - if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > c->resv_blocks_gcbad) { - D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); - nextlist = &c->bad_used_list; - } else if (n < 50 && !list_empty(&c->erasable_list)) { - /* Note that most of them will have gone directly to be erased. - So don't favour the erasable_list _too_ much. */ - D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); - nextlist = &c->erasable_list; - } else if (n < 110 && !list_empty(&c->very_dirty_list)) { - /* Most of the time, pick one off the very_dirty list */ - D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next\n")); - nextlist = &c->very_dirty_list; - } else if (n < 126 && !list_empty(&c->dirty_list)) { - D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n")); - nextlist = &c->dirty_list; - } else if (!list_empty(&c->clean_list)) { - D1(printk(KERN_DEBUG "Picking block from clean_list to GC next\n")); - nextlist = &c->clean_list; - } else if (!list_empty(&c->dirty_list)) { - D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n")); - - nextlist = &c->dirty_list; - } else if (!list_empty(&c->very_dirty_list)) { - D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n")); - nextlist = &c->very_dirty_list; - } else if (!list_empty(&c->erasable_list)) { - D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n")); - - nextlist = &c->erasable_list; - } else if (!list_empty(&c->erasable_pending_wbuf_list)) { - /* There are blocks are wating for the wbuf sync */ - D1(printk(KERN_DEBUG "Synching wbuf in order to reuse erasable_pending_wbuf_list blocks\n")); - spin_unlock(&c->erase_completion_lock); - jffs2_flush_wbuf_pad(c); - spin_lock(&c->erase_completion_lock); - goto again; - } else { - /* Eep. All were empty */ - D1(printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n")); - return NULL; - } - - ret = list_entry(nextlist->next, struct jffs2_eraseblock, list); - list_del(&ret->list); - c->gcblock = ret; - ret->gc_node = ret->first_node; - if (!ret->gc_node) { - printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); - BUG(); - } - - /* Have we accidentally picked a clean block with wasted space ? */ - if (ret->wasted_size) { - D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size)); - ret->dirty_size += ret->wasted_size; - c->wasted_size -= ret->wasted_size; - c->dirty_size += ret->wasted_size; - ret->wasted_size = 0; - } - - return ret; -} - -/* jffs2_garbage_collect_pass - * Make a single attempt to progress GC. Move one node, and possibly - * start erasing one eraseblock. - */ -int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) -{ - struct jffs2_inode_info *f; - struct jffs2_inode_cache *ic; - struct jffs2_eraseblock *jeb; - struct jffs2_raw_node_ref *raw; - int ret = 0, inum, nlink; - - if (down_interruptible(&c->alloc_sem)) - return -EINTR; - - for (;;) { - spin_lock(&c->erase_completion_lock); - if (!c->unchecked_size) - break; - - /* We can't start doing GC yet. We haven't finished checking - the node CRCs etc. Do it now. */ - - /* checked_ino is protected by the alloc_sem */ - if (c->checked_ino > c->highest_ino) { - printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", - c->unchecked_size); - jffs2_dbg_dump_block_lists_nolock(c); - spin_unlock(&c->erase_completion_lock); - BUG(); - } - - spin_unlock(&c->erase_completion_lock); - - spin_lock(&c->inocache_lock); - - ic = jffs2_get_ino_cache(c, c->checked_ino++); - - if (!ic) { - spin_unlock(&c->inocache_lock); - continue; - } - - if (!ic->nlink) { - D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", - ic->ino)); - spin_unlock(&c->inocache_lock); - continue; - } - switch(ic->state) { - case INO_STATE_CHECKEDABSENT: - case INO_STATE_PRESENT: - D1(printk(KERN_DEBUG "Skipping ino #%u already checked\n", ic->ino)); - spin_unlock(&c->inocache_lock); - continue; - - case INO_STATE_GC: - case INO_STATE_CHECKING: - printk(KERN_WARNING "Inode #%u is in state %d during CRC check phase!\n", ic->ino, ic->state); - spin_unlock(&c->inocache_lock); - BUG(); - - case INO_STATE_READING: - /* We need to wait for it to finish, lest we move on - and trigger the BUG() above while we haven't yet - finished checking all its nodes */ - D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); - up(&c->alloc_sem); - sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - return 0; - - default: - BUG(); - - case INO_STATE_UNCHECKED: - ; - } - ic->state = INO_STATE_CHECKING; - spin_unlock(&c->inocache_lock); - - D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() triggering inode scan of ino#%u\n", ic->ino)); - - ret = jffs2_do_crccheck_inode(c, ic); - if (ret) - printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino); - - jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT); - up(&c->alloc_sem); - return ret; - } - - /* First, work out which block we're garbage-collecting */ - jeb = c->gcblock; - - if (!jeb) - jeb = jffs2_find_gc_block(c); - - if (!jeb) { - D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n")); - spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - return -EIO; - } - - D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size)); - D1(if (c->nextblock) - printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size)); - - if (!jeb->used_size) { - up(&c->alloc_sem); - goto eraseit; - } - - raw = jeb->gc_node; - - while(ref_obsolete(raw)) { - D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); - raw = raw->next_phys; - if (unlikely(!raw)) { - printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); - printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); - jeb->gc_node = raw; - spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - BUG(); - } - } - jeb->gc_node = raw; - - D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", ref_offset(raw))); - - if (!raw->next_in_ino) { - /* Inode-less node. Clean marker, snapshot or something like that */ - /* FIXME: If it's something that needs to be copied, including something - we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ - spin_unlock(&c->erase_completion_lock); - jffs2_mark_node_obsolete(c, raw); - up(&c->alloc_sem); - goto eraseit_lock; - } - - ic = jffs2_raw_ref_to_ic(raw); - - /* We need to hold the inocache. Either the erase_completion_lock or - the inocache_lock are sufficient; we trade down since the inocache_lock - causes less contention. */ - spin_lock(&c->inocache_lock); - - spin_unlock(&c->erase_completion_lock); - - D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x(%d), ino #%u\n", jeb->offset, ref_offset(raw), ref_flags(raw), ic->ino)); - - /* Three possibilities: - 1. Inode is already in-core. We must iget it and do proper - updating to its fragtree, etc. - 2. Inode is not in-core, node is REF_PRISTINE. We lock the - inocache to prevent a read_inode(), copy the node intact. - 3. Inode is not in-core, node is not pristine. We must iget() - and take the slow path. - */ - - switch(ic->state) { - case INO_STATE_CHECKEDABSENT: - /* It's been checked, but it's not currently in-core. - We can just copy any pristine nodes, but have - to prevent anyone else from doing read_inode() while - we're at it, so we set the state accordingly */ - if (ref_flags(raw) == REF_PRISTINE) - ic->state = INO_STATE_GC; - else { - D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", - ic->ino)); - } - break; - - case INO_STATE_PRESENT: - /* It's in-core. GC must iget() it. */ - break; - - case INO_STATE_UNCHECKED: - case INO_STATE_CHECKING: - case INO_STATE_GC: - /* Should never happen. We should have finished checking - by the time we actually start doing any GC, and since - we're holding the alloc_sem, no other garbage collection - can happen. - */ - printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", - ic->ino, ic->state); - up(&c->alloc_sem); - spin_unlock(&c->inocache_lock); - BUG(); - - case INO_STATE_READING: - /* Someone's currently trying to read it. We must wait for - them to finish and then go through the full iget() route - to do the GC. However, sometimes read_inode() needs to get - the alloc_sem() (for marking nodes invalid) so we must - drop the alloc_sem before sleeping. */ - - up(&c->alloc_sem); - D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", - ic->ino, ic->state)); - sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - /* And because we dropped the alloc_sem we must start again from the - beginning. Ponder chance of livelock here -- we're returning success - without actually making any progress. - - Q: What are the chances that the inode is back in INO_STATE_READING - again by the time we next enter this function? And that this happens - enough times to cause a real delay? - - A: Small enough that I don't care :) - */ - return 0; - } - - /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the - node intact, and we don't have to muck about with the fragtree etc. - because we know it's not in-core. If it _was_ in-core, we go through - all the iget() crap anyway */ - - if (ic->state == INO_STATE_GC) { - spin_unlock(&c->inocache_lock); - - ret = jffs2_garbage_collect_pristine(c, ic, raw); - - spin_lock(&c->inocache_lock); - ic->state = INO_STATE_CHECKEDABSENT; - wake_up(&c->inocache_wq); - - if (ret != -EBADFD) { - spin_unlock(&c->inocache_lock); - goto release_sem; - } - - /* Fall through if it wanted us to, with inocache_lock held */ - } - - /* Prevent the fairly unlikely race where the gcblock is - entirely obsoleted by the final close of a file which had - the only valid nodes in the block, followed by erasure, - followed by freeing of the ic because the erased block(s) - held _all_ the nodes of that inode.... never been seen but - it's vaguely possible. */ - - inum = ic->ino; - nlink = ic->nlink; - spin_unlock(&c->inocache_lock); - - f = jffs2_gc_fetch_inode(c, inum, nlink); - if (IS_ERR(f)) { - ret = PTR_ERR(f); - goto release_sem; - } - if (!f) { - ret = 0; - goto release_sem; - } - - ret = jffs2_garbage_collect_live(c, jeb, raw, f); - - jffs2_gc_release_inode(c, f); - - release_sem: - up(&c->alloc_sem); - - eraseit_lock: - /* If we've finished this block, start it erasing */ - spin_lock(&c->erase_completion_lock); - - eraseit: - if (c->gcblock && !c->gcblock->used_size) { - D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", c->gcblock->offset)); - /* We're GC'ing an empty block? */ - list_add_tail(&c->gcblock->list, &c->erase_pending_list); - c->gcblock = NULL; - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); - } - spin_unlock(&c->erase_completion_lock); - - return ret; -} - -static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *raw, struct jffs2_inode_info *f) -{ - struct jffs2_node_frag *frag; - struct jffs2_full_dnode *fn = NULL; - struct jffs2_full_dirent *fd; - uint32_t start = 0, end = 0, nrfrags = 0; - int ret = 0; - - down(&f->sem); - - /* Now we have the lock for this inode. Check that it's still the one at the head - of the list. */ - - spin_lock(&c->erase_completion_lock); - - if (c->gcblock != jeb) { - spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "GC block is no longer gcblock. Restart\n")); - goto upnout; - } - if (ref_obsolete(raw)) { - spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "node to be GC'd was obsoleted in the meantime.\n")); - /* They'll call again */ - goto upnout; - } - spin_unlock(&c->erase_completion_lock); - - /* OK. Looks safe. And nobody can get us now because we have the semaphore. Move the block */ - if (f->metadata && f->metadata->raw == raw) { - fn = f->metadata; - ret = jffs2_garbage_collect_metadata(c, jeb, f, fn); - goto upnout; - } - - /* FIXME. Read node and do lookup? */ - for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { - if (frag->node && frag->node->raw == raw) { - fn = frag->node; - end = frag->ofs + frag->size; - if (!nrfrags++) - start = frag->ofs; - if (nrfrags == frag->node->frags) - break; /* We've found them all */ - } - } - if (fn) { - if (ref_flags(raw) == REF_PRISTINE) { - ret = jffs2_garbage_collect_pristine(c, f->inocache, raw); - if (!ret) { - /* Urgh. Return it sensibly. */ - frag->node->raw = f->inocache->nodes; - } - if (ret != -EBADFD) - goto upnout; - } - /* We found a datanode. Do the GC */ - if((start >> PAGE_CACHE_SHIFT) < ((end-1) >> PAGE_CACHE_SHIFT)) { - /* It crosses a page boundary. Therefore, it must be a hole. */ - ret = jffs2_garbage_collect_hole(c, jeb, f, fn, start, end); - } else { - /* It could still be a hole. But we GC the page this way anyway */ - ret = jffs2_garbage_collect_dnode(c, jeb, f, fn, start, end); - } - goto upnout; - } - - /* Wasn't a dnode. Try dirent */ - for (fd = f->dents; fd; fd=fd->next) { - if (fd->raw == raw) - break; - } - - if (fd && fd->ino) { - ret = jffs2_garbage_collect_dirent(c, jeb, f, fd); - } else if (fd) { - ret = jffs2_garbage_collect_deletion_dirent(c, jeb, f, fd); - } else { - printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%u\n", - ref_offset(raw), f->inocache->ino); - if (ref_obsolete(raw)) { - printk(KERN_WARNING "But it's obsolete so we don't mind too much\n"); - } else { - jffs2_dbg_dump_node(c, ref_offset(raw)); - BUG(); - } - } - upnout: - up(&f->sem); - - return ret; -} - -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, - struct jffs2_inode_cache *ic, - struct jffs2_raw_node_ref *raw) -{ - union jffs2_node_union *node; - struct jffs2_raw_node_ref *nraw; - size_t retlen; - int ret; - uint32_t phys_ofs, alloclen; - uint32_t crc, rawlen; - int retried = 0; - - D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); - - rawlen = ref_totlen(c, c->gcblock, raw); - - /* Ask for a small amount of space (or the totlen if smaller) because we - don't want to force wastage of the end of a block if splitting would - work. */ - ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN, - rawlen), &phys_ofs, &alloclen); - if (ret) - return ret; - - if (alloclen < rawlen) { - /* Doesn't fit untouched. We'll go the old route and split it */ - return -EBADFD; - } - - node = kmalloc(rawlen, GFP_KERNEL); - if (!node) - return -ENOMEM; - - ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (unsigned char *)node); - if (!ret && retlen != rawlen) - ret = -EIO; - if (ret) - goto out_node; - - crc = crc32(0, node, sizeof(struct jffs2_unknown_node)-4); - if (je32_to_cpu(node->u.hdr_crc) != crc) { - printk(KERN_WARNING "Header CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ref_offset(raw), je32_to_cpu(node->u.hdr_crc), crc); - goto bail; - } - - switch(je16_to_cpu(node->u.nodetype)) { - case JFFS2_NODETYPE_INODE: - crc = crc32(0, node, sizeof(node->i)-8); - if (je32_to_cpu(node->i.node_crc) != crc) { - printk(KERN_WARNING "Node CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ref_offset(raw), je32_to_cpu(node->i.node_crc), crc); - goto bail; - } - - if (je32_to_cpu(node->i.dsize)) { - crc = crc32(0, node->i.data, je32_to_cpu(node->i.csize)); - if (je32_to_cpu(node->i.data_crc) != crc) { - printk(KERN_WARNING "Data CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ref_offset(raw), je32_to_cpu(node->i.data_crc), crc); - goto bail; - } - } - break; - - case JFFS2_NODETYPE_DIRENT: - crc = crc32(0, node, sizeof(node->d)-8); - if (je32_to_cpu(node->d.node_crc) != crc) { - printk(KERN_WARNING "Node CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ref_offset(raw), je32_to_cpu(node->d.node_crc), crc); - goto bail; - } - - if (node->d.nsize) { - crc = crc32(0, node->d.name, node->d.nsize); - if (je32_to_cpu(node->d.name_crc) != crc) { - printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ref_offset(raw), je32_to_cpu(node->d.name_crc), crc); - goto bail; - } - } - break; - default: - printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", - ref_offset(raw), je16_to_cpu(node->u.nodetype)); - goto bail; - } - - nraw = jffs2_alloc_raw_node_ref(); - if (!nraw) { - ret = -ENOMEM; - goto out_node; - } - - /* OK, all the CRCs are good; this node can just be copied as-is. */ - retry: - nraw->flash_offset = phys_ofs; - nraw->__totlen = rawlen; - nraw->next_phys = NULL; - - ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (unsigned char *)node); - - if (ret || (retlen != rawlen)) { - printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", - rawlen, phys_ofs, ret, retlen); - if (retlen) { - /* Doesn't belong to any inode */ - nraw->next_in_ino = NULL; - - nraw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, nraw); - jffs2_mark_node_obsolete(c, nraw); - } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); - jffs2_free_raw_node_ref(nraw); - } - if (!retried && (nraw = jffs2_alloc_raw_node_ref())) { - /* Try to reallocate space and retry */ - uint32_t dummy; - struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; - - retried = 1; - - D1(printk(KERN_DEBUG "Retrying failed write of REF_PRISTINE node.\n")); - - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); - - ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy); - - if (!ret) { - D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", phys_ofs)); - - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); - - goto retry; - } - D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); - jffs2_free_raw_node_ref(nraw); - } - - jffs2_free_raw_node_ref(nraw); - if (!ret) - ret = -EIO; - goto out_node; - } - nraw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, nraw); - - /* Link into per-inode list. This is safe because of the ic - state being INO_STATE_GC. Note that if we're doing this - for an inode which is in-core, the 'nraw' pointer is then - going to be fetched from ic->nodes by our caller. */ - spin_lock(&c->erase_completion_lock); - nraw->next_in_ino = ic->nodes; - ic->nodes = nraw; - spin_unlock(&c->erase_completion_lock); - - jffs2_mark_node_obsolete(c, raw); - D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); - - out_node: - kfree(node); - return ret; - bail: - ret = -EBADFD; - goto out_node; -} - -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) -{ - struct jffs2_full_dnode *new_fn; - struct jffs2_raw_inode ri; - struct jffs2_node_frag *last_frag; - jint16_t dev; - char *mdata = NULL, mdatalen = 0; - uint32_t alloclen, phys_ofs, ilen; - int ret; - - if (S_ISBLK(JFFS2_F_I_MODE(f)) || - S_ISCHR(JFFS2_F_I_MODE(f)) ) { - /* For these, we don't actually need to read the old node */ - /* FIXME: for minor or major > 255. */ - dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | - JFFS2_F_I_RDEV_MIN(f))); - mdata = (char *)&dev; - mdatalen = sizeof(dev); - D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); - } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { - mdatalen = fn->size; - mdata = kmalloc(fn->size, GFP_KERNEL); - if (!mdata) { - printk(KERN_WARNING "kmalloc of mdata failed in jffs2_garbage_collect_metadata()\n"); - return -ENOMEM; - } - ret = jffs2_read_dnode(c, f, fn, (unsigned char *)mdata, 0, mdatalen); - if (ret) { - printk(KERN_WARNING "read of old metadata failed in jffs2_garbage_collect_metadata(): %d\n", ret); - kfree(mdata); - return ret; - } - D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bites of symlink target\n", mdatalen)); - - } - - ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen); - if (ret) { - printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", - sizeof(ri)+ mdatalen, ret); - goto out; - } - - last_frag = frag_last(&f->fragtree); - if (last_frag) - /* Fetch the inode length from the fragtree rather then - * from i_size since i_size may have not been updated yet */ - ilen = last_frag->ofs + last_frag->size; - else - ilen = JFFS2_F_I_SIZE(f); - - memset(&ri, 0, sizeof(ri)); - ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); - ri.totlen = cpu_to_je32(sizeof(ri) + mdatalen); - ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); - - ri.ino = cpu_to_je32(f->inocache->ino); - ri.version = cpu_to_je32(++f->highest_version); - ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); - ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); - ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); - ri.isize = cpu_to_je32(ilen); - ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); - ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); - ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); - ri.offset = cpu_to_je32(0); - ri.csize = cpu_to_je32(mdatalen); - ri.dsize = cpu_to_je32(mdatalen); - ri.compr = JFFS2_COMPR_NONE; - ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); - - new_fn = jffs2_write_dnode(c, f, &ri, (const unsigned char *)mdata, mdatalen, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); - ret = PTR_ERR(new_fn); - goto out; - } - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); - f->metadata = new_fn; - out: - if (S_ISLNK(JFFS2_F_I_MODE(f))) - kfree(mdata); - return ret; -} - -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) -{ - struct jffs2_full_dirent *new_fd; - struct jffs2_raw_dirent rd; - uint32_t alloclen, phys_ofs; - int ret; - - rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd.nsize = strlen((const char *)fd->name); - rd.totlen = cpu_to_je32(sizeof(rd) + rd.nsize); - rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4)); - - rd.pino = cpu_to_je32(f->inocache->ino); - rd.version = cpu_to_je32(++f->highest_version); - rd.ino = cpu_to_je32(fd->ino); - rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f))); - rd.type = fd->type; - rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); - rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - - ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen); - if (ret) { - printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", - sizeof(rd)+rd.nsize, ret); - return ret; - } - new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fd)) { - printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd)); - return PTR_ERR(new_fd); - } - jffs2_add_fd_to_list(c, new_fd, &f->dents); - return 0; -} - -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) -{ - struct jffs2_full_dirent **fdp = &f->dents; - int found = 0; - - /* On a medium where we can't actually mark nodes obsolete - pernamently, such as NAND flash, we need to work out - whether this deletion dirent is still needed to actively - delete a 'real' dirent with the same name that's still - somewhere else on the flash. */ - if (!jffs2_can_mark_obsolete(c)) { - struct jffs2_raw_dirent *rd; - struct jffs2_raw_node_ref *raw; - int ret; - size_t retlen; - int name_len = strlen((const char *)fd->name); - uint32_t name_crc = crc32(0, fd->name, name_len); - uint32_t rawlen = ref_totlen(c, jeb, fd->raw); - - rd = kmalloc(rawlen, GFP_KERNEL); - if (!rd) - return -ENOMEM; - - /* Prevent the erase code from nicking the obsolete node refs while - we're looking at them. I really don't like this extra lock but - can't see any alternative. Suggestions on a postcard to... */ - down(&c->erase_free_sem); - - for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { - - /* We only care about obsolete ones */ - if (!(ref_obsolete(raw))) - continue; - - /* Any dirent with the same name is going to have the same length... */ - if (ref_totlen(c, NULL, raw) != rawlen) - continue; - - /* Doesn't matter if there's one in the same erase block. We're going to - delete it too at the same time. */ - if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset)) - continue; - - D1(printk(KERN_DEBUG "Check potential deletion dirent at %08x\n", ref_offset(raw))); - - /* This is an obsolete node belonging to the same directory, and it's of the right - length. We need to take a closer look...*/ - ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (unsigned char *)rd); - if (ret) { - printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading obsolete node at %08x\n", ret, ref_offset(raw)); - /* If we can't read it, we don't need to continue to obsolete it. Continue */ - continue; - } - if (retlen != rawlen) { - printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %u) reading header from obsolete node at %08x\n", - retlen, rawlen, ref_offset(raw)); - continue; - } - - if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT) - continue; - - /* If the name CRC doesn't match, skip */ - if (je32_to_cpu(rd->name_crc) != name_crc) - continue; - - /* If the name length doesn't match, or it's another deletion dirent, skip */ - if (rd->nsize != name_len || !je32_to_cpu(rd->ino)) - continue; - - /* OK, check the actual name now */ - if (memcmp(rd->name, fd->name, name_len)) - continue; - - /* OK. The name really does match. There really is still an older node on - the flash which our deletion dirent obsoletes. So we have to write out - a new deletion dirent to replace it */ - up(&c->erase_free_sem); - - D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n", - ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino))); - kfree(rd); - - return jffs2_garbage_collect_dirent(c, jeb, f, fd); - } - - up(&c->erase_free_sem); - kfree(rd); - } - - /* No need for it any more. Just mark it obsolete and remove it from the list */ - while (*fdp) { - if ((*fdp) == fd) { - found = 1; - *fdp = fd->next; - break; - } - fdp = &(*fdp)->next; - } - if (!found) { - printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%u\n", fd->name, f->inocache->ino); - } - jffs2_mark_node_obsolete(c, fd->raw); - jffs2_free_full_dirent(fd); - return 0; -} - -static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, - uint32_t start, uint32_t end) -{ - struct jffs2_raw_inode ri; - struct jffs2_node_frag *frag; - struct jffs2_full_dnode *new_fn; - uint32_t alloclen, phys_ofs, ilen; - int ret; - - D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", - f->inocache->ino, start, end)); - - memset(&ri, 0, sizeof(ri)); - - if(fn->frags > 1) { - size_t readlen; - uint32_t crc; - /* It's partially obsoleted by a later write. So we have to - write it out again with the _same_ version as before */ - ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (unsigned char *)&ri); - if (readlen != sizeof(ri) || ret) { - printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %zd. Data will be lost by writing new hole node\n", ret, readlen); - goto fill; - } - if (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n", - ref_offset(fn->raw), - je16_to_cpu(ri.nodetype), JFFS2_NODETYPE_INODE); - return -EIO; - } - if (je32_to_cpu(ri.totlen) != sizeof(ri)) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%zx\n", - ref_offset(fn->raw), - je32_to_cpu(ri.totlen), sizeof(ri)); - return -EIO; - } - crc = crc32(0, &ri, sizeof(ri)-8); - if (crc != je32_to_cpu(ri.node_crc)) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", - ref_offset(fn->raw), - je32_to_cpu(ri.node_crc), crc); - /* FIXME: We could possibly deal with this by writing new holes for each frag */ - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", - start, end, f->inocache->ino); - goto fill; - } - if (ri.compr != JFFS2_COMPR_ZERO) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", ref_offset(fn->raw)); - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", - start, end, f->inocache->ino); - goto fill; - } - } else { - fill: - ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); - ri.totlen = cpu_to_je32(sizeof(ri)); - ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); - - ri.ino = cpu_to_je32(f->inocache->ino); - ri.version = cpu_to_je32(++f->highest_version); - ri.offset = cpu_to_je32(start); - ri.dsize = cpu_to_je32(end - start); - ri.csize = cpu_to_je32(0); - ri.compr = JFFS2_COMPR_ZERO; - } - - frag = frag_last(&f->fragtree); - if (frag) - /* Fetch the inode length from the fragtree rather then - * from i_size since i_size may have not been updated yet */ - ilen = frag->ofs + frag->size; - else - ilen = JFFS2_F_I_SIZE(f); - - ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); - ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); - ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); - ri.isize = cpu_to_je32(ilen); - ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); - ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); - ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); - ri.data_crc = cpu_to_je32(0); - ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - - ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen); - if (ret) { - printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", - sizeof(ri), ret); - return ret; - } - new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); - return PTR_ERR(new_fn); - } - if (je32_to_cpu(ri.version) == f->highest_version) { - jffs2_add_full_dnode_to_inode(c, f, new_fn); - if (f->metadata) { - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - } - return 0; - } - - /* - * We should only get here in the case where the node we are - * replacing had more than one frag, so we kept the same version - * number as before. (Except in case of error -- see 'goto fill;' - * above.) - */ - D1(if(unlikely(fn->frags <= 1)) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n", - fn->frags, je32_to_cpu(ri.version), f->highest_version, - je32_to_cpu(ri.ino)); - }); - - /* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */ - mark_ref_normal(new_fn->raw); - - for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); - frag; frag = frag_next(frag)) { - if (frag->ofs > fn->size + fn->ofs) - break; - if (frag->node == fn) { - frag->node = new_fn; - new_fn->frags++; - fn->frags--; - } - } - if (fn->frags) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: Old node still has frags!\n"); - BUG(); - } - if (!new_fn->frags) { - printk(KERN_WARNING "jffs2_garbage_collect_hole: New node has no frags!\n"); - BUG(); - } - - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); - - return 0; -} - -static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, - uint32_t start, uint32_t end) -{ - struct jffs2_full_dnode *new_fn; - struct jffs2_raw_inode ri; - uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; - int ret = 0; - unsigned char *comprbuf = NULL, *writebuf; - unsigned long pg; - unsigned char *pg_ptr; - - memset(&ri, 0, sizeof(ri)); - - D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n", - f->inocache->ino, start, end)); - - orig_end = end; - orig_start = start; - - if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) { - /* Attempt to do some merging. But only expand to cover logically - adjacent frags if the block containing them is already considered - to be dirty. Otherwise we end up with GC just going round in - circles dirtying the nodes it already wrote out, especially - on NAND where we have small eraseblocks and hence a much higher - chance of nodes having to be split to cross boundaries. */ - - struct jffs2_node_frag *frag; - uint32_t min, max; - - min = start & ~(PAGE_CACHE_SIZE-1); - max = min + PAGE_CACHE_SIZE; - - frag = jffs2_lookup_node_frag(&f->fragtree, start); - - /* BUG_ON(!frag) but that'll happen anyway... */ - - BUG_ON(frag->ofs != start); - - /* First grow down... */ - while((frag = frag_prev(frag)) && frag->ofs >= min) { - - /* If the previous frag doesn't even reach the beginning, there's - excessive fragmentation. Just merge. */ - if (frag->ofs > min) { - D1(printk(KERN_DEBUG "Expanding down to cover partial frag (0x%x-0x%x)\n", - frag->ofs, frag->ofs+frag->size)); - start = frag->ofs; - continue; - } - /* OK. This frag holds the first byte of the page. */ - if (!frag->node || !frag->node->raw) { - D1(printk(KERN_DEBUG "First frag in page is hole (0x%x-0x%x). Not expanding down.\n", - frag->ofs, frag->ofs+frag->size)); - break; - } else { - - /* OK, it's a frag which extends to the beginning of the page. Does it live - in a block which is still considered clean? If so, don't obsolete it. - If not, cover it anyway. */ - - struct jffs2_raw_node_ref *raw = frag->node->raw; - struct jffs2_eraseblock *jeb; - - jeb = &c->blocks[raw->flash_offset / c->sector_size]; - - if (jeb == c->gcblock) { - D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in gcblock at %08x\n", - frag->ofs, frag->ofs+frag->size, ref_offset(raw))); - start = frag->ofs; - break; - } - if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { - D1(printk(KERN_DEBUG "Not expanding down to cover frag (0x%x-0x%x) in clean block %08x\n", - frag->ofs, frag->ofs+frag->size, jeb->offset)); - break; - } - - D1(printk(KERN_DEBUG "Expanding down to cover frag (0x%x-0x%x) in dirty block %08x\n", - frag->ofs, frag->ofs+frag->size, jeb->offset)); - start = frag->ofs; - break; - } - } - - /* ... then up */ - - /* Find last frag which is actually part of the node we're to GC. */ - frag = jffs2_lookup_node_frag(&f->fragtree, end-1); - - while((frag = frag_next(frag)) && frag->ofs+frag->size <= max) { - - /* If the previous frag doesn't even reach the beginning, there's lots - of fragmentation. Just merge. */ - if (frag->ofs+frag->size < max) { - D1(printk(KERN_DEBUG "Expanding up to cover partial frag (0x%x-0x%x)\n", - frag->ofs, frag->ofs+frag->size)); - end = frag->ofs + frag->size; - continue; - } - - if (!frag->node || !frag->node->raw) { - D1(printk(KERN_DEBUG "Last frag in page is hole (0x%x-0x%x). Not expanding up.\n", - frag->ofs, frag->ofs+frag->size)); - break; - } else { - - /* OK, it's a frag which extends to the beginning of the page. Does it live - in a block which is still considered clean? If so, don't obsolete it. - If not, cover it anyway. */ - - struct jffs2_raw_node_ref *raw = frag->node->raw; - struct jffs2_eraseblock *jeb; - - jeb = &c->blocks[raw->flash_offset / c->sector_size]; - - if (jeb == c->gcblock) { - D1(printk(KERN_DEBUG "Expanding up to cover frag (0x%x-0x%x) in gcblock at %08x\n", - frag->ofs, frag->ofs+frag->size, ref_offset(raw))); - end = frag->ofs + frag->size; - break; - } - if (!ISDIRTY(jeb->dirty_size + jeb->wasted_size)) { - D1(printk(KERN_DEBUG "Not expanding up to cover frag (0x%x-0x%x) in clean block %08x\n", - frag->ofs, frag->ofs+frag->size, jeb->offset)); - break; - } - - D1(printk(KERN_DEBUG "Expanding up to cover frag (0x%x-0x%x) in dirty block %08x\n", - frag->ofs, frag->ofs+frag->size, jeb->offset)); - end = frag->ofs + frag->size; - break; - } - } - D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", - orig_start, orig_end, start, end)); - - D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size)); - BUG_ON(end < orig_end); - BUG_ON(start > orig_start); - } - - /* First, use readpage() to read the appropriate page into the page cache */ - /* Q: What happens if we actually try to GC the _same_ page for which commit_write() - * triggered garbage collection in the first place? - * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the - * page OK. We'll actually write it out again in commit_write, which is a little - * suboptimal, but at least we're correct. - */ - pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); - - if (IS_ERR(pg_ptr)) { - printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg_ptr)); - return PTR_ERR(pg_ptr); - } - - offset = start; - while(offset < orig_end) { - uint32_t datalen; - uint32_t cdatalen; - uint16_t comprtype = JFFS2_COMPR_NONE; - - ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen); - - if (ret) { - printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n", - sizeof(ri)+ JFFS2_MIN_DATA_LEN, ret); - break; - } - cdatalen = min_t(uint32_t, alloclen - sizeof(ri), end - offset); - datalen = end - offset; - - writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1)); - - comprtype = jffs2_compress(c, f, writebuf, &comprbuf, &datalen, &cdatalen); - - ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); - ri.totlen = cpu_to_je32(sizeof(ri) + cdatalen); - ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4)); - - ri.ino = cpu_to_je32(f->inocache->ino); - ri.version = cpu_to_je32(++f->highest_version); - ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); - ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); - ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); - ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); - ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); - ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); - ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); - ri.offset = cpu_to_je32(offset); - ri.csize = cpu_to_je32(cdatalen); - ri.dsize = cpu_to_je32(datalen); - ri.compr = comprtype & 0xff; - ri.usercompr = (comprtype >> 8) & 0xff; - ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); - - new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); - - jffs2_free_comprbuf(comprbuf, writebuf); - - if (IS_ERR(new_fn)) { - printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); - ret = PTR_ERR(new_fn); - break; - } - ret = jffs2_add_full_dnode_to_inode(c, f, new_fn); - offset += datalen; - if (f->metadata) { - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - } - } - - jffs2_gc_release_page(c, pg_ptr, &pg); - return ret; -} - diff --git a/components/dfs/filesystems/jffs2/src/gcthread.c b/components/dfs/filesystems/jffs2/src/gcthread.c deleted file mode 100644 index ab66e1878e..0000000000 --- a/components/dfs/filesystems/jffs2/src/gcthread.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: gcthread.c,v 1.3 2005/01/22 16:01:12 lunn Exp $ - * - */ -#include -#include "nodelist.h" -//#include prife - -#if defined(CYGOPT_FS_JFFS2_GCTHREAD) - -#define GC_THREAD_FLAG_TRIG 1 -#define GC_THREAD_FLAG_STOP 2 -#define GC_THREAD_FLAG_HAS_EXIT 4 - -#if 0 -static cyg_thread_entry_t jffs2_garbage_collect_thread; - -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) -{ - struct super_block *sb=OFNI_BS_2SFFJ(c); - - /* Wake up the thread */ - D1(printk("jffs2_garbage_collect_trigger\n")); - - cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_TRIG); -} - - -void -jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) -{ - struct super_block *sb=OFNI_BS_2SFFJ(c); - - RT_ASSERT(c); - RT_ASSERT(!sb->s_gc_thread_handle); - - cyg_flag_init(&sb->s_gc_thread_flags); - cyg_mutex_init(&sb->s_lock); - - D1(printk("jffs2_start_garbage_collect_thread\n")); - /* Start the thread. Doesn't matter if it fails -- it's only an - * optimisation anyway */ - cyg_thread_create(CYGNUM_JFFS2_GC_THREAD_PRIORITY, - jffs2_garbage_collect_thread, - (unsigned long)c,"jffs2 gc thread", - (void*)sb->s_gc_thread_stack, - sizeof(sb->s_gc_thread_stack), - &sb->s_gc_thread_handle, - &sb->s_gc_thread); - - cyg_thread_resume(sb->s_gc_thread_handle); -} - -void -jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) -{ - struct super_block *sb=OFNI_BS_2SFFJ(c); - - RT_ASSERT(sb->s_gc_thread_handle); - - D1(printk("jffs2_stop_garbage_collect_thread\n")); - /* Stop the thread and wait for it if necessary */ - - cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_STOP); - - D1(printk("jffs2_stop_garbage_collect_thread wait\n")); - - cyg_flag_wait(&sb->s_gc_thread_flags, - GC_THREAD_FLAG_HAS_EXIT, - CYG_FLAG_WAITMODE_OR| CYG_FLAG_WAITMODE_CLR); - - // Kill and free the resources ... this is safe due to the flag - // from the thread. - cyg_thread_kill(sb->s_gc_thread_handle); - cyg_thread_delete(sb->s_gc_thread_handle); - - cyg_mutex_destroy(&sb->s_lock); - cyg_flag_destroy(&sb->s_gc_thread_flags); -} - - -static void -jffs2_garbage_collect_thread(unsigned long data) -{ - struct jffs2_sb_info *c=(struct jffs2_sb_info *)data; - struct super_block *sb=OFNI_BS_2SFFJ(c); - cyg_flag_value_t flag; - cyg_mtab_entry *mte; - - D1(printk("jffs2_garbage_collect_thread START\n")); - - while(1) { - flag=cyg_flag_timed_wait(&sb->s_gc_thread_flags, - GC_THREAD_FLAG_TRIG|GC_THREAD_FLAG_STOP, - CYG_FLAG_WAITMODE_OR| CYG_FLAG_WAITMODE_CLR, - cyg_current_time()+ - CYGNUM_JFFS2_GS_THREAD_TICKS); - - if (flag & GC_THREAD_FLAG_STOP) - break; - - D1(printk("jffs2: GC THREAD GC BEGIN\n")); - - mte=cyg_fs_root_lookup((cyg_dir *) sb->s_root); - CYG_ASSERT(mte, "Bad mount point"); - cyg_fs_lock(mte, mte->fs->syncmode); - - if (jffs2_garbage_collect_pass(c) == -ENOSPC) { - printf("No space for garbage collection. " - "Aborting JFFS2 GC thread\n"); - break; - } - cyg_fs_unlock(mte, mte->fs->syncmode); - D1(printk("jffs2: GC THREAD GC END\n")); - } - - D1(printk("jffs2_garbage_collect_thread EXIT\n")); - cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_HAS_EXIT); -} -#endif - -rt_uint32_t cyg_current_time(void) -{ - return 0; -} - -static void -jffs2_garbage_collect_thread(unsigned long data); - -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) -{ - struct super_block *sb=OFNI_BS_2SFFJ(c); - - /* Wake up the thread */ - D1(printk("jffs2_garbage_collect_trigger\n")); - - rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_TRIG); -} - -static struct rt_thread gc_thread; -void -jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) -{ - struct super_block *sb=OFNI_BS_2SFFJ(c); - cyg_mtab_entry *mte; - int result; - - RT_ASSERT(c); - //RT_ASSERT(!sb->s_gc_thread_handle); - - mte=(cyg_dir *) sb->s_root; - RT_ASSERT(mte); - - rt_event_init(&sb->s_gc_thread_flags, "gc_event", RT_IPC_FLAG_FIFO); - rt_mutex_init(&sb->s_lock, "gc_mutex", RT_IPC_FLAG_FIFO); -// rt_mutex_init(&mte->fs->syncmode, "fs_lock", RT_IPC_FLAG_FIFO); - - D1(printk("jffs2_start_garbage_collect_thread\n")); - /* Start the thread. Doesn't matter if it fails -- it's only an - * optimisation anyway */ - result = rt_thread_init(&sb->s_gc_thread, - "jffs2_gc_thread", - jffs2_garbage_collect_thread, - (void *)c, - (void*)sb->s_gc_thread_stack, - sizeof(sb->s_gc_thread_stack), - CYGNUM_JFFS2_GC_THREAD_PRIORITY, - CYGNUM_JFFS2_GC_THREAD_TICKS - ); - if (result != RT_EOK) { - rt_thread_startup(&sb->s_gc_thread); - /* how to deal with the following filed? */ - /* sb->s_gc_thread_handle; */ - } -} - -void -jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) -{ - struct super_block *sb=OFNI_BS_2SFFJ(c); - cyg_mtab_entry *mte; - rt_uint32_t e; - rt_err_t result; - - //RT_ASSERT(sb->s_gc_thread_handle); - - D1(printk("jffs2_stop_garbage_collect_thread\n")); - /* Stop the thread and wait for it if necessary */ - - rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_STOP); - - D1(printk("jffs2_stop_garbage_collect_thread wait\n")); - - result = rt_event_recv(&sb->s_gc_thread_flags, - GC_THREAD_FLAG_HAS_EXIT, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, - RT_WAITING_FOREVER, &e); - if (result == -RT_ETIMEOUT) - { - LOG_E("wait completed timeout"); - return; - } - else if (result == -RT_ERROR) - { - LOG_E("event received error"); - return; - } - - // Kill and free the resources ... this is safe due to the flag - // from the thread. - rt_thread_detach(&sb->s_gc_thread); - rt_sem_detach(&sb->s_lock); - rt_event_detach(&sb->s_gc_thread_flags); -} - - -static void -jffs2_garbage_collect_thread(unsigned long data) -{ - struct jffs2_sb_info *c=(struct jffs2_sb_info *)data; - struct super_block *sb=OFNI_BS_2SFFJ(c); - cyg_mtab_entry *mte; - rt_uint32_t flag = 0; - rt_err_t result; - - D1(printk("jffs2_garbage_collect_thread START\n")); - - while(1) { - result = rt_event_recv(&sb->s_gc_thread_flags, - GC_THREAD_FLAG_TRIG | GC_THREAD_FLAG_STOP, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, - cyg_current_time() + CYGNUM_JFFS2_GS_THREAD_TICKS, - &flag); - if (result == -RT_ETIMEOUT) - { - LOG_E("wait completed timeout"); - continue; - } - else if (result == -RT_ERROR) - { - LOG_E("event received error"); - continue; - } - - if (flag & GC_THREAD_FLAG_STOP) - break; - - D1(printk("jffs2: GC THREAD GC BEGIN\n")); - - mte=(cyg_dir *) sb->s_root; - RT_ASSERT(mte != NULL); -// rt_mutex_take(&mte->fs->syncmode, RT_WAITING_FOREVER); - - if (jffs2_garbage_collect_pass(c) == -ENOSPC) { - printf("No space for garbage collection. " - "Aborting JFFS2 GC thread\n"); - break; - } -// rt_mutex_release(&mte->fs->syncmode); - D1(printk("jffs2: GC THREAD GC END\n")); - } - - D1(printk("jffs2_garbage_collect_thread EXIT\n")); - rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_HAS_EXIT); -} -#endif diff --git a/components/dfs/filesystems/jffs2/src/histo.h b/components/dfs/filesystems/jffs2/src/histo.h deleted file mode 100644 index 84f184f083..0000000000 --- a/components/dfs/filesystems/jffs2/src/histo.h +++ /dev/null @@ -1,3 +0,0 @@ -/* This file provides the bit-probabilities for the input file */ -#define BIT_DIVIDER 629 -static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */ diff --git a/components/dfs/filesystems/jffs2/src/histo_mips.h b/components/dfs/filesystems/jffs2/src/histo_mips.h deleted file mode 100644 index 9a443268d8..0000000000 --- a/components/dfs/filesystems/jffs2/src/histo_mips.h +++ /dev/null @@ -1,2 +0,0 @@ -#define BIT_DIVIDER_MIPS 1043 -static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ diff --git a/components/dfs/filesystems/jffs2/src/malloc-ecos.c b/components/dfs/filesystems/jffs2/src/malloc-ecos.c deleted file mode 100644 index df6e3c0f5d..0000000000 --- a/components/dfs/filesystems/jffs2/src/malloc-ecos.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Free Software Foundation, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: malloc-ecos.c,v 1.4 2003/11/26 15:55:35 dwmw2 Exp $ - * - */ - -#include -#include -#include "nodelist.h" - -#if !defined(CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE) -# define CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE 0 -#endif - -struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) -{ - return rt_malloc(sizeof(struct jffs2_full_dirent) + namesize); -} - -void jffs2_free_full_dirent(struct jffs2_full_dirent *x) -{ - rt_free(x); -} - -struct jffs2_full_dnode *jffs2_alloc_full_dnode(void) -{ - return rt_malloc(sizeof(struct jffs2_full_dnode)); -} - -void jffs2_free_full_dnode(struct jffs2_full_dnode *x) -{ - rt_free(x); -} - -struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void) -{ - return rt_malloc(sizeof(struct jffs2_raw_dirent)); -} - -void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x) -{ - rt_free(x); -} - -struct jffs2_raw_inode *jffs2_alloc_raw_inode(void) -{ - return rt_malloc(sizeof(struct jffs2_raw_inode)); -} - -void jffs2_free_raw_inode(struct jffs2_raw_inode *x) -{ - rt_free(x); -} - -struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void) -{ - return rt_malloc(sizeof(struct jffs2_tmp_dnode_info)); -} - -void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) -{ - rt_free(x); -} - -struct jffs2_node_frag *jffs2_alloc_node_frag(void) -{ - return rt_malloc(sizeof(struct jffs2_node_frag)); -} - -void jffs2_free_node_frag(struct jffs2_node_frag *x) -{ - rt_free(x); -} - -#if CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0 - -int jffs2_create_slab_caches(void) -{ - return 0; -} - -void jffs2_destroy_slab_caches(void) -{ -} - -struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) -{ - return rt_malloc(sizeof(struct jffs2_raw_node_ref)); -} - -void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) -{ - rt_free(x); -} - -#else // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0 - -static struct jffs2_raw_node_ref - rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE] __attribute__ ((aligned (4))), - * first = NULL; -static cyg_drv_mutex_t mutex; - -int jffs2_create_slab_caches(void) -{ - struct jffs2_raw_node_ref * p; - cyg_drv_mutex_init(&mutex); - for ( - p = rnr_pool; - p < rnr_pool + CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1; - p++ - ) - p->next_phys = p + 1; - rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1].next_phys = NULL; - first = &rnr_pool[0]; - return 0; -} - -void jffs2_destroy_slab_caches(void) -{ -} - -struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) -{ - struct jffs2_raw_node_ref * p; - - cyg_drv_mutex_lock(&mutex); - p = first; - if (p != NULL) - first = p->next_phys; - cyg_drv_mutex_unlock(&mutex); - return p; -} - -void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) -{ - cyg_drv_mutex_lock(&mutex); - x->next_phys = first; - first = x; - cyg_drv_mutex_unlock(&mutex); -} - -#endif // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0 - -struct jffs2_inode_cache *jffs2_alloc_inode_cache(void) -{ - struct jffs2_inode_cache *ret = rt_malloc(sizeof(struct jffs2_inode_cache)); - D1(printk(KERN_DEBUG "Allocated inocache at %p\n", ret)); - return ret; -} - -void jffs2_free_inode_cache(struct jffs2_inode_cache *x) -{ - D1(printk(KERN_DEBUG "Freeing inocache at %p\n", x)); - rt_free(x); -} - diff --git a/components/dfs/filesystems/jffs2/src/nodelist.c b/components/dfs/filesystems/jffs2/src/nodelist.c deleted file mode 100644 index aee9d88cff..0000000000 --- a/components/dfs/filesystems/jffs2/src/nodelist.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: nodelist.c,v 1.102 2005/07/28 12:45:10 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "nodelist.h" - -void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) -{ - struct jffs2_full_dirent **prev = list; - - JFFS2_DBG_DENTLIST("add dirent \"%s\", ino #%u\n", new->name, new->ino); - - while ((*prev) && (*prev)->nhash <= new->nhash) { - if ((*prev)->nhash == new->nhash && !strcmp((const char *)((*prev)->name), (const char *)new->name)) { - /* Duplicate. Free one */ - if (new->version < (*prev)->version) { - JFFS2_DBG_DENTLIST("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", - (*prev)->name, (*prev)->ino); - jffs2_mark_node_obsolete(c, new->raw); - jffs2_free_full_dirent(new); - } else { - JFFS2_DBG_DENTLIST("marking old dirent \"%s\", ino #%u bsolete\n", - (*prev)->name, (*prev)->ino); - new->next = (*prev)->next; - jffs2_mark_node_obsolete(c, ((*prev)->raw)); - jffs2_free_full_dirent(*prev); - *prev = new; - } - return; - } - prev = &((*prev)->next); - } - new->next = *prev; - *prev = new; -} - -void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) -{ - if (this->node) { - this->node->frags--; - if (!this->node->frags) { - /* The node has no valid frags left. It's totally obsoleted */ - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", - ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size); - jffs2_mark_node_obsolete(c, this->node->raw); - jffs2_free_full_dnode(this->node); - } else { - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", - ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); - mark_ref_normal(this->node->raw); - } - - } - jffs2_free_node_frag(this); -} - -static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base) -{ - struct rb_node *parent = &base->rb; - struct rb_node **link = &parent; - - JFFS2_DBG_FRAGTREE2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); - - while (*link) { - parent = *link; - base = rb_entry(parent, struct jffs2_node_frag, rb); - - JFFS2_DBG_FRAGTREE2("considering frag at 0x%08x\n", base->ofs); - if (newfrag->ofs > base->ofs) - link = &base->rb.rb_right; - else if (newfrag->ofs < base->ofs) - link = &base->rb.rb_left; - else { - JFFS2_ERROR("duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); - BUG(); - } - } - - rb_link_node(&newfrag->rb, &base->rb, link); -} - -/* Doesn't set inode->i_size */ -static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag) -{ - struct jffs2_node_frag *this; - uint32_t lastend; - - /* Skip all the nodes which are completed before this one starts */ - this = jffs2_lookup_node_frag(list, newfrag->node->ofs); - - if (this) { - JFFS2_DBG_FRAGTREE2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", - this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); - lastend = this->ofs + this->size; - } else { - JFFS2_DBG_FRAGTREE2("lookup gave no frag\n"); - lastend = 0; - } - - /* See if we ran off the end of the list */ - if (lastend <= newfrag->ofs) { - /* We did */ - - /* Check if 'this' node was on the same page as the new node. - If so, both 'this' and the new node get marked REF_NORMAL so - the GC can take a look. - */ - if (lastend && (lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) { - if (this->node) - mark_ref_normal(this->node->raw); - mark_ref_normal(newfrag->node->raw); - } - - if (lastend < newfrag->node->ofs) { - /* ... and we need to put a hole in before the new node */ - struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag(); - if (!holefrag) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; - } - holefrag->ofs = lastend; - holefrag->size = newfrag->node->ofs - lastend; - holefrag->node = NULL; - if (this) { - /* By definition, the 'this' node has no right-hand child, - because there are no frags with offset greater than it. - So that's where we want to put the hole */ - JFFS2_DBG_FRAGTREE2("adding hole frag (%p) on right of node at (%p)\n", holefrag, this); - rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); - } else { - JFFS2_DBG_FRAGTREE2("adding hole frag (%p) at root of tree\n", holefrag); - rb_link_node(&holefrag->rb, NULL, &list->rb_node); - } - rb_insert_color(&holefrag->rb, list); - this = holefrag; - } - if (this) { - /* By definition, the 'this' node has no right-hand child, - because there are no frags with offset greater than it. - So that's where we want to put new fragment */ - JFFS2_DBG_FRAGTREE2("adding new frag (%p) on right of node at (%p)\n", newfrag, this); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); - } else { - JFFS2_DBG_FRAGTREE2("adding new frag (%p) at root of tree\n", newfrag); - rb_link_node(&newfrag->rb, NULL, &list->rb_node); - } - rb_insert_color(&newfrag->rb, list); - return 0; - } - - JFFS2_DBG_FRAGTREE2("dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", - this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); - - /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, - * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs - */ - if (newfrag->ofs > this->ofs) { - /* This node isn't completely obsoleted. The start of it remains valid */ - - /* Mark the new node and the partially covered node REF_NORMAL -- let - the GC take a look at them */ - mark_ref_normal(newfrag->node->raw); - if (this->node) - mark_ref_normal(this->node->raw); - - if (this->ofs + this->size > newfrag->ofs + newfrag->size) { - /* The new node splits 'this' frag into two */ - struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag(); - if (!newfrag2) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; - } - if (this->node) - JFFS2_DBG_FRAGTREE2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", - this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); - else - JFFS2_DBG_FRAGTREE2("split old hole frag 0x%04x-0x%04x\n", - this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); - - /* New second frag pointing to this's node */ - newfrag2->ofs = newfrag->ofs + newfrag->size; - newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; - newfrag2->node = this->node; - if (this->node) - this->node->frags++; - - /* Adjust size of original 'this' */ - this->size = newfrag->ofs - this->ofs; - - /* Now, we know there's no node with offset - greater than this->ofs but smaller than - newfrag2->ofs or newfrag->ofs, for obvious - reasons. So we can do a tree insert from - 'this' to insert newfrag, and a tree insert - from newfrag to insert newfrag2. */ - jffs2_fragtree_insert(newfrag, this); - rb_insert_color(&newfrag->rb, list); - - jffs2_fragtree_insert(newfrag2, newfrag); - rb_insert_color(&newfrag2->rb, list); - - return 0; - } - /* New node just reduces 'this' frag in size, doesn't split it */ - this->size = newfrag->ofs - this->ofs; - - /* Again, we know it lives down here in the tree */ - jffs2_fragtree_insert(newfrag, this); - rb_insert_color(&newfrag->rb, list); - } else { - /* New frag starts at the same point as 'this' used to. Replace - it in the tree without doing a delete and insertion */ - JFFS2_DBG_FRAGTREE2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", - newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); - - rb_replace_node(&this->rb, &newfrag->rb, list); - - if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); - jffs2_obsolete_node_frag(c, this); - } else { - this->ofs += newfrag->size; - this->size -= newfrag->size; - - jffs2_fragtree_insert(this, newfrag); - rb_insert_color(&this->rb, list); - return 0; - } - } - /* OK, now we have newfrag added in the correct place in the tree, but - frag_next(newfrag) may be a fragment which is overlapped by it - */ - while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { - /* 'this' frag is obsoleted completely. */ - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x) and removing from tree\n", - this, this->ofs, this->ofs+this->size); - rb_erase(&this->rb, list); - jffs2_obsolete_node_frag(c, this); - } - /* Now we're pointing at the first frag which isn't totally obsoleted by - the new frag */ - - if (!this || newfrag->ofs + newfrag->size == this->ofs) { - return 0; - } - /* Still some overlap but we don't need to move it in the tree */ - this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size); - this->ofs = newfrag->ofs + newfrag->size; - - /* And mark them REF_NORMAL so the GC takes a look at them */ - if (this->node) - mark_ref_normal(this->node->raw); - mark_ref_normal(newfrag->node->raw); - - return 0; -} - -/* Given an inode, probably with existing list of fragments, add the new node - * to the fragment list. - */ -int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) -{ - int ret; - struct jffs2_node_frag *newfrag; - - if (unlikely(!fn->size)) - return 0; - - newfrag = jffs2_alloc_node_frag(); - if (unlikely(!newfrag)) - return -ENOMEM; - - JFFS2_DBG_FRAGTREE("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", - fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); - - newfrag->ofs = fn->ofs; - newfrag->size = fn->size; - newfrag->node = fn; - newfrag->node->frags = 1; - - ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); - if (unlikely(ret)) - return ret; - - /* If we now share a page with other nodes, mark either previous - or next node REF_NORMAL, as appropriate. */ - if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) { - struct jffs2_node_frag *prev = frag_prev(newfrag); - - mark_ref_normal(fn->raw); - /* If we don't start at zero there's _always_ a previous */ - if (prev->node) - mark_ref_normal(prev->node->raw); - } - - if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { - struct jffs2_node_frag *next = frag_next(newfrag); - - if (next) { - mark_ref_normal(fn->raw); - if (next->node) - mark_ref_normal(next->node->raw); - } - } - jffs2_dbg_fragtree_paranoia_check_nolock(f); - jffs2_dbg_dump_fragtree_nolock(f); - return 0; -} - - -void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) -{ - spin_lock(&c->inocache_lock); - ic->state = state; - wake_up(&c->inocache_wq); - spin_unlock(&c->inocache_lock); -} - -/* During mount, this needs no locking. During normal operation, its - callers want to do other stuff while still holding the inocache_lock. - Rather than introducing special case get_ino_cache functions or - callbacks, we just let the caller do the locking itself. */ - -struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino) -{ - struct jffs2_inode_cache *ret; - - ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; - while (ret && ret->ino < ino) { - ret = ret->next; - } - - if (ret && ret->ino != ino) - ret = NULL; - - return ret; -} - -void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new) -{ - struct jffs2_inode_cache **prev; - - spin_lock(&c->inocache_lock); - if (!new->ino) - new->ino = ++c->highest_ino; - - JFFS2_DBG_INOCACHE("add %p (ino #%u)\n", new, new->ino); - - prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; - - while ((*prev) && (*prev)->ino < new->ino) { - prev = &(*prev)->next; - } - new->next = *prev; - *prev = new; - - spin_unlock(&c->inocache_lock); -} - -void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) -{ - struct jffs2_inode_cache **prev; - - JFFS2_DBG_INOCACHE("del %p (ino #%u)\n", old, old->ino); - spin_lock(&c->inocache_lock); - - prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; - - while ((*prev) && (*prev)->ino < old->ino) { - prev = &(*prev)->next; - } - if ((*prev) == old) { - *prev = old->next; - } - - /* Free it now unless it's in READING or CLEARING state, which - are the transitions upon read_inode() and clear_inode(). The - rest of the time we know nobody else is looking at it, and - if it's held by read_inode() or clear_inode() they'll free it - for themselves. */ - if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING) - jffs2_free_inode_cache(old); - - spin_unlock(&c->inocache_lock); -} - -void jffs2_free_ino_caches(struct jffs2_sb_info *c) -{ - int i; - struct jffs2_inode_cache *this, *next; - - for (i=0; iinocache_list[i]; - while (this) { - next = this->next; - jffs2_free_inode_cache(this); - this = next; - } - c->inocache_list[i] = NULL; - } -} - -void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) -{ - int i; - struct jffs2_raw_node_ref *this, *next; - - for (i=0; inr_blocks; i++) { - this = c->blocks[i].first_node; - while(this) { - next = this->next_phys; - jffs2_free_raw_node_ref(this); - this = next; - } - c->blocks[i].first_node = c->blocks[i].last_node = NULL; - } -} - -struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) -{ - /* The common case in lookup is that there will be a node - which precisely matches. So we go looking for that first */ - struct rb_node *next; - struct jffs2_node_frag *prev = NULL; - struct jffs2_node_frag *frag = NULL; - - JFFS2_DBG_FRAGTREE2("root %p, offset %d\n", fragtree, offset); - - next = fragtree->rb_node; - - while(next) { - frag = rb_entry(next, struct jffs2_node_frag, rb); - - JFFS2_DBG_FRAGTREE2("considering frag %#04x-%#04x (%p). left %p, right %p\n", - frag->ofs, frag->ofs+frag->size, frag, frag->rb.rb_left, frag->rb.rb_right); - if (frag->ofs + frag->size <= offset) { - JFFS2_DBG_FRAGTREE2("going right from frag %#04x-%#04x, before the region we care about\n", - frag->ofs, frag->ofs+frag->size); - /* Remember the closest smaller match on the way down */ - if (!prev || frag->ofs > prev->ofs) - prev = frag; - next = frag->rb.rb_right; - } else if (frag->ofs > offset) { - JFFS2_DBG_FRAGTREE2("going left from frag %#04x-%#04x, after the region we care about\n", - frag->ofs, frag->ofs+frag->size); - next = frag->rb.rb_left; - } else { - JFFS2_DBG_FRAGTREE2("returning frag %#04x-%#04x, matched\n", - frag->ofs, frag->ofs+frag->size); - return frag; - } - } - - /* Exact match not found. Go back up looking at each parent, - and return the closest smaller one */ - - if (prev) - JFFS2_DBG_FRAGTREE2("no match. Returning frag %#04x-%#04x, closest previous\n", - prev->ofs, prev->ofs+prev->size); - else - JFFS2_DBG_FRAGTREE2("returning NULL, empty fragtree\n"); - - return prev; -} - -/* Pass 'c' argument to indicate that nodes should be marked obsolete as - they're killed. */ -void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) -{ - struct jffs2_node_frag *frag; - struct jffs2_node_frag *parent; - - if (!root->rb_node) - return; - - JFFS2_DBG_FRAGTREE("killing\n"); - - frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); - while(frag) { - if (frag->rb.rb_left) { - JFFS2_DBG_FRAGTREE2("going left from frag (%p) %#04x-%#04x\n", - frag, frag->ofs, frag->ofs+frag->size); - frag = frag_left(frag); - continue; - } - if (frag->rb.rb_right) { - JFFS2_DBG_FRAGTREE2("going right from frag (%p) %#04x-%#04x\n", - frag, frag->ofs, frag->ofs+frag->size); - frag = frag_right(frag); - continue; - } - - JFFS2_DBG_FRAGTREE2("frag %#04x-%#04x: node %p, frags %d\n", - frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0); - - if (frag->node && !(--frag->node->frags)) { - /* Not a hole, and it's the final remaining frag - of this node. Free the node */ - if (c) - jffs2_mark_node_obsolete(c, frag->node->raw); - - jffs2_free_full_dnode(frag->node); - } - parent = frag_parent(frag); - if (parent) { - if (frag_left(parent) == frag) - parent->rb.rb_left = NULL; - else - parent->rb.rb_right = NULL; - } - - jffs2_free_node_frag(frag); - frag = parent; - - cond_resched(); - } -} diff --git a/components/dfs/filesystems/jffs2/src/nodelist.h b/components/dfs/filesystems/jffs2/src/nodelist.h deleted file mode 100644 index 53cdb49bbf..0000000000 --- a/components/dfs/filesystems/jffs2/src/nodelist.h +++ /dev/null @@ -1,415 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: nodelist.h,v 1.135 2005/07/27 14:46:11 dedekind Exp $ - * - */ - -#ifndef __JFFS2_NODELIST_H__ -#define __JFFS2_NODELIST_H__ - -#include "jffs2_config.h" -#include -#include -#include -#include -#include -#include - -#ifdef __ECOS -#include "os-ecos.h" -#elif defined(RT_THREAD) -#include "os-rtthread.h" -#else -#include /* For compatibility with older kernels */ -#include "os-linux.h" -#endif - -#define JFFS2_NATIVE_ENDIAN - -/* Note we handle mode bits conversion from JFFS2 (i.e. Linux) to/from - whatever OS we're actually running on here too. */ - -#if defined(JFFS2_NATIVE_ENDIAN) -#if defined (__GNUC__) -#define cpu_to_je16(x) ((jint16_t){x}) -#define cpu_to_je32(x) ((jint32_t){x}) -#define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)}) - -#define je16_to_cpu(x) ((x).v16) -#define je32_to_cpu(x) ((x).v32) -#define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) -#elif defined (MSVC) -#define cpu_to_je16(x) ((jint16_t)(x)) -#define cpu_to_je32(x) ((jint32_t)(x)) -static __inline jmode_t cpu_to_jemode(x) -{ - jmode_t _x; - _x.m = os_to_jffs2_mode(x); - return _x; -} - -#define je16_to_cpu(x) (x) -#define je32_to_cpu(x) (x) -#define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) -#else -#endif - - -#elif defined(JFFS2_BIG_ENDIAN) -#define cpu_to_je16(x) ((jint16_t){cpu_to_be16(x)}) -#define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) -#define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))}) - -#define je16_to_cpu(x) (be16_to_cpu(x.v16)) -#define je32_to_cpu(x) (be32_to_cpu(x.v32)) -#define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m))) -#elif defined(JFFS2_LITTLE_ENDIAN) -#define cpu_to_je16(x) ((jint16_t){cpu_to_le16(x)}) -#define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) -#define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))}) - -#define je16_to_cpu(x) (le16_to_cpu(x.v16)) -#define je32_to_cpu(x) (le32_to_cpu(x.v32)) -#define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) -#else -#error wibble -#endif - -/* - This is all we need to keep in-core for each raw node during normal - operation. As and when we do read_inode on a particular inode, we can - scan the nodes which are listed for it and build up a proper map of - which nodes are currently valid. JFFSv1 always used to keep that whole - map in core for each inode. -*/ -struct jffs2_raw_node_ref -{ - struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref - for this inode. If this is the last, it points to the inode_cache - for this inode instead. The inode_cache will have NULL in the first - word so you know when you've got there :) */ - struct jffs2_raw_node_ref *next_phys; - uint32_t flash_offset; - uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ -}; - - /* flash_offset & 3 always has to be zero, because nodes are - always aligned at 4 bytes. So we have a couple of extra bits - to play with, which indicate the node's status; see below: */ -#define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ -#define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */ -#define REF_PRISTINE 2 /* Completely clean. GC without looking */ -#define REF_NORMAL 3 /* Possibly overlapped. Read the page and write again on GC */ -#define ref_flags(ref) ((ref)->flash_offset & 3) -#define ref_offset(ref) ((ref)->flash_offset & ~3) -#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) -#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) - -/* For each inode in the filesystem, we need to keep a record of - nlink, because it would be a PITA to scan the whole directory tree - at read_inode() time to calculate it, and to keep sufficient information - in the raw_node_ref (basically both parent and child inode number for - dirent nodes) would take more space than this does. We also keep - a pointer to the first physical node which is part of this inode, too. -*/ -struct jffs2_inode_cache { - struct jffs2_full_dirent *scan_dents; /* Used during scan to hold - temporary lists of dirents, and later must be set to - NULL to mark the end of the raw_node_ref->next_in_ino - chain. */ - struct jffs2_inode_cache *next; - struct jffs2_raw_node_ref *nodes; - uint32_t ino; - int nlink; - int state; -}; - -/* Inode states for 'state' above. We need the 'GC' state to prevent - someone from doing a read_inode() while we're moving a 'REF_PRISTINE' - node without going through all the iget() nonsense */ -#define INO_STATE_UNCHECKED 0 /* CRC checks not yet done */ -#define INO_STATE_CHECKING 1 /* CRC checks in progress */ -#define INO_STATE_PRESENT 2 /* In core */ -#define INO_STATE_CHECKEDABSENT 3 /* Checked, cleared again */ -#define INO_STATE_GC 4 /* GCing a 'pristine' node */ -#define INO_STATE_READING 5 /* In read_inode() */ -#define INO_STATE_CLEARING 6 /* In clear_inode() */ - -#define INOCACHE_HASHSIZE 128 - -/* - Larger representation of a raw node, kept in-core only when the - struct inode for this particular ino is instantiated. -*/ - -struct jffs2_full_dnode -{ - struct jffs2_raw_node_ref *raw; - uint32_t ofs; /* The offset to which the data of this node belongs */ - uint32_t size; - uint32_t frags; /* Number of fragments which currently refer - to this node. When this reaches zero, - the node is obsolete. */ -}; - -/* - Even larger representation of a raw node, kept in-core only while - we're actually building up the original map of which nodes go where, - in read_inode() -*/ -struct jffs2_tmp_dnode_info -{ - struct rb_node rb; - struct jffs2_full_dnode *fn; - uint32_t version; -}; - -struct jffs2_full_dirent -{ - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *next; - uint32_t version; - uint32_t ino; /* == zero for unlink */ - unsigned int nhash; - unsigned char type; - unsigned char name[0]; -}; - -/* - Fragments - used to build a map of which raw node to obtain - data from for each part of the ino -*/ -struct jffs2_node_frag -{ - struct rb_node rb; - struct jffs2_full_dnode *node; /* NULL for holes */ - uint32_t size; - uint32_t ofs; /* The offset to which this fragment belongs */ -}; - -struct jffs2_eraseblock -{ - struct list_head list; - int bad_count; - uint32_t offset; /* of this block in the MTD */ - - uint32_t unchecked_size; - uint32_t used_size; - uint32_t dirty_size; - uint32_t wasted_size; - uint32_t free_size; /* Note that sector_size - free_size - is the address of the first free space */ - struct jffs2_raw_node_ref *first_node; - struct jffs2_raw_node_ref *last_node; - - struct jffs2_raw_node_ref *gc_node; /* Next node to be garbage collected */ -}; - -/* Calculate totlen from surrounding nodes or eraseblock */ -static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *ref) -{ - uint32_t ref_end; - - if (ref->next_phys) - ref_end = ref_offset(ref->next_phys); - else { - if (!jeb) - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - - /* Last node in block. Use free_space */ - BUG_ON(ref != jeb->last_node); - ref_end = jeb->offset + c->sector_size - jeb->free_size; - } - return ref_end - ref_offset(ref); -} - -static inline uint32_t ref_totlen(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb, - struct jffs2_raw_node_ref *ref) -{ - uint32_t ret; - -#if CONFIG_JFFS2_FS_DEBUG > 0 - if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { - printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n", - jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref)); - BUG(); - } -#endif - -#if 1 - ret = ref->__totlen; -#else - /* This doesn't actually work yet */ - ret = __ref_totlen(c, jeb, ref); - if (ret != ref->__totlen) { - printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", - ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, - ret, ref->__totlen); - if (!jeb) - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - jffs2_dbg_dump_node_refs_nolock(c, jeb); - BUG(); - } -#endif - return ret; -} - -#define ALLOC_NORMAL 0 /* Normal allocation */ -#define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ -#define ALLOC_GC 2 /* Space requested for GC. Give it or die */ -#define ALLOC_NORETRY 3 /* For jffs2_write_dnode: On failure, return -EAGAIN instead of retrying */ - -/* How much dirty space before it goes on the very_dirty_list */ -#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) - -/* check if dirty space is more than 255 Byte */ -#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) - -#define PAD(x) (((x)+3)&~3) - -static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) -{ - while(raw->next_in_ino) { - raw = raw->next_in_ino; - } - - return ((struct jffs2_inode_cache *)raw); -} - -static inline struct jffs2_node_frag *frag_first(struct rb_root *root) -{ - struct rb_node *node = root->rb_node; - - if (!node) - return NULL; - while(node->rb_left) - node = node->rb_left; - return rb_entry(node, struct jffs2_node_frag, rb); -} - -static inline struct jffs2_node_frag *frag_last(struct rb_root *root) -{ - struct rb_node *node = root->rb_node; - - if (!node) - return NULL; - while(node->rb_right) - node = node->rb_right; - return rb_entry(node, struct jffs2_node_frag, rb); -} - -#define rb_parent(rb) ((rb)->rb_parent) -#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) -#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) -#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) -#define frag_left(frag) rb_entry((frag)->rb.rb_left, struct jffs2_node_frag, rb) -#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb) -#define frag_erase(frag, list) rb_erase(&frag->rb, list); - -/* nodelist.c */ -void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); -void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state); -struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino); -void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new); -void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old); -void jffs2_free_ino_caches(struct jffs2_sb_info *c); -void jffs2_free_raw_node_refs(struct jffs2_sb_info *c); -struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset); -void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); -struct rb_node *rb_next(struct rb_node *); -struct rb_node *rb_prev(struct rb_node *); -void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); -void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); -int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); - -/* nodemgmt.c */ -int jffs2_thread_should_wake(struct jffs2_sb_info *c); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); -void jffs2_complete_reservation(struct jffs2_sb_info *c); -void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); - -/* write.c */ -int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); - -struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); -struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); -int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, - uint32_t offset, uint32_t writelen, uint32_t *retlen); -int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); -int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f); -int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen); - - -/* readinode.c */ -void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint32_t ino, struct jffs2_raw_inode *latest_node); -int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); -void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); - -/* malloc.c */ -int jffs2_create_slab_caches(void); -void jffs2_destroy_slab_caches(void); - -struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize); -void jffs2_free_full_dirent(struct jffs2_full_dirent *); -struct jffs2_full_dnode *jffs2_alloc_full_dnode(void); -void jffs2_free_full_dnode(struct jffs2_full_dnode *); -struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void); -void jffs2_free_raw_dirent(struct jffs2_raw_dirent *); -struct jffs2_raw_inode *jffs2_alloc_raw_inode(void); -void jffs2_free_raw_inode(struct jffs2_raw_inode *); -struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); -void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); -struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void); -void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); -struct jffs2_node_frag *jffs2_alloc_node_frag(void); -void jffs2_free_node_frag(struct jffs2_node_frag *); -struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); -void jffs2_free_inode_cache(struct jffs2_inode_cache *); - -/* gc.c */ -int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); - -/* read.c */ -int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_full_dnode *fd, unsigned char *buf, - int ofs, int len); -int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned char *buf, uint32_t offset, uint32_t len); -char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); - -/* scan.c */ -int jffs2_scan_medium(struct jffs2_sb_info *c); -void jffs2_rotate_lists(struct jffs2_sb_info *c); - -/* build.c */ -int jffs2_do_mount_fs(struct jffs2_sb_info *c); - -/* erase.c */ -void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); - -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER -/* wbuf.c */ -int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino); -int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c); -int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); -#endif - -#include "debug.h" - -#endif /* __JFFS2_NODELIST_H__ */ diff --git a/components/dfs/filesystems/jffs2/src/nodemgmt.c b/components/dfs/filesystems/jffs2/src/nodemgmt.c deleted file mode 100644 index ef2167aadc..0000000000 --- a/components/dfs/filesystems/jffs2/src/nodemgmt.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: nodemgmt.c,v 1.124 2005/07/20 15:32:28 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include /* For cond_resched() */ -#include "nodelist.h" - -/** - * jffs2_reserve_space - request physical space to write nodes to flash - * @c: superblock info - * @minsize: Minimum acceptable size of allocation - * @ofs: Returned value of node offset - * @len: Returned value of allocation length - * @prio: Allocation type - ALLOC_{NORMAL,DELETION} - * - * Requests a block of physical space on the flash. Returns zero for success - * and puts 'ofs' and 'len' into the appriopriate place, or returns -ENOSPC - * or other error if appropriate. - * - * If it returns zero, jffs2_reserve_space() also downs the per-filesystem - * allocation semaphore, to prevent more than one allocation from being - * active at any time. The semaphore is later released by jffs2_commit_allocation() - * - * jffs2_reserve_space() may trigger garbage collection in order to make room - * for the requested allocation. - */ - -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); - -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio) -{ - int ret = -EAGAIN; - int blocksneeded = c->resv_blocks_write; - /* align it */ - minsize = PAD(minsize); - - D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize)); - down(&c->alloc_sem); - - D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n")); - - spin_lock(&c->erase_completion_lock); - - /* this needs a little more thought (true :)) */ - while(ret == -EAGAIN) { - while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { - int ret; - uint32_t dirty, avail; - - /* calculate real dirty size - * dirty_size contains blocks on erase_pending_list - * those blocks are counted in c->nr_erasing_blocks. - * If one block is actually erased, it is not longer counted as dirty_space - * but it is counted in c->nr_erasing_blocks, so we add it and subtract it - * with c->nr_erasing_blocks * c->sector_size again. - * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks - * This helps us to force gc and pick eventually a clean block to spread the load. - * We add unchecked_size here, as we hopefully will find some space to use. - * This will affect the sum only once, as gc first finishes checking - * of nodes. - */ - dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size; - if (dirty < c->nospc_dirty_size) { - if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) { - D1(printk(KERN_NOTICE "jffs2_reserve_space(): Low on dirty space to GC, but it's a deletion. Allowing...\n")); - break; - } - D1(printk(KERN_DEBUG "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n", - dirty, c->unchecked_size, c->sector_size)); - - spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - return -ENOSPC; - } - - /* Calc possibly available space. Possibly available means that we - * don't know, if unchecked size contains obsoleted nodes, which could give us some - * more usable space. This will affect the sum only once, as gc first finishes checking - * of nodes. - + Return -ENOSPC, if the maximum possibly available space is less or equal than - * blocksneeded * sector_size. - * This blocks endless gc looping on a filesystem, which is nearly full, even if - * the check above passes. - */ - avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size; - if ( (avail / c->sector_size) <= blocksneeded) { - if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) { - D1(printk(KERN_NOTICE "jffs2_reserve_space(): Low on possibly available space, but it's a deletion. Allowing...\n")); - break; - } - - D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n", - avail, blocksneeded * c->sector_size)); - spin_unlock(&c->erase_completion_lock); - up(&c->alloc_sem); - return -ENOSPC; - } - - up(&c->alloc_sem); - - D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", - c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, - c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); - spin_unlock(&c->erase_completion_lock); - - ret = jffs2_garbage_collect_pass(c); - if (ret) - return ret; - - cond_resched(); - - if (signal_pending(current)) - return -EINTR; - - down(&c->alloc_sem); - spin_lock(&c->erase_completion_lock); - } - - ret = jffs2_do_reserve_space(c, minsize, ofs, len); - if (ret) { - D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); - } - } - spin_unlock(&c->erase_completion_lock); - if (ret) - up(&c->alloc_sem); - return ret; -} - -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) -{ - int ret = -EAGAIN; - minsize = PAD(minsize); - - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc(): Requested 0x%x bytes\n", minsize)); - - spin_lock(&c->erase_completion_lock); - while(ret == -EAGAIN) { - ret = jffs2_do_reserve_space(c, minsize, ofs, len); - if (ret) { - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); - } - } - spin_unlock(&c->erase_completion_lock); - return ret; -} - -/* Called with alloc sem _and_ erase_completion_lock */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) -{ - struct jffs2_eraseblock *jeb = c->nextblock; - - restart: - if (jeb && minsize > jeb->free_size) { - /* Skip the end of this block and file it as having some dirty space */ - /* If there's a pending write to it, flush now */ - if (jffs2_wbuf_dirty(c)) { - spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); - jffs2_flush_wbuf_pad(c); - spin_lock(&c->erase_completion_lock); - jeb = c->nextblock; - goto restart; - } - c->wasted_size += jeb->free_size; - c->free_size -= jeb->free_size; - jeb->wasted_size += jeb->free_size; - jeb->free_size = 0; - - /* Check, if we have a dirty block now, or if it was dirty already */ - if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { - c->dirty_size += jeb->wasted_size; - c->wasted_size -= jeb->wasted_size; - jeb->dirty_size += jeb->wasted_size; - jeb->wasted_size = 0; - if (VERYDIRTY(c, jeb->dirty_size)) { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->very_dirty_list); - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); - } - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->clean_list); - } - c->nextblock = jeb = NULL; - } - - if (!jeb) { - struct list_head *next; - /* Take the next block off the 'free' list */ - - if (list_empty(&c->free_list)) { - - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_list)) { - struct jffs2_eraseblock *ejeb; - - ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); - list_del(&ejeb->list); - list_add_tail(&ejeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", - ejeb->offset)); - } - - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_pending_wbuf_list)) { - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); - /* c->nextblock is NULL, no update to c->nextblock allowed */ - spin_unlock(&c->erase_completion_lock); - jffs2_flush_wbuf_pad(c); - spin_lock(&c->erase_completion_lock); - /* Have another go. It'll be on the erasable_list now */ - return -EAGAIN; - } - - if (!c->nr_erasing_blocks) { - /* Ouch. We're in GC, or we wouldn't have got here. - And there's no space left. At all. */ - printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", - c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", - list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); - return -ENOSPC; - } - - spin_unlock(&c->erase_completion_lock); - /* Don't wait for it; just erase one right now */ - jffs2_erase_pending_blocks(c, 1); - spin_lock(&c->erase_completion_lock); - - /* An erase may have failed, decreasing the - amount of free space available. So we must - restart from the beginning */ - return -EAGAIN; - } - - next = c->free_list.next; - list_del(next); - c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); - c->nr_free_blocks--; - - if (jeb->free_size != c->sector_size - c->cleanmarker_size) { - printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); - goto restart; - } - } - /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has - enough space */ - *ofs = jeb->offset + (c->sector_size - jeb->free_size); - *len = jeb->free_size; - - if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && - !jeb->first_node->next_in_ino) { - /* Only node in it beforehand was a CLEANMARKER node (we think). - So mark it obsolete now that there's going to be another node - in the block. This will reduce used_size to zero but We've - already set c->nextblock so that jffs2_mark_node_obsolete() - won't try to refile it to the dirty_list. - */ - spin_unlock(&c->erase_completion_lock); - jffs2_mark_node_obsolete(c, jeb->first_node); - spin_lock(&c->erase_completion_lock); - } - - D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs)); - return 0; -} - -/** - * jffs2_add_physical_node_ref - add a physical node reference to the list - * @c: superblock info - * @new: new node reference to add - * @len: length of this physical node - * @dirty: dirty flag for new node - * - * Should only be used to report nodes for which space has been allocated - * by jffs2_reserve_space. - * - * Must be called with the alloc_sem held. - */ - -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) -{ - struct jffs2_eraseblock *jeb; - uint32_t len; - - jeb = &c->blocks[new->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, new); - - D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); -#if 1 - /* we could get some obsolete nodes after nextblock was refiled - in wbuf.c */ - if ((c->nextblock || !ref_obsolete(new)) - &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) { - printk(KERN_WARNING "argh. node added in wrong place\n"); - jffs2_free_raw_node_ref(new); - return -EINVAL; - } -#endif - spin_lock(&c->erase_completion_lock); - - if (!jeb->first_node) - jeb->first_node = new; - if (jeb->last_node) - jeb->last_node->next_phys = new; - jeb->last_node = new; - - jeb->free_size -= len; - c->free_size -= len; - if (ref_obsolete(new)) { - jeb->dirty_size += len; - c->dirty_size += len; - } else { - jeb->used_size += len; - c->used_size += len; - } - - if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { - /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - if (jffs2_wbuf_dirty(c)) { - /* Flush the last write in the block if it's outstanding */ - spin_unlock(&c->erase_completion_lock); - jffs2_flush_wbuf_pad(c); - spin_lock(&c->erase_completion_lock); - } - - list_add_tail(&jeb->list, &c->clean_list); - c->nextblock = NULL; - } - jffs2_dbg_acct_sanity_check_nolock(c,jeb); - jffs2_dbg_acct_paranoia_check_nolock(c, jeb); - - spin_unlock(&c->erase_completion_lock); - - return 0; -} - - -void jffs2_complete_reservation(struct jffs2_sb_info *c) -{ - D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); - jffs2_garbage_collect_trigger(c); - up(&c->alloc_sem); -} - -static inline int on_list(struct list_head *obj, struct list_head *head) -{ - struct list_head *this; - - list_for_each(this, head) { - if (this == obj) { - D1(printk("%p is on list at %p\n", obj, head)); - return 1; - - } - } - return 0; -} - -void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref) -{ - struct jffs2_eraseblock *jeb; - int blocknr; - struct jffs2_unknown_node n; - int ret, addedsize; - size_t retlen; - - if(!ref) { - printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); - return; - } - if (ref_obsolete(ref)) { - D1(printk(KERN_DEBUG "jffs2_mark_node_obsolete called with already obsolete node at 0x%08x\n", ref_offset(ref))); - return; - } - blocknr = ref->flash_offset / c->sector_size; - if (blocknr >= c->nr_blocks) { - printk(KERN_NOTICE "raw node at 0x%08x is off the end of device!\n", ref->flash_offset); - BUG(); - } - jeb = &c->blocks[blocknr]; - - if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) && - !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) { - /* Hm. This may confuse static lock analysis. If any of the above - three conditions is false, we're going to return from this - function without actually obliterating any nodes or freeing - any jffs2_raw_node_refs. So we don't need to stop erases from - happening, or protect against people holding an obsolete - jffs2_raw_node_ref without the erase_completion_lock. */ - down(&c->erase_free_sem); - } - - spin_lock(&c->erase_completion_lock); - - if (ref_flags(ref) == REF_UNCHECKED) { - D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) { - printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", - ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); - BUG(); - }) - D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); - jeb->unchecked_size -= ref_totlen(c, jeb, ref); - c->unchecked_size -= ref_totlen(c, jeb, ref); - } else { - D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) { - printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", - ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); - BUG(); - }) - D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); - jeb->used_size -= ref_totlen(c, jeb, ref); - c->used_size -= ref_totlen(c, jeb, ref); - } - - // Take care, that wasted size is taken into concern - if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) { - D1(printk(KERN_DEBUG "Dirtying\n")); - addedsize = ref_totlen(c, jeb, ref); - jeb->dirty_size += ref_totlen(c, jeb, ref); - c->dirty_size += ref_totlen(c, jeb, ref); - - /* Convert wasted space to dirty, if not a bad block */ - if (jeb->wasted_size) { - if (on_list(&jeb->list, &c->bad_used_list)) { - D1(printk(KERN_DEBUG "Leaving block at %08x on the bad_used_list\n", - jeb->offset)); - addedsize = 0; /* To fool the refiling code later */ - } else { - D1(printk(KERN_DEBUG "Converting %d bytes of wasted space to dirty in block at %08x\n", - jeb->wasted_size, jeb->offset)); - addedsize += jeb->wasted_size; - jeb->dirty_size += jeb->wasted_size; - c->dirty_size += jeb->wasted_size; - c->wasted_size -= jeb->wasted_size; - jeb->wasted_size = 0; - } - } - } else { - D1(printk(KERN_DEBUG "Wasting\n")); - addedsize = 0; - jeb->wasted_size += ref_totlen(c, jeb, ref); - c->wasted_size += ref_totlen(c, jeb, ref); - } - ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - - jffs2_dbg_acct_sanity_check_nolock(c, jeb); - jffs2_dbg_acct_paranoia_check_nolock(c, jeb); - - if (c->flags & JFFS2_SB_FLAG_SCANNING) { - /* Flash scanning is in progress. Don't muck about with the block - lists because they're not ready yet, and don't actually - obliterate nodes that look obsolete. If they weren't - marked obsolete on the flash at the time they _became_ - obsolete, there was probably a reason for that. */ - spin_unlock(&c->erase_completion_lock); - /* We didn't lock the erase_free_sem */ - return; - } - - if (jeb == c->nextblock) { - D2(printk(KERN_DEBUG "Not moving nextblock 0x%08x to dirty/erase_pending list\n", jeb->offset)); - } else if (!jeb->used_size && !jeb->unchecked_size) { - if (jeb == c->gcblock) { - D1(printk(KERN_DEBUG "gcblock at 0x%08x completely dirtied. Clearing gcblock...\n", jeb->offset)); - c->gcblock = NULL; - } else { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x completely dirtied. Removing from (dirty?) list...\n", jeb->offset)); - list_del(&jeb->list); - } - if (jffs2_wbuf_dirty(c)) { - D1(printk(KERN_DEBUG "...and adding to erasable_pending_wbuf_list\n")); - list_add_tail(&jeb->list, &c->erasable_pending_wbuf_list); - } else { - if (jiffies & 127) { - /* Most of the time, we just erase it immediately. Otherwise we - spend ages scanning it on mount, etc. */ - D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); - list_add_tail(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); - } else { - /* Sometimes, however, we leave it elsewhere so it doesn't get - immediately reused, and we spread the load a bit. */ - D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); - list_add_tail(&jeb->list, &c->erasable_list); - } - } - D1(printk(KERN_DEBUG "Done OK\n")); - } else if (jeb == c->gcblock) { - D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty_list\n", jeb->offset)); - } else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - addedsize)) { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n", jeb->offset)); - list_del(&jeb->list); - D1(printk(KERN_DEBUG "...and adding to dirty_list\n")); - list_add_tail(&jeb->list, &c->dirty_list); - } else if (VERYDIRTY(c, jeb->dirty_size) && - !VERYDIRTY(c, jeb->dirty_size - addedsize)) { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n", jeb->offset)); - list_del(&jeb->list); - D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n")); - list_add_tail(&jeb->list, &c->very_dirty_list); - } else { - D1(printk(KERN_DEBUG "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - } - - spin_unlock(&c->erase_completion_lock); - - if (!jffs2_can_mark_obsolete(c) || jffs2_is_readonly(c) || - (c->flags & JFFS2_SB_FLAG_BUILDING)) { - /* We didn't lock the erase_free_sem */ - return; - } - - /* The erase_free_sem is locked, and has been since before we marked the node obsolete - and potentially put its eraseblock onto the erase_pending_list. Thus, we know that - the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet - by jffs2_free_all_node_refs() in erase.c. Which is nice. */ - - D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref))); - ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (unsigned char *)&n); - if (ret) { - printk(KERN_WARNING "Read error reading from obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); - goto out_erase_sem; - } - if (retlen != sizeof(n)) { - printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); - goto out_erase_sem; - } - if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) { - printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref)); - goto out_erase_sem; - } - if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { - D1(printk(KERN_DEBUG "Node at 0x%08x was already marked obsolete (nodetype 0x%04x)\n", ref_offset(ref), je16_to_cpu(n.nodetype))); - goto out_erase_sem; - } - /* XXX FIXME: This is ugly now */ - n.nodetype = cpu_to_je16(je16_to_cpu(n.nodetype) & ~JFFS2_NODE_ACCURATE); - ret = jffs2_flash_write(c, ref_offset(ref), sizeof(n), &retlen, (unsigned char *)&n); - if (ret) { - printk(KERN_WARNING "Write error in obliterating obsoleted node at 0x%08x: %d\n", ref_offset(ref), ret); - goto out_erase_sem; - } - if (retlen != sizeof(n)) { - printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); - goto out_erase_sem; - } - - /* Nodes which have been marked obsolete no longer need to be - associated with any inode. Remove them from the per-inode list. - - Note we can't do this for NAND at the moment because we need - obsolete dirent nodes to stay on the lists, because of the - horridness in jffs2_garbage_collect_deletion_dirent(). Also - because we delete the inocache, and on NAND we need that to - stay around until all the nodes are actually erased, in order - to stop us from giving the same inode number to another newly - created inode. */ - if (ref->next_in_ino) { - struct jffs2_inode_cache *ic; - struct jffs2_raw_node_ref **p; - - spin_lock(&c->erase_completion_lock); - - ic = jffs2_raw_ref_to_ic(ref); - for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) - ; - - *p = ref->next_in_ino; - ref->next_in_ino = NULL; - - if (ic->nodes == (void *)ic && ic->nlink == 0) - jffs2_del_ino_cache(c, ic); - - spin_unlock(&c->erase_completion_lock); - } - - - /* Merge with the next node in the physical list, if there is one - and if it's also obsolete and if it doesn't belong to any inode */ - if (ref->next_phys && ref_obsolete(ref->next_phys) && - !ref->next_phys->next_in_ino) { - struct jffs2_raw_node_ref *n = ref->next_phys; - - spin_lock(&c->erase_completion_lock); - - ref->__totlen += n->__totlen; - ref->next_phys = n->next_phys; - if (jeb->last_node == n) jeb->last_node = ref; - if (jeb->gc_node == n) { - /* gc will be happy continuing gc on this node */ - jeb->gc_node=ref; - } - spin_unlock(&c->erase_completion_lock); - - jffs2_free_raw_node_ref(n); - } - - /* Also merge with the previous node in the list, if there is one - and that one is obsolete */ - if (ref != jeb->first_node ) { - struct jffs2_raw_node_ref *p = jeb->first_node; - - spin_lock(&c->erase_completion_lock); - - while (p->next_phys != ref) - p = p->next_phys; - - if (ref_obsolete(p) && !ref->next_in_ino) { - p->__totlen += ref->__totlen; - if (jeb->last_node == ref) { - jeb->last_node = p; - } - if (jeb->gc_node == ref) { - /* gc will be happy continuing gc on this node */ - jeb->gc_node=p; - } - p->next_phys = ref->next_phys; - jffs2_free_raw_node_ref(ref); - } - spin_unlock(&c->erase_completion_lock); - } - out_erase_sem: - up(&c->erase_free_sem); -} - -int jffs2_thread_should_wake(struct jffs2_sb_info *c) -{ - int ret = 0; - uint32_t dirty; - - if (c->unchecked_size) { - D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", - c->unchecked_size, c->checked_ino)); - return 1; - } - - /* dirty_size contains blocks on erase_pending_list - * those blocks are counted in c->nr_erasing_blocks. - * If one block is actually erased, it is not longer counted as dirty_space - * but it is counted in c->nr_erasing_blocks, so we add it and subtract it - * with c->nr_erasing_blocks * c->sector_size again. - * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks - * This helps us to force gc and pick eventually a clean block to spread the load. - */ - dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size; - - if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && - (dirty > c->nospc_dirty_size)) - ret = 1; - - D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", - c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); - - return ret; -} diff --git a/components/dfs/filesystems/jffs2/src/os-ecos.h b/components/dfs/filesystems/jffs2/src/os-ecos.h deleted file mode 100644 index b6d2a0e8c8..0000000000 --- a/components/dfs/filesystems/jffs2/src/os-ecos.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2002-2003 Free Software Foundation, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: os-ecos.h,v 1.24 2005/02/09 09:23:55 pavlov Exp $ - * - */ - -#ifndef __JFFS2_OS_ECOS_H__ -#define __JFFS2_OS_ECOS_H__ -#include "jffs2_config.h" -#include -#define printf rt_kprintf - -//#include -//#include -//#include -#include -#include -#include - -//#include -//#include -//#include - -//#include // tracing macros -//#include // assertion macros - -//#if defined (__GNUC__) -//#include -//#elif defined (MSVC) -//#else -//#endif - -#include "port/sys/stat.h"//#include -//#include -//#include -//#include //fixme - -//#include - -struct dirent -{ -#ifdef CYGPKG_FILEIO_DIRENT_DTYPE - - mode_t d_type; // Only supported with FATFS, RAMFS, ROMFS, - // and JFFS2. - // d_type is not part of POSIX so - // should be used with caution. -#endif - char d_name[JFFS2_NAME_MAX+1]; -}; - - -//#include -#include - -#include //prife - -//#include -//#include - -//#include - -#include -#include -#include - -//#define printf diag_printf //prife - -struct _inode; -struct super_block; - -struct iovec { - void *iov_base; - ssize_t iov_len; -}; - -static inline unsigned int full_name_hash(const unsigned char * name, unsigned int len) { - - unsigned hash = 0; - while (len--) { - hash = (hash << 4) | (hash >> 28); - hash ^= *(name++); - } - return hash; -} - -#ifdef CYGOPT_FS_JFFS2_WRITE -#define jffs2_is_readonly(c) (0) -#else -#define jffs2_is_readonly(c) (1) -#endif - -/* NAND flash not currently supported on eCos */ -#define jffs2_can_mark_obsolete(c) (1) - -#define JFFS2_INODE_INFO(i) (&(i)->jffs2_i) -#define OFNI_EDONI_2SFFJ(f) ((struct _inode *) ( ((char *)f) - ((char *)(&((struct _inode *)NULL)->jffs2_i)) ) ) - -#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size) -#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) -#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) -#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) -#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime) -#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime) -#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime) - -/* FIXME: eCos doesn't hav a concept of device major/minor numbers */ -#define JFFS2_F_I_RDEV_MIN(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)&0xff) -#define JFFS2_F_I_RDEV_MAJ(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)>>8) - -#define get_seconds jffs2_get_timestamp - -struct _inode { - cyg_uint32 i_ino; - - int i_count; - mode_t i_mode; - nlink_t i_nlink; // Could we dispense with this? - uid_t i_uid; - gid_t i_gid; - time_t i_atime; - time_t i_mtime; - time_t i_ctime; -// union { - unsigned short i_rdev; // For devices only - struct _inode * i_parent; // For directories only - off_t i_size; // For files only -// }; - struct super_block * i_sb; - - struct jffs2_inode_info jffs2_i; - - struct _inode * i_cache_prev; // We need doubly-linked? - struct _inode * i_cache_next; -}; - -#define JFFS2_SB_INFO(sb) (&(sb)->jffs2_sb) -#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->jffs2_sb)) ) ) - -struct super_block { - struct jffs2_sb_info jffs2_sb; - struct _inode * s_root; - unsigned long s_mount_count; - cyg_io_handle_t s_dev; - -//#ifdef CYGOPT_FS_JFFS2_GCTHREAD -// cyg_mutex_t s_lock; // Lock the inode cache -// cyg_flag_t s_gc_thread_flags; // Communication with the gcthread -// cyg_handle_t s_gc_thread_handle; -// cyg_thread s_gc_thread; -//#if (CYGNUM_JFFS2_GC_THREAD_STACK_SIZE >= CYGNUM_HAL_STACK_SIZE_MINIMUM) -// char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE]; -//#else -// char s_gc_thread_stack[CYGNUM_HAL_STACK_SIZE_MINIMUM]; -//#endif -// cyg_mtab_entry *mte; -//#endif - -#ifdef CYGOPT_FS_JFFS2_GCTHREAD - struct rt_mutex s_lock; // Lock the inode cache - struct rt_event s_gc_thread_flags; // Communication with the gcthread - //void (*s_gc_thread_handle)(void *parameter); - struct rt_thread s_gc_thread; -//#if (CYGNUM_JFFS2_GC_THREAD_STACK_SIZE >= CYGNUM_HAL_STACK_SIZE_MINIMUM) -// char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE]; -//#else -// char s_gc_thread_stack[CYGNUM_HAL_STACK_SIZE_MINIMUM]; -//#endif - #define CYGNUM_JFFS2_GC_THREAD_STACK_SIZE (1024*4) - char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE]; - - cyg_mtab_entry *mte; -#endif - -}; - -#define sleep_on_spinunlock(wq, sl) spin_unlock(sl) -#define EBADFD 32767 - -/* background.c */ -#ifdef CYGOPT_FS_JFFS2_GCTHREAD -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); -void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); -void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); -#else -static inline void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) -{ - /* We don't have a GC thread in eCos (yet) */ -} -#endif - -/* fs-ecos.c */ -struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri); -struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino); -void jffs2_iput(struct _inode * i); -void jffs2_gc_release_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); -struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, int inum, int nlink); -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned long offset, unsigned long *priv); -void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv); - -/* Avoid polluting eCos namespace with names not starting in jffs2_ */ -#define os_to_jffs2_mode(x) jffs2_from_os_mode(x) -uint32_t jffs2_from_os_mode(uint32_t osmode); -uint32_t jffs2_to_os_mode (uint32_t jmode); - - -/* flashio.c */ -int jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset, - const size_t size, size_t * return_size, unsigned char * write_buffer); -int jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset, - const size_t size, size_t * return_size, unsigned char * read_buffer); -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, - unsigned long count, loff_t to, size_t *retlen); -int jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); - -// dir-ecos.c -struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, int namelen); -int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode, struct _inode **new_i); -int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode); -int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name); -int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name); -int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name); -int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, - struct _inode *new_dir_i, const unsigned char *new_d_name); - -/* erase.c */ -static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) -{ } - -#ifndef CONFIG_JFFS2_FS_WRITEBUFFER -#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) -#define jffs2_can_mark_obsolete(c) (1) -#define jffs2_cleanmarker_oob(c) (0) -#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) - -#define jffs2_flush_wbuf_pad(c) (c=c) -#define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) -#define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0) -#define jffs2_write_nand_badblock(c,jeb,p) (0) -#define jffs2_flash_setup(c) (0) -#define jffs2_nand_flash_cleanup(c) do {} while(0) -#define jffs2_wbuf_dirty(c) (0) -#define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) -#define jffs2_wbuf_timeout NULL -#define jffs2_wbuf_process NULL -#define jffs2_nor_ecc(c) (0) -#else -#error no nand yet -#endif - -#ifndef BUG_ON -#define BUG_ON(x) do { if (unlikely(x)) BUG(); } while(0) -#endif - -#define __init - -#endif /* __JFFS2_OS_ECOS_H__ */ diff --git a/components/dfs/filesystems/jffs2/src/os-rtthread.h b/components/dfs/filesystems/jffs2/src/os-rtthread.h deleted file mode 100644 index 95496c2e73..0000000000 --- a/components/dfs/filesystems/jffs2/src/os-rtthread.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2002-2003 Free Software Foundation, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: os-ecos.h,v 1.24 2005/02/09 09:23:55 pavlov Exp $ - * - */ - -#ifndef __JFFS2_OS_RTTHREAD_H__ -#define __JFFS2_OS_RTTHREAD_H__ -#include "jffs2_config.h" -#include -#define printf rt_kprintf - -//#include -//#include -//#include -#include -#include -#include - -//#include -//#include -//#include - -//#include // tracing macros -//#include // assertion macros - -//#if defined (__GNUC__) -//#include -//#elif defined (MSVC) -//#else -//#endif - -#include "os_sys_stat.h"//#include -//#include -//#include -//#include //fixme - -//#include -#define CYGPKG_FILEIO_DIRENT_DTYPE -struct dirent -{ -#ifdef CYGPKG_FILEIO_DIRENT_DTYPE - - mode_t d_type; // Only supported with FATFS, RAMFS, ROMFS, - // and JFFS2. - // d_type is not part of POSIX so - // should be used with caution. -#endif - char d_name[NAME_MAX+1]; -}; - -#include - -#include //prife - -//#include -//#include - -//#include - -#include -#include -#include - -//#define printf diag_printf //prife - -struct _inode; -struct super_block; - -struct iovec { - void *iov_base; - ssize_t iov_len; -}; - -static inline unsigned int full_name_hash(const unsigned char * name, unsigned int len) { - - unsigned hash = 0; - while (len--) { - hash = (hash << 4) | (hash >> 28); - hash ^= *(name++); - } - return hash; -} - -#ifdef CYGOPT_FS_JFFS2_WRITE -#define jffs2_is_readonly(c) (0) -#else -#define jffs2_is_readonly(c) (1) -#endif - -/* NAND flash not currently supported on eCos */ -#define jffs2_can_mark_obsolete(c) (1) - -#define JFFS2_INODE_INFO(i) (&(i)->jffs2_i) -#define OFNI_EDONI_2SFFJ(f) ((struct _inode *) ( ((char *)f) - ((char *)(&((struct _inode *)NULL)->jffs2_i)) ) ) - -#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size) -#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) -#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) -#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) -#define JFFS2_F_I_CTIME(f) (OFNI_EDONI_2SFFJ(f)->i_ctime) -#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime) -#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime) - -/* FIXME: eCos doesn't hav a concept of device major/minor numbers */ -#define JFFS2_F_I_RDEV_MIN(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)&0xff) -#define JFFS2_F_I_RDEV_MAJ(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)>>8) - -#define get_seconds jffs2_get_timestamp - -struct _inode { - cyg_uint32 i_ino; - - int i_count; - mode_t i_mode; - nlink_t i_nlink; // Could we dispense with this? - uid_t i_uid; - gid_t i_gid; - time_t i_atime; - time_t i_mtime; - time_t i_ctime; -// union { - unsigned short i_rdev; // For devices only - struct _inode * i_parent; // For directories only - off_t i_size; // For files only -// }; - struct super_block * i_sb; - - struct jffs2_inode_info jffs2_i; - - struct _inode * i_cache_prev; // We need doubly-linked? - struct _inode * i_cache_next; -}; - -#define JFFS2_SB_INFO(sb) (&(sb)->jffs2_sb) -#define OFNI_BS_2SFFJ(c) ((struct super_block *) ( ((char *)c) - ((char *)(&((struct super_block *)NULL)->jffs2_sb)) ) ) - -struct super_block { - struct jffs2_sb_info jffs2_sb; - struct _inode * s_root; - unsigned long s_mount_count; - cyg_io_handle_t s_dev; - -//#ifdef CYGOPT_FS_JFFS2_GCTHREAD -// cyg_mutex_t s_lock; // Lock the inode cache -// cyg_flag_t s_gc_thread_flags; // Communication with the gcthread -// cyg_handle_t s_gc_thread_handle; -// cyg_thread s_gc_thread; -//#if (CYGNUM_JFFS2_GC_THREAD_STACK_SIZE >= CYGNUM_HAL_STACK_SIZE_MINIMUM) -// char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE]; -//#else -// char s_gc_thread_stack[CYGNUM_HAL_STACK_SIZE_MINIMUM]; -//#endif -// cyg_mtab_entry *mte; -//#endif - -#ifdef CYGOPT_FS_JFFS2_GCTHREAD - struct rt_mutex s_lock; // Lock the inode cache - struct rt_event s_gc_thread_flags; // Communication with the gcthread - //void (*s_gc_thread_handle)(void *parameter); - struct rt_thread s_gc_thread; -//#if (CYGNUM_JFFS2_GC_THREAD_STACK_SIZE >= CYGNUM_HAL_STACK_SIZE_MINIMUM) -// char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE]; -//#else -// char s_gc_thread_stack[CYGNUM_HAL_STACK_SIZE_MINIMUM]; -//#endif - #define CYGNUM_JFFS2_GC_THREAD_STACK_SIZE (1024*4) - char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE]; - - cyg_mtab_entry *mte; -#endif - -}; - -#define sleep_on_spinunlock(wq, sl) spin_unlock(sl) -#define EBADFD 32767 - -/* background.c */ -#ifdef CYGOPT_FS_JFFS2_GCTHREAD -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); -void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); -void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); -#else -static inline void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) -{ - /* We don't have a GC thread in eCos (yet) */ -} -#endif - -/* fs-ecos.c */ -struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri); -struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino); -void jffs2_iput(struct _inode * i); -void jffs2_gc_release_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); -struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, int inum, int nlink); -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned long offset, unsigned long *priv); -void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv); - -/* Avoid polluting eCos namespace with names not starting in jffs2_ */ -#define os_to_jffs2_mode(x) jffs2_from_os_mode(x) -uint32_t jffs2_from_os_mode(uint32_t osmode); -uint32_t jffs2_to_os_mode (uint32_t jmode); - - -/* flashio.c */ -int jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset, - const size_t size, size_t * return_size, unsigned char * write_buffer); -int jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset, - const size_t size, size_t * return_size, unsigned char * read_buffer); -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, - unsigned long count, loff_t to, size_t *retlen); -int jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); - -// dir-ecos.c -struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, int namelen); -int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode, struct _inode **new_i); -int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode); -int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name); -int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name); -int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name); -int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, - struct _inode *new_dir_i, const unsigned char *new_d_name); - -/* erase.c */ -static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) -{ } - -#ifndef CONFIG_JFFS2_FS_WRITEBUFFER -#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) -#define jffs2_can_mark_obsolete(c) (1) -#define jffs2_cleanmarker_oob(c) (0) -#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) - -#define jffs2_flush_wbuf_pad(c) (c=c) -#define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) -#define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0) -#define jffs2_write_nand_badblock(c,jeb,p) (0) -#define jffs2_flash_setup(c) (0) -#define jffs2_nand_flash_cleanup(c) do {} while(0) -#define jffs2_wbuf_dirty(c) (0) -#define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) -#define jffs2_wbuf_timeout NULL -#define jffs2_wbuf_process NULL -#define jffs2_nor_ecc(c) (0) -#else -#error no nand yet -#endif - -#ifndef BUG_ON -#define BUG_ON(x) do { if (unlikely(x)) BUG(); } while(0) -#endif - -#define __init - -#endif /* __JFFS2_OS_ECOS_H__ */ diff --git a/components/dfs/filesystems/jffs2/src/pushpull.h b/components/dfs/filesystems/jffs2/src/pushpull.h deleted file mode 100644 index 4e84ee38a8..0000000000 --- a/components/dfs/filesystems/jffs2/src/pushpull.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001, 2002 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: pushpull.h,v 1.10 2004/11/16 20:36:11 dwmw2 Exp $ - * - */ - -#ifndef __PUSHPULL_H__ -#define __PUSHPULL_H__ - -#include - -struct pushpull { - unsigned char *buf; - unsigned int buflen; - unsigned int ofs; - unsigned int reserve; -}; - - -static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve) -{ - pp->buf = (unsigned char *)buf; - pp->buflen = buflen; - pp->ofs = ofs; - pp->reserve = reserve; -} - -static inline int pushbit(struct pushpull *pp, int bit, int use_reserved) -{ - if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) { - return -ENOSPC; - } - - if (bit) { - pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7))); - } - else { - pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7))); - } - pp->ofs++; - - return 0; -} - -static inline int pushedbits(struct pushpull *pp) -{ - return pp->ofs; -} - -static inline int pullbit(struct pushpull *pp) -{ - int bit; - - bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1; - - pp->ofs++; - return bit; -} - -static inline int pulledbits(struct pushpull *pp) -{ - return pp->ofs; -} - -#endif /* __PUSHPULL_H__ */ diff --git a/components/dfs/filesystems/jffs2/src/read.c b/components/dfs/filesystems/jffs2/src/read.c deleted file mode 100644 index a70edd9bc0..0000000000 --- a/components/dfs/filesystems/jffs2/src/read.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: read.c,v 1.41 2005/07/22 10:32:08 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include -#include -#include "nodelist.h" -#include "compr.h" - -int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_full_dnode *fd, unsigned char *buf, - int ofs, int len) -{ - struct jffs2_raw_inode *ri; - size_t readlen; - uint32_t crc; - unsigned char *decomprbuf = NULL; - unsigned char *readbuf = NULL; - int ret = 0,i=0; - - ri = jffs2_alloc_raw_inode(); - if (!ri) - return -ENOMEM; - - ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (unsigned char *)ri); - if (ret) { - jffs2_free_raw_inode(ri); - printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", ref_offset(fd->raw), ret); - return ret; - } - if (readlen != sizeof(*ri)) { - jffs2_free_raw_inode(ri); - printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", - ref_offset(fd->raw), sizeof(*ri), readlen); - return -EIO; - } - crc = crc32(0, ri, sizeof(*ri)-8); - - D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", - ref_offset(fd->raw), je32_to_cpu(ri->node_crc), - crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), - je32_to_cpu(ri->offset), buf)); - if (crc != je32_to_cpu(ri->node_crc)) { - printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", - je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw)); - ret = -EIO; - goto out_ri; - } - /* There was a bug where we wrote hole nodes out with csize/dsize - swapped. Deal with it */ - if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && - je32_to_cpu(ri->csize)) { - ri->dsize = ri->csize; - ri->csize = cpu_to_je32(0); - } - - D1(if(ofs + len > je32_to_cpu(ri->dsize)) { - printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", - len, ofs, je32_to_cpu(ri->dsize)); - ret = -EINVAL; - goto out_ri; - }); - - - if (ri->compr == JFFS2_COMPR_ZERO) { - memset(buf, 0, len); - goto out_ri; - } - - /* Cases: - Reading whole node and it's uncompressed - read directly to buffer provided, check CRC. - Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided - Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy - Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy - */ - if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) { - readbuf = buf; - } else { - readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL); - if (!readbuf) { - ret = -ENOMEM; - goto out_ri; - } - } - if (ri->compr != JFFS2_COMPR_NONE) { - if (len < je32_to_cpu(ri->dsize)) { - decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL); - if (!decomprbuf) { - ret = -ENOMEM; - goto out_readbuf; - } - } else { - decomprbuf = buf; - } - } else { - decomprbuf = readbuf; - } - - D2(printk(KERN_DEBUG "Read %d bytes to %p\n", je32_to_cpu(ri->csize), - readbuf)); - ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri), - je32_to_cpu(ri->csize), &readlen, readbuf); - - if (!ret && readlen != je32_to_cpu(ri->csize)) - ret = -EIO; - if (ret) - goto out_decomprbuf; - - crc = crc32(0, readbuf, je32_to_cpu(ri->csize)); - if (crc != je32_to_cpu(ri->data_crc)) { - printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", - je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw)); - ret = -EIO; - goto out_decomprbuf; - } - D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); - if (ri->compr != JFFS2_COMPR_NONE) { - D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", - je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); - //add for debug -// for (i=0; icsize); i++) -// { -// printf("%02x ", readbuf[i]); -// if( (i+1) % 16 == 0) -// printf("\n"); -// } - //end debug - ret = jffs2_decompress(c, f, ri->compr | (ri->usercompr << 8), readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); - if (ret) { - printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); - goto out_decomprbuf; - } - } - - if (len < je32_to_cpu(ri->dsize)) { - memcpy(buf, decomprbuf+ofs, len); - } - out_decomprbuf: - if(decomprbuf != buf && decomprbuf != readbuf) - kfree(decomprbuf); - out_readbuf: - if(readbuf != buf) - kfree(readbuf); - out_ri: - jffs2_free_raw_inode(ri); - - return ret; -} - -int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned char *buf, uint32_t offset, uint32_t len) -{ - uint32_t end = offset + len; - struct jffs2_node_frag *frag; - int ret; - - D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n", - f->inocache->ino, offset, offset+len)); - - frag = jffs2_lookup_node_frag(&f->fragtree, offset); - - /* XXX FIXME: Where a single physical node actually shows up in two - frags, we read it twice. Don't do that. */ - /* Now we're pointing at the first frag which overlaps our page */ - while(offset < end) { - D2(printk(KERN_DEBUG "jffs2_read_inode_range: offset %d, end %d\n", offset, end)); - if (unlikely(!frag || frag->ofs > offset)) { - uint32_t holesize = end - offset; - if (frag) { - D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); - holesize = min(holesize, frag->ofs - offset); - } - D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); - memset(buf, 0, holesize); - buf += holesize; - offset += holesize; - continue; - } else if (unlikely(!frag->node)) { - uint32_t holeend = min(end, frag->ofs + frag->size); - D1(printk(KERN_DEBUG "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset, holeend, frag->ofs, frag->ofs + frag->size)); - memset(buf, 0, holeend - offset); - buf += holeend - offset; - offset = holeend; - frag = frag_next(frag); - continue; - } else { - uint32_t readlen; - uint32_t fragofs; /* offset within the frag to start reading */ - - fragofs = offset - frag->ofs; - readlen = min(frag->size - fragofs, end - offset); - D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n", - frag->ofs+fragofs, frag->ofs+fragofs+readlen, - ref_offset(frag->node->raw), ref_flags(frag->node->raw))); - ret = jffs2_read_dnode(c, f, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen); - D2(printk(KERN_DEBUG "node read done\n")); - if (ret) { - D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret)); - memset(buf, 0, readlen); - return ret; - } - buf += readlen; - offset += readlen; - frag = frag_next(frag); - D2(printk(KERN_DEBUG "node read was OK. Looping\n")); - } - } - return 0; -} - diff --git a/components/dfs/filesystems/jffs2/src/readinode.c b/components/dfs/filesystems/jffs2/src/readinode.c deleted file mode 100644 index ae1481fd23..0000000000 --- a/components/dfs/filesystems/jffs2/src/readinode.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: readinode.c,v 1.132 2005/07/28 14:46:40 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "nodelist.h" - -void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) -{ - struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); - - JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size); - - /* We know frag->ofs <= size. That's what lookup does for us */ - if (frag && frag->ofs != size) { - if (frag->ofs+frag->size >= size) { - JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); - frag->size = size - frag->ofs; - } - frag = frag_next(frag); - } - while (frag && frag->ofs >= size) { - struct jffs2_node_frag *next = frag_next(frag); - - JFFS2_DBG_FRAGTREE("removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); - frag_erase(frag, list); - jffs2_obsolete_node_frag(c, frag); - frag = next; - } -} - -/* - * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in - * order of increasing version. - */ -static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) -{ - struct rb_node **p = &list->rb_node; - struct rb_node * parent = NULL; - struct jffs2_tmp_dnode_info *this; - - while (*p) { - parent = *p; - this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); - - /* There may actually be a collision here, but it doesn't - actually matter. As long as the two nodes with the same - version are together, it's all fine. */ - if (tn->version < this->version) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - rb_link_node(&tn->rb, parent, p); - rb_insert_color(&tn->rb, list); -} - -static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) -{ - struct rb_node *this; - struct jffs2_tmp_dnode_info *tn; - - this = list->rb_node; - - /* Now at bottom of tree */ - while (this) { - if (this->rb_left) - this = this->rb_left; - else if (this->rb_right) - this = this->rb_right; - else { - tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb); - jffs2_free_full_dnode(tn->fn); - jffs2_free_tmp_dnode_info(tn); - - this = this->rb_parent; - if (!this) - break; - - if (this->rb_left == &tn->rb) - this->rb_left = NULL; - else if (this->rb_right == &tn->rb) - this->rb_right = NULL; - else BUG(); - } - } - list->rb_node = NULL; -} - -static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) -{ - struct jffs2_full_dirent *next; - - while (fd) { - next = fd->next; - jffs2_free_full_dirent(fd); - fd = next; - } -} - -/* Returns first valid node after 'ref'. May return 'ref' */ -static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref) -{ - while (ref && ref->next_in_ino) { - if (!ref_obsolete(ref)) - return ref; - JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); - ref = ref->next_in_ino; - } - return NULL; -} - -/* - * Helper function for jffs2_get_inode_nodes(). - * It is called every time an directory entry node is found. - * - * Returns: 0 on succes; - * 1 if the node should be marked obsolete; - * negative error code on failure. - */ -static inline int -read_direntry(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_raw_dirent *rd, - uint32_t read, - struct jffs2_full_dirent **fdp, - int32_t *latest_mctime, - uint32_t *mctime_ver) -{ - struct jffs2_full_dirent *fd; - - /* The direntry nodes are checked during the flash scanning */ - BUG_ON(ref_flags(ref) == REF_UNCHECKED); - /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ - BUG_ON(ref_obsolete(ref)); - - /* Sanity check */ - if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { - JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", - ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); - return 1; - } - - fd = jffs2_alloc_full_dirent(rd->nsize + 1); - if (unlikely(!fd)) - return -ENOMEM; - - fd->raw = ref; - fd->version = je32_to_cpu(rd->version); - fd->ino = je32_to_cpu(rd->ino); - fd->type = rd->type; - - /* Pick out the mctime of the latest dirent */ - if(fd->version > *mctime_ver) { - *mctime_ver = fd->version; - *latest_mctime = je32_to_cpu(rd->mctime); - } - - /* - * Copy as much of the name as possible from the raw - * dirent we've already read from the flash. - */ - if (read > sizeof(*rd)) - memcpy(&fd->name[0], &rd->name[0], - min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); - - /* Do we need to copy any more of the name directly from the flash? */ - if (rd->nsize + sizeof(*rd) > read) { - /* FIXME: point() */ - int err; - int already = read - sizeof(*rd); - - err = jffs2_flash_read(c, (ref_offset(ref)) + read, - rd->nsize - already, (size_t*)&read, &fd->name[already]); - if (unlikely(read != rd->nsize - already) && likely(!err)) - return -EIO; - - if (unlikely(err)) { - JFFS2_ERROR("read remainder of name: error %d\n", err); - jffs2_free_full_dirent(fd); - return -EIO; - } - } - - fd->nhash = full_name_hash(fd->name, rd->nsize); - fd->next = NULL; - fd->name[rd->nsize] = '\0'; - - /* - * Wheee. We now have a complete jffs2_full_dirent structure, with - * the name in it and everything. Link it into the list - */ - jffs2_add_fd_to_list(c, fd, fdp); - - return 0; -} - -/* - * Helper function for jffs2_get_inode_nodes(). - * It is called every time an inode node is found. - * - * Returns: 0 on succes; - * 1 if the node should be marked obsolete; - * negative error code on failure. - */ -static inline int -read_dnode(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_raw_inode *rd, - uint32_t read, - struct rb_root *tnp, - int32_t *latest_mctime, - uint32_t *mctime_ver) -{ - struct jffs2_eraseblock *jeb; - struct jffs2_tmp_dnode_info *tn; - - /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ - BUG_ON(ref_obsolete(ref)); - - /* If we've never checked the CRCs on this node, check them now */ - if (ref_flags(ref) == REF_UNCHECKED) { - uint32_t crc, len; - - crc = crc32(0, rd, sizeof(*rd) - 8); - if (unlikely(crc != je32_to_cpu(rd->node_crc))) { - JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", - ref_offset(ref), je32_to_cpu(rd->node_crc), crc); - return 1; - } - - /* Sanity checks */ - if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || - unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { - JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); - jffs2_dbg_dump_node(c, ref_offset(ref)); - return 1; - } - - if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) { - unsigned char *buf = NULL; - uint32_t pointed = 0; - int err; -#ifndef __ECOS - if (c->mtd->point) { - err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), - &read, &buf); - if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) { - JFFS2_ERROR("MTD point returned len too short: 0x%zx\n", read); - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), - je32_to_cpu(rd->csize)); - } else if (unlikely(err)){ - JFFS2_ERROR("MTD point failed %d\n", err); - } else - pointed = 1; /* succefully pointed to device */ - } -#endif - if(!pointed){ - buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), - (size_t*)&read, buf); - if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err)) - err = -EIO; - if (err) { - kfree(buf); - return err; - } - } - crc = crc32(0, buf, je32_to_cpu(rd->csize)); - if(!pointed) - kfree(buf); -#ifndef __ECOS - else - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize)); -#endif - - if (crc != je32_to_cpu(rd->data_crc)) { - JFFS2_NOTICE("data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", - ref_offset(ref), je32_to_cpu(rd->data_crc), crc); - return 1; - } - - } - - /* Mark the node as having been checked and fix the accounting accordingly */ - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, ref); - - spin_lock(&c->erase_completion_lock); - jeb->used_size += len; - jeb->unchecked_size -= len; - c->used_size += len; - c->unchecked_size -= len; - - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. - - If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) - when the overlapping node(s) get added to the tree anyway. - */ - if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) || - ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) && - (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) { - JFFS2_DBG_READINODE("marking node at %#08x REF_PRISTINE\n", ref_offset(ref)); - ref->flash_offset = ref_offset(ref) | REF_PRISTINE; - } else { - JFFS2_DBG_READINODE("marking node at %#08x REF_NORMAL\n", ref_offset(ref)); - ref->flash_offset = ref_offset(ref) | REF_NORMAL; - } - spin_unlock(&c->erase_completion_lock); - } - - tn = jffs2_alloc_tmp_dnode_info(); - if (!tn) { - JFFS2_ERROR("alloc tn failed\n"); - return -ENOMEM; - } - - tn->fn = jffs2_alloc_full_dnode(); - if (!tn->fn) { - JFFS2_ERROR("alloc fn failed\n"); - jffs2_free_tmp_dnode_info(tn); - return -ENOMEM; - } - - tn->version = je32_to_cpu(rd->version); - tn->fn->ofs = je32_to_cpu(rd->offset); - tn->fn->raw = ref; - - /* There was a bug where we wrote hole nodes out with - csize/dsize swapped. Deal with it */ - if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize)) - tn->fn->size = je32_to_cpu(rd->csize); - else // normal case... - tn->fn->size = je32_to_cpu(rd->dsize); - - JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", - ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize)); - - jffs2_add_tn_to_tree(tn, tnp); - - return 0; -} - -/* - * Helper function for jffs2_get_inode_nodes(). - * It is called every time an unknown node is found. - * - * Returns: 0 on succes; - * 1 if the node should be marked obsolete; - * negative error code on failure. - */ -static inline int -read_unknown(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_unknown_node *un, - uint32_t read) -{ - /* We don't mark unknown nodes as REF_UNCHECKED */ - BUG_ON(ref_flags(ref) == REF_UNCHECKED); - - un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); - - if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { - /* Hmmm. This should have been caught at scan time. */ - JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref)); - jffs2_dbg_dump_node(c, ref_offset(ref)); - return 1; - } else { - switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { - - case JFFS2_FEATURE_INCOMPAT: - JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - /* EEP */ - BUG(); - break; - - case JFFS2_FEATURE_ROCOMPAT: - JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); - break; - - case JFFS2_FEATURE_RWCOMPAT_COPY: - JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - break; - - case JFFS2_FEATURE_RWCOMPAT_DELETE: - JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - return 1; - } - } - - return 0; -} - -/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated - with this ino, returning the former in order of version */ - -static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct rb_root *tnp, struct jffs2_full_dirent **fdp, - uint32_t *highest_version, uint32_t *latest_mctime, - uint32_t *mctime_ver) -{ - struct jffs2_raw_node_ref *ref, *valid_ref; - struct rb_root ret_tn = RB_ROOT; - struct jffs2_full_dirent *ret_fd = NULL; - union jffs2_node_union node; - size_t retlen; - int err; - - *mctime_ver = 0; - - JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino); - - spin_lock(&c->erase_completion_lock); - - valid_ref = jffs2_first_valid_node(f->inocache->nodes); - - if (!valid_ref && (f->inocache->ino != 1)) - JFFS2_WARNING("no valid nodes for ino #%u\n", f->inocache->ino); - - while (valid_ref) { - /* We can hold a pointer to a non-obsolete node without the spinlock, - but _obsolete_ nodes may disappear at any time, if the block - they're in gets erased. So if we mark 'ref' obsolete while we're - not holding the lock, it can go away immediately. For that reason, - we find the next valid node first, before processing 'ref'. - */ - ref = valid_ref; - valid_ref = jffs2_first_valid_node(ref->next_in_ino); - spin_unlock(&c->erase_completion_lock); - - cond_resched(); - - /* FIXME: point() */ - err = jffs2_flash_read(c, (ref_offset(ref)), - min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), - &retlen, (void *)&node); - if (err) { - JFFS2_ERROR("error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); - goto free_out; - } - - switch (je16_to_cpu(node.u.nodetype)) { - - case JFFS2_NODETYPE_DIRENT: - JFFS2_DBG_READINODE("node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref)); - - if (retlen < sizeof(node.d)) { - JFFS2_ERROR("short read dirent at %#08x\n", ref_offset(ref)); - err = -EIO; - goto free_out; - } - - err = read_direntry(c, ref, &node.d, retlen, &ret_fd, (int32_t *)latest_mctime, mctime_ver); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) - goto free_out; - - if (je32_to_cpu(node.d.version) > *highest_version) - *highest_version = je32_to_cpu(node.d.version); - - break; - - case JFFS2_NODETYPE_INODE: - JFFS2_DBG_READINODE("node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref)); - - if (retlen < sizeof(node.i)) { - JFFS2_ERROR("short read dnode at %#08x\n", ref_offset(ref)); - err = -EIO; - goto free_out; - } - - err = read_dnode(c, ref, &node.i, retlen, &ret_tn, (int32_t *)latest_mctime, mctime_ver); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) - goto free_out; - - if (je32_to_cpu(node.i.version) > *highest_version) - *highest_version = je32_to_cpu(node.i.version); - - JFFS2_DBG_READINODE("version %d, highest_version now %d\n", - je32_to_cpu(node.i.version), *highest_version); - - break; - - default: - /* Check we've managed to read at least the common node header */ - if (retlen < sizeof(struct jffs2_unknown_node)) { - JFFS2_ERROR("short read unknown node at %#08x\n", ref_offset(ref)); - return -EIO; - } - - err = read_unknown(c, ref, &node.u, retlen); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) - goto free_out; - - } - spin_lock(&c->erase_completion_lock); - - } - spin_unlock(&c->erase_completion_lock); - *tnp = ret_tn; - *fdp = ret_fd; - - return 0; - - free_out: - jffs2_free_tmp_dnode_info_list(&ret_tn); - jffs2_free_full_dirent_list(ret_fd); - return err; -} - -static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, - struct jffs2_raw_inode *latest_node) -{ - struct jffs2_tmp_dnode_info *tn = NULL; - struct rb_root tn_list; - struct rb_node *rb, *repl_rb; - struct jffs2_full_dirent *fd_list; - struct jffs2_full_dnode *fn = NULL; - uint32_t crc; - uint32_t latest_mctime, mctime_ver; - uint32_t mdata_ver = 0; - size_t retlen; - int ret; - - JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); - - /* Grab all nodes relevant to this ino */ - ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); - - if (ret) { - JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); - if (f->inocache->state == INO_STATE_READING) - jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); - return ret; - } - f->dents = fd_list; - - rb = rb_first(&tn_list); - - while (rb) { - tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); - fn = tn->fn; - - if (f->metadata) { - if (likely(tn->version >= mdata_ver)) { - JFFS2_DBG_READINODE("obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw)); - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - - mdata_ver = 0; - } else { - /* This should never happen. */ - JFFS2_ERROR("Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n", - ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw)); - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); - /* Fill in latest_node from the metadata, not this one we're about to free... */ - fn = f->metadata; - goto next_tn; - } - } - - if (fn->size) { - jffs2_add_full_dnode_to_inode(c, f, fn); - } else { - /* Zero-sized node at end of version list. Just a metadata update */ - JFFS2_DBG_READINODE("metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version); - f->metadata = fn; - mdata_ver = tn->version; - } - next_tn: - BUG_ON(rb->rb_left); - if (rb->rb_parent && rb->rb_parent->rb_left == rb) { - /* We were then left-hand child of our parent. We need - to move our own right-hand child into our place. */ - repl_rb = rb->rb_right; - if (repl_rb) - repl_rb->rb_parent = rb->rb_parent; - } else - repl_rb = NULL; - - rb = rb_next(rb); - - /* Remove the spent tn from the tree; don't bother rebalancing - but put our right-hand child in our own place. */ - if (tn->rb.rb_parent) { - if (tn->rb.rb_parent->rb_left == &tn->rb) - tn->rb.rb_parent->rb_left = repl_rb; - else if (tn->rb.rb_parent->rb_right == &tn->rb) - tn->rb.rb_parent->rb_right = repl_rb; - else BUG(); - } else if (tn->rb.rb_right) - tn->rb.rb_right->rb_parent = NULL; - - jffs2_free_tmp_dnode_info(tn); - } - jffs2_dbg_fragtree_paranoia_check_nolock(f); - - if (!fn) { - /* No data nodes for this inode. */ - if (f->inocache->ino != 1) { - JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); - if (!fd_list) { - if (f->inocache->state == INO_STATE_READING) - jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); - return -EIO; - } - JFFS2_NOTICE("but it has children so we fake some modes for it\n"); - } - latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); - latest_node->version = cpu_to_je32(0); - latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0); - latest_node->isize = cpu_to_je32(0); - latest_node->gid = cpu_to_je16(0); - latest_node->uid = cpu_to_je16(0); - if (f->inocache->state == INO_STATE_READING) - jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); - return 0; - } - - ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); - if (ret || retlen != sizeof(*latest_node)) { - JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", - ret, retlen, sizeof(*latest_node)); - /* FIXME: If this fails, there seems to be a memory leak. Find it. */ - up(&f->sem); - jffs2_do_clear_inode(c, f); - return ret?ret:-EIO; - } - - crc = crc32(0, latest_node, sizeof(*latest_node)-8); - if (crc != je32_to_cpu(latest_node->node_crc)) { - JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", - f->inocache->ino, ref_offset(fn->raw)); - up(&f->sem); - jffs2_do_clear_inode(c, f); - return -EIO; - } - - switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { - case S_IFDIR: - if (mctime_ver > je32_to_cpu(latest_node->version)) { - /* The times in the latest_node are actually older than - mctime in the latest dirent. Cheat. */ - latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); - } - break; - - - case S_IFREG: - /* If it was a regular file, truncate it to the latest node's isize */ - jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); - break; - -// case S_IFLNK: prife -// /* Hack to work around broken isize in old symlink code. -// Remove this when dwmw2 comes to his senses and stops -// symlinks from being an entirely gratuitous special -// case. */ -// if (!je32_to_cpu(latest_node->isize)) -// latest_node->isize = latest_node->dsize; -// -// if (f->inocache->state != INO_STATE_CHECKING) { -// /* Symlink's inode data is the target path. Read it and -// * keep in RAM to facilitate quick follow symlink -// * operation. */ -// f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); -// if (!f->target) { -// JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); -// up(&f->sem); -// jffs2_do_clear_inode(c, f); -// return -ENOMEM; -// } -// -// ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), -// je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); -// -// if (ret || retlen != je32_to_cpu(latest_node->csize)) { -// if (retlen != je32_to_cpu(latest_node->csize)) -// ret = -EIO; -// kfree(f->target); -// f->target = NULL; -// up(&f->sem); -// jffs2_do_clear_inode(c, f); -// return -ret; -// } -// -// f->target[je32_to_cpu(latest_node->csize)] = '\0'; -// JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target); -// } -// -// /* fall through... */ - - case S_IFBLK: - case S_IFCHR: - /* Certain inode types should have only one data node, and it's - kept as the metadata node */ - if (f->metadata) { - JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", - f->inocache->ino, jemode_to_cpu(latest_node->mode)); - up(&f->sem); - jffs2_do_clear_inode(c, f); - return -EIO; - } - if (!frag_first(&f->fragtree)) { - JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", - f->inocache->ino, jemode_to_cpu(latest_node->mode)); - up(&f->sem); - jffs2_do_clear_inode(c, f); - return -EIO; - } - /* ASSERT: f->fraglist != NULL */ - if (frag_next(frag_first(&f->fragtree))) { - JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", - f->inocache->ino, jemode_to_cpu(latest_node->mode)); - /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ - up(&f->sem); - jffs2_do_clear_inode(c, f); - return -EIO; - } - /* OK. We're happy */ - f->metadata = frag_first(&f->fragtree)->node; - jffs2_free_node_frag(frag_first(&f->fragtree)); - f->fragtree.rb_node = NULL;//f->fragtree = RB_ROOT; // modify it for vs - break; - } - if (f->inocache->state == INO_STATE_READING) - jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); - - return 0; -} - -/* Scan the list of all nodes present for this ino, build map of versions, etc. */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint32_t ino, struct jffs2_raw_inode *latest_node) -{ - JFFS2_DBG_READINODE("read inode #%u\n", ino); - - retry_inocache: - spin_lock(&c->inocache_lock); - f->inocache = jffs2_get_ino_cache(c, ino); - - if (f->inocache) { - /* Check its state. We may need to wait before we can use it */ - switch(f->inocache->state) { - case INO_STATE_UNCHECKED: - case INO_STATE_CHECKEDABSENT: - f->inocache->state = INO_STATE_READING; - break; - - case INO_STATE_CHECKING: - case INO_STATE_GC: - /* If it's in either of these states, we need - to wait for whoever's got it to finish and - put it back. */ - JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state); - sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - goto retry_inocache; - - case INO_STATE_READING: - case INO_STATE_PRESENT: - /* Eep. This should never happen. It can - happen if Linux calls read_inode() again - before clear_inode() has finished though. */ - JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); - /* Fail. That's probably better than allowing it to succeed */ - f->inocache = NULL; - break; - - default: - BUG(); - } - } - spin_unlock(&c->inocache_lock); - - if (!f->inocache && ino == 1) { - /* Special case - no root inode on medium */ - f->inocache = jffs2_alloc_inode_cache(); - if (!f->inocache) { - JFFS2_ERROR("cannot allocate inocache for root inode\n"); - return -ENOMEM; - } - JFFS2_DBG_READINODE("creating inocache for root inode\n"); - memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); - f->inocache->ino = f->inocache->nlink = 1; - f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; - f->inocache->state = INO_STATE_READING; - jffs2_add_ino_cache(c, f->inocache); - } - if (!f->inocache) { - JFFS2_ERROR("requestied to read an nonexistent ino %u\n", ino); - return -ENOENT; - } - - return jffs2_do_read_inode_internal(c, f, latest_node); -} - -int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -{ - struct jffs2_raw_inode n; - struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); - int ret; - - if (!f) - return -ENOMEM; - - memset(f, 0, sizeof(*f)); - init_MUTEX_LOCKED(&f->sem); - f->inocache = ic; - - ret = jffs2_do_read_inode_internal(c, f, &n); - if (!ret) { - up(&f->sem); - jffs2_do_clear_inode(c, f); - } - kfree (f); - return ret; -} - -void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) -{ - struct jffs2_full_dirent *fd, *fds; - int deleted; - - down(&f->sem); - deleted = f->inocache && !f->inocache->nlink; - - if (f->inocache && f->inocache->state != INO_STATE_CHECKING) - jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING); - - if (f->metadata) { - if (deleted) - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - } - - jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); - - if (f->target) { - kfree(f->target); - f->target = NULL; - } - - fds = f->dents; - while(fds) { - fd = fds; - fds = fd->next; - jffs2_free_full_dirent(fd); - } - - if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { - jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); - if (f->inocache->nodes == (void *)f->inocache) - jffs2_del_ino_cache(c, f->inocache); - } - - up(&f->sem); -} diff --git a/components/dfs/filesystems/jffs2/src/scan.c b/components/dfs/filesystems/jffs2/src/scan.c deleted file mode 100644 index f67d122a12..0000000000 --- a/components/dfs/filesystems/jffs2/src/scan.c +++ /dev/null @@ -1,946 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: scan.c,v 1.121 2005/07/20 15:32:28 dedekind Exp $ - * - */ -#include -#include -#include -#include -#include -#include -#include -#include "nodelist.h" - -#define DEFAULT_EMPTY_SCAN_SIZE 1024 - -#if defined (__GNUC__) -#elif defined (MSVC) -#define typeof(x) uint32_t -#else -#endif - -#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->dirty_size += _x; \ - jeb->free_size -= _x ; jeb->dirty_size += _x; \ - }while(0) -#define USED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->used_size += _x; \ - jeb->free_size -= _x ; jeb->used_size += _x; \ - }while(0) -#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->unchecked_size += _x; \ - jeb->free_size -= _x ; jeb->unchecked_size += _x; \ - }while(0) - -#if defined (__GNUC__) -#define noisy_printk(noise, args...) do { \ - if (*(noise)) { \ - printk(KERN_NOTICE args); \ - (*(noise))--; \ - if (!(*(noise))) { \ - printk(KERN_NOTICE "Further such events for this erase block will not be printed\n"); \ - } \ - } \ -} while(0) -#elif defined (MSVC) -#define noisy_printk(noise, ...) do { \ - if (*(noise)) { \ - printk(KERN_NOTICE ##__VA_ARGS__); \ - (*(noise))--; \ - if (!(*(noise))) { \ - printk(KERN_NOTICE "Further such events for this erase block will not be printed\n"); \ - } \ - } \ -} while(0) -#else -#endif - -static uint32_t pseudo_random; - -static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size); - -/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. - * Returning an error will abort the mount - bad checksums etc. should just mark the space - * as dirty. - */ -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs); -static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs); - -#define BLK_STATE_ALLFF 0 -#define BLK_STATE_CLEAN 1 -#define BLK_STATE_PARTDIRTY 2 -#define BLK_STATE_CLEANMARKER 3 -#define BLK_STATE_ALLDIRTY 4 -#define BLK_STATE_BADBLOCK 5 - -static inline int min_free(struct jffs2_sb_info *c) -{ - uint32_t min = 2 * sizeof(struct jffs2_raw_inode); -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER - if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize) - return c->wbuf_pagesize; -#endif - return min; - -} - -static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) { - if (sector_size < DEFAULT_EMPTY_SCAN_SIZE) - return sector_size; - else - return DEFAULT_EMPTY_SCAN_SIZE; -} - -int jffs2_scan_medium(struct jffs2_sb_info *c) -{ - int i, ret; - uint32_t empty_blocks = 0, bad_blocks = 0; - unsigned char *flashbuf = NULL; - uint32_t buf_size = 0; -#ifndef __ECOS - size_t pointlen; - - if (c->mtd->point) { - ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf); - if (!ret && pointlen < c->mtd->size) { - /* Don't muck about if it won't let us point to the whole flash */ - D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen)); - c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); - flashbuf = NULL; - } - if (ret) - D1(printk(KERN_DEBUG "MTD point failed %d\n", ret)); - } -#endif - if (!flashbuf) { - /* For NAND it's quicker to read a whole eraseblock at a time, - apparently */ - if (jffs2_cleanmarker_oob(c)) - buf_size = c->sector_size; - else - buf_size = PAGE_SIZE; - - /* Respect kmalloc limitations */ - if (buf_size > 128*1024) - buf_size = 128*1024; - - D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size)); - flashbuf = kmalloc(buf_size, GFP_KERNEL); - if (!flashbuf) - return -ENOMEM; - } - - for (i=0; inr_blocks; i++) { - struct jffs2_eraseblock *jeb = &c->blocks[i]; - - ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size); - - if (ret < 0) - goto out; - - jffs2_dbg_acct_paranoia_check_nolock(c, jeb); - - /* Now decide which list to put it on */ - switch(ret) { - case BLK_STATE_ALLFF: - /* - * Empty block. Since we can't be sure it - * was entirely erased, we just queue it for erase - * again. It will be marked as such when the erase - * is complete. Meanwhile we still count it as empty - * for later checks. - */ - empty_blocks++; - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - break; - - case BLK_STATE_CLEANMARKER: - /* Only a CLEANMARKER node is valid */ - if (!jeb->dirty_size) { - /* It's actually free */ - list_add(&jeb->list, &c->free_list); - c->nr_free_blocks++; - } else { - /* Dirt */ - D1(printk(KERN_DEBUG "Adding all-dirty block at 0x%08x to erase_pending_list\n", jeb->offset)); - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - } - break; - - case BLK_STATE_CLEAN: - /* Full (or almost full) of clean data. Clean list */ - list_add(&jeb->list, &c->clean_list); - break; - - case BLK_STATE_PARTDIRTY: - /* Some data, but not full. Dirty list. */ - /* We want to remember the block with most free space - and stick it in the 'nextblock' position to start writing to it. */ - if (jeb->free_size > min_free(c) && - (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { - /* Better candidate for the next writes to go to */ - if (c->nextblock) { - c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; - c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; - c->free_size -= c->nextblock->free_size; - c->wasted_size -= c->nextblock->wasted_size; - c->nextblock->free_size = c->nextblock->wasted_size = 0; - if (VERYDIRTY(c, c->nextblock->dirty_size)) { - list_add(&c->nextblock->list, &c->very_dirty_list); - } else { - list_add(&c->nextblock->list, &c->dirty_list); - } - } - c->nextblock = jeb; - } else { - jeb->dirty_size += jeb->free_size + jeb->wasted_size; - c->dirty_size += jeb->free_size + jeb->wasted_size; - c->free_size -= jeb->free_size; - c->wasted_size -= jeb->wasted_size; - jeb->free_size = jeb->wasted_size = 0; - if (VERYDIRTY(c, jeb->dirty_size)) { - list_add(&jeb->list, &c->very_dirty_list); - } else { - list_add(&jeb->list, &c->dirty_list); - } - } - break; - - case BLK_STATE_ALLDIRTY: - /* Nothing valid - not even a clean marker. Needs erasing. */ - /* For now we just put it on the erasing list. We'll start the erases later */ - D1(printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset)); - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - break; - - case BLK_STATE_BADBLOCK: - D1(printk(KERN_NOTICE "JFFS2: Block at 0x%08x is bad\n", jeb->offset)); - list_add(&jeb->list, &c->bad_list); - c->bad_size += c->sector_size; - c->free_size -= c->sector_size; - bad_blocks++; - break; - default: - printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n"); - BUG(); - } - } - - /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ - if (c->nextblock && (c->nextblock->dirty_size)) { - c->nextblock->wasted_size += c->nextblock->dirty_size; - c->wasted_size += c->nextblock->dirty_size; - c->dirty_size -= c->nextblock->dirty_size; - c->nextblock->dirty_size = 0; - } -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER - if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { - /* If we're going to start writing into a block which already - contains data, and the end of the data isn't page-aligned, - skip a little and align it. */ - - uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1); - - D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", - skip)); - c->nextblock->wasted_size += skip; - c->wasted_size += skip; - - c->nextblock->free_size -= skip; - c->free_size -= skip; - } -#endif - if (c->nr_erasing_blocks) { - if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { - printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); - printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks); - ret = -EIO; - goto out; - } - jffs2_erase_pending_trigger(c); - } - ret = 0; - out: - if (buf_size) - kfree(flashbuf); -#ifndef __ECOS - else - c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); -#endif - return ret; -} - -static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, - uint32_t ofs, uint32_t len) -{ - int ret; - size_t retlen; - - ret = jffs2_flash_read(c, ofs, len, &retlen, buf); - if (ret) { - D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret)); - return ret; - } - if (retlen < len) { - D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%zx bytes\n", ofs, retlen)); - return -EIO; - } - D2(printk(KERN_DEBUG "Read 0x%x bytes from 0x%08x into buf\n", len, ofs)); - D2(printk(KERN_DEBUG "000: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15])); - return 0; -} - -static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size) { - struct jffs2_unknown_node *node; - struct jffs2_unknown_node crcnode; - uint32_t ofs, prevofs; - uint32_t hdr_crc, buf_ofs, buf_len; - int err; - int noise = 0; -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER - int cleanmarkerfound = 0; -#endif - - ofs = jeb->offset; - prevofs = jeb->offset - 1; - - D1(printk(KERN_DEBUG "jffs2_scan_eraseblock(): Scanning block at 0x%x\n", ofs)); - -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER - if (jffs2_cleanmarker_oob(c)) { - int ret = jffs2_check_nand_cleanmarker(c, jeb); - D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret)); - /* Even if it's not found, we still scan to see - if the block is empty. We use this information - to decide whether to erase it or not. */ - switch (ret) { - case 0: cleanmarkerfound = 1; break; - case 1: break; - case 2: return BLK_STATE_BADBLOCK; - case 3: return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */ - default: return ret; - } - } -#endif - buf_ofs = jeb->offset; - - if (!buf_size) { - buf_len = c->sector_size; - } else { - buf_len = EMPTY_SCAN_SIZE(c->sector_size); - err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); - if (err) - return err; - } - - /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ - ofs = 0; - - /* Scan only 4KiB of 0xFF before declaring it's empty */ - while(ofs < EMPTY_SCAN_SIZE(c->sector_size) && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) - ofs += 4; - - if (ofs == EMPTY_SCAN_SIZE(c->sector_size)) { -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER - if (jffs2_cleanmarker_oob(c)) { - /* scan oob, take care of cleanmarker */ - int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound); - D2(printk(KERN_NOTICE "jffs2_check_oob_empty returned %d\n",ret)); - switch (ret) { - case 0: return cleanmarkerfound ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF; - case 1: return BLK_STATE_ALLDIRTY; - default: return ret; - } - } -#endif - D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset)); - if (c->cleanmarker_size == 0) - return BLK_STATE_CLEANMARKER; /* don't bother with re-erase */ - else - return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */ - } - if (ofs) { - D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, - jeb->offset + ofs)); - DIRTY_SPACE(ofs); - } - - /* Now ofs is a complete physical flash offset as it always was... */ - ofs += jeb->offset; - - noise = 10; - -scan_more: - while(ofs < jeb->offset + c->sector_size) { - - jffs2_dbg_acct_paranoia_check_nolock(c, jeb); - - cond_resched(); - - if (ofs & 3) { - printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs); - ofs = PAD(ofs); - continue; - } - if (ofs == prevofs) { - printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - prevofs = ofs; - - if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { - D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node), - jeb->offset, c->sector_size, ofs, sizeof(*node))); - DIRTY_SPACE((jeb->offset + c->sector_size)-ofs); - break; - } - - if (buf_ofs + buf_len < ofs + sizeof(*node)) { - buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); - D1(printk(KERN_DEBUG "Fewer than %zd bytes (node header) left to end of buf. Reading 0x%x at 0x%08x\n", - sizeof(struct jffs2_unknown_node), buf_len, ofs)); - err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); - if (err) - return err; - buf_ofs = ofs; - } - - node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs]; - - if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { - uint32_t inbuf_ofs; - uint32_t empty_start; - - empty_start = ofs; - ofs += 4; - - D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); - more_empty: - inbuf_ofs = ofs - buf_ofs; - while (inbuf_ofs < buf_len) { - if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { - printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", - empty_start, ofs); - DIRTY_SPACE(ofs-empty_start); - goto scan_more; - } - - inbuf_ofs+=4; - ofs += 4; - } - /* Ran off end. */ - D1(printk(KERN_DEBUG "Empty flash to end of buffer at 0x%08x\n", ofs)); - - /* If we're only checking the beginning of a block with a cleanmarker, - bail now */ - if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && - c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) { - D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); - return BLK_STATE_CLEANMARKER; - } - - /* See how much more there is to read in this eraseblock... */ - buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); - if (!buf_len) { - /* No more to read. Break out of main loop without marking - this range of empty space as dirty (because it's not) */ - D1(printk(KERN_DEBUG "Empty flash at %08x runs to end of block. Treating as free_space\n", - empty_start)); - break; - } - D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs)); - err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); - if (err) - return err; - buf_ofs = ofs; - goto more_empty; - } - - if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { - printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { - D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs)); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { - printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); - printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) { - /* OK. We're out of possibilities. Whinge and move on */ - noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", - JFFS2_MAGIC_BITMASK, ofs, - je16_to_cpu(node->magic)); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - /* We seem to have a node of sorts. Check the CRC */ - crcnode.magic = node->magic; - crcnode.nodetype = cpu_to_je16( je16_to_cpu(node->nodetype) | JFFS2_NODE_ACCURATE); - crcnode.totlen = node->totlen; - hdr_crc = crc32(0, &crcnode, sizeof(crcnode)-4); - - if (hdr_crc != je32_to_cpu(node->hdr_crc)) { - noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n", - ofs, je16_to_cpu(node->magic), - je16_to_cpu(node->nodetype), - je32_to_cpu(node->totlen), - je32_to_cpu(node->hdr_crc), - hdr_crc); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - - if (ofs + je32_to_cpu(node->totlen) > - jeb->offset + c->sector_size) { - /* Eep. Node goes over the end of the erase block. */ - printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", - ofs, je32_to_cpu(node->totlen)); - printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); - DIRTY_SPACE(4); - ofs += 4; - continue; - } - - if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { - /* Wheee. This is an obsoleted node */ - D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); - DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); - ofs += PAD(je32_to_cpu(node->totlen)); - continue; - } - - switch(je16_to_cpu(node->nodetype)) { - case JFFS2_NODETYPE_INODE: - if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) { - buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); - D1(printk(KERN_DEBUG "Fewer than %zd bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x\n", - sizeof(struct jffs2_raw_inode), buf_len, ofs)); - err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); - if (err) - return err; - buf_ofs = ofs; - node = (void *)buf; - } - err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs); - if (err) return err; - ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_NODETYPE_DIRENT: - if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { - buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); - D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x\n", - je32_to_cpu(node->totlen), buf_len, ofs)); - err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); - if (err) - return err; - buf_ofs = ofs; - node = (void *)buf; - } - err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs); - if (err) return err; - ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_NODETYPE_CLEANMARKER: - D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); - if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", - ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); - DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); - ofs += PAD(sizeof(struct jffs2_unknown_node)); - } else if (jeb->first_node) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); - DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); - ofs += PAD(sizeof(struct jffs2_unknown_node)); - } else { - struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); - if (!marker_ref) { - printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n"); - return -ENOMEM; - } - marker_ref->next_in_ino = NULL; - marker_ref->next_phys = NULL; - marker_ref->flash_offset = ofs | REF_NORMAL; - marker_ref->__totlen = c->cleanmarker_size; - jeb->first_node = jeb->last_node = marker_ref; - - USED_SPACE(PAD(c->cleanmarker_size)); - ofs += PAD(c->cleanmarker_size); - } - break; - - case JFFS2_NODETYPE_PADDING: - DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); - ofs += PAD(je32_to_cpu(node->totlen)); - break; - - default: - switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) { - case JFFS2_FEATURE_ROCOMPAT: - printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); - c->flags |= JFFS2_SB_FLAG_RO; - if (!(jffs2_is_readonly(c))) - return -EROFS; - DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); - ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_FEATURE_INCOMPAT: - printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); - return -EINVAL; - - case JFFS2_FEATURE_RWCOMPAT_DELETE: - D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); - DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); - ofs += PAD(je32_to_cpu(node->totlen)); - break; - - case JFFS2_FEATURE_RWCOMPAT_COPY: - D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); - USED_SPACE(PAD(je32_to_cpu(node->totlen))); - ofs += PAD(je32_to_cpu(node->totlen)); - break; - } - } - } - - - D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, - jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); - - /* mark_node_obsolete can add to wasted !! */ - if (jeb->wasted_size) { - jeb->dirty_size += jeb->wasted_size; - c->dirty_size += jeb->wasted_size; - c->wasted_size -= jeb->wasted_size; - jeb->wasted_size = 0; - } - - if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size - && (!jeb->first_node || !jeb->first_node->next_phys) ) - return BLK_STATE_CLEANMARKER; - - /* move blocks with max 4 byte dirty space to cleanlist */ - else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { - c->dirty_size -= jeb->dirty_size; - c->wasted_size += jeb->dirty_size; - jeb->wasted_size += jeb->dirty_size; - jeb->dirty_size = 0; - return BLK_STATE_CLEAN; - } else if (jeb->used_size || jeb->unchecked_size) - return BLK_STATE_PARTDIRTY; - else - return BLK_STATE_ALLDIRTY; -} - -static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) -{ - struct jffs2_inode_cache *ic; - - ic = jffs2_get_ino_cache(c, ino); - if (ic) - return ic; - - if (ino > c->highest_ino) - c->highest_ino = ino; - - ic = jffs2_alloc_inode_cache(); - if (!ic) { - printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of inode cache failed\n"); - return NULL; - } - memset(ic, 0, sizeof(*ic)); - - ic->ino = ino; - ic->nodes = (void *)ic; - jffs2_add_ino_cache(c, ic); - if (ino == 1) - ic->nlink = 1; - return ic; -} - -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs) -{ - struct jffs2_raw_node_ref *raw; - struct jffs2_inode_cache *ic; - uint32_t ino = je32_to_cpu(ri->ino); - - D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); - - /* We do very little here now. Just check the ino# to which we should attribute - this node; we can do all the CRC checking etc. later. There's a tradeoff here -- - we used to scan the flash once only, reading everything we want from it into - memory, then building all our in-core data structures and freeing the extra - information. Now we allow the first part of the mount to complete a lot quicker, - but we have to go _back_ to the flash in order to finish the CRC checking, etc. - Which means that the _full_ amount of time to get to proper write mode with GC - operational may actually be _longer_ than before. Sucks to be me. */ - - raw = jffs2_alloc_raw_node_ref(); - if (!raw) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); - return -ENOMEM; - } - - ic = jffs2_get_ino_cache(c, ino); - if (!ic) { - /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the - first node we found for this inode. Do a CRC check to protect against the former - case */ - uint32_t crc = crc32(0, ri, sizeof(*ri)-8); - - if (crc != je32_to_cpu(ri->node_crc)) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ofs, je32_to_cpu(ri->node_crc), crc); - /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ - DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen))); - jffs2_free_raw_node_ref(raw); - return 0; - } - ic = jffs2_scan_make_ino_cache(c, ino); - if (!ic) { - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } - } - - /* Wheee. It worked */ - - raw->flash_offset = ofs | REF_UNCHECKED; - raw->__totlen = PAD(je32_to_cpu(ri->totlen)); - raw->next_phys = NULL; - raw->next_in_ino = ic->nodes; - - ic->nodes = raw; - if (!jeb->first_node) - jeb->first_node = raw; - if (jeb->last_node) - jeb->last_node->next_phys = raw; - jeb->last_node = raw; - - D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", - je32_to_cpu(ri->ino), je32_to_cpu(ri->version), - je32_to_cpu(ri->offset), - je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize))); - - pseudo_random += je32_to_cpu(ri->version); - - UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); - return 0; -} - -static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs) -{ - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; - struct jffs2_inode_cache *ic; - uint32_t crc; - - D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); - - /* We don't get here unless the node is still valid, so we don't have to - mask in the ACCURATE bit any more. */ - crc = crc32(0, rd, sizeof(*rd)-8); - - if (crc != je32_to_cpu(rd->node_crc)) { - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ofs, je32_to_cpu(rd->node_crc), crc); - /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ - DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); - return 0; - } - - pseudo_random += je32_to_cpu(rd->version); - - fd = jffs2_alloc_full_dirent(rd->nsize+1); - if (!fd) { - return -ENOMEM; - } - memcpy(&fd->name, rd->name, rd->nsize); - fd->name[rd->nsize] = 0; - - crc = crc32(0, fd->name, rd->nsize); - if (crc != je32_to_cpu(rd->name_crc)) { - printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ofs, je32_to_cpu(rd->name_crc), crc); - D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino))); - jffs2_free_full_dirent(fd); - /* FIXME: Why do we believe totlen? */ - /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ - DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); - return 0; - } - raw = jffs2_alloc_raw_node_ref(); - if (!raw) { - jffs2_free_full_dirent(fd); - printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); - return -ENOMEM; - } - ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); - if (!ic) { - jffs2_free_full_dirent(fd); - jffs2_free_raw_node_ref(raw); - return -ENOMEM; - } - - raw->__totlen = PAD(je32_to_cpu(rd->totlen)); - raw->flash_offset = ofs | REF_PRISTINE; - raw->next_phys = NULL; - raw->next_in_ino = ic->nodes; - ic->nodes = raw; - if (!jeb->first_node) - jeb->first_node = raw; - if (jeb->last_node) - jeb->last_node->next_phys = raw; - jeb->last_node = raw; - - fd->raw = raw; - fd->next = NULL; - fd->version = je32_to_cpu(rd->version); - fd->ino = je32_to_cpu(rd->ino); - fd->nhash = full_name_hash(fd->name, rd->nsize); - fd->type = rd->type; - USED_SPACE(PAD(je32_to_cpu(rd->totlen))); - jffs2_add_fd_to_list(c, fd, &ic->scan_dents); - - return 0; -} - -static int count_list(struct list_head *l) -{ - uint32_t count = 0; - struct list_head *tmp; - - list_for_each(tmp, l) { - count++; - } - return count; -} - -/* Note: This breaks if list_empty(head). I don't care. You - might, if you copy this code and use it elsewhere :) */ -static void rotate_list(struct list_head *head, uint32_t count) -{ - struct list_head *n = head->next; - - list_del(head); - while(count--) { - n = n->next; - } - list_add(head, n); -} - -void jffs2_rotate_lists(struct jffs2_sb_info *c) -{ - uint32_t x; - uint32_t rotateby; - - x = count_list(&c->clean_list); - if (x) { - rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby)); - - rotate_list((&c->clean_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n", - list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty clean_list\n")); - } - - x = count_list(&c->very_dirty_list); - if (x) { - rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby)); - - rotate_list((&c->very_dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n", - list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n")); - } - - x = count_list(&c->dirty_list); - if (x) { - rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby)); - - rotate_list((&c->dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n", - list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n")); - } - - x = count_list(&c->erasable_list); - if (x) { - rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby)); - - rotate_list((&c->erasable_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n", - list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n")); - } - - if (c->nr_erasing_blocks) { - rotateby = pseudo_random % c->nr_erasing_blocks; - D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby)); - - rotate_list((&c->erase_pending_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n", - list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n")); - } - - if (c->nr_free_blocks) { - rotateby = pseudo_random % c->nr_free_blocks; - D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby)); - - rotate_list((&c->free_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n", - list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty free_list\n")); - } -} diff --git a/components/dfs/filesystems/jffs2/src/write.c b/components/dfs/filesystems/jffs2/src/write.c deleted file mode 100644 index dcfc3a49c1..0000000000 --- a/components/dfs/filesystems/jffs2/src/write.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001-2003 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $ - * - */ - -#include -#include -#include -#include -#include -#include -#include "nodelist.h" -#include "compr.h" - - -int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri) -{ - struct jffs2_inode_cache *ic; - - ic = jffs2_alloc_inode_cache(); - if (!ic) { - return -ENOMEM; - } - - memset(ic, 0, sizeof(*ic)); - - f->inocache = ic; - f->inocache->nlink = 1; - f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; - f->inocache->state = INO_STATE_PRESENT; - - - jffs2_add_ino_cache(c, f->inocache); - D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); - ri->ino = cpu_to_je32(f->inocache->ino); - - ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); - ri->totlen = cpu_to_je32(PAD(sizeof(*ri))); - ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - ri->mode = cpu_to_jemode(mode); - - f->highest_version = 1; - ri->version = cpu_to_je32(f->highest_version); - - return 0; -} - -/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, - write it to the flash, link it into the existing inode/fragment list */ - -struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) - -{ - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dnode *fn; - size_t retlen; - struct kvec vecs[2]; - int ret; - int retried = 0; - unsigned long cnt = 2; - - D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { - printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n"); - BUG(); - } - ); - vecs[0].iov_base = ri; - vecs[0].iov_len = sizeof(*ri); - vecs[1].iov_base = (unsigned char *)data; - vecs[1].iov_len = datalen; - - jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); - - if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { - printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); - } - raw = jffs2_alloc_raw_node_ref(); - if (!raw) - return ERR_PTR(-ENOMEM); - - fn = jffs2_alloc_full_dnode(); - if (!fn) { - jffs2_free_raw_node_ref(raw); - return ERR_PTR(-ENOMEM); - } - - fn->ofs = je32_to_cpu(ri->offset); - fn->size = je32_to_cpu(ri->dsize); - fn->frags = 0; - - /* check number of valid vecs */ - if (!datalen || !data) - cnt = 1; - retry: - fn->raw = raw; - - raw->flash_offset = flash_ofs; - raw->__totlen = PAD(sizeof(*ri)+datalen); - raw->next_phys = NULL; - - if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { - BUG_ON(!retried); - D1(printk(KERN_DEBUG "jffs2_write_dnode : dnode_version %d, " - "highest version %d -> updating dnode\n", - je32_to_cpu(ri->version), f->highest_version)); - ri->version = cpu_to_je32(++f->highest_version); - ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - } - - ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen, - (alloc_mode==ALLOC_GC)?0:f->inocache->ino); - - if (ret || (retlen != sizeof(*ri) + datalen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", - sizeof(*ri)+datalen, flash_ofs, ret, retlen); - - /* Mark the space as dirtied */ - if (retlen) { - /* Doesn't belong to any inode */ - raw->next_in_ino = NULL; - - /* Don't change raw->size to match retlen. We may have - written the node header already, and only the data will - seem corrupted, in which case the scan would skip over - any node we write before the original intended end of - this node */ - raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw); - jffs2_mark_node_obsolete(c, raw); - } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); - } - if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { - /* Try to reallocate space and retry */ - uint32_t dummy; - struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; - - retried = 1; - - D1(printk(KERN_DEBUG "Retrying failed write.\n")); - - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); - - if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); - } else { - /* Locking pain */ - up(&f->sem); - jffs2_complete_reservation(c); - - ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode); - down(&f->sem); - } - - if (!ret) { - D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); - - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); - - goto retry; - } - D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); - jffs2_free_raw_node_ref(raw); - } - /* Release the full_dnode which is now useless, and return */ - jffs2_free_full_dnode(fn); - return ERR_PTR(ret?ret:-EIO); - } - /* Mark the space used */ - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. - */ - if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || - ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && - (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { - raw->flash_offset |= REF_PRISTINE; - } else { - raw->flash_offset |= REF_NORMAL; - } - jffs2_add_physical_node_ref(c, raw); - - /* Link into per-inode list */ - spin_lock(&c->erase_completion_lock); - raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; - spin_unlock(&c->erase_completion_lock); - - D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", - flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), - je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), - je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); - - if (retried) { - jffs2_dbg_acct_sanity_check(c,NULL); - } - - return fn; -} - -struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode) -{ - struct jffs2_raw_node_ref *raw; - struct jffs2_full_dirent *fd; - size_t retlen; - struct kvec vecs[2]; - int retried = 0; - int ret; - - D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", - je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), - je32_to_cpu(rd->name_crc))); - - D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { - printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); - BUG(); - } - ); - - vecs[0].iov_base = rd; - vecs[0].iov_len = sizeof(*rd); - vecs[1].iov_base = (unsigned char *)name; - vecs[1].iov_len = namelen; - - jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); - - raw = jffs2_alloc_raw_node_ref(); - - if (!raw) - return ERR_PTR(-ENOMEM); - - fd = jffs2_alloc_full_dirent(namelen+1); - if (!fd) { - jffs2_free_raw_node_ref(raw); - return ERR_PTR(-ENOMEM); - } - - fd->version = je32_to_cpu(rd->version); - fd->ino = je32_to_cpu(rd->ino); - fd->nhash = full_name_hash(name, strlen((const char *)name)); - fd->type = rd->type; - memcpy(fd->name, name, namelen); - fd->name[namelen]=0; - - retry: - fd->raw = raw; - - raw->flash_offset = flash_ofs; - raw->__totlen = PAD(sizeof(*rd)+namelen); - raw->next_phys = NULL; - - if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { - BUG_ON(!retried); - D1(printk(KERN_DEBUG "jffs2_write_dirent : dirent_version %d, " - "highest version %d -> updating dirent\n", - je32_to_cpu(rd->version), f->highest_version)); - rd->version = cpu_to_je32(++f->highest_version); - fd->version = je32_to_cpu(rd->version); - rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); - } - - ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, - (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); - if (ret || (retlen != sizeof(*rd) + namelen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", - sizeof(*rd)+namelen, flash_ofs, ret, retlen); - /* Mark the space as dirtied */ - if (retlen) { - raw->next_in_ino = NULL; - raw->flash_offset |= REF_OBSOLETE; - jffs2_add_physical_node_ref(c, raw); - jffs2_mark_node_obsolete(c, raw); - } else { - printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); - jffs2_free_raw_node_ref(raw); - } - if (!retried && (raw = jffs2_alloc_raw_node_ref())) { - /* Try to reallocate space and retry */ - uint32_t dummy; - struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; - - retried = 1; - - D1(printk(KERN_DEBUG "Retrying failed write.\n")); - - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); - - if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); - } else { - /* Locking pain */ - up(&f->sem); - jffs2_complete_reservation(c); - - ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode); - down(&f->sem); - } - - if (!ret) { - D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); - goto retry; - } - D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); - jffs2_free_raw_node_ref(raw); - } - /* Release the full_dnode which is now useless, and return */ - jffs2_free_full_dirent(fd); - return ERR_PTR(ret?ret:-EIO); - } - /* Mark the space used */ - raw->flash_offset |= REF_PRISTINE; - jffs2_add_physical_node_ref(c, raw); - - spin_lock(&c->erase_completion_lock); - raw->next_in_ino = f->inocache->nodes; - f->inocache->nodes = raw; - spin_unlock(&c->erase_completion_lock); - - if (retried) { - jffs2_dbg_acct_sanity_check(c,NULL); - } - - return fd; -} - -/* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that - we don't have to go digging in struct inode or its equivalent. It should set: - mode, uid, gid, (starting)isize, atime, ctime, mtime */ -int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, - uint32_t offset, uint32_t writelen, uint32_t *retlen) -{ - int ret = 0; - uint32_t writtenlen = 0; - - D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n", - f->inocache->ino, offset, writelen)); - - while(writelen) { - struct jffs2_full_dnode *fn; - unsigned char *comprbuf = NULL; - uint16_t comprtype = JFFS2_COMPR_NONE; - uint32_t phys_ofs, alloclen; - uint32_t datalen, cdatalen; - int retried = 0; - - retry: - D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); - - ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { - D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); - break; - } - down(&f->sem); - datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); - cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); - - comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen); - - ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); - ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen); - ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); - - ri->ino = cpu_to_je32(f->inocache->ino); - ri->version = cpu_to_je32(++f->highest_version); - ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen)); - ri->offset = cpu_to_je32(offset); - ri->csize = cpu_to_je32(cdatalen); - ri->dsize = cpu_to_je32(datalen); - ri->compr = comprtype & 0xff; - ri->usercompr = (comprtype >> 8 ) & 0xff; - ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); - - fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY); - - jffs2_free_comprbuf(comprbuf, buf); - - if (IS_ERR(fn)) { - ret = PTR_ERR(fn); - up(&f->sem); - jffs2_complete_reservation(c); - if (!retried) { - /* Write error to be retried */ - retried = 1; - D1(printk(KERN_DEBUG "Retrying node write in jffs2_write_inode_range()\n")); - goto retry; - } - break; - } - ret = jffs2_add_full_dnode_to_inode(c, f, fn); - if (f->metadata) { - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - } - if (ret) { - /* Eep */ - D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret)); - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); - - up(&f->sem); - jffs2_complete_reservation(c); - break; - } - up(&f->sem); - jffs2_complete_reservation(c); - if (!datalen) { - printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n"); - ret = -EIO; - break; - } - D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen)); - writtenlen += datalen; - offset += datalen; - writelen -= datalen; - buf += datalen; - } - *retlen = writtenlen; - return ret; -} - -int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen) -{ - struct jffs2_raw_dirent *rd; - struct jffs2_full_dnode *fn; - struct jffs2_full_dirent *fd; - uint32_t alloclen, phys_ofs; - int ret; - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though - */ - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); - D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); - if (ret) { - up(&f->sem); - return ret; - } - - ri->data_crc = cpu_to_je32(0); - ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - - fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); - - D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", - jemode_to_cpu(ri->mode))); - - if (IS_ERR(fn)) { - D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); - /* Eeek. Wave bye bye */ - up(&f->sem); - jffs2_complete_reservation(c); - return PTR_ERR(fn); - } - /* No data here. Only a metadata node, which will be - obsoleted by the first data write - */ - f->metadata = fn; - - up(&f->sem); - jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - - if (ret) { - /* Eep. */ - D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); - return ret; - } - - rd = jffs2_alloc_raw_dirent(); - if (!rd) { - /* Argh. Now we treat it like a normal delete */ - jffs2_complete_reservation(c); - return -ENOMEM; - } - - down(&dir_f->sem); - - rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); - rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - - rd->pino = cpu_to_je32(dir_f->inocache->ino); - rd->version = cpu_to_je32(++dir_f->highest_version); - rd->ino = ri->ino; - rd->mctime = ri->ctime; - rd->nsize = namelen; - rd->type = DT_REG; - rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); - rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - - fd = jffs2_write_dirent(c, dir_f, rd, (const unsigned char *)name, namelen, phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_dirent(rd); - - if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally - as if it were the final unlink() */ - jffs2_complete_reservation(c); - up(&dir_f->sem); - return PTR_ERR(fd); - } - - /* Link the fd into the inode's list, obsoleting an old - one if necessary. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); - - jffs2_complete_reservation(c); - up(&dir_f->sem); - - return 0; -} - - -int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, - const char *name, int namelen, struct jffs2_inode_info *dead_f) -{ - struct jffs2_raw_dirent *rd; - struct jffs2_full_dirent *fd; - uint32_t alloclen, phys_ofs; - int ret; - - if (1 /* alternative branch needs testing */ || - !jffs2_can_mark_obsolete(c)) { - /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ - - rd = jffs2_alloc_raw_dirent(); - if (!rd) - return -ENOMEM; - - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); - if (ret) { - jffs2_free_raw_dirent(rd); - return ret; - } - - down(&dir_f->sem); - - /* Build a deletion node */ - rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); - rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - - rd->pino = cpu_to_je32(dir_f->inocache->ino); - rd->version = cpu_to_je32(++dir_f->highest_version); - rd->ino = cpu_to_je32(0); - rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - rd->type = DT_UNKNOWN; - rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); - rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - - fd = jffs2_write_dirent(c, dir_f, rd, (const unsigned char *)name, namelen, phys_ofs, ALLOC_DELETION); - - jffs2_free_raw_dirent(rd); - - if (IS_ERR(fd)) { - jffs2_complete_reservation(c); - up(&dir_f->sem); - return PTR_ERR(fd); - } - - /* File it. This will mark the old one obsolete. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); - up(&dir_f->sem); - } else { - struct jffs2_full_dirent **prev = &dir_f->dents; - uint32_t nhash = full_name_hash((const unsigned char *)name, namelen); - - down(&dir_f->sem); - - while ((*prev) && (*prev)->nhash <= nhash) { - if ((*prev)->nhash == nhash && - !memcmp((*prev)->name, name, namelen) && - !(*prev)->name[namelen]) { - struct jffs2_full_dirent *this = *prev; - - D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n", - this->ino, ref_offset(this->raw))); - - *prev = this->next; - jffs2_mark_node_obsolete(c, (this->raw)); - jffs2_free_full_dirent(this); - break; - } - prev = &((*prev)->next); - } - up(&dir_f->sem); - } - - /* dead_f is NULL if this was a rename not a real unlink */ - /* Also catch the !f->inocache case, where there was a dirent - pointing to an inode which didn't exist. */ - if (dead_f && dead_f->inocache) { - - down(&dead_f->sem); - - if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) { - while (dead_f->dents) { - /* There can be only deleted ones */ - fd = dead_f->dents; - - dead_f->dents = fd->next; - - if (fd->ino) { - printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", - dead_f->inocache->ino, fd->name, fd->ino); - } else { - D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", - fd->name, dead_f->inocache->ino)); - } - jffs2_mark_node_obsolete(c, fd->raw); - jffs2_free_full_dirent(fd); - } - } - - dead_f->inocache->nlink--; - /* NB: Caller must set inode nlink if appropriate */ - up(&dead_f->sem); - } - - jffs2_complete_reservation(c); - - return 0; -} - - -int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen) -{ - struct jffs2_raw_dirent *rd; - struct jffs2_full_dirent *fd; - uint32_t alloclen, phys_ofs; - int ret; - - rd = jffs2_alloc_raw_dirent(); - if (!rd) - return -ENOMEM; - - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); - if (ret) { - jffs2_free_raw_dirent(rd); - return ret; - } - - down(&dir_f->sem); - - /* Build a deletion node */ - rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); - rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - - rd->pino = cpu_to_je32(dir_f->inocache->ino); - rd->version = cpu_to_je32(++dir_f->highest_version); - rd->ino = cpu_to_je32(ino); - rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - - rd->type = type; - - rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); - rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - - fd = jffs2_write_dirent(c, dir_f, rd, (const unsigned char *)name, namelen, phys_ofs, ALLOC_NORMAL); - - jffs2_free_raw_dirent(rd); - - if (IS_ERR(fd)) { - jffs2_complete_reservation(c); - up(&dir_f->sem); - return PTR_ERR(fd); - } - - /* File it. This will mark the old one obsolete. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); - - jffs2_complete_reservation(c); - up(&dir_f->sem); - - return 0; -} diff --git a/components/dfs/filesystems/uffs/AUTHORS b/components/dfs/filesystems/uffs/AUTHORS deleted file mode 100644 index adaedefb4f..0000000000 --- a/components/dfs/filesystems/uffs/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Ricky Zheng diff --git a/components/dfs/filesystems/uffs/CMakeLists.txt b/components/dfs/filesystems/uffs/CMakeLists.txt deleted file mode 100644 index cc36f060e1..0000000000 --- a/components/dfs/filesystems/uffs/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6 ) -PROJECT( uffs ) - -SET(CMAKE_CXX_FLAGS_VGL "-O0 -g") -SET(CMAKE_C_FLAGS_VGL "-O0 -g") - -SET(CMAKE_C_FLAGS_GCOV "-g -O0 -Wall -fprofile-arcs -ftest-coverage") -SET(CMAKE_CXX_FLAGS_GCOV "-g -O0 -Wall -fprofile-arcs -ftest-coverage") -SET(CMAKE_EXE_LINKER_FLAGS_GCOV "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -lgcov") - -IF (CMAKE_COMPILER_IS_GNUCC) -IF (APPLE) - SET(CMAKE_CXX_FLAGS "-fPIC -Wall -Werror -g -rdynamic") - SET(CMAKE_C_FLAGS "-fPIC -Wall -Werror -g -rdynamic") -ELSE () - SET(CMAKE_CXX_FLAGS "-fPIC -Wall -Werror -Wclobbered -Wempty-body -Wignored-qualifiers -Wmissing-parameter-type -Woverride-init -Wtype-limits -Wuninitialized -g -rdynamic") - SET(CMAKE_C_FLAGS "-fPIC -Wall -Werror -Wclobbered -Wempty-body -Wignored-qualifiers -Wmissing-parameter-type -Woverride-init -Wtype-limits -Wuninitialized -g -rdynamic") -ENDIF() -ENDIF() - -IF (UNIX) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNIX") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUNIX") -ENDIF() - -ADD_SUBDIRECTORY( src ) - diff --git a/components/dfs/filesystems/uffs/COPYING b/components/dfs/filesystems/uffs/COPYING deleted file mode 100644 index d511905c16..0000000000 --- a/components/dfs/filesystems/uffs/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/components/dfs/filesystems/uffs/Doxyfile b/components/dfs/filesystems/uffs/Doxyfile deleted file mode 100644 index f46a4c0af1..0000000000 --- a/components/dfs/filesystems/uffs/Doxyfile +++ /dev/null @@ -1,275 +0,0 @@ -# Doxyfile 1.4.1-KDevelop - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = uffs-doc -PROJECT_NUMBER = 0.1 -OUTPUT_DIRECTORY = doc/doxygen-doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = ./ -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -TAB_SIZE = 4 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = NO -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = YES -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = YES -CASE_SENSE_NAMES = NO -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = YES -SORT_BY_SCOPE_NAME = YES -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = YES -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = ./src -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.C \ - *.CC \ - *.C++ \ - *.II \ - *.I++ \ - *.H \ - *.HH \ - *.H++ \ - *.CS \ - *.PHP \ - *.PHP3 \ - *.M \ - *.MM \ - *.C \ - *.H \ - *.tlh \ - *.diff \ - *.patch \ - *.moc \ - *.xpm \ - *.dox -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -VERBATIM_HEADERS = YES -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = YES -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = uffs.tag -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = NO -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/components/dfs/filesystems/uffs/README b/components/dfs/filesystems/uffs/README deleted file mode 100644 index 0828cf134c..0000000000 --- a/components/dfs/filesystems/uffs/README +++ /dev/null @@ -1,275 +0,0 @@ -UFFS: Ultra-low-cost Flash File System - -Project: http://uffs.sf.net/ -Blog: http://all-about-uffs.blogspot.com/ -Q/A: http://groups.google.com/group/uffs/ - -Author: Ricky Zheng - -INTRODUCTION ------------- - -UFFS is a nand flash file system designed for embedded system. - -UFFS have some unique and advanced features: - * Low cost: e.g. it needs only 41K bytes RAM for 64MB NAND flash (page size 2048). - - * Fast booting: it reads only a few spares from each block, typically - mounting a fully filled file system (Gbits) within one second. - - * Superb Reliability: - - The file system is designed for the embedded system which may - frequently lost power/reset without care. - - Journal file system, the file system will automatically rollback - to the last state when lost power on the middle of flash programing. - - When 'write' return without error, the data is guarenteed been - saved on flash. - - * Fast file create/read/write/seek. - * Bad-block tolerant, ECC enable and good ware-leveling. - * There is no garbage collection needed for UFFS. - * Support multiple NAND flash class in one system. - * Support bare flash hardware, no operating system needed. - * Support static memory allocation (works without 'malloc'). - * Fully simulated on PC (Windows/Linux) platform. - -Disadvantage: - * space inefficency for small files: UFFS use at least one - 'block'(the minial erase unit for NAND flash, e.g. 16K ) for a file. - * maximum supported blocks: 2^16 = 65535 - -Memory consuming example: - For page size = 512: - [VARY]Tree nodes: 16 * total_blocks - [CONST]Page Bufs: MAX_CACHED_BUFFERS(10) * (40 + pageSize(512)) = 5.4K - [CONST]Block Info caches: (24 + 14 * pages_per_block (32)) * MAX_CACHED_BLOCK_INFO (10) = 4.6K - - Example 1: 128M bytes NAND, 8192 blocks, total memory cost: - (16 * 8192)128K + 5.4K + 4.6K = 138K bytes. - - Example 2: 32M Bytes NAND, 2048 blocks, total memory cost: - (16 * 2048)32K + 5.4K + 4.6K = 42K bytes. - - Example 3: 16M bytes NAND, 1024 blocks, total memory cost: - (16 * 1024)16K + 5.4K + 4.6K = 26K bytes. - - For page size = 2048: - [VARY]Tree nodes: 16 * total_blocks - [CONST]Page Bufs: MAX_CACHED_BUFFERS(10) * (40 + pageSize(2048)) = 20.4K - [CONST]Block Info caches: (24 + 14 * pages_per_block (32)) * MAX_CACHED_BLOCK_INFO (10) = 4.6K - - Example 1: 512M bytes NAND, 8192 blocks, total memory cost: - (16 * 8192)128K + 20.4K + 4.6K = 153K bytes. - - Example 2: 128M Bytes NAND, 2048 blocks, total memory cost: - (16 * 2048)32K + 20.4K + 4.6K = 57K bytes. - - Example 3: 64M bytes NAND, 1024 blocks, total memory cost: - (16 * 1024)16K + 20.4K + 4.6K = 41K bytes. - - -BUILD SIMULATOR REQUIREMENT ---------------------------- -From V1.2.0, build uffs simulator requires 'cmake'. -'cmake' can be downloaded from: http://www.cmake.org/ - -or, under Debian/Ubuntu: - sudo apt-get install cmake - -BUILD SIMULATOR ON LINUX ------------------------- -1) create a 'build' dir: - -mkdir -p ~/build/uffs - -2) create Makefiles and build: - cd ~/build/uffs - cmake - make - -5) run simulator (interactive mode): - src/utils/mkuffs - - -BUILD SIMULATOR ON WINDOWS --------------------------- - -1) create a 'build' dir along with uffs source dir, - d:\build\uffs - -2) Create VC project files: - cd build\uffs - cmake - -3) Open uffs.dsw (or uffs.sln for VC > 6 ), compile & run. - - -LATEST SOURCE CODE ------------------- -You can get the latest source code from git repository: - git clone git://uffs.git.sourceforge.net/gitroot/uffs/uffs - - -CURRENT STATUS --------------- -UFFS 0.1.x is a working version on PC simulator, also has been ported to -uBase embedded OS as a 'real world' product for thousands of copies, -it works fine so far. - -UFFS 0.2.0 implementes full directory. - -UFFS 1.0.0 is the first stable release at sf.net. - -UFFS 1.1.0: support NAND flash with large page size (up to 2K). - -UFFS 1.1.1: bug fixes. a tool for making uffs disk image. - -UFFS 1.1.2: bug fixes. add more Flash Class. change Licence from GNU GPLv2 to GNU LGPLv2 - -UFFS 1.2.0: - - eliminate 'current path' and relatives. Now you should use absolute path in all - uffs APIs. For dir, the fullname should end with '/'. - - allow using static memory allocation, 'malloc' is no longer needed. - - using cmake for building simulator. - - bug fixes & minor changes. - -UFFS 1.2.1: - - improve bad block management - - bug fixes - - change Licence to modified GNU GPLv2. - -UFFS 1.3.0: - - improved flash interface - - support hardware ECC - - support user defined spare layout (for customized NAND flash controller) - - support 4K page size - - no partial page program required, support MLC NAND flash - - reduced buffer flushes by grouping buffers - - structual improvments and bug fixes - -UFFS v1.3.1: - - Tidy up three memory allocators: static, native and system. - - Fix bugs in flash interface example. - - Fix memory allocation bugs when using static memory allocator. - - Add flash driver interface 'WriteFullPage()'. - - Fix compilation errors for BlackFin DSP compiler. - -UFFS v1.3.2: - - Add POSIX like file system APIs. - - Bug fixes. - -UFFS v1.3.3: - - Change Flash Interface, simplify interface. - - Improved bad block handling. - - Better support for MLC NAND flash. - - Added hardware ECC and RS-ECC controller emulator. - - Bug fixes. - -UFFS v1.3.4 - - New UO_NOECC option for skipping ECC (fast reading). - - POSIX compliance uffs_seek(). - - Improved unclean page detection (add new 'seal' byte in spare area). - - Optional page data CRC. - - Bug fixes. - - Other improvements. - -LICENCE -------- - From v1.2.1, UFFS is released under a modified GNU GPLv2. (the same as eCos Licence) - The full licence text can be found in the header of source files: - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. - - -TESTING UFFS WITH SQLITE3 REGRESSION TEST CASES ------------------------------------------------ -UFFS can be tested with sqlite3 regression test cases (on Linux). - -1) install tcl8.5-dev on host PC: - apt-get install tcl8.5 tcl8.5-dev - - # make sure your Linux is using tcl8.5 as the default tclsh: - sudo update-alternatives --config tclsh - (select "tclsh8.5" from the list.) - -2) build uffs: - mkdir -p ~/build/uffs - cd ~/build/uffs - cmake - -3) build sqlite3: - cd /src/test/sqlite3/sqlite-src-3070900 - ./configure # create some build support files - git checkout -f Makefile config.h # restore modified Makefile and config.h - make test # start build 'testfixture' program. - - # now you'll see something like: - Connect: Connection refused - Assert (uffs_ret == ret && ret == bak_ret) fail at /home/.../src/test/api_test/os_uffs.c:os_unlink:329: unlink("/home/.../src/test/sqlite3/sqlite-src-3070900/./test.db-journal"), unix return 0, uffs return -1, bak return -1 - make: *** [test] Error 1 - -4) run test cases: - Open two terminals. - on termional A: - cd ~/build/uffs - src/utils/mkuffs -t 1024 - - #on uffs simulator command line, enter: - format / - apisrv - - on terminal B: - cd /src/test/sqlite3/sqlite-src-3070900 - ./test-uffs.sh - - Note: if you want to run mkuffs on another PC, for example, a Windows PC, you need to specify the IP address in test-uffs.sh. - - The test will take 1~4 hours, depends on how fast your Linux box is. - - -ACKNOWLEDGMENT ---------------- -Special thanks for your contributions to: -(list in no particular order) - -* Chen Jun -* Michail -* Sjpu -* RobertGray -* Dongbo -* Cag -* Sergey -* Chris Conrad -* Vladimir -* Thien Pham -* Emmanuel Blot -* Michael -* Mick D -* Paul -* Rogerz - - diff --git a/components/dfs/filesystems/uffs/SConscript b/components/dfs/filesystems/uffs/SConscript deleted file mode 100644 index 53f7713fc2..0000000000 --- a/components/dfs/filesystems/uffs/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() - -src = Glob('*.c') - -uffs = Split(''' -src/uffs/uffs_badblock.c -src/uffs/uffs_blockinfo.c -src/uffs/uffs_buf.c -src/uffs/uffs_debug.c -src/uffs/uffs_device.c -src/uffs/uffs_ecc.c -src/uffs/uffs_crc.c -src/uffs/uffs_fd.c -src/uffs/uffs_find.c -src/uffs/uffs_flash.c -src/uffs/uffs_fs.c -src/uffs/uffs_init.c -src/uffs/uffs_mem.c -src/uffs/uffs_mtb.c -src/uffs/uffs_pool.c -src/uffs/uffs_public.c -src/uffs/uffs_tree.c -src/uffs/uffs_utils.c -src/uffs/uffs_version.c - -''') - -src = src + uffs - -CPPPATH = [cwd, cwd + '/src/inc'] - -group = DefineGroup('Filesystem', src , depend = ['RT_USING_DFS', 'RT_USING_DFS_UFFS'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/dfs/filesystems/uffs/TODO b/components/dfs/filesystems/uffs/TODO deleted file mode 100644 index bf6b4fb66a..0000000000 --- a/components/dfs/filesystems/uffs/TODO +++ /dev/null @@ -1,5 +0,0 @@ -TODO list for v1.3: - -* New API: int uffs_SkipObject(uffs_Object *obj, int size); -* Introduce buffer group -* Interface to Linux MTD diff --git a/components/dfs/filesystems/uffs/dfs_uffs.c b/components/dfs/filesystems/uffs/dfs_uffs.c deleted file mode 100644 index fb8caf9dd7..0000000000 --- a/components/dfs/filesystems/uffs/dfs_uffs.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-10-22 prife the first version - * 2012-03-28 prife use mtd device interface - * 2012-04-05 prife update uffs with official repo and use uffs_UnMount/Mount - * 2017-04-12 lizhen9880 fix the f_bsize and f_blocks issue in function dfs_uffs_statfs - */ - -#include - -#include -#include -#include - -#include "dfs_uffs.h" - -#include "uffs/uffs_fd.h" /* posix file api is here */ -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_mem.h" -#include "uffs/uffs_utils.h" - -/* - * RT-Thread DFS Interface for uffs - */ -#define UFFS_DEVICE_MAX 2 /* the max partions on a nand deivce*/ -#define UFFS_MOUNT_PATH_MAX 128 /* the mount point max length */ -#define FILE_PATH_MAX 256 /* the longest file path */ - -struct _nand_dev -{ - struct rt_mtd_nand_device *dev; - struct uffs_StorageAttrSt storage; - uffs_Device uffs_dev; - uffs_MountTable mount_table; - char mount_path[UFFS_MOUNT_PATH_MAX]; - void *data; /* when uffs use static buf, it will save ptr here */ -}; -/* make sure the following struct var had been initilased to 0! */ -static struct _nand_dev nand_part[UFFS_DEVICE_MAX] = {0}; - -static int uffs_result_to_dfs(int result) -{ - int status = -1; - - result = result < 0 ? -result : result; - switch (result) - { - case UENOERR:/** no error */ - break; - case UEACCES:/** Tried to open read-only file for writing, or files sharing mode - does not allow specified operations, or given path is directory */ - status = -EINVAL; - break;/* no suitable */ - case UEEXIST: /** _O_CREAT and _O_EXCL flags specified, but filename already exists */ - status = -EEXIST; - break; - case UEINVAL: /** Invalid oflag or pmode argument */ - status = -EINVAL; - break; - case UEMFILE: /** No more file handles available(too many open files) */ - status = -1; - break; - case UENOENT: /** file or path not found */ - status = -ENOENT; - break; - case UETIME: /** can't set file time */ - status = -1; - break; - case UEBADF: /** invalid file handle */ - status = -EBADF; - break; - case UENOMEM:/** no enough memory */ - status = -ENOSPC; - break; - case UEIOERR: /** I/O error from lower level flash operation */ - status = -EIO; - break; - case UENOTDIR: /** Not a directory */ - status = -ENOTDIR; - break; - case UEISDIR: /** Is a directory */ - status = -EISDIR; - break; - case UEUNKNOWN_ERR: - default: - status = -1; - break; /* unknown error! */ - } - - return status; -} - -static URET _device_init(uffs_Device *dev) -{ - dev->attr->_private = NULL; // hook nand_chip data structure to attr->_private - dev->ops = (struct uffs_FlashOpsSt *)&nand_ops; - - return U_SUCC; -} - -static URET _device_release(uffs_Device *dev) -{ - return U_SUCC; -} - -static int init_uffs_fs( - struct _nand_dev *nand_part) -{ - uffs_MountTable *mtb; - struct rt_mtd_nand_device *nand; - struct uffs_StorageAttrSt *flash_storage; - - mtb = &nand_part->mount_table; - nand = nand_part->dev; - flash_storage = &nand_part->storage; - - /* setup nand storage attributes */ - uffs_setup_storage(flash_storage, nand); - - /* register mount table */ - if (mtb->dev) - { - /* set memory allocator for uffs */ -#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0 - uffs_MemSetupSystemAllocator(&mtb->dev->mem); -#endif - /* setup device init/release entry */ - mtb->dev->Init = _device_init; - mtb->dev->Release = _device_release; - mtb->dev->attr = flash_storage; - - uffs_RegisterMountTable(mtb); - } - /* mount uffs partion on nand device */ - return uffs_Mount(nand_part->mount_path) == U_SUCC ? 0 : -1; -} - -static int dfs_uffs_mount( - struct dfs_filesystem *fs, - unsigned long rwflag, - const void *data) -{ - rt_base_t index; - uffs_MountTable *mount_part; - struct rt_mtd_nand_device *dev; - - RT_ASSERT(rt_strlen(fs->path) < (UFFS_MOUNT_PATH_MAX - 1)); - dev = RT_MTD_NAND_DEVICE(fs->dev_id); - - /*1. find a empty entry in partition table */ - for (index = 0; index < UFFS_DEVICE_MAX ; index ++) - { - if (nand_part[index].dev == RT_NULL) - break; - } - if (index == UFFS_DEVICE_MAX) - return -ENOENT; - - /*2. fill partition structure */ - nand_part[index].dev = dev; - - /* make a right mount path for uffs, end with '/' */ - rt_snprintf(nand_part[index].mount_path, UFFS_MOUNT_PATH_MAX, "%s/", fs->path); - if (nand_part[index].mount_path[1] == '/') - nand_part[index].mount_path[1] = 0; - - mount_part = &(nand_part[index].mount_table); - mount_part->mount = nand_part[index].mount_path; - mount_part->dev = &(nand_part[index].uffs_dev); - rt_memset(mount_part->dev, 0, sizeof(uffs_Device));//in order to make uffs happy. - mount_part->dev->_private = dev; /* save dev_id into uffs */ - mount_part->start_block = dev->block_start; - mount_part->end_block = dev->block_end; - /*3. mount uffs */ - if (init_uffs_fs(&nand_part[index]) < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - return 0; -} - -static int dfs_uffs_unmount(struct dfs_filesystem *fs) -{ - rt_base_t index; - int result; - - /* find the device index and then unmount it */ - for (index = 0; index < UFFS_DEVICE_MAX; index++) - { - if (nand_part[index].dev == RT_MTD_NAND_DEVICE(fs->dev_id)) - { - nand_part[index].dev = RT_NULL; - result = uffs_UnMount(nand_part[index].mount_path); - if (result != U_SUCC) - break; - - result = uffs_UnRegisterMountTable(& nand_part[index].mount_table); - return (result == U_SUCC) ? RT_EOK : -1; - } - } - return -ENOENT; -} - -static int dfs_uffs_mkfs(rt_device_t dev_id) -{ - rt_base_t index; - rt_uint32_t block; - struct rt_mtd_nand_device *mtd; - - /*1. find the device index */ - for (index = 0; index < UFFS_DEVICE_MAX; index++) - { - if (nand_part[index].dev == (struct rt_mtd_nand_device *)dev_id) - break; - } - - if (index == UFFS_DEVICE_MAX) - { - /* can't find device driver */ - return -ENOENT; - } - - /*2. then unmount the partition */ - uffs_UnMount(nand_part[index].mount_path); - mtd = nand_part[index].dev; - - /*3. erase all blocks on the partition */ - block = mtd->block_start; - for (; block <= mtd->block_end; block++) - { - rt_mtd_nand_erase_block(mtd, block); -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) - if (rt_mtd_nand_check_block(mtd, block) != RT_EOK) - { - rt_kprintf("found bad block %d\n", block); - rt_mtd_nand_mark_badblock(mtd, block); - } -#endif - } - - /*4. remount it */ - if (init_uffs_fs(&nand_part[index]) < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - return RT_EOK; -} - -static int dfs_uffs_statfs(struct dfs_filesystem *fs, - struct statfs *buf) -{ - rt_base_t index; - struct rt_mtd_nand_device *mtd = RT_MTD_NAND_DEVICE(fs->dev_id); - - RT_ASSERT(mtd != RT_NULL); - - /* find the device index */ - for (index = 0; index < UFFS_DEVICE_MAX; index++) - { - if (nand_part[index].dev == (void *)mtd) - break; - } - if (index == UFFS_DEVICE_MAX) - return -ENOENT; - - buf->f_bsize = mtd->page_size * mtd->pages_per_block; - buf->f_blocks = (mtd->block_end - mtd->block_start + 1); - buf->f_bfree = uffs_GetDeviceFree(&nand_part[index].uffs_dev) / buf->f_bsize ; - - return 0; -} - -static int dfs_uffs_open(struct dfs_fd *file) -{ - int fd; - int oflag, mode; - char *file_path; - - oflag = file->flags; - if (oflag & O_DIRECTORY) /* operations about dir */ - { - uffs_DIR *dir; - - if (oflag & O_CREAT) /* create a dir*/ - { - if (uffs_mkdir(file->path) < 0) - return uffs_result_to_dfs(uffs_get_error()); - } - /* open dir */ - file_path = rt_malloc(FILE_PATH_MAX); - if (file_path == RT_NULL) - return -ENOMEM; - - if (file->path[0] == '/' && !(file->path[1] == 0)) - rt_snprintf(file_path, FILE_PATH_MAX, "%s/", file->path); - else - { - file_path[0] = '/'; - file_path[1] = 0; - } - - dir = uffs_opendir(file_path); - - if (dir == RT_NULL) - { - rt_free(file_path); - return uffs_result_to_dfs(uffs_get_error()); - } - /* save this pointer,will used by dfs_uffs_getdents*/ - file->data = dir; - rt_free(file_path); - return RT_EOK; - } - /* regular file operations */ - /* int uffs_open(const char *name, int oflag, ...); what is this? - * uffs_open can open dir!! **/ - mode = 0; - if (oflag & O_RDONLY) mode |= UO_RDONLY; - if (oflag & O_WRONLY) mode |= UO_WRONLY; - if (oflag & O_RDWR) mode |= UO_RDWR; - /* Opens the file, if it is existing. If not, a new file is created. */ - if (oflag & O_CREAT) mode |= UO_CREATE; - /* Creates a new file. If the file is existing, it is truncated and overwritten. */ - if (oflag & O_TRUNC) mode |= UO_TRUNC; - /* Creates a new file. The function fails if the file is already existing. */ - if (oflag & O_EXCL) mode |= UO_EXCL; - - fd = uffs_open(file->path, mode); - if (fd < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - - /* save this pointer, it will be used when calling read(), write(), - * flush(), seek(), and will be free when calling close()*/ - - file->data = (void *)fd; - file->pos = uffs_seek(fd, 0, USEEK_CUR); - file->size = uffs_seek(fd, 0, USEEK_END); - uffs_seek(fd, file->pos, USEEK_SET); - - if (oflag & O_APPEND) - { - file->pos = uffs_seek(fd, 0, USEEK_END); - } - return 0; -} - -static int dfs_uffs_close(struct dfs_fd *file) -{ - int oflag; - int fd; - - oflag = file->flags; - if (oflag & O_DIRECTORY) - { - /* operations about dir */ - if (uffs_closedir((uffs_DIR *)(file->data)) < 0) - return uffs_result_to_dfs(uffs_get_error()); - - return 0; - } - /* regular file operations */ - fd = (int)(file->data); - - if (uffs_close(fd) == 0) - return 0; - - return uffs_result_to_dfs(uffs_get_error()); -} - -static int dfs_uffs_ioctl(struct dfs_fd *file, int cmd, void *args) -{ - return -ENOSYS; -} - -static int dfs_uffs_read(struct dfs_fd *file, void *buf, size_t len) -{ - int fd; - int char_read; - - fd = (int)(file->data); - char_read = uffs_read(fd, buf, len); - if (char_read < 0) - return uffs_result_to_dfs(uffs_get_error()); - - /* update position */ - file->pos = uffs_seek(fd, 0, USEEK_CUR); - return char_read; -} - -static int dfs_uffs_write(struct dfs_fd *file, - const void *buf, - size_t len) -{ - int fd; - int char_write; - - fd = (int)(file->data); - - char_write = uffs_write(fd, buf, len); - if (char_write < 0) - return uffs_result_to_dfs(uffs_get_error()); - - /* update position */ - file->pos = uffs_seek(fd, 0, USEEK_CUR); - return char_write; -} - -static int dfs_uffs_flush(struct dfs_fd *file) -{ - int fd; - int result; - - fd = (int)(file->data); - - result = uffs_flush(fd); - if (result < 0) - return uffs_result_to_dfs(uffs_get_error()); - return 0; -} - -int uffs_seekdir(uffs_DIR *dir, long offset) -{ - int i = 0; - - while (i < offset) - { - if (uffs_readdir(dir) == RT_NULL) - return -1; - i++; - } - return 0; -} - - -static int dfs_uffs_seek(struct dfs_fd *file, - rt_off_t offset) -{ - int result; - - /* set offset as current offset */ - if (file->type == FT_DIRECTORY) - { - uffs_rewinddir((uffs_DIR *)(file->data)); - result = uffs_seekdir((uffs_DIR *)(file->data), offset / sizeof(struct dirent)); - if (result >= 0) - { - file->pos = offset; - return offset; - } - } - else if (file->type == FT_REGULAR) - { - result = uffs_seek((int)(file->data), offset, USEEK_SET); - if (result >= 0) - return offset; - } - - return uffs_result_to_dfs(uffs_get_error()); -} - -/* return the size of struct dirent*/ -static int dfs_uffs_getdents( - struct dfs_fd *file, - struct dirent *dirp, - uint32_t count) -{ - rt_uint32_t index; - char *file_path; - struct dirent *d; - uffs_DIR *dir; - struct uffs_dirent *uffs_d; - - dir = (uffs_DIR *)(file->data); - RT_ASSERT(dir != RT_NULL); - - /* round count, count is always 1 */ - count = (count / sizeof(struct dirent)) * sizeof(struct dirent); - if (count == 0) return -EINVAL; - - /* allocate file name */ - file_path = rt_malloc(FILE_PATH_MAX); - if (file_path == RT_NULL) - return -ENOMEM; - - index = 0; - /* usually, the while loop should only be looped only once! */ - while (1) - { - struct uffs_stat s; - - d = dirp + index; - - uffs_d = uffs_readdir(dir); - if (uffs_d == RT_NULL) - { - rt_free(file_path); - return (uffs_result_to_dfs(uffs_get_error())); - } - - if (file->path[0] == '/' && !(file->path[1] == 0)) - rt_snprintf(file_path, FILE_PATH_MAX, "%s/%s", file->path, uffs_d->d_name); - else - rt_strncpy(file_path, uffs_d->d_name, FILE_PATH_MAX); - - uffs_stat(file_path, &s); - switch (s.st_mode & US_IFMT) /* file type mark */ - { - case US_IFREG: /* directory */ - d->d_type = DT_REG; - break; - case US_IFDIR: /* regular file */ - d->d_type = DT_DIR; - break; - case US_IFLNK: /* symbolic link */ - case US_IREAD: /* read permission */ - case US_IWRITE:/* write permission */ - default: - d->d_type = DT_UNKNOWN; - break; - } - - /* write the rest args of struct dirent* dirp */ - d->d_namlen = rt_strlen(uffs_d->d_name); - d->d_reclen = (rt_uint16_t)sizeof(struct dirent); - rt_strncpy(d->d_name, uffs_d->d_name, rt_strlen(uffs_d->d_name) + 1); - - index ++; - if (index * sizeof(struct dirent) >= count) - break; - } - - /* free file name buf */ - rt_free(file_path); - - if (index == 0) - return uffs_result_to_dfs(uffs_get_error()); - - file->pos += index * sizeof(struct dirent); - - return index * sizeof(struct dirent); -} - -static int dfs_uffs_unlink(struct dfs_filesystem *fs, const char *path) -{ - int result; - struct uffs_stat s; - - /* judge file type, dir is to be delete by uffs_rmdir, others by uffs_remove */ - if (uffs_lstat(path, &s) < 0) - { - return uffs_result_to_dfs(uffs_get_error()); - } - - switch (s.st_mode & US_IFMT) - { - case US_IFREG: - result = uffs_remove(path); - break; - case US_IFDIR: - result = uffs_rmdir(path); - break; - default: - /* unknown file type */ - return -1; - } - if (result < 0) - return uffs_result_to_dfs(uffs_get_error()); - - return 0; -} - -static int dfs_uffs_rename( - struct dfs_filesystem *fs, - const char *oldpath, - const char *newpath) -{ - int result; - - result = uffs_rename(oldpath, newpath); - if (result < 0) - return uffs_result_to_dfs(uffs_get_error()); - - return 0; -} - -static int dfs_uffs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st) -{ - int result; - struct uffs_stat s; - - result = uffs_stat(path, &s); - if (result < 0) - return uffs_result_to_dfs(uffs_get_error()); - - /* convert uffs stat to dfs stat structure */ - /* FIXME, these field may not be the same */ - st->st_dev = 0; - st->st_mode = s.st_mode; - st->st_size = s.st_size; - st->st_mtime = s.st_mtime; - - return 0; -} - -static const struct dfs_file_ops dfs_uffs_fops = -{ - dfs_uffs_open, - dfs_uffs_close, - dfs_uffs_ioctl, - dfs_uffs_read, - dfs_uffs_write, - dfs_uffs_flush, - dfs_uffs_seek, - dfs_uffs_getdents, -}; - -static const struct dfs_filesystem_ops dfs_uffs_ops = -{ - "uffs", /* file system type: uffs */ -#if RTTHREAD_VERSION >= 10100 - DFS_FS_FLAG_FULLPATH, -#else -#error "uffs can only work with rtthread whose version should >= 1.01\n" -#endif - &dfs_uffs_fops, - - dfs_uffs_mount, - dfs_uffs_unmount, - dfs_uffs_mkfs, - dfs_uffs_statfs, - - dfs_uffs_unlink, - dfs_uffs_stat, - dfs_uffs_rename, -}; - -int dfs_uffs_init(void) -{ - /* register uffs file system */ - dfs_register(&dfs_uffs_ops); - - if (uffs_InitObjectBuf() == U_SUCC) - { - if (uffs_DirEntryBufInit() == U_SUCC) - { - uffs_InitGlobalFsLock(); - return RT_EOK; - } - } - return -RT_ERROR; -} -INIT_COMPONENT_EXPORT(dfs_uffs_init); - diff --git a/components/dfs/filesystems/uffs/dfs_uffs.h b/components/dfs/filesystems/uffs/dfs_uffs.h deleted file mode 100644 index 72f0ee9240..0000000000 --- a/components/dfs/filesystems/uffs/dfs_uffs.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2012-03-30 prife the first version - */ - -#ifndef DFS_UFFS_H_ -#define DFS_UFFS_H_ - -#include "uffs_config.h" -#include "uffs/uffs_public.h" - -/* the UFFS ECC mode opitons */ -#ifndef RT_UFFS_ECC_MODE -#define RT_UFFS_ECC_MODE 1 -#endif - -/* - * RT_UFFS_ECC_MODE: - * 0, Do not use ECC - * 1, UFFS calculate the ECC - * 2, Flash driver(or by hardware) calculate the ECC - * 3, Hardware calculate the ECC and automatically write to spare. - */ -#if RT_UFFS_ECC_MODE == 0 -#define RT_CONFIG_UFFS_ECC_MODE UFFS_ECC_NONE -#elif RT_UFFS_ECC_MODE == 1 -#define RT_CONFIG_UFFS_ECC_MODE UFFS_ECC_SOFT -#elif RT_UFFS_ECC_MODE == 2 -#define RT_CONFIG_UFFS_ECC_MODE UFFS_ECC_HW -#elif RT_UFFS_ECC_MODE == 3 -#define RT_CONFIG_UFFS_ECC_MODE UFFS_ECC_HW_AUTO -#endif - -/* #define RT_CONFIG_UFFS_ECC_MODE UFFS_ECC_HW_AUTO */ -/* #define RT_CONFIG_UFFS_ECC_MODE UFFS_ECC_SOFT */ -/* #define RT_CONFIG_UFFS_ECC_MODE UFFS_ECC_NONE */ - -/* enable this ,you need provide a mark_badblock/check_block funciton */ -/* #define RT_UFFS_USE_CHECK_MARK_FUNCITON */ - -#if RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_SOFT /* let uffs do soft ecc */ -#define RT_CONFIG_UFFS_LAYOUT UFFS_LAYOUT_UFFS /* UFFS_LAYOUT_FLASH */ - -#elif RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_HW_AUTO /* nand driver make ecc and do ecc correct */ -#define RT_CONFIG_UFFS_LAYOUT UFFS_LAYOUT_FLASH - -#elif RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_NONE -#define RT_CONFIG_UFFS_LAYOUT UFFS_LAYOUT_UFFS /* UFFS_LAYOUT_FLASH */ - -#else -#error "uffs under rt-thread do not support this ECC mode" -#endif /* RT_CONFIG_UFFS_ECC_MODE */ - -#if (!CONFIG_USE_STATIC_MEMORY_ALLOCATOR) && (CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR) -#define RT_UFFS_MEMORY_ALLOCATOR 1 /* use system memory allocator */ -#elif (CONFIG_USE_STATIC_MEMORY_ALLOCATOR) && (!CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR) -#define RT_UFFS_MEMORY_ALLOCATOR 0 /* use static memory allocator */ -#else -#error "UFFS: CONFIG_USE_STATIC_MEMORY_ALLOCATOR ,CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR are invalid!" -#endif - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR > 0 -#error "dfs_uffs only support CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR" -#endif - -#if defined(CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME) -#error "dfs_uffs not support CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME" -#endif - -#if (RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_HW_AUTO) && (RT_CONFIG_UFFS_LAYOUT != UFFS_LAYOUT_FLASH) -#error "when use UFFS_ECC_HW_AUTO, you must use UFFS_LAYOUT_FLASH" - -#elif (RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_SOFT) && (RT_CONFIG_UFFS_LAYOUT != UFFS_LAYOUT_UFFS) -#warning "when use UFFS_ECC_SOFT, it is recommended to use UFFS_LAYOUT_UFFS" -#endif - -extern const uffs_FlashOps nand_ops; - -extern void uffs_setup_storage( - struct uffs_StorageAttrSt *attr, - struct rt_mtd_nand_device *nand); - -extern int dfs_uffs_init(void); -#endif /* DFS_UFFS_H_ */ diff --git a/components/dfs/filesystems/uffs/doc/Understanding-UFFS.odp b/components/dfs/filesystems/uffs/doc/Understanding-UFFS.odp deleted file mode 100644 index b39f4d0f320d781dc1ef2e793491150701f9a814..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 369408 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�wU^Sy8W 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%0Ds4oG8bEWjhsSJ;^O2u?S6L5?{7a?j*Lp^e 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 z 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 kY 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�I%?^ZH1v$V@Wl`>=SnZK^fbE9^+#9K6*$)p` z{4-!q$X4gPp-wVR%P7@T4ZDhKE?KxJkwm=pg%lya>(8lBIm4pisuR4^#p{qz^BQBQ zLCmh{=vt#Rf~KHx_FO(3yWKzj9I^XlLG;|&n{_T~$v{Nzi6b-J)p@l*kepf}vus_|sSZcN zRx*B9N~Xp?%zKt{sZ=^Od5xt2tfVqMl)1T7YMq;u+$X$gx1v2zQ3se{e;^zhucFK_ zb9P;pV7fUFbx?ll3hERag)P$!P`--j!PQRdi&c4Cs&xsuU1Q8OU;HTtGfE|#rDznt zMU|_|`9;d}Hdk3&dW%#^D}m*z?=JUH;UNh*Y`+g!=5NYTi>owB;Lz;%R8?3VIGh{(GDo8Ho?rM1+{X>+gj+ex_7b|PBH0|%+(&K zQgm6iI0POw7<(cV9h8Lye-fuqpsv_lLF%=?Ree;=mCcpZixms90FSDWVPq%R;Pw$L za`Pw>J(fz}d*20Npr$)H@>M zsYLa{5x^BHaeigks8Wl49kA-Hglve}N`tEY4)kSq7rq=qLXcF2{>nWwhkP1obE1xXNdqG z+_{+X*rUO9m6oItrL$IEm@wc9f}ih(Mdwu)IxMF}N~gF}twh#Mx?v~`GT|5;Mjfz~ zWqn2vRAHF~3oaee5{rIQjmnUt=EJeay4DT>!wkV?K8(~~61dK0X)2XgI8@)}&FPV%_QE|K{W6D4BWEnpgp47| zLY0*2py4Ve>PiG?R46#k45-_+;!~PJsYUt)FMAVRLAM4I>g9qIp@blD%oFM2XpMSA1Y7zzi*+#&M1Dj0O@pny#}qY$Iey#tQ9(i#yU!L{gf4j@8hPx_6s!fkdh=4uE$ zVbG~jva*E-P^aZPDcJ%LK?0#UyA|w)En|je^-=!-Lbv*@L2A!T!_Lb-;Z}aYz*2{F zWfT!aDBLJJE0vfyha)7Eah{2l8k&Pb{?TQdsvXm?pG2Y6Mu;84f`}>2+hqt92Oi2k zQoo5%vXv;bqS#R7Aw&M?*=5;5QG^r&#~}ZV=1NEL2^}vz^mK_w^{I z_E4$!7)tIim73wJh{}~tf;4lXc;R00S*`a0XgPNg64IL3q zM8?Rc1TYDyr9r|K(CV7xO1_Fhx;Xb3N;J;uJr>zY^E#x*+L1fRzY?_xMk>zcM0uNvg}p)lpvqi3RMQ7H0ob^VL7Ya0l0;JVUCzKH?I;wu?H({y_S)oA?S4BH0$2V2o5L1Gl zrAFw2h5&U!bSuOb=+d)=m~X27Cm2D{gLf*cPwriuntoE6VFS1*cSLNXs$+X2g(vMd zRH?A)GZYEaRUa!;LIDp+W3@$yJS(W^qjb}{E%}Pg)n@sVT^1^fQxQ^tO$wh?RG@;= z<##I~z@UoC>;s02F3JYVZ~&&lF`x^?Ps~%JRQhhwLd=4PAT=FPBxs!7GhH=@P*gin zx(zxf4ymOQq^e|K1{9cGCJ_zhD3hy`x(`&M?u#<^Q7BXcu}vsdK{2VU35{Rl2e6=_ zeHN+dq^5)=0kBe|00;uk#GFIb}SqPj_@45fc)R?h2(dfeEMRjA03>!Ac5OhGTA8$tpXk=!?3h4yn%AD8MTs z-igiL6e>>WQT}38H*8AEKXfX!2kKIGR|IK3a{E#s&_HuGQ>8@FV zpio5?8+rjmCqj~;eG^C57d$33X{kWYr2#fho*cqS!J}P&tSfQxHz7s67yQ z-$hJ3akeOa#X`o)r3*n+F8R)F2TFy^4AW zs(s3Dx}-(`uMf0YHNjOM#W@;!5>zq4${(_BcZRhwg1cRq-96e(vQ0#|?HjS(#nO z`|h&%rUu`gnthcw({OWKEJgYC$D?6x&0=Lx5Sc% zpGWAfN7;F{&((05Rzb$gD|FnbPjZErXr}|zpo($mi&cSpjk1l@x~TT(rLqrMMsk6< zH&G4^KQ`<23G7oG+c;i&tgdhP{{Sinz0{3{V4`z3Sx)ek4+FV9(-1=jx4hwz+7wH5 zR~T6sSt?$f>aDu=P=db5zhu=5vU;-43=o6nTso&vc9NZ!lA_TJ+A1!X5}e&_Ar=)# ze6WT&G|Y>sygYPF&31yO0_9((6o!VPB@o;*qSQhyP^AR%)m84i#ODH9PPuHSFW0J& zP3(hdwogcvmZNgI+}#sJtRtt@HN1mCpJClou6G_~wi*v*6(oEz<8IQM6Cs4?nshO8 znny5)CJ1#u?q3e0U+hqgP@AmIU63GO4u=wo$m@leA`@J_$|YveIIP~P@{ zi=EC+C1ol>Ug}T*H`@weZ*~5N_gM~uL?d;ht*w(oz8x0bsH&cWa3POh_GHt3I&`v-EQ7RpF6nv9&vhr&WWMJ6(9pLJ_;nmaK8fE!> z!Tu3Z=*>;pJ+w#7t55F>inBtWGmEoIj|k5)q4}L)7HYLz@2bl865fQVX;vyVUTzZU zg#iQyL4f-r;-WOVvOLD$D`g-3iL~kGgRudjIk}p0*~A%HZ=@2@nA@P)XdD}$2)LQQ z5kLLWXSk^xIet*H0hl(!u4LA9)zPV4kY-qpiU8Uq2$Tq@CU(^dH36?rzcTY^x_XVq zF#3%IcSd|eeS$fBL_1>z0r;AEySYn9Ej=(fup?r!e9bAo*gxL~j54D3-j?Ap&D3Af zs%=J-nWk)m>Yi4>3L$X9wP^Y;`Ir3^yTnzW?oetxj+wBHmbhz;@N*tQokD}6C93$h z*$Y^Iq6TfU)7=2bnc3hKmLHmLnxNGed9+$BXBq06!X8=sTVXM(rrLZDE)e!}1KBib z1C(FxxU$1}TQHt^MBU`y>D4z-enw~!Etv0yU~a#bvVqDUzy3m!N&f&<=23ZT!p%^8 zQLx=`yCY9Usk-7ANYQ*cuW9U175LlLO*hYM2~Dp$;(hRrsD$TsRoMMjLVg>xR{omK zDjX$i9_nIGP_sJHr7)o`)0JMxyE8+g*@Vjf0HuELo0^A*CZMy;Lv2T1tBv_v)|+M* z6Q5KKGn)iM18xYgPkmQ$eaR^4uA0gXsBbdHX0ubA=S-bW>6RQn<$I@-sD(NV=tQ0* zJ>g!&>=d0bg(H`uFg}VxEpiT|>-J6aEbghr7P#nazKO*W6I`0%s7GnKjY@OlRecsm zpJKKCqRRJNd?93K6?u@ZWl+#{4Hs6VW&xV6LAl&y zPFA+b;$S~t{_ecbFbQzrXxD%K{{W(V7fC;+Z}lZhOq*t%PyYZ2nEwD}1vYFolrsYj z;y&q@nBpjGnY?h}c8-=0QV@K3oF3(S8VrM1*kvLYb9#FLW5?I9h!-2o`1ALbx0K3 z)}#9_XFQ#v0)kxDMe?>&pZa1n*ZiUsUV5SgANEk7eS55?%?4m@Q|If4MPx3u3%sWi zh8>iq-A`RneLWB#L`TR|hQ$o#2;FC6k#|w18TMJ;XZWjA$xR8Vbs_S&N%}0MfcGNm z?zc=ey5w3uu_dT+$T5wn~-+O=ZG$g%c=A#%25$2NX$`-dts*r}=?>PndoogrS^=2k- zivT?X9?PoHXaQTO(OOmT1a1+L3Puryg3)D*lCu~C-5xNne|3HmxJ-qnQn;Eb1^Z7z zvq@V2W$5rM(3jLk-)Ms{vD3xvyX5~D>8Bi(WX-8gc`MGkq%(QS^ajAm9aSMF9Mb}QmG zJB7mKpev%f(O*?NuDInwF1JvoGc6Rw)zyqGRpn|`uB>5LPqMiDsbk1oVttm)2ti$y z)>4R4!y$1~GK-jf)0^`9qcTrr#iG(m427Mum3geTZeiaUY|6ab2GosE%wco4?!W)U z04ERu00II60s{a70|5a60000101+WEK~Z6G5P^}Q!LiZs;qf5<+5iXv0RRC%A*<9R z#fm-60bI`Fv<78-ec7Cm_#j%tmk^Js%>=`|sEYm?%>Mv5QNj?ICC$sH;{FJPF*(17 ze>d}|A0$0xAEACXQ_^kX@{8Xsh z;;Z7NN}Nt&pgj%(5&_3g}GdV{zP^na4KrVLDaM`Y4ti`<^?+7 zLGQ%w2f@)DsH+a%2(Rdg+es1UN!(N;S+ElnXoA>ZSAHNsyVlBf{P(GlRNf6C!zrNw%Ph?0UJrvm9L)C&Hx33;!XfmpxD>0?J)#4xp_5rQZS+KQi}R`IdNV)aU8bF8+x3Bia3xpXH5G*<8TPzcHDC z@yEbhh`{p)rTDsK=l=l3ejGuv#c1LPnQuoD<;FJ-VGT{7+H&<3SSK;xaZ7|)K}(Ah znOL}WE{TXA0Y(JQ;VM~XlRiFXqcLR2j+X;3(jH(E$V-oHEH&~m7)>=USHS9NFFz7W zGtpxS;2^|sixTQAVQMmJ2~C{ohs;f^xp0Fl5vFBpGdf!8R$&=-u` zl{M}s#(^5|b0P{_5QK3yCXvemYG1(CIHW~G%5xUn%Z(3(VwqHNZ5=}ighS-0{5bdw zM_PdcEOqb~bIRiK?u@=)ag=&~YF;6a5yQAkuXd=-u?VfU^*^Y55LcS!8(mMjKs6Z# z64^{vM6E}Kg5QaZ#sWahp<$>O7RZ?ToIVM}xXS~~@iOHai;DrZ_-xB0#bCrSEsCa5 zRx<=4M&K4IXDye9?11^;e;Ghjh1$z`hsGs3MA-aKGYI5o+@P;t!SRZgE{KluhC_8M zyrmwvHHIR-E7mZ@7!LHtprtUR+(B1Ut(emeB_A`GlZZ;)T=F!;gs8_+VD{)n2+t94 zUk6fwAb8)ttoAm~FAYewUmsB3n4 zohcYg5gN<@ox$+oUcZ}x=kY;{0|aJn1Yc1`*d#@PhY6KJUfYsX6BjZ@Fm5*?SS~Ih z3q$_^_#V>5rI0l^hfJ%3A0>;4;ejJ>8SpW{OSOWtBLbuwOM z*k$S?Qss(c7$DHGQ7vAgkIYnD6ca478mOhzjbPHKhf)?&AYkDzO@0bEnhdZ+ty~>^ zY8hta^Fu5fnq13U|V^G~3 zco3&e!R2%4?JRdOaXC@W;CPzAt;exS^DcIX{Brq)uXr$}gd^C2{u3go<$8u2cQMZr zf(-@AvNaviXcVIE67)h@l+C7Lz`;pR*p3ORe`d7)&Hn)AmG?g2!lEMS`yFbjK-S=3 zqjFZqQ@Dx`p@3we)bby&?~CpLAohu~`o-ZNx#H}wI1u0v0+RYlEm$z&@XQcI6dy_c z2$%-N>3}(0RFQ~9G(AgEZxt&Re8Dg)oEZ;G+*@&JzO;J@g{Y&{KW;P%)#jP>K_YM4tsoVDgjz zw1`Ji%5ehfm8i(6?iE{>V`9sTm!O{IN3ocY+*-SYdL&&n&bTVKxnD zVQREIEU{1C8JVU2;IxN}fr-FPewx z2oeIlOyjN)FJ!f7U6O^Fjj%I~3JKIwR)7jPN{ir^qll@GPg3bxfNs<@iDL3j2gFzk z%dyh#2##V>#uQS^p~ON0(h2q6 zcqV2}kO&Hb3}=EziYdF8J%JgwwNdc^A_anq#|k@y7}w7UEet}D!OA#jV-{R-g_qls zJxk6ELlrq|oRm?*;LXJ}Ov1M=3oZ)GtxN8M0&}5OQV+?mGS>d3Jx8ISh$uuFqSfC5QoKjVvxV^)j)Gr{@`iaP;2z=H z!_3AW2H6Ot($XOiuX7OSFm76a?G_I;8CP=7B*CLn;q%L>cJ>mmL+(A5B_|$YPFPCw92})wAw4zR zqp6%RW?dHnsU4v8kntQSx2hYGW@Yw#tL)J9zL}m4NgOyVg1Yz+ss{YS>I&e^rgS@s zG-FbU)T%kNgfq`GSn5ylSYqk!Cr^jMl zsWcnzSlg^;9-~-JR_AT3uzlt@rlWO_G4i5OmKEj_0-Zr+RE)ys0l!cd>Ik_hvye4H z0jwIh!2^nzD%hwexq{sgXgH500$`(DL;g(4o;Nh^SeFNud5cN_o(nEDa=rv{<4X}D zolT-UOC`<~)U$2eV!gp= zp?HMHJw!{{Qm)8{w2h+^RWRlopZY+7y|*1iEpB5)sBIPK4WY6cLf3&5g`}}l z1&gA4xq?B=#G@O9B~!!;@N>JwvsP9Op<|fyizVeo;E9(P2&T?hO7PTjZqJYH*0Bf| z3TT2D&Y&Tn{hNwPJ_xlH$BbxH8-gkw3WfY?CBph(78dAY3WpuQnFj_VcDqy~%(~t6 z<_KG8WbsZ{a+yOTE>iswrIcjPAjGRAbXbP~TimI7#3DHp5A_7taZ%A=K)Q3gf%UEU zl)zYEEi^{4yk^6V%1MC>B)K-anG8a5kM|}q zbqeD=%Yje}mSR$vOpjwcpol`-?ge;H)UPU<%*4VECKL|h#8?xEkMl8Y$cr+}cFP_k za)NJeB^t4LE~*!p>Z#olwsytHCn37H2C+QGn-4jdSl%CjkeO3$f?3Y=?4-Ji;-hNt ztafwRaQwR;9Kj*nwVb7F9SeiUra%M4Awdq!W*V@J7ZQe0L2k1k4w5mAQ-&a0>gD$W zyNo{L;nTZ#82{##LO0$||$R`9i89`1 zY!6IEVtJ2it{9Cmq!LrGJ0ih0#B5$Dcf3OhRn)DVwqdhzZdO@0EE^oMpl3{?5z^eG zR{+d*qYKP(2s)RvWO zCx;P&BP!uX)U-iXa~Kv_;yfW=n5I^_1YoI1mlTBE0dMw8Y68yW%raIE9Qq5yyfcHiFWHMAk7X zYG>R8CAP*!4;guT1A;YRXdtWF0$QqJtAq=F54pR@gC08?CqYG+I6=a5mj@=D5Xyt9 zis*6s7QoIdO-Guthv`rEM_$y|^$vvQF^^}R5dPP_5Q*3@_Dq1UCCo~9C12V|7hyvB zg|qU+qdKJ6U}b$9FRlTKd*cdmA9q|w-2NE%^X5>v@Q;egF1kUz$qL4VTBZbW6hX4b z12VS{h7{KBAoJ8>XWu1|G#vPq{74QQOBt;R=*wyzQ5sK%HkL0k$EQ;4{gI^egvTdR z&GR|1;x^3jh%#`oE5!A3!1D>I78n}+N?=?~%t0YxY`#GYbhSA3{7u0n7z!h?Q_Nmg2I*9LReSe}j$RFxlw=T-Pkx{9dig;yZb5 zd3ovrHM*99l|hFj&a=Fdk^_`EW)J7&j?{5cX7Gu=V6*Zo7P^M3m5GG52x(GT`X-*t z$3W^=EIGb?5xhvlP`8ydW0g#{$-HT)E(Il{zQ@%mUlP<=1#cqFMV1Z9=yy^mCj7R1v_;mL@PWBw?Z>#sJlbmS-_VZ=HA`Qu~w?mv;I`VB}5| ze*Me(M;GKwN>jgjXXGb|UB^m3=ZmE?0p&y4T5h7dW1vi>*^f|%L^GFR3U2ONj-5+_ z4u#4m+6uRAqY4s?ROg7WLWr)^^YvU5YZ)Y6E(-a@uwe}|n+A_ga zg@UL{M8~;Mk=_A}nF*cAKtZb36>J3bhNRR{>i+-;_OV8#qAp&hW%lohb#YQ2=SFHG ztW2}9*v$f^bTPT(KT~EHM5Ykr5#+_x4B&&zz(%FF$s8!8%)I9@}T`FtJV&0seigFaRcL=B0XMC~4|Z7A;7>Nlsiq@?Q*~P?&<_ zT02mWhqht)sz110d;@Ls2vDFVpA6^(^H5E{7bs8z+%|=>QPZ25hLnH8hz01Ug%GkZ zHSj`TbP%Z7#lY=#%&@8(fl4PQaC$6UC4KQ1iEv<87B&TR#8@7aKkO_bT@&(Bgc@AO z`6KG1WO;ZZrlYbntZq=T`xvy}iFjIbF0(~_LoD8nvVpW};T-JZ3TRj`+?Z%H0Epee z8466ZBJ!dEYO>HxtCC_3A*NCcUa3$;aumyK(=%l|MU|FV3wo5Tx|d9s;hBBe)E^+% zd6qz}fATU*XwWg7%)&Yzh&GQFUm{&pD067@04*u@gqD2)--v9r+YY8R~I(<4^^s8;+DQ7>6D;1^)m^Rk?F6!c%We68FqICmA9TwUu$|krNAu${fqE44Hoq zsg=1b4iWbD>H%DHnakk0+$CF47Z7GG)qV*5iwJO!aI=5Q5{)iC2xC`p&+0+eV{61! zk?`T(In;$#0m0ZfXJkyhvO7^#+!CyDqm}pt4$-11so&gWuN*|UY`GWI+leq^c{MN? zY)Zo@5Ye{COaSFhn3Yg$8=@8ODlxaz!qepmwJ>IeEb^DO0;>I`KO2Q%!4?FHRkk^Z z8jA<~Dmb2Tf)>8wmPQ=NfPB^acX7c5W0;keu7=|1Sf@xUat#?EhJ;u(MUx;)QeYY? zGX~;1>f^4C;smp(^;(CF4g?YqQh?o9AcXT22zkv3)j5)V1yw`|8Pv#A9<(MG)UFBvg zxmLTDy$QHZ#G6J~@)d8wD%EQ_el8Z;_?F{%>?SeLu#^I)%y*K^Wn-7pY%y zM-r~Pwp4C?3jY9^TJKWAB$Tm9R_M%|ZV^gm^j2gu3j0H;Qxs!hS=`8gw1OiM?l$i^ zm_u>}To4J|SSN>!e8rYKZg#}5HooAvDT?hb0i6P3 z+2s{ZCi3N}NG=W_uZtALmv&%4=z5Ua7iWvAiIm;;fXrI4CPJHPpeQg<4BTos(;5%D zx|NJtz9aMCI3lGjgQ#>Mpol_U%5KjvZdhzT znrSKZ2mP=dDbx@hz3k7M!Xzd2DEn^(i62d_R;{pOP zqBm{rT)}fSxnTs_ARI)weZXb|gSe@-Zlgs^nxFECXr@}s8u)?~)+@GlvsL1LG0q(} z3lWM(i8MIV;>Qxl)vB4DmVj3a`;})x+QXBjKlYhos+HeBb#R($pmk zHA-(Q?pu8zTF<$84PNeB8uSRUsCyQr6?3h`VGo%osho%7id+!p_?Zyu;k}w#qntru zz?7$^P*yJ-JfR&4mVnj>>=y>&pt>c^mm!7SnrR-bEnUXO?uKJbIgOU5?Hsl<2^5lm z5!j?TxGYa3f_61uz~H${9$*g3E2aa?wS5LwaH3G1@+oh?dr?$v^V7Gz5}n0uiy-IB z2#cfqgsbEWf|A-VWqzDQ3;eYPqcfA0equ{Q+;JUA+^H#WSXZD98}X@-H(B96@&%9o z06}70FOfZHQWxbwnGA6tjrd}wz0KheshZ_mF=)p%%-MA)F(@Pmm+XVpv(ubP;vYq2 z4w7tp%mbQ8<%F=qV3eu2F5$9WD^R^*fS5m^IGuRKAAV#^psVu=jm)|Y`IK^0YOQxO zD9OotuMw$B>tg4-b z&80_J*q-7+&6ZgOt@@>NNF4_1FaTR_>Jm5$BZ4-pn1xZet`88_rQnq-hiYcx5uH}9wRV57YQwuG|C{{d>mqyrXs{CfTj%0?BOlm zCFD+b7mdU8OtSG1)@5ybfh#d9SeSJe8c!NJ#2F;POD03wFP{IItw%)sh$+Z3uWRf&j&MUum<=Mehgpm^UN8LTS|L?ylE!>mGRKwojk zqBZr*=H-K@)G&D*t`&|4Vik~bG5ucWa9iN|ONFI=Z&7`Lq&AP$KxNZ4n3DKh*Xm@f z#@`dEhIZ-{7uVb)mV1RB;60(MY8K&@gdGS`i*e=*hEV$@9sF?$4YeFSTM!cRl$LrU z{ehD9Qp#s*E~eS&B@2Lrny#jPMYji1?5U;Tlh&K2!L%FCs zfWe7Sol0(I&pN*(w1_igJz!pRi@;Bf(lQ>Rq%{1)#fhd&&Paz9+{50_gjwuzLvDcf zV;!x4PnKg31E|qiWtccd2IrDF6=I_nTbF4g<8kU1_r0TpqU8plV5oi3tLkbIs({;C zY8~6d7=m76KSnF1;w(oHbLKU(a~0xaFLCq%#H%@GMid$t%vW-Y(HUAfmO$KNOq)DP z=|_~>Why1|904|r3S7ceAi0EB4$(7QIbv4ALIj6!!e?}KM5J7m(J0m+FOrc)3gwQY zYHD0&QxrX;KrSm_@djd}=!jI@%vj7;sHHT!YwA9w+06TOi4RMTT73fpFt&U_yWkl` zjZLjk{V@O-CNnswSoyDnS<0HCGTHL+>T%`46$acu@C%5T&xGb!U1hN)BLj~S5O*63 zVyJLR0j6iyFyc%DxsDkdYXumYtr~G~SU%>l*_hKpRJ0rAL?!Lqs%Mef%Xv-|vE?42 z(*W?F(+DRV%eB#hDBM{lOO4(#N+@V^s*O`C@*=16n)`(&{TJablxC&Wc&B7v;e>V! z;|e2_>c#DnKCN8*ToY^W%*&9Sm^O&3{-rJ|L^Z0xu3=fW$Z*qjxs4mL4j5u(q{zd< zSG*omF%KFN&I;k?5E!0iAOM{u%phE;TpNO+RRwm;&41W~C9%xvUWPlaHUkGL=Cvz! zU$VgF*mi+TJB$J-mJdE9p_a0^H7Pr|7Yva1jySz#Mal;Ye5zo>&q)6OfC-6oP>H`p z2kv1Umq--D9bi;=@E9@A;|&@kC>$mhTZ3VV`anrcIicUWG5ZM9iLki&aNJ*{w*wZG zmomo<%F0wR1Z?#`Nf;FzAtI>ICQLMuw~yfbcwa1eNG z5Ztj0HK^M;M?#EZ5xlUp5C$2bnDAUILkfuwv=UcR&8o{WVws5*_j{Frsr4E9nhv;r zAQmkIISS-=>Q|QVzGHKh#1I-Bh+L{;!X^oFT7iTdu;;D@znHC2@_>I`XLQPDkSDai zhR$OVZ`qfKw(&!+cngLBeKBkbyKxWzcCgaQ!5QJ5;eA{F57 zR|H9f`Igw4x_e;N16#+P0G3wohoknNnRyP{uNq67k+4oh-=-rxFf{VJ4;< zxY9I+OlYIw$+>nf6Ex+GM9+9mIejxr%ZP2RSQro|EVfbA8DxdDd`f{wqG*~mIP-(aRhTR+!pl$2azxkTq$f{Gh8i_R>uWQ;A*#1 zCV6wH#z#Kb1+FjG4on?khfzkLLSsR-xbQu#ON)?>Y|itjXNPpUcByLTGQ`*Na(5YZ zD-0=yTrEvAL4sG>cPwx`O7vy86KQCwL?@9IRKpzwVf9#xSZ-g}65(NquX>!)ynt+p zObkpJk@cBCo^KG>{7!ExClPX}+6fEI5LS|OD};T`4kEjwJd>>wA`S?YZ%!i*DxJzq zW!O=|ZdDS1s@JJcoNrRSH z-*7LYG{O2 zh7sai6)w!C2Fc2Mg?C9g(c<<-rIDaBa+F551&%IfMrM7O9NZ8J2NL93Rm!Y&P0;&} zTSTnDuV*F$1m-Es*P4!Yhz($;Q`w5j2(^X{11ydA$p)6^Qk)b_u7qz^jm!FgT`jQ;>2flO5~QLdPxlnoJ*b|gL&0kkv4!I~nL zU#V6j7gNOmea#x3?7F)^c6}v7y-OoP7jMV``(Tc^hakTa#}VAL@dRSVdnF3lDlE(} zzc92)ikjvy?C52~RW1h6*sN{tSV{V_^h*fA?!A@W^IpLhUYQNbNGm=>##!hpipA|dX7=Fd@q*2jO<%@90rMYEb6>~^sI+U-FmvfwHpHL+`U|zT(q#uCL{1qUorRU7C zcZd|aOI*rp(F9kF4rwWgTLw^f#cM)efUuZmD@*M)>S`vs@h>gPUm-V)rWQw`mz>-% zIo-_mYEY;BT&Gs2ZW;U;?%0EY&oKK;4wFRJFJ_a7m=7h0KVRNtbd*n^0%>OdDkXgY~}FJuKJdL;)0#A=me zL-Le`k%Y#VP`(LNH3gj*%4;42?3q;yaLUKV28s*^dy65F_=7t+BGF-sw-?N*?k&Ld z$^iHw<)?(kkPH+RKz*@f&;tEJaXpsoOVL87vxOt zU^S8h)S?Sw%Ge(;{Eyje&Q#NKuCHhq%b4=j&7_uroE`%z&uT*m$PpEMPl<%*=n&g- zZ8x@A-#BG1f z4Do{qmvNN#^D&LoE2axW5qD>pj&be@!Sg8b{mw`28uAo%0EdSWYq`uoQ{)#8-WPD= zF`e#Au&JNKsB}Vkg6d;U~jK7>jiTi+)B%E21oYi-RzV+)DFo;$o-La~U5{DvuP9 zpc`Dn(g4P$0bEU*#f|S2G%a ziN!eVOQS&=pszC|dY5wX6maH$q@i%_gyDJ0O(8y@6+&Hplv*M#SwTZg<`GmB<6>4@ zYj8Rf7U_*MremaL(}|BbV!l*IAyuL)cq&ioYgG7t?SKwqf!wd_EQZ$+@DY+7$6Uqj zP|jI^OBv=O0csiou3;TQ8CecfpST=KOlSLn%=_t%7i?P?yTj}uLOL6GYo0GP=fF6Heynu7JwESDnga0!84 ziMkl(CnfohgjrmJs65Q^iNpt4Y*M5(6?slj0SbhTHcGIsF;Ft@lHp|{bpfA*U2Uwr z+71jZ=3gkirm+YnjwM>(;lUaKh6g&_UVsybsZONa9?KGutPHaf&Lh8JQvwcDS_L52 z6T<0nr*Wz!V?>Tof>N#{Y}`kQ#N1@jN>*bZGjjmjk|gUn`BrF^@UAgtXGR1RCdEFY%QmGheL~_!t(gsVU;04x zk)upb8A^OhS}A3B00m^tN_N(OMk{=h&_1U90N@dT5BPnNhCKajE8&3#|hS;s%nBnSLd~WyCA8h(P;43pLVAK4!a#hHUMQD&JkWI2jpD;K+s#MS0*3U)xVx9%GM%X&1L|n}gZ5Yv*h1o4 z=$Cs68a6eG{92%ko}ML$i-N^KRI`B`2&0@u8xC5H zL4762;#at_fYV*d1}idzhGQ2}_GAoN$V~J2~|L;%}SI^iy4a8c5iCksH;9W~QAzo*w4djJp zisE_aB&Y1|C|*{WVvIb*)Q*UaKa4@4*$dRf_#HsYB@}4nN{cI)5WdJjVGw-^nz?PR zA{^_am0|-5f-0U_CJs*%Pw)wxDlAX$lV|PXGkIW^0>;?qF696_j!}%7<}R3@vee5h zg&ZzkW(vwgr+Mctib{SPVX@zX0R&c>6L1gAZm#9t}W;ev9 z;HT;-aqm;fC|Di@0YOekvsuS*fy1URbU2&Pj^!X7Xdpw!QSV4*{jt@-$s_!H%goR0L}y8`fAn!~th-G1S`xrPNpJ z5i;dH(i0~&UQj~dMw$XquM;q*u(r#UcvHEIHG_%GM0oKqjD?~+Qf^QtfuHiH;+T%tj4-PAUoMxa$Wo1SBE$rrx~ z4bXUs?7k6cq_SUz%+wB1Ms>w*(3DJh){->k`UNH!E9eBEFcO9Lq?hbi#zM68`{#9%+RoTD(H2 zJlvy2mn!9ss>U&z9n014FxEZJLvTpUB*ZV&x~6q3l?$t=2V@G~V}Tti=2HIvk5<3A z=n|vMU+bJi!6Klz<~y2Fo(hh%$t)|R{{RfiNhn&YiVa;rijtQ3<{GDjUBMORTmwv9 zVCpSm{QN@45KbOrsA|mjG7cMtAktjKRRG6^b99%F8xoq2IK;#jzl)Ofm%#AX% z7R=xv5aq*CfIj1huPodWY8`ySplW5z5fxNHV;^LPj!fbb91|ouELk+6bM6)V!SQb?pc|}|#sYcZhA2EpNM}eWtusVutf`j59SxTEB0hJ;RY!gShjnTwtdE84( z#$q{&W%Uy@V*%aLdFQI)cjq$U!ws5p_lcC`?t6kIb-yWEyf-gvTP9_GLcAfn*4~H< ztUH7Qz%aYnY-=rIYCJ)l;V(vs2|#qt&LZM8z+HwXF_RE7BL@jZ>>(P1*q6)ji$4v2 zl)hFQCOqa6k?1Fubt!Fz(yQWU5`{6BY2p(E;55|%iXj2oE(^GcZpZ^}rKE)%rBMs>;FcNX zj4B$;I-Wq`_Zrl?gcg2gW~NU1tQw-4jW7I#JK5#Nouj`le(rF;&gD zm9FkK;y8B|kk1rd$gkWK9$-<%j3yqgV|YqQL;R{(w@hew%dsjWBz9^52p|_pxnq;e zDofiJ!+C>IOvGH`EsrvYV-ezh7}W;Ji;*KJc+Qaa6xa}y43FdBUrCvI9*~_4%ZL>R zFEPk5#r!}C#ZTTx32@-l6q4m`VH}fr==ztaVo|QPCHcVIOdUiI32G4%d77Qn3K_Z) z=?%_0ZRE;~Rt%0K-Zhe947@=>*2t8f0~*Ew8nkrzogCs83b{dV;p7Q zgm@yTrh_SZmqby8ifSuWyhV#Iahy-#o}Dj_Hbl3Yjyxq12Kej3H4lM?TN{=q5bD!W z1fh&VGoC2Uv{oE?*wHrW}O zol4WK7{gg#kQasq&MyqX7{T)mHxqh6aTD19FDOFu0T|2t#;xXRO1LZ#05vZv60l#G z;9eqfON!etZn+199i3YZ_1vR27*NsVVR}YLyg-3ZsTC~$0E%&NO3lC9GEO0u^Ehz{ zp@WIUa!^dm7O!D7#Reg(@GP*cHvkV2*KAMF7{i<_HZ&Yc7VM2_>QhEZiwx|8F2Yni zk*rNPns}tg%BY8-n5pJjSkpYgD;U;ciJXS5Q3hqSa}^cW&k=y~W?Wv9#BQ30I-Y&T z(Rr(fV}lzM1)acjyF%4J(!!u&%;pw3i$V)xt<0#a)eXeD9Lcekw~`|)m59})C~(x@ z;g&>XnZ&dVN~H3J<+J{b;pen$bblugl>C+YLSCps)-F?rCCuxNAxW2kxCE)?w6RX* zSN4rRH5?7eFJ(+5<1_sX@&v2rgm&hJQwRGXp0|h?WsTZJu0&k7(-+BHPRzw@Y?i^x z{$R+0^vMxgsk-NIhQwC^7QYTYafo|EQ4J}9CpL%#WQj0N>7I3O?r36__=&lv&Z8T;>kc!{mq#StAQMbJV-s3`)ORFqVmhD|to( z$^zI;!7l-G6L<)1-q}%XTthFU5MJ*lXC4S)t+fzc;tnYV#AKo|;>5o(_ERgYz^jDB zeJY-qU}d>P^!_FI>7y@+g{bK2RhdC(v%(=29w9JBmURobLLH5e`9w7%dSML-D^iIa zBBCO=Vu}wIn59FDu`WW1K{jO^*91zJQnVrRpi8Bw8pN1L%pL||5i zD$U|{ATa!rtg9uMmnq_U4D=Ah;<=Nb(iR0s0x85vlmSfpSurnrFSuzZ?|aX79jPmo*`OSaL54B6TK`~?uh%=Y#NN4D!Ggu z&T~*6-f$b#4UMFx2v>q84AMwn<_f&V-k|z0kq!mJ45e&&DgtXcGO^%;Vig`?Rl>~r zp(;LtI!`7fsX%X>JV1Fx z?r^T12~!o^-l7hJF3j*_Z%AS<6*g@qsReefUcAH7fC3yH0uRuEgA)P}W*;25s!Hr4 ztBfkp<;lNrT}?Cl3#OPws%J3|f88@Q&pOTj`i)uYwI?u)^>V{h0_)%OjqsY}8k33as54X%RM-hf=>2xxLI495UND zF|a^8;$Ouy4Y4rr#efJml$LcHB^P{?D|8!xXNEXmqFr3DtKOlaVlExP)o^&NTP^&5p{8ODAP%7Qa>B0 zEj!9lUTUG}Y|ko1!A-wa2N-2>EzgNgSwoLC4aww%b|Sk-NGLfxKp1n=Qxnx4>YH?# z7#4!@!Wbd|u~>tF%Mzx*N!%iuR~^kyn2AfltHef_{g8Wc#9>Ky@eq}Ai1Rp|%q{Xu zW~m+${oZ`a>T*#BVy-4&wi%T>VR0GcF$ndAi>$GgrBj4ARaq0j1Vq|m9o;cSZsB0p zP@vTV6L96;2FX z$Lxn#Vo@E+U>|IWF0(>e=38VfyO>OP%|gaL_OwW+W@<7@`AjGtt~eLR zQn50WD{}5zZiqCF6Q~xaz6eS3P$2Fc#|Q}A2f0A=%&R%fp|mu|w}`$I5D;v3PT@pt zWiN0H@JvaYl@UV>If|tYSW)UI$YQ)%QBlpa#5;Sr_b6%mgWe)G)DS&IjNoUOWkr+^ zwiAuGjbE5Xy+xtvWl7cx(=*XLX&4PQj>76YWw-wT5TNri*Ob(>VjrMIZc&Iga=ITW z__d5G3JmJ8gPDBybIkQBNi1vgeMX>EV{pqEd5Aq*sN=R9O*P6nl@7tf5%wyV>)hH$ z^hGk}kXe_krt-9y8_cUa+EiZUpvHn-?gL5zcetZG!@TUI2Puu*HFsH;7bQVv)JiSz z!ckkj${^IkO%Va3bU|H0zbiq+7tm{zm9038bt9X^pgCm^o>7mui3@3#0LHR1*kuU- zLDOY|0tSRbz%b%iCdTX#Sfyh!oQ!?|bW7C5>=1BDcT!gPR1JIOQQ+rY%{FUfpdi}b zeinczH3p!MWN3-djT3So5N#0Q@nAVoqEKG#mU~3TkNY;Gos1b^Wz4x?^>oZ9G)%%` zS{58PFx8vNJX3UIj)FGqd7A!W9TPz~@pl9Vvd3RpfyAxf$(epsuEsj6pFk(@C(}#T zWthV&3d%Lg5@iNmbqKdJp&KPZrr9h(6Kn7(-;OpQJM#FFbq8R>WhOqXSt^*uQ=lcgxT%#Dldsfv%zFLV> z1647t<8bk!p9ZRhN{AH;^)be1DC8Zwh=Rm$T`VmRJ#wcMnMdu1@V z3;zHqz7I2>^n|)W&OhscZA|cM>IL5R$?w!~B^Om+;RcIyVf;1zCc2=RuM4^09$W-w z{{V-dC=+N0P)M@5f!iMt;Z~|wItUom7t`JY$AKeRa@2B$)-k}$tnN}a@9I++R>?{+ ziRxlJ&mbTjj&t26PikDpF&_=%P+j*g#l*v1vei5bmiv`SXn)SB%b_6*4b21##KwAo zkQm9nHb6-TwfYNDj@Rs$yy%(nud=+b>dnQEd~nHLmUldYm<@p5IbWt%*d`T zu2!OChM;C#EfGsGMNPoF2sZZ{$ha&aHoFd!G+Cn=HJ6!4?HtBfHons)Z5Re>WLc;{ zVYpUGw_Pzl!5LIhQwQL+!-2N^W?ZAWZ3?E4&T62=!E<<4;< z8(9o=AB7L;He9{J#(}R15UL z0Wx8iqZ2J>wAI31Nr^9Zl*NO8idhW_m`0Y*-5}Wysjc}|6_R>>NkH^rnvbJ(scoom zuFZ1-f_7@ih-)&G)?|%Csr!tB7d5+wI-5wzITwb3&zY+*99P%-ojO%I-}eM8@vT6m z*1^Pu7$M_zhAyWdC<{0$a+i&7acCnUA*&~f!C2m-QraY{qlfJKoFm!j3LOR|a#bjp zIlZ5pz|JTqE*5_>%S9oq;J5(XT#~pyAp|?Ir@!|+!>muP{-w1z?1Rga0=mp$4`lkl zsZiKgFz~>bYZlVJdS#awR@U(WGgcVfp#$P4oQyiStVOo+#Sdsy^HVHmS>h`l5Cwtc z^A?;l)VGh~CoocB18w4LQAM?)Y5yCWw z{{UQTV&g;653Qz0pMoi9M|R33+c}r0v(yM6Iby^z--ulCkle#9)s&CH2za@$8&ix; z><#*rEYWZ5Ly&CQw&5ZZ$Q8aN7b_R%4JPx{2El-(2GdGAuSO*fu}Ko~;$uC!w(Cbc zBj|#*+S}tX-X*u?E^!|%eZ|-B_6OO|60-zA!qa;t``4{+rP%O}YP&wm)D)j|cK@^o}BA9iu3g;BMs{*bV zZm^lQUH5JRbWgQfZ$ZURQV-E zkAW-{JJMR)wdazMRT0~7a;)Eppsb{~Q?Chbt}Vg^8m3^x_QcofA}o&>TZzOiL~d&s zpR+Ari(~2y4YLPo7*KZ0GRwf%2y1aNtQ@x#K-dr&JpDzh2fmv+c|Ve6A#TC&aQ?pH z(zzn=72W>;^o!b8;8)M+aIIeB;LvQvsN+Kn%A8+%dOf8xD(oPjX9@aV(b<%ZRD`MLn?v%Z})lr74`t%Au%g z6V>|(Q#C2Rrio~(**TO$)UKsgA(+zX}p(eeQ@#Fr?+&S>4*ONsM!DYxY6N_gF_Se#210gy;@FiPKqwZB`Rd18)6%KX&5`dRn+&$W_ zuyrYbymgkP7nm5hV@sJ$ZU?GgjX9bO*D7gGpg?1pEt%QWw)UI$S9l?J^EEG5>XcOE4|UlTs1bw9*N?iAi) zXlkCwcJ?E1cbP&aOUeHLb^OW`khNR}>URXR3(G4qjSAB)QvQZlYaXie=kxMf0OS{8 z<;HotCkY@H`lky20OxU9R=&T8iX8y!m`wpgw z!?~=L^DYDF<|%G~7UdL>I*3x1^%~CjtI1RN70e>{aZ+gU*(siDgxqD&MM4xPWzoS* z1sr&WJB4`>vk&Zm-NBN$MQ=W$Z2Asi{{R_8b%{*kVTabHi!e1mllqnE#m&UJF0XR7 z)52^8?k2~68Gs8sRF=c)X3r63zBdBe_`@-N<`ph!?qTL)=58hSh97|RrUi3QP7cg~*~M1>p! z3{x<`^%@HfTA<7rWjn$!ODds=z}LBE+m*@?*HYhO zxOv~GE>yI?74d8qt3Ax>9|NY~&CVskt^6jjkANIQ#HoLB`eHe2Qq#=*N`f(W2;+Vs zjGJ1Sr-)7vzCAD61l+=QvSZBdA>uCjis4P9S|8ZeGUQzNC9pQi1jv)NIRJIS2IRD!S^0Wf1690ZVdPFg=PChWHp$` zcON(yPx$^i$Gt*2aP>MWa}ffiuY8iZl=)E1EBMR!JTqbwz>(2S!@Y3MrW^_+3A?k@ z5u+2%yuk-TKs%-nNrc0Y1jy!Du(*0=CkLirj)LMP zY1FKt594n=@sIIv+ zEZD&FF|Mw8HIIc<*UgXd9mF8Mp;|-A%ux?0F<06ekd=^KXGSg};HR&IQ(`c z&CGM_(*u%^^C`x{;C~8)Vt(^8C>pNbWnvb(hUX7+{6t`6Pe_c?DvvvZtK!%#lwDj| z*o<5%lnXbQ{{Vz_FBzU^XujB)0K0)zj^YKEJwe*NOF0pylHj+U=20*p;i2>KuBDk@ zkMl6r7;AFY9Aa=qlC#WI{gyt02OPtq1o9jVO5iUOHR0k~>~$_+9(6MT3Ysd&#A{<(nyOB8{RFcO3qfrzjZ2n=HdJE*Ft zFN_zzrVKKJ%34hXqsatAjT8d~B^kfA`3F4n>+^4u1`73LO@II~>M*>`3?SP|tWFTH zPYg39!vhDGzp16XYNpyIt3l5sA5Pd&ABsy&a|Sj1G5MyM57GhL;RviOqauf~a_=W2 z))O@;#H{jV3g7IOr0Fn}*8`2uZgpoR1Y$&xa~=&$V61#tteyR$VTIg3e=1Ees8a2! z{cRw^Cr{5YAUyiE;W8Af&HGDM-j&I+>>#_at(-ed$HOJ^kjb{N5@gJg#~`F(5;ezu z`Nz`DhD%DmgCA}^P={2NV&}aM6`*4AhFb2k-Mi2FDSQsFneTh|i(QlCx>u7$!~n(|9FfZM84><)OP{f}RFFJZBE0NY!z#v3 zHBo$BYA|*73}wI3-5SjgNzMNN(E&r$eXWro=#!f%^ZD%G;Md8lsK&DzcvbEb(0bfO z*&dqQaek%q&gdX8G(t>pWs!HV$JGR+NHPzz>XdXzJ+dwVuGRH32zOk#_dH3S&g8n9l3F^kjd9^pNE+H9ecIJg&8I{tQ!8wqH0QBrHkjief1(`fmh^-q!LB0J z^$O3L%}>w7n&M2*bn9t`Qceib`~E8il0@`UPXgam2l?xL=L1s=b>g&71EzNG`_JS& z7eGLhhst30xh2!+uDv4<*CW+;JO z72t;18!_qgxX#sz-?0U4=EgN3v9l&T$K(%M~P zyDG66!Akswm!M2tQ^e_$%L z-T*i!Pn3M|to_TuWrN|4$Y#}g#fco7NA*leFX`a-KB8*C2)^{u9?Z`gPDXa6N1n>J zr~6?+dq>G9eboN|Lcj4iY~Y9uNZQ*uT07@;VM9;&)Uo{d72T`2{oSF&uX|>hYm3Lz zw6?udEjYfIhuqrf)BJCbkAt|+2gT(-ss^BzdYZRXVC3nq*beK1@Q8412!V#e`5AFL z`HVZN-&e;Zr&uXu?^4I*50ok`CC^u#{afgcE2Q@^LdajIs+XAhOFWvdhjlhe+okCvn1Yh5QTLzolW@^pVc~AH&%m zNn}T}XAhhjXylu$_*h=7&vs65h7$d9L%UXf4!zh+{gUCl0l)yt*c%~xgy_7IV|iv4 zN3gvd3y}|m<-c3Ra{JCVxE|OZzeE(m+!<_jEA}*OyNnH%!NwTr#>|xLPg90%wr{*3 zV=sS*12>VWDLuarkoOaY+h4Xl7X6HBBFc@Ai%>^!P94Ipwm@SBN4RfeU|OQEmTu%n z3?R}$+yo8ZEsN}rZyWyr?Jk=y!`53poO_61TQcdzBLEI^kZ;oUpGC)wg&^uFv*B*j=_0+Q#gENqHBs zBkN)620OE44#IsS*$X7t5;%P)sPBN;6TsV9h1ytU?0vi|`n$2Rjt5>xagiN>XwQ9t zyhC@=;Kh84tI34YqATnWxPOqXARe#x z2;@_zB4gg&k?Px4wy^hgXuBo8q{uK}h8A^^#h(j293#P%nQDKQ_wBjewLP$8J-sCF zd^1fF#Cj}mT;=7tan{Fxdx()F=v|mHU3DFD0Bd>KSPtZSw>WpkU97{36ozGx);c@3 zNDYF{^~g?pF4-h{k3!it2W1yS3l7;Qv;0W=a>v=9lQxdY<2@&c?cLptfxU);z<81L z@HSZMA48FO-{eDtJxIaq#@$D!*`bjRne#)^Uv^sp#$##7^nzI=$ub@89`4;sC3Gdw zka4m7o^Wp+qeLc4Y(4O2u)~ot*bJLZ(Ys>-i=$!EX3}frh<_p+;!B}yZr|(p7{Uy+ zc6`64>Esb(QJic{?#u3RA69OW>BbSpStW<5$-TEC{wN&<-Fs|^e*w@eZ(L4baHL!Y0GVM+5&qq@5C7;J2IxKh`v=Z4{M%c#B zrR*T-_AEF?$+yx9cVUFL50E5x+>@4uTD;)uGVcEXOUJxf4qcFeY0q(VC*DiGuCVoV zOL?Uo$a-Ja3#MB(N7+!LsgA}A$Y=cEjxylP@24a<>O2kpJUi)aok1dW&!n}w>gvNj zr`J);dSB}ZJ&WUke+x$bg)XnyGB5J;gy7EM@h;0Zt3S>|vlodc<^HW1_k%l}7@ilo zyB{viB=$DLhqC*BtVQy{CHD5tHchrNp|@d;q(fU_$#)HyN77T(gf@uVVubkA4V;Uj~-4s(U3S+zZmw^TjsKPT2qIoBTA@oa4L=^wYk zF2-A=I~|Z`1J2ou!QM%oar1_BVZwNj-s~rQ1~GXj+k3Uyn*vYuc*D2#E;xr9#k_7? zZgJ`_Q|vIrI)~)^oi}d))A1Q*vExy|JDL0J1<$zmK!5B7NBIBq#M7(jxiC$bMgEf!;T} zdyC|IFH)~0^=z=)J-V2UYS6cA>6WVz4R<@ndY0`yGi{NZ5$r^NE#rPqk=&=g7h*iF z{ohE-+yrk?@fi1k+c;&E&1}4#{E_UxZ=3_S-Q(5vdbf?z%gc1&X7vXmDQmZI_YbVQ z;BJI_z*n!vPOp$H*hfY-LqFTcK18`b<-g^GaWepgj{J{skcjs2V7=ox@?RUQFH6Qn z<81If%hmSZk-M_XX1rdWr@Ar;XY-YbZ2SCt=WU;(C#!!8Utm7MJ>581Y>0nH>mZkQ zSAXTD(}EWo61?~+v2`Td4GxL^yGxP7_aLt?t zTf+Bj%vq6QTW#;`PlP{({#H|1p8k%~w%Ku!(cc>RZ}vMf|HJ?w5dZ@K0{{a70RaI3 z000000003I5Fs%jK~Z5aKym-t00;pB0RcY{&hbCGUrN3ed?I`!%rArg01XqtA-@ZS zeoy>K!kRQUnvq@!!=lUo06j~icgC=gS$-|T#r@mN5J@i;th~~rZexmH>fOTFzQ2mv z!_JB9e9;BNeiszJ9N68&EG#HbEtQ*i-X3;vJ`_V1C-83KB2prLkq}6P5*lNOr5Q>! z5cn<+q7h+#4VC;a;MIzefa+XjeVWHeGxwQnzk%c7;3E`-8& z8WthbJE8p+%^n}%o5It|Noab+;=@}U4;CyXct1jZV2xr4T^|H!Nr{|~L@o}*=EhHD z!s8cCVTKYulAnQl9f?vLDed7nK~o^CdK!aJS{04!9AWOUM9!Dsn!?Xz)uhX5o~AYJ z6l&;B2J1ctqLgoir8M?6FR>CY!31ouzXa+K^j#2D^laNV^y|T&u{G#p8SvxSnBEZo z07P9JE7k_WU#5tcp&WP~j`*};GrlBfQnHOv{5=bhe*~bmAqfOQ;bJkfd=f~cH693pSg925 zA}K~EMuhY&F|Fcm;R%SwO=zV>x}-(V2SO|;+k+Dn78EQy;$ka(D=5AS@Jlu;airBm zVo_&oMu=*&LHrhp?-pK3j}nT8Q8D+Fdq=De5NL5P8=J%G2xLJfu+$JC_&m|TZjT%j z6QhSl-h#2YVy%~e)3jD>LiAb?<;)uo*$9r9o#%oc$Peh#!RVjc6bfrtLR}kDRKIw7 z=?<9*q#=nJ_$rv&9Bii$YtZPMLi!W9OmAb`!`RkSnd&W8)EB{{9(c({pq?7>{KI+>$}y?2w$IqcF-O?; za7sWez|{%v36FbNOy@AmHWv;L=+2F7ThS^W2&Iy(cmsnWwc5bE%7@T92T2x!d7FgH3MA5sV zY+~ur(D*Tn6ttxu1ol$KHpIrp#_+bFxHL3A3KhfF8PT(Cq$EVxx@yF`8r9DWqKHgS zV^s->k7L`}1+lLJ6X2GFkE2?K#Jvsde*$d_L=r(Qi+UOwgTyo@Qu`S+L9)fq1fm}e z5*(D#Xpn#&vMYcQkZkETP=?@G-(cOt*65%VsHtsquN0pfi1|!kPwj?%e zN<5_CxP+6@tz%OOv@fHN9)x-p#7%3W(x3Kejxf5Tj~ozhM-B(?2(*jg(axdXR|tbb zeuOQTV`2!R6#bVMM#!NixWwMgiZTm9jYcF#e}=_riS7vpskz5f7O zIIh2q8#|P&V&cY~9)d=yA=JvSv9IZT*rhH#lvN3Ao{cmv2@wrEPw-y`KN>#FBqbSf zMNEYL6%`OcSB=AA_$~<9<`FhegdzXL045Lt00RI50s;d70|5a60000101+WEK~Z6G zfsvuH!O`&H@eu#o00;pA00BP`u*ILqimV=X5ixK>022;9i26#(Ik*H?eIKOJ@Fo$P z#+M29%Vl?;^kfK|@Abz1;mB{F+&0CZhFB8Cd*x;+PJDG8-5j!ml!fnwiVZ8NMbFm| zXnDVg6{^3TiW~;YD@Ld4;_s!B>9b51$b4g%50{>DoD7QYsR)62j3@>6y8)UrUxR zxuIP56OXr_B)p&WKnazovJEfu2tU~_7{3$a9-pzu@wGGxeUg-{dHzPn+JA>nw%EY; zD_aq(yI$@#dB0Izaq6G~+kDDhHl#TJ0JxQ3(l%C-;*Sp(C|pCtpjN9T39er+|VRTNZHhY9F`*cz0PJ7yBY=*IY$}pG%BsF2=F3mllHoX(IBEL@h|epKMJF<6#6W zuQKDJK}A?EYY1}Y!NzwO@C*Bwhkw-$y|B#v#nxNpb^idU{l@E{SU!#Y#Ff>m6Z-wc zOWz|9r+w==c~4GHPJKdw3UXLkzSv`ba)qm&4xotA=Y33Uuesz1Sqr7{8!MlfCA#~V z9(#h4xbqekGqSaPM#hIts42XFj)Y6muP|7t(y)r_f5a-Q8L8ZO6Op7oU{lNW1y-uQ zXFvB18!`={{Dax|5@T^rQBI;2MRFJHArJz9C?LB({KF3ZV0M<8wl+Dxa*V(IHbBul zpXk)|gfsoz`EdvOOW?;X0sTUSUnsyS_L%-+y&oG8G2^buK;*sZHvq;_hp0)xc$YbVIZ-BYWG|0%hxrVCgZh={bblCU^$zzf`Xa(5SJEUJuTu6Z#>GR$ zzfo7e)K0c5>TvRo3{bls0pqaym{3)92%aG&Ml`Xi)nO(f;$sEAqY#_)to%BFr7FNt7F=mS!d2u zIP7tFB;*voWDC*D^81a)7SnOy5G*f!K~r{#;-Y)R8iLk^1aj?FScg4Bzdb`jAXiO) zvDCNx60lBSbpcVe6Fwr>niekQbpH|$c?s9VljXC(6!sHZZ&OttBnwMxLKtwOx z($e=LB~kB)8!GRqQr31gnz?3 zfAENTyFXHwnqkr0F0G35CJO7!;{_0Ig_8Imi%*=43nOB-37K$!{15<*CccW1w6g0qBnU8-EN)=I2PT!clhnH{tL1s}_0prOx z&}sDybhH@yvjF>-2PEWtTsAfU?pFDy`!gT#M{iJFdx4{WQo&rQu>?lwD$|N3xKmzU z=L%>%B--cV2JWqN%X_+Im9nF5)z@$wskfK_2fq`Co%0ak%(ke3#4isw>OWo?Vf|%f zyw%jWgWO8Hx|-0oUU9xE4LK6+l{rq+5+YfCp?PJc1nz z;qIS|g;<68fz_`aL}AvPRBlgApO{DKD*ic&Efb`GIiCR%#H#C@*YZ}}-75W|^XUQ-+rn$~=y5Y7dp zzQyKRr32icZy;@(f?!u`20$y)o1wVaTZ>&qyAi8j%NCvuyN?Jw3zLbbt$j+?!`W)X zCfv3fGM9f)L3-*dclQuSqwW)eqWw*O`F2__2j*z5J|ISF-cND3?1ROzR zHXGbymjHau6s25nG_42rQjs#+#Gl9`sTH9eR@NjIlN08Wnp` z<-GNDM=kHYn3Kd1%TvzE(dMG-YLE^tEE(!OL}9}!0eU0J1sN|Oi(_PR$R#@Xlo_#K z`y~zW{zZ`Dm-8)djp7B3PD_D4J;j_r1Jc62Rrb61Le&9*II~y-nD9il3CIJUlY@R1 z{{V0Xhj#w}+(5TKQra9mA|)I2zCNd{l~^97!pU94DrQR$giT$paKT(6M>Vgg*lTa7 z2O{s9iKPX2sE7-WkaGUw&{j;8iP*~gAsz89;?c6}xTW1)#R8^|b}&{_uArF~?Zj_q zM=`e59_5x0+YEV^kk0RjH(+>pmm4ofF-I-(v8+O`m^ZEu1RCiPXfv#iwaKA2}5P?p6hewyh3K^ir{KMjue`N#Ue}=D74i#|1X8!=P#*Kkq+v*2~e8gSD%v%bB^ASK5uA-DVT`=6g#Ngrw#eZfp z>l-Lgl>jP$TtKS@&{yhsl=En$OXlD4Ik+&CBX1puLD*PaQ95g>tH#r_1yyZ1m|~xp zVp81`h>m)NbP1i!HBj{qBA${8(AzGH7b0$MEV zk~J(i_bUtXlb{HP%AzAO^2vO!_@4t)jwQZ%m=57kRQ~`lPAO$WX2*O3R@Pb#4NoN5 zG2pnY8Pxt8gEH%bsF1O~BaUkL;s`qVlv*q1Rnhr~)>Y9E>Ej7L-bq$JTuaKlPaqo= z41(?iEbu9*$Oa*)h*vDPT1>Jd5rW|ry#@?L-11eOlaDfTlnaJD?{jBaszWEFXjm(W zQNtneHovKL?Be@|&^AY8JY}EIV~sP*5S9a{Bmr#nOX?K_8yap35^p1dZCqwUd_lN3 z>Eb=nFp9fzal1igw~x4E&79*XnhNB5fK$w+4aDwL@oYy-c+@mp1(35Ae~9>80rfH- z^XkJGD|`vVo;rf6ltTsAF?%W8Q%51ZWiWPJB!gN2fNF;a3}6Zs!7oaQ!YubJA#WEH z0^0@1#sKjZ!Za!l!N5U4x*O_d9v5t({A&lSv6_BiHz|3S3Ke@tmHDFr(MR}9Y)fRn zG0MD^YIXXBB~mB!oCmR*uL;`>mWZoYKmDdfpjBf9V2|9Od2u+Dctb36s9#=T$#g=H ziBjuu*;ADxj^L-39YrhR1tkOG4wZdFx#jcA3s|D+hg?g7pTt6(xkpxdg`-~o08m$L zj|>D?MH>iVv%Y4$HN>Mt(E_&WVd4Wu2IY-ztX~bCuq7P7*=Z>vi!0Qz0Pry(XdF&p zZg8PvyBm;@$>s>LPg3?KMJ-sWA4m@dF3TROS!nQ(N*@@mEzeUg5X>O}0qQZWA-cDo zV7!M+Wi|2{W6{}cTk1w#{8dRz8E7w4#80neB!SH)5!uu`9eIMNMYaC`<(?w0Uzk#L zd5=X7FPT?1JRpd$IFnO^>MS-K?)^?2JY2gHoZLy?knt}kiA*iwD(Y*gcqu-kxGoq} zu+%Y-EZR_Z(OxUscDv}YV4%tMA2rc^9I)(r;AU09%v zcflM#%m-Td1Y)Gk;sa2)!pd$P> z7NiDcLzT;@PACx9EULY^$}MeP14sxgiU|28MFP1ACo<+GUW%XME2VMiE)ZJW&4Me5 zTspU|!5omf*$YfHRcDDqPAh%Kij7qw8}cSJN(8B6#q%D_Peu_&9-x_nY=f;&i7H`? zFeWY3Nb0yHK_Jlc{{ZIFoI8dnyBn!fiwZ&%Vv24*B{|`OD_@uhM87E(f#$$oxCsL> zV$^IQ1V@CHwf!O_33Q~nQ_Eaycm-;p$aUdEXE+I1iN(B|i?QxxUjC5PqOnFtaS9BQ zuwNos{R0d#H$uO#5IsPztKHGz{7^Lx3(f~)p2MqmAIjQslxqQ51Ql2)0!yy{gEdH^#esl4C~w+LFmS&aVU9$l7?!25FTBZ88wYXj4p!sCJZHIDu-1RsJ?OaA*-eq zC9$;ZdkfFpx>>;C=hMu&vz}MUt{Rk4`?;0h)!oW(^{_ zxs|1N=i&=D=$n-YogtA3kKZ8xYojAHh-g3Z2r(2+QObnrBS%&@2ve!}LqHXLy-P|1 z+C`v|H8`DA&8mn?%%?K@X?4Otnys&ZfaZw&LSPm>GR;~W^K}CF8nyEaM}_0mLRA5g zb}rENB(M#+W;B9+WjUZ96PneDvt!)kX>e8_i-5tdM!p8ZfDQ{L;>bI(M%=DA8Me6 zGgykSK2ewz@sLnA(#j25Gt2cYDxw42XgOF`5RO}*g;#$A*Z1gc(!K6N_gqn0i-Kl9h+nT zQZ+SSlc?uz)4vj>(GTV*t3!W?a(>m+Hujq3AN`qn!~{=si}YNgI^S>!7B33mh$&2o zf{3_&j0Ymdft$;^V2z>(x?NdYEfRZqf^XM4l^pOq%=``rSuajO@!OK&UvU#FZnTWt ztwh+^6nXGU#CiFTmK~&Dr$LSa5OP!}0(v@tn^c1C4WYbo9<+>QTe1Mi7WI%+eZ+yF zGYZJqj9TZ^03NOaL2dym+KmS8F23+5XF@^XKbW<--}z_BHD95MS2>CPVU=HkS%_WR zKT#ChfD1nnU86-?VQZm-uk{smaW(x#p{3hGW)HyHBg(1deOz5YvB>z{{Xxpq%O?I} zqUVEG9P9&yGl(;2<|l$<{jv!B0fWg7@Q{Ecl=S__s@?(kl}KI;B^Z|m5Lay+RWqO) z{>zT(Ai=A^OV+m6?;sWrOc!Ag_X@8@c#OObyulFw+Qz{&K8isxeZ^SYw{Zb@#abxD zV>_e;5?%EHL^hF?j^6d0D>M}%7dYdoS}EYO5{NCFCw(mJoGmRhBh1@ znEgj6sv;9yin6@m`C#e4N?71L1iR(?1l`=)f-0LiWvy_u5GG76Hq69jSC$oG3>3%? zQHBFo%s7`0vc`(tT-$2u@=z4#k{ba{_JOc?=RXk|HgcRn*%x-8aDl^LiNPXOz-3Z< zL?rcB2M3r1{m%2qdAY+^rGOEZKxc}T$#K?hor`8iV`cDz!K5+^DDZqk2E~k3KtD(% zGkObyg&v$ng&f8}TI#)@F|Ekn7Wf#3tSLK)FaEO@KM7?WplK0k!&3O-bLI!M_u^Q+ zcDZ2j&K_4~-TbpX?ZE6vk|&slF9m$f`qIo!!OPSeAoDOT&ys8+d1JsU*HFUv6A3}N zc?u)Jp;xk(`(^dTr#UQL$o?Q98U>IPwBXATF9Z=_$IM}~LyRZ1YdeF~Rl>S~#B568 zAYD|RQtU-xQR6|T@hf${*~Zq|*E5H}@`dTSg!gM`hbrz?OYqI-A3i3!w=Py8QLbG~ zv0ybGc_GVm1H=dF&dBPo0A@jyX~ikSqPDMaZ$ztLXeRWD0SuehnaNW{yhfJJxrjJP zq*oZ*_e{L%#jJ1=Q=Vb*vgGg>Irk9k>udo^xw2NK=^{=X#R@kit&rDcrEXN3r3QBc zg0$EKWUk)e3ex`o{6;-sFV05-jh8S`LR2AcUu+f#m+k$bMMIe2k>JjhBBrv31Fr4E zF{owPhbXa$G%j|?Xl|`IjZIV6NFTLV#Yd2{cZej)FbM4DmEv8~!Z#F&bgw#&G=pV2 zlYOQ{r$zM^0c#g>w*xP^O`dQhxqT9Z0gL5g$I?-E7+{+pF!-Raa2D6(K-<$jFp!U$ zgQ%_@viMj30Ei6g`UI?2w{27YV8TPGdVjfUJVYq_i4vvXUjhS}0px)JINA!fs*g~} z8gO};AQw}jS8n71AUkpf37rzwFsm6b!O-BF3FvbIYf8mMwK)VN&;iqN3msb4BHJrF z^AMn7uY`$fJdWkWH-&k4BC^L1NWF)e-5`c7Hs06?Qs8yWb~-qUrkCf`3^(I1eeF*g z#Zhijb!_~@M_{(VQVaLd7}h`CC>UG`cok~GCOB%OrWbUV698FfxM%^k@-1maQ=1u2 zxYS4wR~2YDi4b^Q%uPi>JAFwL=yl zqtqoaIARwD5peZUdkc3Q5)>L$JVC=~YQ|T_@61pj9kiz9>0&$2%&#mady8+O2TR{y zXSNF)niDVc%wpKHq9Ls+_*OUJe z=zL4ofu-tdc0wpB-o0!kI2QPd?1m3+O={rUK1Oe?3%2cYb z_<}(>wIFU?W|8=g>?%C@L>sLP%DW}@6qyR4mYd6LM5FjyFAGX2;idr*TnCo`iXEZ4 zC)D4RO|yxha9#5$KNm$@f7M+kSs}veUT-V3zNMwPTOUwx2Qg9M9BT-0VB{5WUIA8z zb4ig<<7TT|l`S~7kx^ysoJ%1rw~IgWav&zB7*8ZBXOU|>Pk9_{oMl~|WI+cM$C&>B zbrd2kRA}9Ct{0N6uJiVz5z8!;2(%(i*X;)K(O~%Q6cT-cT!Ts} z{{RrAlC(}`&H?_B1{T+dOz`M6^B+*O)hb!kXr_wTN|}f?jj=}skZ^}mfHqTtZ%8-P zz6fxjY2T=X+dJPdjGFeRH$)r{B1cly#RHWrd`2@|N>4?lWYaO?ARCs0m_Vpkslu4q z`<8;Q*$)APvF!nRJjXD`ksUye+J!;7EPUKgTn21kfxu-z>eGtlgJGC^U@~$N9lypv zz?X~#`Hav(k zznRP;C6}t4_K>K*6sC?DS+|sja=K{`$C*cVI?(f8DheVRHIk`f3DxGoeMiTKL%=}D zNA25%<~LotG++9MBxQf7m5@{(4-)5yr;v2Y^aVK|3<*`qIhWYzjsX&$DKTGB*zC)8 znE=Id!lP8u;ZXZil63>tk;FDxOk7+FGATrkhYPMc`h%h7UJ2R=ox8rKs>-*CLszG- zm@4$)b(e{L1mTVyih?-OzcAxxgBYNb7eP1})AuWzFkU!_hHi;o<<7Q&Rp>p+xNs;U zugyyZg1kFRHpy#cE71eo4CMvw7LJf2ofYQdR|mR*JPHb~Bj=izb=*>sLv28e8_Ff? zn!OheNCAh$G8+gWXe_u@)fM8wfJ;_!DD<_*5loix;vEWLVpL0;VUICJXA$nWoJd`z z9;HL7879gMcQJ#}A1Q@$yAZ%zaMJD(mRn)|b{Yyd<-RT0?Awx4>zEEgmG)3e1de%~iibPd(iL?Bx| zkUFQWH;4f8F0bZR)`s?%%mhZF*T`v%L~cc7XYtc}^y3;}I4XQ3M7E>eSSf3hF6i4J zO$ORbCotjZTXZfV>vcv9p-2kfQBHVt!5J%k#MHVEL<>(8-Ek?5EtRtA#^rd8OrtT6 zvpGW%)VF?HX{f&-K32c%H8{>4ugtRs>Mn$h*e-ubiw5DarZ#k$k!6LZ^`Fu1-{8`sxsqiLjEpWpgV>09`V55$^d#yoMKL%WxAuX zP!g=z?0{Oo9Yo;i30deUc!7|SPT@j(x3d9sG-nXqmMjgSTB{;+pu0=T!E}XzO{udV ziCEIB_mS8sqQl+9-D27S=7X;gF)$6*L86NFI)qk5>z{=jj*zbI0cyJ^NjL5Ut1F}t zg6fJ`j$6ug4DHK&OD`39)N+Tlyuw^Ny_}8u+|67-#hpvwZHe4kycrHq6UD;iu{_GI z=sdL(K06-w4)j0x2>KCTEbESbEE zs!Gy4IQtUgr4?Qe4sIC&(>T1p60zt^A;ISRhQq)W4j!*B9^;Cl0=k4%vpmgxscRN$!A^OgJjTs|%iUD*t?^LsvICmH4KUZRE1BgyRH>~a zgQh)Mwrm=@EcFx#lQ}hoE;~XwZ^ToTqQlj|yKkiN-O4lq84oDr_>^Cu^%u)zdSM8t zw28=Yw{SQ#Av=htSHXJ;n@`H4`Ja(3*irt=Qx{XokdSaM5|*=d5`bOWdxJH&FC@9r z8xg*xUIdZKsHjn9?N!`IDnCL!m3g7U~F~ zdBd&L7UF*-4gqc&<_p#UdUjq2qQkh8;vuRYC6xgiX~|vyB}-rtL20aKwu_7bdslu_ z#4y_jN8&nlC{wNR3|a-JL-D-)MQd=VHNL)OI*VqpcW#FwgSes4j@7Hx#3DyV!41(? z?-)xig7Ww7uiPuY=t0e{9VcT!<-T8-z$EdtUTnxiZ97_cH@uYV&_D@n4-(W8P;y}v zl46@|Xi@ccqIy z<7)*`5}`<*+K(ARyCnwJ1iJAEO{BOW%SsC7>I|q^yKjAylUT7j3|?vvUlP`1VgCRV zo(3wo9pT(tq?TV$N?N<-5fwPS!oVw!5QCH}#Z+E;JWebl8fd*Hzc5mjQ@gkU-EhsT zsH8zjgn_kNF7dGt5PR7Q~(y*hNZDFmZ!+FbIn- z`-7-ivXqq2^8%aOLF*=%iKYQJ;RUBG(t++C-Xq(6BOG=&TX6vi3FX(+br0i$@OX?Y z(8e!AfJEGzzFn}2Zit4t4z-7Yq0~{~vd_3S1q`g}3R+t0tpWhFw5Zo0!Z?Ts(u{ub zi!$YyS}l38RB8e=@H)v>Y)~%+)jixi^=en^+`|wD1^gX(^%lit0474XEYI8re#wgJ z&}X7wEoJYQJDra-K=dT3$d_i;->h5CI?r2gA%9CSBcy=SIP>Jj4SPmA8Q_@{?ZN7tit` zZm>Ar%NLIjh`CCe5JeToh?y~k>Xt3P#7}mgG*!JybLfT$f`Zd2eo$MFxUmjCrN`+G zDt^$!q$&Ywx|e#iJ}v_R4#&rEk+mm5;fRozKdHC_9sq7up>XRQ%5_}9sT2k3I9<;D z#~_fesMg!cwmB!F^u>i~a6nv`Z4fIU(Zn=5fnF!nXtvc+8y)Jp`dL&-s9X05sT)F% zyPdU01^J1E3w!?nnCZA3rc(locELhwZCd0Ap}c1>UguV_1&33+#lCuA;wJP}POC46t~9ZkQWU zLB>K(maYnNe8E(qPmJaThXGLs(`@fnqGFccNTyrj>`xKAY)ZdY;F17`ECHMA3r{gS z(~>++(SXPt6M+{u9`I!phUwl$T(GnQ(a``d%S!}b{{SgESmAsFzqnSVp$~A$NGUZ2 zv0Hffg;_%FDZlIx5{J}dq76WRS)%fBREYjB}b9X=DP*N z8X|apSVjHH(}T7o4f%#F5Di$v@?>dX4JaA;oCD@sI}aZ*b=k3BMdWy-2!)@Ced1mZ zy3T>Ee6lVU;@kL@q$T9{gzLg}9qW_K?>Lv48j9Nmi35W^@)&rWB}Sd(?NeI2RMIh{ zO@-%j&XS;sNlOlx`q_Y*(>!Jv@jXiJyu;>Bg2kc$sF}TW9AmP%8iwhE+bTFBCHu+JRh3$LaQwj z&t1gt5?sB2gDsIeSkX$>7e0_lYx}gv8V1)escGEb?yJLL6&qmETd=C4dRU~1VrO{~ z6Za9SfL^yN%iZ@YW zvgBDU4T!ka1@j=CZ{-A}C)}!)tEgU?#%Yy&L%btA}i+eUw(_M0N2t)?;1j%06 zfePpYxJ@agP|t^Rq5CBSFJx|8@o5-B~8Lcr*=27N`Y?} z+`98Q3BYR~wEWs8m&cI;CQCRyw4112UqO#$lzh%z?9p%)uf(?%MDJmD)gJM*a zDVuTd0s@rOygDT%1RR-pDSQx-8snKuV0x78XlbLwQc$;c6b}2B(Ho7|JZT#whU=%= zD%dN9IU>gSWGOczfe_? zb|0vvQDbOi#s@Zx&UFaBSrF1` z(9d-g0+mO?&*UD-v|IU{QztJYMiI@ZHHv4dp_aJiWgswzqgQtt~SgtGzck z1TASE=$F++-5R0Iaj>hh%Pt(i@}bY>CObhM4D>*36ElLM6QVT?SDcMw?k~<@sC32BG zMOlBy8CF+hR@m6G<4my->tWaLqiO-IXlS|4QYD{=jY?oZYpf4azp22=U{*eF2*q@i zOQKks!nz$Nh#Hbu#A_@Q=rRDe6O@&#Baa}KjBiLbE(im&K`YBG@MtMl%nBU9worR< zFTA(7pHc8vNVsjjeZ-qWqwtQG7!0L@@o}0eD}X=Z7$xj~S5c{HO7-1&ng+x~A2PnU ztJ?XNn0j>uZdgwhAFVPlL2QKarT%7it!nbtENh9C2`oX2cN@9|Wu6NUE{HImpQ3Pu zFbcJIoq_afA!mXsXtid(No1GGG-wY(ekXYpUV1Q16&DM)$r??1vu-(>=?Iijo=9xd zV#{aA+*&ntR~0JJQg;X<>}MfGTaX|DGr@_?cn%n0S zk1OH?ynL`U@_S$u#pIPp@<#MB*CPJIAle9=HRb>VUSn6#kZ+MHFdf3mYfv0&E~;r^ zsA$v4YZ}u)l!(SCpzG%OH|`1roxbMM(Op0+s9#YlEv7=N#J%$N|-P8r_w+d1Q5Hv5^%(TwgUxKd_`Bi^(xt z9cu0rAHoI{pj2B#Xm$&}&vd~l+uEVsDMh959m8x9LW}%M%1QEA1w5;vzqtP8xv)J( z7*2s5vKMSz=U5dqf+kaf1>kZ^m=XO-l9a=8TR3{)gp;ai2^5lP*o+Y$J1X-x#Sv?Ak$r-4kt$fWQtFkZ;P-*V@mPEGX{ldPFiF`F&qqMg@2H0 z1BbkbDXMyD{E){^gV_QyxFQcTFI3pV1M%)#@H-S=8!fQ{vG)7c5LzEG)nh{O?T=wa zJ<6e#Krl_&#xk6}?lnbjBWju+B9b=VjA+U;TOXXb%c$G+KPn}GVavmC-omDF90Sp` zg)oUr`z2H@Tf-}rLzTGlx0#5Sl#whxUVg3)Yw(&E!2bX+5z0}~<^c+n34nrMMa)#UZxkxoOBOaB@IcXSq{771I@vw%>7Td>@^I-9wm~9BoTFSxUYK3;>Ez2pI2P zVFJNvdaS=>s24Hnb0cEW^DZGZXf<9Sq#gxr5yT4mok3mq9c$=Zy;gfjs~PY!RBghc zI?}1_2d@Wk^3ZZaZ@_gDDLf|-4BH>P9A?^n;Evp(eBP@Jm?TVB6Y6mRaaRr^RKXe- z@dOI$%U~eTw8QRdUvl=!ro?aV&-MucgD41$!SjtIm1}CmqO31c5@Mm^Q(UkW*vP7u4gfp=^t&3r)54 z6i2z}aaSgkmcqST)HqWsyYoG3fSWWIHw4%`1XFnmnj9@>Y^zr86vf>sUnX#7Xrl>Y zOQgE8k(nbvYXX7{g0xR0K(H)%L^=k9rY=AukY7-JEs5lX!=bal;)}~h--b5>QaB}| zvymh(hz~%!L(p=uX~nwK>&zjqqz}=iGos4{erI9^s1=tK2Lo@^rc70+eA@0{%ttb1 zR6HAME0XiNr5RL%uH17bI%VF&mFi|x_^596>fq8YKZvLtKzF!`(%_tf$B0Cz-o-t@ zmo$)8;?5;_AcH-|vzi=EE2Q9whE9s8eLw(t>dxUcD^l?vE^_2x6Qe5Unidcb;*Mz_FWi+qk@@NF`Ndgw3Y?pZEav`@H*CzUK{80-m!Y1g(_>NO~PUjG0?AFiH~ zF=qg=?ALyy0sAjX`VUhUH3oj?$W#zGAm`?7l<>;TR}3%Hf+Ic(;)kwtz~(dIYE(SuBHLb^c|UZ(%&ABy_|LM0)&7Arw^)Tttr;O1x&j zm>j50C_u}M+S5HeF<bybAv~zJl#;488d<^@c z5hBV9v9s-!)Te38X0OyLQiF-I8~B&wgRfue9SV(!IUUeK3vflWpgXq9%;O(Kq7llk zVhZbl97LOVqo$SSP)n6ms1qU?4t1Q@6KPZ0O3NKnhCV6U7{jWb4yB40bIcqo`Uw#g z0E2$grQ$6EUzv3ZRN~=8QO9s-x9TPZwmxBFcV7_D2}SaJOFu=n8huK@Bw*jvY)>S* zeyS1yS}D|Sa8ch(&P@<8Ys3VBHb4fon*gKOD<8-|#_*>Ker^c#SRl3panhkST5B)? zzL|Idj{BEKz0S&dHKL9PBr4BA*kewH4S0qw&EHT%YV#H)*g=5Ev}uCjMNs=9>=y;? zyd&Af1IKd~hOf+g%k?PBWCCiS@dW3hnRA_Kwdy}=Q?Vf3@Epnuhn!cBzGX`&P&o8T zMfPQ;z9EjaHE~A+!x7rPCHnbyQ-FqXW{#!v%|#w6LVznb#HFC#0$c5VRZER(V#Z)1 z9wK49XH26~zH1-?s5q#r3U7y~v;}fc8Auny4P0J+WtDm^0rJggRHMr{Iz|9$&`vap zX2t<`%JLvx1IAQMvF(bk^Ugy8z}Mh46lTs(5O#q4#dMbX(S$VFP4V0`tPP3J+_+Z4 zb5V$j`7uUN1YNGe8qiQ5xP_`*G{fdyVETGFGenKpzTqQcf_s3IL5ME)Pq=He33QMm zf0QgKb&Yu?#3O^jFDl<~!Zrxx`vY4tp-FiWho-HjEgWZ8 z%vI|s<#Nq2eOxE!3RPi8aq+0H+spMIkQ_Rcs8B2BS2z)pS^G_T=Zb!qfL&Nb$C#c& zznMd+MLU26;AJ9il$?nm4^enjEty7`;Mh-a4okskps8y@6^!c~iiIXnOjs`1qr*G? zAdgx{m?3F7IzqH|IAMTkr_OnlN^S=bQ0TfI=Pth7lCJ*%=wqpLzKDF0aIg4_wH|3; zB&)jh3u)DQmtUvHs01B5mcnEz*t+?Qe;%Ulc375JJ!t`pmCRzXD|R5dx7mid4QE|M zn;zdH!lMJbjT953Es#xAL;^cQP5M9(@bfhka4vpGgb!Hhi$=6;s5uj8SU}XRa0q%p z1F#eoHBE~EMU0Jt+$#&ov@dShNGe(-gXollpbD`{eM*(FZEtWb3WJFIl-gDePcS<| z3)$u{VvB=Y3iKc=wpHzEdWT)rcNc=Ww6`c0Wt88DI^c$_ATD^5FPnrrB~AWi)WNER z9}xJsRmeK`3N$)EOwN@Oxyrs^yAFXW3XrF3;#gg8<~Ebf*m2RUxm3tJ5kY3~{{R># zLQ(1lZ)Xlg;1wRyz+49e;hFYIFjri_*zI+&IOtvzsLeN1I!aZ6%&3^td@u{a9=t^h zaZqSmZm5jp*%I+Q`1ABMWx7H3XTd zzL@JrQ^W+1$&ZM)Av>+naaOX8V#x%NvFK}R)Q8T~#1q9t^C>Lth4 zh=D&5;%<0&Vk;Z35jON9^em#K(-0x#hcQhfZZvj8V}4t0_?8NRf7G*!cBEUkFvM`b zaSnr-X~d$A0vQsk$r*+yer0&1SQwL$%}!5JmYj^{2NZJ(H9%nQ7HPV2_sM ztW^4lnU4>dK)c{)3BDty(ffeVsbeZjw@ggfS{=baX~waunz#xhK$F#*yX7u3?}uI?aU@G z#kiMZelcsr+0`2>hr~{)Sd)af23baG!3tGgK*76KdMLP!& z-8Ef1pYP6T6xl__Zi{ItUxQ$&YfJvbPzj2pXeCv__YVkiiXDxKcKdrZzXssJuurY2mf!IF+<&b~?D92vl~I z+Z+T&K1($M+l03YHGTSz{Zh5t!51O`^peyFRd%wY$g`vU+h8mPG= z%c!D)r-*FLSNxh66`&bfDTlxi)esPz2H*Te1;?L2f{=&B~$xu~6f8tce z)hIl*)Cf`qo7-1V!)d=BqgT*!JAeXPvb&X(CMPlSczzz>$&J78N9On|`zySG0M#(m zI*lGxSE+Jx{16PfR+TV$p%wJ7gV+dL`XT^D(5i#HKA}0W0@nK`5A=9%;Svsvfd{+g zbraw=(m-qFP`|j)J=zr%d;wrCyiUX}8kGkzl@NUF2dIjiZE#8*h|F*_zT9nV(92Ze zhNP!waZ0B02q`yL%)Sar7~`Z>>~;HyuW8*TZ|+~pw^)}Ny4AF~v_TPi_?bxel9jtY zP_8uuDPnnNqSOv^K{M(KQ5ct`Ag>28>>TkMMsOl~ge)Uf5UMX7BGvRTmAZUTmNLbF za-)yn#F`O@hy~m~Nag|+-GVlLh0_DHQe9~D#ipqD6;Ws?m??vbCnCaBAZo9+3coJE z^JhQ%4n4k$R@&DN2q|6El~^Oq#RUKvtmXu3VO|I^XcgFVF*uf9UzqQ6Ea8Dl4Iaqy z=sxjcRHnGBPSxLI030n%^)rvhQp8Yc<|IxORoUj{X0gFC2k?~~hZh`1u_Xke1=1Ej zm_w|E^G!mRc$;6`;;;w;J-4e71M7uzi|U%Dc^7u zDq3nWfWh#LBVHhZR+9=0Yuu&TgR*YBTRqNb3`U@ydrYxV3O=HPZuJu4Fx;ELYm1y$=JV1Bz1UVcg;IK;h0vctB zw#wumVrB^SJce}f^(tIj#R54C`cpI~5(ihG2lhMF4AKIH_rFl$NA?2u#A;f$i+r)G z6@FlYq2QLU()5dNfo6j6u9(JuQAp#I{{V;pzP>StYYL9>D*~^We{veIJ|$WLiEHFz z1qb9Q{4ro}t3r{~4n>GC9f}x_y4ziX2=*!pQoTb3k4C_MEd@vH{cBH%5!74r2=AVy z?3D}h89}vg5%{S?D0#OY5C!EtP0(WE`Vp?=hv1ZAST>(rbq_Tz+F0W+CBM(X!vg!L=c}{2K9HOMSo>#bov} z2}XWR%0iA!s%rp{j9=z?sbhVT^QFjj16=8SKt!<|J*OnVkc=73*9&Sl4SpXH8gv81 zO3()b`xGs>X-^CpJuiVK(O1NzHSvli0&lEDn8rdcjwVx?fdTTFORHtc)Y zYoUsZML9*`xB{{jtPQ#w0WH~iRHh6tf|T-5w7N4DTC^J#k?1E#6qJCPr~$C}3*nL>2g!i|R3C+YX~6 z!NhV6n+6*RQ~BmTS)+W!0|dBqoK1s7r<4@9mMTnJbM-zCG6to)#ZkwZiG#VJDd5?* zX&o%{hpJbrfOh=)k9UBYzcG+QuIF|BOBG21Q1J!f0HN=Vh|nHrv^@S5Z^Ub;Cq%RN zY!UrYoOH~Bb*TK!IJah%!7dnV2<{6#y~6(N47jX7YpjIAHqXvQ z7FBNyWMx#Ap8*S9%7ySj_?3O-t`O1OB3D%p5t6=*&9D<{IsQ~VzDsB~#S>ok7kzQItW;xRXGALLn?DyYU}*>cRKKV6yjB z^Rk#nb}!KaADb|6BcF29sVb`-a3w+zmtD-`S()*-mtwKdEfihMmdBxv^uC&dwId8< ztShnrsRxG_<{(fBlQp)Nm$2%3@UxCJPa#JILMZ;B@ZyW zf%#=IPGRa*s#A{+Y-WYDBSjFp*bthp9Lga#ELrAm z#5#9Ji-Cm%#j~qM6+KdmziiT22MwjCgEBgitE*vVwp*ne;LG_D)V#z%j>J%P)pSkOLYlC-y2a z&zP*Ys5&lx638XMVrOILl+E{#FPTPEyrY&jx#!5RT5{6nU5miB;nZ9Pv&#;jBWI>@ zF3_kJPf%jDRlQ}#7Q&C*2n(*V)LP`FF2s*3d_}EKZn};wJA-Su5{mZ`0L)~dPPIJu zE=%7c?AH#uFQO91I<40bF4b9b>i8iqsO}yY#3VvO$V^M6oud=^Mv)LE2U|B*pl4;j zGT#@Hy_$F;tYAVCpLZhul>}6;(M6 zaHzYOS5&AJ*DOi{$*W?$EKOK#Qp&`VMacahkc8n#r3&&K+bA)uV&>IV&jcmquMaG& zNonqmqMCTM5p8tBJu+}(Vhm1qr-h;4}K1SCTZ zS;h6z-+=BCFNtXU@emP)A7y!2eMAoG!bgycrPLO7ts6)J%T|E(9k*+12dQ-|BWfeg z)2l*z^AH7NZZg)76!%fd6|6ijiO&iNYhMry{plk95B4`g`8QAmdP70;JaJ;a(Fjzr z1R9xG4bl~pjrR#r@a8=f-Mh1yQRNUe#<8~DEf!UEa^V3+hZ|Dx!8#13bzN$9V*rzN z3HyXmm{OC}ykW+N@qw$t(P!`dOjuywGUa?!P<_Z#>zPE95rAvdc}6Ae9w5w~${E6Y zhhE!-pA;Xnk%EH4r>hmeiidz^N_i-NKl2sykji=~bM9Kd9B3j(3UAyEaB=#T{$L(u zv#Nc2k2gCavmYPv1l+rM<|2iQ31jgS2b`^YnL9kLWf^=Pewleh8SZTv#56Asmo9Tbd%0QiXfUVM=4r;_1~Ce|hq7cs~l$Q(+bCQkZ5P_#LhiJ;(=g3Mj1 zb%?v_JY{QY@IUT5&IX_RZAeR6w-&HligbT*MXFuu9kXMAg@tc6`c(K;a?wTihHr zUoA^~CEEn68hpi)i)YM6u_*;Z?j(cKkW$t2$q?Kf1Vo3bG+if%gtrY8^{n!c(N*xK ztsOj)h+0^2Z#7|^zYHO?`c303M+I);f>51^MhOkPk9NETErSuOmIVu)}h`I~U5 zLW$&*Jd|Y{eWjH5i-iYmb1bIsn#aM3Si!kb71{xD9`eaazjY{P{Y)E*ODJ?wGBtlW z6>z?#xHfGblyGVQqmpH2p;5auy7dwahQS4ztB4atwK&*PtXeyd3&7uq16Nw?dz>Hx zMH0}iAZzsxseV;DX&4mxzf#Mh&Qpre|ucHyg*>9sBoFXP+=3~cH#%7HE6*ee|YP5BF@IFQi=yf4iF_(l=L7`s)38r zqh-+r^jB-#R3`S!l+g7p1lPC3E>g$tA;77a(20rwKxZ=eh!<-x8G#Lt*%r58a85`H zn}_o^jt|L)73M}exK|LvUX@aVz_I-xvY;5$RiJsUW-`z6m2$1?#1~#^vJhJ1b$l=Y zqou2)sBXK#?l+@{GQy2IirN{`D4!}F5(NS+mz8lB)h!&y&y~@fN~?oc>M81tkBHr@ zrOnKPlZaNjyY(u;XnqhpF_OLMukJc)N~UTa4Z>dA8>dQui5>vbX3sEe_|6<`r3Xi3 z!-oe*D0-7JHx2JjO}+GDd;>f=u{fN zGWgD^%fupU3`hL7M!=0H3$uYZj=mE=o{JvFbEG3`BD&SxOSD&qRV-QokuDg}!Uaa% zxF^}7Qc>jqBB1Q67;AE(OFI&Ak{cI;=ggy>6EDeylGyTj_#+~|kDHbWupdMxYhsDj z0Ql-jc`plya?R!vs^#%4>WcCJ$-bo@gtG;shH!Fz{NjmBq>c0hA)#L5IY? zi+pTd2ni#jDg%sxH@OY>7zsr*1~}Fcj_$kJ>JZhZbGRn%1c`X1m%{;(Z(d-U3q#*V zY#KIJ3&T7lUO)!Kq=)pan@m8_$#U*IG2$!M1r=0a%9gPS$3d!NHzQ+X1}B6th53DZ zfn)`}h`tNc=5TA`a8%b5K_CmWvDBsFcsUkGFHQ-8KyVCTQ3*0X<>t>4-U-qy=k{=k zOt&TB1}##$qI($)Z-~5AKy*826I40(H%Ci5sB4QAUvpV4FM8r$QY}g*G=P=?yj*7R zr0tBttJ$~`%u>NTbV568_#A`e$xC1x6~)Frjjj&~L{1LjhCweEhdfIQLYN=iBqK_D zh-MDKv0OAhW5)*S7T(AYOLcMF0Pdz{8%VC88PO@(a22)FHpm)$LGYH;2p49Iv&33G zkYXs=FEW@phP0uUa~Gp}K4TJf%O@cD2tf_m4zv*GIT1w@h;T1=rc_9I@mx+nKlh?r zwb*dNt`k9st>ct+7N95|Wsf0Y{-B4Tq0V`Zt%=a$FbbE3S`s7B!UqKan9AOu3*huk zvS^^n^MlZqXFFy-W}?+Qh~ER#9z{DI=Yj^1IXp$y4fSqBdIAi859)KShPvZeBX~h7 zd4*6LOl;!f?n0FajZMPnuQ3#D0uOPD9>E9zL_+#zizxsK+946mEI}~|VdU9jFO6L+ zbj<~Od_}gPZ1+fj6r*}PK`b77aza){+B~%^rMQ2X#jXpA1yu7Ca*G5{TcNZgE*h1AHq5l97@SKpA;sroL=`fWPu=4dS?j8AoS}9k| zMEN*i`XhnFM^pzETn5hS8I^S~dK_c0%E#1BxG)P#;UnR+dk7YdZgKS)3bv`o%srs# zT|uFuwt0*h79SGEmVq6rZjSwsv%Qws>Cw1934EG&c@1MP(>ERgWycDVgUizZRMP@w|SX zBH@|lAGqr_Xj8_q2CSFNEjB=8r@26w^wBU~wT0qZlwNy?01rpZQXpEhA?oc+v&^MT zT@E}!MNT*S5xU5)2_CU#x`7Uw)v=iS3kHn1omB++WhyQM!bHb{)$NG-?8F&HxqE`z zQMrXus?1p`2yt8y z%eFvzoP~EOk`JsZoAT}>{B;osIXuQM4IlEApzhmq2-QEKn^CFY5t1p!yPF^$2MiDn z({P+T2gJ9jy~Ua!J$im-=OQ$M3|iL-K|!`ljK@LN{lqN*3awc|OVbZAIKU0pscH`a zJogCBs3M$2U?w$7`;87flGiCOm$)K2UV{#h7MTgD-T8(DTE~A=bJDy#L;#_Uk#lRY zCF`$JsjT-IaB2g@S&uj7AC#-WVGMZ!i00B%;+0M8XLWb(7brMinVrWiMCdms_93kv z2MpGsZLiE%zR&}goP|2yHyq$1i|#ndnE8rQoau}4^$t8+QMTYHirvE79JLc>!AHS0E~RIDK)#@}1821A zJ#hlZxpocrWE@K3;Cx0ANX{3zQ&rUt$0j5bq^NRyN=i9(UL_#bB@&WIclM%V&;U9i zD!zzgEa_2FG^iz$*}1haVBu1O(JbZmJi-|1Z%c!rWpU~cHgs~-98&BeH1a&c9d7Kt zrw?P~nhrgY4R0il6x-VI3TUJQoOH62G-5)&+p_%lfn-CbxMCY)ZY~(;6rIjdt$e{t zOKHSzZiRP}mq-5q5-$c`q7hKi1=_N%nO%rje6pFy+mZDKEiu9zYkfcpIm(xfAoB4j zQF=a@EqV*YrgcD%l}TrU26Lf2=$3X$YrgXxVR?0%%tfhrp~pS*7&YSXg2_~z+)+@W z@Ww#SUl0BW3K!12=_J=aM74!X zWw40KNX0_E;s~T@9^+QUHRc=3pb!gCw%2j;!Dah|z_qt7w9am9S=x*RO{cFhdb!>A z03wYfFqg{bNu7vI)2YnF%VMG5sM8MD-4k^z#q|W0<6ffPZkJcg6S%v#WHf{jg{^UV ziXIB6ZP>tjV_5_YzVsGy^#lP6Y44)|0coSS?;3vNm6w-LS^}}-!vs)MeBfNKAbE{r zcphVsDhl+3mq^+5FUb5$0;X245gPK3BO-7}Yl=rmhbVrfYz7|*5B3{88U7{ADb;<) zcPadki{{9CBRQ$BaJWSx%EZ_L_5xBtCXMOIB8HU)&!N zRVllCPA#s*p(#Z;@Iavtq9x!QA2N*9QQ8{2hnk1#|e!?DrP`krSbDk@4|B}{#Dsij&6iDJ|W0wE%dK4Lp&5J(Z_ z;>!a@lc~Z)=Y|S}s}6`zIy1x6ru;lVlY*TeF!-ug#`7UPo~5lT(VwOp1#2E6w4$YW z^!kOtW)+DRO`K0st5sE~wAWT8LisR-x;j0P$)}6z;GizVNg8fPa;7*enL@lWkSz<; zs*z1OcT%*L zu%;O6O+Qgj92Mb?&tIA)`2o-#9q?S@4} zv-U(Z)zigGNU-h(hj&>rM^W(01>HV+i%88NyaFhpR_%+*YDsBtPpyby z=Msg}y}{-CjM{a6WfZFz-Z+&3`{t#%u-5S@x?W}&90Tf88R3*#;|?uw#UxWrcj1Fc z6TlBlThph&tstyg%3_mIr&k}jG*k@pgA%Y-4^pBV$5kvKgOr01X{U*F7jgt@=fMVA zs2BAW>7*wcDD_1ik5kG;Ks2&A(Ke3d{{RPMWd_G()YKv3A_I1qouQbZ?CvgA0%N|E z3PAj#ztka0?p^wfi%UydSQlip_f2nPx~ZwKMc;_iFnO1~FQWr3vEmt^8u13(71a)_ zSN@Fit<`=Q0Rpu3EG0IU(?FZV5QVLCHbas%2e@-5nNc2=zyawj3<5sNBs z0Rzg`M*zB3K&H-BMMXtT_?D8DOd4AqCu{vfD_ygvk}%TvyvJaRr<7=a5Y=iFv$YO# zp-C0)RCPK!_mCvC5f5`+j{B2H9uD)A|&wh7E^^uVD2t<`{w zMv<~O>M5M6fa7h$nn$Y4%TX!$<^mG9SOr~`*~-GEk3*@98qEr>{fw`2y!nmmxdbni7qoOT9cO2 zF{B@mX8;9!H67ZX_kjC=Fy$G`U}D`|?DpYf8mMW-^9@z>oQFF`Dup9tvz_xOW616B z%c7KY@eGwlc!8;0T}uVaAfcjNz$7creMV)wvSF$gJjKd$Y~msY#S9et7TrZMN%<1b zu!|N1iCxPy(B0}NbO~=pz&FaCBBra>@hwmN5h)jYhhi4}Mhn#g;yZny`}xF z-zkGbi^#y0Tc~jy&92-&V~0`m+#4l=c!gbNHdM!0l8zQMjCKpi!^Q;Cc>9NWARFaR zQG&MS(t)+^3>48{F*#~%Yup^hY>TI&8ifaJQB;ma5G%XXTTb*o4k3mCOYDK99FGue zhW_AEvs2|#h~g%3I6zaK5ULAo)P;+d#Hp8g7|j4NWz=j_0&JBBfl)XtCU2R6mRus7 zxHUNzrABe*x0p0-DcVfMRR|wgU5o5HVUHATD7Q6uF<5j^F_+c6pZ;nWo&6b$%B`W+z1{|O6 z5-${BE8BZvqpU17u=#MpGF|2);tuL(OR`;w?o!(v<|hv@S!r7yCGfX35f_!y4~}tU z5vM%t4*@$gZAQ6b^VHc>dh#-`!A0dOKT)cWBCwR9N8ssU zRXCjY0M}8yN~O36F|dwzDALn*vN_ut!e$j~nM_dz`KeG`%MdgP+w};Fu${y)>0(1G z!Z=X`0Ub(?A4b=^hJ?9u*^1@eu_(3Kl1Ebs@sd3oE6@uP$&RFrBGq(m(2&Fn8rKD(r@&G}GVapZW z^9zQJ6QOHJB9%kwV}Mo%faX|&$aF|ob@iU5aK$JOQlNzHDbRm(KzNbK*#5&&(qP6} zpmk}K?0HbEfLiz8)DQ-xD#!&-1nJ!;cEO>)M0ZuF? zRa@``G~ixD=7Oa@dy03L*BAx3v0Mzpr_4TdjSf#U&bviR(l*@dw<&;{ad6jsnt7Fz zI;-G?Xff5e>5L<_vEd^opTCd*g4^@zA%e?Z zV4b(J<1}_B6667S3iT@cN*-!)RG|8Tx>f|X_(AB5Afo{=EC_h!Ft&5Pb~gE-Lhb!N4a;{{Z2TA+P8* zSPCP!p;)}AoB=&!;Gqwjj8tJ?%vvQHs*Rx4Z!oDskH46XZdlk9MRHd-MGHKFDo^pGN({`i-iae#WJr()%7f_b;YKB7@{j7`N$6n0qB~4 zm{*7pxQ7O${of373!*v1QjY-GP6Aw1lUBMEySGtd~nFdf` z61bPIWV%>HTYI@_XsRMSupewuOG5o^MrS8vQnX&Ifqz*+Ys=&O%Vwci_NXxW zI07~I7TlI&ioYZ^miV>plweWjUk(HAP_TqgQpuvXSRgE4346sKjw2Nds`%M+;LiL* zn#P6oE~7#xp_(uiJ4i}^BK^XnY#YB&`;GbT3L0|tC{%Kzz-e)FT^*Mv8b@0|gAj`% zS1=JmXkwAC4x(M($u?NndL>~5MaDLc9}_u}qF4cD*QsWfZzd3HlPhft9Znw>AKcFl z3ECXXPYEg12MRaWxmoHo_Dhtzom3R7ae+$qH!l5ZgXCaR7PavNLdOXj*C&XMY~(Cu zSlYMT=6l+FM);m$jutRodm5tG{6uuJnUx=jbmAiIy<4~h5zyi~SV9XxImSc_%P+wk zo8}IPm{KF9OVw7+K1@Rv6Qp4YjZ#MLs=3X?3+V~D619oC}p}VVB-0X z$4F%1+e7Lu`!>>=V5}hG`iDt)J0G7QNoh%LON{oC8t}k{;9{mIX$OyMVr9~`5)*<~ zm?E1MxMZqU>(tALR;6OoZ^lXrK(J+1qSPO9>VN_6x|OJA^DGJ=ttmx7d}M5jy?d3S2yQM7P4gHagwu8uQV;i> z_9ZJ6F7EHSS8yUY4t>EAE&D~<2U}}jsEfJ7k>)x=vrmXE$i4PQGswll!kbNNjZd-y6IsrXr!m%j0S}~IV%^;wg|xFsHQb(+}sSHA=)+>xTiqGLFycdR5wi?a zT}t8>tL`uBK$SKI2Z%(ZJl4vi@Nb47b}W5FmE8~^rLgvfEI)iqAws9cGLW2s>NF=0 z1R-|gL(C|xF>$LPH$LD9Qm-H=Upd?a0ct%X&0GVXBep8g^EujOzcCuML#mYqfi@sm zr@>O~wQy?I!?Q?41lnL+KiRB)QNm)!;vkX2iwBud9pHJ4=4lMEsM|78Ru_`k!j`h8 zXXEDt3U&|VC^ZktL2!G{V95p56I`pW;Eoz;2rAdaqb&ifLJ)MoXylZ1Ra(9G9^zf$ z@*s)8aDYV+MD2IEZX+b~+~~%N!~FqIw^N9gKE^qhBK(lwavxOyAT3z;IYx*70EP)n zv>JFWQqw6tkd+`QR<0vN0NC6`1?(q=4N4#`TmeV2d09~$TjG0`rq$5?qBU#mL2R|d z?r#@;!pXGi1d_Jf8=M)=6AK|W#q3Jf+EXaFmzAXPq0b=30YpaqLExx66p)VwH$s(4 zFfLL;z}aIc%y+km;CNIr0oWyqi6yxo5sC&|a&D?i7lHX&6YdqzQ1lO(Y|EihajxPDl$*068_}Yi@dzbBJ|jWS-9uod zqSv^b@-$n7@))4kOZg!+wJ}I}C78p23zor?S1ccMg={*%7YE;WO<%-X#IdpvUXi{c z`B$iSI0+-+gKs%puGS3%sP!9BdqPje@XVTjU`QZ_--=Xh%Y1CUJATl39gk~Zg#Q3q zMywjJfX%zNCJI5#UBN+nrm%BIE566-H720O3Z^^bo2A-jdWFm|Hjc62h#S|Pv%i;V za<;J`JtQDJATx^ytS-ioYVObK1eCOnbaQX{mK{og;!`mzGNnkOh1^g#UP!G?C%;nj zaQJ0A9+bAFgWEP~Cx%&DTRPsNTn7c}<(c)5h9=-^SW{Z43DwprqF)nPnGn3WU?P{> z++jIy-N6@7E&>vy*Kkw<2cJx=BpMX*MF-Rx4PadwQu)929RmT@UP@Wea|rNT1E>B< znjB9ra_mdNq2{6uqc6ZkDv43>oJ&!n7u>8*1ww*~sX`BnEp*+}62%(pOZrGFtp#>f zK*oWt>J`bQL2yk`m&4*KoFF~TdevNLwo5RNYm8TB>*81z6@5yiiFC$_glW$aK(1eC zCo7`r&La&<(0CR*c*|Wuz;?&EVG0+8Fa8mX5kvvat8KsA;uGr;d(1IL*Poh#)R_(` zAiTYmWZi{x1RF!33C;JcDw5QyTzK0ngN4n!A}h&$K;wIsDA6}Mat?>2`q-To-K%|V zz$-m(kcpp+QGZWW>Qw7eKF)|iY7`wp=nE`USEb{aWd{xL_?oP=5vyPhpg9CY<$7nt zuoTe6AW2j?`z6vEo=B(ifOYc$cXg5W?5K3O**!zC?#MvgV;=YKFW`zvMgfIojQgP02~oTGAK9_n?knyMRncuDAhsc4)lV6_?(qu6avF^+WEQN zR*oZ;uL?C{<3UroS=S5vj(lYkcDCV%n|3M}*zoC+bvB7k9XWlVbtXh?2&nw(UpO$P=4lAFfCbCZqXrQpFZ@iqVY5_&Vm2u7eLTOrp z`DppS-%%}*CWg=s=SP}^@qMPOjR1*xV^^?imeux0E2Alm*izK0*Ak@?IUg~(YVCHx zekH&f*!BU#+%99YraA*%%HUN zIhJ{aM=MjAZbj*r9{r+I3MhG#2wTlfjHqF?f18#bi(zVkT5#XXe@v7mdTgigzWafn zReAC>4zuE-w1w3na^wizy>ZMQR_@1|Kocn}Rc5#~+X}*T8qo7b`j|3O3b-N7f#4mo zGqA0KYDDBEf^Q5aNH{2$RP|S{xcpE6nkurrdGQ5^3zxCq2kP9q{0LDXirc0tBzq+{*qI$&`eL|RK1xFC@j4j2&| z6S56!s6zsX+r{%P&@kWuN)MWiu)ryBbfMkCSd-VeW>{)U4&eSGHGY9n7p0`V_DW!p z<1u)O1LAY`nD@f@36uEw4q=D4gCT?lRV{}`y{mX_`6>ICFrEN=gb+y?*e=71`Iw%% zl)2@C!Q3ELH;=Yjgee$3knJdiZ;k8Jx(oNg@hKHXytsjT&cTG%faQ*$^%sv&asqI7 zEb1>%Zj^`IMI=JXKpbo<#P zU>9;hRGR$igBmI=B#6gtwlzf!#Tfx+T4B2xS@ zLZw}}5DaF;(+!f1+zvlHekB0|NkO&k!|ogzWf!=>;9>cO6XRwfVRJN zsq3OVShDG2*45}GRB{T%`6)7qh=a;BuULHXAD*me^#%vTeRJC8-f9UoJl@g})K*L@ z`ER-t>(a6zanA!}OELHkHckOPZ#v;msnugo~E2zO12g6`N|BzKiq zDvDhSff^1#K;(0^l_-gM)#sEiur~M~7*I3}+Kxh&C|THcI0m)mD6xg8gQIWSYtJ%* zxxp6_R;|cs%HxPm(ryOSrJk|K)jdHd!$z#8)fa>k{gM>Ra$#oJw^f#?6#x`~lonC! zRWdtOuD9AR*Ivi~^Fq<%kb~FPiC|=|dx$T4aQy>d$!@H%;)23!T|0R-7vdYjHsj}7 zi{ap@@RQ-?R=g7ggqPN@#3gRuSGd3Co9w4(p=>vJN!V#P~Ddl!8b`Ect zzVW&-Q)8RYTuW@GfF=9{r-bx>j!SnusJ8fDF;z~)?0n+zgwqG&5H9J|qy;_`ElKT) zFn*ZGfKM+l5W&o72N)6JY_j4Hauf`VJ?ZZcOw)1`6>`&<1ZB4ot`^#^#sZDC0HXQt zo_-;z4?tAD6X&SkSc1+3@6*QTF>aC>M2*o)s=Vbpf(9ahV6|5*dnXGdlV?R5F8Fu_ zM@mtJ1+b!nd@QFjw_#8faYhGdg+Q(%0IghYa4cZgB?QY3Lu^x>61TxnoLdcOO*mX= zQ)qxnj1&T@mCaQ92?qlNf}Gwf%i@ls3e;J??${$G9J|ny({x;Bt?F171Lwbqwg-ZN z$T6GiVmKvNe|oFqRpzFgAk#YdCFtrFN+o=0(dr=IgqWQk!}Mr0tE~nlwI`;S%tcQqhCrq28cpcCIDJukj`R=$jI|Rd3wx z;Yu;;(dV?Pny*G!0l=>?*3^#yW030&Wf-~cZK z*eRUcY&8kOy^_>vZieMf8s7B-Vq4^t9aHWdO@8AQlyPxpupUx)6NyFLSJccEe;(zd zKyQ7;BKgdhAbE~YNWp_PqbsRLHinQ`ZBV&kEMDcnhR7Q1@BRHsh$U5r^jBWv!B=e{ z7aBM8#7hkp^1>rcCrqK{qblbO^%P-jZ5Y=P9e@J#0b>c(rpAp5Wr=MoKuZu*wFI&o zhf!)2D@ku`tOy>#2PdNq6LFt6C|S z0Um2_?RK7HNF&s?CaYVbs426RV1Z>%E$^pMfR~o7N`EjHQ53_wxb|!jU^b*JvcDG* zR;GTPpSeUQAVS@m_ix+_;6VjZ@zmv$@yGqdOhhWH{`r)@R9pKm9jRAuUOS0W!w&op z`?zjwN7sUN{$QFYp-!RKREMQ`J0Mx1yB3k~oz7t#T+_l$po&+BxG#;~AgLhOrxH6a z3%J^%+~|GEcq)U;3xKJ)F9~Vn$)k2SX*|GT;D=9gmr82m^9liMDnZ6HA55^yqtrJz z^HDe--!L(XdN_`y3DivAe&sNUSTBT}5E~Y3ejo;%L`64|0K2RBjU}x-5LSn!60vPx zn2_6tWK;|!OS)6#$-*g3$xzv1Alh;GfQC)%BX2P_#SkDd2#WJ}*NCSIM_MN}2QIzfsL34!|`6Ag(tpETbyuFvm38&D!uHkP&LLhNDqd@M=rqq_MNL z0@%^Y$Epezwh9G-sC@CbFyo8Rff;J0DuvPmYDERm5vf4f6AD#T9+&|@EOLOO$=Zj( zY_z(9X%_8(X#gMucoei(MP-Iul(F?Xr^#xN_R&5_9Wbh-Fy9Sce9M)m3-fqubHsh< zOj8v{Sp?-uFP`Qo041w~&}FRa4Rx80yJEUqGH;a@`ez;GcQTzHeK}m07qdH@jYfm=><1LZC{9r-xw?l7SOqn0$S$W_pzP#2s%F#C}08DY#ReZa<1(m6GFzN z6wRwvc#mS2%qrtvA#E)%7L~6JM)7<Lg(0eaUJ z5=}~!pe$SzEEkPJym&l;qOLmCja$gy6!veglABW5X0 zrL^_Dm3XM-0bo;w<&D=rGhqSZN(jEp3gei(RO!}OBUX;=+e4MkAdewJ>F|1^eEx@e zH&uy1y?^8`frG$!j=_zz*WwC%pruI-;W2jrSPukIDg}oC@AUjbfMHeVKgaG=`3QgS znPD8LECHqa*b)WX>8t+$zNc#&a;qlWB?lm!e2Mt?DFOvv7yh}}fp!m{iQ`b@dV|8! z#?9_hcCvp=!+jQ#zoZs{o=ChPEN;w*6ALA^VvDc~o3H*)d1i4Wu@62dW z)k;-6^}{-e@Dq_%zlfL4R^&u6{>)Q;R}>Ju%c_RUAa1`%G&Zw>=007#Frk7pyq_T% z(La&!>BJWIckwr1K8VoYvi1&pGfmq@>vtvfRM=ryU5fdzmqgwX=;ZrfHH^wk zY2`bEZX&N^R`zqpM^I}*`!hpD;d^GHP!|hDl~fQfH}v78!IBCBQ036qJbBy37d0RI zt9%6Vu`TGtKq-TXQ38$E8~*@^ zuWpKXvHt)v`in`wu_!2d)70dLAGl077V32@mgAN?B((l9V~%yw26j4jMyCa%p#W0~ ziAQQ71OEWPPLtA)?SyNm2rNro_IRH(cE)Kd>4e&la;Dn>vRUU+N=b?+~ildZFcoNFNKjUy@ zsBi&HsMPd@+s;p}k=LlPtob$8nRIE)kLlPI0A;4lzdY;lET+>tC0e?LT6Pc#KnGFE zvgrwB+HuH>;V2Ra$}|W;66~joh=eP4yU4+yr9txnL~e;tLqdfgF&d|kX+GjK-5>A& z0OVUe(m!PCBkW7%8gxyF{kDhnQ_S68`Qlx|%|^G*EQr14YnwYYPGG z%njY$c$~}b`G~jgAf+0PI1F=O)Sz5PsJjArCL`0#6b^-PEPjaE()w-}f@5Cd0Exij z8$9uF^eOr4+XQm$<$oX^TpIbGHXg7akY+?w&1K7V#NyBzBU60VzbDtlrG5V2H<;+ z5T5!=Wuiq`6P_y`NcF`RRIizC0QVNkQo@e>K@dFUKRnGuxvTuh*k{od69ai`@fe{T zqJb!IoQ^}89k7L^KJfD^*APA-!zK=;7$emmv{&J8MVy2nc~sj#o~j*-#Kj-+4uE+Y zJ|ndVMh4=Jv(0z@AQng<*VJy4O0CfqAlCi)mTDr`<;3$uM0NEKqySpQVF?{rX}=MR zCAj4o7rQDNId0v;$h0q*5S7o&rFr%mXL5VX4&7%~)i;m=G#64%T~uy}*Ef4B+_1jRut2EK-~%|NIs zkm+ddH(knDz6i>Ik50O%#cWYu5fD_OnAd~M0RSz^cc>r{&~fRM+H7x{1D1{B2zM)m zN=8B)Kg1?W{{RTm&*OwNK@5s>cY_H*-@gz$AYd_mXYE2{aiC&iQq=|YKv6h$M#|%M zTxj68mMK|ZP)e|Wh=izpKwg!XvWZ)>nv8brOnpq%L;!L?jlUYN7x=ljV;82+`II3I z?wS6XP1(hIr~d$83WwOqgNs6ZC5=pnKN58lC4b|*XOjjhv-t)I-tbusK5U zYb4?5axX?~VRU6gWn*t-WiL!+ZfA68F(5NB zG&eRrJ_>Vma%Ev{3V59Dy?K07$F(>TQXkJHO3fhz-G5e z9Bi-wCxC2YNXUlMEF>f;WNVf#khWQ9@)BW4Vn|YGlb1FNFT7@hq>0HZ&GJ$nv?a7j zu=G7My0T3O@AbXU@AuF5`y|fHneCjpGv}N+GjnAI2R8N~EgC{B5?8M4>igFZ-})^= z=naIhY2~It;hJp&j{trgA*Fs*-|BTQ-Sk!&LaNgUDgJr&+Rdx}$~L}@kZ}Z|+OOC2 zbag-eyE%Gk0!?9n;A^j&vd)KTRysBFDu?(SB9@2}}##VND+PBVxbT>(_ z>$<9Mo_v84(m)Rh>$}$Vlx_Ir1xO!7$oy$vY{TGT}fUq54E82>0!8V$E z584gk)#xU4FO0hZZ2>6?;x_ao%7^@8D1err`{DZ)q)g})C_kM1Gn$UxLW^kqJjlBr z(l6udm~6&{7<8EPp|^07`vRNTN6;p`1^<;@4)pH_3JK<5ayD9kZbm;+7ABuUek7uG z=vs6a`Y|@(oaFlCF(gM>z`G&&NbmP~w@+ynFjs17J?0j_tU zU!x=F&v*uYi}TA+0w-O`*OTuf1)2tJ@53y7d7Oi1;wKmj`zHG}k|8TeoK3O42@w7Jy?Zf_&WSUybB-3A2Tnri?~_b7s*x0 zn-F>D=d4~0~{p{83HSB%tmznN^XE2- zyv)4Ce9SIlpJZQP-(uh5vbee2VvxeexTj=DW|Y?|-}vU(xu?e-7<(weB=Qp-Nk!6; zoRVxzKAn6ic`W%Kpt%An1i73CI(04D0a7ypGxa)1;1QVXKcY`ThGZabM(o9YJQrVz zZ-9}$1;+YE_-F9l4U+RT9)a%*@I8e886Sbse-9tWf5hKl5MIX51fj>5GOL(tn8%qH znU|OZt6?3i2gb98?SV19j@`;W3eWI6_Rs9!I6ara`MGMYhr645g8LPBjQd8`D4Q$0 zQf`#rA>S@pj>D6!5pH0@K%c?wp#NGJ@n@Jzs1whAMqGS`EBsM z0euE~w3MmGpMWI&6i>x>4Cb3&@S{a`y_ssxe?s~+Fy*mfDkila527>nF7}E zE@m(K14zbU(3d|mjesA9nYN|xx8{*M2G??k8ISvr|av>N{oRp49k478TXM;VIlm7*0NvYfv=cCuaV)5)pXcqba-wt+T7J46Np&usKCc_|&hm-Bl&zsO1v{+Ur zbAmPQV%DNxDR#*}lGn&f&r6D^T1LM<@ge$dPtC28ydTl*NKSePpltN>9M@i{Ojmm&tNbS|v4FQX@u z53`Gb#vZCHk1=mzA@MVm3sz=5tWVA84|p2-clho@`^FvuZjZ|!1Frk!yU~~OAG6;8 z#r^1Zra@-pf*|u_Obp+dyd-f6*tBcVe(sNGF+$>;wxvrJFIu=@erwCTrrFVHwKdgM zl@(JX;j+?_P_VeDFi?=6m+SX=JvnZ{<;nQYz#!j%6?^ zZ1BwN6ypBQIOq4wnpH&7o-WAfnv~HQ7a(iq`E}w#C#@!&UsHsdtG-oJOw|;}Yhqrg zK{Z8%LW4($AD-b6M)0!vZGhi7!_zLrPf~m?#W_Ds=pf;CLkpq7x@LwD$DKk$eCDP# z+ZsA&0KGjLb-ky)M_p8i_NX<0Y5O3#Wo@=T8#0<;RMr)=W#`nZC!5qinvpxcE#g@?A? zF~Xx2odIpPr@QOYwm93>PIwptz;{O6a`g%8L=uRb>f5$XE_JZm8mzqnNp9P=RfzAJ z-!{3_O~UqepaE?e-^|W!GlBITWE8DI=m_aPd6d*c^>`XcPUq!9T;-YWS+ni(PM8q; zwm4d_**$Exi~Ezuk-b6Kwy4eHjz=Ay_O2OI_L$MO1)KNUM8S4`Nm1b*-k2KAJ$i$L zXmyj3p7An@(dq+z!!-29 zRrQ_Q_$rc5+Q(%+-Xm=L62Y{4PX6iqoGvLx?&Cp||3pRvT#B@SL3tXF2Lkbe0wNcR zdYDM)<20I%6cuh7VGeuxcmX09KGfO<&DyJiFy?MInbq4zM6?1D@uB%`skDGrIEIlJ z47A6YPEv9xU6Q$&lnkXy#+!F~Kz#Sn-A!g(=^y`R;IlFs)>OrD)_+pmlPYgs=xLt6 ztW9Xx)+vo`^P=-osq%{PG6{=k)VHw?M#2~eOG`l#FCDK;5^dTz=YxN8D#_g=3MGgl z&B4OVINv!d6}GG0?tie+Nb)pkMWcykQa9sOf%DVV=cUix-*=AQf?)FRrI}hHp4azc?Vo^_@O2Acpaf1ejmk_O`>_F0={pMFn74YOJS& zr)%P^pzd*v59F1EGD^!pLmefW>5E%@R?OF&tEsFFT92P5)zm)1-atd8FV6eoMv7>|+HcuN5OftI%4kkU+ds@bFuP+^ zs9JQ&6{lfEmT{+9q?XH0vn*p*DY(-Z*_6%KSOfF;Gc|L^YUc50Yv%G}H7Hs$Rzsj9 zRAzJ=eQu+BHHXd#?4fg_41I$H?hxTIJvqu<&OU~+kr)3^RF9ZO%+EP~ZYe zDb8>=v)23@`FrxC=A*Vx<)4{9v;CF%QvO%dIrHCLUwI7W@NWRTFSlRrTIIQy z+3DKhdD8WB&(}6hwnD~gGQ3W#97!J9TTm4yv8c7>gol(zl+0-*6yU69OinR7;v_|e zY$41$vFIFfGTWWlIfAWX1c@e36p3y?rbJu_8^HB?6R}AcQ&DRO!yvgugEI<&IqG(2 zDL6N;agH#Z!{|y4h{j&e%qWeU{Uiqd9&h-#25ano@0A$piRKK^6LDqqWiT0{&JfP9 z`DU-B;~D4(%pE%cBia!N1m>POiJ~W?V}XFNG8pLSAAr1*Gy)^{j8n9^qvRR(n)6aI zbehH<6OD)S%+Ub(wEss(e;@#=jEyEsWl0EkK>PiONxm(rjFzaY5CYFg^6g=WNp;lU zfdd`bot0HqI<>s46g)MBob%+MNEkuN0^iJBzu%K1S8%=Oo)dm{`@oCyocR^byu@qU z&nAxH=#lIGwQN>U_(Sl4-Zc+|@MWzlO3YP-c~gA#IP3MJ*w9wiv~EuKrnaR^+h9xs zFrbgIcc4mUa6d98KNF4h5rYtouvVu(>>$C^k>qE4A$CJ7P6Z^Z@YjW-hIb0NS&o^7 z@5tU!AJZN)y<>jI_I}>`p|1^^X2UYW?S|J4|6C|@wMHY^Vl;xukVGSuBgwc}39)iP zM1hpfskm2vm0q^S^?-}X#I|gk>n;4g{-f-VTyIq>-_+n1&2r6l&C{BL8kt6;50dGe zmT3tGgGDFTK6=i3W>;>64n`A%9SDJag66^VFr_!RXEZQH~?{b#<8P>`+Hy}Y&9nnDcl!DZH9z)0JdNyr{KF>}ut1Qj1H1iLZ}F#^d3 z*&iUx;Db{71RspEK*Hr7PmVtlE}xpKI4_BPeiE0Z)W9-zA|Y3>2v4o3h&FxR6fMeq z@JGS?X-%ItMJpkV!Iz%rdjB=m5qzf~Xzp?||W+OU8U2{~v)4us=pqWe{cqtWy*$$yg14q9jzm zS>#O_49EI86V66VhAbO|KM=U#25dB2zGXf95o2md%gRUq`I&Ayj2qy)Q7h_X6KD2yTIM0<5MzO9D0=F-0)Z0l< z_J&HsGzR-c;%CjaFwWO&MsT+1*1I`HzT9q8Bc-4WDO;7D%08uh2dr220Jz{r6PZV2 z4sr|bkh|60>F#sO-L`@ejQ3niXRL!x7Z3CG$pF!sXmsw$lQ3x@;HeOdePARkGMdiq2NqqKGzoU_GjJfVx{PgIUh%n~z2vzQ^8M5AaCt>P3h zTQq1Vt7&Tb)Xv#%XTD9YP`k;5sa0P(-CB(@C&x{kGXv_wPvhg59Rho354fLaRLG7T zWQvT&Arp3)u*p_%{uF&er-)1t4^sql6OGoGCbVszO4Jynxq+!6$|y}rL{3yCcam{5 zn!#|EPfe#eI~nko+IG$Axi{eQ5Y;#xt(&&JSJINPIx@<^yu8KD{TQ^wRECHxWF`*e(xaUTqpb#Af>Lhcvh!PZ zQVpO=*-KHYV*z?G+mu!(MUjLI@&N5EPY$y*+vE zY-H*#Dns2xg@wE|WEHKg)=uk?Rc@6Vx>YKsTd78Y(3i3i{O_Wc7)8cykHEOn1y8W^ znOA8O)I!Dho&3}ML7qc=D@1Sd9B&IxvYY+jXP@9}PEy->wqx#z6Lbn|_>rZxU-3)D z@2cKbzgzN&>eG@l+Ot8U8Y^T9m7+W^R32>1pBYqoiL&)+46xgQK#dGo>6wbA<(0{JLQJs$>tBcj;GrDfTU;7eOEK|ShN~j#R76Y5D^sNq zlhVDd3rU*Bw7jV$RSq$2-AGy=NJYm*O?@N;%(-0DP$lsov8b}=hO25=ty)c-?S@dX zITR{p-BT5=hAj=J8dyU^O9SI-zzw3u7j6*CBMtA?*4D@^qN6Bmxr&E1_qdxy?kLFG zyLNT1+pG~0+4j}V3yd&}MPna7#P8ta{2~50FX!#E70)w^VV&}VQPDWF=ef#+vQQaY zMjbS_CtPNm)v{gM_RT$0bCN$v1rV$U5y0rl{*Ds?F!vyP1N|M*lUw!0f$R8}5nawr zm1#G5;xk~Zq&qzL*AD{P(N7j^I}+8pXgvvLlAwVEGf0p_1{7ki6bn-9ru_pXBxdQN z>XaX^j|OuLwkT}UKiUhiht@SpG>o(ji3ttS0thfPMjJ^mlLQSU2z=M49TSI~Y&pq} zQX$VYTj&mxx{bs%QUe)DX_O_kC5^xuM!t06g52_yJDF<0&L~}9bLC7|fe?G6wRfQF z_K(`{j~a4J#Hsd`>Vr2expST`5_$A*3m0}=|3>4DH5qPwK?N^N^;IxGa=CJe=gJ$V zO!3`4e|^&xE~ic(ZE9$W=9lK>7iL-W>~@pAY4#QCXLmcM=%J{z-dbD?RyO(c*n={E zVinRMuc%WLVPz3U8oPnB=|^zMo?no8KEZ#2f;DqtqG277j7G{Xa6kFxA)@x&s@c(L zV-Hpo7gwgNH-oaldSAi4h^C+d^s#8)?|xPLs-IorUYdKWj%`5Fnzi>DU6 zlR`^Dp@Oj}z0Wi4$bdXdyT}`O(JDj{$SlLZQCI-m&?Vr(AexDSz~2@SZ%SE8>VS}= z2_mWpTo59fC86fHzIC%$?#feT>hxN@Mz7X$a=$Ov$H+~_45Qh|%H26a4kOP~c?+;B z(^G(b`uqZ%V{{fE*pv6qG8hvgVrSP z!kv?Y(%uDeQ^2vKQ$S|m#Z>-8lZopuX>#^CXG1T@!lg0tW+Tcm@;Rxr37l9H^dSS8 z9CkZ6r*Z@y%RZ9{OgSLWimm)8!xpES_-%ae!CMeFB4ZiHc zukb5+S5<129jjvwrdHfarvc=C2&AGJye1Yj?~5%7}(2oTD9zX$TcH|Svrib z;)rM%GBe4JzSGQ_ZQ09yp56rVV`r##!WN-FaFQG&QlAslEYlOg# z@4$``?B17yuFltwFkkQE-T4aD2yPNpj6BPoqmj>}XSO_Spq$5@Osn&VlX2RMGRWd< z>hojd7yKcApP%#F3jZbT-pz$oH8Ic;n0taQs?o6%V24k3kliqVbR>$%k*LTkMO{`@ zO#&4O97Nz?=}QS*e+OBmq@{*BcK(!aXQqo%`l!QArIH+!vXA<53&{yjcBZv>{`Ge~ z{rF2m^FvEK1+^X95@%1{ybpW7SbR6T+7q39Q`0o7Ddq_M;(J%!Zs+GtE0|Gx$;z8Q z{Q$cJvIZ;xKkphCZv)8Uuf@xrV@Blfs*ma4H@%bjuJs+;`;MbiKGpw?`AV*P#rBGW zF`djfk@<=33kUbU_1!6-GoQ*oQGcQT+@$EXUOwd!*<-3lHNVh3Zcy|xtK>cEEA*F} zy0heFw^m_ya~htErWzq03FtWD(DTffAkr3Q@pCR^NZF@kmHQzl8`go71n8g=5rYpI zLyaRRt<{;-Sx`l75D!aQ-VPhn4s0d|LS7gIW3< zEQS*m;65>^)+qI|O!kZ(^BPyCOW+FxO)xVk2n8SbKPdRZ|3$$$K`|4sV#N-t|B7M zXhwLFgw=Y8bvr%t!3CctKEZkKv_8~KH`bov8-|8=-F??jWyWt_Af~Pq+!W1kj$nUD zNs>4c=N{S;k6+t=*Ih8%?O+4R`BOfcifhG4feeR=v8+6++*2Mchz6pCwMFan*XmU= zAyc?t`I7uq;cfW|`Pp*icbprVowJP@p@OM72;Y*A^9!biwI=F#2c1HgSGTGeQ9Yz) z)b8blxTO#m7UrADHrd=`;@wU~zIrH(!=So4;xp`XFVDer!Bv?w(HwiFWow8UNQDTd z%%u<%AqA_jRYaeaygJYUnAt!_>Uim7Kg=spWN-|NmPL88qVwdUizx3&*mnf`2Tt}6 z1n3nKZ2$K{CAu|(dNk%8Qk+TSVMF>Bs*+e-kQaIoNzNka9tF&*J9P*W346;*Es-$Y z2BfB~Tr#Waxn;+<2;_)_bmtG$bO>m`Rx79=L-*Kzh0;`DaZrbJ@gn?bZ2_PrkE>Myv4Ppc)M$R z@lMyy;!)RVvARS#S}_`BqNKJ;AFd#^GXMdXQXfX)Ncq%?%Bt$>nirX!=j(I&-6(^; zPCvN}WdRrgOaMHoYmlYit8zKNqpl%UkF*iBCRzHGtm2{rsj8`y%;|L^d26etTFM=E z&Nl1^^dWJIv#20~71Ql*b%C3^QmvRSkA%ZMU#1$|9&)T{$r4K=MCV0^KawRntHN() zjb@$7N@j7LS$$bUSv#^gQ`QJREgGGIE97Ea{(7d2+Z>$6S zE(^5CA{Dbp#VqoKS>y>NKbW#0mtNxszQnCFQlF)=VFq-KOwi7TcwX0x_S7{Nv4m;Q zTtU252bIs%sjy^>1#7laH^ry*IaJPUlL)&-^WBSmcmk#&^=jhBhjrZv5k;wvmH4Ai!MFA*W9r_9!%*JNu*tV|_}eMR*tJmvJ#V{Gtx7r>6-D%gp8aJA?b z{i2;7GTX#SH%gj`onqRyXTWyQPinB^zYjrmQ^r^DCeThlfE~aBUaYqBFY(D}$_j`>zWNWs&USX8ts4<}dzwMye^9uyGOy!ojTsU6^fglGLtw1@+ zMU%WRf38OB*Mg6htMPe|R(HOS=J7JDmjNHm!$K*&JiNe1BWjK^&4?WAWqQ7~3B{9q zG~C_%!!q^Hy z30X^YL^f;$nS!Uur)N(wPRp8pljCO3w%U8AtEY`5Pm4U!Z(eH%tL&O7TrKM%mKj>q zLM-~V=BPaff|z$@bhB%V_kP<0HP4p4YIvpWsNvnRPint%oUPT@5-w%X#!h(FR$Coh zW`$MA@r4~EunNIaz-Ukvu>#O45ut>@xEk(P|JQ9>MG|t3;%(+L${-`QU8TWNrgVh4K~(1( z3UIOj7fj0>VcJApr`RVBi91A2w9nGhgCuIsjlafy$>PS3 z%5k;BZ4HvwOG@ne?0eg8YpW=)&Aa{aC%e!7bIaDLd3hjFMgA#SS;p+aIk6ieWjVNd zci$D?|NY{J!-6R~8*Hw>op*_1Zl%9I%V2l4?drJaLytE%I{TrfsKvM{%O74{;cqnS zr#1a#-2<0gl~2yS-vgL-J#>4??WH@>&d`G;50*ZKo(er#@?_~jbTD+>dfLkOlw4kVGgP>zbEVww|-!IzhtyjHf|0K{A9&XzZ4?4Ctrn-?#)oQb#(pjJe z0#qv%p-!m?6-r5kQmX|jSZpPsQVR}=3nM#2Ah;w3J7Os*RT``=m?x{!63zwoE6in(p6qI)!Sr@D7>ov)Ai0Au3q$TBZU(t| z`pOIE7V{(S5&W45E0+LkDlxm57+_3l+jxUGy&-H63kt*A4cKJ}8W@AEjQAv}J6>Xp zi5H&oP{xRLw!vPOxcSn>t~KRo^J8agqG!&WFjfXT=stBI0RM1m%eu9gRPC4EK$B2w z;Jg(@QdxOs$btZofGV27mMY5Dk|HfBf}qr@F_Al66XZcaYv>H5&_JrC_v9Dc#r1d4 zm*Nnt*WX&Nq2>5&n2z#5)j z!Oy?&x=`=b&e<9@uTq-Ga=lD6s8mQTs6(*A*i837GjUv=@=(uTqSF`q%S3#CbWi`r zMOm2|WWzRlHfOR;**ubZnVWExE-3l4HQ#Yf$)0~{={$EYb;;I}a1ze^G(EkE>r+>m z#T77*Z7`2l$_%IoT_+XZdi&RdT6AHFH!Y z#q>?`TtGay0X1hYtK#yNsIpRHuB&opsN{uJb%@QVbcS$-rm}K``Mp@-%rHBh8C8`T zh{HAcGji938x7!0MZGOv&dcyvzzkj*R7F)Ss^zMfYKuzlQUz6vYJ~YKY!ozthS4lF zWvI;~%-=;vw9%>w{Vw}J!2suPYtE1B~XU@<|1PITZJW0K#nz8;f{T*Zd zH9^QeK^-RY;=@+ib@a^#@^S;2OobjclnP#7QxdYm9%f4Iv`Bf5$7YXsruxw|Ta6!; z=Y;*Z)*kgw>|)3bb93ChusQCVzpU*=*jFEg{q=F!XCL1Ki%JE2+Q~5rG1LJ(ReF_C zAy=f|mCKcjz!tR`+-3s=c13mo2@C}3<1XoQ z1I{!v@E8m@&?cA-Q|dkmrXf>$3pv91KYj1oCm#Idy=$KM;lFf5Iy{Lcdx^~pMU%t99x_C;E~6!YnZd)7au=%ivo+PJ_m>;XH3|bNYCI2!aFVLsG9(D5F zeJVbz<`G|(c6PwG^0}oqy(5TjXy~DyJbk(^X^tE}hJWRA2dAD}#uRL*x^dn5*?x<@ z#9L4sd*`}e|GjbR<%gZqnpYgduijW+)4V~5-aOuZo5N};ckKo4nVng5?Owy(}%xE#UL%alV;8*dlY4$OGQ2l9YgP` zS)CSEe+?)pS?wKajajYMs3C(hDQP6r%S`r6<(uXa{K}pOK}SECM_v>Prc52Ne{;bA z>aTkl9F(%sQZl$0r!CP`TrRz3&*{cuHnZJVP-|uGv1K^C1vT8+udj;mnKgb#Shf|A zYQF=zF(209KDrKHF9sjAf0@b1Gkux)E;dKy_TGWU(ARpI!e5}uv^nWotXQh$-T&2M zyw_q6jxWP!zr6~RcZJ9@oVs+Uzd=g9@|9kD>C0W|Rashl$M1m1s?1b)92Z-NZDb*? z$20Ri%Bp<25YI^bBH&h+7ZuWlIB|b$d?Cg&m&_sa1X`U7T5U&9?uP%jI9^OJFJdud2JttdYTJ~4U$f5w@apCK06MJ-c=kX?pt+|YyL zFRIO@?q9^sna@4Ww&Bm7C%b)c$hlv_ZodG(v7ek%i`51v*;P2B3R?>jZLAL!*dnOP z#yODL#*|wt3#MD=7A&xK6s)rL7L4YpChfW}xW`Wa?WDZ?I{v)fwRDGtGNgO0)NWh; z-Mj6Hzb%l?wZI0R7mZ>D*}}^v{tCe)kKBq13WTai0ogxWY*w?)X0_sieA{*ys##SL zGz8xANODB9S4C_&1=g@7C+v1xnEZkQvR}3bX))c*(ik?THnK4l^7A|M`tpYI*gUbi zCY)z4{EpqL9mYZ|DGR&!5YO;phBdsM-o1+(Q+MwH^6DK=_pj1TZ7Pwz8>)c`J3(Fx z?T3HFJ2KIo>iFI?ZKQ3<H)ude>J)l3y zXlWMKL6-PBTRC=bO5h5s*c|ZvEAhG4m|luh6c<&U1IdR;{5S3Z$Wajg)84-+uo3pa z&*~$dA$`OG=&+vLDU!&PiZWACMk+Fs9kWLt@j~@H03SdufFEEKy~mzHC*;S~vJz#T z17yW4$xT6WX!3pNdABVN=>~?}t4<-Zm93xn!(IoOqmx9@l6tXAIt7~a-X(eO55`OS zA&FX*&M$&|@~Z^$YlH%Fjx=PT!kD@|a)@@(#1~9@CE#e98eb63&o?qtayeCwJ9QO< zlZT!&WQOtIN~~18jB2C`fy*vtWQJ9L3lV{#0z%%?B-e+;+o}N{EOqq)jR>f9&R_x@psziF`zxnjTy`>-s#~gv79?#-9IW;%xo*?%c#QR23ChU?M7G zyDznehDG@?y(0a|3Rj2{kb^I9Y(9sbQD1Mf^S>~ zIZkvRxBt?UaH-x`+@#Oe!H>D)NA?| zvpuUh>w&C4T7s56)(>qe+cx{9_J{3%b!>E;onp+6IOjXZXwUP}EbtIhzlP^g5Va$u z+%J0zaWr=!`|pVSI-Yzkry)z9IE$uO+Db{@9Hlsmy3wr?&LIK)Ny25winS6hM}F*; za0Pk=H%Yh>g&1DKRcHz$O1KWB?9%Zuj&Nrs93zb^AmI$Sl;sl6qEcCvgmZ|Ot(9;Y z(#o!ta5>75-74Vr%$ z4&$$UPQrnX^00)%_$%L$aGgv0o& zcT-$Vo?TZj;qdIb`4rcXzk#Q_Qo=b@pu3IYTGBV&UI~Z(=$@yzo=BSR0}1C)p6&~Z z^MsB*L&AZM-be8aGKTsV35PM%FQ&Me^hduz!l6I<8z`O$`DXoN63(GQeTr`ut^cWn zllrOgw~_h=hlE3YLy+PQGN*=1Bpl|{&_nTT(jUWC35Wg|Qe)+!^`DS%QvVr>d&!&{ z-ji^cQ^Ox9UO>i&S4cRF4{xA&5uw8eC7eTur}L()ZN0Pb-P4x&Q|0*mXnxI*13*6_7{z_TL|Of&R@!LNV2DF{FASMMheHo(sNvc2n6PPadOk|J_fT8tJa{Mzu$h)o)8I8P!3kw~@9az1>8gre~ZEsks(v{HJrY zTPO{MDuhLAdW5;L^|8UteLX^bY@jbT&^6c_TVE{Htz9cD=v}>LaD%X*XG71xrk?KN z`q;*S-kt$rUeA@&V{5z94XY;Q3#6cGQ_sK#pdv(yOG<>ixxFg~VjE(s2J^pNaml25 zQW+GrE-a$t7fr6-yFus@1_!#jd)9RgTp`3(U9|5)?|NYn$`-Hh9qj2A77lg|_CVwH z-ND#^5QCBdVP$ON`avMQq4;7%X2q`T8t4|9dj<#B_6)SgHVW&yHVYd!^Z;q-%BtA< zL7{7d(AP7tu6K~IS+SWiZCE^~4oU}TqHiG9y>aCr>ClyHdRMNQ)E462^()tI?1rX; zF`>J6L*H6p0KJ4(y-;B#)aqG3SS$!>=CSo_Hw$^a`9jaS6{OV!t@Y{J-`OQvy}Nh) zYGI&f13dLg@_dun)8Ue6Rns2i^#Yf{o^@m}26};OckIgbYhzuLnL?+#QeB1d93R-& z#=*XggF<)Drrwo3q|Tb2wSC`uBDyTBrpic+^u-p9^J@*FjaUbw`}sxdPt;gNRrq4{ zQl&E`GkvjIQaO7o`y%@?dl14s7pr?-o&R+v{@0oKUuWWfor(XaoQZK;-TMz&^i-`m z5U+uF6VxU-8!y`K!kUeAWHwy1MY?<@tOjerE}Vt7pF`fot^N7+((N}$`WO2zIZf1D zLa~e0PnFJsHfw>`s{gd^`L$Z178$*bAc-ki+kDZM-&J?==wJMK&a1__xM^H9SI?Dm z6`aV`a?M=j#ae!6-9`W9sy$I-=6^aCsnTXLBDe(VU##9ljb^H$eK4yRf7(fPuo3+m z>jAyHNZs-BIn*ll0-yhh)c+4=;eW*EAJq`)d=n)+=l`Ys^k>gfS6wZKQ4k;mz)~y< z&;qa=pcCLtfKh-`07{UBRNd_WJEamCa5I`K@H~@?Tgh6%;p7<*uJVtAE0_*@d2O7~MlXQarNd#h?nkJOpjFX7pC(9i&35FiTB0}SI&lTatJH-Yrrgh<>9z(K2rpw&ar>LFtWmQq*tTukwr$(CZJVcU+qT`OZJyR?+t&1X_n&v)MBJE|h^eSr>&x7^>x-(& ztgj+=?Uglclr?REE1Pp~wicgk&3;)6nGy{bjfSn8tb<=(?YSa-8|PPUm}gRJUIhB^ zi7N2$D)Ns`TrdlS5b?ka1d59VE?fv1aIB?6#PZ@ytqHIM{LR&dsr_byBWl8#!>Trf zvD78)L9j650rGIzKvaakrV$z-ZRm=f2vek$^&~tA4@2$32p)tcbs{DSo`Nc#7bH=_ zm~B+zLJiyGg`%XT^-Z>>jBa)$P@lKMMi*wdV7WoxI6=MgCb{Ok0bo$L!lb1vna6IX z#2^9R70pd(r?e)hlU|WP=0`FKXTmvzqjZO6PHR8g<1B+U1qj5oFl=dIQqV@#p@oY= zJy!;AECOrLNQ9t~3P3p*f^aMi8CnR$H+sC1BykM&aGz2ydHO%la*X__>C8abw<)H(; zfC?2VigCZQ;|rfXgnku!z3bFFf=VAgoVrFd^P3$`hQPCqcm=ovIl>4bgb)P)a}`<> zZy~_&%sd*~Ovn@mhy$)?$!j%@W3;AZ59EZ>i4(dkiZG31ieJ>p z^@Nv-!287jLIBhZRLZs`gW*AOyklp0K&L==WfnxdbSHT!0dv zt8;Dv!2tCWLYD*vic;2`AsDuXwW8|G-T{kfM^pjR0P4Uxz);Phm>_Eq^^m(#nTz0a z@C*R;fk)M#8sPPK1Y*uB01rSqa1Njc!vW&(hls#>mdF zB$MikTBrkhQx)igI#E~r4+DNuN&T~bIA34%^uHMNp(=e1ueOp75~eah5S5|45GE*D z5CH=u@E=eH6EHvk{R1U1K?4Mke^3k))K38M4Onm4i((GH z(|}!o zTmY-{Inw}ipymJ_FsC)4=D_CQ>SK;*Kr~dq>mzL zhCcicJ6IL`FWbQiP>wcP8QQ@rklYH8k2YBz3AQ}J-n5Mv~4GUEPPjD9zXjFSH_C|*(W zKl_LKjgxN-YDeOkRt>lIbjzz;rf1yO@xlNU@(xDb2-*&HeJ4OU9Z@M>r8h zJP{{6k)%6`hHoYUZytixA_{2b$XFI|MxDD5+*$I>U)2}B#t-AW3hKQI;rsc8l_ms_ zT~PKow~uw=3Gt>5@<|i&btKg1JJ*GCQiAP8%>XT$br0@;?Y0HR05Auy0HgrJ5Oiq- z!c%1bbB$pES^@|Ga02uJ-~<2)Kn5^19axz%QHgRzD@_ID2ROZnX89vGbiH^Zg*8)P zNDNygB3*SgqPEqlrdzGr)~&j_U759BS!K1%8;^YAReoEM?%Q+Kd+yq%Q`hz2rMvjp zdAfRjR=cXIS4Z8ahYq6C??1?@a9hUm0SJ3dMEDjK=3lnwh@~esgoOpg;_^4s5LYR7 zmp*)}<>rrh*cL594vt%0fW>n?_k|ZAf7G9PW0$==_%8b3KY6fS=mO1NYq)_H%k^C# zg{MPTUJ++c9m2JBTf{hMu(k19z_mLaSvrpHCFh2T>=zr7(JZxq?)}UAbPld%jcKKY zUP!#>m99VgucQu9N}bTm%b8TT#cuo>WE%F_qi}Pga0y4^0*u51jl%UChN{-~lrF~A z(o@Jt>z1fnq*|0JlBqdKi$tWDUt>)OJ*CHJjwMOT{Qu+>am@buCE3Fzx@{^hTYe9q z3~eWLiDzcT6Krdii7q!beJf0@cn?MB=T=}2QguupJ;}4^_-8356I~YGrk-ug7CLJm z`k3At+t6xXm^l;lW!M(l;%+YHsXecd7z0p`YL94F6^ReTqbNl9^XX+t;68$=gFp|_ zBCbk{-f}be_IZ;K)!Yu0DtbfAA<<;(g5W!J$uFeg{D>QuL~h&1+?#u11Eobwb}=S} z+1y8bjxsb!kG@$hKg9jqO!3@HYR^iceFB9pKInj*K4c14p3;ql!mVGVn5ky{7N3RQ zCYroyZ-As2)6BNO!E)1&Y+{LRYHe1ASkZgaZ~PMD^LTl4@x(5@VeC?F)w0+XYqqZG{DZ5@B1cyVmrZqy zw?a+~)M=6HDkcj0?BD~~)v2#(#{Cm5+0Uy~zuDpr{8}9P<|Ow__Q3!B?1AM0z-82a zr+E|$UyBgpU6B7Q)VKPe|h4h{yU|3l)5?LYn>i6<3L z2UB`6dpj2qQ)go*O9vPGAAzSIQ_j%#$1nKrMlEdb>SSr^BxmZbpiC=dZ(|~>0`*S? z%G{ZN_2=LxT1d#=Lz|Y7laYXyosofnoq>^nk%@^(mtNAv(8khO(9Yb(lz;(>UeMXt z)Xs%~gP946{@)4z8O#hn1Hy(55~h~s7B2thF+$NRyO`Rl5pevB{CoNz;VDz59~r8D z(o{-6DpUV0R>l6`ujD^sRm_~6|ASD~|0zwSn>cAV$bcaF{0c>X3PhUAL!pEM36#)y zB3$wrfB?^;krdVA!hBF+QP zwvazHH)}ZZ{aKP#xVDOSwTek!!y9XgIb#2{?&{{=vX*`u0k8P+7p8L{clmD--^=43 zo2C6(#T!8?!ZqOv2?96NV(>w{~-2^j39bTmJUJS?2Du~XV_un8)q`xU9?XyKD zP=8x4%7(Fzx(TVSI!W_FRb&+jDJKGY=v~U^9wG9vCy;AG?G4Z=-)FbG|r>eFV-Fj^MZVy_C7ABYgY@9L7%{!9R&X zxXODA{_)Wv`0x7O&Yoxs+?2hC@9N(JgwV?t2{gSi8&&pk9*;$XXC6n9S=GOA-!F0~ zqJH-R7KZ(X`5*I^O>;M#DKp??!fPjJV z`pYjukO3?taGY#d!e6ihzcYy;rMfkTCc&(ad@IG6%-s8~+jjDH9$c0eRhPGxmuGe5 zA5#mg=|#m@VmOLx`@AlH{{J|FC{#xrVtd|Zr>N6ca}Vf)L^y3vkGS}UA7eZ5pxS`y2y3m4c*JD=&TF^kDQ{;$@!lThH2t0;9r zja?VMZ`f`&rkb@{=X>M66;ITBO|j(veb%xH&-2@#f~eUa8HZY5)BCZ+|HD@ie#`;> zbO(%0zsVFh3Jvk?xXR+Qf35`BpYO>LEABdw&qW9`EcPn~AnGCAp_{;}nX6~Of=QdC zYWm8d^H1a0`F$E_kQ4<@AZ&qbamu+8Wh^RO?h!$lBh0`i3za6~_Qo3WuS*uB7Y zW5VX%Pe`c5w@#kdz*bL1fX71{NB9LdVy~$10@b{h;`~B#ht&5WKj&(;M z55x{f_D9*=iLohwuQ>($kzg} zZ`y7b>pzjcRXwoZR$^;K*@0|*vBj>zPcU6TR(G-flG$Oai>d^A6@(X^khYIuW(Tr4fYVLc?g4+G6}X+Lc?`myD7pZB zBE8*uV?4{xnYRPA^8cz!v>izqA&d13i7WIU%R|O( z_6hbEZCB*b?S}tpsCFc@gD!kt;&9ouM|&y0U*7{NZ#e?RBg)(hpdZ5iSN8>wCvIop z8X+NMoZyw2eY9uvGtM3*#0XmFcPNm<4un=D+W__pRm_v`O}BiZ`W)lMu%iyB`~zC{ zH)Vz>m%%%pXYfaESMcUY9_kfMHqA%Lji)2|0zm3?uwy&gCxY0X{TisR#9!(g)|Z|9 zW8wn<^CJ?vK~@LbKTNgpUC~{6@0icfei8ne-!=6D8q_>Bn%XZ?dubzAe=j4PAQ9hE z1X9ZJSOLFuz}8$yAM62I30;^wQ7=WFfqMUhKjoM0b?A$X&DG6!ofvxnLxktgrVVY? zfmL?_??7+beZcrZ_65c7@$br?iVfDMB#9*wUlvE(khu4|@pB4p6X84h+3~i;VuxKa zULicg#e3w^L$%aTqhF!<5%iW)u1>91FZTMmIaL}}+Mhjxs@$Ndq2p0>tGv{=7kU6c z@P}0@us*nOKRB`P?(WxrA~4({c%gbc+iU25$3db2?3>~M+LVX1r4HTS0Ihl5gx1rB z+mh;mZfbSI*$3HT3{nh@ea-W*hmMpEfxE~&6)qN-qH5K zR}#4oY2K0cE9!^X7uy%?SK7zs$FY#Y2?`rzJS2TIUxS_wogN_{$rUO;(yW!pG}1KJ z^mHaWtEeqZ`?CCA2fSb8VaW*l4Qo(vUv4+J3!yXcpj$VNm<-8edsVx4hd(0SP#Gua zH`?_9-El3AU;H^yo@3T6)EyC=vtU7J7tB_0)QjaExKo(VIQK2n9l6eoKQKO7R)-rA zQ|}w~_U|1spAdvsSS!M|UC28qcWigSwEDLO&^{#zEfFSiGf zIUH;O;16B#;`u>`Cyv4Y`xAhkNX$dqcsL|W-~sno=tWj8{>=j4F`MHS$tjcO*pDW6 z7mERm?w0;UY-$f?cV?aj#?+$PHr^=@q*;P*GD!>8Scx(lvaKqHv~r@Zym9(N$~Bk*?*b}K9eym)-!`*84J-JH>d zScE!MJYecKoGuX4@y_m--V)TOc4+U=&%zh#?o_bDXi?~^MChg50~Xl{+Q~gm{ypi3 z&u%w7N?ibXH;%~?(XYs{xx*1~Megpd=%_Z-YccDn9ZJ0zw!)GT^1yF9+AHx`i>^6w zH3-UHJdX=TAC!anzQ0|8_Os%BpnfPrOmECK{6Sx{h`Hk2uR8$OQ>fRJUs#-mJcA5E z=K@i=Lh40*gYDDDWD2@_K#g^4Bd`G>UhujaAA*b#j~2?eRJ+~$V)51>ySzgb1Uzu< z-t7LEzXkl0#zPksyc!syesQ_KGO@CoyPa33+Bhp43;XKY%982os%BJ5q>}$_upq%v z3JPTEn>|n1q6^1}U1Dkx=hrLc7M_-%ohGuR3uwp+%|Yt;_e9 z`B9yxZ^Kl6(_}uJq*b->T=%!ENY$!5)-sZ`6s=KBkun#-n;n25xSC1z1+kQ!t6;P*E^?kiKF#OF*f+|tW{;umsBdc;LWg=(RgK$wdQ5ON zreJcPN;HyH;O?4EU*jt^Y*VBwlMlX9ds3CV=r-38I)76hg-w99roY17UwNAM)=+lX ziDP_@Ejyrx+xy%4w0(KJ`qrM4b9V^E`=`UXi>dW^aQog`nC0?3*g7UbL;ZV(uKkvm zA!JJ$wH>{qsLmZ`2asLm#Cgt~ig&9dK~8JIKa{C7dMegt!&8*M8{>M0(PbXC;8U;8 ztJnj{lRG76(u=sDA)9`ot#znxHqcGaWvB^H_134Ow9+ZhgckOkugMgPA#(L8(akSt_fwpV|I6w3#wijbnQst0eDe@?DBq0X z7_4fF_SkO?69FZH;5}h!1Dn;SmSV#jVZt}BYdrONE)ERr-ugC|>U`JUPYKzww^0fH znvC=cN4hfBA!gQNx$AfUJbVMUC}$aL{^vFcI`8AsRK|-p|BBvbm7N}z1>e0&y%J~h z?}s%v`u7FJir!b9EtU{zREAw+9~dz!K@f%OLe-vTfG?qH>IF~FZyy5Ill}Cbp0xXf zUL+A8oGz5z>yhJH8F;VQ2Q42Nlb1e2ogz>WGg6IHtfaT&v;{t2iibWP%WjX%+>u6l zxh%iZhSa6Bcyr&=7wIkLtAqR@pKKR;?H1>YOYHN`GI%^AWIMnmGK;HTh~D!-U#ec~)5>jPr1U~}+Vd@W z2FvTb%{F={*B)_{-P!8oIVCL#coZ)HCirqA{`tnIUScYtq3Tp~&k?Qf!pzdX))U&_C%{7b&9QFb@7+On|myzK`@%z_FT}2NqAE(5(PBd&+zj>>}pe$+a$yrXwOrWDJ_wt zkt;3}9VX{9WB&LBpVd`DiUc)ON_4`lf)G@|sjn1BuoNw=7$zrbDP!3Ap4WI-FvJ^x z8}S7hjU>ItYQm6o?Ih6R)93OWj3fOP9#{k~u@P%DLFA?nRr2M?lL{5mhzZ$;tQxwk zta1*+I`d#sD}5i6m-eKW6Y)TMy(@U~dbovkjwBv^u3-(p3$Zon;!!gyfIV(;jfrXY zd(oL5&IZl~+Fzl)X@Q$hA~e+vDG(Yi8G3>+QEsW@ZK;yGvHOLtSIO+sV6X0EDRKQ! z^vodiNabE%B44oO;x!UU9Xun-o|(X_E6eiHYW^%{3){qJ2`Pt2FQfM9+91EwqErgwLHKop@L8#6+~Y-2(&#Oq(R(8;b?< zB=cMH#dr|@Z2YPHf?mFUJpmJehp;!XuH`)^MU^^R8bdD8QxO<)YP0Fea*LctRe4$M zf}Wm@vPF>YFDGUqoyDb3TyYR4+Gf!TfL&xoRe7VDv+iQ;7Nr7TE+=0~29+E$N>^9US8Y&Qp@u9t zT>77*oP;J@E7h>7VN&A0|J)YVLmdmtE?;N4Sdk0ckvLk2k%Lekf1N^ZGC3 z-hFFw2Ad|(G}kn5;dX0d#%0G@R6~6+mRCYu2pTYz!^Ar4T8TmJea$&Ux@jpzmRKHvsfY^N!28E9#HVOD zEga07>|QunIrvpMSU8CSyeK^@8z(tH6h5a>cCpCMa{aB*dZOJv)i4?VVsgbKGb_uH z8O#g{BN$*Hpa4%GG5Zma6t~eFRI)I})u=C7m0*(`kh}yV73czMn1}$~vRvGCF#=2@ zCEtUT3zu#}DXTrSq0Qd=fj9=<=37zrusUEFA#!S+;eGJ>Lc?89nYZ_4m*4odr>((L zU7iQm-3}HEt@eH9ncu#yRF8~$Z9{A~Qua^uVtUFQQ}-gBCoqcuo7R1Cv-tkw&-*Uj0@*2hE0aUCkg+In7y39b{yv59!80JS`?eg>s z=qwphz~WM}Qpy#Pk&so>Ikb#RDrdTDkDBr;U1D0sy2#y98#Y@wJ|QPxNa-+%hFdj9>K*E|{zU$b zGFsnei$~R*oai=cPV01&zrM7h*<`6mNK1zoHTxkY_mfliql-@9zZISXX(e-vKb!D3gA5xl^?VS(GJHbgU6&4h9AiH@AvRwHGOJ^2=HgX z)7Qrt5$C_+?C-WkA`3^Rmh&fpJbp;QyxeU6vK%UZrEN>RRHMdMtGO0ri-q%E% zO&U?$%GR_q1v9zoa>Eip5ZF_TD_Mm$)vnA{oHdgVBd?%9Q0haNW7f|C0hTF83aHU> z4W`4OgErcbUK#Lqf>u)~BaqNKKZDhp(zH{_tQco7GiRl_^c7_0*^s&(s8W;^OGr*} z$>M^J-9`l~kfBoEfGX>c3R{EQ${Xfh^NT!m?1lo)j`#est^ey}rvuqphO$Nc`vf$; zSEV=9vMyrTfRS4F3>0;0i1#d9@46u~7Ots?qQqmhJ5*l>Wis1&k>W*j*ZIxpU}Ucu zrg)KBFt-aKySq#7ELMTjl*Y;58HeX0Eu`Ed7PuTb)q#R@WDZ3$WL%kRCk3olra39W zK>?uwEwB}(39-fGPez-Lhg%+EE2;shHT<~}g^VF7yXujaaWW!CC*q#)k-c)^^4_>! z1?qgqtF4cD9XOS0WO52UV4`?Q1Bt!>pOM*LWgb|b(Phu4qz2p5zI>0CIUx2E*>7rz zYv)zE*jV<+R|t`EKP*GDoXh;LCT{(hWlsB>k*mzm@ zqpecm)v+rVxC;bNs8Cfdav2=#CPUT5ty)tPKA*U1*$&$^1)36(m1D3A+asS!v`#5q zyLt2OYgE0to!)xCEqX1~;m>``&Ys%;K1DlUIpNr%-Eg!~n^dybM6pp6LoK|}QjT0q z>5x)7t*G*+dKhLCV|p#fRel{%RyMyApbl0>chTFp1)O-4$&pHl2>a<1gB-viCBkGJ zsemOIL-*xfnb2ILRZr`P2VW{6613J7o}It|!O^xQ=ZLP*60&5#5V6>)rdyMh2`ej$ zF-&M9_R-u_N%gSpSS5xnw-=?+QGJhcW%tK>uUb?#L!ng%KONnc8mBdcC-JB41b-@p zvb-AgFW29 z$d|yHhq&Doo4QhZaKNi3q|A=mvugHV{TuJaD&|~opQkN z!5cLqx39e>_g@oxxUhte_l#GKgP`g)HO`}-gN3srfn_6uR~X-Fo!4UBC}ImC2+#QW zjx33~i$3|)nk75Am4rOD$mNxuY7Uz)IJC~+TQBdKuy zW)vza@m896#Zn;{gIicG$BZhn7C8dkG*}gssW+Uf8iuwtp9=QX58ws&;5>m;g6j?~ z^t;4{i6z&ks@`Gk@-0e@92|_{FYdhym81iN7NW64DgC}(QiOClcW%|P=WSZR(tvW8 zSsD^OC9Q$vO&a$~h|=e6>Um(IPSi}Wp~=vhmSt|tLJik&EVmk!0^Yrr2?BOVmAt8} zJSwFp@sJFW*S1kflxJehotDe8IyGx46x{g(f7VB8775QD&vI`(jXX`B*^wNP#`4S# zKS$JpNv*{&5g@6pV%-ik{5e?9hxx0Y2iTK;CS&t4fHVH&|7=@~sN2@@20wfr?2jR53+`RnfIDs_x9b zFa~0ZWv;D4*{U*mHo^vBb;ZVQL!pRE_Z_x!=p4P-XbODov45g>F7PE#q3dCi!Q@%Q`RG93&U8&%2|hj zc~j-`9_TGV2|>--Gz>0!`skcygC&VhIeGU3*eQFW<&UK=caZ*^K%%yw3 zO7)qm*NgU8pKo^#pYL&cQo!(FB~)USms~l506pZOh)OFK%0j0u3PsJF85D$$FsE5u zKZYGotiLSy@+wVzLv!)Mzbf!Hu{f_!#XsZPI0lMdn(WqeEBUdDdluU0t5?A)eoMpW z(bCtMk4RHjp8FPxuUhvFw~Y2k>0K@x$dOyQXcg`15L^*FM{LG&mvB$?isz=nZ|sm< zYxq&;5PlD=+kR&HT>|iI!EH%r=4r}V_dBho+mUBqan?JD?wUYjyXuM)W($aOW zw@kN8j&#g$;0$SH&&OFvigii9=cXn#SEA*LaF_B{ptkU{aC?CfAsZf^BUk?Le+f#g@F2<$Oolu`xZ+|b=+&pSJ} zV6d!WRH@g9LaJoJkr_++*kup6NC+h6g)ts!=@T5|r6#aDvq+;@3zc<{uJq&nU3F=) zV%@5r{^_`SWftE;THHekF)p{#bZ52loe6Igt91~rVhvWw%==@Y5>YA(+;g+2T@jim z4T`xP-ff%5P}pVFRXG%w|JU5U|Le0bd>>Z}E;-RjVoirsgcp5X))6@EAa)u3ommW;7b)&*|ctXOpeYdoysVkVycM}^KTF%r%@95 z)EFVK4x7kh~~s;-LC&1(BKBr0}C3zlRo zq`z`k=%wWh$SN!gGNdF4*foI$nO)_4^b*|^!Gyxabo7P{Rsu5@9%&V6jnTBo2wG$W ztaL-rIy4fbrK5Ff!@N{RwNe{`nA9{!@sd-?%!?@j{P|_HNs?e6zqJXWl$uKbi_2RB zrRHUZ62rd20>cu(3ZllSg2VSLss(YZIpzgMu^jkOWLO+bwbYpmC?S_jm=JU^R>**l zLK7NI2$Yb@StFxbW%5gh;)z;ZFCvQ)B1Vi>x^xw%Bhcb48$csmRo=r=SCs3G#Nf~SSEizmlk4u>_e|)TOW$_nHuW&)IcyD;3ifQ zEIb0=ljqfyDgEM?Qu&p0jP6G$f9~+?es$g}<(L7>>I~gf8JqNHK4Pon|^pw z321pHuTf7dN~V9MH}B=V7nULjpHz}M^3tgd)~7}>*)`!af6@)>vA%!bvlKs3ux{Z0 zMLoAp(+u$F2w$n+)RD@Av9mQE=+=;FQ?u5YoDbEY)qP?YI?GC{*VA#j@zQ^$`$4zI z_I!C)8}PDT}blag}h2d6QB??P*y0p~;gbMR^2v+(*^@hx-$4nC+~Cjl>L!I;6vm?@`+a`W?N0Zq239~)kZ}<6~CHBt|l$r z9`I2e4O#g|?3l-@=`OsJL0u%?iYhTj!)WXNM=%H$0{!KQm)ry@e!3NL^b(l&E1a2S zlXg-Z&B4GHQpXTEOrCSfDsxVql&p-!f_}rdm_LVAYW(4K;)K;ZZNN6w@|1!AEi!Pj zj0Q}sE>cpkeiLv?!YYF$U?s}tyABqKok{7tS#JSR1KBK`Aa{r?6@-zk;iCkQ@ZE@B z^dbUia5))MWhc!$f$T=tBl#u~Nc+uOV(wN-=9rU!Ufm7erqbrk1Nuj)4G8heD@)5u zs}4rmK91d7YKZ!X+DBtwnt=Rgb|;E+I@!u|HiXCG(v@BxCxuH)pzhCVP_dUpET5P!ED+y{f*fk7XK?+pk7le5O$_%K$wx@Yjx@RcAY-tTYPdVj+TW9u%;Zqnq^`R6^JCmcs$jyH-~IGv z$L#vIC&%<#^S1SD7As3-jcXka!s4HaqUT)aPa+_)f!3a8-qSoPy?9?G_H7zSP#(rkrf*ZG0NYF*-u6_C2=^DbC?`IJ&IQ z7d5Uu4Kgk>t*?)C=k@`fcWz zB{3Y$+LIP=kk6%kexP}@iDLtbB4C*hT4!!GK`jh+m&+;ridjbq`ewys0dah}7P*(V zdp=vckN5uJddKvYmJ(WrQmYZVBSdNs$O)s7^PqvK15ZEqQwpi$IQjQKl=JUP(@=^uEyXK^NXvJudPQoxtf(C6FyoQ+ zte6fvn35#PtsVsPfe&F&Rl*4j^ze(6O1~pweR0DV&bI;Afla@ZxgK)3+L{mu8M zx>2*5-h__6)!82kt?eu__3>k?T{f~+F}p0UvV|(CFXo|3BiPgDjLF-c(fcgwWLVs| z64Ox7XruxH;ya5YTp{)P%vrNuC&%6Ao|k`KQIBbfzlmNCVC5jBLeczfiK;F5WTmPsC@6P0QczcbhH6%3fK^ zvc^g))R{&m-QU_ZZ8<^uCmiyAg@`hL&P*~MyE&p6p~Y+g^;%};hr}pe)bG-wb&oc# z3(;T}ig#2L_~eo@I51!Q0T=nGAZg(Q9%qOvvZ^7#nFELEUN?$#>JHxbm=W-RX3N|n z^FsHF37l z2)_kQbMGPrenR1kaYD_NxEvI^xX4P7G9`X&tfqCbqzd((*J+07tJ1p#@hZIBXM^+n zrGLlqDa|wasjZ7eQ*akQm$xZb`_i0rt$P=854jqN+TAG9q0nIwI~D#bD3A>OK5MST z#CY9pcqhQEaCWoZccZn#`TVGG1bunRmNoTQu9DW}*?T%B2F&>5chT}SRS z$HSVmHMAntG3Q1z?MO|dg|~ONpSOq3?+^U^apG<6PIK0<)z@ddt*+iioE~qB;Tfp^26RNy4qReEizQ2&0a-Lr zxx!$IG4kxeveH;9IB@i0egT7NMNxH2z|=G+nyn(sk$6cFJtqljnro$%uFCLdsXsHZ zqp&FH!0?2H3qTZu)*$_U70U-5K$e@PMmX?}M{Q`|-xyFnJxEZkZC4DOUu zd%_L6v*b$7rETvDtYPZND#2-pQ}0-xga(N_W#*<3jkT>vri$Gf1w}8Q>k%3T8mlvF zLmO>M&vMP8UD&MU=J&qQSO?=Ye6iiVwma#Lkn zi69dlBNA$&A8}c|O;rMW>%x6g~5kN<{B&Nz%jgXtXd*f zSOz;5h|vk`O7cnvRezY}jF{0kFN~L_si;bCJbMvElp=Q)b43~q?6}xr4^}rWvHtcL zMs12G9!qho0~)ytc(a^+k0Pv_k|tKHq_P7og_fd&SEe@{!Usd40eolhN=8S zYgw7tS&`+7XDuQyp(zZA*f5%)nv)lPCQaHwWc+aAW{{fvRx2yi?FHKg_tJhgaKZ~j zt#6bCZA|-xCME#3%zyEKl8kirp=4$z3F~cVSPoDX9O2;qAj1vD7)0B4>%btasi+8@97I>BvRk}r1Erz znvy`vqEIgD{#HMJF@}*}_i29vlC2*jXnxUSb52_BMbSh}nma?us$p_@ly&k+V1jvf zXb=xR1D15H5A|H9$d=W@ElL-pstdR6klY9GD&Z>iOZt_?Iycw+Qvu%Ws%xhj*LDB% ziJQjut!0pvE%2<)OOfD5<$ZcuxnQ>d_aZj7GQX06Bi&KM#6B{M?%?x1@CO9{X!OUJ z*cp>zY>}7|&v8$wi@@i6#Z|*y$(FG+oleUvhDJU8IDNZ?>NRxo9U{DUJ%^w%$cDFn zOt%j0--O_*&!h+P9nWxs_h(st1OyRcx~7pSN2L3)M@B}w77i4ZupTJ4Q-DNPfOXl# zAYU93xnONUJitUtLiT&(bogTSh>A3w7Cq@&RQshJi{5#+o^!2NtvqVAW@EKQ}h& z^!Va8-`Adc*mH3GKCb-V&iwUOQ@t;a@=*Qyj`L>!EXuo{*rUkrO`n*W2v9D^tIYRT zaJ7^OmK|ZOoZOV#(Q62~W7M@LykTpWlPZrGACD*)C97>#R&8$RnOVAOiQ2Fp-233S zBr?{WnI51?Mol^$!7Mra-Jpa84y-a=M`x3Yu3dN-d9qo@mGnhgV z70IQJF0s!d>3q5ioVpcwt=VhNZNh28YyrG>INIjG&ROT~o3nZP#`YZWjCth=C!@+N zKXK&joBeA=YK6k0LW4uX2ZJB{&FY!((6Hdo?4IM@wxG2Y%)u(hs+&Wa<&ucZzK)hG zx61)$2xDzZ?z;7ep!JMYwH|BSey5t~C>ke(Q@kUNr=ZQy+X4?F25!>QOFm+%IT#>q zDcJ16tk18kkC!QuboBfTJmcab4&OpW4-kdZ6IDuz9qDxq_nScYEs zvHD|A5Ltx~NP9-LKmod)LIl@?3Cyukpt-yao+%eo3$x_YJ_-W`)C*_lK^GWA!2Z&Uz9)+B|Ij3(qAwu2D^D@e0QHB zu~BDbaV5;kON^Biy=Guod8qdikAvV^Fq^IJvW6T?xM{n4>$&uvU_JXB%*Uke;p%m- zwXZdgwvRqU(nK^W%Z+DGQhImeltvD6GdL)BvvycW?5zgCfYWLWl;z&fTZ_1 zuj#y-!?7k}`lGm|eH&Y9UHM1yt7NdQv(#^iom{im&UY*G(L{ON_4VVWL?z4}MgA6O ztxQlww6pA%D%T7n1;rHYqlOkVs43r}IJx7&25&C^M^~~WqO_h?LpiD`KLY3R>J$5Ibif>7sH5=HytQAze;c^EYEo_GnMBVcsa8!a%%~&C%71=S*F+ zjRTqz434<`BYd)9OEo?iuSLKlh7L@i&J-jVugO~34N5Qyn`Rls=^2Uj5T2Y4UDWB> z0*JpARt;HPS$f!w9iKlBJ0zIZm2PDyj^OFv;imhe<+6(IysXOFYx$k29h!@S@I~)M zWXsr0JUQfKH&qVh$>g;yddSD=69t(K# z2|f#SsB_q60UJ|3Y!nSZ;g45I?B*8+uGpVUfd!miegp%(o`X*KzJmc;g$RQ!5Bw~`3Ws%*D>&4v=abnl_OdJg} zD`Ca{rbP;ukbQIZUDWl#6M*SO+6B z{F*Wu;TUr^1vF+`mUICL&a@EiRrQ};%l`{sK%l?KQ$xmTpG za9{6vRemM&mi$)cefj;2*%I{Wz^)4VyrFP)&{rM`lb}xUDLJ+eGbj;V7pX-7tOXVNlg3D9@9*W+;$omPubCX*=FW>y0O@}#T7igMoS3o-PV zT8nEjp_ed87R6#E%Po)9to>aHb7{O`4|OI|pcVA`0-*1-8CjZGraog9C@Rb-I24de zvYWos{2=@gTYjec(vriN!=*&Z%Ca>pOSUZ1%31e#@x(!Q)}1LuC!!h8An3j!{NER! z(NI#1X?!VQ^?#|xT-VeYUu;RHP@Y*4bvex4OF{Gd7@xw!>6KBJKei-2HIZ2vaZP=~ zUwd}zEy0RdtX>)7wyr8KOT<3^SDqc7-FdEJ=jV4*+^R%~ds^6p0(g`9HH{4BrtF_x zFRPGvXkrPtTuDuCwnq)$Ht)7RV|d1VOgQHLnfwkQ z#!2Nr`Tuk~ow$tm2tKFB<#CtE8lBr98_McE^E^A;yA+M=Ap~Bg(Ic8T4*}81Ce-Y_ zX&kzt)6se2VHRRq2Wp1k-Q~ffp1mI8d5)_CP4?^0Vqy%8r)+eT{vyeVd)P zk7JE$S6N7`qAJ4**RSkRh~jx3|0ig+CakKCHDoi{Ms|@G$s6Q7@;9O-p5Sx%UW`kN zX!1R$TB)u#_-Vd}302D2ra%J*ov$Q54)4<87jif*CY-OXFE{UVEH(x>m>KI0dS>&Q7(pZ{>(1;qM2~npV_w<^xC-GXWJoc3hqw$#M zjYl4TH?#1G|D1!@UA3~yi-p4HF+3MP^wh0STswH=)i*~rZv5`S!s%wIrV4o1!s18V zVR)YsilXQCuhjxy7xxQ-lV&E9cN|+(o6d{kYMiL?{`j8w$v7Xk(qi)(v>9zfyTB|E zkSF#W4ty~xr7`K5{K8ILgrkvYI7&o-nk6U7fxa@HQs|@khbtou$ z*I|blAeRxKC|1^CpB56EgMsJPW$@@TqUR_5tU#G9m2gj1uHO_@>> zAq(%>va0{ln;*IBSL!rqSyhradx zOaG_v(Y|l39eM_5KYHYvOlbDf!lQsJG>Y+Y;I0Pr(h;zkPd;n+%@L^oB?W*-iv_Mi zHy5d8oP#I1nnUwj^Ge=0w;b!ep6^2z~3s|J(yWmS0*fq z|Klh8E57P}!}N?2e;A%xL1U^eyc?M5yENFGx#dty+_rw%gq)TyO}oUW_Fc3 ztkdb4Ca7nndKMF=e=M{%|HblRiLEa_bB2*0u;f$uY_`OChf+9?X?XXSR_r?CqBtGL zL;c?T1EDRSe=xH=mt1z$N<}i(-nRbHuWrKEX$m8;W@QU^iB}6P6HfO9}V}0beCxA(jTyvqIy!E`Zkua3H35ald!KOT0D%${o$;C-eC<n(Wea2PsN2L3sf?lI9*C+ey2I_|EL`&T`R@CjLeB*1T*UU$w zM`OQZ$Oq9sRT^x$%6#Qls&1*=g?Eu%+^}=lJM0_w@2J{UZL(ks(SyM+ z`t_AR3m=PU{hZ5T^SjDCNnhn|-ERFO$~Pn5j2dhyQ+egW%EfhS>aI^-UwNnb$;jTi zkGK!~#-z3;fLl%@HkHGM=w;5W3OthkOQ6?Q(7~5!Q%-?9_6X#G30~XwG8L*64 zILkP0R6Pl=r#h&`+RD)c?oSLPh7+8U$RtSOIUu@PtnBNaac=ia4xM2^Zd24>TnyoS zUp5Uo#{MD(kaFKsP!BAaYAL6rN$bp_miAs%AB{w!CWFIdGHf@OmbmoENc#B9WPXTw zDM~N{r{z?&qBGT_R3BsL{_>VytmTR)t1I_pv8vA!*nOoSST9>0uFqCOQ6<}TS)&xN<;)6A=;9Aw zmSvu7v=mAlDP=}FJ8REY%J$N=Y^7^iKv1hTxP>iSso3Z_r&Wsunpv`(WP(1Z`jkZI15$)xrMdA1-;^!LTlQb7*vr+dZ=;7Gzb#TIZVnl0Yn%{?e?*#-99#>=AI5nS-vPU z6NZwZAs&=@(Gt}{`CTT(TBT~5x@KB+&9tH=YKXS#YMa-_+O@IpmNpjN(zb|&uq>K6 zZ_!MU%c7YJETS>G9@=)1o?d2Aik+Tfr>B~j_nj6rN%XWPIwNPG=Qa81g`3#o8rrmp zuzEtT(e$MV8#;|rx`vXO_9?tvx`tB0{0-y9->L@MR3X##XH^69LAX5W+RpjZ$Dqtx zwp^uc(#!GU<(rppTh1+CA`OHu-$&xHL6Ee>1T+GywO%gET6a zh7YqS;uOnYW#3Hrg0;88<>BfEji6b!e1%4?nP+7VE~~D1U+Xv zJOX0Rd_0$F0L;C!2f|IsKn(z@A-pIVn75F{3XOB-1CdlRkQwJp2O@3BKo=1dbFXc}uGO|;C_v$8F^Xi>0dNe>zB8R;RYN9rLxz&s8)T=hNu zy?x_k)w6WT;W*yF;uTWo;*QQxhuo=B);hiXkU2+k?BBzd>`rs+EIJpoJhK)k95q@@ zu}C~>1omsTgw3(@*8&Y8%0elN0Tq}{_5TkGf~Lck63npBxWD+~!?|M3c`Jp!^c{#g zykvu|YE#{co1Gi)?Ore#a+&mvvkR^ESs}Nc_a#;|T)Bu4XG>S1W>MB4gen&|HY~03 z(6HxRt(Sc>q7?W1@diu0V#Av2yStaS++5hYLU9G7Q8$Z)+Bs0IHq1Aq3f*iqQ8a43 z2+C^IvdX4{b5)}+8uiUujxTwzGBo{tiN#=>-YDFIQbarBudZT##VYn)k}Af}d@x96 z5o^s!%vce&nJI&?Q8G8%*wQ1WXqrXpM$`da>$TBXz>Sb4X`yawo2W(U+~kBbkvmRT z%`pO=c$WsY0d2zer8xg1$imJ+)TvvR6r*q@Z4xt&AZE0P87;DIyj_|_G_!Iz{w<52 zGn=a_XIzCWLXXAI%}goIxm(%o+#TmSxDMld&mG(yM&V%|r>nMwM#K@#sCHEMnDm%+ ztV$<|l7_6QSd$`tt@%JedtVqI2x!JRts0C3MguQ`;%AM<+&HyF!cwLpX|sx2jb8F$ z-#EVL*O_CfwsDLSu}#cxenv-$K) z(g!HO8gSM*@e}^o zoTXFmCd=n~_V4dKICyz)OMSpyw=futSF8SyxkXb?42LVD(ejRUWYzrE9Y49YqpCU3 z5W3oKui5z4-1#(W@BQMR1-iO6fnQR)ciOOR7sf|s>Bvz7mPx54vB<&7*31=vj3FC<{ z4l_F|%syEWE`_$ksbNp~+V9TTTKPf7ym}-$mCS;}0serlu*j8sVUv^FOKva(%2SrP zz%){8O$OzMK$$Do**vx+&Y`SrF^2qyS=|yf)E67a>_;S70YIpA4A%_~TsK_N8wH)W~|BPpi{~LvWtK!Il&`?4q@TX#+Nq zuo8krg#ik^&hgY2|B_oO{qAvz%|EC*+fse6yxPNg*swK(DF&@|HaI*EZ$uZ?hpdV% zDk~nv+oH?rTWr)N+~QrRU7+jGcgmff1>VcGk7{@8zU_V3HyVBlJ*j{xs>sg+vDdmA=DW5m5lqV9UJQ6A8 zRx8U@)#I+Qay+nh33!}DyW`~Up zNH?J)x^evCAt{W9!==%HRy03kvDb&_WS&P#r3Q!2&_xv~@09$32Y9D^#yd&#A$bx_ zlOhl!ozdGq{rv)A`Xe8y|KaNe%tuX^4o{Vs5kJ%W)gh;XNpfI0kD0jsTPX3}o`<|ChZl4{W2j_n+BaX;=43 zvhHhjtPV?-WJ~g$c%3_O5}PFCB5qFSAcr02B9JtO0!b*4wA|1_D1XlP{r-Nk=h&Iq+1c4SzVn^$_cO>2Aqf9j zF=80+Gz?a01U)0xv0j(|{U zWCH+=N{mDOZS1rbH=hVj$yjETbUKTt1+C4CMwlh_b}cWv<#F71AN+K8Z@r(9WyV*1 zHS-_0S4#c>K|Bm0#JvY|i613VJ+o8EE<_9cd(j^M-rPOzZ^jO}55+!k|5xny8GSvv zI<`G`Z_PcqgOMk4zi|H|_KUcdYaC*JKWJK2+ejLbHC)EE{S>)~5EjEBy9|J#NdUYbHjf<>%q~u7$BX8MBDQ z#>?@-$dbmM#=gb_jeiQ0vz%R` zTB2UUFUf9IZ*p()^!PVNHpQ-vU$4H=bEAJ>uCMX?nO|l;jQk_wS|Aj6f{Ob-xd>vp z6e=VG5jK>lPvzKjC|)RN?1?z6o|$xRlD!rYhljh*jdp7D=cbVJwC%jMc|FT3u`!IbQbJhyG-gC?GDxo*a` z$LybWdmg%~{p)i$72!*dL5MM_ZbdfywK5K(XUF~B%0hSC*dTx)XVi=?0!EkX z;%gVl55%k#A)|td23X-Xg!mHuU!?r0v;Zkoab2x15^vN~1Siz%9rjDKbX%x|00Fsp zZolJ%qP?CF6p14Y5LsK3*1`I1|I~-VXbU2ncdK~*52OuG@Px$$1A)N55W8sRJ zq1EcIm;goM)mnrj27M`;qWEv2DZgKjJM?&ozDK`be?Wg$uhI|LFM<~=>ejY2U(l6- zk&ja06i@KdwPRU5<{DRi@<>Zd+HDLt-ElKEt8V?Yb#A?n;svtGeUr<05oG*JlJh`N z3SV^;rJ+o>H5M}IEzZrJ&E6gHp7b4Fe!KIz$g%jZJiqe(GNN|H#B@B`AUDLC;@R}V z*qT^Rx-YGJ4Pm!8;cfH&-1RGu>ajTfe&lV(FC%ZmDEVPT?N!3QxL_n3%pn}`@WC() zI<{aK`J_~(FWwSv4>RE~Z>x+$Q)dKTupqYxW1ZseajV=@shIfKmI6v+CEcH99-vTN zY&wPMD1qrHQAC`>A(OGF1YcZY(!C7h{Z;89ylpVJba`o@Ca@Z`picjEI1SIhATH%zE<_ zm*tKWCft1;i%eV`B~;0F+|FpsjYD{nad9#qPx(waTC}qRJDE+-BWo z!)D`FQ;)wV(39!O?iFs-?KbQ-UT@l+e2jZ6Ct3_SL*7vE<$QTxfru4WagtvOBobA* zv3M-g!ew1qe>RW}j>(THOfgKUoTHm-m?zFn%uV_NIKX&vfr6)Yj&qJ{j(b7PqTHhV zqQauug>^<&r%PCMo)y!S{N0&*vX5m>#9yj>EqS8xY-7btq27bK z8PC)B4b0$OxFnUR7z+1Rdp*AHfXDAY<|83_*S!^$&?NN63ccQ#)K?n0sD?V~Fdjxo z9j|7?aU!jV6+aMEI6$UB99G1P`9(AHju}hlr_Jw}S@RIH`?7c5Fk=`1v4F8w^7gc|T9I*k#+r!!gHcOcu`y~DjQDiwEmn=jg4 zC~qhf_Y*GJP1p$jqTp~O%Uk17T}qQf2@`3oRDG8`q{VmIgfOtDSJqLJvu?05D_+0uDv(ds?Pu^+tf)wVxA-;@u0$L;d* zvh1G!?7E#_t80vnJbc^qQ%|kiUhi-RwW_rv$=wIOwCl35xwf4v*WZ5Gz3*sLE&dGt z@z=k$ z7l@)>Aj~5o7uRwobA|$3T)>(9b@Ids@imy=GM7lm9YrMktJql!g?5w5S%bs3D3+k#SCzpmCC9 zdHQ8-6OoZ`5T}Y)hrjB^hVAv{;KtNf@4#$>lWGR0p*C3D{hp z_GvAv{ZL}8WQFIEqz(d6+ZV(H+O;T9qzW!+e7UVGaw$?2ie9=XJJUk&cO9enyR4B= zeML1iDO2DLf}D@)qglDY*GM>H04t}dm2kB#EqzWHnChRyN{f|qwlX`bs74+uPr5n# zMc7WNBHNdY;3dW`gWb`|``T|>v~f?*6VqzrHI9b15y@2-v)aV4-znp~#<+g=im{h1 zQs!qf5w@ZCt?f(KUH`K)_wBNoszyHeQqC{S*siNy!7f{nbsBe#JkcF)oIi8r(VuLb z>9i2qtP3f z!ygl5gk~xmBz`1P?7ERo(lDSc0|7;vcTwpySyDbtme!D+*c>EG`kXmTk$Hmj(^9FH zx?D-7;lhkeB*Vdn58=wqvAkNAjYi9?%SYZ4mNYZPGT>q}71Ky2t!#0mB`uk~zt)kjs%moA!UN;iB$dXdto*f+w@Ddh<346S zSlZ&T1S>Tqj+u1|y#1OhEb_vA}G? zHJWSzTc3@!4dF^f7ceb0F(#Mu8xNP{pN2c>=6eaAut*kLi{PcS^Obd~2o1Gi)kY1^ z>tstsbz@uYxK;Z`o=k=Ibyy9W3Qc3KdeWxFs}7UWdCtGf?}Xme!1~MlL0q4RRuFJe z!sujTj8~KOa5@X469|$I5eaD#hfl)q1mzPdE{)p2>jkZb*J`us2Hs+HS{wAGUGG6b zllPFdGPquFmG{9@t0`orX%=wvHIHi4QFT&C>EimhHSSJ$D&w*0T6KdvpPj6pz_;n9 zc;=|*^YeuT+WGqV?)lj{)oau%_;tF~?$w^Pxvkt*^;UkX_A1>q`fJ=*d3JiQlD1@S z;BFRf^6ts($?mQGI)9JuHtTK9d)#+>ZjaxQxjp-s@Py_G-4pJ|Jdb;y@I9IthO76i^LGa}RB>H=m#|vHwrQpZro`Ja+yc+M z%w<`&gYOU)>R66PS|HH8_DrQW5vb-Hbeb~c8?rPtda@cXr!yC8)?*QP9o7jAF$+UB z=UPa&eU<#m`*IB)C8hCt1&v1Q1&Yn@7mylzkkwt`vBonAPu!x1Tw?yHC)QA1?`ar1 z-!tgZX<-KJRw}XrFX?rr_~AquW7npeXtt7*?>~0E;2tTGb37+&1b9os`pp3?bVB`msI!Ai&NES ztA*~9Z~c=sb}?%HZ~10R}Kc(-b9dLI?tSTiKm_7@Hu*X zLvr}NQC#7Y6l_`AjPe*Sc!Zr7aUH*i?f69is>Wslp~{QR3yMt1BFu0no&GSz8&@jg zal4_#Pb?`5R={b|wG`(^3Lk6>l~|30+gM^g7D+v9jm3%>s}~32BB>WH@H-3R{1wTO z8{;EC82M3TWPO#sVqz2i*jcDgVcolN$>ug#T`p^a5hL~aD$HRf<+De}sHV%&eE9lL zkF(1^`zE*Y%Z{il%h^!)%fmdgyZ4HksMTN*U_{O)a=V5D%!fO&4p?x?q*t@&Pcvgx zx58*P3n(zv4+5)d5ynKf%fPS|3am$BztBZPn9x$6UlW(- zV2H;L{q6F00}w~Ci4*>2&`POn_3*LmoT$^F4Zy_C{>cz_Pwcu9Cf*O*x;1sG>(MPR`JKjZfyuiuMcE$a6&beG6M zxKv=Y`~FW%e-}UTed14POl=+} z;K!tr5RA!QjZy2-*u4&qU0`^RU^7>EY*+bBA`w{ghRkAxxyOtNteKGvvS!8)9nT-| z9Ym;Daisa_1<}OX>~_Lq_71^lsWHJl%t509OX}=kyC3_9n2!{rM35xU8d>9`5*a?B z&AHq_4mjQ78Ig9-lG?yIN&=FVGF2MrB=FL^RXe|Md!}gb7I(hV%s0b7k>KsTAWhZ_ zV_uLdwvf#Rs+E<)#hnLAa_AWL@!`KL3NyUy!R1) z?XC7$AOnk7lQVl8x9HQm_gtouWiA~|Eye~WGW;K8+!zbvMnC1o{YhzDh!-*oeGC0- z@mglBZ>?X*1Y3gb!Mjy=c^*?e;^7(W^V^BUZ%9MVEei9_Ff?D$Bm{?;6N*)XlSpwG zTP!BXt^++yM4p+r;ubWti)(0a*3d4l2|4V6q@N;Nk~@%J^e^@w@N@oSOdQ$Ie^ivy zDq%%J?t{{b&LSaxu9Gm%`~-l$;HNnBraVj$$=&(|Km*p}3aqZ(Gw+(OScjG-gH(oHr5o?R9HO}S$ zn_(FO@J1#Ag;lXreUwq#QjmO#kMWtCMUA9kOqzg((MI`vXlAz&SB#~c( zJw)=}9koV{dUF->U}qJs;K65Cflt&Ls<4Xz%OcpSkb?v3;w|#zwJ}q@~ zZpPz(czEjW$3~tXd1i1AuEec)(UW^f-ONA#K6_ZT8aYuMeWp}y(QMUjGhU~8TmC>+ zt6990y_&n)euIN+7UF6Z8+OHAYF1h-U||T4KO#kOG-`sbd&{5`sfb#`pvi#IF|434 zQEJe+QKeGJD3wbp4^*D2M({sP6wGAf~o7xBgQM0SzxnGBu(1C^fA>!b3e(8@n5J+E}+hez2iM)AYyBkE`Q{|a!b zDB&te(Jky&?nZVu_Xzu>z)$9Jqfp*1aXR#f^VpFX#G@st4yg7Q;pU!Jv8oUCc7&V} zyXC7m#OnB{#QG)d);hh&<<#lD0$c^SpoCpI56}c^k5p<$B^)7WNgD~4Nb#Vj3vDSH zyMR_|Hrq!V6R*ZiH{5&6PrmilCp!+#HAzlyr4d`Ja_bwe_~tiP6bfSz9kM474+&;nTnQa< zm=)a-pji-`aX8#2iu*!wKkDn(G)fqO=D8oiJLE9@l-V0xM-}`XcU{0)l+&eU-J|? zf4*D`m_>Cke?ElZoyj7ML71sz6DSF@3#qG-SJ>H<^N>MbRmOb7^NsZ5nW4<+^%b=R2gjlCHAdsN+Q6apS57zzYDu3)G#;K9MLHQ;du!!D;2)+US`H)tvoL+Afg zMv8u~j1>J|2`L(ALs6p<6n%rBz?3Uw1xBDM=@kTqma3!+6pDs~9-(m7Zd%d_Ed?=) zd$I?z{n=AlE*p?2nIjdo){BQxg)Ej`R@`mH)*?`Xks>JgDR$*=1?#kWYi`(CP$1?6%x%+eWD8Mv_Vm>LUEl; zW_VmeBqEa!ML&jdgA632GH?`S1*jp4e0)JPu7d8Fl-QB%kMXHoN78oLnIHbY$pQIERoUV= zi^sfl=%tY@zuGnTeOxp0?`IcolIwz-*mXpm?WU0zeme5I7k;+Pizi_RcHs#=G8)PF zSKK0Y6FqZv$6+-;#Kw-O+PTFX!@a;xC&#O@F>>bb`97tov4Bt?Vmc5xF5x6Pg;Yqb zR>5Ll#P}qJ$1C^%41QR|5@zut4bO4x1=N@_6c=5c6Xt9SG-)8dKklSQv=Rm_`IEW2 zPrpYDyJ^|(u&v~qdF@>N!&vx#Y=h{B}7!oU)mQttyt-Hn42ba zTd0nRr3_hODes_x=Nvui(h@0em>He2S|=HuYG2Bz;|bROvt+|e(4x$*lSCdHM$H!S z%txhDE{iH01XJQ7VUT%z@el%5(CQ?e(-@H*kZUnZ9TuoOh_)yXLM22bH^b$#3)ZK_$h(rrXVkw_&Njy||#9{$*@gnUEutbVV|060&PBx{)ABl9M zt>xFn6DA5cM$|2&7|}lKk8ycjU7%5#5||>X+=8{8?3V@G{cbJ5*y1NKn zqP8xHzP#&Fq*kI>JxoD)OI?V{IFgc&%AY`I5n~xNB&T?b;raR8&lr8DY$h(OLBc%!$S7<;Wr`4Dl+xtKrmG0H>-&}E;&y+!Piz5LJZD$%Y^~y|FX7 zvBa$_0F()Qg+;b{pNPf3`9^3;tb<~nv-8g^!!ABm?4;BMwLt!PU_XQmTE zM0zRi_y~NwAT}GDcN@j#ov*w?oL7WbcyI&=r2w~`bU{!)!cTYp?0}Y>)c5!2Gz|`- zGYS6piQK)7sK;r%<`#qE5nG%j6fTIXSRKX|6~UY12@}4S_=uS4bKoZ8CX(CPBc=vf zG7*8{UksSYQ6;CqsUaAK28b}w5VC<4m54Dzn3>#1B=w1q@qnf1n2RFE9z%l&6<`MA zP%I6iXlgKnNhvlW-hXz$)?hC>7RqiUnw)19tF56{ureb8LHlHlB&QR~8BSYJ(*+`_q=x}tt^2!xvXN-wNR29B$=RaFl2YqGE$TVgLtnRI- zQ3>B^e$>p|sNZX5w0CRF=x%IZxkq$w+6FWrQxH)d zte_ZpRX@Y*xT|abH*n3z*W5od=$^K7q+6c8@@x2}pW#}3enaJik4El%^{uCGdh}i( zAz*pR9#ySIT4X>!SK@X9Hlc|I#l$KmT&c%49y4mpYE){>>2(Ig=?xq?8F&bL6$>v^ z@Vp?f98g~Z3K+2AIQ|BVo;v)1Vo+hVMo_B-6{pv8$MIC4Vg$TW(P=a$7C*o~O%6xE ze^Z>eg#v#N-RlFUQzq7=R(Q<2j2EGMY;2~;9?dh(k@J4u6RDaDbS^sWh{L_j=AuY0 z5wYh=M+2HnCISafHVt~QEo=^(g9V%e2eU_y92|a`*|Oo_NCcm|b>v>WvX8y)vzwU* zhZmFeP8z<-T>4cSlt_ZB6sD+H_#9^VELMcEMhl;$cw8QASo3ePiT}zg_ddjG(J+hiXM-+sdzxY~r7hzWWGvz#Xcm4$fol-SKv!Z&XvM{ipx_!|z(EW-Z6;IkB zR*}3qQKYYaojgIPD`jKPtJHRYm$3vqx?m_2@OXove87_qh9(9) zV=0!9mM;E0!LS_gR0YF@fM-lF3^fprL_A~1jM3?|OuDMd>-7j0Ylu-o_?-|YIMh9% z1EG_lQz3O|h>;YxIC;tB6O&nKGM+q94i!4`OY%(q{z(KmXoh&MmjDKdL{sCEQ)r6E zOVX{U@~Bb7eIji93wud)T~&msxP<2%{MXx0rCabpW~)IfC9_#(0u}f$XalKicKG@1 z?5Jz_CK^>ee7v+J1u@J-sKkJi`8mFRb#WugA-1mg?2Ze&Quv!A%P-oaT6I_V_QaVh*g2N9>t>7EuUp-%#abW;ZL2HHXf?L_pVDb}aP^Uh zldlg3jrE?f=6dI#4YI1JkZf6-V(YN=*i^P-SVnQY_Ao`+>@3cc=U@^g9S|nVbInB- zSy2+UVRU3790_`UEEP$Ii#p2YAuI}>3a)~mo%-mH)7#gs-JbsOqg&Qj-G1BtyQ~ z(%(zJ6MjejRrDd;N3Q9=_OS^uUrJE5sCD}E3`6ctJ+Sg34gc!ZSW3`DI{Sl|0V7pZeu``u` zUvcVS>Y^JjwH~q26buCWf^6`0k1IkTVxd9_zfGi6-!KubByfx6V{h=rOF-Y)f5BbD z?h*jpmp(5t#2!|P_;1QT{_)SkLl_+%nZ&$9`)8jrZJPzlLPEpLVXv@sFpr^wV^my!5?W?+<8|*yNVzq&BYhreT!z~+RV;jC1f5mWv@o{8qLXEf$ zwc)Ap#rTTYqTH3}O1y?y6}>XHI(H4;5!;&Dkt64A_3?eeb>{0V`zrR?@8<3lZa3d) zxzGMc^r_fWxgqX|@PY2X^dA^Mh<#9#;0>BsBWl3)HL3{$(z|0EwL}L+C8OP8Y=vaZ!9y7e{V&g)}`vpKwZG&y(XO zJA@?yyI43OoD|s7iH4L;5(tBdGKh!Hk0?IMBwi}@z!-5V$Yz5b!6iYK2oEz9bP(tT z$~{bWZX~>q5@Q!Aha#;&Z24cz{$+ZBx$1KhJWTy`;+HRxG9muYZl`{VdChdNJuptp zLjR@QVw-b=>5AH;#uwd#lb)OPhWk5{e&hbxB%w~#WUMzex|^bfy4p#(Swe+R42jJZ ztrg=c#-}`~iDNutCeHNCoVeJtc;a^FChw;4+o$Yt-srty{N5>dJMZ+~G5+o;PdFd( z9vuJV)bB^XUngBQb$kO?Gd(}4mUAa#5uZck0$Kx#)z)y@Bo}B&?+7&y;pddFCEvb- zN9b#eAr;bgGVQi7CNA}y&dR0?us_gcLvWbLe$=IgawrhM< z3Cm=7Qccx^6T&s^(W-#l=rh|rM*Fy!KUF!kI@vIOYcgKvv!%1Ub2YK-EW4QYy6PzG-<= z`b2lO)oaO!k|iWXlJRsVGe*o>vQks9HkM6JMg|LNm0Gi{CtJDKs_^Ej9hn=Fdo$el zOAW)w_w9+^~y$E|h? zq$)ho`X~|hq=KF$hg3pmN!+t7EoE?3P|AoQvlz0#DzeJbq853N+ATpYv8uQy*3i=E zX;5L#qk?|raYaKU*G!$KzA7Y&AzW2~aTP3UEEKa;%2W`L;Gh|C)WV^L`g$T2=XSZ& zYL&3M1-B#-VV_Dkix=S~xCi&+6ZjN9i?w)&`G;bfAkCImNUT(YV0ps8(&Rfwl-4`T z;+y9>hk<}(!AJ)^{$B=fYwP6$e?D(i52j}8^_N-lEH~kW-Qye zfXdmd39d+XXO^^b6yB>hiKr~6X=Q9pJyYql8(PAmfnYMcuUPdBVW+Mk4JJIr-Vn{& zN%)B)_J&a0PLBUQHDGV3APgiOg-&IPXS+0136_SCWND};U=XH;SkbW*`A$;NNfw>4 z;C%iNrVD%>`W6VRvJ_Qaksyn)SbY)4rnU|fZFa)iDe1ZwmEB`SW{;X@C*bh*EenT_ zHF|9x4WE5)-LtqI>=o_;$Sef#q<;roHmyk?-N^+PKXo+RPY& zOpcjrN=U$}UqHVf&-5!p*BD$_N@NT2B$q|&*y8h`8oI=bh~`L18`+Q&<48M*tTuk+}O5l+uYc;t&MHl zwzF|=te5@$s$RWYHTTT)bocb!Gu^l9oSFXirZc$jOl~jqhf(g>-^gX_2(?leO%bu3 z)^+eo*C|N~a@3Wo7Ol#Etv`vb8!-<|;S~$o_`{u(Z*=9u3?bXv;vQJ2I?Vo(5%FZj z$xG{(c@dREo^2*9%zaPdsh!h>h zIO4=prKu5~J}xP7=V2?UXN>=i7r}`OcRI)@O3Jb`jM=aTvr^j6OI3wsc#hg-c*?-w z1GZ_`8%lVLOq$F%CnJh{l#)gPKZFAHObI^GXQ~5pxpxvbIk$`(y@Iq~vf6`#$=NHx&-4fjc-Okh|EnjypN?>Y3s?>d;RhO2^ zMps9A<|exbz9IfXT(&84yd3fr+BYsM0u{_*5&VV9q+*?rAt&YOqr1lTSUCY8Ku`io zGj>ldF0qMfR{h2f@qR-e!J&*|g6&1ak%G7C`Bu+h2!B}8T_O!~BkYD;OypPq0bGJC zLR4`On25MtXygXB_^9t}8dF3!x$1xdd6$I>4|&!xl~-X(I;+J!8w_)tU*9NoIp!WN{RMnZ$2dBlY{;Xik{ZX7j!1=NQ*hki z^usEu4(x8lweJsI)rl#}MT=f&#q*W77vVP4>0vb;v~}|79nMdDg(*I-N9 z@dH_tn3T*UQ*B1KEX3@B$au@-b^Gf{Y2VZuss@!7tr0G(g{zqL zob}AM(pIIWteh?dw}O;xqBzDIdO~R2`#S(jlAtFR6kf23Q|33M5t`@4bHMq^&Ad8KTztyVnm73g4C%qeaG38+|)n<^wxz0{s6nRdbi;CdL=Y>zm)MEZNJnqup1T1_B$ZrX-_ zqWS?0 zpHAR>>;*lbUnXdu3%@Ove+M)gLpL7!5nI^}-$gAK!7&uO{KkFz1x&-A!wiPO4L`uP zB$sDtRlF3sO$1i2Gt0_jJE9!YtD(#=iW&h0Ru1EmTr0l!u1Av#HVw9B6jL~TaP_%M z-g)k@LiluFL401w<6I=R6nihXiq}+mb?}t=sCCtJ4PUXms>;FUw9(`vxFqz(BPLcS z)fK9y(?^d`GwVCn+FPO+h-(hVEyt==oe=0zv&{x6!&+hN5*Q2ZptV`^z4JaT1oV9@ zuYv{4GoF#c;?mZuIJ@Z{>@EV2Siu_Yr>IbIqjO3MYGGvrR8c>k@t<(KLT`$$m}cVpZgbB7HXm^L+m?V-}*cbCz7Lx`QW;4#OQgeyfv7p>1XM4wwQ>8er}e6UkG z6fz_si?wH*V|AfXdMSQo(e+Q3J`hRPWz}H=sqEnUV0vl_K@DJ#pUQA9Iv$_#9m!x< zdx7Gb91Sk?T6`|*$ zi>{{XXMm_oVn%VQROuZf)N+NU5|gXuguBQm7u^axjczd!PmIc?If)s#^9~r(7`Dl+-yH_6 zj$F`t9G^tP@o4|MG6U=VaGRO)4rn3XsO?JN^xT>(zSecw{miw^%p@w+&*iW74DG@# zUd2ytR4)|lSsN{afbRdzqEOm9bmYITj1p!sW*qSzc4sdiiu1dl%i$;L`=g@1qb2v5 zLcGwNt0*f@#KL4tsXdfUe0|jh(uji&{MAD?Av?RUkcMgCe{y6^MUpk*&+Hy!R>d-7(e{%%*(qze17hkn&{K;ub zIBgcuWqx57q;liA@SJM7;h$LnWScICQ?<{vFq@ zJn`SahO=NQwgMuYEm zX|!?f_?N3lJ)4FG%*!N|=uMpCmev~-95G-6*zrMDBvZ`z9MPuAlmxRHfMdYgC^Us@ z;5O*&Fl){lfIqq}G5m%`uoV!)Hkc$NhBV%t zec=~!5Bx&Xgt}7xoeA;e9X%-QyFkzb1(Er~mj7Cq@TRm^8kiaPPNt5pQE1D5GES}I zyyL`A&GSm5l^x_MYLBgtH&Y&;=LA_?FPyz#g5c8HeHiQ$?J$6aW)NIu=NHjnET|jQ zCO`hXAJh@19veapFf!RupgUL;_+2`14Tx>VU_Ji`UTY4l$M*Oq4ldXi-0z8iH`d?m z0fa|-!&8E&0M0|)o=6%5SIpK!WY)b}rfUbb2bNEVPX~jNW8N*T&`fE&aGm4q<2RZo zW%J8UqbQ?jWNtlspWXDMww1T`+8zF-FUdS!cMikU6S0=Thg*8Jh-Bh1xyl;JFS7fs zDl)CiuKbeH<+);7 zw+RV)0vhkCW3__pOy>zZy_*x8JnN#+73O2Hd)V3vcgzA!+8TEaWr9uhhbIJ6$fP|` zXDVV+zN}1@y0kAIi$$K5hv;!iHgqqn=HKsW?yzrQ9=Jv^ooINZX7G!B6@`hus2(aU zo--F`7H-_i_3}RX6?#G!^ZliK%Y+SV#^7BjE@)r!;X*njzX{PLhhbccga4{BQr~@L z8k%>)xR$=U|Gr-m@XzJFpdYLxIAMppor|nPaUT9!JiDK>EBbLiM1Hra%XXlABMo35 z)Mi;$ffX=@VAH>XGTgrP9Uj5`g4&TX) zpQ&%5hwjin02-p2xt>_IEb{z5=!MX{aL5j@jTe>-NEtz@g>?32dA5x}lctTh53_N% z_Dj&dhV&sftSrB<3^nJto)c$jAhbZA>_jt9RnS{?;ykHWsR@p7e(T8zld>Rh+OVjw z2h)aRiNC6tLmxJxT)n*CV}E6K6whq!K=3BtjlKK3iYJqk`y>7D?1J8h+Nx$Do@q&%kfHGySUPFyD<@E_`LJ*aF`np&7)VqE@ zadr~*K{g+^iE{*AtP5Vxm!`IWO<1L3XxQVsWBW^B>~&V&1(*`Ap@c}6TCgkGL&}id ziS0ZCgGkJ~WX;2A><2~Y0j(K(OZ0A@MH8_!bt%tLoyTEcz#?AZ1$0z}txnyDt)~a4 z%z3e=TIv(EpJrkVg@A6=;p1N#ostH)8oKvm0259Ih*T8-y zJ$-ei&>eOg0=S>%RXfsCykE?vUiMq)`95+dmYfxEE9kEGX(05!wgRKkg zwq?Bf(R(cFOHy?eD|G-9uBjLMTBsjdyA@&UNVJ#Bb17PrVMW^Dl%KUbrw-+0TG`3R zRaXh7&UUBUon56;SUX!A3tJt|_Ze5P7UeEmTo%h2DwXVZ38pSK=jU7NO+>tAQ?E5L z^OH3;^Ho<5QtXrGnoTBK^V@eH(YcW+lDE-L9iHrhIf{hY)rtGe%QV-Q+lyU}PWw)0 z^s=Ib1finNlR1nh_a3!tB(%wFPjotSO}-Y_n&nYg^1LD&ea~Di zCQ9fm?ky=6#%+IVv`d_yo$K_N-XGVX&i}bYSRj?@^!B74e4LNW*}g*6O0i2>wvKDA z)@|^9`1KUnVLEWV95n0z;+-*T(%5RMIdQTBNt9r}T$HkK z3%H7coz<=l273d-9iMPG>ht*JFl%yc0^hJ>st4kf#5;`ls`qo(57PgO^v7rFkLT~k z*K0H#o(=u;*ir_4l-E;&bCI4l4;;GI7y3yX+`M(qbH=^Xk~TJbIySKD0IA&SkC)F% zZPUQ6&_K6nfaD&LKViJS?8(Q}^k2=Q)5&1tr zI+^vKX47_HqOjHO7MIa^gOXKPuNy7bcJlZG4OVyRt_6e(-C&0oSk1Ix5&YNaiIImX z{Nd_)L_hQ~it2iBqC~9l+~Yq82mNwC@H(;DF1>)koM4Tgbsjm51%VzR-mEE)*8~gO zz?y6g?F2Ehf4q^TDd|rK?#Z*iQLKZS;-{7N*^h#_{*VTf=7u!LHO>uo#3S*>tYg-1 z@4EmV5JW|yo76OHh^<#EK-lzR_Tv5%@TT&}cFqS=gS}}d*owaizL(JopHy=VoI1Fp z1=RyybGf^%<9Hot58vw6&+2eZp<`##GW*7sx(R$y0^}!P{UF>4LIxcQx^ubPfm?Cq zI#1L)e4)1L0+0yns|IrOnF~2z=R|;6uxoUh-K*gIq0)|A;Y+@_DO=W-{X3`(_lSi% z!lGgoH_jBiXbs51RiN5l+kYH|>r-c&cV8Wyd^@7?cI=ix<{1@$^XSiF#z zSk7+|bVZsQmd2@tR=o^mKQAECc+w#CIb2@^NRT;(r$zpP7GVH)r0HDH*``KJ$o8h7 zuVF0`5|}5THAArq2a4!BFxO}moXr6&)C0GYzd>8!qAN1DhOUe>0-u)pn;RlEP}lVK zv7L(cWPs3r{SWt4K} zZRf+KJ}1#pEj{IOuJ{oP-?-gNN9@g0_ltp7|1oGUF9uz>b`WSk?QJ1ieqbv6(!5ZF8x|Wd* zct_ejv^LUh$GC}LW=FCd&QZ{QAWj5$oWn;MKhM|5@Ap*Gv^m?nJ}b`6G1kJcBn_;K zuw#QhuDwS!<;+cNjB*2iX}-e(!?nMG!jB7>G&F`SeU4*`I^anqgjbYczL51k8nD7Z z?i`{4=+yv497sR^VMP3JGrDlIy&-s5mg9A;(!RJ3j7ea9_0czkLHvU9$nH`LcmCB< zb9XPw4BQT$8lHS1kx&Um@m)4vpV2!&*y;+HA3&- z;c>;gM|sCJgsZ0@zDTZ>uGBC0LLody| z$uWfh437-{I^%Cw>MB3igq35#+Sr1HR1G#d6%aVuyINLF#`YPv&Rm|YNEH|=7Z}3%WN^j98puN+VfS}|R;(-x%AP4zD?)VVW`_#_J*@cT^f8|iGQdyZ zpZ6Z_J#F?cT0AbhW4*Dl3FlZ4o$*-xck#VFVX@%4(J*^$zyZkRgg`{P(y)xrYrO_# zhrZ$yyTk#dN|it5LM$%&7zX=Gee>F=?DgCYcJVN4z<;iku{N4KoS_1?wuJ!_s z$$=9O31Q|WnR%q=z_13o0>B_@@cWg(b77RlLd6yS#Em41{Y<_YG*3f2x@$L*2D){R zOxS0?pLlM2H}OW!J*adKf4bG}7OI0N&_@9Tsv>|i^+HDZgAk$Cl8lkbhiH<-WDv87 zeGmy-m$WvF=?4UKFW8xEq&2S{*!L8}Hcer!=%rd?@6XJf*UB|NK;x=S@<-iPL+@7P zt}zGCWxdP_NX)|K_(BV=401RP(Bkc1weF>WLfdP7g&&pKq%VHmTD!wvnn1s)>^aC9 z@2u}z*GI9kOK04GE+-`T#1nMiBh`DC)_zSluid}p-q4=b66V}@gW7x~nn^_-Fi+Y87#xXoQO9! z*-0{Ipb<(!nNGr~O)eZb;D{UTdne@l{FUT7L?`56)2vHy{T<$pJ;1K2WKn$*`G%xZ7z7 z-|Cn{b%mEQ%uKPO60xnzB$F5+#0e0ZQ8gepf<`iK9HphRuc`F@VDqPwH^txM2i6O~ z??v*0`~q`_mZm6VZ7M0fZY#pb0L;!cEgv3NFCT*so?0MwZ2SUTq0U*hI1e6hV^d$U zN_TQ*_WS+p{;}hqE1+RzQQhgF0$7)4vT)4e^PxyhNHiU{&_O7j$d+6%{-aJl=m37F zm;IgmDoSd|p3+_zK|aZh6t{%pla1(x;uF;F43ZYg#Mao!+0n$n=3mXu&=LxYk&%Ib zf#6@2nVp$|;s4MX|BKGUL$B;%Z$d9>XX`9t;$-A#Vef3`_#aJK0~-^1VZnbNYGn%> z6DL^{H$^)e16z3|8D%JXQELM;Cjz$b%D1SHke$00Eh`%b0WC8F8vzpo0|Nmg0|UDb zy@a!YwS|$Ot(mn60Rt4hpp%h_tup}!CnFU7zw!Pxm>9pc2piaon^>5cJO7jWZYw#P z*r*b4e2e_kFKS_J!t~w4`E9l$AK(9(2-E*gMB2pG%-NiPm5qu1o8Q^wdm7dT&L$!z zMs~&~-$MWO z^ALx6zj|=MSNu1he@C^l>Y0zfL+*gsZ@sZa=`{&eZ-gyc$8Rjx*E;t8;noPlx7g~u zv~zO#Z>P*j+sujQv!b3-eqj#$<$G%;-pqZRALw-~;gN1FF6C6U%u~MYy!umWQuVlF zcJ1SvOUmnGkD0?5VX4!71Kx?^cfQ`E{@RlZRy8SO1GK~5_lV9}oTifb3#r3VKI}vE z8z}eZ;dH#--+$*}KaL0}S^T=`zIRQ# zzp*aRfXHc+H~w=m8$EhHyDWacnCQ+IjFFeoSz*Z;s4OI%+|L}N0h?Zmk2hE%5|YRN zPtRih--Y)-9z?I?V(9$Oos=D2O#Xu^WZ-1-Zvp@RIg*8=le4h7f#W~_kT&?QIy)y6 zy_$uwv$>NNJ3Bi88{4;6eP3Bvm!t4NOj4c81QXg6 z(v3eMK7DNZQGNQt41GXBuxV3O1`-g)pwcO9loAaIEZlMW)&zmpjfCF`5$P|j+KVn% zNNQy>SRBTzBr@3Q0oiQ{eMM)F+fOS`UhR|F%*lS+h(p3F%KZAe76qnBuc&oseZ)GM~z%VE@yg3mq>J1r%C8c%H! zX8G?L>;kPeHc!nDc5_yk5IsN!t~yWa+d=f=FbI6HakrljADL`#aDSa39(;p}YIjyU zKA+g>_gqFR(yD4k>KGVn-^8n( ziT(U~L*9h4C36g<&SxiJ7J6~(?UK{B75#+nvpgKDp8P`B0UrgAsJXe%C!eiW4|Og0 zD~~LhCpP;uXW581B`Br<<`d-?Q$h$<*Iaz0gtfbH` zUvC%2w$u&!eAdJqyd7&RN~RS>?VvIqf4vTtH+EXyatt!hjXEQQYxZa3Ph2yGMM?pi zQ;JW@tsktk0&fmbxnuZ(G>zl2MCMF2Mg1=eqXCi%NJ|Bt&cv@^uVk;BG5ZqEoK8^b zd2(B)D5{3Ut_SG%PlV(=)#iwe08?jju3%q(U;pgZpolps5V_-RG08=E+RgCC!rX$d zVMTAuZBdi6QpblEm6yGDjZq!Y2bKcN*{keRy3?(LQxdMAZdju`XzLN1XS#QA(*^=Y zSDUMmwwC+hcRym(Mi)HI@a23RbNtz3AOJ2viY1V500zwn_7e`Z)K`K!9UP>DXZ#wd zqMjm@Y{1+`*lSkTT~;tAl`%4?^{3r1e_>Kmgr=~LFm4H7!PDHx=?+uR1p8s`Xb*_d zClC@LJdZC6dRaSinJf0}6@({NwtxnJ7vKe8WxFFBmXoA}gPVqqH3HyQdf%<{EVUML3^t21)P0iO0 z7$F3}cp|PpngKYYBH=v$4mG*cZHLwluk3H!1U<`Gay3Pqmo6`)H80?C30#|GO&T1J zOwxmLgS*UxN2e<>t-gvq7EG z41itq18suL@Z`Pz^ai~eroNSZXW)zS3;z-*r(`}Vu`TQtUi0P?KpFcepowc zH^rai$MdE9Y5obruVk^S!+nDeE%)P>!Es|=`YDw8mt`Z6yWo;ZmiqQjLUQ8v#mEh-XQ%x z^Yhy?`SZy$`m>EY-;m#Mu7akd*iac&Mf^9YZOO6XM47H7Z&TzenG5{`#siE?h9_p( zJM;O;Vux}J9grl;+`<{%D-=fjC7=l)3}6Oe1LV&1X0K;+`&JnQh|v!Wyrp3q0^4#t zv=D+F&JnASaDq>`h0^VlZ_4b|pMm$@i1H~YGUzOkdC9Pljtok0ezgqHWZwYCc>N43 zo5)XQ@eSvSx$do15T2wc9?W(Jk1m5y0^`|^*e-mWQtX~{E<2xU}Od{SEQ z?-;YAo7{)m9f0eT!vOZhAv`DRL^_=M+sjYu-+-Pi+Wk%+2j;`ugO%M&mZs44(qTY% zF--dmGntRN2zLH7iQb6C0lf%Of}7%7*};n%Wia2*wwAc`P{ez-(GSJL@8>_I`8GSH zzCxD+S#<&6 z0g#d9RB2*DyOmF6!T?8a`q%JXZa{6i>MM!i4RmY7YoKYl=%%FFiCDbcGiLSZ2g{B> zR=M}5t0CznZo%Yqds^qt@2C5pD(QvOjOyh!4#YXuO= z;NLnl++W4dI3^(uZbH(qQAy!1>nFKNPI1|<7=D4xdmH+$?)l`n1e`GisLznSsJ-jT z@RhxK)cCqz)HkfD0;S3tJUb|vsO;II|2yzrH0 z2L3pKVoo@(@Nr)E26UfL*I^p$*^GOrQ^iRLrWN_tnQ?B`r%$vVVHbp z0B49ukIup(Pr<)QgJ?u#x=_sGbovYHQw<&c+uo(pw1E;k{KJ>5!AyuutP{g#oXCb!}~>tq5kO5jtj71s7Mq-n*~(cdDwP_1#G8|I z^$Qy8>`GQKj11<14KBkqDvcg2-`-{*kQZ6W1|X2w7E9U}5Wst}8{~v0E$tHTW=5U_ z=B5?wuT9SM)o_B5CkunyTV03|ZEA_gcuYBK$Q)0JGAdA;Ar@L<5fr=%ctBe4D;%#U{Q=0K(F zV3PXiYtWqv1Rn@nM-ynC&cKLjoA_1M&Oeb~jDWGpYbHoISy0?eI5^aw9khs);AqM- z#1LC_fhX4%=MxUT`ov+UfdMx33H_yPSy*FXGDX1l8FaWUtQ3HZt|LGe0D31l4E`0&L;hs^%TWIpA6SDD_>xo! z`gXQr>R-Ldq$xjX$J^~8>mgIP$-FMX>8Du0}dI#h_3qq*aiHv(%5(eNL7%Kf{Drz2L%eI zjOb5~O@AbY3@COx&qr&nLM;L-DOdS(l)8>-uD$5*0ml4u!`AtM?f4WHb z?O9er$P~crHjkY!3LFJ(G#X|!_hZ6@nn_)nl4;e}h!MlAhPgy{7F!p=SxJfDSv`>& zzK__|4%aZQCk;~qiD_6kd2npmn{cR`u!|gcQ6U99YZr298kWzGKR`vwn6S1QHjAIp z<(<;sUqjS_L-Ph~$Ptnwh!$5KKsKQH1LqvvAxD@+OLyqkI3@0j!V||t7+KiZ_{S#& z1EZiRx>_4aU9h1@tj4R@)oX)0bmMvn{isjKR zse%v}dp3F1ra))>ZCZOzH^?rIdCn3_jIrXh$xKnTs(FO3&x&G-s zk+Y){j^E0D90BRg=QWX$b(jc$^|ckS9{Pv%xhW@&o3!i|JD`1;);#AnvQ9C)PO(_1fGNbVewB`CUB=Z&--Kovw-G#efwDqN zA012CvjZr&d1kNaEl%>NjvL_GL5%jGpb(;Haibs_w2BAMbz!-eC_Wfow(`p^oI+vO z^)U90(=XGnOK-O&rI1~@G+-32Jv`A$#kG{zwA5{*o;Q*`J4!0=xD}<>NbiOOHcZgk z#l~Od5arK_8~mHhgDb-BK(F}Vi812u-AN1XQi=P8HsqF=sOU*WzxI3=lI11?lF3B; zVBIb@+=-|PG000$bct=1n}R}o!Uyu!U76o&#PVjYIjH5#!P5f9?L-P1DuP}Rki2*q zv+E>|DyYYNa_T*$<0|6t&%BGg@NhO8n%6y~Wf=>8?~=`yP2LwiLo`_%R)nUKn!UtiM>ta0%ImIzp{biSRY)snF|Es+Ve$a!K}dGj;>;4SkHiDW4Ni zsgMxk#-rBcj4th0CSe!84YDV1qqM2{#@^vQ1VoU}D%};17k+P97Auq+mfb@?oT1cH zh8L3?o)*I$KE=_8il2|mT20&oPj+Arc<=kAjGCv!%)AG@vpKZ)F_no|+k;_}G*Z7I^_N!0&tWANrm`4rW!G`ZlOmlgM z<28@-ON3o5Q>co~>|g0mAJ4SyFcke_{vjDOB_vIXV*EK?8{b*BB3!0!eKcL$tH#Z; zjx}!qx1JY;>M}(&qx2H1W^J;Z+RNGSBFDC2YUH_}0b>)R0F75oS?cwz`5cr>Tk$P2 zE(qimLzRTnA28K_@EqboTSHOyk#=z?|A1qN;dmlktfgA-rH;m-8{4%$05e&H!y};& z(tc4vNG^svpbSU}RiiJ9BVr0g;9Jo0dNZ&)E_9dX3^rria=fn|EnGj}Cmd^iN;hq# zza7OFzFqhB5zEP4YNm9&i$$vKhKh4%F3mg#L3s$TI> zPv5j7%Qu)X%xyENLsq;nF6(TCLwa+fEe^~JPA4K+PaI{& zLjk>6!_NJ1Tv6FmjZNzeAfPifGK z#|>-6L<(-oljY*HssMIL%5wS~8Wh*i&>kLJH;$UzHde==3E$9q*^=YFT*ML>VJtJ& z6r0Uc(G$@o=8et`A?nJ?dbEf~%boiam$GPRO-bY;(M((>+~R5whf5<3d60${2~HoP z7D@;%##Cp`1uIwq&b1PuovDV%fsdP zSy*%XE3V3C|EC8u%CGYpwU=brL^1~^%yKbFT@2GXM!5|7Lg<590wOv^+Fvdwa2n2% z*^KF~G`5v8FVyN)jxRwaX}ila=&t7~o-*d$_a#aEXOA_d@HX>l*+lrKQyOmCJ9H3=NvBUo;+zXokBhR-aB_bl?7|d7JnP&q&;}hkXHxb ztlCrt;x4P~>jueOlVkCF!)2r`^IlPTkv#NZ!Evb6&~o=G##ytZGnFl}uq2U_>=@(u ze5U|;;g-yoY_J*T%P3(S>x!%1oMFv5EBVsh z@^@B8@F}^}r5odJsY=!!omteS6Aj8^_FT8v+i;X+xx2BwfS}%0h&Tg~rC1;3Tuy$? zMoITbkXz9)yn-+$GiXO77$j?!3}?`;pI}^)I(0H};_56Mqn?BGVmxS<6w^=={e1}m z=(bFt2`iwsa5-Xngl$4x?9RXW3b>4Y7pdCjJbN?X7v9o3Fvs_t4HpkzeHc*0s?+8h zk`nuC(tc9^c_uhnehU_&fie_uIz=P@Y~aL;k&hrFl4n|gaCj!d0xDEeH!WsW8Ie$9PH-1k{fuIajo*aj=6iW+<3y$H z+rnw+$e1Kfvrtx5{&=M*Rvy>&hEh4-0kZ_iI?qB4YheTPR$@X7QzA!+Ox~P-D`~W2 z(GjlJL0%ePLIT110dBPehT%hfmye@Xt~lXs+O#%8P_HR%u`%RCqAag?UYWAURT7yo zG?j2RKQWYAe)4jq-#x@rfo&-Jx(LJ+ocK-|j=idNu{?f0gj6r0FKied@C%qtmZn;1 z^`bc~x_QkQuU3@=V$|3=dVH5f9?a?otCEN?1EpI_X;Md!&4VP992`~s{64)o$ou%h zD|$iP_unZJur&(criLN?$9E!moq3CgN>D8vRd`)G$zGO_67kXP08vePx>urosY4eM z9uQx_UPP|bhzcx-(#Q-@!r$T;1fkx7a@_Rorh5SFTK1^V_eVS9`r82G< zGP9IALp7)!e>)0Z{~n8uLO|vmF)H~0)1Q~V^uyOzv8dQ2rQ~8}bxFAOAnh|avSbok zSb;8!W{djp9F!49xIoA01TGWrg|F`1VH9&DhFTxr9>E$0Fhj_mnb9QdajJ_?8Xy0K zeE*e8(E(7+|f-FM~u5rpL)uu^#OaS&`1klTUD-dIzEJof3fcdi& zM&vgp#8xt%9unqaXluY{29WULRsLhrp2ztQs>0e|nhY(|Fk*=k-1Il^0Y$jKy=Q%= zW!I3C!4mToGu+GT3Q)_n8|S8BT0p~XTum`jShm^G2f*a|)KCxd2_O4Se_Z1;>!^2d zY4LO5lQkftBs1zNQLfsb&)u}1>89lsem{=fb90#=(ufe0AUrc8k zs4}TTK}o@qSJxFOf5)bPq)YS5rAS!10k(x2uoOea-e&3EMosOgxDBag*pX2oN;_6| z&;Wre?D_Zx4vjd164w9IaptNoSGf1;(qP6`>vDlabwBbp_3zr5z zrDd#p=^o%Ea71WQR-p$Tjt@+9NKP+G>NGw!rlLGRLPd}+N?>~Y$mR7e* zvr)HBQ|r^7Jg$*YEy=*0YPv7*Qgqw*dU(RX6DD_1_3ZcM;mlHWCAb)QmZPL$2d+rk zy-z1|=w2j&OPZC?mXNGvcklG=v5iKNGO5qvkNg^Z37T`SS}Lp+ANgp`kc`b)CPV?@ zr4r?K@$Hg5slEAA;LP?lK`6#0!=Yx%Ms3nAJzJ|(NFxLP7JF_S{8p4aJ3R<2vF4wo z?v*@y7Yd%BC|}4)$&1A8?`(-%OwCYt#lm1u3PD;7`@94e-RR(Im!S41h;rWnYxmrV z&AP$ZnM_AC!@aY2_+S~jZaXx-UT$m~u?jJjLGR|tp>tEyjOt;v4Z)Q&DEKk{S}kg z?q98w=E=>Qejl~!vaBOLD&#R0uvAKu%=m6HH(N<((i$L@Dzk9m3YD}}49}XF)Z$d_ zkH`0Q-c0!2w#wsVmEB)_MzfakmLlEtGMiPK3Fw-p2iLt+x!e$%>y^E3uAl3DeS&B{09%C+N*&1G>{9C~@=Sh-}T zMJ@K#e(7@Tu(ENnc?LWehOh}3EfOCfK_I6C2k$sNR^46T1-w=e<5mr*8X~u1uD#_KnM(moyQ)4617~{grsERFR}_?wFFwkKv~> z=yUyemEYTfvq|z1g3YMi@^6%53V^Nvj0)3dKeDKy3wAOjceNwJs88 z8>)ikgr*Z1r5k7)XvsAV)!!hF_^>$e6OD*}@CL0C2Js_G+-nPd}4H`72n0~l&dG)LP%Sfd(WR%fsF5A}h=_;eKS1Qf%=`ddH2&VPbBzIOtlHs?TJ-xs3wPZJ-jJ1~tNwt}P@ z^i)?V`?u5GA==M5WNPKGAr^}zvIV&bB{sLK@Ju+n-a@OQ(@91|s{Y*j&P@mDRaPLG zafj(5id=%u#@pqXkW|hj+Lhlp?yy$jR^grKG%@~tl72+dAXeW@l-l^Ft4_qik7E;^ z*^&e=w+}N%IX-G~=gs~q$nyMoRoeS`hFU#wcH_qVs{ZfRq7eb*U7^0l7u+en*o^%) z$S_%pj1GMYBUQs>UIipXAXDtQZAQ$VCl5CLFwC@JXric|phJ8wHj>7lXOL8uPD8e_ z3*G1_EP+~mI6yC3)NSQ>27bL=1AfE*!`M9lM-s)0!rypfXJXs7ZQIGlwr$(CZ5taq z+1U2R{<81A`|f>T-49h$HK$LXsp_6SXS(O$_rIroWSu>kse^gTYa8+HM(1!SgpEpGo#Cj|?lPKiRAg?Ow_B{)bQPa&8)ruBjylGT# zV;+m|@9yYyVI@7<6L6%E72z)BnQNj~KytP7)Z^cC6JF=Rdn)atBLa?g*@2_o=RqJg&Qu3gssmU`_-f<*oQk z0blr$Ss_{TwiNegw3m;+rQiJspyoo*85LO;X}X+pe=0W$Hf(s1xJi6yoht5CDjWJY zLyo9U*(EzTgntFMasw^&o3RW>gBSDK+%T^;Jlo4+IF0gD|Bn3S6J?c0vo+8@)}n$y z5ifSyw05srIdz>pj-NUnQH?5)siNb8xhR0hhbLl08w926_rwm8iDW;$XoYwrY+dkB z03l*33_NGvffhA*W1l&i*qp$^72kj~yfB`-o5bH|BA3%RfT?Z3qA`XcJ5~Pz5T-M@ z#JSG=MIRqQx&{Fz(B*%zFQ*+C4#nOh!D5pq!`-vHvL_v)7X{rJTTn15Jfyz=R1$@1 z1k(F=phQ_xEXMXEU=DwPj;)$!W7S>eDu<6)bAL)ysX-+HTB4KGb5vS(IY(P+L5=Y z2}}n@8P5;PN=)M%#BhdX3FbBG9vAgs+`zFpX6m?Q$p*JiNR`08f^>%nMWU?|3!Gr* zpTd)#Wj#4gFpr*T$F5*bik>x}mW^)un4WR(%4u42r)iYG9#6YL+$3?;_VY}) z^Vvpnz88EJ4Cz8_EX%Ukv#HZBtBTo`9yq)h4jaFUEa|Z5G^-gMP3e@MGu2S8({9^r zD74Tt#%}4g@HN)%`n>8Mb|*ivamT<@;Z}Gwyqdk5P0g*9GKFH|*>Ea&Hyj-}ZJ&)N zt5jm1wwE>9Uuk>j9d3=-vd(p%;v{QX)L3*mybhWhAiT}{o7cO4-~gv~@~k8blW2?C z*>rWIQdkJLxi<)E1}aE3Xcwky(;_wZ1_*mZ4r4@|3+1;pm5gX;mDW~Q3oR(TIhi^} z_O!PT(^=;5cDJ;MVxIjR5pr&(nX-8Di?nLjyzg;Kv6|EHB9KkjMDm~#4sKBXYvc>d zs~Kn+#;IR+$X%{Et(tIAJKSuYH~o5+Q^6BGlXr^Z-E~;rUdw9w60NaySCj!Qg?t-A zfQ;9K5>RaH6~{E3F!p)mIHlZJOk`BS!jdV717I_yTg}G7z~J%qX_A7K=38q9+9SJI z)Rh++BXlt6Rh8%N%c`^I0(LB5r-@+twFhT&+l90Y<1;E(NI$WFVfPa)9b-o=0k>?P zvSF)iUb`1fOg*m6N4r+4;xb!OYTxU_x7iX;?O+{wVmPoDlPOg`}Jymh4D!vS3S zDow$)!b(bTkmvSu+RP?5g9=iHVdl%-_2bEyWs4Pe62bDt1lcy~PPA8^`q@L-h?Fsv z;(CAU#>^{DZA0Zwuk_=@6sjKkacU?|)Mli(-bA<-9i1tM@V~1Z+CD13K9VxV+ACcs zk`?1?tU3tX90{+&zi%8@spm~-#f)9&o1MG`9Vs1Fs*d=vEy{;JqL-Jm5>dGA@Fubl zRn8M>mhm9aas)u+>{$Af>?*H_{TyeGBs?>$e!Rm?E4qQSYV(xK(~6yc9H|faB~eX4 z2@xAo*{%L)8oH)|p@ByVsA^He2yOf07S+j<2@%FGm;vn?F>nT=6=qnd&gI=7nM>Ci z%qhfM@VjIFA_h)Lwv5&`=5!xZ&*5F}jY8T9T+*47rsk~GUB!A@n;cD3u zxQ9}+0Y5w_HX39?ic7!@m%T$(Oh~N2R0b~fLsAzA>+!9swj+FC8)%5w*pZJUmwpUs zDkr9Owypk&^ZQ8kWH=Go)f#eS^F{w=A25&0dn8$6ip^){xDe}@5J zjiT>RY#=_k?S#(w7q|4j2o5|Jyd3|}I281KB8SbBqzG@r3)mUTbMMhcOcNdd#BAm3 zLy8~p?Z%CjP@l>;2Z}ufIBkltetl`W4Odgo)U&ORL^hfqbDvZ)*m&jP!vqujZU+PlMX z3dGY!bYLlMuA}{Qt_%>pdAIhF*^MRcWjGqUzn(Xa^IX^k_bL{lhLMSJ);>&oE!ac?@6pF0g zXK68CB80darsPHEgp&Dor;s9>^&8XX;|J2Ui`;|(6u7ImqLD46&a?qU2Vt~-U1Lr( z#lkXP5AQhSJw6|U-~dH$B&LpECw4JmKR%O~HMvQ6G`NXr(sG`uWG`qX&kLMruPpW} z2K;p*&L%&u4&XcYw8!8QMN4LjDzmRHQ`@~6W=IkAT=agGy4#jVcOtWS4#-x|;I}RiJ_nFnfkQjvJn z@joM#*8$6Vb-+TCsuyR3&>?ke3A#-rptUCspRwnMjQ;T}cEw7xg!J$_aHOq#sj82b zN;TnwER2NK__j1Eus7Uh~w4+>i6cozg^k>n_pf z&GgrODBn@Pv?*s@vO2nOCoJo+p1uD@*Uh7qiNGy@Jnyk0rkk%7TuDy(xQ|&kE^lT{ zefZ4iK-g~-vWmd$%Fj%K&0P0()mZ+fYjdt@HXXU-!W;MYGz0myW>ZJmMEIr0SJ{C^ zcBR$yw=bH0|DOJ_H?Y3;$2m2v>-hqOY`$a(yAb7YxsqbKvQ3J{f#Y0shS*X8rINQr zg?UeS{R_2^We}}qt1Px(JUpktxR6l2-VEqrxSI%-po4+@Sqf0(%8Dj zeoi#>EXtsMwyrHW>DskPHGx7F0B2O&n80TNfdK)T5B#H=vv?Gh4TJ>--@w zI2^qJENK?>9#iHAM4qAhk3h5FWo3THfjrR=R0jica%b#1@QnsL@#?w~Y>;VcUgvr4 zy{R*?ce+`IoqjEOgf#r9TpY=FV&$%4BuZ&#UUZmS0mdbv_Z(vxN+XF7>Gvx_UyS0s zo#^f-3hC?mIgPU?zsItk z+P1;JF2B+a84e(e&|mkU+#VrzHEc<}pBW3pM^j*+sK-8+9gns8Y}KrKMRE802GV?D zEkf6&C%$^|^d3{GVY$)8v1<|KVy$(Lm%CAT=PnJ2zFue(ezJ+2*rI%U2K1fgF@2%- zLxaBTwpHtUb!o-0tIgErjMZt&$z;`{kjVqjOKTZWzeSN4bp|7KG2-;R7)Q84ip(Bs zdR4?i8zf}CXPDm6TQ0+lgSxg7EuAJmKJlmt%L8kVSjf!+jK&&Io~aq#S+1Z1AU3Ct zF9hrTP(VtsBo^I^1W3osGg{tNhdmK8HGq|Ae<<>4r(|1Eh9Gb^qe8Z{Lm$R z^So|ds3(tyxR}_*JbccCP5_4Ub4M0bvq`WeTE$A`^FpoeH~G0`BBQ!85}n>{0u06h}u zuU%Qx+Yq66;_LP9E_g*o727Q94dbpUw?%S#T_wsnAgPn6;`hzYMnJ7nOs$lg6S1@~ zU^+UAPWrvNV=~o7IbswR3Hayd+|qbBfI9Y` z2hQUgh>9|_&vPrun7KnR3|=Z*hau^5@>>fV+i9=$VPsMJ%Q&l+xb2gnNZuV(y8h9z z?fi0aa*yK0ok4Ox>iXZ8)--E97`pNsi05+`P0v-9`#I^LM?|>Ic)Vij`yUDY<4Vp@ zkf*iq{v&ZL0F-Xmi}DIno3xd z)z!ri7E&)|YxNCl^YS#|L9En2q=+c#1+fJ6JHe&TEfhznEEU)2OJ#yN;smoDtZwxS zDHabj(LobiRbrN*8}GfdRA`~bRsP0}pW2<`z@^F@k;8UiTP*xYgM=MbNqA`Djx2?p zlgdNRF%`6If}2ipKwvE|m*I?Vq?b72uJ|})+-c|yzWJ}eQ#zo`QNs^{j2~PzP%B8Wl_vrRl z(wZZi(SmXVp;44#_I^NOa~i}sf1NxkK>6mvc$c-5eEWa0`HV%D+|iMk=YkRw&Q%L0 zR!HcUP)=oI)|i%QCCcYZ@h%JF=H(8#w!FNJHACuz&{108ru~e+cRJg!hFDTCB{L~= zRkz|bj5lol7;qc9VSFs%rvom_bV%~GU~tUx{cD6VKn|fo<`)ehW#7&N8v`Q)bJ2NO zd=k)3EtxQ~h0oxXOD&^F1%e3*?;xxa3s6x-j9IA1@d*mdOKA&NP8m&#CrdIxD=b7y zQ{co?W{s!@Q`{v-S&E#pRudNc9WEEAmT8tZOSsCAPa2dH64joqv{A&oFMz76?RqCi z@K!XR7a9z@^LJ87+;bb<0>;{+8+ptMty3hBG9^p{B#X85I`FA!<8tH1N8Fnpynr+@ zzWZO%Y>=B1aAFj26Hhvji^o9MnUs8Qvx2t;XcyC=brI?_w5j5(Gp~xItRG;GBJCel*iEXn^F6)8;%1wV+xEU4Ne7+0SGJc+qq9?lkmjeWj~Cn8 zx`}&=yZ(8$8&p~VZ>HnSafV|PZ?0Ud)NHA2ZQWRKC=w}CD9>_cx_5SFQqJhWkj|dC zkb@6vbQ+e&C}_CH$zpnx3~rTPJYcD8!u)We90~il9p_Bl2!y9!n0T03fK(3HyKfH5 zpWu)X*WK4Z&d^p8tRYktv=1Wr!y@?fMcdB@RV0v+kg*}*bQkI!MT4&Z z(zgvCr$q-j+wr5r^6Rh1M1r{G@ja}o_FSCiGWuluQIqKrpUXPD=JMh^4HeZdwkmak zUlWU%-QR!e$dqIppIVk5iw1PyHkobN+v?`+&W&4pF7>Z%weHs|HB*~vf$^(z!&%HCrU4ST@Wg7A{}fow|ukV6_tmKLTLGYvq`Q97Znoo(Q@E4j%X$e&Uy zL>AMDvcy8hMv@bRWqBiJz$K+JIb;verZOmYMtz|VUO%pW9K!7Xu*O(qPF=s`SBIY; z3l^#`V?h~4*P!UtrcETMUk9tOPp3s(JpcXqNlSks5FGuz-uutD63Y}AD?_%TwiEG} z4c)<9PwrIqx<|X~W{FIBR;!b7yWi|Cy0v#!&WRiE~y6gal28 zA&nQ(VuMzw^TDGpa1w%!VF0+p*p-<8EXBsv^=p#Zg2*|f9J|g!$*=E#o1dJUL2}%m z`M3>YQ(CHBTe}6p{sT6LsWuOh723hI{!XIe10t#cB0)C3jwb79iJNW8jE`iiFqYz@ z9->n;N{7$)w$nWx_aV;-OAYm4+IzpBT&|2J%DCz{Tf3?&7OPO-yqdIs#ab6r9f=lT zKl0RHzp`Dn%e2xVyq4)n=yo-KNit|?QQpE;0FDu(B}3*OP)>elBm$2QRCOnpVG>oJ zA);Ufk|3=~J%o&WVh+4u_1jE*kqH8$+Nq=ZBzQ(OVzHIHLm4D%MhhEDlDzN+ zsaX|{Ra5{BA5Wg22wJeDOJb{Cu#`e3ybL@s6f1Fb@z4!>D$FoYRVtK27{^hXBfFOb za@Ap$gQy_rt2B!)XPb&*~D&5+oqydlZ*w%J0emV$|!}}NxO?b5O-+F zpwEf1;jC12{h7ep^iZ0Ies9hU@{g?`(M@dC^uV+oU^zh&rPS_vKzdwQ^o-=bpz)Cx zd{69a)}7|Q)k?U#&i0M%UEA{bgjR1b)Y*-XTmk-^79&aZlKtDNmmCIKr+-CYxgOkU zdtg^_o-iX7v7PGohf-K~AU5Z=R{D8C=d8xl^>S0;XdQ3SgOsNG(IZ=Aq3yC5zSFCd z&sUFO0&Q{4%a>fD8S~)Y*XdbU_37YQ3E1P}4xXz;d20u{Oavb+=;6l6~TTkB(AN4eDo_fm5yd7`25uv0{Deu08gBYP_g;kob7oPhD}7d!mP*=`C2l&#oYaPX|7g z?bB-!7;#%$+o&|2jf8IGYf};3N^33Adrs|K*F9H1Y+Z(z52yLw)NwcOA-rzLCTc2} zGrNlemfDY;)2T9mrCejUpDt7Rx?a}`W3RsU&U^b~y|5R~f6=$*h>0(PI96s+Vzl_7 zilxyPrmoD4LgOSY)5xxtu9mC;lC(|q{9`(OY`z+GFv;DAWocTsjrhzHmC3XK;z$!m4{qZ|l}JeTqDFh+yl|=kdn)?0#ol zWhGdFu``${s^tbwYYM7g;H=!Lxl0u=saF2A@|txpK|{|!ma3K3z(uTBUTAkBB|V3f z*;6!xMnQGQj^k0fkiT>)`Oce*Lp|pptb|f8!C>vIi7b%0w5uGL=X218dX$|kofk5i zsH*GTMD|iw7y=J}s`Q>;D_t(pu&lETQQh?5ZoyaaBj!8C%8;S6gN4le*chsWY5fn= zdj35}O!6^znE?xjjH>A%X2)GEz6W$ZDKRnHDnvl?*ub$5vW>R3VG-jn%kIGPc&|k@ z+EzB;h`QFhLUNMdvlB}S4!^ib)Jg^wLqf zP>xt}^6YCbKE;mT_UR?+Y`W9@@_00DRWD2P@(yvIb$3(rYs?xgzH|Kr!2cEYJ=3{9 zs50(kQb3Yx#x2v=SKs#r@g9cL92qP?U3#^CxvJ5U1*uu*SBpBfVYn`JirXK3G-wV0 z*03gQ@NmB$1VizjygZ?5A(?_aj!~e~jaB)fd)y*Y2c-FTd`Sm!Le_90J>4z$aB5m{ zLxx)XwD1`z!&@6i4{d~4w4T$9Z&kq8bwKy8D zcZ&lR>CLu?(+=f<4(ME)2wKHjyBS>J+g&=R@5k`+ty7NUvW)Wh@$$Gf%M=x?*IAPV zqnh68LRt;Rsk1u;#%i99Xj!`0x3QQ&HlxnN$XwdL8PSxr)${c%g51{m_O>~RsD2=|JII_gK>J>dLfB2mwZ44m zBPa$;_(98?GiUaY^oF$*D!!r(321jA9x$@dX_G7f&!T;ZMwE zl79(CM!UpKUY*(^vB?mfcu$Lo<$-6c^c9pszH=;fQ(3*pkTkVNSf$UK(|PmfM|a@AvM24|4c+3LOR%&N{~pI z>dguvwWx_f#ZM{uz`Ew2RCbj&mhy}yW@S;TIY9q8PxG(Ts{vxjZR%1|z1te#Gg#Jdab za$-*9Wlg>W*3zD__kT)`@6VvO1*QMv!NW|2V6eX9o3Wj@0DR=Ln9fG zoPqVCJ`_6duohm@H%dr@1hE23Z+#PaqrZd+j2SgS;3JO&H=us^Vp#79b?-a@KPKN? z0Zqb*>rIR{n4vvuxmWpworff35a_WbErh0g$Xv2~5z~1}TwyZj*19UyM^j4*T-qyx z$s>%DvSSe#BexyK(cRl7e?E=(sEg(YMZT=db47TS`{H~xP4n^=V{MrD40-+tEwUD_ zB#3Ex_Z6)6WgFezbJq65bf2vDYll0TE?Au{IrRDxw*b}V+CFxkJ=guMQszvw&7^37 zF*JF6%XW85oiX+ld+&rZRNt3qF5iM&hCJWOpLU;{)EInB&B#a<+d@TYWyAFSi%j?ZkgyO+3T3o8GrdJ$l^jNzdT~t=+iVQ;+=Hc1xwp0D4>w%4+bIeeTXp0;&%&g zeovekmO8o`liY1(`PK0`wZ8Jy0Q-Tp@??9lwXxDmJ1(o+7?Qo-YIt}gbFr}{(~VVo zaT)G%UwyebG<~)?K7FaT-d*GF_>|FOyuWJMlQfQ&V0rXpvjIxdP;S;00o(FOv;L>I z-1p^ZR;^HO=!oHmznraQEXw)$v%_?cj1^m_`!83y>$R)s%GJ+9-(D?Wx?MqS2zM5n zi>_#f2XLAWJybEBUcJyLdG zaxX7@hsR$@xnD{?pWhpJ=?iWlJtJ-Ma*DZXNRdcPeN8m#=}uX_ompq``M z;DT7c7QFV|z$6&9LVUN5!~X!p@&M#dwXuNyPrRBafa=Pn-$QN9-u@q>sx1o1OW&;( zsX7d*g+9AUqmm4X_r|Q$otAek&C%jNUxN$-x6s`6uepbvpslbE`!+t0Rd0Zi@3V03 zYMBl7nGyP;zApYFGaG{A^=)Qaz}Eppta;FQ7(=8!YPf*nQ5n^P6= z6K0qlz-#E46kfwXTcrfI?r3 z64wiE#2jH`eQ^$%S*%k~ehx3x@;wo0W^N@OVkvA6lI&PZS%6m)U2_rSr!V@W2-R=B zJEEXdPye2jto1uvlJH29MPlpeLr9KW((m%b6Q60+oGH2{{^@;>_ zkt@YFF1Zf4E`TQCSBZ-)EE3DQ3R*|bk?Lr& zBvg1qlaQE$;{B;To_bxYFJ9*^n(#~?*L7S$pGXDk;2FG*Cr7;T8DUZO z#Uy(cI!@w~NyTsjtQ>r*b0FYzqQ0nch%yrNAoz;!oa7Pjk!=V!FLnwzT`@1gtFtLI zC&MW`KV7{y)XdAsDiHN=i`?}_*w8{*t%~jM#MS1*?H9#4~E}<7ik|tnaOy`$3V==U8i0X*=n@6m;Bk|rD z;k(Xmsc5gIXfLE#&scsUP05)MaVjCAp@=9=Nm^NsB2EfsOl12G_T>}q+j@J=I6Y3u zYl2Ew7hzi$aam=ET6toE8mS>dRGC)Q=iG)#F-!c3bG+^HcjVWoN;M_1J7TPVe_mc} z|14%)A|uR8;xu(J-rto#GF%7l^DL|Upx*=|ag;w?(Xo~8%@2&kxkV3!p>}5CA!Z=H zP6>R=nIdy3-9jbO6JZa&oblUl3V-{1@9+h{-R;`uJ8b!uoow?RXn?F<5p5Yk_5j?) zN#q5<^v05fKFNt|F(|iBva0$k^JS5`k=)&zNc9o-RsfCeA=vQjxr4L^dEy8-PqwZx z0zTVuceSV*47d)T!5g%||z$D?hOjmlqea{ea`=Ol{8Q~Jn8ultYAwokat4vdY zA|h-PFI5Dv9JZ)eqy|V08`jHDhEXseoj1O;w$pP!EkQ30Au}FK-PC0WzJDzY=6Wcp zOXp*l$&0nh(_AWnR}Rodb$b8p%LzqLBwqkj|E?MN@+*VWxe?d=R?4RAnU-nr7@UPA?ACOZIU#=HHwhWvZ1kmD8^ z6!uTl4i49al?C^a(_i*U52v(Ij>#&zooBbKC(@mtizhs|$2|TSwbMg|Zry&0S0v=4 z8@l}LN6vR+j&VWQJsIk!R7e2@P*IcdZINzYznPqN()*2c%av?=F zY$Q~VLU&Kh@i(_9(P>?35BWiw5X=SfwQWzqWxb>7Vp!LjI*V3kuo(OOIMWA?@(aQ+ z&cRY7obyzN8m12)g5nqm>Q1oO3C9^nK(X%tCSea`QxP~hp{!9ARI>q?lH>;p8mK0) z^r%OFpHuo}hX56jI7O#0qj;N1#}C9LO7MXB`T4!Q1Vw}&7V^-KTl&yz+7%^79RiH~ zB#P@QgbT%>v0wS6wX1>5^^Ki2c0VjAX_vvz7nW&*>HSOs(@ye03Bgsz^K@VU5Y>Z* z80ygV zfBb;pu{{27-KT&4&p%O(;amA(`Y#X}>wj87|J#H5PjcvgC}#gdR1^PiMKzlL>7@N9 ztj6}ge~NLTaA(F|G`#c_=g?+pSBv?f1c9+ z;*Xd(nEo63=)Yn|Itep2f%Gt;*W4m8>-hnoP}Rx=%}vQ3fAFf;LFDbYiV)=`;l1Au zO-(bKKu)0RrvRh&&VO*N*oJFu%wm|!9Zj{wR(6jt70EiBSm#BXb(n%tdoz1*3;!JB zUay3|27bd0Dk!}#-RB2aX9k;aWFAp_fR%*v3lSbKWwBn~t&!VEkA_6af(B)pZ13z+ z53d@}2o6gZvkw=xO;g@Ox}6W+1jerAf_WGkozZWHdL3G%l9*!2qL+@S;j*{eiGbo; zQ`6wWtME2UNOL}2{YkcyD z?itI?;&#SPm*$hgqb!hb1@HxIy117+xE=O|{UCF~#~uA_8pgJl+dmcb=@|8FdQy$( zt8^<8iZz`4i_}+Cf`#q)9sPFa@4LPOr&Mnv4;)d$^9%SZ%@Ff{TXot0^Lqa8D*FFI zmi>R%)c;m4V`Be5LpUCweTG@X{U;iPR{gcN2X<+{~|63V@`j`J7BG|vr z|11Bm0sPmp|I+{R{;6dD-v5U>_CF;tsQ;mu{oD7gkNw-v{+<3Omi;@P|4s$_*M|RZ zD%ig^@PAXm{vm|_egVGi#Q#vizJ;~_4;74=m4Sotzc!S`E_Xka;TJw_74Ijf8K)WV z%ZthB>5GQOwm#a?0m^D^LI=Dn!oo;whcJh50Ob&faG@C?F2fdt1q?KGTV8k&0x~?X zM3fJUfXh>DMi5XztQr}DE?V};)9%%_j*&DCNjJ0xGPCy2UUBm$zA`v_Djw)_l2 z!A!RKJE_zeEsx7d_>q1eEWsMR0R|Yn*HR#gdGCSS0P?Yjvw5f1QTlFPUwm{Zv4VOx zjRNlU3UM`)29+gm3x{U!nX>a0Uw-ewK7qhcW;mQ>rz4HQ>c$xi28YEHhT|9>+l`lf zvb?Xa56Dgh&>n?d43ynQ@+kRRd)PBVuAp?5 z_R4kG=0H$^8G`pMQt#)N(mT}|bZ;Ag$B%dDiJa?u#)Jll+9wK)7`%f!E`W{(Hx#pI zRz)5HH(KoN7B?ZVb4Dn4hhBFo+OLya!HViCuyT()7A+5A&W0NymVm-Q)!xgV4{Cs^ zCZv&4Jj*oKx8))6GQet?zHxoA!9mWIP>ii1vJ)tCH$ypTN(M z!ZtX$AtrG=2Qc?Etr#OWL*M5~5$OEx>(EYLKSwvRx!*unke}|KLF%gP%1%PDMssqr za&xtHaJCskR5$Q9>(6*bpzUezLGRgb3}4h=V&<$}4XzpI^ zP46vazz$IYxsS?&Ksi77dxLL zVlNbCbrNpEf2g_XE>L44GVVbz#%y!E3OY;P0)Z*3=&UHMsG0y@A;7bt3TD9$ zi=fT9u(=|$+nIj*EqQzfuxqptmNy#DUS{c$w}f3VdayL^Og;#F!)Kq4?~G0JT+dQv zjk0@H)24C$2iS~=ynuLjBaBt?D}u`dYlo~vcEIs2ur@4P$b{ovTk;0W25C*SXQF5B z8<%So7i2DB?cYN$u-rq(cl1xgPsvY%PvlQzgOr<)oA|N_sUfXlxZ5xBz@o+?iFqRm zx=oVHq^$%ke=gr>mpp)Hth-m3)`%D#&t zg*FWw(clfJQ__r}R<9&3!RT*#8*bdt(gKm9UT?O!89s_J>(OdG^I0eUy4kW=KtJV8FwG=nRJ zI7TRfXOJ&&JNuB&9C6SKH$UE4)P%9qe`qtOy+L$9(vW@yavEUQiaqVNzZaj#D#w0z zy3H=oQ@;L8jbt(W(JPAf7b^_Dm1uwu+IA(3ih=BTZi;<|hulYEOGK>zq$`4V#|ONb zkKgAz(t0eE(hV>=&`P1!T*IEGQ}pcQ7ouJSJ2!~&vk?BKsw2oVij^&BIU}^unk@Qe zrvO~mRCFkj!A{nlKV3;+kQ)N;Q()GPe<0cbdhd^-Ki3MK?9onnQebT0<$(xaq6SbI z8eW(@@?9u8x?K^#+y{><)89_<~>6fJ46h=m5 zDnO+^tEm?7-aduN;JvoGeA75>g~{4v|9i(D_5tMesgkSE*1D!d&RK<3DZNIVWCGdv zR-G9M4h+O6cZHeTM#r%{f;t>{1~JM)tXQm-biJY4+Kbius@?n4$Ac9+ZS$PpQVR(# zn)f54#fYkt+Wj>dO`GFOOHK1JS#>7)k2q_7Nl){b!l}{vXZ)!VL=Hzg#tB}GbSv>X zCk9W>92Q13NVa4@d_v&>v?%Giouz~F`iTlOYm@~JWb68wqF9mGq|)1RL3IVRI6&Sy z|9-xj-3iSE6fzpKBN<;KRI*uQfk>=bWS+ltrMn6 zY;IR0t&_FEU8PPt$Lp{o=kA%2HrVfDOmuP`3~?T75hG)J;>|2DmV({@@sVOI)MASY z5!(ieX1B3G$`Q3OH@6vV?ITLOmpRc|y=J51iNH12NwQL!KQ01TsV_q5AaBlwlxQce zp+#$UMuf^cDLV`{9XVB4yHRg4dK!6E;#sFTOg)ArM`ihx*j}m*HetC`t}78Tce63n z9%C2&IZVQ2D=sx=s8;ZxrWe+7kVUeX&kAwH6pVBinhoI)+F^XQ?7yjOX`dy6UQa@- z#)`_nXaDfdjANJ|gZ&ci13I0ak>g|RbP}FK{}N3q@|qvCu-nRCcW7_Pz#J!>|9PTR zwy$C3tG~Ubf(<((>*Ad+9$i7F*fz+gQSDB9#Ykz zErn%XZ2HJ<3cPTd&N7{zliOP2pSX@84A(Tan&TUbcpt4v-vkTsWh*=LJ<^z&fy?G@ z;^?p#vaGlslj*XSuxY-$_6+kL8C8DlBF<<> z!WEEMxE{6ac-bH#Q~WuB=Zq3NuU9`+o|{~;%F68e`dPQ|C|8-&;vWbVSb@!EeG~$F zW`69qbO8}VW9_#;*L0-pAdHm(N5lm3g)__}bka()Y$A{tod@{wwHhkfS*n9hHAizJ z*4}7)X@=m0#Tq3`CT454N#9x6c9h^WFK+usP}oZEn}nzV5o0HB%Y>jAEZ0OMh?TD_gy==u1@@qsEJS@Q#xw))sM}lGaLgPZdqhGX6=rSW}pIEuI2ChOa`O(V*!)aj|D&bBW1l~msj|w3Fjh(c+)~R(WW{b zNJE0qKaN<`CrUv*?ob&20v>cgS4IH|h%Qc7>CP=7?6@q^KG%CdM`n ztgEXS(dI5>;ZgKEI;<_@&ac#a5Zkcb59#CeKW#Se812q0*IKTk&z+gtw5`+D7wZrr z3%sFcIy?5(IpzCn()wN2x-1(C+^k08(AblG{g~`+&{4+d!DiZ-&@pYhzg?z~sN2el zefhe$V;wlM-j?;CR^9^g1p*EBgQIJ4C;P3E$qnA^c00Cx)G=^?Z=M_ZWTi*neBRFo z4(U+0$`S-W2P_A!5(lq4pK_BoAU5X)j=ws(v)^8B=e#~+4!Rh~a`N80;lP2K*FK)N zbjZ~=8hH>bb~qzKsatCz7nt7p`9C|Ib8w)72w@3U7p3{g^bf+J6Sj+iO?{@^P{V4` z7c7%bEzws@P%3@og%tWdQLvk|X&HIUFu>DmlpE)-U4&K@-ZvPXamdk;l)2}pd*O@NOj5h1FyUoLA25oNYZ6^Bu z&A*Bq`*mKE>2dt9N!OoQ43*eU_e>p;Fs#~6X2k|d15yRkFh963FZEU#qiExzY+7uh zX8=vAdRDcl4%z!MZa5(Q3$`L+7`}4zaoyQ)g;R?i3qN{$5Z?IA1kb3hkf?Pv~UZ4Q9gi@CP&qcL^ zin+=wzI7b$?1$fJ#iQ!mG;E8TmKTkG@K$h7u)pPy$}7uJ^QR?9>j~B*SC{Lv&E0mb zjZ3#xm(kUuZ;8*|SL>Fw*FN0{@>YT!%&Yb-`ZdOB`|6-OAk4!$Y)@EU)Cdd05x zkObhVcZ*~T!E0Iyp_Zq>kep*!ZA{YavnCv!S%k_`@I58{oO_nl$jy_w-NT0+B6_8} zimI0y^9rnEtK;Gt?_7d$b% zcrLwoZfcw=cYyXVQ5$i<51>oI&pik(2(}8;Kr8_ooK-|KW-8$5q)08lXh$;)defdm zCxT#yo(laBKY_s0QsO#(#qb335-OW}_)2R|HX{=-HG{FOCr8x7cHbrdEmvp5_8A6j zuv9Kf1=X)e9%C=(ClIw7o$d%~-rG)^<0k21#hxV zvjlQwWn6)9ZV7VW_KfTl;+la{ftCT<@}?eorqs2S_o5!G<%Y?sBEc195|qOFPw1U2 zL?_uQl$_f4SCq&kbziwIltRjs%gU5ui(dNb&|n4w*v`5?7RZWz0^EO#1a4k1wd`xis~Ors*C1i zV%Y(n1d?>~URnoTz(W`9yktUSpDrM*@bSE$i_=Q=dS!|&+Emdoz@D1#lRm1uvNeG~ZP01hS&E{x}?*-BPJcszgC!hX4`06D|$OM&d_lx2k@`0##HMl|&isIa? z1jhORp?Cn?JN_qCVb!94J5IGRGHqxWmoUuFbLo)n0hr!;q(%ogwotwP>Vp^QCH@)) z-T*ABY(3TrFQdbgigN8p=E{qJvvsd4W@G*})nvGM`>-k@We(vCmO}4(86#}Ma|9J- zo|qEl=A3HcWNj6bxKaWhMy3iI69-Wbk0ZtvLhpLd9$(#O%$4TX=A83rDk?Q2n?u$% zn*}yEAF~Zbccmj-??h82e1(JnZzT;|YAlroZ#%SnUIjY7JYTda5U=W|Zc-Pms3Asy zZrcLNKqf)?JWioP9ZKR?%5dSh!mQQw!aby(V%X%Y{E-gXH{`}w6UxmFDe>V6BnAy6 z_n0ttB@Liazb`}YLNw#_&I0x|3}J5u9A#aPp*{(2Na~$pHzG892%E+Y?^B}F!u*kA z3OGsCEc=?I5L9`MMTn<-w+zY$-lny~`yB5A5Jl<4Vsy1qbY(xZJ`Flln0v$8!D(F& zHu#TZSIom#@h=X*+8>8^1N~Lmz?ex$6rh7u{L3?=XalEX$58V*5v_h02D@;7P>jej z1m{n?Yn-@(_AFbwfIc%^<~jnc$sNK0o&HPj+fPBKCkNoy|{hX=&4^f z0gkFs*v{sh%v@~G;qGeh7FPpoD;>7Ij+ep6=jQ-5`1Sg;aS$q1AE*?h3`j-6!1!c- z)Dx4+tC*8Zh6c_KPEp$M>B#uuH7mCCav8@&fvb2Mq{!b$u~C$MCmwiwvUzX~!;+{U+rHG3uCH-0Px1KHxp+NXyc%3pjU>HV zTqT@b-Yss=`WPIjt@7|6Px5Dr@Kr9f>91DJxGfL{cYfKc2zHJ+{scVH8%!3(WoqJs zqo+K*?sY+Tyq&nB@0@2h5ecE4B=$CZ0`EbqN@YXgt?6-gCo8Hf%$EG((S-9{XIcgC z@Meg&IZ=z50GiKgGGXx2wf!AMW<_f-KUS7hHJ%aTVBW^8utz+?ge3HT0bM|%zv)tv zS}9VPvWFC>PnXC@d&pSIH4c6 z)$)Z{D}-4YVP&-=@~a#o>kt`-sC0<5LsU3K${~_;Ox{Q-zQSKIR5?!>SvjL(Ud3wV zPUYsxr+v@Y?&WkP6b*;^jjMe-B*Xw85@P^X!?WaB$}Dx3YnC=kUnDP57O9I|i?l_0 zd$zsGLxpx_pFx!~)fU&>?A+>=>6MjhDu1Ltq}@|}U+um9o>ZUJo~U}VdVBUa*Ug=tVS?xkm;?{||6kyQL@CuIStvIcInBi?wh2G`JM z(%;um%tmj@2>SaP+n2_OuATHQHBnZB6pX~y0ec3J;RDtTAOq;|u0*UV$Y4S>X*WJ$ zOv2uXaZ5R^Tas~MveIMFSN5>Fdy@2G55>M&X79S`^F129nMY)P!ioJ<~ zjmG@4@y>{(V=rgGcKHPAJFvy~GCC%Exe+>-!|;Ud@Xlp0I;m4(IYSwAVMBJQb9@Yy8)eiJ zk)w8`T`;FqO>XVlwWya%1Lv17%bz-c8G2!|U|>U4w(1Pf(^NBj3%tN5L2UGr9lp(T z+jXn29+>&js}D>(dq~aQQ?LKUOtVc}v2gXGV6ZNB^DFnwSorGo2j0bJ#uqQ2H}cGM zI5S}E+6iN>sV>i*d)=ksDYK>wPRGl9YGwV|t7px8iUh@UxkIaZ3SlvoKr?q+fXIfUR4JoO2eG3PGxvT&>v zSt+rSJ(&{7Aq0nDPaewf>mbTt6P1n1qe`2yNBK}Wsz^vFSC%Sklt)U34k<-NEmttY z5>GfqD^Y#N_c*|K z<^bbWHm3blo$z!hl}2`fjVV@7m9jZMLH@QIY&pOUYR3V)V#l{iHOTVbX!rC#AK*6* zjM??=?d|+O4;(lV;Ik**qrG`fVKVm_=z|2R!N0LuT`pj2SH^$7Ym{G9$|7a8uB^W{ z-RK(RKhHJVKSOGEEpQ!I{~d6jk*=*eD}7eg`BfWhAFY)Jr3UpGUOU<~IyI`#wA8dd z3#B=!Iel7d*VMjObtLsg`pYUa6chs;WNUkM+$UiwJdGskhg#86vA9mwaZGSm>`5%7x^0iOT`^%%h{Op0JuV20Sg=??g+#H>p z88CO|;I`Xw)BE>he8>H3PA>ZTz}3%lHGkOi%A3D__1BKK`(xmuAO=(+aH5ZFHad)d zaG&^&a>slkPu&w0F1_Iz1K)2P3?B*?!+cWqyZu3LT#&FB)K%TBxgE!X+v#(6$*u&d zGR!>OVdm|2F+aD9`MF&^er^{VS*{9p1^p%KVi)ss!~Qq6pWDU!+%9TccxmIim@D0d z;omhOOh1Wc^yUYD?0;W`aV925g2z<2hTi)GuR2Qq(-zc;<@q+ zu|>XATqw&8#!&Cj;K1-GW1M$fa8!7fFiV+Yt$6j9JG z(E0VYdjrlFsNkz`0oFcv76F;i3O|6vTr=oL$-(E+quwq5^> zdl}QXE0N}=wx^e&A&qfIoN)&;D-eqfA&v4Y3Nrq%;Bn<>I5adfND#Xlb^bxwKT4qv z(+v63I04L#{IOg#6K-w6l_Ko!eI%xbojslrs{65$es$N3fpG|o zjC}I8-~0s!ulwii9~L@yZCiKiw(Ym9+eUo2>dsY#zjg2b=MQiK>uq|4Pt@$%mz{y^F&IO zhswjb+M0$&zOi;Je{Sszxg|GWUYJ{@tLR%7iQG7_-+g_N-&fURU{wct9lO z;&73OeufVH45_i-h;G`JqDEgqWcIbF(fW(buPw5HATm2e>_6lb_@V00R*JyoB`BZo z>`|FaMCLyFh_d=&K=R!Ty4Usk?J^t6J6N6>-C%X+Y2+ot^dt2MvOo*N*~}Am7Ac9x zfIk>YXF2K;3;1mvJCJLdyKB*wm&dF)ci`gpF2(hu*57zdSzGw>gSV}JZjzydDqfC< zF4=d*tN}|FE_gg!cGL9H&)+g(?F7GDk5*>X%ln?$vMjvp_Howi^Uk>X=!sj-9D?7k zjvLkE>&|VxaN?O)QSEvY6oV<^#^Wu$H{L!CV_W985%p;(nzG#KnE5oEOt}ewGDF1z zwMPdJX<*xif%djve|uYzVOuK`2sL>q!@3%8{x_U>FQMlg8#lzvam8-<~W8yHBj;Z#+JlUvpv&&6p~FBD^oWh1@8H zgVwmH2m1}bKNgC`c-{bGFXW2x&xUroUv+b#P&h`CWtKV7H!);In}ufO0%N*)v2SMR z;_!^<1+m*h4-g}g;5cu>r34)3c);oN00potW*EpOB`n#3{~U@^j<5kG*^W};02mwk zI3TCX0XfI5;SAhF*OcKh4+}_o7%zC(%{^Jl0WuRZn#Pn7>uZs9bR<6KRIt$w(o8V& zJ-t1?H}0UuNj|^KXQ0#op1QYLh;^{-=WHM#YSA3L9uIm0kAA+ru=AAzh25Kfhs)mi z3yxj$>D|9CyhC2cOYl$k7M}X+hlNLX{0`6jW#K=C1GoXlwqw_i3LioHKL+FM1)5cc zD#%bP<#oBScTjw0`FwdvIj=DHlgvuVD7gXmu$Iwn)JRy44I^9*;q55?eY-c>0NbP6 zE2%Z??7=W^Y!(^yAS%FIyXI`M^om-<#LI{-^QP)6XwH4nXAmZ_X@WnmfafAbwfTvGRyT>ao{#w@s%>hvhh4+CwZl0mzW zOy%^c3`XRnDay=GK`9a}DQereky*T-DRdTXFQo~E1R1Hah(#3%iY#CvR5CqKmwSJ| z@&10ZzMkgZP~$N6;y?kT3bRqAVo^666|lq`WLkg-{A@dHacK)z{Eww1QVpmY3YDrS z1wa4_LIHd4SvORl(SVXrc(gvKTFI)7XrOv78l%p@Gf0cvtjx#r$wGOday7aNUq!Bw zuU4*7*Wq>KR_-=wy}UvBDY{>|Tm2b&T>S-lQQE4$hJK^IhyJX7j{c#ZKwWAryp9@1 zLA4rX)xqjSWT}c^d4mlCG)_Y)%&x%u&{sz)g{K~t`hgfQr)@!xdD-xXR$)hpAZRX% z4&To~+rW2!ZhsEd(Zo#JKGtAWlI4t|`V~b*93dGy&r(oTq}oZ7qNFMu!a|*fwF=p? zEM<*Clnxx*VF3yv0#KHcBo?l4efCGH1UsXV?tFJX8ty!tFCm5=E;k!#QqiewNE*v7 zA=6&mop0&MU`(A#1j0WrT=vVu8L)Uh-&MGr&vxH@=@rvfk@d{OSL_Cv*a9+9LT*yF z3*nM^q1pz49n*JQtY14W)~~G)<1-tq^UO0Vmo6%qL$X-%<#v^LS1Uo%F6-=G&fuV} zI#>n>bJnYjZv`7^xY_*~EioFqJ%*h-)LtUKW}1rXXsd+NNV zjmB%jtKuHxsNs@@7GS+e#sXKH@h|OP`oG)?ukkwX=3KxzJg@0)S(GFVXj#<2nnyjE z2q-COfVeckUi4Ui9^;a{=7(P?2|J;2xFJ!)skqQ#7&vR zAK*Xaxs5#LJ219fle9h3hZ?sL*o5vI9_fHYZj{zYMEa5E?RRV>8G$eShXGB}^s`PB z9^MoMD~5&bJ1KAEXu=sV2i;;PpVrv7&%JNoI>Fw8IJA>r6O(5)xAPuOmUb79B2@f( z$Pk(2K{tu-2{pY)X^4Poh|2#0dB3@6iGJd%*lFY=L zc3t(u+o>e0EPh35ga=Rvm+wMaN%y!MB_un91=~SRoPS^)hNN^Q~}>7XPs z08~OkT}(|$l&z?VA=zwIB1+ikIP<|%v}C!M<3}uceQalzw3{qKVLWK-{BPMAU5BBM zYz=m}tBGZjb;EcDL$ki#c&(R;%7mzanH^}R2iBW|&H6yv&MqTH^!%nvE~~xy=IuLn z_;S^W#~v}xn)f)Fa|f0#EBx?|?jMb>jY3P$4mo$&q8NtoDvb9V^{oKp(Xd7Tq-&k0E^W#E5hg-$6y zgNYT9FQpruJmm*w_4F`F;&srj+;c+GN*(dh2yX|<-9;=R0rp5MElfy_8 zB~VcwP$9Y|GQ4SG!mGTg(jC*`N)zzT{{6<=`;E79`%g_5U@F0}OJY{gA{Q{}Dm4?%;ySIM`^_jC7Y&*05uv+HSX2ihs_cK?ol zTYOhJ!XNQ`;_VWTD{&VCpc*R;(RQoZabD&>F6sK1>h|znWXh79kvti-wux~9ppBvHKK1$gg9s{fdw z<5qpCzDDQt4*ZOzCMT-+3iU>ns2yawrA##O73Pg5P1l`nxeNifGQSK5h~$|a_?Yk5 zd!#6a7+}e#fDfN-0A%~gVe@rzdH4Nq>?iY2yhm2=IC%hM^)0{VsWQ z)86U>G?^hJF_)_tFmHMMtcAlbyy&cR&KY)*Kfz}oTXycyXR5{wZ(ZK~7Sy>PLi}!q zYCo_dBC}E@R*DkS22u%(e&hH@zp;hBC{Vp7u@W;!nyt%DSSFtfUpaY%e|K!*laB4{I4xjcAzbWi!a z+Iyk*B7gUN9{N1;kFrDM#qvl}sPokM`w7E6mTAY#(<{?&-~YzJSNBtVKB;(w>jW7R z#sAucLNpN101sJEzN#Qu}!tQ`1Ga$_x zOk$zTQY4jyTlT;8s-3I7FF$~OsYN|T(QtWugl|M>s&8tj)z=#O3Hb^4p#G%sWK@&& zh`NX@c^l%=QI+E>&Xr*ZK$VT)i2(P0^ zK^~6_ovLG;PVXr(q=zyj;}uV(n@KBoMU0K%E+;_pg|(LPQl%?b4vH9qrRL6ojIda! z#A3GTASP5S#t{}{hjSSdL>Uu|jR$0VCKz+nGO-(|JRo73SxQQoqbjp8Sj@7NV`}G{ z_K!835}r1L^pd2@OA~IX`MzgJ3!GivMT5G_StENJ>&(VFBM*Z1FiU|4R&pE#PC6;e z0y&i_MtO>B+FJJI&)+NjXZfeMz3|uaEs+~%u7B>yn-|@QZwbA40GDC)XPB(r@>p!~ zWxxK@+k1ZiGG{dK(uW{(OprORSgTdS>lwX4AE^ri{R86{kZI}^|J3-UWUeqznd5Jb z?9&8WZFaOX6hG$z*v$W>4Ob$?}FwCaug4+gt)n%~F?5CvV7f+!U0s zTG>EaS+ZE|d40CsS}8Gioy0POUXcz+A4)}ucQTI?y|RrH_PAm^!~9he%M_y7#*=zU z8kz^fyzISmglLKoW1#L_)8W$GCi*=kYG@8XYM^b6mN)~%4(=84=Z4JNcjKS0T=dpW zt()q$cPD>#<*KJPUw8Fmw?2Hwi6I6S(MZErooDWyZzMzJEK^FiO6M7QW2c518Iv(p_Pu@>36AsY? zohZxx39-DNke8)$^~AtKO!9|%GJZn-Qc_oGW@|{J0-Mby&}kzULwHXJhbBZR2&$sV zKGCC5vNZZ=v@KeU@>Ce<&IC+*TBep!dH|Dxk&;vnDu)zaaR8Ij1DHy4ZB;hImOhaw z3x#F-C~RV@G9hwWsIoMB^}A_3Hh5xcqR9qLEU72T8*bgB)9K=LssSe&ycR>cY{n2x z?5U|)3mr^>gWbPXSvHF;#8O8GQJNdR`p*|VG0||fyUfccPrh?l`$O&LE}1xR1-Ykt z`w#n%nLPEb^`!B{dv;!zm<8RDCV$_Be5KAYoL=%egy|4vj&~sL5HW{{Iz*Y{c#Jzl z%psx;aHM{7F{iQk&vm-TCA414u}Gx6J*WAVMVT8>3`nGF&Q z(V}-QT(248j}3Tw(W?8(Z+QLT=eDP3owfAG?agz~Upth~-aFyqOPY6Y+1Xu1etOx( zL+^dE`#!Sm>Z>O`cz5@^Fp>rrKjCIG&H0gK%p;eIE6J7OdVReqDlGrM-9>>!2adM$ z36G*UOx}CuT`7jAWK~t}9g-knZ7ztbp9pe zVOyl7bH*;J-rMr4AN*=Rel)y!^@tTWa9^E_biBUk1FAo&5#rtg{o%&H+KGFzB<#c$ zZwGlzCSE+i8)|@~zqb@1@L7oz-P>!O2SguIt<)KfxKSO8N0ZU=SY@Iy3r{1{i8{9?b)@5-YIj1zrPs#6K$)NLwj6ega^)@PWQINE^ z5tE^cN@P{dVB*J^U>ZLlvxS@_it20~Q4wM(%;}VKtE2;a+GSZ1#Fxm02qB4D%S@41 z=#RQFa$D|J_Zs(6x4_(*mGqQ*B~ov|cniW4(G{o&gDlJjQp97dOs(E$4-?Sql-Ii{ zaX4pmQ4bBB(FcwH5!j6%G5uZ&BN^^}Iopmb%_0~vt9eHsoRulJ*{vtjwuHUCFVa?| zP023AfF1M99U>P$*yf>)P}&@MG1jQa!PuG9hqx`&XwL=>HWEL4qd_NpYNtvJ1i45p zS1b*xPX(&UlPj7F6S=wFzq;a@MfjihaI$#MRoxd|r~HKW{QaP3Jk*xuLY5}8WmpI+ z9WSg*SFNB-DZ6!(g@wLor-VS|Ts5UMJH^GLaSFmjR$Oi*D@1jPY$O<^VQ_pW8wLil zC)3!j4kv_t(l*%~W$+J>mB^{bp zn$34-Fpgus65>7;!&0?UfZ=OL|9owgQz|Q9Evb4NJggAt@-c1~l4VR(`r@UT?l$yP zUm`P*7a3%RrI%)fi%!7Zb~<4CE?sq9_6iwIP4>&=dwCgbcUH{05fP8?q=>newBW;dz~)3h#)uWgWMCzIBuk5$>a5N-0J=00dAADN#4vo zBZ*$(al88o#4iX$1_0Ynkb#u7DV`~G@)MEiTCbpr+-`&RQ>%B4mw0!R%}B@nw+TtP z1NR5{q^K;2Xon2dq@~^H!mi!$!fxz>t6-$Lws~;x+{t5hYyl-bOATyvkQpx~g;v}7 zNj7gcX*N>C=*oBHo5Cy;iACFBFWPJOa2|z0uk<)U=_hJ*cAg%g1u1tb*!Byg6;A+{ zzKuxn?IHHMG#Z?%W=5M{{CcZfrAOJg(u;5HOf|Y|Q;i@v-r701(LG==BX{(LqkT)` zsD;k|VcteN^(ckeLNzJSMmUYl`*9_{uwO7T5MPXimkKks6q<$IC%(G-+(|#-P97i4 zzj0z9f9OP#X11*>EaX#w;=Cwwyy z9vT`NJ1=xztVO<1n-!WBTO=>m78*-Ji(`9|fAYT{en0xB#9{y8#Gzy{8BFszBNrIR z4>d;f=NU7Nk6iyOD;O@*%?0Dk85xWN=ei?~nu<8aSfs@4Kvf=8v7uUOtGY(zlgt!L zTBRt<$21fNRM=VVfoZ1Rqri3+v9yGNY&@*QzIsxBTDZ_Q!7>PazZb}H{usTSKgMa! zpJU&4{;-jYy|(kGe9Yi5KF#~nPS`Qddl?>fVLdezm>KeKYh*1|&J7aJx|zN2{m6NMAEpFgzw1o!0reQ*5v zjo05n_Ka)38>Fg^!sw`#m}f5blX1p4|Aoede%_@eXfz=dwpXR_I*7vC3*Fn3Z@pOx zF6>yJtkO1;jgo-tvij17kfX^chW}{zdlvHef4ic^@$al?5$Qb%+nI$u!C02>y?#e2 zQOI_m0@7m>sp(uel1j0}9cK2uHc%kF9UqVQT_J-+Vchx6z6zqxRmu-omOw{yu$ zh3@X3arllKXWbOgsb)gOPe`NiCs4>!X*S{q+x&JWVbb4tABPF|2)BhJ+$x0qbQNn1 z*QwkQM2-NIdv*u3|MqLcbe3NiKvX7usSL^YWG)48J;u*&EHp=i&yV}*x@nu>H=o)b z7F2_8*@bv}r8Cei{OI(I^!)S+E{H62 zDauUyv5_D$H>fx*Ld+>I`=VfpCYGFdH7@1`*pVv*)5dIv393-w_MYm99YjBOJC z^`!mp@=NY}ChfCjBy3*kJuS3n{yt?Lqq~VEi!&UBy&-2_cCU0WDBUEDQv>Wt`M^(b z&R#SD=uITM`HdCxFTLfi3)cMVj>3=dnQMofH*WL~9xnU^FS#f?V&>3k_uf%>LD=20 zYu-gq*H^u~=F+XL{kbV-aQ^tQSM)jYsH6>9JbKDC{VC_I2X^=xIKf3;-O0I2ec1!{ zzjA`vUs?U_@HY#7uu>?|%xxsj5N9f!NB@^_Oay&i>d!7mj@pFc5G?zclN66lpRaH8IFiNFYw}EWehK5#J*~?dKGu2`X2WWQF>a$X)!Bh zmM{paOT(c51qp2`q1~2v|hZ|CSmvzqe6qV|E}) zi zX>7CA<$w`vn-G@weICnz_Z8XiZ(;>aBi$CJKmL4c%)XpPNb@CXSr5dd>Go9KrLknL zZ^zGlT3Cc%`JnLFjl%AeFXOhts_wa@{My2W!23Q>Uu!_>hHxJ%;a9LHQWxnLu_8+& zKhYl2pVj54Uahx9_C)vy^~+h&@`f^5=QK}T#Q~D@`*==7>LY&aFZx&q`z+pG>>$K? zI;7bXS9rvcd$2uCp?_(bLM~q30R11a*c^IGr=9O-VyK$QpbEwgwIwn1RY`mKOWNx* z$M5km!zENcy~sG^iE!j)yc?y^F{~oskY00I==7~7X3muur87_USrZjaosFjL((oIm zs7NB%ouZ+5W5^UeF--k^Yu93G<1MeJX+?Amm!2?cAV5=$wmtHQFM89e^Jm3|445+V zzya>TJC-eO7=3~Fr|Rg|OYS&1AKLp#gxE@8F04^_YOnvra|uO#R6VE?RUpJA%fk1& z9c;IRoPUCB~x)t(aZU%&?W zyJ^NjTMcMQ9VhikI!%?}De%uP>lIRI>Ya0Z+DwGTd%;ir0nY)>;0XF<+1^or6(fr~k z!YUYxW$4QtbI77H>OioaNGt??F{P4dfIbH;MJvnJpqtA!q6dZNxu^79T)X~T{UADA z_OCM2?JYCQ%D5V_+N_Bu%g5+5{1*gfL>35(%dYd@?tPGZ!2Mu+Gk%h6HvjDQAwP;5 zek00Lu(hqaku8les=CqeAk4>n35|;-c*V$i&O=$cGHJ9t#9Fj8$ko!KK{A$E9-GX- zr5s80OjmFwD;%TJ*j`u4UJeOP(U}S$y693Y_A+n{-pcv`d?|PakkU($Ip4nb%)+lf z>MXqTlP!3}-oN77VXxHh{n4}kn6>2NTc7wlA^pER@hg1!A3ws=w;p<<@1yrTUik9v zmkOV5c$sQ<4`}!Q!)L*6$8^M%vha)^J#Q}p$@N|YGT^~3ktYgB09{3DY4OLp9Lri_ zm5;sX@nTO!gh_I1QlxRFXA{3khL-j05%!3Cq&GZ@#|kz^IiC{HqsBly)U_7h>5}Wb z7w|1oi>ujvAHH9`-}NHt(0=E7-TkKV9`|SE5Bgt>k5sRdedW@S*Yt#SkaKh{f#s%@ zM?^$Ns!BvQhG>RIE>~LMalR;WlB_6L6hTLG9GG;5Ti3D2qZ=-a6r#I0%}_-T@u{4O)fjnJp?eSZW83y=aM( z#5F8KcZB6mayO8QiO|?%&DAWpn(wkxu%qEl<0HW2ALma?cw*SRWZ>sZt2#D%JnLkZ z#$=bUk=R0yO(o^q?hcnVy4d8RvPP{U)X2e??t^+Ym>df<;)+zGV#QB6$k@#5oU_s+ z=*0REHSPyf?Z{PO55BqZz~7!YBVL=?{!Za;eEa+F4J~|1s&V0)G5yY|KT*)Se~-^= zDdZ_9HGu?@ggq!h!n=@E!vEBlbZRkPs{zNjxD^xR#n+Y zGXP3_OdqIuz4ojdOYxY*dCnor<@J&22|qnX@4XFfZNES%-sfiVzVCS&_14kn(WkM8 zS%ZcN!^D?_SHzd3-^#DWrLkIzHqE_Qo9n*Td#&#_@5|ngq94VMMzvR5FZxK#h#O@_ z!VrI1JPNIN2+6QjK(a;?sv(Qw>+z^R9*@fLC|G@RG|uS>qk}xTeWHoY4jkS=-vH4n zZ^uMa9WO`k#VfwHSkzZt5&9E!o0Up8;Fri+ltcy|Vrk}%;pAd+1-X&%WH+fq<@m0x zx0iSpv=+4>d(0KO8A_wtkLXEPgxTB|iIBl!oGh6x}B0m&?7iacYbB*HPFY)dhY31#lTR&&R` zGjB-zzQx$s7=}inx{PYGO?$~7h26*h^#Us8I**3>X@pq1OJHGLL3dKW^q$l&W)j%x z$YN>c>~SYCq?E19^QGZ*(iu+2+k1pH%U|X^49Bp{Gwplw&+J(f%219U20!{_yB*2+ z#Bu|{N1)(nL4%Lm!_4UVA8Qy8d^Hr_EZ;}2QS03N0=z(6;QB!1sU#I;Ndch>hMlU> zFmzIN`Bl{g0#M;t@R=Uvk_7u{{;1{>F-H(~b&!aqfE~pVf@F6G2?K;vrdaA4nn8+p zKvTK2B;uw_BzF-)=n(}#vft@5+b4&#Qjh(;)MF&PQ+Mx8wQhFMEzND~1en1#AKQ=? zV6JJe3%>4*99u+JV3Qiya=LUXg8{|3w$RjZZE-q@LDm$F-(BoNT(OJsb&KsZV=EXa zpz37!(xmOJkyF{4%<{;6`!7YU4|}n1Y?5K!Z+wnZlSZ9$5sv@8`$e*Z8($c`di9Ep zc+1J{-9MuKv+>1G_y9=OGE_r2nhAc?i7p@QS>()-wmqw++0r&$3hj`#PRVOUaemcm;m{5`M>uLg{j6r`Dp>1y@LIzvf zhGFaw>yJ<=da?hl{l;&c?4Uf&!=f^=@8Sp^DOrJ$k&(%n-f79j++1m{yvRE@xl+C| zev5o-{B8NIpeeCT@+v2RJk2CCrBcb#tkFa5RmpTRMNgQtmXmY>^^D;^T};tCSpdd( zsm{0q57~xx^sFA&+cWgF#g+uftT3oJ>}OzP0FS{79%VL@v9T7|afk(Qua|p>8E}aX z+-Ow{4_zF(B6MSj4;c*hu~rPRux2P|FXKZhx95I)yCXJOESbvFQqn~U`7wD)o2h?4 z#$&eS+IzMYGhngA7U82JlgdwTX`u|0Et?U<{$Q{4nG@T?wPP30ID7gfdo2$?LqBX?KMp}pF3awG0%BHAtDVR zo}juoiOv$%U*~u~$MKwwh^F%r_Y!#t$%x=bEfw)RT!LO#K}XDgQ4mzCth|9uS|}~? z{IRpLv%SnCaKK0NrH~C`IJQk5AS4?#df$m@EuHl zeon1x+WDmk=N}tvNdOQ-$C{i}F-^irabe zyr&9}f%3n%dok5q&lNtvH=+H|;}dqM9Fm?FJMbhci@7F{np$x5{F1bC!&kd z73fCvDCprwU8S`N*sLU)QA|r3HSV+#LjAyc>d6EIFnH(wNf!)g9K`M4zwGwx_{ePP zd6^C}FC{#U68NO$^VxwD+gBEL{K~dIw3jgun4Dv&Hul6ER@%!s_xPZN9%1Oy?36gB zZ^Naf*^V$_NUyeGX({AOS4-4cL?-T56M;b7OTnhg!}E!_?#4(8Q*R5Ee_A*XMiP?eV*Pe)s>?-j~Nmaa;*kRd-MK+@rZPqZ!S#u91Y$0Z8aTpcV*YTj4&8 zFqe=95C|kR5*Wvaz}&`wy)izru`t)K-bu*lYAyWh6k#@pJ(Sj#8IT0Sw}@`(`-Yxz7Fd2Aj+6{ugPMfB{E z?I&;%vf@YKi!bT2yo8V85_-OcVgz~_(c@Y61bgr!nvj?SgV-+yH*5>ak!BiPZS}2Rcx76hl&g7n}jJIZ+?m z>(1&e>ooNVi0Pjrx4P;yWXbPn+tZJ`+QxoV&Yl2k2QvdLz|7RQEY z5vXY%*2!L*pQ=s}+4xhaXKnyHfEDW76kfNLY%^}NzHSlpqR~SpI=dNwozp8){zLCm6PMuPc=oQT83a0Xip&C(=Nz~X)wnR z=NPa8!3HU8lu}bOsDaFJ*qAD++wQW_HPFnE!^Ujy+gPVNd*$2v)^@dyU-9S?|99kN!1$YX)>)sWND$!N3t~I>Ry>H-{JkB%?vV@)d4&izJGf6P;xQIW;)9>V>qPM3Max!(; zHqlZ$4W%n#lIGJ*m)*(CKiO?})9~LZV_}q{&&U`n>Al{ubZN_=mka{O^Rl|2rI#dG zUF0$tkU)4$M5BZx14oQdS9(a9Vg)Yk6FP;H!bO1>ZkK47u|UMK*e-TbGjwE&61drH z`u}td_0Iz{$ZX^E0@Y~b*Bf0 zaXzL3!}q^eQWLZ4!}nk7HYHFdUIXDFp-@MS9!oZhtx!)fgUxI!)VA2w45%qlsVjjE z`G&)gk3y=iRG=1q+<>~(Nl&94Mug5%UU8OE-oKOqXxy*|OOPgv*R(8PXRWANsky4e`(5(5@4C7^@BcPKL>J+}Cg9&6L-ITi{V^Q1%TArm=sF_VTb#m`@f ziN)s+YbUULp^Rc$Xf5rTI5U}5m}FLAl39gGW~Z*ODRTq+Xbs*_-JL_G%qMG0CJQtL z7dq7&7r3awt+=t|m@;k^pXT!?`MrKlXA0ReT%lk{%HTt386I& z3K=QbZ%ju^66$fzN#g@oXyzsqq zIC6Md&-V(N+b2)oG<93YtI@x<*B0Xh`Y!K@PA7}uUE0uC#gJ)*ajPBbysZb1>P8(F z34A3%?653EoQ;E5!yQQY!A@2$`o5&cF|a9e+Kk~4NuZ}LjDn&U&pWYU zedgFSc--jp6Zo&#^7;9`uivWKvG@2-qQR&%8t$|6}dqBp?k8JZ&~fuVzgLHDS` zsDoQ*p>q|QwL(?T(V|-UXUHEFtHD4GY6n50Jz&?$NI82$IUQ*zfm)poWsahD@NA@S z1H6mWv6**oI5BVX+30k95r1^z=-wUke*Jad`Ol+&j!ICX>}U zd$ftT_?l#V&Ms~WYd~K@-TtXgMUvPu%Z+As3{GuM@UnWY4Nhlz0n9ZdX^CG}*d`vF z&a?&62kn=$QyVl)ohojCCx5Wz9nG{%dcJ^%p)4-LkZ&q5EjDeJw(IwpPMWTnjIwE( z31kJMq#ZE$vL2g^NMeTuYO5*f2EAUE1g9hk2xFNDPC^7dWc8_RK$1Qz;V_Zd5IL)K znuOb>JrZ1FteAR}~87N!ZLKv*p7fv)A6AP7BVTep$U;87*XHMAS1 z;IXOdOG(}<9#w@&vqeJZomC}BCq0!9Sz*}zr!Ku6Q%`bIHC=7UZrrXFZrg@}+yl?uz^9T2*-pju0#EN;dGs$lhEjp*4HzG@- zWfY3lu)#YCHRIHXZZflCn^mzcwzgaO05eVRUE8+0 z=^BhRW^td9FJR-?)*;)uRVh9F8~e!y?=MVed&`&=YLQu?7Tv05jCzJea^Ob$)0+9| zLHo*LmZzzWlN(hS;k!-HHX4rB%uNs3O*VYkW3zt}z1sBleLr8bzc1y$U6E%Fu5J5a zw1G%trrQEoS4qrr!L2Hv1I zS**4MQD?-&L(lsb5zk49b~8wx0zCno9RO}N8J)byN!Xwhj0o9eCwBJg1Z4b?t_MG= zn1vr9CBadMyx!)Ws$?+vi@r;A5oSSoX+E_W5nGy~r!#3|6-Ti<5jqc@IJ!8IT2&LN zfuYRN#UUlH<5mZLm~$@MoOl1-W1H?On|gc6+SZX9_!oDTWWQ8Z_h{kpUBfIz+h$MQ z_R#IKcjtMbQuKcmZQyrA{{woKB*la)Xnz8o$%M*5L$(nG9P}eW{<(zR19T+c`Y`I) zwr$%sCU!EhZQJ(5b~3ST+nU(6{bkN~et+D1*1fB-s<-OxURArRt84GatbZul35Fx_ zO^ylP%|ImlnAg}R^eH#xCu%j<2RNP^Fjm_dd|)VDR-;xKouP}Q2loDIyMp1U0hsxl8QAQ~(7h1{&ke-vE4@Sb>CO;E18mj;>|T!b!yCGY3& z50YePRhyjQr<-;-U{4UD=#sVuu``BPLxZfK5{rsAIitY2SV?DE(Pm`Gk#SzAl*Q;v zQNQb@Sr7Is1{$s4#1}ak9D^0KbtA=aG__L@+45un@uj9WlX|k6xE^T&r>CszYV&m! z^rKWokOe1t$S_HF{ldb&nPfA|)%6qYiTR~lbZ&DWzissK9b7CC{5?Z)M4w$JQ$0gy zoo=ub$bK4ps$FsbUy{sPl9q2Sr0a}~8wvk9{^%#aOCmTBw^3dHwO>vLVRy3RrqkDi zcnoRhAqi|jY^$WOfg1|s(H>{PVJum5R606I;>MnLAwe07gix1LTJHL~fDIlDmA8#+ zowQ54@k=VH1GoGTrngqYJQ|$~3-=>ui&y9_K@5DNt7lC~=!DYyroBHJ zCnkByFC+SO)1gCeVl+jq0_uq6(*8_pC*!L~(3Gy0Isl%Yye=J}%VD%4QEB%HA{gO@ zy&;=t!bwxGROT|!LjxBkY^{7WyN=PG+6POEP|OhVTJLk)rT5p%Shh-@=e@QYQ{S3q z_E&uMi3dFTR74xyZYnIZj25#w>qc{PH;4NXVrf_F%+K9OXXn_hyMZQnlcsa5?i1zd z5M6J24>KFfrBTnO_0~5uo4bJn)Wt|N)go2+GwMFM^_ydBR`ULt;;EDFiT2<`3UGWr zCWaT>`b>7WOHD=(-inN;XGHAj1NnJ*4(>_4rt}KHK*BZD>pOp|?l@~%<_sR4xOL+t z&=G^MBFOzbucoM!>BIVqB2?7-y->oXq-Cq>RcY($!>B@m!BLvtb2d2^TgE$NvN2J7yzWKdub3Sek?kz2njIxACvo(MyC3HyC{j&&(i$#Em@O zR=hTeWA8VU#P$AASqJ#^-I%N%G4$(|S6p7q>$x65-j>23Sa=mJh(ObZ!QI}(wOViV z-yZBz(y)`9I9^T%AK*`0+^5{K?TmBv#-jbQM?1f!eY}>_lBCbrFT;HtE|YxT{f@#b zv#_t+|Gc2Io^7^8XRwXZXXz}dbRXy30r9UoGrj7jm{-q3ZYT9Cm{XW!vrqIClZJ^=WFqqOEC7re)AfoOer5FN_b4UOHwgNM=M z{Z%)A%a9r6WBCTND|{WYQd6LIm*`JhV1sWM@imNH9`2{;_&Wst=<5@^<8(>L53RubdyK|+cnF`X;cB&&~B;*fNQ zQiVv~;jI&jM)WQi=WtxCrX?|=8L`ZkpWE(SMe(u=qqSun&Td)pLC;o<;~W!6b+L!z zg-paUH>&1n-2&;hnWkyRx*`4VQ07Ioy+}>XH?Gq6*VE3A&M~y_aQ2})3SHtJtDjh3 zZTECv+4o%snIDFq$S26-#&34G8Q83(ajR_X&e2HDWxQ!N5iq6Sht+JcgoMS4;*8iz zWr;8|j6T9eHvY0IrG}?YY#IGh4<}Y^jsY7xVdV>)Fk%(;h@qR?b|dz|T=hKa88IBG zY+1jq`l<#7NLCAL=Ht;jX|NwLWU)Ae;iLM|&54Kb26MS9R*F}r{%~L;P=aB)XVJ+V z8IGafOFV;S`#$Mt*ck&7SmiuMQ@IGAhcd!)7aNw~W%H~kEnetU>K6z)PqEWo)`@Bo zXI1@WpV442|twTcM*3fQZ9-&mt~*drqme%1%4`q?$RFsOrW_MwDw=h z;!vLe?z#1(;_2cw5R^SC7Ep2;(};~y9*6-CLJa*LSXG*Do7YpFtpARm7P6|C(98vx_BehS(RB|0zylEd_ zoOeJ^3$XjF1bO-MXj&rS!ZC5vPiG^|KxzQCbLO%Sx=iBeTSjoIJ~UwD$1JUe%QXPi z-E@RT%JkVYQqfiQ_ZPLN?tq|6&kiONYXe(`3Zs*qz?`ABJr-8Vb>YafBUysZmVveo zEKyc68bi?fVu?k&QkAj9nMhwb)uP&?d(QbEMH+*-?|4-LFzPkMN3L_Md1t&e%^1&@ zfCh8{Y(-uUK3!MNVHrl2O?tWR2AY9yj@rhvVX&t)rQ%Dy8~0hlc~Uh_9;GCfl8?VE zj3)^ko| za8+PvSgRUb^ukkb#^cQsXkl4V4I-ZuE^Ul34JJ(y&1)EOMgE9wF&I~=leR}(&PFUT zB!Wy5NhJ^>p8(Ug;Q85;T8cZ1#w;o^Z6R!FVe^|JpOqLG$nGbNAOh2~Jf2NWAEM6e zx?AhhzA3euwKv7h?(u;LB*1-atzLgT}oD8%SS&kky)_eMwZcLX7( ziE*_t#l9eKNk(QNq6y?&O7JM=W-ZZwY7t8ECUO3OGAu#&&CAyP(TG_!@D@*fI#Z=Q zzp4L5$&0*1&3s*YE+C5#ogfZkZv#>D?$k3efF%;%K^=w+g(AO=jnG_iN|vE85Zgy;Fe`hK@`#gAg{{jF2m zB4&M-cW-OUc?%HB?x|^Ych@J05j07oLT-}#&Kpsv8_|BzkCGF10=u5mk_@ZRd zRiSPIDo-EBd*pD?ae>N&DGVAKbeC~KAmIZcG6Xc;LKMX*j-0Z1q<$J0>GQ$oxY_58v%N^PiNczK%pMTX+ZC52E6oR`2?+c3hYMds}N9wt3mH` z+Li;80BSqx&6(T=umCgzdk2yM-;EJ`Q5EF8oXth*dqD7|9(ZsVmDnNvz!!Y};U|f} zj=p;+@RK}9x1?d6+KeS=5+!k#YdZ(pmdvunwbk_{`klN@Tr~1o`a~^+AA5^ko88y= zz?zM z4;PQe(EcU(H=3i_oneQsbXUvIx&UBeAC}z$1<2qn%5`P8w&Tay$pTl@W;A>{MCp*E z7|L-PPv;*ysg#DF@?AdXr}k^Z+89rb4k9mW&#~k3@L_<13gt7E-9dm7962y`O#QYz>}h|=yBlQ#XDTjBVi$tW{^$h zEkRIrks)V!cPrI9CbvA8c-1MQ@0_s15(rUPvT+nEESbVDLir(g0*;X(&?6+umMw6{ zS2K2q(FkZ3EkQheHn7VD;eFi}Etu12pAeLW*##c-2BiIzp;o&_A!q8(Kp~Md9sWB= z{maZh<=iQ3mhHClo^!C^cu?M0aNH;`S-+oH%{Z>*BmO>l$oKn)&LMwi|LR)$F3BhU z{rWWp!$!}8I}*dD(3rW>s3knuH)RJc#MZbaI(hP54#pM0hMjlPj=bQ+q$RRwe%y{7 znt$AmzWoU}!BvdbzVq zh9!4LMGzby%KKm%3rfM3!Wm=`bV1Svqtt^JJy^TK$^QsB!q0RC_Ds<9Q+-@`i0h+L zjY&cfbA0~VS^2t;v7MWYFjR?hz?H88qZ^%(r48mE1I5Z1e_jqsu5rVZ(Ptbd402!& z2oYXkNmhc6G}oKvLSARftzLd61x}I5`@jyj*q&l*Ddtg!_rdn;|HVDdszYmRY;CMB zv%OS*ZIZm@F(jQ{1w%+%@#9yWY&&^{_Hx~?bdAe$zu!rNv+c<>ESjvJtQOO)Tslw> zG3uO}V6$xXnhNlwRfg`R@9M*2GMo-~rt;O4*0}piLmZ0Jr|;33xvnfsG|)jevjDeeo-bfD`ni@W}9+LBFIgNNi zOSR;-2D-yr<&cfSn;xm1S!9zcIZ}gb+rQIVnW!)RxLK>t=lzNnxOqC2-*mhk2|y&? z*BI}=-7j90sXWW*zYQu*J}gfDvlLRi=r5*XUtCnV8f9Te0-eeu-Puk^v^-Wx z+xW1f(nw2vP+YX7Q)3$$7CM$Ou4iWHvw1|uUGrHqc>E}iRWkmHr(dCJlms?B4SG7jFtg{_E0 z7HZ4mleDl1>fns}*OtT%jxEM2!j_gTIy!ZDHqhhIaYq*EAR;p?n(Ahb(n{W1+T}0@ z>diP%OcdbP*s9B{O^d*Z2kM0Bs_a!M_22(mDGdn7nr^ksJy(~-;RBE`v*lU!wv z1MK9@Ucz`3(SVJUwsb>1FqQ`1*W7BbaW+)4{*WhI_#KO96TcIlPC#w9rkSy(dGLCz zIcAcpfoEfdH#- zD90G?9^88Y@u#@>du+@zKJLv|WsIA|8He9;9hYN$OKivts}NV`*0&C;6je%!&&zW zcZ7+(#s;C>btUpowl)ZXmh-C2{cQ!hMCnT`WMz+*2Ag)v!bYZ)0%V_;iKJd@AP$Hb z=$-=6p8$Q<+new+aCQi}=-adaxF{q&2F8A5esF$~EFsc|@7fMCs%fL{J33rgjSk_* zR08|}p#j^6z&}9ML29sbfdz(-%_NX}J^(ramer&BNL_fDpvJOS9tiH*)L3GSQW{SW z-a*gn-eRy8b9l5L%59WJ$CT?3gTF}vx5a6ks@KP;_=^ShRPpQzCr2AM39boiF!V&V zcvM3akv9(XQxJkoS!e|gPgf5!BXRm+;t52!er~wOoPE0#PJN>y|NF%9k(hveM+ebp zLbWzpNMdd(Tk>vka6k`0j$6;?w=l1uOLBC|>E23!V}N5&4rn`60dcy%EzsvT+!x%s zgsprpKPW#@0Nn34pav*%t7T`sFU%F&_cKBb0O6Lfh3yuQX9;{;bJV?OD)COfp}9Rm zS{%<_@4Pv9f%L`1>;^x zjUbXF7A9^N3+sjb{DMFqr`9%q(fc_DG6&rO9gqPp56FP3huC8SfO|q(ru`tuP2zx) z6^|hAk|&q;1@niV&{$L+QpOL8LWx|N4UNH$Yd;1-LC7=5Px>^-g%=3JSt!E=NGxk+ z0~??~w$z?hZvk?#8X$@*&pq-x!R(Z#r{{!Ft}`B$g2z>Ow)+Vs{>qTfD(+w!W{oYWd(>?*eR2*?SCb;RSDgv-bpOrf&J* zpaWEGFg&=98&@0*T$|p0M7Q?@X%4mX1hbJFzF?wL^^lNSwk}9zk9Xflx-S6sJ?Aj< zt{?&BNC$G}1N{@EV>b2uJH^1iSo4Dd1F%kx~d-oID1ZA-8pOx)}Gz7|-0 z^dy1cK(r9p%T2~SSMZsz9chYj0v6_0N9~6H5Cd}cAO}@-UmsS3Rm%XR7QxCv%tG%* zU8r`Ti=<2xcNni1?5kh%vxqAH2?r8Q0MS9&2?K>~ZJJ32x(37){b~DP%+9`=LoJgk z22DJoe-MR{f-I76mU5Le!zlhof?xtk)_}B#P(mV|#^DU7S;^GUL{!bBAWy$_P@9PM z4?=aKW0!@K?cb6Q6E`hwcSg9sb%1Cp_T`C{F41`CsfAh4`e-m3eVLZ*#~(XW8O@g8^>md| zd@LrPGWkdI$BgDGp)>E{^@n)r)j{QLLllN&#fz$oPIBq0>O3UX7dIVHB^xBQ<}9^B z>C1(?86xQO$C5172I*>yla>ig;RnI$xH)W3aX~}NKT@k-HwMi7UfWhu6qz@zE%An_ zu2NB^y}JwvDtRKKI9aob8*Z{p0I-s@(zGNCwlne-&>)&D6tdrj3ZG+kOdBb_!R*3l zan4HXc((nt75So1@ojLyO6y-czcY|un(zl?&Xq07i7FvfT;Vb_HZ&N$H`j&pA@U+m zh@F!M`=W-zc|XV(dw3vd3jA@<$qV%lSbkJ5Lv+7e-{h;@EpqQ9OGJ_0 z;2W#TW*Sz;5xm;Md^sWfC)e>`_~2iVkcoqxiQ~UXQYOZ4l4UjUi5HK-(+lq_~3~c`!ApLKCl#_uKivI6fjBT6< zm>3zM=!Ny|B#g~X&7A($`_5EyGPYJF;P|d0W^3alW^QH7M8L@SS5^F9{OGs$_+R1w z+gW5~WBC8$M}NuKW(XjJT)jiZoDc?VU=qaBNXOtx^W6(OzXCHK|s9iFeTunaSl997wt*kNBPA!`RMKLno%PD+F%~4^!&?6w}kD7wy$K4k5%mW-3?z%cOUD$V>vpR#Jg`idjr_KwTL;k$%e`t3c&kcGAS0x9N(9kwNz)YDI-1eNUS`9+^@ zS)r}Zrz#Kqv6J=piW1TV+B|n1<+I>U`xhXzy;IbRAwF>QDEgkF+T`tsGaw(vWZvf_ zMySo2u7j@Hu0h*Yo9;&9jA`x{+z#@B;_*?qA72j8#obmt_iFoGujL0~zVOAqpuXb1 zjp_H*+vmquJA22vnBuKe6zW2xZ{02N9)DykpU%08CP`>y_wm2WOA)ly^ zee>N6#ogku*`HA0a$mQwI7hKQydS8Z7bn$+!oI=vCBDXt_vi~Kuhb@VH}85^Bvbeg z!Jh#>q}lk9CEeT2L7zardEL3<;YZ+}CSzv+ye{}){S7mWIipZ?RS#V{Z}vdztPrz^&I~jZT;@K{-2!*Bhz2XS@Az~ zDF0?%83~v;nOQjgC)#@6>F)JwagoF4%KOnYd-X}Ok0()*Y@CFI1X+k6ft&_0Oh8>` zMgj;DL8PuGTqPX499k7rnZ{nUcPx&8jD}S6Y_7|@sLIT8a?L=2I;puaOv=RPh>uy{ z+?xOD>3b~6o4aYtQ)c`3&GWMLhz?oRrNTlC>Qn?~4sCO0MU}nHo=oVNAEB=)xLob` zakzrJA3Oocgw{gSbI1eumnXWABB#(gcw|bYw$pxKD8J~)_gonrE|QLh^EESs zw{pgW6?C>8c`w6fPv?PlU_y_y)|KC~g`dM71gnU-hnBeGS}FUG56I3QgvM3~2aN8k z0>FWJDg(_hbUq0-%J=m5wSUgxO2#j4UKJJRLtYjIJQ#?Xe&SEDmtuVI zKkUHeDQ{eem3_|-Nrb}Bxo<#wlgJV+bPLKrO}mqjV{^~*3Ser8`mlW!hn>~0!viEE zM)L|*XpD~~0#68@9^IsmJtjcM0xmN|vkzI&ep7I>cr*Qd{q*p0__Or$<1?N_H+*Nv zlpwUvw1IL&vEV0XDW><7SH$UVECHgm02m9{zpJ$d6OUk4SHW-@aP84tXN##LpG=^4#YJjTJICYl0NhjsFD_ERXAf#0zf?wddo4 z1eJR>t8E7U$W#sZh~NP=SR-_rcC*e{YR;4%nOwkX#{4JHC)~Ovgu6E@{ENZ|>SiRS zE>DK`*zspTNkWMRDIeP>VjI{)9(!*0{o1rn|K(v-xXJ*2WOqR3F)7U+@w0JNSi9?W z)AQa9x&V=|8Hk+`)-FX`Ft*$fE_w8bZ=Y(Eto;P4i?jstaTk~=tT z=;o5JrCOdg1r)IZ1g@C4KYO<*@UhZ)59Rky5x=WpUs5P@B3s5-Ch$~OjR`*Rcewl? z+p|*lEL;$GFU!ZY6M`?nEnxJ6m2TWVFz|5{F9}}#5$Cw)Pv->a5wHVYv2u}LxbAWA z+QBwLXMW9c`FKtMALJhJAE+O&S%YXiQ1rdAdlYy*x=7)Li6@28R>X3NIZX4ZZ)qv3 zNG>>@yl<9|#5TOmqGl)tM>*lV2yf=+>^CX9-GHl%f-i*1pg5hdg}dfXFrC0fzF~Y~ zzPY!+2eG|(*Us|eP#uW;VZIT*{=R|TemX=S8L~rhkn)z)CjfjKvUmjWLKn8ZPaH2{ zUOzs6d`{W@;9^cNH^no}|3UAV`GRbzFMMw20>Yh@H9Vwm6wyN6s1(D!{Y`05(3>o(Z%mCI667xyk;0E9gTd>^^ zmY-?)#5<$B36GPS}D&lhE4o zm5i0p)s1t&NA`7N~6o10x1HvP@_bXLw4Zl9Z02 zAbDcaGXqs`x4@ZOpC6eCxIFtOE~cKZY?Z*(4%oS|EAx1(ZUVp`=s#xEoI-GW_QwE} z7lS1?W?s;AgJ(1C1A`NNuKBmm$U%ch*-_I3W`J$c z)Mh;jyLpz?Toq6Sc2p0u(v+w`I^;u zhpSwvu{tvZy_{ z8%R#16RC27QZYiQAyvU?bb)k~0UFwYhk0a9&}N-)d$Z3|&$u^@H>&s4xgT&xJ6Cq- z6Ja{J6yml$Pki@;n?QHhV_)qm1WQ4$v*;^<%=U;Aq4Vn&Hq_0b+&v#rZ>;=4E#BlF zC?v1&1d~kndW5gAuRz{`q8QlpW5S4LR}^NRw3=e4sRd>{k9lmV^{ctV!=#>dKvJ!^ zEzQV>cM7T4rUG(5BYi?-^#V3#3WDXkAr6#*bB=^BP4z&odUz4$K{UD1KQLdd`wB*+ zO639*n*5heL)kvyJ|J6gm)DZOJ@kRHp^d!*tHfmF`z4eEpZXziM2vGa$Qix>-=})e zSl~+bO8lw-O-dn)@|Z4TQ*%338lEZU`f!3-$>46ZYdnf_sqMHM`d~gVL}YnzlLkzL zus3^Qum^3=D&109hS?b`4aR4xXB-*Gu-Y|K{o+(PwaPI(MPE{9jSHlti3UZ9p`b&K zj)EN>>*|HlFnjO)PVtkI(|7MY*6B+6ZR#~A$O;VNNENm@lL;{nWMEWTOK0VUf5C#1 z%Z!!m=n;#s=pfA^s1W`>z2#A86r3*B$yN%?jQk`lNggTF9to$l;G~+KRw4&mJgz1O zS=8aN6{FpL`T?<2HapM7r!w4p+Jbm3006NNo=u9pKw%?KE>^Bezsggq4}{XZMGy-g zW1D<;H{-JkPzqR6%DvKr-#%=BOL!Sx@Ptf)m8YPfYu7hW%Ff~6L@;I~Yh@L&G*Ozx zK}d>FIzAn_djlN^oln6*X90JnG2_;mPQlMdb-Y+g+rVxX*~VY(d$-Yv){skB!2+6r zRb3g)6z$vqXNhr|h2Xs9H0Q_&5xh3EY}3NR8obIgJD)$deK?7|VD=UDM_LJZp}IVf z$uHSRmDQ>$;P(|6nd-D+9-D)jwl&HYsLJmK@&>i=PgZd9xzvy%3uUMnXu8#o2EdS^ zX3hwcDp;pCFHK!9fETjg8K%o%z_Ss*^tAVa7Czt_+z=-de}`I=eK=APakXkW9T|9xtlmbk+YS+B91Reynn~ch7J`` zpC^j4!M*~IZgg5}Ls|@MjfM(95C1pdCfiap9l#?vkdt5Yy@eSdNPZTx1+qRWt;C6# zreF)56qcFPmwbdHoXiQ1RI9)y0*EAEt}RNY0;AJT&gyQR+)pO12<``uB7fo}dm$hk5LoQY69AC6H=i;^KDk@Eq1%8&@i^G0*6*iTpO5 zUhB~4qN#*JnK_(P5p1+@>^~gZbUO;jwScs_ByJzQoU}&94gqUm_c4=}YB;^*Ivzmc z!3s*swSNnA+l%_Z+T^g*vBtL|T#T-_Y=9 zWUz@i4z^(&O$}pI2hsE(gd<339LP`&xO-o6{XyWtJdJLO94?JGs-MirdrzP9ad58dyNpm@U z#d`Tfi(1DQPfR)^OMBS0W5^+5OY^F-jSJ1LnU!)Z&rYK5t)S_VXKNRL<^2~9sOZr+ z8bHy_sS*slC}U7bJbv}Ck8d_zjq{=P(6-z+eQWrerxJT`Szq(B3U@Z@9T%WvUVLcW zPqR&JL*hs49?6eaJ~hB+E44Mmt3~c0?Q48;KZ)u(X=1_<$3g4^UL2u^pAwQZ(^VKS z-3Rr0B*-}Sh0@azS3~V^pl;kf_CC_7d5P;5=MM<2vzhU3lfXTVge4dsb~9}X6!JJH z1m=pinW0oWE+ZT|3odZ=kB`iuaj}lApDXb4ViBC0^E-C$!-SM$*Uo?eElE(Iitjp* zUvcbWXy~xSGOe`Fm4~A0MydO2l~UJkWj~1LKa5uHCJQVs&tqOzXQqJnQr2IH|0aQph_I3+ExmpG%MOo+zJOb57w({g{<%U<)* zNW$p}u$x{h@TI~8jKX*)Z*YVFi($E|%K|5(A%@bP1PwU1nvQ-S$nihS?X~B2C(Ufp zU}%6#4az+dO222S8dG?xdknNp-qJK{@zLP2J-&*}`jf{~zfifq)|f_vzXWzIAF%&= zIzS%d+`%qjT+BROP@E%@oivJ0%^J?M{l4TA#yHkpJs3{L#%~`_hB3p6wHOSU(cKCI z3C=@_sAVO@ESrTjzyCfH1m=i5ms}+@ebp$&Ng>O|-(?=r7Kcez;!V+j(0WM#~(pnU^H#FNCm z0OJXgs&i zkx#xbbqFz?c-$W2$&zlXGG{}vx`L)JVDiaD1kh;r70I1h{RxoMyJ+_19K}7VmYN0@ z^|f_Is_#&(a^cj4LTOb9MJW}t4j_OcS%e*#(Ik<|6pfM<`&y=J#>98lXI5`k!`2m( z0Ya&H$h`s*QC0n*6p0fdlnuR2y|sKFF)(E;Eb-M$KNw}%)j)@epieM0@)V0mcU@Fi$i$p$^1`HIGg+Ra&vLTo3tny(pdpUj1`xk++Vz*6!>s9b0F4 zHgWCD{q+Wlie8C*&_4%)wFeDy$?m#-B$T<&5v6tUaM7--w&s(;qaW@B@MN;n$eZ;h z8{o{8#Ay7UAvBsTi6g-z9>MOaO{sh53B&ji_&6^ajb&3ph|oN5#xFNCU9~9X7Uh24 zmv6 z1*JCy?`L`T`MN|dJK((M9x!h|lbKuYa85jgr?-c?G~m7mFs_ z)8I%Q-=A1?LCai&-~1lyFQ^=xz4vw=CP6~9li-@b=mxOMdQE_?yUeMAHLDeXj>(IT zf3)L}4XvpRZoD30q|MNOVxe46xme0qX$1;xXiAz7R0f9zrlbMm{jzj<+qm1Pv{~XE zF6p%}dECL$T^CQtvW556u09L69%X>_!7V;t41_cxK{^vCUOQ9Z_BuUtZj49tRZ4_u zf^uYY>j|ZY#~McoRTP`GDT3j+AM_DUtHNTKDR}hoB+L3NssS(xt`j(xB4R-PX+xI> zms!JA6fxPai(TJ?BV&4)7p zx|8Nurv$BB(yz(ua@n5|yWVa*uww6{W|zwBJp1ePf!~K4s(u9jD{6h37wmDWx)Fy# z#!h~UF_uk+aWM_F8rdBq1-aGQ1>9vV4A>JxG7fZ5c-30$lFoHuk_F({mHARckjkh8%G9@$~-kb@eh9p??_M_|Ex?V|m<{ZKDq=wKcf z6mCWTS$i$DK1!pjvbeOMTofShY$(pnr-Ji=QW+}vW5R(Yy$WrK^Eg~xHVCg3En9!+ zDaJXBCN7uUhS!{W9hh{4G*jh%v5&B-#S+SNKt^?2*#yCc3-)7ep8v}ET7MZO{sG!_ zD#tG2`%(|L+#p-;EemGDgxw62pmNY!BWZx#kAu0NU6hoGisYuBOSj=FSSOXYI=Gtq z+Bll{ueDErTg+Wuzm~mi3n_SPo!Z>0sUxTDm)w`*9`-RmML$_}IMH5agyxtc#MJMi zFqMgz8}6;HJIv#kqV6zB3aFx`dgzT}xZ0y&jI z&J>a5x*rD-Q|lUm4pJyN&jFjekAljE#u3NDMI17~U?U8=(bbO-F|<(ZSI ziQLGHx4sI{wLLTstSWDPu>bN%-ia7PdD$&LW9FLVEi?po)X~P_* z+07jKiEti;3d={A@moX9Mbu3V4jaCBS^RJ<)e0^sYRHtI;NzU z{E2RU?Dic8ii-WnM}{_BgWE!XJHwyanyq=>jFwKnDjmZ*z(KQ%hR}IBzN6oK!ei6h zlEdfnJ%|^U9)G)JjpxqxJip1|*?7QUu;f19xCA*#ln+%UbfB3whWf2efrreGxC&%n zE+K-*XhmkVKuQ9I`tFo{&5XGsh@4|V!GZuxU8XJ?OhE2*MH!pwY=2dTJ%6A?m>apN z*UIM%c)H7;UxP7G?|0e6Tmn8ESKOPmp66IwG7Y;aM>|D%!(Z!ruqo*N+~Ojd)5w0I z_h{)}p@*Jn)4p~B$?iD0O8tTzO+v zL0g)E{0R}P$(#z$JZB1`E9=WS(p1t6ZY$kQ`>cENg}UGGP{l~hORR1Z1yXK|uy}vd zTQqdIt+^+2k`a|LpA+wjog>pMU1zjE|B|crh^4JJ4Qfmrx#7s0t`^uvArHNLWLSxcs8}oe2v>s>( zhhf@z-john*S%5-3tU#g!K|3Yj_P<~^xk}V!1Ty;(RgWBjE(M^{Ty4KVpfrF*(0s$ z>Ub0~I;-qTZbY%(VzXtx_mi%@O5qhfEcTN30}j}lU|3eomczJpBJ{1;&au`vG+kg= zOK)(s7pru&)#4&%KCOk_399gc#I`#vy|p^IDv-^0d*^t`7IjcoZX&f&cwVkssjKI5v*Q@TOuHv^Gx)V2*WbI3yr=yZL zcB@Bxuldn+m0DDG$v$P{YZZfOvDcOLxz&3W$eytj|0qgCQ2KRr{TY*n6D^+mX!XHh zD%2`M8z)*LQi}{7RIUvO6Sb8S<@nV7?Lwjpr{SX83Jc-*9e(=L98nciE{-Hk&1;16Aoqvl z^H07aFJfI_>goYIFgf(jZN*oi9jFoaZMaH;A{)ApiZtNIKhNc24h zM4TcD2Cxx|12u3V`gurV{-8lB7_w{-2_umKJ@z!xdI}0g8UbT6HqF%n0|xYT3r0!& z7977(8SedZ<&~6Qhy3-bZ`y*xN4M`}aVwtO!N9#Ydp)Kb!Y7fB?bAg0U+YP_JhhPW8LPW|rW^82dMXn_wHx?g7O&1a;#4 zq|d}&!}NqDTNqx?yHh=ZXp|u+F`6&iVHqOB__3HUf zn+!5FXdI_`hD068Sj%0(#=S?dQh}er6hJZ#S8^^iLJ%q<$}nxppa_HGWJgGL4?B^!*c)ww`}Mh>S^&vG|+!DID?aZ|+Ynk<)ci>YZV*63jkCldRXXu#aehY+c{|8&pIfp|}@}xd@769HL4x+Z0 zqew2E9PbpUeGuC^JahP-`;r;M4O+lCk0m)xzhBVJBN%kk{jPWVq#heuYF+#(jT0LO z<{wG#9Q=r5@8%-7NDjg8!TVx&Zp3F!kYjTs`Jn=T%tk`SGUS=@Sn-sL8du%!Ai?c@7wdjuLy-`+$5NG}Tb#@fv zsB52@W4XO#|9!;Qdl)Xrq%VX4dyyHJ@==nd3&*X7w=PwuLm@MQLk}%pRS}_DW6n5|t zB)qDm_%LWY#v*y_OAiYmV17T`CR{~=rd6yrLkoU#l-FU_)$df|Bk~zcE%2rj${LwT z2Gg9GL#v~vNbX;_WU3&f1nHo1$wy-5(K70WowKdk8zeT0OBt7S)(%!qHcqzp6;G4_ zuq3@l4KFx+vGe3BchL##x_Un~-i*}qY3rz%nbd!!Yo-<#u@*KKITt$@-B|odV@WU> zJrzo&@)z=+xVn_=d^kd%m@0ck^m+pYhFKbM0U1)I%$gdMG(^@9y$EPkVedLFiDZA+ zhJ3DCsjMxi?OLgH8_0RQ`q~?&?_?3!#9f(P!o|bY!t*3~RIfn&F-5vHw0raX;<%;6 z=hr%l>#wmb0_Y^$-Z{au>eX1YP@}v`e8J`n3ZE|PcS3Sor{y$CETd9P#eCjMy28Uf z0XHr&FL9T2s8ZaR>}u2>Jr}*XXpUVJz4>6Cdy11_z&6QL$+ThaF>_xS&RixosLw)W zGHCA9&UAqWZe!=f8P@N=0I>0iB|}DzLDu;kmK+>~M$Fiik+3)@{^Ik=F@1~uCqNw* z4NQ_@yTeI1lh0sh5Vm%TyG;qZEv=)4bjcKUBGqG_Hd)QyKt*!%K_Q%S&Q&;I{GbUu zb%z9_LGz(ptIZz@tT}#(zkB&*Y#g?k<|6!K|08B~nU?D7!c%&@L~e`&p#1h;ck}Ze zysTj9D*6LZ?Yt5i=F+Ixcp)akA-YdN#?Wt3AMcn!zCJy1{1H_I zP@BrIAV0-8ZXFRVFk&wr<_ttV!&s6VIoXAzUQb9$5B1hh+E`3#M{+U-Bg)4xPl35k zOnr^kA(%%S{ZMGKCxHoAt5?<(^AUkE=%Go8nVJ-$yk^IwMlH{>T}^kLS4nO;rwL}s z^Pxx^{%kC=O1+6meR=$z_}PxPQ)Rw{q49nFJ`4fP;9b#*ZOX&2A%k7RCmfh@dvhCK zC-Zo0n!La3D{PF`Th|U|UsZsq>RedpJ%}tR8BnfQnxg1D0ixRYOzI>^6?r6p<=R1> zE@Rwy9CVCAc}#^udRB36f@U{4Eb?F);|>K6S)mW+IvAA%#(|7O&$dsRrre<;aL-L) z$;;f(IIG?1DjxC-bXrQ;N~S}gXJSY~+0ULJD>}V5_JO=Vt0!A0Ay3i=5?v|_DIP8! zW{78^v*uTd?f>EI9-}0Q5Kwr$(&vTfV8ZDXtF&CGkdXLdjAhy34+8xc1$^W2C$nQ`M6E=(;y zF=OysYm3|eM4@+cq8DZNGTf*(4UY!z(rwSbd~kAzH^uTkBAhb7>TW{-b=`**v#iCF&tZj`2&{AH|tVr86;M7^YSn6+PK zPi1RsbQw#AA&-67h{oE*gg~I*WRymg$6}uCb8>wz8U(swYyLP1pbQlF1HO7yu|OT1 zs-M5O!R>@Cxe}qTRXQM5Gq(#=4AcH+*gAFc#0jj+E0o_P4K+EIgzoCB>l?0^d+AQ& zX3+brkiwPf_53ym>)T$s1jz&qjSjQ|#mKH?0{l_`Qk%VMpOV@JU z(Kdd1Xs2dwtL=~b`6$JNU};k%bGsY(xyTl8{i)gtL>qArCvDt0qdSgb4zXPO?0DA9 zC|$Rr3F$DxHzO^7{=q>hk^X3w08cgXR zj#*!bM}CeP1?v4TTom|Msvb}ZCF|BdX8}^S>SzsPZJvk@mrGMor*W+`xmR)WdW%;! zN-+Q_-ra)B?#H7r9=Zg{x_dE?K>l=SpuYGSx4oNCcj`w~Tk2oWr(`uU2ErL1qcZkY zt*vh2o7RuI8Y(X9l$IAXEdpjs+??JwcRLjXXK7K57(%_B$ZupMTAl|1Z1610C~b1` zr^S(N%*m%iY&TQ9r4d5f_d2T)>h_sXg2U_j=C&KVYG)hLjTBXC+IJqhu3L9(UoFoq zANEIVo7|(^qih4r14;*_3hIb@^?&A-PW2XT%*QdB9}cB9O)T5AJRAL~M+&y`3j|3$ zW)4GA!b-EwZlJ@Dr!68;Vf2v4=MvK*`=c+u!J1Ntc-affRoVDlFuj^E7K^%g2O68vMzSu@UVvEYCY0 zV&)S-Qy7%dC%)lG!D^p$x0KpUtX4!*O)?9h5*bjdCt_ zS#TfdA^(ExIhJ)W31(7geNZR<$&)oBI>LZnEI4IqYI@8Vlze>ZGGaDD8Y%=Q|}dr)^w2m_^`#w0PX&EozEbZPr-CN)hcjMwtMc*1PBTWQp@O! zm_Z3p@r8uB=SNVFV-0Cz=O;Y#)fbY};N#%u>+BEJ?=x%Kr{4$HbF2)Y+E@@LsqD^Q z&Za$pr7=|dzYCaEHyXtOquJs{=mmN61Z6-MXFTC1mkhN5ct_ zSOHkx>fS=F7~FqMvsnh@RxlonBI>7)O(h~!jda32!#hRTMsyGw;cHk{G|EW2%DSk= zAt6X2?9buEgWc?Va1@^mZzUL9zbU;AB5{YmpVnh^L#|T4e_aj(5c5;+X-%F#Pg@s%)b1DD#zZ z37tP7L~W>uExV*KBsV_H@7jBo1Gz*hL$Ec8#s}5xPVFt8Z0z^fdf-)UJuz;B{vKGe znq`qBWCT@w3o8^eua}+5K>Mrnt@`J%I9-cDviGH_?>mh7=GScXSALEu)R^FC32NN_ zq|Cvq#3{=t7h8(QiKPngZMBh}^6(7y*pSHU*DDY`rmX~~)|anBW9xraON^|gJWGVx z*=UA$JIRujEhAp9FQb+I*r|;94fdb#8_vi%epyqTlKr?hLAcM zFr0`Ns@)$jtZC0YC!R{vomGc@uTvvcfn6SASAh=k-osWR<*|?$Qt-;a=5%G_I5$9B zKBXUM9pOs}ts{<*)~Y{Qe%#nA%Z{En{#4TrXP;$u&Ey_C&8g^IawD~o#8D>AH2(^6z8=o3eC|?mE$z`Ot%Qf)hAktO zQD1J{3|W>d;4+c1b?zsTsl8A)wP$;r3Nd8P`y1V%><*P6C;m4%)eL{oM^Dr!(95-Bk)a&IULqnWO|>X<1;>je9>WD>n{ zeS&QsQclD9tpufi!mbn^nUkdV4zm9Dl^nEIot~&>}#%Y`e&`5R5ZDc zS`Q0(#6QlHb=s?|P52I$nDE%e750jk5m5^!!t%m?3e&wlq;YD+TKZD|7(VH#C^ zq#{BCjp@|;1R!`iEB~B1XHXj~nT0XPX{IDue7U;2y1lx?xwHTLvD1GKnXv=WCf&TW zjWC?f!H8Up;Gc`(H~%RC4f^0c_7@DPC?s(g&VQDwcdECmmn8zjQ0~Fer$vey?1RU5!v-D@i8;aJ zoFxSmK)!)Nqzg&I1>kQMAo?!W`ON;wW#MKDearqH;*e8pQ$*>;l#tjAUn|>>ORuY? zk3alsDeF2w)WrADyj_2=F~^8s$igi=7ObwQoKUb&1VcA$2PXhPBnz4E^N_oS?RQ)p zy;4&X{K)tYD;5$Jos4Cs4Q>|igzj`#gVP;42I~#bF zufRB1yx6YeQw(!C*QU)&KllW}TUD&$X|GT9*W07$xx@M1GLAu4@I-O&%X!;37=C44 z2yJ+Zt-5F8t8~iG!SuASIIw7mNpPdxnUSDTF4pjX2zQ^3MPY7(w{l`L3~%imkRdIo zVihmZwQal84AJ&E(dHu7Zqq}s%g|lp?b*Zd;LviAz1g=!f*ldee-8o>72XA`TNKH? zYWI;S6GPM_nu`e>1{NI>f#bxmN<`XaVG{U)rrttN6MCVQRia zs7v^PQqB8r&jZGWZft(8M32+F9M0kefg2QRx1S@zoxoPP0{k5Yy(KrHBXP*6@Q2Nj41L^ZJAKRVofHtv|+Ss$ea-obo$uu+Vt1~!=Yh* z%s5l#?U$ftU(}N3Va~=h1bsgLK1$kOCa@i_KtISUVT=3vjr%Pmd>uOzRZr$b^GC4p zqh3nJ7OwEAUyHQm@u{oc2DxYBsJ%6jo-98X_a+uI8 zZkZ8gD{y2EOyXAK9j<`c^a~t+&(>j=bLKwX+*(VQM0!aQ;-&v%In#tYrU-$K=)R zk$bW34eXTzT(x@ztlDX8ID~s<6mdb7m`t0fVqCsbqK;1i!DAa&Ukw+) zQr_LCO=gf@>)aAq@B5}zx<9j9{3-|nT%>}pm0aSeK}gn4W_&u+b07DYZ~bvZ-E! zS6OJ&Ubk}1o}2dFeJ%0tj}T6VkkwZbk;IMoCsHEWa4HegzQf`9sB7336=#0?a94?- zebf=;eu}I#pEML9=GY5i@Kmn#7zOTnDTy7w50Zx&^~XR2>~zBq3e}3miiG)j*(6B& zK?|^ziq-bGUldk>vByM8X)DR_;u3+)i;C+pVG4McyvC#nLL@RQ{AwdQz_KNg0Zt}- ziX=wS@{izEpLlY8;8}^IPE^o9; zh)DK}E~{p6S=VqiB2zdI9U@YT7D7$cVt(vWBGLQBpuOKNe~Sf?@R0=4LUQ)_1%wN~ zaC;Z-WB{biVFB&cs&B;*a55?rl@k!-%Anx3jofZ+oBbFeQ^n+-+j5~2mQ5L!!8JX* zFL0eZ$|fVhWtL1Lb(+Gr%6OO%4XwJT_>_er;^tN*a}=iIl=7?f9VE(?tpf(r6YyZJ zhv$B0Rwet#k$}a(%hX7B&M4wsa&~Z6XoEM=hw`2-d*~xNRGamOw1rFI#I&$U|o2@le1&5SN!P5z|KVD89S%`N<6xbdn+Ei zhJ-ffJ&O+~octl5a2b0VTxhM_m)}3tna2$6L=D++&Z}sQ;CS+`AP*gY7u ziH7kok%f0>_>r>k&uKIEroiNhG2rbEKsnU0r=;V(C&N@m>Q>lWLOb|6;kNL3hOH2w zN3LqR;-|)hgOIu{?0O!lRj7?A_Q{p)YPDVKIi)(aHzzv#JIS(*hBmyU8Q2@fm63&`{0)g1y64-jyG3KOdp}`Rg5`y5t4`D!#>@(mhGp<05 z1i|iN(yr-B(**=?`2Dcet#G^>fNxlV)W37squv7;#u3ODtML_Hn%EFE=RJ?#;*>Q)>1co|VxRu&&!M3Pm~>QUlJ9a-!8+mphBfVqa`(a@IXX zGWeK>n`00Gt_t6XuHwE$&w^j`{dVE9pF@6vA-rKthKTuh^~4*{;C-+hWbBEk)t=P6 z9NuQtT17}-VuR<85qn>KZkoy@8f)Siv$FdUOL_b zyoosQG_Rb4D~=T8LIFUGVDE#lrY4-6)cwHsS!-!A1)pXF3QlEXZ0$C$V;gy-^CxCYwS8|?1vjyxc_T?^pYd21BZ^*?8h zpuZ zUM$3(cJC*5XkWGcBcU|xm}?xX|84U;;Us=)dO|;2fek}EE6lT_m?kelbD@}~Aok@9 zA$4x3rVKpGF55aADOw%myb*j6u`TjTfVo44odmKnku7pdfFt{)04EJ+Lcf|J0``Kf z@2%9c89azK7|khbN~tK^rsOW=E$G!rv)~I&hV*W?_suCG^g&3Z80IrgBcUy+f(KhD z(APk&ozK^zD8A5## zq4Y?r%m%cf0`3udSS)g449bMI$c5;|XRIHgwG%F$@Wlt~d3#Qy0(<#lm@cLsnnPIi zT!UGJ&=+*XuV(=+!8c9c?Udb6U^&mc6WhZFzZWrLJAc)|zM zF%b>2L^cl96Mb(=^69KuXX?ukzW4=UFP(2_{{D^-+TgdF#E?Ciw`6e~>-A8AsR=jL z(D?U@!K;hi&71s!V6ETE$lG)48YdFV7>q7%jvLm=?l)`SL=nP4xziHEJZ0MQ&+=C) z09}lQyH=X9sQ<|Xlo6&rV`oD#qds3W6cH>7vORAd@QlngWFuNCIJRA$mkQg2daRO% zF%doEvhoQa^@!iDQoDDTe*PUpZr1sXZBHnECCb&4SO6cGu=c zAlJjnYv6StQTf%{c~vKPD-8~`za-b2KN=a;A9MZw*(87EiICt3)D7*x)jy;DWzG8J zEq*igVyx3me9X4QJ9$9+i#!e5QoX=FsOa!)Zzc@+_=G&IsF-rbeGSxe%)c4EqX?R- zQ0VH6@>+%Ovxx9WF(!t7TNSPhXjBRI+uVY%N#vd_`$Xx6Z&xp9axBDN0{4o?-YQyZ zQa&Q0QVC3f?)Y}edI_cM>DNn==ZluSzVW5fV!1M4H#Ca)ca5a;qg#kSqOy<;`FnBg zmaPSheBmgkj)c!O!qzMY!!S>Ha7C^t{FdboQH&?GU(p#kh+__v7`I0N1#z{wE0;Lb z?k``_ojQ~qC%wzg#|+k{l)(i@!EUsQZ#+%r<3t96?s3Os;vJoMEd>W8ud6@l%gx_ z#K_FFHN9-xvD$j9!*Z!Zq#2Sf)d7YTX|A3`qg+g*K3`j{HlbqDNNuWCDQ&LST;Qm- z7slC8WNRcc)|({ksJvHpAT`bED7aFR*Se^53KeO-phS_jkSLL(6t13JrKr+aCPhWD zn#9MycT3#xCm$Feg~jODV)6pjurkYuPC zC`@U{+^Lm$M`#k5gs!b_o(r3U4g6G+5sjybXWsg5pJdr1>ZD{7C*I&TBx!fLCEn@@<9t~n`m}c zauJb!nZs*hav|YfO60iQq0%Ah^Bav+7v-ln%G;OL`ImFe*Ve%2*T}%9UzFub@+wQL z9a1+DfC>;-q?)7Jrnhv5{84wtxBl5eB-ue2S?{V&X2>ZS4IVyKx4(cd?VIFvW~ zr%eaXHSX8it0=Cm;SI9GLoNEG}D`t~tI!+_{f#Fv=L;|SbLilM156^TC)Wk}72u=W5duc zu;z(wmN2UN3!@u^CMG7(A8+*6TgF#%v_Agtk?ygG>L2m!O5k^dvZ*~yK4(9hVAeIZ zS?9q&scme7u!qj|vwZ4FVD++ev9B7RsS@e$5bB{Z^|1MjCBJPRp1S;@yt~64?79xo z@_JgBTy&eCLaC)CIGDcrS0J@-aK7gY8!rS7$jVQ{Mfec=TY!<9fKa(40$SS!Tou0g zFHQH$TJ_HytrN!#05N~r;B_wG%nLod0M@eZbtfkr6r1>vHGUZzA*4ZpWX$Yf z&s;qKW7*$*aNx!_)|Q(iPQef>CPXdTmL(=2?V~hKi*;#?9gKEif_(;7`1%IJ0CTL! zQxwSmV1SUv)Hq~Hep;1~QWJx2bQ$=gS*6OuT*g!pt_+fHr34o92X+;ZMJDxq`j0ip z{6;k4-wYA+#-{VeG2HzYeu%FuMc^svvKV#0EPD^D>XElO%4Q>|+PX9FW#`+`&^Ue(T zO7*$%vg4#98(u?%RxE;lb+P7tLA?Nsi0Ruu(!F~f5h+M+^z#sXl?CobfVBc#2B}8f z&b{o$_|%?V0|Hq6G;Nv@;*jv##G)3({~RaWl@`NiR*^Fzb`5Ngkk1W)0Wb#eNWIT@ z@EHPd19*&2Jcjb2iG!!5f8XbY?-Y-cg(IPf_1D#Z6_aTSWyV{jlC7>vFWwHcN&sCz ze2$Jm8P?wSui&|We!+cQ$&wA)@<1K!+c&GN<(RN8PZ-&2M)rnEZJh=KkB#J<(GrJP zS@jfrc#8dFSbj*hK;PhTfmTFYN85FcCOi?qWncOlp>BrvG6eXG z*oFttnW0(ZJ|%Hm*;fN-wE&8A)hF*e9Kx7$Oo9H!9NFsqs)}zuA{6foz~9JGU<42X zlKl>UX}-0!?>crNDA{>{zj2Jn#488%H}Vz!Rf8^T%A5Nmut?z_#V^D(>F=q(g&Zhi zAn)H`7s8W81pFJP|EdWDMy~HknxIJDwOwp(_!Xe*%))-8XxIOj} zTU<71!l8IAol*vWpXGIME39T|n}kLj(>LG0;kfFh)voNDUoV#v0w{z?n#cY(c;SG< zN~FJoR94V2j5_BS@NdkLwff{ikbZ|m@$oFMGZL%#jW>0|*N}jKRbK;sMMD9?(XkEI zt9)=%9s+wi@Ws;3#4#GyC+J3HU%G55^ioa?bS@`WrJxs_^P9v(BDL&~xtwKn5QOFu5+;4WOq}e*-nG9l^jk%WJhG| zC{>&%4+u5XkOq%_#`B|+F@Xu0ajpZT%i*m}fZ(I!Srl;JRL@7pZw=-W&8Eqp0$AlI zHI61RYZrDh#EW^uyjk7YI z&*o*t34r$Lr22MM!Zlxl&>#GF{D^gJpSRWz61aoW{7LY_<2#=Cc`2TH82q5;4KGaQG4myPNc@#Ai#*AB?7hsh?rrT=1v>M@+s1OD z|<-shm6ZH495!^5}EMthU91T_8iR@(#LQ z2CXnC_(?A>ym_sr zRV~%93avQCek%-l+a5R7QZZ3!ZSkhy0+J2<^DJ`0lTC}NLKJU)w^%OXU*cM%i0=rW zKA+K#9myqYaT+2d*0-B1S0m%5F1o}X1C7WYNP%aRVFsVRALtJQH3xu?;k2p~O5Mu{ zh&~r7l7f(4GLrqeQSy~PHhkk{0aPlhf7wRb1vcXcYqrB%QXmWIBMvI}S0FkC`yv5( z{%M}U6-Q=W&45uF2_M}tFcK2r=K7eT`JxF0>Zy}Lm)xO2t&Vsx-@x8cHS`YPrdN3KZiLZIW*d zWW>UpJK|VpujAKfsB=mv25hY4a|eCJ4xg6YMDW{Qa&r!fiM*wJ7Zv?w&_$`0gAQ{( zxFVxjkZ}%Jr-^CVu7W1Lf~6htf^|#!cs_A)F z( zv&TKH8ZnOe2E3W_Bqu9})l@cv%Q$UhALIW~68q~*{q^_gSlL+U{)fxQ{Lgw$PMUuU zWB97C7`RG{x|8PD!mj4UR_YXbmf5-V){`)=r z6X#=OWcv@6*8kMAwBpC2@@Zj(o;(7Rxx$g3;Y1}s$ub=ZC=YYRra)kAW<{}hq1E=U zhMFo(gwueJQB_uoCE2#Hoq}yuZ*lZaqrBvf^v?aeq@Jc-9dDEM#_Q!irm4&buP#?7 z)v)cqX};a6;2X{b$E2?a`z9jJ`MIKO=}(CyZEiges9u!U4u&bgnsz_$`M-p z1j@sm28b6p8cCs*6XCs);-g%JfVXp`Za=3`+2|GVzr$KQ4S*8i*g`}{AT z_pi49*8l7I-|hb;>%QCi2YL6e*Y$Uu|HRn+Jt+JijNRXT?Ehfw{wkUOBt8GR+tD%5 z{$1=p?0WxZ?C4mS>Hjyz?!w)iS8=J~di5=X;RrH1l>ulRXqv4Lz#o!^4>n(74$E_uXijGBX_lu6D?`T-k%PBV3Vi4>$-sZK`T$_%CJ*fujh6B*I z*4)ZpuQ^?F#`lEpM$}xX`EBVv_+bqs>Iu-BT)t?bx$@SgBLt}02)Nv*o`#Xe9qzsa zn6n;ju-|~Y_ZrI~Sb;O-ra!itb#@32Q>^ zU8%2SX0Ez+K8~px@!$qPa$$OP`NDM*0kF?f^B7fm7)2AMeKzu8yd$(iTT;(5%2+9+#`bEt5Ba`&;F@-vh%R^I8Z0+Ap0$^;#E%=EsscrugvFPa)y3KIiR!RY%x?T$SgnU9kkphNr=zg>L^&nCFQqNqEjIN9D?w8Umzq2WeUf%`3u@eJQ4-j2jqr@7MV7%gl^X+TF8hSCEpW?li~NN5 z#G<|1HDQeuCmd!o`E%IU(XQwyh>~!yS9IJVDqQd`Vo~4%R9$;P)9Y+0~>T#VAD3& zJbSjLgcWXd4A4I3i=UerAXUM|{g!FWWwG}@=DLR!+|r2U9`=6Lk@k+I2bj(X&-m5B z7Gq&LHzI~GHkK<3Ba0%|tM)NSE>P|fe^tQePva0lD36$5e@xG$HJ6C%_osH$-Z6u= z`Y^7E-+ychQ~|;B?TS*TN+HJ$7($)kJIA{Zd+vMPQru#o3tKVCOF;S!l?n8Nc=wX2o4kHRz%)Md7>g%Rk2L`9rsGN z7R75<6#aEkvo=jrq%*k9g~v7IJ>{H8VBhRk!Y%=mq>G3qerbebKl*!!3yEEj-Mkdn zya-TzRO7VNb4%o=1WpdjEXs^b)Xd&J(<>g=#E2$f^2otnaSX+wc(b+@i*rWwPNwOF z>pT0WTm7@lv)(7lyY-7RFsvb-xG3UmfcTEIo~jF_h^XF&2vXQ&$;I^Ro7%D@!P{NLaUwLK#pP5$$ zbuTzG?xy4$6NFO09x-~Cw$14T^P^9;TO?0C@d4cq&4J@SQ2QXwb5rrq_mzw;F&x8@ z)8Kx3zUPE5Hd!1&bSFyni-`28noxBodY>%45Mxc#g0GghzrHNvQ@yb-3qhXUxRXgt z*CJ6*t&cAKIG+)gCNg^!YLc${5L|(FcF5VWCh@(XJVlAc7=gluDJP}MniC0;mquPY z!{qW3ALsB{1uyfL?8x>x2r(vmKq0}q0zd+Q-^+7b-sACr*_O-)mjm~<(MOakv$7G@ z*>6>91MO#YY)0JPPNBFkVL-F6pbg3(CSA@u3=CElMaAtc>?*?jjOQ*_*{-#mUquBD4KPQObF z&fY*dDie4ABTu(0XB$knMgni*iAc!{nhW&O6L739j^SRWUQe9^xkHvWn&s2a^&YtA zLR6!)o~>U~pdbTi)f9|Kdu|w#ewNkA?IS$Drpk!I=kw51kfgJfV|bWooW-Rd_bbLD z?(2C^3lP2SM+@V~#Vg-A#FUa1hX_L}5c&1o(&R4{{6xk) zMq$;MyUTgnS1!Q$KsIaO;q3!B>`{~UeZRN%JZPevt zVx{>fSO~Dj^-kx~dG@Qxyunx~l%A*|t_}7Q#jrPzYu>5PgFM&lHLN zB#MskGS5w2xs0l!T*^)!bT@RPq?j#hFKOl*>bfFJrk*q>b_LU<OFIN<) zu6ZVmKYWzpgWga!fGxx)U7DI7OQWrN3iAvSG}A23okm-f5YTaCNJ7j&Zm#G4h|g5*6H1dq=@g=ZbqAR>GZQ^i0Iro3#FG zvRQXv5nWRdA~h&WDz{)u#43BMDsByhx_pylPh;UCybOdEi0Thb>4{8# zg9cYiF;&>@9lu^E9a-RKcto$14uVb8S6)*jZC}ONQm-b#463QxiBR)Mi`XUM1{u?g zd67nmHLSHv&zr66W(q5v^>Dbp#y;Dr!hT-#(vXycKlips#!McU{jOQAqlb*~BYV*H z(h)cNMB`xDC~9U6MUfN2wkjbYORJaQ0d|pATtHNa>(g+Xut~dX{ck2jztqhf!xWtU!RH z&i}d&bqC+-&|k&srxX0Gc!vGN_e95XWNXqIzMkPu%E$?;w2hrd!)1091;?Kvn~)=n zbPns6VrW;J1F8l{0%?YTsC8Zel~G33ih5kZr7=canwkOp{r@n#n2M!hT;Iv?$YA+K zc1B7@1_u$H$WA7|T`f%yBEp43wTvXA3j%z+H9q!SL7eZK)rbW4%EvW5JRLu2XkA1G zXqVZXb5$niOHKGexo}j}`$=l7OzW`5B1i3EWhJHb)8^9i@TsQ>&zGa2xrn3LOu@XG z`B)mZm(~7#5l?N$6@+JZ_5jO{D!oQWl(=1w!=2KM{kVOeGdRCu3RQ+UHA=GpFs{4YJhTJhTSRzqhCdBHd;9w*~-{cjavbT~1IcP4f8fQ}EaFU$w9W-i0;P^l!Oa<0|i z4G38(ny``L0C>tPhIPTArF1)$&4}e#nzfdF#BX#Q56j`_cjuU46pvDmQ|B3;A?=lJ zFM>9)+)L0Z(@f{=m+*)xN#U*IPQ_yggg)~m3N?y0N>lI^HylqV!U zLLYd!48O*_qrUgIF0q?_F}3Tu@_lxbTQ^uGn(3?N0V$X;m_(|Zaa4lN8`r?2i%`zM zA!8gE>Nk+n3y#sd1&~oI!RCL!?I^FDimwx3#g`Nm8B4W@fQ!{j>q9~ls>v6SmkPia z;K{!v^>79LGEl6GrPTflEx1k%4Dlcj_)XpMxALTp{Uyd72j9m&}TB*8Q z$NNmbHMq-f40;5`C9^<$q7VcfC)(G2x2xxp3mpI#oM(iKdl~)dWHM zzV)$Fh*uH&51q|2&_DR5zxgE}!9Gc6JOq1v7*i7H1NE2&xopJ~1rNmpxAOO9(HceW ze=`kP^-3jL(c+|Tw~h&sY`eRmu^I;NZeyk+B=o1-4hwcmsZ^L$v_EiN6%d_smvU{m zrX^}+n%HJj?*ezhNV4iRwhi|aOFN&k5~&Yyw*`R^tB0$SLd{oSK>w6R${egLbN36w zA}Lum_Y2b^E+OUN!$N38%5gB>8Cb34*Qe1nDQj#*c}Ta)Etzx3wqm2c##xcvIiv=MPs^t0+D zdD_3?I!ZlVFuu1aMQ3|6?3uB*-ltE6S0R7_A1sc5!BT;MVxVxxvC*lfuRahn2nAoK z`jh+CU(}uOC z*+JPlIYO+|aGcaUqu`iQI)0p+ZJp>q+tYH$M6dM0dGX;6k$aPc<7M$%2$1SKhmQMc zy{3C-<5@zZj9so5>QGc3_R%t1f@;LsX@wCU^pu`-qr$v&X2_5%9-Qy@?N&864rS6m zy5r`-9A`e$vo3uF1}r7_fxU=LBLXLCML3BsbFCBfoecgR|C?Uf=WYiNrOgg#s&HE2kxkqA6CL>F8QUHk| z!dm!M2mVCSCXOD^G0GW3Wmwb+$F`EfhvCbOkLA51@8)I1+hs_=yKGv-_l($rTSpCo z)6tRCr-=>=N_xSjDs3!72;!%)a*uyAQH>(p)Y<*{kw<0#Q86D5$g*kIgiSsu(J7B} zKgY@76`kR9hUO%*RA0EWM%#P62kqaT*E#FhKN9sGCMPTFOk_q-Wc1Y5%$7SCd@7@X z89Id^0v-Y7s3`?uAs~7J#eQZ5pZksK&i0OOE2R)Vt;yqd1p$j9<2?k2a8F_!q^J2O z%WNKVhZ4)}-_B~Iqq>^timXDLv~%c7%(dz!1lODK2Rz+i9Fj*)|P66@fZsF_6Xd1+G!(kL?=2SVwpCbTa;Y90c&kfZ;(;IOg*cUc znNW+PblidBH=9b5(LR@{b(?4V0!$lt!Kqcg;cp_Nb8Ps8v*zeAjSwcy0BDOh*gHO# zdHiD>;(QV?iD^+E_3V_861j|Ct`8i*x5T*Lm}_xCH|2Y9(1>aLu$`!N?N&iCj_Wwy zy{t&J)O^04_NL-(&v39>_Q&Zlo`!Up`91-LPQCpO6_4j3jmX$VoykNg9wGC!o7my_ z$-o9M^efBK1_$;=OvB-aNfns}tEI5e!IV{(w{^mVQc4P4zUjW%3}Skwi;|P8oB;(o z5!QzZ)2j?R+A;`t(x3cHEpTKp0o2h6U~a+F#cMz|fsx@+S%xzD0NQXyGMe|(5U9>3 zd>yG*T6uU+{sqKUaGB8)M127emQnZF^s8cf48SH}?E3St6}aVC)p)Zfy-aH*$gR-x^KWVy%%Sf3sxrI){RKuTGY=}1idH}Gj{yPP(s2u+)WLTW4jO_ zFoHO?49u0N54&|r?tuW3M>fAGJ&@uf@4l!y=$@KvZGUTDx(^XY7EaGoizTv``G;HY ze2!N7sjLgmz$!sXYQ2it%}~PjobE)|utJa@%BnXjy_J8ckY8f5+9J6r?RM4@lZJ$L z1`_%Ywuy`k4f1a65Fd0`m2py;Ok~un7c<$JPSfsJ?60n*%61OBTF+i$J5@x)SytP{ zcFPwXsp8*8tlBfJ`YBG4^mssZgGlC4b-ATg@kVX4$cUA7FV-NVXs9~=pVqLH1q$Wnh-KdmUuo>Ptc};jOJ85kC>{Qt~_1h&gw}xYi^DX>k zmMjLxJoP8Ub?0Tb26w|!%}+60MyZS{ynlJ}lvx!+{o&U_yLQCXgf3LJ)mQUK)qB=5 zIjxUsTVFgSL8|@X8c4arZ@s%-I9M}X#xKG*lsp=L>9qdEGWBs3Yf!@W@KE1czN_S% z*a9wt)^vBS?_8eyz9Qz0G#$)yqi=OfYG%6_Niu)tLNkjczew^{tC=^>*w}PnlF9Lc zQiOe*Kn~1}&FI3R9cU8j^WEy+wlTGeYk7P{I(h7lZ6qek7! zQtsk)+aJ|3Ij*mqDU-hjH^f`C?I;V>X6xNDA~cw^|LN(@LvuuaDb7n*-t1>;R?PZV ztisw5#xaB=@kI!>k#>GcO|!l@Dt{y0uDD@BNE}5fj_yis-@&8$BS5~$#Xqav#^&66 z;zgDDcvd#>3Uwkhq%!MA8 z%;ui7nSGYc#{Dk(o;_u6r~V+h?azz_>Cl9lx#K?{CAnxj?hbu2%wbZx<>KhR_Vj5D zfzHm--XvY^K1c4`Sx=YxlVTTUxo@|0JIudK@?KXtsu5wcgy8;iPrHlcXgU|m)cj3s z4{vhg*FEUB4sOb%`P1hHl3YyZT3@^9z_%7u=iUtI5+DWG)VaYq>=nlXLfevEjuv)b zLW}W)4`r!aTWBD19)_)F4Zp`S|Mked6Amix&H3vG@E4f z+hT>cFGg=+^MYM3$#oXDS2_!s@^5r?Nk7z}D!NhC8fp5nBeY=0yw(rqCnm0!wpWkG z%5~4`EpnP7eX?zWnF9HmZM5(b^Vbq3%65BeCN6RME)C6ntLRTbWNAkBpO0`Xb7N^z zynVvn!7}%KuS97rORi}^xsk@T(oak##@wH>ieoE^V@^2cvKE>If6@x#;P{-qzSs=g zWzp(>$`lW?{o(jWoM_>39$&S)Cv>fyMUfB1O(_zW}b9&+Z>5i5UV`kTVT1QU6 zrRHCJiIZ~*dwKM8$!F4R=nvu_bDYO{N(LNNdG1EvbI5obFO&Q_!j#LtEWzd+v@`F#(=={(slW9Y6ygwD`k*|U zr(V|;b@x+r6d^a%baG%)%vZ=y%k?Qkc{-EpA8=c-gbsh7vt*!eGg;F9=wB0yv zJB}j8+idD!?CTR3AH~5_Xk2tb%)!Y@(P9Hns>WLnN(nC4VM13Yj7|K{hO#~E_ewE& zhA#qrlR`w>2TN^IBRZti?aV6I*YgPv%z<}XywN)I#k6_gOmvfsxmHa@SSZHSSof${ zOGjr_OwZkH4qHe2p|;ZW`^oS1_M^u%$WwaG%9D7Gm=8Wu-Csnsnm@$G>ZYf8Yt^Ui zepYj{FC-)Kb~E4P7IX^vgJ-8tPFS_$1H-$_-8a-ePlXkX80C)m;1^2}d520m@ZVot z=W##V+E{XuR8cT%;C;#LkLXuU?-E{bbzv@?V7}D%koT4UGd9=x0&LziPHj;v_4`Sc z+5C`E^F7Vg$hg7~n+XpR#woaC=_6lx)iCC=F?)Xf$Jn}x>T6RW(*DKglz!SbUmf_P zF6UU3-2>}8Vj2do{7RViw|VcK-rsDmWi99G^K&Y%Jfdr?Vc>~lm)ve|75A!Jd?#bf zQc6PZnV_bAenUt|BJ>?h^9Ry~C=ULSCLArT9^~7*-`?DY4ylaBrFfcE^etUp@Cqa0 zCYG*mckIm{lQxeWmR;E5FJ=Dh-N)}$&&(g6{IoG?rm#Wx`{`j~82<^KC zL-Y~dY{QFbX+7~ zhrH%2%5Iq&9CAasyo!ApuxJz+%~;t~XK8CcV6!!DOq(M3nNOZp(Pp@HAfl(bU5dq)1b?pc zBwy_9i|CIZo_%vCE>s}>P4`sig_xiGmtZzl?>$dU)tbI+dCf-}Q|4VXQVo9YT<5Tp zRhGX{>U+$%{MikUd;)y}w*($%JbdAgr_Rb7Jhc_jRyrTO$FDZ`8?;>qiowU2AjWmP zif`MK)U%Ynvy`s0lmT!vd1^`?f4L^KL|4L7^183K?!K1k!E0Fy2Kq#u&hUxu_8q+9 z-MY7=I6rc3;@@8tQoxYRW_j=tW>eaxllz7RGzBdVtGBS*Ps8HX`Co5hKqY%I-Z~c2 z;t_v`FKO$XJKue)Bn(UaIae5wBk#Nn!$BE_ZF>&5b8l714)VO1cwpb)C9lnImbldX z7%LrBrxicLeYjFa1EMxxj$_i>1zuxz(C{)hlitSDJpaC<0<4#>Xx{^)RBBtz@af+FRs zS*yAJJ8!vTyb%p%t*V(kvia#-bW@CEs~hp--aWouvyD-jt!}v@nL)lm#$i4Q${&9! zIi6?MZ|`mJhhc_h7mrhdwpd&FZSXKntmx|uP<&09n{1}E8CnoG}|>_ z_~3>9A93S`aR{XdCK*;|?p;+(4jOYlqAs5dpVXbqV3Hx?y$^P})#%?!3H|fUCZ*6> zlM&gG*y~c7&G=VOwQf(v-g0^NRzv*jf#Nquw7qw$#_ey`pAWjM-Mn-Dr^dvG9rL@d z`RUg^&@7aM%?V!fQ$IbVR7k$SCEg=wcvo$^-pvE*LRbFylTi;nKXd^-$Lmt8Zqra# z6!C%-dtq+6qxZ#7l-e$vi?Upg4LY7(5`4IDWF(x+i2WA#pIeR^3}sCT4^MGFVcUvR z7-13g@=qpT4s15xz3Z&t0aAY8GiAX%*nPjtH7WL=UAtd*~r`Di8*|V+c`(lm7~Y@C5z}Y3H>e};;Za>%=N9uPdN4mPknruH1>37VFi1(Uruj* zR^H}^j?t{y7b}Ij7>o97kJHiLQ)QKWx5|g#U02n+M{eBu&vYOD!)m4@tXzrwhq5y> z>%_ZwwPlWB|MZB2nej z!fmn%E{2)sCKyh7JH-Bci(D6Mo*}R8xy`qtv2iAYS@dEitJuZw6JbQC;m#jAqtdT)qSH|(Ai-T0zkU8~`BPCFHqrDgqNA*$Lad@TETZX~Ma^D`4i1W% z4Tui*iJJ9_4!)GWT3dY9DLAIp@x|Drm)|HmM-dB$J`0B=g@f$I(aFd`w&j>*<;ZvE z*trGczTT$IKX+!-wfizSX!sPrh+rBXv!t#b<1PZ)J7y+l> zP%Mu6ci;E@&$kq>dfzu{_4~e&IMi?UHLloFe52K=7PjTdw9Ll(DIEs8NGH8rnIDcH z3|?%%D|cl5v7lmhrG|av!|)!V$#p;WoJ%C~cw{Epr^@=eMV_hYG~*euNZ2hL-~lHo zDyc-r_+Oiev2xhVI%soSHl*Zz#@z!GvcophCn}_~GcQU%GP}J#qxp#EJ&m1jYzpUC zRp1G(dIrbk`Nw7M&86`MBs-XAhj;rAFgGT?vMM=(3Q@LKKE`6xchos|&-tiZCyT4h z#MY}UHePA&`0}a9U0(D;)a-)J#+Gnx?_tH$eBUpdyz)&LENa;38WgABvFpb4&T9?Z z)Wg2CUJ1LwA9>Ou(im4bP}Z7=(J9Aso;a^j-}APsw`RKf^T1oHl$ft9~ip8w$s zt^Ye+`Rzts=pFAg8+D1+He2gZiGdm@o-x088H|l>l^G{O7JE3vCXCObc$y_DmMu_(&rw3L4x6+fS?u3 zji*h6`-|SOzQ*3Z4*o!K`BMwqb05~JX);E0pns$go-_OD>^%Nx!}V`szHMAyGxGdi zZFS81t^B7a4fmDR9j@_^{yMwpe|V_%tM9Sa@{F632-1a}FhzU>fq0FzHF1$myveuSim<;z9e;jf#H(S(U-LC6%LA#_9 zV*B37&z~$lnTC9vTKHW|d|jSUaePNlnG5&aev13+ws6Gt(JDP*d7du;Mk+y=2VWm@ z6xaTlJaYHaY399g%p@67y_ih^+E;pQO~g%Dj1Wbmf9BA0b7W!BkcDWD=qDaKk{r_|Z@6!9nx7({fuy z-fljAl91;-@SL4QPTi0UBX4Q5^0<+&6XaU%tCMPCc>iLpb8*u%rjmz>at6=+i1pl= zh8_Xi*zj4}R!WP3`wic@Lr33xh@ak@qU$qrMC;KgrZ2h>E#5gfaydEL z&d}|dT`7Ls{+;h^rM+(UFpU=Dqp{5%nOR{iF)n-HcI=fs`+f9zjU0}o7NwM_q$;M$ zMemd~da{|#o){X#+!$vm+@&|6%6?#B@koNJ@QjkL1@GC*(lxEod!{zKAQin7FW2Tc ziVbF6`&KTa?|8s}Y_hUi%kjgBzOI9NMz3o)@9e))eN4N2hecvmwii>FSZCXo0flx{ z(aeD=!MbR}2Nb5ItlaB2k4_s;`Z-@bDm^{t)9*SnI&GVg(He20QFxlM0mU1&E?<7as%vW{S?*{MAMt(7$(f>ov z_pbZf#DbKEJ;R(!_@%x_L5bCto*zo3$>%R|t{e59YvHY)Gzph(xstO^v)szr;AtOA znaBLTcLmm@?NSl5K_7dcc2qSOs}E*5i06OUaq7bE?S_1(_7{Zw46k8%!w_Klt)*AA zfM>DNfh$--rUavzw0$ekM zC)f8o$`+fY)H7<3#WxaqkG^u|>^TGvU_uJP=M+z`Z!8G0-kbBvc^hG0LGDse&5q(o zPsW%VvxvMcy4>x9Y7aPX9trLeEnpOn5CXi&1#r~$F?z`Vaffw6W$88MV@YxKJpJW*4j97(n-pXoJGW#++MyD-ZEbECvL1}7?bj34M1~j&iW$N`ah*F9 z-^#_6IV&LOutOuB(zGi}q$2WpidEX_8@hKS3wEzZ+dfctsSs>j@YJB(GTalxUtPp= zpwNdT-3YhYH_$M0s#gZ>Z>;SV{-$8Jh?(X6Z@fp)EP@3y<*b?^Bl}o4-mF;?fH%B~ zeDmDa@(%MhgROqMZ8R;0*C9LM7ZMJL-g#Kl|CsCA_qi0|uwEe}k4d@X)AcS0iK&KO z--DZZubH+bhJSyDCu~-%vcww+4ioQl7m@|09&40ZF+SY9XjX+dt;_q9L8O}5?zg_` z?;}%aIF2UH`FBrDDJ{o2+Rj8LeQ(FpGM7bA%y%yLH?c?IZa&$p}_`Y)YQVv@S9Dl zLS}6YKj5>qsOeGoqDAv<`Uu;U;XqRR|$z+M5{dwiWo0U&56mXBF^fR`=)4$m@n8pnG90P z9p|&ZtyjnV&D7v(rp}kM8xD<<$A7B>|HC6izw7hg#wp0Z!xRi0oF^in!C4;6Z$psP zXK|=KNEd?8oW)T=zz|4?ZxDU}wL(B47q~^i5U9VPXn^n+6a(qqG6EJL`~}4UGAfh> zL?}cjYbe}jL7<_-J%1hef#P$3PYs+|Bu{CdwkKLqz!^eyM-ZVyQ989ubw@k~20jo2 z;2s=8qP9lzxGQMGax=g^8Uq6#2Lv$yWMAim{}Ql8WSUq89~JZD~tXT)wC;UldGNG!4-H)iCP8 zF&%&}sblF14K)OOStxo$H?q5{710g0EC@YGEuyuZr2^T@7-E>(g#?VLq`Z?8nc`;5 zf`CJF2tBAzRb9#M&Y%tYpn;Z7Zq87_R^F0|`d~bJfQS9-sVYdS!zixqL^(N0MIc#F zuN#a?P9uMsDD!{K z*tHKbvGh?UcJ0RJ54$NBH0+8)rIqpEhWvzL_)5n?k zwYTFS`?OL{V5wxS2#n0{Z{&+zOOR(Xg|2Glo%3AB<{jVASCavNVvUfQ;1gg(?pig31DnI*HSRQRhwI zLbc_v<)uB?a()!HoXCPv!%jUIHPX|AQG+Wz7HT{Lel62cy|x~V>L|fwxpt~M(1TGe zFt{w&PPH?7FzV0-mt|h43akgC>I}FnmkHXXNOlLgCKR+H_-pRDoIs+L7d5r?_XCYI z?VKDW709mEL|1AC3T_G{X+<$cBH$7T7!rk&z`-yCf&?0d#3CiYW4PphO&H~^D0XBg zkd89YQ-{7Hj+S<3C}b&DJ1Ylob6X#C9}>~Y_K3G7iAnJ`}NN|1i0sKM}P!^nf*c<=>TRje}j;y@Zv(UoXP z`I{6CktqQZfR2NT0jM}o3=RcQLGIAn-HQ0D8Z@X1!uwSm^c#!)>-(#EK#zo~f^ebo z00G1b3X}=KQOI8`0GTU+WTuFc6cUaAe@Fs?fI%X$VhEHl94-vW_*dV1xe{$yz-|XL ziUkz)*B=av!GPJD4U7syA#ivcFo)0|%xM`0-9t(b{n5Yx`zv861Rf5hU+M86Jzfbz z;GuaCEey~iAYVZX1GVCz5wQ}6#KFNxpoIZi6f{q#g#jtypnSqg7>WQ5Em|0$MMJ)v z76znCfCkn|7#hfRB@EDFq2W)D2hBTI!mwy4ZA%LSv^Z#B)51V6qoL=}t%QO8peqm1 z5|BW{>G2>duo6c2jjRYj#aH7&_G<+#0*-}}^|UY)0#r*cD}V=?Ia)lRh8TL;16mXm zgVWJUTf8S`3;F28KQca>OfX@wioE9|?xSDp}!itHwSsiu85})Qg9f zmsZpP8BcniQD{8m<7x2#ErDK#-~bPb-)ZsSC_Dm+KxknoBmx1sNm>|$w@S`HqV#;WE>KU-NI z9(q*i3K$9r1_-^L;_#?d`iCQc7;6Mn4vS$%fP0b^ycB`wsvE#%^UDKmbS-T{|EcmW~$y zL(|)AU^d`j*?R@g0EVHrr@&YNLrI4RVDvHtc<SfZ^!n2RZ`|u_11cxdtL)x$V$pc0x&QzfD!ZucwPqxBs?t506<2D z2|xz^@p)bZ-T}ynh)9SC$Vf;?C@9FN=y(|DXlUp}IJj7NWW*HYWW=PTlr(JglvFI# zq@)aQ7+E+txw*M1==p{CxCGf=b94Qk1O^2K1sx5Y5Cemd>lNuMuK&lM=XL-a8O8!u z1P+D@fW?M^!-je81}Fdk1_4UNZ$ke5fq{jCM?geEMnOe`cBpv)z{0@6!NS8KAi%>z zd;3D41Mt`gIIlRx5OI}1AW=EuaRo$YAXAH1bl|IupV7QFb_zs6C3s0lL`+LZ&%nsU z&BObKk6+;39}<#M(lWBDYU&!ATG~1w6H_yD3rj0!7gslT4^OY4kDr1=K7R>~iTxHA zpYZ)hVrEu$PHtX)L1AT8bxmzueM4hsS9ecuU;n`1#N^cU%zmuV``>iI0C0aJ>pv*_H@dK)biu;I!@(o{rV9qv9opcq;SpYOBI1ZCBYkkh zrQ!-e#uJausOUhUeywtbZ|pRVN#f7Ji0EsO6^6oK9=!uva`k>?3r1fi1YR&-!tq>7@fZOwMgapTg0o`fUZ zu1$HpD<2;pbwqk7u;D6gTgG#&Hbz#`)yM7d3z;RfLV_v_hyT_0`lC1KP8jL}rU8=g zK3LX7k07`N|m({6vwLBRl38&odyBrYChQzkxy1h zhfQCH@?8!s@(3zF=dv@3k5zO2(M}m%@7lhlVWs4ixlL3uurZpe1NiSMv(dn}KPDbQNR8!_!EzJPo7x_1Yg zk?9LzuN;WRD5ak4c3*vG#+4v(V`XA+ajY^zn_Y1KhdM|8`7u*=?b%3JT~?kP&TO-%9d(<{gKp4 z5Yk_fLO_)HQI>$#98o9(4+bZ)K8Ua{pXaBh(7MMoWvgj0H@kDZNrGq8k#ammyGO4O zAas~fMqJiArjyX#0vpPZ&%%%y3jF`mg4#y_JXQAqQ3nP7bR-oVB%LhJlKn)F*yDuj zpM<^o2BL(1WY(O`+V;)?Ir|Ioxrz)kGY`~`OJ7WwDJV|8okhto*AFGvtW$ArOK**t zS()F5x0=T9m^VdXom5L>i{0Qv3GIW|i5r{lY7}2sxx-(8YNE7z!y#jFUpV*3Ru2@p zVJbZH=PmcjyxkEhD>{Exii+bhQ(&P~}ElO*Gz z$19?FHo)i2*~>3J>iN3M`?GHZ%u>)p1VSqeSwockU&uMnZ6@AtSbLmM#-K#ggi0{% zZNB;z_Cl&Y|JcT;yefENg0SRxU8$l6=U5#s9dJpB z)7B8lQtY{yeEyU7(a1lr{H zmj`cfS{yhY_Rv{u&Ovx8eso*9C7?O_7KOi6`ei&#*Qje9=Rgzu9yq5a%T#*(6IP5# zk*bb+C-#qqR*Pag^9aaY4IwWhpC`T?&5wsPu2e-rd#i;<=e|50y(ebE3F!%S5`JIi zcd=cZmd;c{WAm3cRShpnca|pZ7QeZZ%=aSkQBRbhc^WIeI4H9feiBDs51z+$384NG z?UdDE4vOd^ziOE+p;*6Dy_TK9&0lQd5@f3ESr?*P@t_Oz_Lg3Y;g7XOR7dr=?B^3Y z)Kgvv`=yCL7(=IUTw#$tLR5&|ux=bovX(nZwYzhn7BbrN4Cr{*UG})}jNKZ`U*CM) z{lTjTGLNkqx>MV9Kfm8yB`ZoVBPi>AQZ)FR78DQtU$y;=gli_Mg6+7D?QjKxFrqlh zS_uZMKabf`$7=|4o5LPw+(Ktx!nOM3cM0>8Zo;NRR;EvGCw+LFgMQI0eA~CiWiQ2R zE>tucFZ0>(7l54`!?WMb+txd;Jm=XYsGnhF!Mi8`S+|5d&~DN23W=BczEy2oe^FV# ztK2ljgLwGxkc(Qfl&=E2JDGkgN>Jvbn!aEB)w_63Hvv9BW?fSBz-!v@R+hGj#H9sE zqY>2Mc?{_zwehn1b_hK-;Ies-`79l^>p|r#CL;al zE0Y{-v9LlRS5^fQ4ep4GRu;Z&_C%$LfTP_p=@En|{Kvd2bH3(H2#j%OupT?D;u2-~ znCeX>U#W=9%n?u9XV&!=x)a@gmZ%}H%Y!&sQF(WOk~!Nug8n`6b9IP7S!hCMIB%>o z@!s0;6!jPB??paY^dej)YyL1qWRi|45Bz)9_UkQj+BWvh$>Q~(8xUEaLb2yg(ZUqO zjNKHo|MK%A6K_wGdb4e-!G;QZn&pr=O7FS9V;E?==Pd-=^rH3|u+%?YkbH_Ze|rNL z{=J`q{XHnPc~%^ep@-dC_3pbjgPWAV3Ld&%X^}@pSdOT4MEj}>dfu7anBL=Jq2yWj zdzqKBvgk?vu);6RmYd7uSB1TH!;UxVDkK@MYeas8REC&1k9(*qPp7FiMZpoM$53Ma zbaxTExj?z>8>&l`JS+Tu9j-u_hvEd#+6+Ae90FH*B?|p1&n*=__s)mlnI0BxsXlE!x zI`qi;Up7VzfE8~kQST@0xJ=?}iFO^v*OC@67P&Ew`)XGhDnl~04+=THwx;&=jPX0_ z;apxA!=mYEQ=0rxoB1j1(K7z#zTf~Ou7b1j#x(A_x2tZj8zO~vy^6bxV>HQ99OZUa`FrPUEaOBPCcY;=L-LM%PKJv7Z=hbd4lUh#no%1J8i%H}`%Z z5wm22q?p7Ii?xy>LEzH{bHUX-!P(H{ZHM6HT54bzDzH16w1GBu3z=1!#~K{pzh37O zde>l#b*q|n<`&Di>Qg5W7IK=j7!nP2o4f??%;DfpuCI3L&KLm9Z!j1oaV6oEx;nZ& z_V$FG5~%PJwoV{Bcar&>f|(31GdK5w4l_PZfL1UW<{AmK;F z=rkeGp7yxY8#qyXV~RyTYR~Mu;_3o)$2?`)4mdXO5_~>+arebb;svv~4_VqJsVUZE zHI-FdJ%pVFpxA)L*ol-pEwSAFnQM*q&*`F}x&?hs-mz1uTZuKIzh&Y7b5omUM@-3G zTB&@U(=5--l#GLC4qGy#7%H-*KHYXWVfX|;sr%)~3FTZ|DqPRQX%`)aVqf_t58OEx z3;8q@`G^`(?;*0eKykm*)~~jxzaZn=XZj4F2`k>eWD_}K z5)fH8hw@W=yAOgOrDw*ue<&@zTt`V>f2#OEkG1^u$++j*(ESm&`Wg6?M*oDCKyiyt zX13}hH=9#G56bAWw^Q@G*A1Wv^OaH|9Ni(|`yTsgTPDu;oZc>_$Xs#in7gQ~X2Ii?#tnkb`N>AiddFd- z2JPZGeU4+*Gf)iu{<3=TCDYO3DMg8o2p)(&&iIvVa6!@Gfv=>@msEkE0!^3Wyi6XE zb^a-lJ?*4t0FEjPf(yOg6F>=W?=NCOzs$-@2mKd2i2&a+h^d1nc*XP zXaWQ`Zm8_$P^*;I-M4uovi`6q-)YGLcoaWI6=?#lE@o#PL2b_vpoHB9GJsJA>fuC%1D zJHJ?cquK+{7(OApuI`sT&a+(87@xYq@Qqqpu3ovqv7zCJi_6>0pDr^?CNqJGU%4N6 zEXIV{0~7BwgYypr*aNQgRo^$rc^BzAQ&s&zvzrH;VF`8ID

$s5UkQcXnD2HGFh< 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

*/ -static int cmd_mkdir(int argc, char *argv[]) -{ - const char *name; - - CHK_ARGC(2, 0); - - name = argv[1]; - - if (uffs_mkdir(name) < 0) { - MSGLN("Create %s fail, err: %d", name, uffs_get_error()); - return -1; - } - else { - MSGLN("Create %s succ.", name); - } - - return 0; -} - - -static int CountObjectUnder(const char *dir) -{ - int count = 0; - uffs_DIR *dirp; - - dirp = uffs_opendir(dir); - if (dirp) { - while (uffs_readdir(dirp) != NULL) - count++; - uffs_closedir(dirp); - } - return count; -} - -static int cmd_pwd(int argc, char *argv[]) -{ - MSGLN("not supported."); - return 0; -} - -static int cmd_cd(int argc, char *argv[]) -{ - MSGLN("Not supported"); - return 0; -} - -/** ls [] */ -static int cmd_ls(int argc, char *argv[]) -{ - uffs_DIR *dirp; - struct uffs_dirent *ent; - struct uffs_stat stat_buf; - int count = 0; - char buf[MAX_PATH_LENGTH+2]; - const char *name = "/"; - char *sub; - int ret = 0; - - CHK_ARGC(1, 2); - - if (argc > 1) - name = argv[1]; - - dirp = uffs_opendir(name); - if (dirp == NULL) { - MSGLN("Can't open '%s' for list", name); - ret = -1; - } - else { - MSG("------name-----------size---------serial-----" TENDSTR); - ent = uffs_readdir(dirp); - while (ent) { - MSG("%9s", ent->d_name); - strcpy(buf, name); - sub = buf; - if (name[strlen(name)-1] != '/') - sub = strcat(buf, "/"); - sub = strcat(sub, ent->d_name); - if (ent->d_type & FILE_ATTR_DIR) { - sub = strcat(sub, "/"); - MSG("/ \t<%8d>", CountObjectUnder(sub)); - } - else { - uffs_stat(sub, &stat_buf); - MSG(" \t %8d ", stat_buf.st_size); - } - MSG("\t%6d" TENDSTR, ent->d_ino); - count++; - ent = uffs_readdir(dirp); - } - - uffs_closedir(dirp); - - MSG("Total: %d objects." TENDSTR, count); - } - - return ret; -} - -/** rm */ -static int cmd_rm(int argc, char *argv[]) -{ - const char *name = NULL; - int ret = 0; - struct uffs_stat st; - - CHK_ARGC(2, 2); - - name = argv[1]; - - ret = uffs_stat(name, &st); - if (ret < 0) { - MSGLN("Can't stat '%s'", name); - return ret; - } - - if (st.st_mode & US_IFDIR) { - ret = uffs_rmdir(name); - } - else { - ret = uffs_remove(name); - } - - if (ret == 0) - MSGLN("Delete '%s' succ.", name); - else - MSGLN("Delete '%s' fail!", name); - - return ret; -} - -/** ren|mv */ -static int cmd_ren(int argc, char *argv[]) -{ - const char *oldname; - const char *newname; - int ret; - - CHK_ARGC(3, 3); - - oldname = argv[1]; - newname = argv[2]; - - if ((ret = uffs_rename(oldname, newname)) == 0) { - MSGLN("Rename from '%s' to '%s' succ.", oldname, newname); - } - else { - MSGLN("Rename from '%s' to '%s' fail!", oldname, newname); - } - - return ret; -} - -static void dump_msg_to_stdout(struct uffs_DeviceSt *dev, const char *fmt, ...) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - va_list args; - - va_start(args, fmt); - //vprintf(fmt, args); - if (emu && emu->dump_fp) - vfprintf(emu->dump_fp, fmt, args); - va_end(args); -} - -/** dump [] */ -static int cmd_dump(int argc, char *argv[]) -{ - uffs_Device *dev; - uffs_FileEmu *emu; - const char *mount = "/"; - const char *dump_file = "dump.txt"; - - if (argc > 1) { - mount = argv[1]; - if (argc > 2) - dump_file = argv[2]; - } - - dev = uffs_GetDeviceFromMountPoint(mount); - if (dev == NULL) { - MSGLN("Can't get device from mount point %s", mount); - return -1; - } - - emu = (uffs_FileEmu *)(dev->attr->_private); - emu->dump_fp = fopen(dump_file, "w"); - - uffs_DumpDevice(dev, dump_msg_to_stdout); - - if (emu->dump_fp) - fclose(emu->dump_fp); - - uffs_PutDevice(dev); - - return 0; -} - -/** st [] */ -static int cmd_st(int argc, char *argv[]) -{ - uffs_Device *dev; - const char *mount = "/"; - uffs_FlashStat *s; - TreeNode *node; - - if (argc > 1) { - mount = argv[1]; - } - - dev = uffs_GetDeviceFromMountPoint(mount); - if (dev == NULL) { - MSGLN("Can't get device from mount point %s", mount); - return -1; - } - - s = &(dev->st); - - MSG("----------- basic info -----------" TENDSTR); - MSG("TreeNode size: %d" TENDSTR, sizeof(TreeNode)); - MSG("TagStore size: %d" TENDSTR, sizeof(struct uffs_TagStoreSt)); - MSG("MaxCachedBlockInfo: %d" TENDSTR, dev->cfg.bc_caches); - MSG("MaxPageBuffers: %d" TENDSTR, dev->cfg.page_buffers); - MSG("MaxDirtyPagesPerBlock: %d" TENDSTR, dev->cfg.dirty_pages); - MSG("MaxPathLength: %d" TENDSTR, MAX_PATH_LENGTH); - MSG("MaxObjectHandles: %d" TENDSTR, MAX_OBJECT_HANDLE); - MSG("FreeObjectHandles: %d" TENDSTR, uffs_GetFreeObjectHandlers()); - MSG("MaxDirHandles: %d" TENDSTR, MAX_DIR_HANDLE); - MSG("FreeDirHandles: %d" TENDSTR, uffs_PoolGetFreeCount(uffs_DirEntryBufGetPool())); - - MSG("----------- statistics for '%s' -----------" TENDSTR, mount); - MSG("Device Ref: %d" TENDSTR, dev->ref_count); - MSG("Block Erased: %d" TENDSTR, s->block_erase_count); - MSG("Write Page: %d" TENDSTR, s->page_write_count); - MSG("Write Spare: %d" TENDSTR, s->spare_write_count); - MSG("Read Page: %d" TENDSTR, s->page_read_count - s->page_header_read_count); - MSG("Read Header: %d" TENDSTR, s->page_header_read_count); - MSG("Read Spare: %d" TENDSTR, s->spare_read_count); - MSG("I/O Read: %lu" TENDSTR, s->io_read); - MSG("I/O Write: %lu" TENDSTR, s->io_write); - - MSG("--------- partition info for '%s' ---------" TENDSTR, mount); - MSG("Space total: %d" TENDSTR, uffs_GetDeviceTotal(dev)); - MSG("Space used: %d" TENDSTR, uffs_GetDeviceUsed(dev)); - MSG("Space free: %d" TENDSTR, uffs_GetDeviceFree(dev)); - MSG("Page Size: %d" TENDSTR, dev->attr->page_data_size); - MSG("Spare Size: %d" TENDSTR, dev->attr->spare_size); - MSG("Pages Per Block: %d" TENDSTR, dev->attr->pages_per_block); - MSG("Block size: %d" TENDSTR, dev->attr->page_data_size * dev->attr->pages_per_block); - MSG("Total blocks: %d of %d" TENDSTR, (dev->par.end - dev->par.start + 1), dev->attr->total_blocks); - if (dev->tree.bad) { - MSG("Bad blocks: "); - node = dev->tree.bad; - while(node) { - MSG("%d, ", node->u.list.block); - node = node->u.list.next; - } - MSG(TENDSTR); - } - - uffs_PutDevice(dev); - - return 0; - -} - -/** cp */ -static int cmd_cp(int argc, char *argv[]) -{ - const char *src; - const char *des; - char buf[100]; - int fd1 = -1, fd2 = -1; - int len; - BOOL src_local = FALSE, des_local = FALSE; - FILE *fp1 = NULL, *fp2 = NULL; - int ret = -1; - - CHK_ARGC(3, 3); - - src = argv[1]; - des = argv[2]; - - if (memcmp(src, "::", 2) == 0) { - src += 2; - src_local = TRUE; - } - if (memcmp(des, "::", 2) == 0) { - des += 2; - des_local = TRUE; - } - - if (src_local) { - if ((fp1 = fopen(src, "rb")) == NULL) { - MSGLN("Can't open %s for copy.", src); - goto fail_ext; - } - } - else { - if ((fd1 = uffs_open(src, UO_RDONLY)) < 0) { - MSGLN("Can't open %s for copy.", src); - goto fail_ext; - } - } - - if (des_local) { - if ((fp2 = fopen(des, "wb")) == NULL) { - MSGLN("Can't open %s for copy.", des); - goto fail_ext; - } - } - else { - if ((fd2 = uffs_open(des, UO_RDWR|UO_CREATE|UO_TRUNC)) < 0) { - MSGLN("Can't open %s for copy.", des); - goto fail_ext; - } - } - - ret = 0; - while ( (src_local ? (feof(fp1) == 0) : (uffs_eof(fd1) == 0)) ) { - ret = -1; - if (src_local) { - len = fread(buf, 1, sizeof(buf), fp1); - } - else { - len = uffs_read(fd1, buf, sizeof(buf)); - } - if (len == 0) { - ret = -1; - break; - } - if (len < 0) { - MSGLN("read file %s fail ?", src); - break; - } - if (des_local) { - if ((int)fwrite(buf, 1, len, fp2) != len) { - MSGLN("write file %s fail ? ", des); - break; - } - } - else { - if (uffs_write(fd2, buf, len) != len) { - MSGLN("write file %s fail ? ", des); - break; - } - } - ret = 0; - } - -fail_ext: - if (fd1 > 0) - uffs_close(fd1); - if (fd2 > 0) - uffs_close(fd2); - if (fp1) - fclose(fp1); - if (fp2) - fclose(fp2); - - return ret; -} - -/** cat [] [] */ -static int cmd_cat(int argc, char *argv[]) -{ - int fd; - const char *name = NULL; - char buf[100]; - int start = 0, size = 0, printed = 0, n, len; - int ret = -1; - - CHK_ARGC(2, 4); - - name = argv[1]; - - if ((fd = uffs_open(name, UO_RDONLY)) < 0) { - MSGLN("Can't open %s", name); - goto fail; - } - - if (argc > 2) { - start = strtol(argv[2], NULL, 10); - if (argc > 3) size = strtol(argv[3], NULL, 10); - } - - if (start >= 0) - uffs_seek(fd, start, USEEK_SET); - else - uffs_seek(fd, -start, USEEK_END); - - while (uffs_eof(fd) == 0) { - len = uffs_read(fd, buf, sizeof(buf) - 1); - if (len == 0) - break; - if (len > 0) { - if (size == 0 || printed < size) { - n = (size == 0 ? len : (size - printed > len ? len : size - printed)); - buf[n] = 0; - MSG("%s", buf); - printed += n; - } - else { - break; - } - } - } - MSG(TENDSTR); - uffs_close(fd); - - ret = 0; -fail: - - return ret; -} - -/** mount partition or show mounted partitions - * mount [] - */ -static int cmd_mount(int argc, char *argv[]) -{ - uffs_MountTable *tab; - const char *mount = NULL; - - if (argc == 1) { - tab = uffs_MtbGetMounted(); - while (tab) { - MSG(" %s : (%d) ~ (%d)\n", tab->mount, tab->start_block, tab->end_block); - tab = tab->next; - } - } - else { - mount = argv[1]; - if (uffs_Mount(mount) < 0) { - MSGLN("Can't mount %s", mount); - return -1; - } - } - return 0; -} - -/** unmount parition or show unmounted partitions - * umount [] - */ -static int cmd_unmount(int argc, char *argv[]) -{ - uffs_MountTable *tab; - const char *mount = NULL; - - if (argc == 1) { - tab = uffs_MtbGetUnMounted(); - while (tab) { - MSG(" %s : (%d) ~ (%d)\n", tab->mount, tab->start_block, tab->end_block); - tab = tab->next; - } - } - else { - mount = argv[1]; - if (uffs_UnMount(mount) < 0) { - MSGLN("Can't unmount %s", mount); - return -1; - } - } - - return 0; -} - -/** inspect buffers - * inspb [] - */ -static int cmd_inspb(int argc, char *argv[]) -{ - uffs_Device *dev; - const char *mount = "/"; - - CHK_ARGC(1, 2); - - dev = uffs_GetDeviceFromMountPoint(mount); - if (dev == NULL) { - MSGLN("Can't get device from mount point %s", mount); - return -1; - } - uffs_BufInspect(dev); - uffs_PutDevice(dev); - - return 0; - -} - -/** print block wear-leveling information - * wl [] - */ -static int cmd_wl(int argc, char *argv[]) -{ - const char *mount = "/"; - uffs_Device *dev; - struct uffs_PartitionSt *par; - uffs_FileEmu *emu; - int i, max; - u32 n; - -#define NUM_PER_LINE 10 - - CHK_ARGC(1, 2); - - if (argc > 1) { - mount = argv[1]; - } - - dev = uffs_GetDeviceFromMountPoint(mount); - if (dev == NULL) { - MSGLN("Can't get device from mount point %s", mount); - return -1; - } - - par = &dev->par; - emu = (uffs_FileEmu *)(dev->attr->_private); - max = -1; - - for (i = 0; i < par->end - par->start; i++) { - if ((i % NUM_PER_LINE) == 0) { - MSG("%04d:", i + par->start); - } - n = i + par->start; - max = (max == -1 ? n : - (emu->em_monitor_block[n] > emu->em_monitor_block[max] ? n : max) - ); - MSG(" %4d", emu->em_monitor_block[n]); - if (uffs_TreeFindBadNodeByBlock(dev, n)) - MSG("%c", 'x'); - else if (uffs_TreeFindErasedNodeByBlock(dev, n)) - MSG("%c", ' '); - else - MSG("%c", '.'); - if (((i + 1) % NUM_PER_LINE) == 0) - MSG("\n"); - } - MSG("\n"); - MSG("Total blocks %d, peak erase count %d at block %d\n", - par->end - par->start, max == -1 ? 0 : emu->em_monitor_block[max], max); - - uffs_PutDevice(dev); - - return 0; -} - -static const struct cli_command helper_cmds[] = -{ - { cmd_format, "format", "[]", "Format device" }, - { cmd_mkf, "mkfile", "", "create a new file" }, - { cmd_mkdir, "mkdir", "", "create a new directory" }, - { cmd_rm, "rm", "", "delete file/directory" }, - { cmd_ren, "mv|ren", " ", "rename file/directory" }, - { cmd_ls, "ls", "", "list dirs and files" }, - { cmd_st, "info|st", "", "show statistic infomation" }, - { cmd_cp, "cp", " ", "copy files. the local file name start with '::'" }, - { cmd_cat, "cat", "", "show file content" }, - { cmd_pwd, "pwd", NULL, "show current dir" }, - { cmd_cd, "cd", "", "change current dir" }, - { cmd_mount, "mount", "[]", "mount partition or list mounted partitions" }, - { cmd_unmount, "umount", "[]", "unmount partition" }, - { cmd_dump, "dump", "[]", "dump file system", }, - { cmd_wl, "wl", "[]", "show block wear-leveling info", }, - { cmd_inspb, "inspb", "[]", "inspect buffer", }, - { NULL, NULL, NULL, NULL } -}; - -static struct cli_commandset helper_cmdset = { - helper_cmds, -}; - -struct cli_commandset * get_helper_cmds() -{ - return &helper_cmdset; -}; diff --git a/components/dfs/filesystems/uffs/src/emu/test_cmds.c b/components/dfs/filesystems/uffs/src/emu/test_cmds.c deleted file mode 100644 index a4bc1eca41..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/test_cmds.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file test_cmds.c - * \brief commands for test uffs - * \author Ricky Zheng - */ -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_fd.h" -#include "uffs/uffs_utils.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_find.h" -#include "uffs/uffs_badblock.h" -#include "cmdline.h" -#include "api_test.h" - -#define PFX "test: " - -#define MAX_TEST_BUF_LEN 8192 - -#define SEQ_INIT 10 -#define SEQ_MOD_LEN 120 - -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - - -static void memcp_seq(void *des, int size, int start_pos) -{ - int i; - u8 *p = (u8 *)des; - - for (i = 0; i < size; i++, p++) { - *p = (start_pos + SEQ_INIT + i) % SEQ_MOD_LEN; - } -} - -static UBOOL check_entry_exist(const char *name) -{ - struct uffs_stat sb; - - return uffs_stat(name, &sb) < 0 ? U_FALSE : U_TRUE; -} - -static URET do_write_test_file(int fd, int size) -{ - long pos; - unsigned char buf[100]; - int len; - - while (size > 0) { - pos = uffs_seek(fd, 0, USEEK_CUR); - len = (size > sizeof(buf) ? sizeof(buf) : size); - memcp_seq(buf, len, pos); - if (uffs_write(fd, buf, len) != len) { - MSGLN("Write file failed, size %d at %d", len, pos); - return U_FAIL; - } - size -= len; - } - - return U_SUCC; -} - -static URET test_write_file(const char *file_name, int pos, int size) -{ - int ret = U_FAIL; - int fd = -1; - - if ((fd = uffs_open(file_name, UO_RDWR|UO_CREATE)) < 0) { - MSGLN("Can't open file %s for write.", file_name); - goto test_exit; - } - - if (uffs_seek(fd, pos, USEEK_SET) != pos) { - MSGLN("Can't seek file %s at pos %d", file_name, pos); - goto test_failed; - } - - if (do_write_test_file(fd, size) == U_FAIL) { - MSGLN("Write file %s failed.", file_name); - goto test_failed; - } - ret = U_SUCC; - -test_failed: - uffs_close(fd); - -test_exit: - - return ret; -} - - -static URET test_verify_file(const char *file_name, UBOOL noecc) -{ - int fd; - int ret = U_FAIL; - unsigned char buf[100]; - int i, pos, len; - u8 x; - - if ((fd = uffs_open(file_name, (noecc ? UO_RDONLY|UO_NOECC : UO_RDONLY))) < 0) { - MSGLN("Can't open file %s for read.", file_name); - goto test_exit; - } - - pos = 0; - while (!uffs_eof(fd)) { - len = uffs_read(fd, buf, sizeof(buf)); - if (len <= 0) - goto test_failed; - for (i = 0; i < len; i++) { - x = (SEQ_INIT + pos + i) % SEQ_MOD_LEN; - if (buf[i] != x) { - MSGLN("Verify file %s failed at: %d, expect 0x%02x but got 0x%02x", file_name, pos + i, x, buf[i]); - goto test_failed; - } - } - pos += len; - } - - if (pos != uffs_seek(fd, 0, USEEK_END)) { - MSGLN("Verify file %s failed. invalid file length.", file_name); - goto test_failed; - } - - MSGLN("Verify file %s succ.", file_name); - ret = U_SUCC; - -test_failed: - uffs_close(fd); - -test_exit: - - return ret; -} - -static URET test_append_file(const char *file_name, int size) -{ - int ret = U_FAIL; - int fd = -1; - - if ((fd = uffs_open(file_name, UO_RDWR|UO_APPEND|UO_CREATE)) < 0) { - MSGLN("Can't open file %s for append.", file_name); - goto test_exit; - } - - uffs_seek(fd, 0, USEEK_END); - - if (do_write_test_file(fd, size) == U_FAIL) { - MSGLN("Write file %s failed.", file_name); - goto test_failed; - } - ret = U_SUCC; - -test_failed: - uffs_close(fd); - -test_exit: - - return ret; -} - - -/* test create file, write file and read back */ -static int cmd_t1(int argc, char *argv[]) -{ - int fd; - URET ret; - char buf[100]; - const char *name; - - if (argc < 2) { - return CLI_INVALID_ARG; - } - - name = argv[1]; - - fd = uffs_open(name, UO_RDWR|UO_CREATE|UO_TRUNC); - if (fd < 0) { - MSGLN("Can't open %s", name); - goto fail; - } - - sprintf(buf, "123456789ABCDEF"); - ret = uffs_write(fd, buf, strlen(buf)); - MSGLN("write %d bytes to file, content: %s", ret, buf); - - ret = uffs_seek(fd, 3, USEEK_SET); - MSGLN("new file position: %d", ret); - - memset(buf, 0, sizeof(buf)); - ret = uffs_read(fd, buf, 5); - MSGLN("read %d bytes, content: %s", ret, buf); - - uffs_close(fd); - - return 0; -fail: - - return -1; -} - - -static URET DoTest2(void) -{ - int fd = -1; - URET ret = U_FAIL; - char buf[100], buf_1[100]; - - fd = uffs_open("/abc/", UO_RDWR|UO_DIR); - if (fd < 0) { - MSGLN("Can't open dir abc, err: %d", uffs_get_error()); - MSGLN("Try to create a new one..."); - fd = uffs_open("/abc/", UO_RDWR|UO_CREATE|UO_DIR); - if (fd < 0) { - MSGLN("Can't create new dir /abc/"); - goto exit_test; - } - else { - uffs_close(fd); - } - } - else { - uffs_close(fd); - } - - fd = uffs_open("/abc/test.txt", UO_RDWR|UO_CREATE); - if (fd < 0) { - MSGLN("Can't open /abc/test.txt"); - goto exit_test; - } - - sprintf(buf, "123456789ABCDEF"); - ret = uffs_write(fd, buf, strlen(buf)); - MSGLN("write %d bytes to file, content: %s", ret, buf); - - ret = uffs_seek(fd, 3, USEEK_SET); - MSGLN("new file position: %d", ret); - - memset(buf_1, 0, sizeof(buf_1)); - ret = uffs_read(fd, buf_1, 5); - MSGLN("read %d bytes, content: %s", ret, buf_1); - - if (memcmp(buf + 3, buf_1, 5) != 0) { - ret = U_FAIL; - } - else { - ret = U_SUCC; - } - - uffs_close(fd); - -exit_test: - - return ret; -} - - -static int cmd_t2(int argc, char *argv[]) -{ - URET ret; - MSGLN("Test return: %s !", (ret = DoTest2()) == U_SUCC ? "succ" : "failed"); - - return (ret == U_SUCC) ? 0 : -1; -} - - -static int cmd_VerifyFile(int argc, char *argv[]) -{ - const char *name; - UBOOL noecc = U_FALSE; - - if (argc < 2) { - return CLI_INVALID_ARG; - } - - name = argv[1]; - if (argc > 2 && strcmp(argv[2], "noecc") == 0) { - noecc = U_TRUE; - } - - MSGLN("Check file %s ... ", name); - if (test_verify_file(name, noecc) != U_SUCC) { - MSGLN("Verify file %s failed.", name); - return -1; - } - - return 0; -} - -/* Test file append and 'random' write */ -static int cmd_t3(int argc, char *argv[]) -{ - const char *name; - int i; - UBOOL noecc = U_FALSE; - int write_test_seq[] = { 20, 10, 500, 40, 1140, 900, 329, 4560, 352, 1100 }; - - if (argc < 2) { - return CLI_INVALID_ARG; - } - - name = argv[1]; - if (argv[2] && strcmp(argv[2], "noecc") == 0) { - noecc = U_TRUE; - } - - if (check_entry_exist(name)) { - MSGLN("Check file %s ... ", name); - if (test_verify_file(name, noecc) != U_SUCC) { - MSGLN("Verify file %s failed.", name); - return -1; - } - } - - MSGLN("Test append file %s ...", name); - for (i = 1; i < 500; i += 29) { - if (test_append_file(name, i) != U_SUCC) { - MSGLN("Append file %s test failed at %d !", name, i); - return -1; - } - } - - MSGLN("Check file %s ... ", name); - if (test_verify_file(name, noecc) != U_SUCC) { - MSGLN("Verify file %s failed.", name); - return -1; - } - - MSGLN("Test write file ..."); - for (i = 0; i < sizeof(write_test_seq) / sizeof(int) - 1; i++) { - if (test_write_file(name, write_test_seq[i], write_test_seq[i+1]) != U_SUCC) { - MSGLN("Test write file failed !"); - return -1; - } - } - - MSGLN("Check file %s ... ", name); - if (test_verify_file(name, noecc) != U_SUCC) { - MSGLN("Verify file %s failed.", name); - return -1; - } - - MSGLN("Test succ !"); - - return 0; -} - -/* open two files and test write */ -static int cmd_t4(int argc, char *argv[]) -{ - int fd1 = -1, fd2 = -1; - - MSGLN("open /a ..."); - if ((fd1 = uffs_open("/a", UO_RDWR | UO_CREATE)) < 0) { - MSGLN("Can't open /a"); - goto fail_exit; - } - - MSGLN("open /b ..."); - if ((fd2 = uffs_open("/b", UO_RDWR | UO_CREATE)) < 0) { - MSGLN("Can't open /b"); - uffs_close(fd1); - goto fail_exit; - } - - MSGLN("write (1) to /a ..."); - uffs_write(fd1, "Hello,", 6); - MSGLN("write (1) to /b ..."); - uffs_write(fd2, "Hello,", 6); - MSGLN("write (2) to /a ..."); - uffs_write(fd1, "World.", 6); - MSGLN("write (2) to /b ..."); - uffs_write(fd2, "World.", 6); - MSGLN("close /a ..."); - uffs_close(fd1); - MSGLN("close /b ..."); - uffs_close(fd2); - - return 0; - -fail_exit: - return -1; -} - -/* test appending file */ -static int cmd_t5(int argc, char *argv[]) -{ - int fd = -1; - URET ret; - char buf[100]; - const char *name; - - if (argc < 2) { - return CLI_INVALID_ARG; - } - - name = argv[1]; - - fd = uffs_open(name, UO_RDWR|UO_APPEND); - if (fd < 0) { - MSGLN("Can't open %s", name); - goto fail; - } - - sprintf(buf, "append test..."); - ret = uffs_write(fd, buf, strlen(buf)); - if (ret != strlen(buf)) { - MSGLN("write file failed, %d/%d", ret, strlen(buf)); - ret = -1; - } - else { - MSGLN("write %d bytes to file, content: %s", ret, buf); - ret = 0; - } - - uffs_close(fd); - - return ret; -fail: - return -1; -} - - -/* usage: t_pgrw - * - * This test case test page read/write - */ -static int cmd_TestPageReadWrite(int argc, char *argv[]) -{ - TreeNode *node = NULL; - uffs_Device *dev; - uffs_Tags local_tag; - uffs_Tags *tag = &local_tag; - int ret; - u16 block; - u16 page; - uffs_Buf *buf = NULL; - - u32 i; - int rc = -1; - - dev = uffs_GetDeviceFromMountPoint("/"); - if (!dev) - goto ext; - - buf = uffs_BufClone(dev, NULL); - if (!buf) - goto ext; - - node = uffs_TreeGetErasedNode(dev); - if (!node) { - MSGLN("no free block ?"); - goto ext; - } - - for (i = 0; i < dev->com.pg_data_size; i++) { - buf->data[i] = i & 0xFF; - } - - block = node->u.list.block; - page = 1; - - TAG_DIRTY_BIT(tag) = TAG_DIRTY; - TAG_VALID_BIT(tag) = TAG_VALID; - TAG_DATA_LEN(tag) = dev->com.pg_data_size; - TAG_TYPE(tag) = UFFS_TYPE_DATA; - TAG_PAGE_ID(tag) = 3; - TAG_PARENT(tag) = 100; - TAG_SERIAL(tag) = 10; - TAG_BLOCK_TS(tag) = 1; - SEAL_TAG(tag); - - ret = uffs_FlashWritePageCombine(dev, block, page, buf, tag); - if (UFFS_FLASH_HAVE_ERR(ret)) { - MSGLN("Write page error: %d", ret); - goto ext; - } - - ret = uffs_FlashReadPage(dev, block, page, buf, U_FALSE); - if (UFFS_FLASH_HAVE_ERR(ret)) { - MSGLN("Read page error: %d", ret); - goto ext; - } - - for (i = 0; i < dev->com.pg_data_size; i++) { - if (buf->data[i] != (i & 0xFF)) { - MSGLN("Data verify fail at: %d", i); - goto ext; - } - } - - ret = uffs_FlashReadPageTag(dev, block, page, tag); - if (UFFS_FLASH_HAVE_ERR(ret)) { - MSGLN("Read tag (page spare) error: %d", ret); - goto ext; - } - - // verify tag: - if (!TAG_IS_SEALED(tag)) { - MSGLN("not sealed ? Tag verify fail!"); - goto ext; - } - - if (!TAG_IS_DIRTY(tag)) { - MSGLN("not dirty ? Tag verify fail!"); - goto ext; - } - - if (!TAG_IS_VALID(tag)) { - MSGLN("not valid ? Tag verify fail!"); - goto ext; - } - - if (TAG_DATA_LEN(tag) != dev->com.pg_data_size || - TAG_TYPE(tag) != UFFS_TYPE_DATA || - TAG_PAGE_ID(tag) != 3 || - TAG_PARENT(tag) != 100 || - TAG_SERIAL(tag) != 10 || - TAG_BLOCK_TS(tag) != 1) { - - MSGLN("Tag verify fail!"); - goto ext; - } - - MSGLN("Page read/write test succ."); - rc = 0; - -ext: - if (node) { - uffs_FlashEraseBlock(dev, node->u.list.block); - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, node); - else - uffs_TreeInsertToErasedListTail(dev, node); - } - - if (dev) - uffs_PutDevice(dev); - - if (buf) - uffs_BufFreeClone(dev, buf); - - return rc; -} - -/* t_format : test format partition */ -static int cmd_TestFormat(int argc, char *argv[]) -{ - URET ret; - const char *mount = "/"; - uffs_Device *dev; - UBOOL force = U_FALSE; - const char *test_file = "/a.txt"; - int fd; - int rc = -1; - - if (argc > 1) { - mount = argv[1]; - if (argc > 2 && strcmp(argv[2], "-f") == 0) - force = U_TRUE; - } - - fd = uffs_open(test_file, UO_RDWR | UO_CREATE); - if (fd < 0) { - MSGLN("can't create test file %s", test_file); - goto ext; - } - - MSGLN("Formating %s ... ", mount); - - dev = uffs_GetDeviceFromMountPoint(mount); - if (dev == NULL) { - MSGLN("Can't get device from mount point."); - goto ext; - } - else { - ret = uffs_FormatDevice(dev, force); - if (ret != U_SUCC) { - MSGLN("Format fail."); - } - else { - MSGLN("Format succ."); - rc = 0; - } - uffs_PutDevice(dev); - } - - uffs_close(fd); // this should fail on signature check ! -ext: - return rc; -} - - - -/** - * usage: t_pfs - * - * for example: t_pfs /x/ 100 - * - * This test case performs: - * 1) create files under , write full file name as file content - * 2) list files under , check files are all listed once - * 3) check file content aganist file name - * 4) delete files on success - */ -static int cmd_TestPopulateFiles(int argc, char *argv[]) -{ - const char *start = "/"; - int count = 80; - int i, fd, num; - char name[128]; - char buf[128]; - uffs_DIR *dirp; - struct uffs_dirent *ent; - unsigned long bitmap[50] = {0}; // one bit per file, maximu 32*50 = 1600 files - UBOOL succ = U_TRUE; - -#define SBIT(n) bitmap[(n)/(sizeof(bitmap[0]) * 8)] |= (1 << ((n) % (sizeof(bitmap[0]) * 8))) -#define GBIT(n) (bitmap[(n)/(sizeof(bitmap[0]) * 8)] & (1 << ((n) % (sizeof(bitmap[0]) * 8)))) - - if (argc > 1) { - start = argv[1]; - if (argc > 2) { - count = strtol(argv[2], NULL, 10); - } - } - - if (count > sizeof(bitmap) * 8) - count = sizeof(bitmap) * 8; - - for (i = 0, fd = -1; i < count; i++) { - sprintf(name, "%sFile%03d", start, i); - fd = uffs_open(name, UO_RDWR|UO_CREATE|UO_TRUNC); - if (fd < 0) { - MSGLN("Create file %s failed", name); - break; - } - if (uffs_write(fd, name, strlen(name)) != strlen(name)) { // write full path name to file - MSGLN("Write to file %s failed", name); - uffs_close(fd); - break; - } - uffs_close(fd); - } - - if (i < count) { - // not success, need to clean up - for (; i >= 0; i--) { - sprintf(name, "%sFile%03d", start, i); - if (uffs_remove(name) < 0) - MSGLN("Delete file %s failed", name); - } - succ = U_FALSE; - goto ext; - } - - MSGLN("%d files created.", count); - - // list files - dirp = uffs_opendir(start); - if (dirp == NULL) { - MSGLN("Can't open dir %s !", start); - succ = U_FALSE; - goto ext; - } - ent = uffs_readdir(dirp); - while (ent && succ) { - - if (!(ent->d_type & FILE_ATTR_DIR) && // not a dir - ent->d_namelen == strlen("File000") && // check file name length - memcmp(ent->d_name, "File", strlen("File")) == 0) { // file name start with "File" - - MSGLN("List entry %s", ent->d_name); - - num = strtol(ent->d_name + 4, NULL, 10); - if (GBIT(num)) { - // file already listed ? - MSGLN("File %d listed twice !", ent->d_name); - succ = U_FALSE; - break; - } - SBIT(num); - - // check file content - sprintf(name, "%s%s", start, ent->d_name); - fd = uffs_open(name, UO_RDONLY); - if (fd < 0) { - MSGLN("Open file %d for read failed !", name); - } - else { - memset(buf, 0, sizeof(buf)); - num = uffs_read(fd, buf, sizeof(buf)); - if (num != strlen(name)) { - MSGLN("%s Read data length expect %d but got %d !", name, strlen(name), num); - succ = U_FALSE; - } - else { - if (memcmp(name, buf, num) != 0) { - MSGLN("File %s have wrong content '%s' !", name, buf); - succ = U_FALSE; - } - } - uffs_close(fd); - } - } - ent = uffs_readdir(dirp); - } - uffs_closedir(dirp); - - // check absent files - for (i = 0; i < count; i++) { - if (GBIT(i) == 0) { - sprintf(name, "%sFile%03d", start, i); - MSGLN("File %s not listed !", name); - succ = U_FALSE; - } - } - - // delete files if pass the test - for (i = 0; succ && i < count; i++) { - sprintf(name, "%sFile%03d", start, i); - if (uffs_remove(name) < 0) { - MSGLN("Delete file %s failed", name); - succ = U_FALSE; - } - } - -ext: - MSGLN("Populate files test %s !", succ ? "SUCC" : "FAILED"); - return succ ? 0 : -1; - -} - -/** - * Open with , save fd to $1 - * - * t_open - */ -static int cmd_topen(int argc, char *argv[]) -{ - int fd; - const char *name; - char *p; - int oflag = 0; - - CHK_ARGC(3, 3); - - name = argv[2]; - p = argv[1]; - while(*p) { - switch(*p++) { - case 'a': - oflag |= UO_APPEND; - break; - case 'c': - oflag |= UO_CREATE; - break; - case 't': - oflag |= UO_TRUNC; - break; - case 'w': - oflag |= UO_RDWR; - break; - case 'r': - oflag |= UO_RDONLY; - break; - } - } - - fd = uffs_open(name, oflag); - - if (fd >= 0) { - cli_env_set('1', fd); - return 0; - } - else { - return -1; - } -} - -/** - * seek file pointer - * t_seek [] - * if success, $1 = file position after seek - */ -static int cmd_tseek(int argc, char *argv[]) -{ - int origin = USEEK_SET; - int offset; - int fd; - int ret; - - CHK_ARGC(3, 4); - - if (sscanf(argv[1], "%d", &fd) != 1 || - sscanf(argv[2], "%d", &offset) != 1) - { - return CLI_INVALID_ARG; - } - - if (argc > 3) { - switch(argv[3][0]) { - case 's': - origin = USEEK_SET; - break; - case 'c': - origin = USEEK_CUR; - break; - case 'e': - origin = USEEK_END; - break; - default: - return CLI_INVALID_ARG; - } - } - - ret = uffs_seek(fd, offset, origin); - if (ret >= 0) { - cli_env_set('1', ret); - return 0; - } - else { - return -1; - } -} - -/** - * close file - * t_close - */ -static int cmd_tclose(int argc, char *argv[]) -{ - int fd; - - CHK_ARGC(2, 2); - - if (sscanf(argv[1], "%d", &fd) == 1) { - return uffs_close(fd); - } - else - return -1; -} - -/** - * write file - * t_write [..] - */ -static int cmd_twrite(int argc, char *argv[]) -{ - int fd; - int i, len = 0; - int ret = 0; - - CHK_ARGC(3, 0); - if (sscanf(argv[1], "%d", &fd) != 1) { - return -1; - } - else { - for (i = 2; i < argc; i++) { - len = strlen(argv[i]); - if (uffs_write(fd, argv[i], len) != len) { - ret = -1; - break; - } - } - } - - if (ret == 0) - cli_env_set('1', len); - - return ret; -} - -/** - * read and check seq file - * t_check_seq - */ -static int cmd_tcheck_seq(int argc, char *argv[]) -{ - int fd; - int len, size; - int ret = 0, r_ret = 0; - long pos; - u8 buf[MAX_TEST_BUF_LEN]; - int i; - u8 x; - - CHK_ARGC(3, 3); - - if (sscanf(argv[1], "%d", &fd) != 1) { - return -1; - } - - if (sscanf(argv[2], "%d", &len) != 1) { - return -1; - } - - pos = uffs_tell(fd); - while (len > 0) { - size = (len > sizeof(buf) ? sizeof(buf) : len); - if ((r_ret = uffs_read(fd, buf, size)) < 0) { - MSGLN("Read fail! fd = %d, size = %d, pos = %ld", fd, size, pos); - ret = -1; - break; - } - - // check seq - for (i = 0; i < r_ret; i++) { - x = (pos + SEQ_INIT + i) % SEQ_MOD_LEN; - if (buf[i] != x) { - MSGLN("Check fail! fd = %d, pos = %ld (expect 0x%02x but 0x%02x)\n", fd, pos + i, x, buf[i]); - ret = -1; - break; - } - } - - if (ret < 0) - break; - - len -= r_ret; - pos += r_ret; - } - - return ret; -} - - - -/** - * write random seq to file - * t_write_seq - */ -static int cmd_twrite_seq(int argc, char *argv[]) -{ - int fd; - int len = 0, size = 0; - long pos = 0; - int ret = 0, w_ret = 0; - u8 buf[MAX_TEST_BUF_LEN]; - - CHK_ARGC(3, 3); - if (sscanf(argv[1], "%d", &fd) != 1) { - return -1; - } - - if (sscanf(argv[2], "%d", &len) != 1) { - return -1; - } - - pos = uffs_tell(fd); - while (len > 0) { - size = (len < sizeof(buf) ? len : sizeof(buf)); - memcp_seq(buf, size, pos); - if ((w_ret = uffs_write(fd, buf, size)) < 0) { - MSGLN("write fail! fd = %d, size = %d, pos = %ld", fd, size, pos); - ret = -1; - break; - } - pos += w_ret; - len -= w_ret; - } - - if (ret == 0) - cli_env_set('1', len); - - return ret; -} - - -/** - * read and check file - * t_read - */ -static int cmd_tread(int argc, char *argv[]) -{ - int fd; - int len, n; - int ret = 0; - char buf[64]; - char *p; - - CHK_ARGC(3, 3); - - if (sscanf(argv[1], "%d", &fd) != 1) { - return -1; - } - else { - len = strlen(argv[2]); - n = 0; - p = argv[2]; - while (n < len) { - n = (len > sizeof(buf) ? sizeof(buf) : len); - if (uffs_read(fd, buf, n) != n || - memcmp(buf, p, n) != 0) { - ret = -1; - break; - } - len -= n; - p += n; - } - } - - return ret; -} - - -static void do_dump_page(uffs_Device *dev, uffs_Buf *buf) -{ - int i, j; - const int line = 16; - struct uffs_MiniHeaderSt *header = (struct uffs_MiniHeaderSt *)buf->header; - MSG(" header.status = %d\n", header->status); - if (header->status != 0xFF) { - for (i = 0; i < 64; i += line) { - MSG(" "); - for (j = 0; j < line; j++) - MSG("%02X ", buf->header[i+j]); - MSG("\n"); - } - MSG("\n"); - } -} - -static void do_dump_tag(uffs_Device *dev, uffs_Tags *tag) -{ - MSG(" tag sealed: %s\n", TAG_IS_SEALED(tag) ? "yes" : "no"); - if (TAG_IS_GOOD(tag)) { - if (TAG_IS_DIRTY(tag)) { - MSG(" block_ts = %d\n", tag->s.block_ts); - MSG(" type = %d\n", tag->s.type); - MSG(" dirty = %d\n", tag->s.dirty); - MSG(" page_id = %d\n", tag->s.page_id); - MSG(" serial = %d\n", tag->s.serial); - MSG(" parent = %d\n", tag->s.parent); - MSG(" data_len = %d\n", tag->s.data_len); - } - else { - MSG(" tag is GOOD but NOT DIRTY !!!???\n"); - } - } - else if (TAG_IS_SEALED(tag)) { - MSG(" tag is INVALID\n"); - } -} - -static void do_dump_device(uffs_Device *dev) -{ - URET ret; - int block, page; - uffs_Tags tag; - uffs_Buf *buf; - - buf = uffs_BufClone(dev, NULL); - if (buf == NULL) { - MSGLN("Can't clone buf"); - return; - } - - for (block = dev->par.start; block <= dev->par.end; block++) { - MSG("---- block %d ----\n", block); - for (page = 0; page < dev->attr->pages_per_block; page++) { - MSG(" == page %d ==\n", page); - ret = uffs_FlashReadPage(dev, block, page, buf, U_FALSE); - if (UFFS_FLASH_HAVE_ERR(ret)) { - MSG(" !!! Read page failed, ret = %d !!!\n", ret); - } - else { - do_dump_page(dev, buf); - if (buf->header[0] != 0xFF) { - ret = uffs_FlashReadPageTag(dev, block, page, &tag); - if (UFFS_FLASH_HAVE_ERR(ret)) { - MSG(" !!! Read TAG failed, ret = %d !!!\n", ret); - } - else { - do_dump_tag(dev, &tag); - } - } - } - } - } - uffs_BufFreeClone(dev, buf); -} - -static int cmd_dump(int argc, char *argv[]) -{ - const char *mount = "/"; - uffs_Device *dev; - - if (argc > 1) { - mount = argv[1]; - } - - MSGLN("Dumping %s ... ", mount); - - dev = uffs_GetDeviceFromMountPoint(mount); - if (dev == NULL) { - MSGLN("Can't get device from mount point."); - } - else { - do_dump_device(dev); - uffs_PutDevice(dev); - } - - return 0; -} - -static int cmd_apisrv(int argc, char *argv[]) -{ - return api_server_start(); -} - -static const struct cli_command test_cmds[] = -{ - { cmd_t1, "t1", "", "test 1" }, - { cmd_t2, "t2", NULL, "test 2" }, - { cmd_t3, "t3", " []", "test 3" }, - { cmd_t4, "t4", NULL, "test 4" }, - { cmd_t5, "t5", "", "test 5" }, - { cmd_TestPageReadWrite, "t_pgrw", NULL, "test page read/write" }, - { cmd_TestFormat, "t_format", NULL, "test format file system" }, - { cmd_TestPopulateFiles, "t_pfs", "[ []]", "test populate files under " }, - { cmd_VerifyFile, "t_vf", " []", "verify file" }, - - { cmd_topen, "t_open", " ", "open file, fd save to $1", }, - { cmd_tread, "t_read", " ", "read and check against ", }, - { cmd_tcheck_seq, "t_check_seq", " ", "read seq file and check", }, - { cmd_twrite, "t_write", " [...]", "write ", }, - { cmd_twrite_seq, "t_write_seq", " ", "write seq file ", }, - { cmd_tseek, "t_seek", " []", "seek file pointer to from ", }, - { cmd_tclose, "t_close", "", "close ", }, - { cmd_dump, "dump", "", "dump ", }, - - { cmd_apisrv, "apisrv", NULL, "start API test server", }, - - { NULL, NULL, NULL, NULL } -}; - -static struct cli_commandset test_cmdset = { - test_cmds, -}; - -struct cli_commandset * get_test_cmds() -{ - return &test_cmdset; -}; - - - diff --git a/components/dfs/filesystems/uffs/src/emu/uffs_fileem.c b/components/dfs/filesystems/uffs/src/emu/uffs_fileem.c deleted file mode 100644 index 1f66cdf846..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/uffs_fileem.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fileem.c - * \brief emulate uffs file system - * \author Ricky Zheng, created 9th May, 2005 - */ - - -#include -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs_fileem.h" - -#define PFX "femu: " -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - - -static struct uffs_StorageAttrSt g_femu_storage = {0}; - -static struct uffs_FileEmuSt g_femu_private = {0}; - - -struct uffs_StorageAttrSt * femu_GetStorage() -{ - return &g_femu_storage; -} - -struct uffs_FileEmuSt *femu_GetPrivate() -{ - return &g_femu_private; -} - -URET femu_InitDevice(uffs_Device *dev) -{ - uffs_FileEmu *emu = femu_GetPrivate(); - - // setup device storage attr and private data structure. - // all femu partition share one storage attribute - - dev->attr = femu_GetStorage(); - dev->attr->_private = (void *) emu; - - // setup flash driver operations, according to the ecc option. - switch(dev->attr->ecc_opt) { - case UFFS_ECC_NONE: - case UFFS_ECC_SOFT: - dev->ops = &g_femu_ops_ecc_soft; - break; - case UFFS_ECC_HW: - dev->ops = &g_femu_ops_ecc_hw; - break; - case UFFS_ECC_HW_AUTO: - dev->ops = &g_femu_ops_ecc_hw_auto; - break; - default: - break; - } - -#ifdef UFFS_FEMU_ENABLE_INJECTION - // setup wrap functions, for inject ECC errors, etc. - // check wrap_inited so that multiple devices can share the same driver - if (!emu->wrap_inited) { - femu_setup_wrapper_functions(dev); - emu->wrap_inited = U_TRUE; - } -#endif - - return U_SUCC; -} - -/* Nothing to do here */ -URET femu_ReleaseDevice(uffs_Device *dev) -{ - return U_SUCC; -} - - -///////////////////////////////////////////////////////////////////////////////// diff --git a/components/dfs/filesystems/uffs/src/emu/uffs_fileem.h b/components/dfs/filesystems/uffs/src/emu/uffs_fileem.h deleted file mode 100644 index 8be7f3e838..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/uffs_fileem.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fileem.h - * \brief Emulate NAND flash with host file. - * \author Ricky Zheng - */ - -#ifndef _UFFS_FILEEM_H_ -#define _UFFS_FILEEM_H_ - -#include "uffs/uffs_device.h" - -#define UFFS_FEMU_FILE_NAME "uffsemfile.bin" - -#define UFFS_FEMU_MAX_BLOCKS (1024 * 16) // maximum 16K blocks - -#define UFFS_FEMU_ENABLE_INJECTION // enable bad block & ecc error injection - -extern struct uffs_FlashOpsSt g_femu_ops_ecc_soft; // for software ECC or no ECC. -extern struct uffs_FlashOpsSt g_femu_ops_ecc_hw; // for hardware ECC -extern struct uffs_FlashOpsSt g_femu_ops_ecc_hw_auto; // for auto hardware ECC - -#define PAGE_DATA_WRITE_COUNT_LIMIT 1 -#define PAGE_SPARE_WRITE_COUNT_LIMIT 1 - -typedef struct uffs_FileEmuSt { - int initCount; - FILE *fp; - FILE *dump_fp; - u8 *em_monitor_page; // page write monitor - u8 * em_monitor_spare; // spare write monitor - u32 *em_monitor_block; // block erease monitor - const char *emu_filename; -#ifdef UFFS_FEMU_ENABLE_INJECTION - struct uffs_FlashOpsSt ops_orig; - UBOOL wrap_inited; -#endif -} uffs_FileEmu; - -/* file emulator device init/release entry */ -URET femu_InitDevice(uffs_Device *dev); -URET femu_ReleaseDevice(uffs_Device *dev); - -struct uffs_StorageAttrSt * femu_GetStorage(void); -struct uffs_FileEmuSt * femu_GetPrivate(void); - -#ifdef UFFS_FEMU_ENABLE_INJECTION -void femu_setup_wrapper_functions(uffs_Device *dev); -#endif - -/* internal used functions, shared by all ecc option implementations */ -int femu_InitFlash(uffs_Device *dev); -int femu_ReleaseFlash(uffs_Device *dev); -int femu_EraseBlock(uffs_Device *dev, u32 blockNumber); - -#endif - diff --git a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw.c b/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw.c deleted file mode 100644 index c7781ebe66..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2010 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fileem_ecc_hw.c - * \brief emulate uffs file system for hardware ECC. - * - * In this emulator, we call 'uffs_FlashMakeSpare()' to do the layout job - * and call 'uffs_EccMake()' to calculate ECC. - * - * \author Ricky Zheng @ Oct, 2010 - */ - -#include -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs_fileem.h" -#include "uffs/uffs_ecc.h" - -#define PFX "femu: " -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - -static int femu_hw_WritePageWithLayout(uffs_Device *dev, u32 block, u32 page, - const u8 *data, int data_len, const u8 *ecc, const uffs_TagStore *ts) -{ - int written; - int abs_page; - int full_page_size; - uffs_FileEmu *emu; - struct uffs_StorageAttrSt *attr = dev->attr; - u8 spare[UFFS_MAX_SPARE_SIZE]; - u8 ecc_buf[UFFS_MAX_ECC_SIZE]; - int spare_len; - - - emu = (uffs_FileEmu *)(dev->attr->_private); - - if (!emu || !(emu->fp)) { - goto err; - } - - abs_page = attr->pages_per_block * block + page; - full_page_size = attr->page_data_size + attr->spare_size; - - if (data && data_len > 0) { - if (data_len > attr->page_data_size) - goto err; - - emu->em_monitor_page[abs_page]++; - if (emu->em_monitor_page[abs_page] > PAGE_DATA_WRITE_COUNT_LIMIT) { - MSG("Warrning: block %d page %d exceed it's maximum write time!", block, page); - goto err; - } - - fseek(emu->fp, abs_page * full_page_size, SEEK_SET); - - written = fwrite(data, 1, data_len, emu->fp); - - if (written != data_len) { - MSG("write page I/O error ?"); - goto err; - } - - dev->st.page_write_count++; - dev->st.io_write += written; - - } - - if (ts) { - - emu->em_monitor_spare[abs_page]++; - if (emu->em_monitor_spare[abs_page] > PAGE_SPARE_WRITE_COUNT_LIMIT) { - MSG("Warrning: block %d page %d (spare) exceed it's maximum write time!", block, page); - goto err; - } - - if (!uffs_Assert(data != NULL, "BUG: Write spare without data ?")) - goto err; - - uffs_EccMake(data, data_len, ecc_buf); - uffs_FlashMakeSpare(dev, ts, ecc_buf, spare); - spare_len = dev->mem.spare_data_size; - - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size, SEEK_SET); - written = fwrite(spare, 1, spare_len, emu->fp); - if (written != spare_len) { - MSG("write spare I/O error ?"); - goto err; - } - - dev->st.spare_write_count++; - dev->st.io_write += written; - } - - if (data == NULL && ts == NULL) { - // mark bad block - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size + attr->block_status_offs, SEEK_SET); - written = fwrite("\0", 1, 1, emu->fp); - if (written != 1) { - MSG("write bad block mark I/O error ?"); - goto err; - } - dev->st.io_write++; - } - - fflush(emu->fp); - return UFFS_FLASH_NO_ERR; -err: - fflush(emu->fp); - return UFFS_FLASH_IO_ERR; -} - - -static URET femu_hw_ReadPageWithLayout(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc, - uffs_TagStore *ts, u8 *ecc_store) -{ - int nread; - uffs_FileEmu *emu; - int abs_page; - int full_page_size; - struct uffs_StorageAttrSt *attr = dev->attr; - unsigned char status; - u8 spare[UFFS_MAX_SPARE_SIZE]; - int spare_len; - - emu = (uffs_FileEmu *)(dev->attr->_private); - - if (!emu || !(emu->fp)) { - goto err; - } - - abs_page = attr->pages_per_block * block + page; - full_page_size = attr->page_data_size + attr->spare_size; - - if (data && data_len > 0) { - if (data_len > attr->page_data_size) - goto err; - - fseek(emu->fp, abs_page * full_page_size, SEEK_SET); - nread = fread(data, 1, data_len, emu->fp); - - if (nread != data_len) { - MSG("read page I/O error ?"); - goto err; - } - dev->st.io_read += nread; - dev->st.page_read_count++; - - if (ecc) { - // calculate ECC for data - uffs_EccMake(data, data_len, ecc); - } - } - - if (ts) { - - spare_len = dev->mem.spare_data_size; - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size, SEEK_SET); - nread = fread(spare, 1, spare_len, emu->fp); - - if (nread != spare_len) { - MSG("read page spare I/O error ?"); - goto err; - } - - // unload ts and ecc from spare - uffs_FlashUnloadSpare(dev, spare, ts, ecc_store); - - dev->st.io_read += nread; - dev->st.spare_read_count++; - } - - if (data == NULL && ts == NULL) { - // read bad block mark - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size + attr->block_status_offs, SEEK_SET); - nread = fread(&status, 1, 1, emu->fp); - - if (nread != 1) { - MSG("read badblock mark I/O error ?"); - goto err; - } - dev->st.io_read++; - - return status == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK; - } - - return UFFS_FLASH_NO_ERR; -err: - return UFFS_FLASH_IO_ERR; -} - - -uffs_FlashOps g_femu_ops_ecc_hw = { - femu_InitFlash, // InitFlash() - femu_ReleaseFlash, // ReleaseFlash() - NULL, // ReadPage() - femu_hw_ReadPageWithLayout, // ReadPageWithLayout() - NULL, // WritePage() - femu_hw_WritePageWithLayout,// WritePageWithLayout() - NULL, // IsBadBlock(), let UFFS take care of it. - NULL, // MarkBadBlock(), let UFFS take care of it. - femu_EraseBlock, // EraseBlock() -}; diff --git a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw_auto.c b/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw_auto.c deleted file mode 100644 index 31fbb28c95..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_hw_auto.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2010 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fileem_ecc_hw_auto.c - * - * \brief Emulate uffs file system for auto hardware ECC or RS error collection. - * - * This emulator emulate LPC32x0 MLC NAND controller which generate 10 bytes - * Reed-Solomon error correction code (RS-ECC) for every 518 bytes data. - * - * For small page MLC have 16 bytes spare area leves only 6 bytes for 'meta-data', - * no enough room for UFFS's 8 bytes tag and bad block mark. For this reason, - * we adjust page data/spare boundary to 508/20. - * - * This emulator does not calculate real RS-ECC code, instead, we use software ECC - * to calculate 6 bytes ECC code, so this solution does not have the same error - * correcting cabability of RS-ECC. - * - * Note: the MLC controller strictly require sequencial access to serial data buffer. - * - * \author Ricky Zheng @ Oct, 2010 - */ - -#include -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_ecc.h" -#include "uffs_fileem.h" - -#define PFX "femu: " -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - -#define RS_ECC_SIZE 10 -#define PAGE_DATA_SIZE 508 -#define PAGE_SPARE_SIZE 20 -#define PAGE_FULL_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE) -static u8 g_sdata_buf[PAGE_FULL_SIZE]; // emulating LPC32x0's 528-bytes serial data buffer - -static int g_sdata_buf_pointer = 0; - -static void start_sdata_access() -{ - g_sdata_buf_pointer = 0; -} - -static void feed_sdata(const u8 *data, int len) -{ - if (!uffs_Assert(g_sdata_buf_pointer + len <= sizeof(g_sdata_buf), "BUG: Serial Data Buffer overflow !!")) - return; - - if (data) - memcpy(g_sdata_buf + g_sdata_buf_pointer, data, len); - g_sdata_buf_pointer += len; -} - -static void feed_sdata_constant(u8 val, int num) -{ - if (!uffs_Assert(g_sdata_buf_pointer + num <= sizeof(g_sdata_buf), "BUG: Serial Data Buffer overflow !!")) - return; - - memset(g_sdata_buf + g_sdata_buf_pointer, val, num); - g_sdata_buf_pointer += num; -} - -static void drain_sdata(u8 *data, int len) -{ - if (!uffs_Assert( (int)sizeof(g_sdata_buf) - g_sdata_buf_pointer >= len, "BUG: Serial Data Buffer overdrain !!")) - return; - - if (data) - memcpy(data, g_sdata_buf + g_sdata_buf_pointer, len); - g_sdata_buf_pointer += len; -} - -static int load_sdata(uffs_Device *dev, int block, int page) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - int abs_page; - struct uffs_StorageAttrSt *attr = dev->attr; - int nread; - int ret; - u8 ecc_buf[RS_ECC_SIZE]; - u8 *ecc_store; - - abs_page = attr->pages_per_block * block + page; - - fseek(emu->fp, abs_page * PAGE_FULL_SIZE, SEEK_SET); - nread = fread(g_sdata_buf, 1, PAGE_FULL_SIZE, emu->fp); - g_sdata_buf_pointer = 0; - - ret = ((nread == PAGE_FULL_SIZE) ? UFFS_FLASH_NO_ERR : UFFS_FLASH_IO_ERR); - - if (ret == UFFS_FLASH_NO_ERR) { - - // Perform ECC check & correction - // In the real world, this is done by MLC controller hardware - memset(ecc_buf, 0xFF, RS_ECC_SIZE); - uffs_EccMake(g_sdata_buf, attr->page_data_size, ecc_buf); - - ecc_store = g_sdata_buf + PAGE_FULL_SIZE - RS_ECC_SIZE; - - ret = uffs_EccCorrect(g_sdata_buf, attr->page_data_size, ecc_store, ecc_buf); - - ret = (ret < 0 ? UFFS_FLASH_ECC_FAIL : - (ret > 0 ? UFFS_FLASH_ECC_OK : UFFS_FLASH_NO_ERR)); - - } - - return ret; -} - -static int program_sdata(uffs_Device *dev, int block, int page) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - int abs_page; - struct uffs_StorageAttrSt *attr = dev->attr; - u8 ecc_buf[RS_ECC_SIZE]; - int writtern = 0; - - // In the real world, MLC controller will generate RS-ECC code in serial data buffer - // and might start auto programing NAND flash. Here, we use software ECC to emulate RS-ECC. - memset(ecc_buf, 0xFF, sizeof(ecc_buf)); - uffs_EccMake(g_sdata_buf, attr->page_data_size, ecc_buf); - feed_sdata(ecc_buf, RS_ECC_SIZE); - - if (!uffs_Assert(g_sdata_buf_pointer == PAGE_FULL_SIZE, "Serial Data Buffer is not fully filled !!")) - goto ext; - - abs_page = attr->pages_per_block * block + page; - - fseek(emu->fp, abs_page * PAGE_FULL_SIZE, SEEK_SET); - writtern = fwrite(g_sdata_buf, 1, PAGE_FULL_SIZE, emu->fp); -ext: - return (writtern == PAGE_FULL_SIZE) ? UFFS_FLASH_NO_ERR : UFFS_FLASH_IO_ERR; -} - - -static int femu_hw_auto_InitFlash(uffs_Device *dev) -{ - struct uffs_StorageAttrSt *attr = dev->attr; - - // now this is a good chance to adjust page data/spare boundary - if (attr->page_data_size + attr->spare_size != PAGE_FULL_SIZE) { - MSGLN("This emulator emulates only for page size %d bytes !", PAGE_FULL_SIZE); - return -1; - } - if (attr->spare_size < PAGE_SPARE_SIZE) { - attr->page_data_size -= (PAGE_SPARE_SIZE - attr->spare_size); - attr->spare_size = PAGE_SPARE_SIZE; - MSGLN("Adjust page data/spare boundary to %d/%d", attr->page_data_size, attr->spare_size); - } - - // and fix ECC size - attr->ecc_size = RS_ECC_SIZE; - MSGLN("Adjust ECC size to %d bytes", attr->ecc_size); - - return femu_InitFlash(dev); -} - - -static int femu_hw_auto_WritePageWithLayout(uffs_Device *dev, u32 block, u32 page, - const u8 *data, int data_len, const u8 *ecc, const uffs_TagStore *ts) -{ - int abs_page; - uffs_FileEmu *emu; - struct uffs_StorageAttrSt *attr = dev->attr; - u8 spare[PAGE_SPARE_SIZE]; - int ret = UFFS_FLASH_IO_ERR; - - emu = (uffs_FileEmu *)(dev->attr->_private); - - if (!emu || !(emu->fp)) { - goto err; - } - - abs_page = attr->pages_per_block * block + page; - - start_sdata_access(); - - dev->st.page_write_count++; - dev->st.spare_write_count++; - dev->st.io_write += PAGE_FULL_SIZE; - - if (data || ts) { - // normal page write - if (data && data_len > 0) { - if (data_len > attr->page_data_size) - goto err; - - emu->em_monitor_page[abs_page]++; - if (emu->em_monitor_page[abs_page] > PAGE_DATA_WRITE_COUNT_LIMIT) { - MSGLN("Warrning: block %d page %d exceed it's maximum write time!", block, page); - goto err; - } - - // Copy data to serial data buffer - feed_sdata(data, data_len); - - // Pad the rest data as 0xFF - feed_sdata_constant(0xFF, attr->page_data_size - data_len); - - } - else { - // We still need to feed data to serial data buffer to make MLC controller happy - // The current UFFS won't write ts only, so we'll never run to here. - feed_sdata_constant(0xFF, attr->page_data_size); - } - - if (ts) { - - emu->em_monitor_spare[abs_page]++; - if (emu->em_monitor_spare[abs_page] > PAGE_SPARE_WRITE_COUNT_LIMIT) { - MSGLN("Warrning: block %d page %d (spare) exceed it's maximum write time!", block, page); - goto err; - } - - memset(spare, 0xFF, sizeof(spare)); - uffs_FlashMakeSpare(dev, ts, NULL, spare); // do not pack ECC, as MLC controller will - // automatically write RS-ECC to the latest 10 bytes. - - // feed spare data to serial data buffer - feed_sdata(spare, PAGE_SPARE_SIZE - RS_ECC_SIZE); - } - } - else { - // mark bad block - - // feed data to serial data buffer to make MLC controller happy - feed_sdata_constant(0xFF, attr->page_data_size); - - memset(spare, 0xFF, sizeof(spare)); - spare[attr->block_status_offs] = 0; - - // feed spare data to serial data buffer - feed_sdata(spare, PAGE_SPARE_SIZE - RS_ECC_SIZE); - - dev->st.io_write++; - } - - // now, program serial data buffer to NAND flash - ret = program_sdata(dev, block, page); - - fflush(emu->fp); - return ret; -err: - fflush(emu->fp); - return ret; -} - - -static URET femu_hw_auto_ReadPageWithLayout(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc, - uffs_TagStore *ts, u8 *ecc_store) -{ - uffs_FileEmu *emu; - int abs_page; - struct uffs_StorageAttrSt *attr = dev->attr; - unsigned char status; - u8 spare[PAGE_SPARE_SIZE]; - int ret = UFFS_FLASH_IO_ERR; - - emu = (uffs_FileEmu *)(dev->attr->_private); - - if (!emu || !(emu->fp)) { - goto ext; - } - - abs_page = attr->pages_per_block * block + page; - - // now load full page to serial data buffer - ret = load_sdata(dev, block, page); - if (ret != UFFS_FLASH_NO_ERR) - goto ext; - - start_sdata_access(); - - dev->st.io_read += PAGE_FULL_SIZE; - dev->st.page_read_count++; - dev->st.spare_read_count++; - - if (data || ts) { - - if (data && data_len > 0) { - if (data_len > attr->page_data_size) - goto ext; - - drain_sdata(data, data_len); - } - - if (ts) { - if (g_sdata_buf_pointer < attr->page_data_size) - drain_sdata(NULL, attr->page_data_size - g_sdata_buf_pointer); - - drain_sdata(spare, PAGE_SPARE_SIZE - RS_ECC_SIZE); - - // unload ts from spare - uffs_FlashUnloadSpare(dev, spare, ts, NULL); - } - } - else { - // read bad block mark - drain_sdata(NULL, attr->page_data_size + attr->block_status_offs - 1); - drain_sdata(&status, 1); - - ret = (status == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK); - } - -ext: - return ret; -} - - -uffs_FlashOps g_femu_ops_ecc_hw_auto = { - femu_hw_auto_InitFlash, // InitFlash() - femu_ReleaseFlash, // ReleaseFlash() - NULL, // ReadPage() - femu_hw_auto_ReadPageWithLayout, // ReadPageWithLayout() - NULL, // WritePage() - femu_hw_auto_WritePageWithLayout, // WritePageWithLayout() - NULL, // IsBadBlock(), let UFFS take care of it. - NULL, // MarkBadBlock(), let UFFS take care of it. - femu_EraseBlock, // EraseBlock() -}; diff --git a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_soft.c b/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_soft.c deleted file mode 100644 index 0a24c1cf3b..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_soft.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2010 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fileem_ecc_soft.c - * \brief emulate uffs file system for software ECC - * \author Ricky Zheng @ Oct, 2010 - */ - -#include -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_flash.h" -#include "uffs_fileem.h" - -#define PFX "femu: " -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - -static int femu_WritePage(uffs_Device *dev, u32 block, u32 page_num, - const u8 *data, int data_len, const u8 *spare, int spare_len) -{ - int written; - int abs_page; - int full_page_size; - uffs_FileEmu *emu; - struct uffs_StorageAttrSt *attr = dev->attr; - - emu = (uffs_FileEmu *)(dev->attr->_private); - - if (!emu || !(emu->fp)) { - goto err; - } - - abs_page = attr->pages_per_block * block + page_num; - full_page_size = attr->page_data_size + attr->spare_size; - - if (data && data_len > 0) { - if (data_len > attr->page_data_size) - goto err; - - emu->em_monitor_page[abs_page]++; - if (emu->em_monitor_page[abs_page] > PAGE_DATA_WRITE_COUNT_LIMIT) { - MSGLN("Warrning: block %d page %d exceed it's maximum write time!", block, page_num); - goto err; - } - - fseek(emu->fp, abs_page * full_page_size, SEEK_SET); - - written = fwrite(data, 1, data_len, emu->fp); - - if (written != data_len) { - MSGLN("write page I/O error ?"); - goto err; - } - - dev->st.page_write_count++; - dev->st.io_write += written; - } - - if (spare && spare_len > 0) { - if (spare_len > attr->spare_size) - goto err; - - emu->em_monitor_spare[abs_page]++; - if (emu->em_monitor_spare[abs_page] > PAGE_SPARE_WRITE_COUNT_LIMIT) { - MSGLN("Warrning: block %d page %d (spare) exceed it's maximum write time!", block, page_num); - goto err; - } - - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size, SEEK_SET); - written = fwrite(spare, 1, spare_len, emu->fp); - if (written != spare_len) { - MSGLN("write spare I/O error ?"); - goto err; - } - - dev->st.spare_write_count++; - dev->st.io_write += written; - } - - if (data == NULL && spare == NULL) { - // mark bad block - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size + attr->block_status_offs, SEEK_SET); - written = fwrite("\0", 1, 1, emu->fp); - if (written != 1) { - MSGLN("write bad block mark I/O error ?"); - goto err; - } - dev->st.io_write++; - } - - fflush(emu->fp); - return UFFS_FLASH_NO_ERR; -err: - fflush(emu->fp); - return UFFS_FLASH_IO_ERR; -} - - -static URET femu_ReadPage(uffs_Device *dev, u32 block, u32 page_num, u8 *data, int data_len, u8 *ecc, - u8 *spare, int spare_len) -{ - int nread; - uffs_FileEmu *emu; - int abs_page; - int full_page_size; - struct uffs_StorageAttrSt *attr = dev->attr; - unsigned char status; - - emu = (uffs_FileEmu *)(dev->attr->_private); - - if (!emu || !(emu->fp)) { - goto err; - } - - abs_page = attr->pages_per_block * block + page_num; - full_page_size = attr->page_data_size + attr->spare_size; - - if (data && data_len > 0) { - if (data_len > attr->page_data_size) - goto err; - - fseek(emu->fp, abs_page * full_page_size, SEEK_SET); - nread = fread(data, 1, data_len, emu->fp); - - if (nread != data_len) { - MSGLN("read page I/O error ?"); - goto err; - } - dev->st.io_read += nread; - dev->st.page_read_count++; - } - - if (spare && spare_len > 0) { - if (spare_len > attr->spare_size) - goto err; - - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size, SEEK_SET); - nread = fread(spare, 1, spare_len, emu->fp); - - if (nread != spare_len) { - MSGLN("read page spare I/O error ?"); - goto err; - } - dev->st.io_read += nread; - dev->st.spare_read_count++; - } - - if (data == NULL && spare == NULL) { - // read bad block mark - fseek(emu->fp, abs_page * full_page_size + attr->page_data_size + attr->block_status_offs, SEEK_SET); - nread = fread(&status, 1, 1, emu->fp); - - if (nread != 1) { - MSGLN("read badblock mark I/O error ?"); - goto err; - } - dev->st.io_read++; - - return status == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK; - } - - return UFFS_FLASH_NO_ERR; -err: - return UFFS_FLASH_IO_ERR; -} - - -uffs_FlashOps g_femu_ops_ecc_soft = { - femu_InitFlash, // InitFlash() - femu_ReleaseFlash, // ReleaseFlash() - femu_ReadPage, // ReadPage() - NULL, // ReadPageWithLayout - femu_WritePage, // WritePage() - NULL, // WritePageWithLayout - NULL, // IsBadBlock(), let UFFS take care of it. - NULL, // MarkBadBlock(), let UFFS take care of it. - femu_EraseBlock, // EraseBlock() -}; diff --git a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_share.c b/components/dfs/filesystems/uffs/src/emu/uffs_fileem_share.c deleted file mode 100644 index 6bd759bb82..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_share.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fileem_share.c - * \brief emulate uffs file system, shared functions - * \author Ricky Zheng, created Nov, 2010 - */ - - -#include -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs_fileem.h" - -#define PFX "femu: " - -/****************************************************************/ -/* Shared flash driver functions: */ -/* */ -/* femu_InitFlash(), femu_ReleaseFlash(), femu_EraseBlock() */ -/* */ -/****************************************************************/ - -static u8 g_page_buf[UFFS_MAX_PAGE_SIZE + UFFS_MAX_SPARE_SIZE]; - -/* - * Create emulator disk, initialise monitors, inject manufacture bad blocks, etc. - * - */ -int femu_InitFlash(uffs_Device *dev) -{ - int i; - int fSize; - int written; - u8 * p = g_page_buf; - uffs_FileEmu *emu; - - struct uffs_StorageAttrSt *attr = dev->attr; - - int full_page_size = attr->page_data_size + attr->spare_size; - int total_pages = attr->total_blocks * attr->pages_per_block; - - emu = (uffs_FileEmu *)(dev->attr->_private); - - if (emu->initCount > 0) { - emu->initCount++; - return 0; - } - - if (emu->emu_filename == NULL) - emu->emu_filename = UFFS_FEMU_FILE_NAME; - - uffs_Perror(UFFS_MSG_NORMAL, "femu device init."); - - emu->em_monitor_page = (u8 *) malloc(sizeof(emu->em_monitor_page[0]) * total_pages); - if (!emu->em_monitor_page) - return -1; - emu->em_monitor_spare = (u8 *) malloc(sizeof(emu->em_monitor_spare[0]) * total_pages); - if (!emu->em_monitor_spare) - return -1; - - emu->em_monitor_block = (u32 *) malloc(sizeof(emu->em_monitor_block[0]) * attr->total_blocks); - if (!emu->em_monitor_block) - return -1; - - //clear monitor - memset(emu->em_monitor_page, 0, sizeof(emu->em_monitor_page[0]) * total_pages); - memset(emu->em_monitor_spare, 0, sizeof(emu->em_monitor_spare[0]) * total_pages); - memset(emu->em_monitor_block, 0, sizeof(emu->em_monitor_block[0]) * attr->total_blocks); - - emu->fp = fopen(emu->emu_filename, "rb"); - if (emu->fp == NULL) { - emu->fp = fopen(emu->emu_filename, "ab+"); - if (emu->fp == NULL) { - printf(PFX"Failed to create uffs emulation file."); - return -1; - } - - fseek(emu->fp, 0, SEEK_END); - fSize = ftell(emu->fp); - - if (fSize < total_pages * full_page_size) { - printf("Creating uffs emulation file\n"); - fseek(emu->fp, 0, SEEK_SET); - memset(p, 0xff, full_page_size); - for (i = 0; i < total_pages; i++) { - written = fwrite(p, 1, full_page_size, emu->fp); - if (written != full_page_size) { - printf("Write failed\n"); - fclose(emu->fp); - emu->fp = NULL; - return -1; - } - } - } - } - - fflush(emu->fp); - fclose(emu->fp); - - emu->fp = fopen(emu->emu_filename, "rb+"); - if (emu->fp == NULL) { - printf(PFX"Can't open emulation file.\n"); - return -1; - } - - emu->initCount++; - - return 0; -} - -/* - * Release resources - */ -int femu_ReleaseFlash(uffs_Device *dev) -{ - uffs_FileEmu *emu; - - emu = (uffs_FileEmu *)(dev->attr->_private); - - emu->initCount--; - - if (emu->initCount == 0) { - - uffs_Perror(UFFS_MSG_NORMAL, "femu device release."); - - if (emu->fp) { - fclose(emu->fp); - emu->fp = NULL; - } - - if (emu->em_monitor_page) - free(emu->em_monitor_page); - if (emu->em_monitor_spare) - free(emu->em_monitor_spare); - if (emu->em_monitor_block) - free(emu->em_monitor_block); - emu->em_monitor_page = NULL; - emu->em_monitor_spare = NULL; - emu->em_monitor_block = NULL; - } - - return 0; -} - -int femu_EraseBlock(uffs_Device *dev, u32 blockNumber) -{ - - int i; - u8 * pg = g_page_buf; - int pg_size, pgd_size, sp_size, blks, blk_pgs, blk_size; - uffs_FileEmu *emu; - emu = (uffs_FileEmu *)(dev->attr->_private); - if (!emu || !(emu->fp)) - goto err; - - pg_size = dev->attr->page_data_size + dev->attr->spare_size; - pgd_size = dev->attr->page_data_size; - sp_size = dev->attr->spare_size; - blk_pgs = dev->attr->pages_per_block; - blks = dev->attr->total_blocks; - blk_size = dev->attr->page_data_size * dev->attr->pages_per_block; - - printf("femu: erase block %d\n", blockNumber); - - if ((int)blockNumber >= blks) { - printf("Attempt to erase non-existant block %d\n",blockNumber); - goto err; - } - else { - - //clear this block monitors - memset(emu->em_monitor_page + (blockNumber * blk_pgs), - 0, - blk_pgs * sizeof(u8)); - memset(emu->em_monitor_spare + (blockNumber * blk_pgs), - 0, - blk_pgs * sizeof(u8)); - - emu->em_monitor_block[blockNumber]++; - - memset(pg, 0xff, (pgd_size + sp_size)); - - fseek(emu->fp, blockNumber * blk_pgs * (pgd_size + sp_size), SEEK_SET); - - for (i = 0; i < blk_pgs; i++) { - fwrite(pg, 1, (pgd_size + sp_size), emu->fp); - } - - fflush(emu->fp); - dev->st.block_erase_count++; - } - - return UFFS_FLASH_NO_ERR; -err: - return UFFS_FLASH_IO_ERR; - -} - diff --git a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_wrap.c b/components/dfs/filesystems/uffs/src/emu/uffs_fileem_wrap.c deleted file mode 100644 index 9893aa2eda..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/uffs_fileem_wrap.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fileem_wrap.c - * - * \brief file emulator wrapper functions for injecting bad blocks or ECC errors. - * - * \author Ricky Zheng, created Nov, 2010 - */ - -#include -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs_fileem.h" - -#define PFX "femu: " -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - -// #define UFFS_FEMU_SHOW_FLASH_IO - -#ifdef UFFS_FEMU_ENABLE_INJECTION - -struct uffs_FileEmuBitFlip { - int block; - int page; - int offset; - u8 mask; -}; - -/* simulate bad blocks */ -#define FILEEMU_STOCK_BAD_BLOCKS {5, 180} // bad block come from manufacture -#define FILEEMU_ERASE_BAD_BLOCKS {100, 150} // new bad block discovered when erasing - -/* simulating bit flip */ -#define FILEEMU_WRITE_BIT_FLIP \ - { \ - {20, 2, 10, 1 << 4}, /* block 20, page 2, offset 10, bit 4 */ \ - {24, 4, -3, 1 << 2}, /* block 24, page 4, spare offset 3, bit 2*/ \ - {60, 1, 5, 1 << 3}, /* block 60, page 1, offset 5, bit 3 */ \ - {66, 1, 15, 1 << 7}, /* block 66, page 1, offset 300, bit 7 */ \ - {80, 2, 2, 1 << 1}, /* block 80, page 2, offset 2, bit 1 */ \ - {88, 2, 100, 1 << 5}, /* block 88, page 2, offset 100, bit 5 */ \ - } - - -static int femu_InitFlash_wrap(uffs_Device *dev); - -static int femu_ReadPage_wrap(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc, - u8 *spare, int spare_len); -static int femu_ReadPageWithLayout_wrap(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc, - uffs_TagStore *ts, u8 *ecc_store); -static int femu_WritePage_wrap(uffs_Device *dev, u32 block, u32 page, - const u8 *data, int data_len, const u8 *spare, int spare_len); -static int femu_WritePageWithLayout_wrap(uffs_Device *dev, u32 block, u32 page, const u8* data, int data_len, const u8 *ecc, - const uffs_TagStore *ts); -static int femu_EraseBlock_wrap(uffs_Device *dev, u32 blockNumber); - - -///////////////////////////////////////////////////////////////////////////////// - -void femu_setup_wrapper_functions(uffs_Device *dev) -{ - uffs_FileEmu *emu; - emu = (uffs_FileEmu *)(dev->attr->_private); - - // setup wrap functions, for inject ECC errors, etc. - - memcpy(&emu->ops_orig, dev->ops, sizeof(struct uffs_FlashOpsSt)); - - if (dev->ops->InitFlash) - dev->ops->InitFlash = femu_InitFlash_wrap; - if (dev->ops->EraseBlock) - dev->ops->EraseBlock = femu_EraseBlock_wrap; - if (dev->ops->ReadPage) - dev->ops->ReadPage = femu_ReadPage_wrap; - if (dev->ops->ReadPageWithLayout) - dev->ops->ReadPageWithLayout = femu_ReadPageWithLayout_wrap; - if (dev->ops->WritePage) - dev->ops->WritePage = femu_WritePage_wrap; - if (dev->ops->WritePageWithLayout) - dev->ops->WritePageWithLayout = femu_WritePageWithLayout_wrap; -} - -static int femu_InitFlash_wrap(uffs_Device *dev) -{ - int ret; - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - -#ifdef FILEEMU_STOCK_BAD_BLOCKS - u32 bad_blocks[] = FILEEMU_STOCK_BAD_BLOCKS; - int j; - u8 x = 0; - struct uffs_StorageAttrSt *attr = dev->attr; - int full_page_size = attr->page_data_size + attr->spare_size; - int blk_size = full_page_size * attr->pages_per_block; -#endif - - if (emu->initCount == 0) { - ret = emu->ops_orig.InitFlash(dev); -#ifdef FILEEMU_STOCK_BAD_BLOCKS - if (ret >= 0) { - for (j = 0; j < ARRAY_SIZE(bad_blocks); j++) { - if (bad_blocks[j] < dev->attr->total_blocks) { - printf(" --- manufacture bad block %d ---\n", bad_blocks[j]); - fseek(emu->fp, bad_blocks[j] * blk_size + attr->page_data_size + dev->attr->block_status_offs, SEEK_SET); - fwrite(&x, 1, 1, emu->fp); - } - } - } -#endif - } - else { - ret = emu->ops_orig.InitFlash(dev); - } - - return ret; -} - -static int femu_ReadPage_wrap(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc, - u8 *spare, int spare_len) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - -#ifdef UFFS_FEMU_SHOW_FLASH_IO - if (data || spare) { - MSG(PFX " Read block %d page %d", block, page); - if (data) - MSG(" DATA[%d]", data_len); - if (spare) - MSG(" SPARE[%d]", spare_len); - MSG(TENDSTR); - } -#endif - return emu->ops_orig.ReadPage(dev, block, page, data, data_len, ecc, spare, spare_len); -} - -static int femu_ReadPageWithLayout_wrap(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc, - uffs_TagStore *ts, u8 *ecc_store) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - -#ifdef UFFS_FEMU_SHOW_FLASH_IO - if (data || ts) { - MSG(PFX " Read block %d page %d", block, page); - if (data) - MSG(" DATA[%d]", data_len); - if (ts) - MSG(" TS"); - MSG(TENDSTR); - } -#endif - return emu->ops_orig.ReadPageWithLayout(dev, block, page, data, data_len, ecc, ts, ecc_store); -} - - -////////////////////// wraper functions /////////////////////////// - -static void InjectBitFlip(uffs_Device *dev, u32 block, u32 page) -{ -#ifdef FILEEMU_WRITE_BIT_FLIP - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - struct uffs_FileEmuBitFlip flips[] = FILEEMU_WRITE_BIT_FLIP; - struct uffs_FileEmuBitFlip *x; - u8 buf[UFFS_MAX_PAGE_SIZE + UFFS_MAX_SPARE_SIZE]; - u8 *data = buf; - u8 *spare = buf + dev->attr->page_data_size; - int full_page_size = dev->attr->page_data_size + dev->attr->spare_size; - int blk_size = full_page_size * dev->attr->pages_per_block; - int page_offset = block * blk_size + full_page_size * page; - - int i; - u8 *p; - - fseek(emu->fp, page_offset, SEEK_SET); - fread(buf, 1, full_page_size, emu->fp); - - p = NULL; - for (i = 0; i < ARRAY_SIZE(flips); i++) { - x = &flips[i]; - if (x->block == block && x->page == page) { - if (x->offset >= 0) { - printf(" --- Inject data bit flip at block%d, page%d, offset%d, mask%d --- \n", block, page, x->offset, x->mask); - p = (u8 *)(data + x->offset); - } - else { - printf(" --- Inject spare bit flip at block%d, page%d, offset%d, mask%d --- \n", block, page, -x->offset, x->mask); - p = (u8 *)(spare - x->offset); - } - *p = (*p & ~x->mask) | (~(*p & x->mask) & x->mask); - } - } - - if (p) { - fseek(emu->fp, page_offset, SEEK_SET); - fwrite(buf, 1, full_page_size, emu->fp); - } -#endif -} - -static int femu_WritePage_wrap(uffs_Device *dev, u32 block, u32 page, - const u8 *data, int data_len, const u8 *spare, int spare_len) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - int ret; - -#ifdef UFFS_FEMU_SHOW_FLASH_IO - if (data || spare) { - MSG(PFX " Write block %d page %d", block, page); - if (data) - MSG(" DATA[%d]", data_len); - if (spare) - MSG(" SPARE[%d]", spare_len); - MSG(TENDSTR); - } -#endif - - ret = emu->ops_orig.WritePage(dev, block, page, data, data_len, spare, spare_len); - - InjectBitFlip(dev, block, page); - - return ret; -} - -static int femu_WritePageWithLayout_wrap(uffs_Device *dev, u32 block, u32 page, const u8* data, int data_len, const u8 *ecc, - const uffs_TagStore *ts) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - int ret; - -#ifdef UFFS_FEMU_SHOW_FLASH_IO - if (data || ts) { - MSG(PFX " Write block %d page %d", block, page); - if (data) - MSG(" DATA[%d]", data_len); - if (ts) - MSG(" TS"); - MSG(TENDSTR); - } -#endif - - ret = emu->ops_orig.WritePageWithLayout(dev, block, page, data, data_len, ecc, ts); - - InjectBitFlip(dev, block, page); - - return ret; -} - - -static int femu_EraseBlock_wrap(uffs_Device *dev, u32 blockNumber) -{ - uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private); - -#ifdef FILEEMU_ERASE_BAD_BLOCKS - int blocks[] = FILEEMU_ERASE_BAD_BLOCKS; - int i; - URET ret; - ret = emu->ops_orig.EraseBlock(dev, blockNumber); - - for (i = 0; i < ARRAY_SIZE(blocks); i++) { - if (blockNumber == blocks[i]) { - printf(" --- Inject bad block%d when erasing --- \n", blockNumber); - ret = UFFS_FLASH_BAD_BLK; - } - } - - return ret; - -#else - - return emu->ops_orig.EraseBlock(dev, blockNumber); - -#endif -} - -#endif // UFFS_FEMU_ENABLE_INJECTION - -///////////////////////////////////////////////////////////////////////////////// diff --git a/components/dfs/filesystems/uffs/src/example/CMakeLists.txt b/components/dfs/filesystems/uffs/src/example/CMakeLists.txt deleted file mode 100644 index 18cb307157..0000000000 --- a/components/dfs/filesystems/uffs/src/example/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -IF (UNIX) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/posix) -ENDIF() -IF (WIN32) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/win32) -ENDIF() -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/inc) -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/emu) - -LINK_DIRECTORIES(${uffs_BINARY_DIR}/src/emu) -LINK_DIRECTORIES(${uffs_BINARY_DIR}/src/uffs) - -SET(static_mem_SRCS static-mem-allocate.c) -SET(flash_if_SRCS flash-interface-example.c) -ADD_EXECUTABLE(static-mem-example ${static_mem_SRCS}) -ADD_EXECUTABLE(flash-if-example ${flash_if_SRCS}) -TARGET_LINK_LIBRARIES(static-mem-example emu uffs emu platform apitest_server) -TARGET_LINK_LIBRARIES(flash-if-example emu uffs emu platform) -IF (UNIX) - TARGET_LINK_LIBRARIES(static-mem-example pthread) -ENDIF () - diff --git a/components/dfs/filesystems/uffs/src/example/flash-interface-example.c b/components/dfs/filesystems/uffs/src/example/flash-interface-example.c deleted file mode 100644 index ff26beb281..0000000000 --- a/components/dfs/filesystems/uffs/src/example/flash-interface-example.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ -/** - * \file flash-interface-example.c - * \brief example for using flash driver and multiple partitions, with static memory allocator. - * \author Ricky Zheng, created at 27 Nov, 2007 - */ - -#include -#include "uffs_config.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_flash.h" -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_fs.h" - -#define PFX "ndrv: " - -struct my_nand_chip { - void *IOR_ADDR; - void *IOW_ADDR; - UBOOL inited; - // ... -}; - -/* - * Standard NAND flash commands - */ -#define NAND_CMD_READ0 0 -#define NAND_CMD_READ1 1 -#define NAND_CMD_RNDOUT 5 -#define NAND_CMD_PAGEPROG 0x10 -#define NAND_CMD_READOOB 0x50 -#define NAND_CMD_ERASE1 0x60 -#define NAND_CMD_STATUS 0x70 -#define NAND_CMD_STATUS_MULTI 0x71 -#define NAND_CMD_SEQIN 0x80 -#define NAND_CMD_RNDIN 0x85 -#define NAND_CMD_READID 0x90 -#define NAND_CMD_ERASE2 0xd0 -#define NAND_CMD_RESET 0xff - - -/* impelent the following functions for your NAND flash */ -#define CHIP_SET_CLE(chip) { chip = chip; } -#define CHIP_CLR_CLE(chip) {} -#define CHIP_SET_ALE(chip) {} -#define CHIP_CLR_ALE(chip) {} -#define CHIP_SET_NCS(chip) {} -#define CHIP_CLR_NCS(chip) {} -#define CHIP_BUSY(chip) {} -#define CHIP_READY(chip) {} -#define WRITE_COMMAND(chip, cmd) {} -#define WRITE_DATA_ADDR(chip, block, page, offset) {} -#define WRITE_ERASE_ADDR(chip, block) {} -#define WRITE_DATA(chip, data, len) {} -#define READ_DATA(chip, data, len) {} - -#define PARSE_STATUS(v) (UFFS_FLASH_NO_ERR) // parse status to UFFS_FLASH_NO_ERR or UFFS_FLASH_BAD_BLK - - - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR == 0 -int main() -{ - uffs_Perror(UFFS_MSG_NORMAL, "This example need CONFIG_USE_STATIC_MEMORY_ALLOCATOR = 1"); - return 0; -} -#else - - -static int nand_read_page(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc, - u8 *spare, int spare_len) -{ - u8 val = 0; - int ret = UFFS_FLASH_NO_ERR; - struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; - - CHIP_CLR_NCS(chip); - if (data && data_len > 0) { - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_READ0); - CHIP_CLR_CLE(chip); - CHIP_SET_ALE(chip); - WRITE_DATA_ADDR(chip, block, page, 0); - CHIP_CLR_ALE(chip); - READ_DATA(chip, data, data_len); - - // for now, we return all 0xFF to pass UFFS mount, you should remove this at your driver - memset(data, 0xFF, data_len); - } - - if (spare && spare_len > 0) { - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_READOOB); - CHIP_CLR_CLE(chip); - CHIP_SET_ALE(chip); - WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size); - CHIP_CLR_ALE(chip); - READ_DATA(chip, spare, spare_len); - - // for now, we return all 0xFF to pass UFFS mount, you should remove this at your driver - memset(spare, 0xFF, spare_len); - } - - if (data == NULL && spare == NULL) { - // read bad block mark - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_READOOB); - CHIP_CLR_CLE(chip); - CHIP_SET_ALE(chip); - WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size + attr->block_status_offs); - CHIP_CLR_ALE(chip); - READ_DATA(chip, &val, 1); - ret = (val == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK); - - // for now, we return UFFS_FLASH_NO_ERR to pass UFFS mount, you should remove this at your driver - ret = UFFS_FLASH_NO_ERR; - } - - CHIP_SET_NCS(chip); - - return ret; -} - -static int nand_write_page(uffs_Device *dev, u32 block, u32 page, - const u8 *data, int data_len, const u8 *spare, int spare_len) -{ - u8 val = 0; - int ret = UFFS_FLASH_NO_ERR; - UBOOL fall_through = FALSE; - struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; - - CHIP_CLR_NCS(chip); - - if (data && data_len > 0) { - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_READ0); - WRITE_COMMAND(chip, NAND_CMD_SEQIN); - CHIP_CLR_CLE(chip); - CHIP_SET_ALE(chip); - WRITE_DATA_ADDR(chip, block, page, 0); - CHIP_CLR_ALE(chip); - CHIP_BUSY(chip); - WRITE_DATA(chip, data, data_len); - if (data_len == dev->attr->page_data_size) - fall_through = U_TRUE; - else { - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_PAGEPROG); - WRITE_COMMAND(chip, NAND_CMD_STATUS); - CHIP_CLR_CLE(chip); - CHIP_READY(chip); - READ_DATA(chip, &val, 1); - ret = PARSE_STATUS(val); - } - } - - if (ret != UFFS_FLASH_NO_ERR) - goto ext; - - if (spare && spare_len > 0) { - if (!fall_through) { - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_READOOB); - WRITE_COMMAND(chip, NAND_CMD_SEQIN); - CHIP_CLR_CLE(chip); - CHIP_SET_ALE(chip); - WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size); - CHIP_CLR_ALE(chip); - CHIP_BUSY(chip); - } - WRITE_DATA(chip, spare, spare_len); - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_PAGEPROG); - WRITE_COMMAND(chip, NAND_CMD_STATUS); - CHIP_CLR_CLE(chip); - CHIP_READY(chip); - READ_DATA(chip, &val, 1); - ret = PARSE_STATUS(val); - } - - if (data == NULL && spare == NULL) { - // mark bad block - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_READOOB); - WRITE_COMMAND(chip, NAND_CMD_SEQIN); - CHIP_CLR_CLE(chip); - CHIP_SET_ALE(chip); - WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size + attr->block_status_offs); - CHIP_CLR_ALE(chip); - CHIP_BUSY(chip); - val = 0; - WRITE_DATA(chip, &val, 1); - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_PAGEPROG); - WRITE_COMMAND(chip, NAND_CMD_STATUS); - CHIP_CLR_CLE(chip); - CHIP_READY(chip); - READ_DATA(chip, &val, 1); - ret = PARSE_STATUS(val); - } - -ext: - CHIP_SET_NCS(chip); - - return ret; -} - -static int nand_erase_block(uffs_Device *dev, u32 block) -{ - u8 val = 0; - struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; - - CHIP_CLR_NCS(chip); - - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_ERASE1); - CHIP_CLR_CLE(chip); - CHIP_SET_ALE(chip); - WRITE_ERASE_ADDR(chip, blcok); - CHIP_CLR_ALE(chip); - CHIP_SET_CLE(chip); - WRITE_COMMAND(chip, NAND_CMD_ERASE2); - WRITE_COMMAND(chip, NAND_CMD_STATUS); - CHIP_CLR_CLE(chip); - CHIP_READY(chip); - READ_DATA(chip, &val, 1); - - CHIP_SET_NCS(chip); - - val = val; // just for eliminating warning - - return PARSE_STATUS(val); -} - - -static int nand_init_flash(uffs_Device *dev) -{ - // initialize your hardware here ... - struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; - - if (!chip->inited) { - // setup chip I/O address, setup NAND flash controller ... etc. - // chip->IOR_ADDR = 0xF0000000 - // chip->IOW_ADDR = 0xF0000000 - chip->inited = U_TRUE; - } - return 0; -} - -static int nand_release_flash(uffs_Device *dev) -{ - // release your hardware here - struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; - - chip = chip; - - return 0; -} - -static uffs_FlashOps g_my_nand_ops = { - nand_init_flash, // InitFlash() - nand_release_flash, // ReleaseFlash() - nand_read_page, // ReadPage() - NULL, // ReadPageWithLayout - nand_write_page, // WritePage() - NULL, // WritePageWithLayout - NULL, // IsBadBlock(), let UFFS take care of it. - NULL, // MarkBadBlock(), let UFFS take care of it. - nand_erase_block, // EraseBlock() -}; - -///////////////////////////////////////////////////////////////////////////////// - -// change these parameters to fit your nand flash specification - -#define TOTAL_BLOCKS 1024 -#define PAGE_DATA_SIZE 512 -#define PAGE_SPARE_SIZE 16 -#define PAGES_PER_BLOCK 32 -#define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE) -#define BLOCK_DATA_SIZE (PAGE_DATA_SIZE * PAGES_PER_BLOCK) - -#define NR_PARTITION 2 /* total partitions */ -#define PAR_1_BLOCKS 100 /* partition 1 */ -#define PAR_2_BLOCKS (TOTAL_BLOCKS - PAR_1_BLOCKS) /* partition 2 */ - -struct my_nand_chip g_nand_chip = {0}; -static struct uffs_StorageAttrSt g_my_flash_storage = {0}; - -/* define mount table */ -static uffs_Device demo_device_1 = {0}; -static uffs_Device demo_device_2 = {0}; - -static uffs_MountTable demo_mount_table[] = { - { &demo_device_1, 0, PAR_1_BLOCKS - 1, "/data/" }, - { &demo_device_2, PAR_1_BLOCKS, PAR_1_BLOCKS + PAR_2_BLOCKS - 1, "/" }, - { NULL, 0, 0, NULL } -}; - -/* static alloc the memory for each partition */ -static int static_buffer_par1[UFFS_STATIC_BUFF_SIZE(PAGES_PER_BLOCK, PAGE_SIZE, PAR_1_BLOCKS) / sizeof(int)]; -static int static_buffer_par2[UFFS_STATIC_BUFF_SIZE(PAGES_PER_BLOCK, PAGE_SIZE, PAR_2_BLOCKS) / sizeof(int)];; - -static void init_nand_chip(struct my_nand_chip *chip) -{ - // init chip IO address, etc. -} - -static void setup_flash_storage(struct uffs_StorageAttrSt *attr) -{ - memset(attr, 0, sizeof(struct uffs_StorageAttrSt)); - - // setup NAND flash attributes. - attr->total_blocks = TOTAL_BLOCKS; /* total blocks */ - attr->page_data_size = PAGE_DATA_SIZE; /* page data size */ - attr->pages_per_block = PAGES_PER_BLOCK; /* pages per block */ - attr->spare_size = PAGE_SPARE_SIZE; /* page spare size */ - attr->block_status_offs = 4; /* block status offset is 5th byte in spare */ - attr->ecc_opt = UFFS_ECC_SOFT; /* ecc option */ - attr->layout_opt = UFFS_LAYOUT_UFFS; /* let UFFS do the spare layout */ -} - -static URET my_InitDevice(uffs_Device *dev) -{ - dev->attr = &g_my_flash_storage; // NAND flash attributes - dev->attr->_private = (void *) &g_nand_chip;// hook nand_chip data structure to attr->_private - dev->ops = &g_my_nand_ops; // NAND driver - - init_nand_chip(&g_nand_chip); - - return U_SUCC; -} - -static URET my_ReleaseDevice(uffs_Device *dev) -{ - return U_SUCC; -} - - -static int my_init_filesystem(void) -{ - uffs_MountTable *mtbl = &(demo_mount_table[0]); - - /* setup nand storage attributes */ - setup_flash_storage(&g_my_flash_storage); - - /* setup memory allocator */ - uffs_MemSetupStaticAllocator(&demo_device_1.mem, static_buffer_par1, sizeof(static_buffer_par1)); - uffs_MemSetupStaticAllocator(&demo_device_2.mem, static_buffer_par2, sizeof(static_buffer_par2)); - - /* register mount table */ - while(mtbl->dev) { - // setup device init/release entry - mtbl->dev->Init = my_InitDevice; - mtbl->dev->Release = my_ReleaseDevice; - uffs_RegisterMountTable(mtbl); - mtbl++; - } - - // mount partitions - for (mtbl = &(demo_mount_table[0]); mtbl->mount != NULL; mtbl++) { - uffs_Mount(mtbl->mount); - } - - return uffs_InitFileSystemObjects() == U_SUCC ? 0 : -1; -} - -static int my_release_filesystem(void) -{ - uffs_MountTable *mtb; - int ret = 0; - - // unmount parttions - for (mtb = &(demo_mount_table[0]); ret == 0 && mtb->mount != NULL; mtb++) { - ret = uffs_UnMount(mtb->mount); - } - - // release objects - if (ret == 0) - ret = (uffs_ReleaseFileSystemObjects() == U_SUCC ? 0 : -1); - - return ret; -} - -/* application entry */ -int main() -{ - uffs_SetupDebugOutput(); // setup debug output as early as possible - - my_init_filesystem(); - - // ... my application codes .... - // read/write/create/delete files ... - - my_release_filesystem(); - - return 0; -} - -#endif - - -///////////////////////////////////////////////////////////////////////////////// diff --git a/components/dfs/filesystems/uffs/src/example/static-mem-allocate.c b/components/dfs/filesystems/uffs/src/example/static-mem-allocate.c deleted file mode 100644 index 59aff8e63d..0000000000 --- a/components/dfs/filesystems/uffs/src/example/static-mem-allocate.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file static-mem-allocate.c - * \brief demostrate how to use static memory allocation. This example use - * file emulated NAND flash, one partition only. - * \author Ricky Zheng - */ - -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_fs.h" -#include "uffs/uffs_utils.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs_mtb.h" -#include "cmdline.h" -#include "uffs_fileem.h" - -#define PFX "sexp: " - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR == 0 -int main() -{ - uffs_Perror(UFFS_MSG_NORMAL, "This example need CONFIG_USE_STATIC_MEMORY_ALLOCATOR = 1"); - return 0; -} -#else - -extern struct cli_commandset * get_helper_cmds(void); -extern struct cli_commandset * get_test_cmds(void); - -#define PAGE_DATA_SIZE 512 -#define PAGE_SPARE_SIZE 16 -#define PAGES_PER_BLOCK 32 -#define TOTAL_BLOCKS 128 - -#define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE) -#define BLOCK_DATA_SIZE (PAGES_PER_BLOCK * PAGE_DATA_SIZE) -#define TOTAL_DATA_SIZE (TOTAL_BLOCKS * BLOCK_DATA_SIZE) -#define BLOCK_SIZE (PAGES_PER_BLOCK * PAGE_SIZE) -#define TOTAL_SIZE (BLOCK_SIZE * TOTAL_BLOCKS) - -#define MAX_MOUNT_TABLES 10 -#define MAX_MOUNT_POINT_NAME 32 - -static uffs_Device demo_device = {0}; -static struct uffs_MountTableEntrySt demo_mount = { - &demo_device, - 0, /* start from block 0 */ - -1, /* use whole chip */ - "/", /* mount point */ - NULL -}; - -/* static alloc the memory */ -static int static_buffer_pool[UFFS_STATIC_BUFF_SIZE(PAGES_PER_BLOCK, PAGE_SIZE, TOTAL_BLOCKS) / sizeof(int)]; - - -static void setup_storage(struct uffs_StorageAttrSt *attr) -{ - attr->total_blocks = TOTAL_BLOCKS; /* total blocks */ - attr->page_data_size = PAGE_DATA_SIZE; /* page data size */ - attr->spare_size = PAGE_SPARE_SIZE; /* page spare size */ - attr->pages_per_block = PAGES_PER_BLOCK; /* pages per block */ - attr->block_status_offs = 4; /* block status offset is 5th byte in spare */ - attr->ecc_opt = UFFS_ECC_SOFT; /* use UFFS software ecc */ - attr->layout_opt = UFFS_LAYOUT_UFFS; /* let UFFS do the spare layout */ -} - -static void setup_device(uffs_Device *dev) -{ - // using file emulator device - dev->Init = femu_InitDevice; - dev->Release = femu_ReleaseDevice; - dev->attr = femu_GetStorage(); -} - -static int init_uffs_fs(void) -{ - struct uffs_MountTableEntrySt *mtbl = &demo_mount; - - /* setup flash storage attributes */ - setup_storage(femu_GetStorage()); - - /* setup memory allocator */ - uffs_MemSetupStaticAllocator(&mtbl->dev->mem, static_buffer_pool, sizeof(static_buffer_pool)); - - /* setup device: init, release, attr */ - setup_device(mtbl->dev); - - /* register mount table */ - uffs_RegisterMountTable(mtbl); - - /* mount it */ - uffs_Mount("/"); - - return uffs_InitFileSystemObjects() == U_SUCC ? 0 : -1; -} - -static int release_uffs_fs(void) -{ - uffs_UnMount("/"); - - return uffs_ReleaseFileSystemObjects(); -} - -int main(int argc, char *argv[]) -{ - int ret; - - uffs_SetupDebugOutput(); // setup debug output as early as possible - - ret = init_uffs_fs(); - - if (ret != 0) { - printf ("Init file system fail: %d\n", ret); - return -1; - } - - cli_add_commandset(get_helper_cmds()); - cli_add_commandset(get_test_cmds()); - cli_main_entry(); - - release_uffs_fs(); - - return 0; -} - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs.h deleted file mode 100644 index 12121cd1ab..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ -/** - * \file uffs.h - * \brief uffs basic defines - * \author Ricky Zheng - */ - -#ifndef _UFFS_H_ -#define _UFFS_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#define UO_RDONLY 0x0000 /** read only */ -#define UO_WRONLY 0x0001 /** write only */ -#define UO_RDWR 0x0002 /** read and write */ -#define UO_APPEND 0x0008 /** append */ - -#define UO_BINARY 0x0000 /** no used in uffs */ - -#define UO_CREATE 0x0100 -#define UO_TRUNC 0x0200 -#define UO_EXCL 0x0400 - -#define UO_NOECC 0x0800 /** skip ECC when reading file data from media */ - - -#define UO_DIR 0x1000 /** open a directory */ - - - -#define UENOERR 0 /** no error */ -#define UEACCES 1 /** Tried to open read-only file - for writing, or files sharing mode - does not allow specified operations, - or given path is directory */ - -#define UEEXIST 2 /** _O_CREAT and _O_EXCL flags specified, - but filename already exists */ -#define UEINVAL 3 /** Invalid oflag or pmode argument */ -#define UEMFILE 4 /** No more file handles available - (too many open files) */ -#define UENOENT 5 /** file or path not found */ -#define UETIME 6 /** can't set file time */ -#define UEBADF 9 /** invalid file handle */ -#define UENOMEM 10 /** no enough memory */ -#define UEIOERR 11 /** I/O error from lower level flash operation */ -#define UENOTDIR 12 /** Not a directory */ -#define UEISDIR 13 /** Is a directory */ - -#define UEUNKNOWN_ERR 100 /** unknown error */ - - - -#define _SEEK_CUR 0 /** seek from current position */ -#define _SEEK_SET 1 /** seek from beginning of file */ -#define _SEEK_END 2 /** seek from end of file */ - -#define USEEK_CUR _SEEK_CUR -#define USEEK_SET _SEEK_SET -#define USEEK_END _SEEK_END - - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_badblock.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_badblock.h deleted file mode 100644 index b44bbb8170..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_badblock.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ -/** - * \file uffs_badblock.h - * \brief bad block management - * \author Ricky Zheng - */ - -#ifndef _UFFS_BADBLOCK_H_ -#define _UFFS_BADBLOCK_H_ - -#include "uffs/uffs_public.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_core.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -#define HAVE_BADBLOCK(dev) (dev->bad.block != UFFS_INVALID_BLOCK) - -/** initialize bad block management data structures for uffs device */ -void uffs_BadBlockInit(uffs_Device *dev); - -/** processing bad block: erase bad block, - mark it as 'bad' and put it to bad block list */ -void uffs_BadBlockProcess(uffs_Device *dev, TreeNode *node); - -/** processing bad block: erase bad block, - mark it as 'bad' and put it to suspend block list */ -void uffs_BadBlockProcessSuspend(uffs_Device *dev, TreeNode *node); - -/** try to recover data from a new discovered bad block */ -void uffs_BadBlockRecover(uffs_Device *dev); - -/** put a new block to the bad block waiting list */ -void uffs_BadBlockAdd(uffs_Device *dev, int block); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_blockinfo.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_blockinfo.h deleted file mode 100644 index dfd3a9be7c..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_blockinfo.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ -/** - * \file uffs_blockinfo.h - * \brief data structure for operating block information - * \author Ricky Zheng - */ - -#ifndef _UFFS_BLOCKINFO_H_ -#define _UFFS_BLOCKINFO_H_ - -#include "uffs/uffs_types.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_core.h" - -#ifdef __cplusplus -extern "C"{ -#endif -/** - * \struct uffs_PageSpareSt - * \brief this structure is for storing uffs tag and more. - */ -struct uffs_PageSpareSt { - uffs_Tags tag; //!< page tag - int expired:1; -}; - -/** - * \struct uffs_BlockInfoSt - * \brief block information data. Block info is frequently accessed, - UFFS use a cache system to speed up block info access. - */ -struct uffs_BlockInfoSt { - struct uffs_BlockInfoSt *next; - struct uffs_BlockInfoSt *prev; - u16 block; //!< block number - struct uffs_PageSpareSt *spares; //!< page spare info array - int expired_count; //!< how many pages expired in this block ? - int ref_count; //!< reference counter, it's safe to reuse this block memory when the counter is 0. -}; - -/** get tag from block info */ -#define GET_TAG(bc, page) (&(bc)->spares[page].tag) - - -/** initialize block info caches */ -URET uffs_BlockInfoInitCache(uffs_Device *dev, int maxCachedBlocks); - -/** release block info caches */ -URET uffs_BlockInfoReleaseCache(uffs_Device *dev); - -/** load page spare to block info cache */ -URET uffs_BlockInfoLoad(uffs_Device *dev, uffs_BlockInfo *work, int page); - -/** find block info cache */ -uffs_BlockInfo * uffs_BlockInfoFindInCache(uffs_Device *dev, int block); - -/** get block info cache, load it on demand */ -uffs_BlockInfo * uffs_BlockInfoGet(uffs_Device *dev, int block); - -/** put info cache back to pool, should be called with #uffs_BlockInfoGet in pairs. */ -void uffs_BlockInfoPut(uffs_Device *dev, uffs_BlockInfo *p); - -/** explicitly expire a block info cache */ -void uffs_BlockInfoExpire(uffs_Device *dev, uffs_BlockInfo *p, int page); - -/** no one hold any block info cache ? safe to release block info caches */ -UBOOL uffs_BlockInfoIsAllFree(uffs_Device *dev); - -/** explicitly expire all block info caches */ -void uffs_BlockInfoExpireAll(uffs_Device *dev); - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_buf.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_buf.h deleted file mode 100644 index b5c99f6d5e..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_buf.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_buf.h - * \brief page buffers - * \author Ricky Zheng - */ - -#ifndef UFFS_BUF_H -#define UFFS_BUF_H - -#include "uffs/uffs_types.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_tree.h" -#include "uffs/uffs_core.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#define CLONE_BUF_MARK 0xffff //!< set uffs_BufSt::ref_count to this for a 'cloned' buffer - -/** for uffs_BufSt::mark */ -#define UFFS_BUF_EMPTY 0 //!< buffer is empty -#define UFFS_BUF_VALID 1 //!< buffer is holding valid data -#define UFFS_BUF_DIRTY 2 //!< buffer data is modified - -/** for uffs_BufSt::ext_mark */ -#define UFFS_BUF_EXT_MARK_TRUNC_TAIL 1 //!< the last page of file (when truncating a file) - -/** uffs page buffer */ -struct uffs_BufSt{ - struct uffs_BufSt *next; //!< link to next buffer - struct uffs_BufSt *prev; //!< link to previous buffer - struct uffs_BufSt *next_dirty; //!< link to next dirty buffer - struct uffs_BufSt *prev_dirty; //!< link to previous dirty buffer - u8 type; //!< #UFFS_TYPE_DIR or #UFFS_TYPE_FILE or #UFFS_TYPE_DATA - u8 ext_mark; //!< extension mark. - u16 parent; //!< parent serial - u16 serial; //!< serial - u16 page_id; //!< page id - u16 mark; //!< #UFFS_BUF_EMPTY or #UFFS_BUF_VALID, or #UFFS_BUF_DIRTY ? - u16 ref_count; //!< reference counter, or #CLONE_BUF_MARK for a cloned buffer - u16 data_len; //!< length of data - u16 check_sum; //!< checksum field - u8 * data; //!< data buffer - u8 * header; //!< header -}; - -#define uffs_BufIsFree(buf) (buf->ref_count == 0 ? U_TRUE : U_FALSE) - -/** initialize page buffers */ -URET uffs_BufInit(struct uffs_DeviceSt *dev, int buf_max, int dirty_buf_max); - -/** release page buffers */ -URET uffs_BufReleaseAll(struct uffs_DeviceSt *dev); - -/** find the page buffer, move to link list head if found */ -uffs_Buf * uffs_BufGet(struct uffs_DeviceSt *dev, u16 parent, u16 serial, u16 page_id); -uffs_Buf *uffs_BufGetEx(struct uffs_DeviceSt *dev, u8 type, TreeNode *node, u16 page_id, int oflag); - -/** alloc a new page buffer */ -uffs_Buf *uffs_BufNew(struct uffs_DeviceSt *dev, u8 type, u16 parent, u16 serial, u16 page_id); - -/** find the page buffer (not affect the reference counter) */ -uffs_Buf * uffs_BufFind(uffs_Device *dev, u16 parent, u16 serial, u16 page_id); - -/** find the page buffer from #start (not affect the reference counter) */ -uffs_Buf * uffs_BufFindFrom(uffs_Device *dev, uffs_Buf *start, - u16 parent, u16 serial, u16 page_id); - -/** put page buffer back to pool, called in pair with #uffs_Get,#uffs_GetEx or #uffs_BufNew */ -URET uffs_BufPut(uffs_Device *dev, uffs_Buf *buf); - -/** increase buffer references */ -void uffs_BufIncRef(uffs_Buf *buf); - -/** decrease buffer references */ -void uffs_BufDecRef(uffs_Buf *buf); - -/** write data to a page buffer */ -URET uffs_BufWrite(struct uffs_DeviceSt *dev, uffs_Buf *buf, void *data, u32 ofs, u32 len); - -/** read data from a page buffer */ -URET uffs_BufRead(struct uffs_DeviceSt *dev, uffs_Buf *buf, void *data, u32 ofs, u32 len); - -/** mark buffer as #UFFS_BUF_EMPTY if ref_count == 0, and discard all data it holds */ -void uffs_BufMarkEmpty(uffs_Device *dev, uffs_Buf *buf); - -/** if there is no free dirty group slot, flush the most dirty group */ -URET uffs_BufFlush(struct uffs_DeviceSt *dev); -URET uffs_BufFlushEx(struct uffs_DeviceSt *dev, UBOOL force_block_recover); - -/** flush dirty group */ -URET uffs_BufFlushGroup(struct uffs_DeviceSt *dev, u16 parent, u16 serial); -URET uffs_BufFlushGroupEx(struct uffs_DeviceSt *dev, u16 parent, u16 serial, UBOOL force_block_recover); - -/** find free dirty group slot */ -int uffs_BufFindFreeGroupSlot(struct uffs_DeviceSt *dev); - -/** find the dirty group slot */ -int uffs_BufFindGroupSlot(struct uffs_DeviceSt *dev, u16 parent, u16 serial); - -/** lock dirty group */ -URET uffs_BufLockGroup(struct uffs_DeviceSt *dev, int slot); - -/** unlock dirty group */ -URET uffs_BufUnLockGroup(struct uffs_DeviceSt *dev, int slot); - -/** flush most dirty group */ -URET uffs_BufFlushMostDirtyGroup(struct uffs_DeviceSt *dev); - -/** flush all groups under the same parent number */ -URET uffs_BufFlushGroupMatchParent(struct uffs_DeviceSt *dev, u16 parent); - -/** flush all page buffers */ -URET uffs_BufFlushAll(struct uffs_DeviceSt *dev); - -/** no one holding any page buffer ? safe to release page buffers */ -UBOOL uffs_BufIsAllFree(struct uffs_DeviceSt *dev); - -/** are all page buffer marked with #UFFS_BUF_EMPTY ? */ -UBOOL uffs_BufIsAllEmpty(struct uffs_DeviceSt *dev); - -/** mark all page buffer as #UFFS_BUF_EMPTY */ -URET uffs_BufSetAllEmpty(struct uffs_DeviceSt *dev); - -/** clone a page buffer */ -uffs_Buf * uffs_BufClone(struct uffs_DeviceSt *dev, uffs_Buf *buf); - -/** release a cloned page buffer, call in pair with #uffs_BufClone */ -URET uffs_BufFreeClone(uffs_Device *dev, uffs_Buf *buf); - -/** load physical storage data to page buffer */ -URET uffs_BufLoadPhyData(uffs_Device *dev, uffs_Buf *buf, u32 block, u32 page); - -/** load physical storage data to page buffer withouth checking ECC */ -URET uffs_LoadPhyDataToBufEccUnCare(uffs_Device *dev, uffs_Buf *buf, u32 block, u32 page); - -/** showing page buffers info, for debug only */ -void uffs_BufInspect(uffs_Device *dev); - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_core.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_core.h deleted file mode 100644 index 1f18007f0f..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_core.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -#ifndef _UFFS_CORE_H_ -#define _UFFS_CORE_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/** \typedef uffs_Device */ -typedef struct uffs_DeviceSt uffs_Device; -/** \typedef uffs_FlashOps */ -typedef struct uffs_FlashOpsSt uffs_FlashOps; - -typedef struct uffs_BlockInfoSt uffs_BlockInfo; -typedef struct uffs_PageSpareSt uffs_PageSpare; -typedef struct uffs_TagsSt uffs_Tags; //!< UFFS page tags -typedef struct uffs_TagStoreSt uffs_TagStore; //!< UFFS page tags physical store structure - -typedef struct uffs_BufSt uffs_Buf; - - -#ifdef __cplusplus -} -#endif - - - -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_crc.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_crc.h deleted file mode 100644 index a31bb21c91..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_crc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_crc.h - * \author Ricky Zheng, created 23 Nov, 2011 - */ - -#ifndef _UFFS_CRC_H_ -#define _UFFS_CRC_H_ - -#include "uffs/uffs_types.h" - -u16 uffs_crc16update(const void *data, int length, u16 crc); -u16 uffs_crc16sum(const void *data, int length); - -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_device.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_device.h deleted file mode 100644 index 22614528a3..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_device.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_device.h - * \brief uffs device structures definition - * \author Ricky Zheng - */ - -#ifndef UFFS_DEVICE_H -#define UFFS_DEVICE_H - -#include "uffs/uffs_types.h" -#include "uffs/uffs_buf.h" -#include "uffs/uffs_blockinfo.h" -#include "uffs/uffs_pool.h" -#include "uffs/uffs_tree.h" -#include "uffs/uffs_mem.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs_flash.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -/** - * \def MAX_DIRTY_BUF_GROUPS - */ -#define MAX_DIRTY_BUF_GROUPS 3 - - -/** - * \struct uffs_BlockInfoCacheSt - * \brief block information structure, used to manager block information caches - */ -struct uffs_BlockInfoCacheSt { - uffs_BlockInfo *head; //!< buffer head of block info(spares) - uffs_BlockInfo *tail; //!< buffer tail - void *mem_pool; //!< internal memory pool, used for release whole buffer -}; - -/** - * \struct uffs_PartitionSt - * \brief partition basic information - */ -struct uffs_PartitionSt { - u16 start; //!< start block number of partition - u16 end; //!< end block number of partition -}; - -/** - * \struct uffs_LockSt - * \brief lock stuffs - */ -struct uffs_LockSt { - OSSEM sem; - int task_id; - int counter; -}; - -/** - * \struct uffs_DirtyGroupSt - * \brief manager dirty page buffers - */ -struct uffs_DirtyGroupSt { - int count; //!< dirty buffers count - int lock; //!< dirty group lock (0: unlocked, >0: locked) - uffs_Buf *dirty; //!< dirty buffer list -}; - -/** - * \struct uffs_PageBufDescSt - * \brief uffs page buffers descriptor - */ -struct uffs_PageBufDescSt { - uffs_Buf *head; //!< head of buffers - uffs_Buf *tail; //!< tail of buffers - struct uffs_DirtyGroupSt dirtyGroup[MAX_DIRTY_BUF_GROUPS]; //!< dirty buffer groups - int buf_max; //!< maximum buffers - int dirty_buf_max; //!< maximum dirty buffer allowed - void *pool; //!< memory pool for buffers -}; - - -/** - * \struct uffs_PageCommInfoSt - * \brief common data for device, should be initialised at early - * \note it is possible that pg_size is smaller than physical page size, but normally they are the same. - * \note page data layout: [HEADER] + [DATA] - */ -struct uffs_PageCommInfoSt { - u16 pg_data_size; //!< page data size - u16 header_size; //!< header size - u16 pg_size; //!< page size -}; - -/** - * \struct uffs_NewBadBlockSt - * \brief holding new discovered bad block - */ -struct uffs_NewBadBlockSt { - u16 block; //!< bad block, FIX ME to process more than one bad block -}; - -/** - * \struct uffs_FlashStatSt - * \typedef uffs_FlashStat - * \brief statistic data of flash read/write/erase activities - */ -typedef struct uffs_FlashStatSt { - int block_erase_count; - int page_write_count; - int page_read_count; - int page_header_read_count; - int spare_write_count; - int spare_read_count; - unsigned long io_read; - unsigned long io_write; -} uffs_FlashStat; - - -/** - * \struct uffs_ConfigSt - * \typedef uffs_Config - * \brief uffs config parameters - */ -typedef struct uffs_ConfigSt { - int bc_caches; - int page_buffers; - int dirty_pages; - int dirty_groups; - int reserved_free_blocks; -} uffs_Config; - - -/** - * \struct uffs_DeviceSt - * \brief The core data structure of UFFS, all information needed by manipulate UFFS object - * \note one partition corresponding one uffs device. - */ -struct uffs_DeviceSt { - URET (*Init)(uffs_Device *dev); //!< low level initialisation - URET (*Release)(uffs_Device *dev); //!< low level release - void *_private; //!< private data for device - - struct uffs_StorageAttrSt *attr; //!< storage attribute - struct uffs_PartitionSt par; //!< partition information - struct uffs_FlashOpsSt *ops; //!< flash operations - struct uffs_BlockInfoCacheSt bc; //!< block info cache - struct uffs_LockSt lock; //!< lock data structure - struct uffs_PageBufDescSt buf; //!< page buffers - struct uffs_PageCommInfoSt com; //!< common information - struct uffs_TreeSt tree; //!< tree list of block - struct uffs_NewBadBlockSt bad; //!< new discovered bad block - struct uffs_FlashStatSt st; //!< statistic (counters) - struct uffs_memAllocatorSt mem; //!< uffs memory allocator - struct uffs_ConfigSt cfg; //!< uffs config - u32 ref_count; //!< device reference count - int dev_num; //!< device number (partition number) -}; - - -/** create the lock for uffs device */ -void uffs_DeviceInitLock(uffs_Device *dev); - -/** delete the lock of uffs device */ -void uffs_DeviceReleaseLock(uffs_Device *dev); - -/** lock uffs device */ -void uffs_DeviceLock(uffs_Device *dev); - -/** unlock uffs device */ -void uffs_DeviceUnLock(uffs_Device *dev); - - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_ecc.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_ecc.h deleted file mode 100644 index 18fbd92a38..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_ecc.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_ecc.h - * \brief file handle operations - * \author Ricky Zheng, created 8th Jun, 2005 - */ - -#ifndef _UFFS_ECC_H_ -#define _UFFS_ECC_H_ - -#include - -#include "uffs/uffs_fs.h" -#include "uffs/uffs_core.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - - -#define MAX_ECC_LENGTH 24 //!< 2K page ecc length is 24 bytes. - -/** - * calculate ECC - * \return length of generated ECC. (3 bytes ECC per 256 data) - */ -int uffs_EccMake(const void *data, int data_len, void *ecc); - -/** - * correct data by ECC. - * - * return: 0 -- no error - * -1 -- can not be corrected - * >0 -- how many bits are corrected - */ -int uffs_EccCorrect(void *data, int data_len, void *read_ecc, const void *test_ecc); - - -/** - * generate 12 bit ecc for maximum 8 bytes data - */ -u16 uffs_EccMake8(const void *data, int data_len); - -/** - * correct maximum 8 bytes data from 12 bits ECC - * - * return: 0 -- no error - * -1 -- can not be corrected - * >0 -- how many bits are corrected - */ -int uffs_EccCorrect8(void *data, u16 read_ecc, u16 test_ecc, int errtop); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_fd.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_fd.h deleted file mode 100644 index c5d8159074..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_fd.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fd.h - * \brief PISIX like file operations - * \author Ricky Zheng, created 8th Jun, 2005 - */ - -#ifndef _UFFS_FD_H_ -#define _UFFS_FD_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - -#include "uffs/uffs.h" - -/** - * \brief definitions for uffs_stat::st_mode - */ -#define US_IFMT 0xF000 /* file type make */ -#define US_IFREG 0x8000 /* regular */ -#define US_IFLNK 0xA000 /* symbolic link */ -#define US_IFDIR 0x4000 /* directory */ -#define US_IREAD 0000400 /* read permission */ -#define US_IWRITE 0000200 /* write permission */ - -#define US_IRWXU 00700 /* RWX owner */ -#define US_IRUSR 00400 /* R owner */ -#define US_IWUSR 00200 /* W owner */ -#define US_IXUSR 00100 /* X owner */ -#define US_IRWXG 00070 /* RWX group */ -#define US_IRGRP 00040 /* R group */ -#define US_IWGRP 00020 /* W group */ -#define US_IXGRP 00010 /* X group */ -#define US_IRWXO 00007 /* RWX other */ -#define US_IROTH 00004 /* R other */ -#define US_IWOTH 00002 /* W other */ -#define US_IXOTH 00001 /* X other */ - -/** - * \brief POSIX dirent - */ -struct uffs_dirent { - int d_ino; /* inode number (serial number of this object) */ - int d_off; /* offset to this dirent */ - unsigned short int d_reclen; /* length of this uffs_dirent */ - unsigned short int d_namelen; /* length of this d_name */ - unsigned char d_type; /* type of this record */ - char d_name[256]; /* name of this object */ -}; - -struct uffs_dirSt; -typedef struct uffs_dirSt uffs_DIR; - -/** - * \brief POSIX stat - */ -struct uffs_stat { - int st_dev; /* ID of device containing file */ - int st_ino; /* inode number */ - int st_mode; /* protection */ - int st_nlink; /* number of hard links */ - int st_uid; /* user ID of owner */ - int st_gid; /* group ID of owner */ - int st_rdev; /* device ID (if special file) */ - long st_size; /* total size, in bytes */ - int st_blksize; /* blocksize for filesystem I/O */ - int st_blocks; /* number of blocks allocated */ - unsigned int st_atime; /* time of last access */ - unsigned int st_mtime; /* time of last modification */ - unsigned int st_ctime; /* time of last status change */ -}; - -/* POSIX complaint file system APIs */ - -int uffs_open(const char *name, int oflag, ...); -int uffs_close(int fd); -int uffs_read(int fd, void *data, int len); -int uffs_write(int fd, const void *data, int len); -long uffs_seek(int fd, long offset, int origin); -long uffs_tell(int fd); -int uffs_eof(int fd); -int uffs_flush(int fd); -int uffs_rename(const char *old_name, const char *new_name); -int uffs_remove(const char *name); -int uffs_ftruncate(int fd, long remain); - -int uffs_mkdir(const char *name, ...); -int uffs_rmdir(const char *name); - -int uffs_stat(const char *name, struct uffs_stat *buf); -int uffs_lstat(const char *name, struct uffs_stat *buf); -int uffs_fstat(int fd, struct uffs_stat *buf); - -int uffs_closedir(uffs_DIR *dirp); -uffs_DIR * uffs_opendir(const char *path); -struct uffs_dirent * uffs_readdir(uffs_DIR *dirp); - -void uffs_rewinddir(uffs_DIR *dirp); - - -int uffs_get_error(void); -int uffs_set_error(int err); - -int uffs_version(void); -int uffs_format(const char *mount_point); - -long uffs_space_total(const char *mount_point); -long uffs_space_used(const char *mount_point); -long uffs_space_free(const char *mount_point); - -void uffs_flush_all(const char *mount_point); - -#ifdef __cplusplus -} -#endif -#endif - - - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_find.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_find.h deleted file mode 100644 index 3408cf33c6..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_find.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_find.h - * \brief find objects under dir - * \author Ricky Zheng - */ - -#ifndef _UFFS_FIND_H_ -#define _UFFS_FIND_H_ - -#include "uffs/uffs_fs.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -typedef struct uffs_FindInfoSt { - uffs_Device *dev; //!< the device to be searched - u16 serial; //!< the dir serial number - int step; //!< step: 0 - working on dir entries, - // 1 - working on file entries, - // 2 - stoped. - int hash; //!< hash entry, internal used - TreeNode *work; //!< working node, internal used. - int pos; //!< current position -} uffs_FindInfo; - - -URET uffs_GetObjectInfo(uffs_Object *obj, uffs_ObjectInfo *info, int *err); -URET uffs_FindObjectOpen(uffs_FindInfo *find_handle, uffs_Object *dir); -URET uffs_FindObjectOpenEx(uffs_FindInfo *f, uffs_Device *dev, int dir); -URET uffs_FindObjectFirst(uffs_ObjectInfo *info, uffs_FindInfo *find_handle); -URET uffs_FindObjectNext(uffs_ObjectInfo *info, uffs_FindInfo *find_handle); -URET uffs_FindObjectRewind(uffs_FindInfo *find_handle); -URET uffs_FindObjectClose(uffs_FindInfo * find_handle); - - -#ifdef __cplusplus -} -#endif - - -#endif - - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_flash.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_flash.h deleted file mode 100644 index 844d8ea231..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_flash.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_public.h - * \brief flash interface for UFFS - * \author Ricky Zheng - */ - -#ifndef _UFFS_FLASH_H_ -#define _UFFS_FLASH_H_ - -#include "uffs/uffs_types.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_fs.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -/** ECC options (uffs_StorageAttrSt.ecc_opt) */ -#define UFFS_ECC_NONE 0 //!< do not use ECC -#define UFFS_ECC_SOFT 1 //!< UFFS calculate the ECC -#define UFFS_ECC_HW 2 //!< Flash driver(or by hardware) calculate the ECC -#define UFFS_ECC_HW_AUTO 3 //!< Hardware calculate the ECC and automatically write to spare. - -#define UFFS_ECC_OPTION_STRING \ - { "none", "soft", "hw", "auto" } // index is the ecc option value. - -/** spare layout options (uffs_StorageAttrSt.layout_opt) */ -#define UFFS_LAYOUT_UFFS 0 //!< do layout by dev->attr information -#define UFFS_LAYOUT_FLASH 1 //!< flash driver do the layout - -#define UFFS_SPARE_LAYOUT_SIZE 16 //!< maximum spare layout array size, 2 segments - -/** flash operation return code */ -#define UFFS_FLASH_NO_ERR 0 //!< no error -#define UFFS_FLASH_ECC_OK 1 //!< bit-flip found, but corrected by ECC -#define UFFS_FLASH_NOT_SEALED 2 //!< page spare area is not sealed properly (only for ReadPageWithLayout()) -#define UFFS_FLASH_IO_ERR -1 //!< I/O error -#define UFFS_FLASH_ECC_FAIL -2 //!< ECC failed -#define UFFS_FLASH_BAD_BLK -3 //!< bad block -#define UFFS_FLASH_CRC_ERR -4 //!< CRC failed -#define UFFS_FLASH_UNKNOWN_ERR -100 //!< unkown error? - -#define UFFS_FLASH_HAVE_ERR(e) ((e) < 0) - -#if defined(CONFIG_BAD_BLOCK_POLICY_STRICT) -# define UFFS_FLASH_IS_BAD_BLOCK(e) \ - ((e) == UFFS_FLASH_ECC_FAIL || (e) == UFFS_FLASH_ECC_OK || (e) == UFFS_FLASH_BAD_BLK || (e) == UFFS_FLASH_CRC_ERR) -#else -# define UFFS_FLASH_IS_BAD_BLOCK(e) \ - ((e) == UFFS_FLASH_ECC_FAIL || (e) == UFFS_FLASH_BAD_BLK || (e) == UFFS_FLASH_CRC_ERR) -#endif - - -/** defines for page info (data length and data sum) */ -#define UFFS_PAGE_INFO_CLEAN 0xFFFFFFFF -#define UFFS_PAGE_INFO_IOERR 0xDEADFFFF -#define UFFS_PAGE_GET_LEN(info) (info & 0xFFFF) -#define UFFS_PAGE_GET_DSUM(info) (info >> 16) -#define UFFS_PAGE_MAKE_INFO(d_len, d_sum) ((d_sum << 16) | d_len) - -/** - * \struct uffs_StorageAttrSt - * \brief uffs device storage attribute, provide by nand specific file - */ -struct uffs_StorageAttrSt { - u32 total_blocks; //!< total blocks in this chip - u16 page_data_size; //!< page data size (physical page data size, e.g. 512) - u16 pages_per_block; //!< pages per block - u8 spare_size; //!< page spare size (physical page spare size, e.g. 16) - u8 block_status_offs; //!< block status byte offset in spare - int ecc_opt; //!< ecc option ( #UFFS_ECC_[NONE|SOFT|HW|HW_AUTO] ) - int layout_opt; //!< layout option (#UFFS_LAYOUT_UFFS or #UFFS_LAYOUT_FLASH) - int ecc_size; //!< ecc size in bytes - const u8 *ecc_layout; //!< page data ECC layout: [ofs1, size1, ofs2, size2, ..., 0xFF, 0] - const u8 *data_layout; //!< spare data layout: [ofs1, size1, ofs2, size2, ..., 0xFF, 0] - u8 _uffs_ecc_layout[UFFS_SPARE_LAYOUT_SIZE]; //!< uffs spare ecc layout - u8 _uffs_data_layout[UFFS_SPARE_LAYOUT_SIZE]; //!< uffs spare data layout - void *_private; //!< private data for storage attribute -}; - - -/** - * \struct uffs_FlashOpsSt - * \brief low level flash operations, should be implement in flash driver - */ -struct uffs_FlashOpsSt { - /** - * Initilize flash driver, called once when UFFS initilize partition - * - * \return 0 if no error, return -1 when failed. - * - * \note This function is optional. - */ - int (*InitFlash)(uffs_Device *dev); - - /** - * Release flash driver, called once when UFFS unmount partition - * - * \return 0 if no error, return -1 when failed. - * - * \note This function is optional. - */ - int (*ReleaseFlash)(uffs_Device *dev); - - /** - * Read a full nand page, UFFS do the layout. - * - * \param[out] ecc ecc of page data - * if ecc_opt is UFFS_ECC_HW, flash driver must calculate and return ecc of data(if ecc != NULL). - * if ecc_opt is UFFS_ECC_HW_AUTO, flash driver do ecc correction before return data and flash driver do not need to return ecc. - * if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_SOFT, flash driver do not need to calculate data ecc and return ecc. - * - * \return #UFFS_FLASH_NO_ERR: success and/or has no flip bits. - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_ECC_FAIL: page data has flip bits and ecc correct failed (when ecc_opt == UFFS_ECC_HW_AUTO) - * #UFFS_FLASH_ECC_OK: page data has flip bits and corrected by ecc (when ecc_opt == UFFS_ECC_HW_AUTO) - * #UFFS_FLASH_BAD_BLK: if the block is a bad block (e.g., the bad block mark byte is not 0xFF). - * - * \note if data is NULL, do not return data; if spare is NULL, do not return spare; if both data and spare are all NULL, - * then read bad block mark and return UFFS_FLASH_BAD_BLK if bad block mark is not 0xFF. - * - * \note pad 0xFF for calculating ECC if len < page_data_size - */ - int (*ReadPage)(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc, - u8 *spare, int spare_len); - - /** - * Read a full nand page, driver do the layout. - * - * \param[out] ecc ecc of page data - * if ecc_opt is UFFS_ECC_HW, flash driver must calculate and return ecc of data(if ecc != NULL). - * if ecc_opt is UFFS_ECC_HW_AUTO, flash driver do ecc correction before return data and flash driver do not need to return ecc. - * if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_SOFT, flash driver do not need calculate data ecc and return ecc. - * - * \param[out] ecc_store ecc store on spare area - * if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_HW_AUTO, do not need to return ecc_store. - * - * \note flash driver must provide this function if layout_opt is UFFS_LAYOUT_FLASH. - * UFFS will use this function (if exist) prio to 'ReadPageSpare()' - * - * \return #UFFS_FLASH_NO_ERR: success - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_ECC_FAIL: page data has flip bits and ecc correct failed (when ecc_opt == UFFS_ECC_HW_AUTO) - * #UFFS_FLASH_ECC_OK: page data has flip bits and corrected by ecc (when ecc_opt == UFFS_ECC_HW_AUTO) - * #UFFS_FLASH_BAD_BLK: if the block is a bad block (e.g., the bad block mark byte is not 0xFF) - * #UFFS_FLASH_NOT_SEALED: if the page spare is not sealed properly - * - * \note if data is NULL, do not return data; if ts is NULL, do not read tag; if both data and ts are NULL, - * then read bad block mark and return UFFS_FLASH_BAD_BLK if bad block mark is not 0xFF. - * - * \note flash driver DO NOT need to do ecc correction for tag, - * UFFS will take care of tag ecc. - */ - int (*ReadPageWithLayout)(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc, - uffs_TagStore *ts, u8 *ecc_store); - - /** - * Write a full page, UFFS do the layout for spare area. - * - * \note If you have ecc_opt UFFS_ECC_HW or UFFS_ECC_HW_AUTO, you MUST implement WritePageWithLayout(). - * Implement WritePage() function if you have ecc_opt UFFS_ECC_NONE or UFFS_ECC_SOFT and - * WritePageWithLayout() is not implemented. - * - * \note If data == NULL && spare == NULL, driver should mark this block as a 'bad block'. - * - * \return #UFFS_FLASH_NO_ERR: success - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_BAD_BLK: a bad block detected. - */ - int (*WritePage)(uffs_Device *dev, u32 block, u32 page, - const u8 *data, int data_len, const u8 *spare, int spare_len); - - /** - * Write full page, flash driver do the layout for spare area. - * - * \note if layout_opt is UFFS_LAYOUT_FLASH or ecc_opt is UFFS_ECC_HW/UFFS_ECC_HW_AUTO, flash driver MUST implement - * this function. UFFS will use this function (if provided) prio to 'WritePage()' - * - * \param[in] ecc ecc of data. if ecc_opt is UFFS_ECC_SOFT and this function is implemented, - * UFFS will calculate page data ecc and pass it to WritePageWithLayout(). - * if ecc_opt is UFFS_ECC_NONE/UFFS_ECC_HW/UFFS_ECC_HW_AUTO, UFFS pass ecc = NULL. - * - * \note If data == NULL && ts == NULL, driver should mark this block as a 'bad block'. - * - * \return #UFFS_FLASH_NO_ERR: success - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_BAD_BLK: a bad block detected. - */ - int (*WritePageWithLayout)(uffs_Device *dev, u32 block, u32 page, - const u8 *data, int data_len, const u8 *ecc, const uffs_TagStore *ts); - - /** - * Check block status. - * - * \note flash driver may maintain a bad block table to speed up bad block checking or - * it will require one or two read spare I/O to check block status. - * - * \note if this function is not implented by driver, UFFS check the block_status byte in spare. - * - * \return 1 if it's a bad block, 0 if it's not. - */ - int (*IsBadBlock)(uffs_Device *dev, u32 block); - - /** - * Mark a new bad block. - * - * \note if this function is not implemented, UFFS mark bad block by call 'WritePage()/WritePageWithLayout()' - * with: data == NULL && spare == NULL && ts == NULL. - * - * \return 0 if success, otherwise return -1. - */ - int (*MarkBadBlock)(uffs_Device *dev, u32 block); - - /** - * Erase a block, driver MUST implement this function. - * - * \return #UFFS_FLASH_NO_ERR: success - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_BAD_BLK: a bad block detected. - */ - int (*EraseBlock)(uffs_Device *dev, u32 block); -}; - -/** make spare from tag store and ecc */ -void uffs_FlashMakeSpare(uffs_Device *dev, const uffs_TagStore *ts, const u8 *ecc, u8* spare); - -/** unload tag and ecc from spare */ -void uffs_FlashUnloadSpare(uffs_Device *dev, const u8 *spare, struct uffs_TagStoreSt *ts, u8 *ecc); - -/** read page spare and fill to tag */ -int uffs_FlashReadPageTag(uffs_Device *dev, int block, int page, uffs_Tags *tag); - -/** read page data to page buf and do ECC correct */ -int uffs_FlashReadPage(uffs_Device *dev, int block, int page, uffs_Buf *buf, UBOOL skip_ecc); - -/** write page data and spare */ -int uffs_FlashWritePageCombine(uffs_Device *dev, int block, int page, uffs_Buf *buf, uffs_Tags *tag); - -/** Mark this block as bad block */ -int uffs_FlashMarkBadBlock(uffs_Device *dev, int block); - -/** Is this block a bad block ? */ -UBOOL uffs_FlashIsBadBlock(uffs_Device *dev, int block); - -/** Erase flash block */ -int uffs_FlashEraseBlock(uffs_Device *dev, int block); - -/* mark a clean page as 'dirty' (and 'invalid') */ -int uffs_FlashMarkDirtyPage(uffs_Device *dev, uffs_BlockInfo *bc, int page); - -/* check if the block pages are all clean */ -URET uffs_FlashCheckErasedBlock(uffs_Device *dev, int block); - -/** - * get page head info - * - * \return #UFFS_PAGE_INFO_IOERR if I/O error, otherwise return page info - */ -u32 uffs_FlashGetPageInfo(uffs_Device *dev, int block, int page); - -/** load uffs_FileInfo from flash storage */ -URET uffs_FlashReadFileinfoPhy(uffs_Device *dev, int block, int page, uffs_FileInfo *info); - -/** - * Initialize UFFS flash interface - */ -URET uffs_FlashInterfaceInit(uffs_Device *dev); - -/** - * Release UFFS flash interface - */ -URET uffs_FlashInterfaceRelease(uffs_Device *dev); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_fs.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_fs.h deleted file mode 100644 index 7bda09052e..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_fs.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fs.h - * \brief uffs basic file operations - * \author Ricky Zheng - */ - -#ifndef _UFFS_FS_H_ -#define _UFFS_FS_H_ - -#include "uffs/uffs_types.h" -#include "uffs/uffs.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_core.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -/** file object */ -struct uffs_ObjectSt { - /******* objects manager ********/ - int dev_lock_count; - int dev_get_count; - - /******** init level 0 ********/ - const char * name; //!< pointer to the start of name, for open or create - u32 name_len; //!< name length - u16 sum; //!< sum of name - uffs_Device *dev; //!< uffs device - u32 oflag; - u8 type; - u16 head_pages; //!< data pages on file head block - u16 parent; - - /******* init level 1 ********/ - TreeNode *node; //!< file entry node in tree - u16 serial; - - /******* output ******/ - int err; //!< error number - - /******* current *******/ - u32 pos; //!< current position in file - - /***** others *******/ - UBOOL attr_loaded; //!< attributes loaded ? - UBOOL open_succ; //!< U_TRUE or U_FALSE - -}; - -typedef struct uffs_ObjectSt uffs_Object; - - - -#define uffs_GetObjectErr(obj) ((obj)->err) -#define uffs_ClearObjectErr(obj) do { (obj)->err = UENOERR; } while (0) - -uffs_Pool * uffs_GetObjectPool(void); - -URET uffs_InitObjectBuf(void); -URET uffs_ReleaseObjectBuf(void); -int uffs_PutAllObjectBuf(uffs_Device *dev); -uffs_Object * uffs_GetObject(void); -void uffs_PutObject(uffs_Object *obj); -int uffs_GetObjectIndex(uffs_Object *obj); -uffs_Object * uffs_GetObjectByIndex(int idx); - - -/** - * Re-initialize an object. - * should call this function if you want to re-use an object. - */ -URET uffs_ReInitObject(uffs_Object *obj); - -URET uffs_ParseObject(uffs_Object *obj, const char *name); - -URET uffs_CreateObjectEx(uffs_Object *obj, uffs_Device *dev, - int dir, const char *name, int name_len, int oflag); -URET uffs_OpenObjectEx(uffs_Object *obj, uffs_Device *dev, - int dir, const char *name, int name_len, int oflag); - -URET uffs_OpenObject(uffs_Object *obj, const char *fullname, int oflag); -URET uffs_TruncateObject(uffs_Object *obj, u32 remain); -URET uffs_CreateObject(uffs_Object *obj, const char *fullname, int oflag); - -URET uffs_CloseObject(uffs_Object *obj); -int uffs_WriteObject(uffs_Object *obj, const void *data, int len); -int uffs_ReadObject(uffs_Object *obj, void *data, int len); -long uffs_SeekObject(uffs_Object *obj, long offset, int origin); -int uffs_GetCurOffset(uffs_Object *obj); -int uffs_EndOfFile(uffs_Object *obj); -URET uffs_FlushObject(uffs_Object *obj); - -URET uffs_RenameObject(const char *old_name, const char *new_name, int *err); -URET uffs_DeleteObject(const char * name, int *err); - -int uffs_GetFreeObjectHandlers(void); - - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_mem.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_mem.h deleted file mode 100644 index ad9a38f458..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_mem.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -#ifndef _UFFS_MEM_H_ -#define _UFFS_MEM_H_ - -#include "uffs/uffs_device.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -/** uffs memory allocator */ -typedef struct uffs_memAllocatorSt { - URET (*init)(struct uffs_DeviceSt *dev); //!< init memory allocator, setup buffer sizes - URET (*release)(struct uffs_DeviceSt *dev); //!< release memory allocator (for dynamic memory allocation) - - void * (*malloc)(struct uffs_DeviceSt *dev, unsigned int size); //!< allocate memory (for dynamic memory allocation) - URET (*free)(struct uffs_DeviceSt *dev, void *p); //!< free memory (for dynamic memory allocation) - - void * blockinfo_pool_buf; //!< block info cache buffers - void * pagebuf_pool_buf; //!< page buffers - void * tree_nodes_pool_buf; //!< tree nodes buffer - void * spare_pool_buf; //!< spare buffers - - int blockinfo_pool_size; //!< block info cache buffers size - int pagebuf_pool_size; //!< page buffers size - int tree_nodes_pool_size; //!< tree nodes buffer size - int spare_pool_size; //!< spare buffer pool size - - uffs_Pool tree_pool; - uffs_Pool spare_pool; - - int spare_data_size; //!< spare size consumed by UFFS, - //!< calculated by UFFS according to the layout information. - - /* for static memory allocator */ - char *buf_start; - int buf_size; - int pos; - - -} uffs_MemAllocator; - -void uffs_MemSetupSystemAllocator(uffs_MemAllocator *allocator); -void uffs_MemSetupStaticAllocator(uffs_MemAllocator *allocator, void *pool, int size); - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_mtb.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_mtb.h deleted file mode 100644 index 41259e57e9..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_mtb.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_mtb.h - * \brief mount table related stuff - * \author Ricky Zheng - */ - -#ifndef _UFFS_MTB_H_ -#define _UFFS_MTB_H_ - -#include "uffs/uffs_types.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -typedef struct uffs_MountTableEntrySt { - uffs_Device *dev; // UFFS 'device' - core internal data structure for partition - int start_block; // partition start block - int end_block; // partition end block ( if < 0, reserve space form the end of storage) - const char *mount; // mount point - struct uffs_MountTableEntrySt *prev; - struct uffs_MountTableEntrySt *next; -} uffs_MountTable; - -/** Register mount entry, will be put at 'unmounted' list */ -int uffs_RegisterMountTable(uffs_MountTable *mtb); - -/** Remove mount entry from the list */ -int uffs_UnRegisterMountTable(uffs_MountTable *mtb); - -/** mount partition */ -int uffs_Mount(const char *mount); - -/** unmount parttion */ -int uffs_UnMount(const char *mount); - -/** get mounted entry list */ -uffs_MountTable * uffs_MtbGetMounted(void); - -/** get unmounted entry list */ -uffs_MountTable * uffs_MtbGetUnMounted(void); - -/** get matched mount point from absolute path */ -int uffs_GetMatchedMountPointSize(const char *path); - -/** get uffs device from mount point */ -uffs_Device * uffs_GetDeviceFromMountPoint(const char *mount); - -/** get uffs device from mount point */ -uffs_Device * uffs_GetDeviceFromMountPointEx(const char *mount, int len); - -/** get mount point name from uffs device */ -const char * uffs_GetDeviceMountPoint(uffs_Device *dev); - -/** down crease uffs device references by uffs_GetDeviceXXX() */ -void uffs_PutDevice(uffs_Device *dev); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_os.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_os.h deleted file mode 100644 index b75e77bcc9..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_os.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -#ifndef _UFFS_OS_H_ -#define _UFFS_OS_H_ - -#include -#define RT_THREAD -#if !defined(RT_THREAD) -#include -#endif - -#ifdef __cplusplus -extern "C"{ -#endif - -#define UFFS_TASK_ID_NOT_EXIST -1 - -typedef void * OSSEM; -#define OSSEM_NOT_INITED (NULL) - -#if !defined(RT_THREAD) -struct uffs_DebugMsgOutputSt { - void (*output)(const char *msg); - void (*vprintf)(const char *fmt, va_list args); -}; - -void uffs_SetupDebugOutput(void); -#endif - -/* OS specific functions */ -int uffs_SemCreate(OSSEM *sem); -int uffs_SemWait(OSSEM sem); -int uffs_SemSignal(OSSEM sem); -int uffs_SemDelete(OSSEM *sem); - -int uffs_OSGetTaskId(void); //get current task id -unsigned int uffs_GetCurDateTime(void); - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_pool.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_pool.h deleted file mode 100644 index 78826fc246..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_pool.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_pool.h - * \brief Fast fixed size memory pool management. - * \author Ricky Zheng, Simon Kallweit - */ - -#ifndef _UFFS_POOL_H_ -#define _UFFS_POOL_H_ - - -#include "uffs/uffs_types.h" -#include "uffs/uffs_os.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -/** - * \struct uffs_PoolEntrySt - * \brief Helper type for free buffer entries. - */ -typedef struct uffs_PoolEntrySt { - struct uffs_PoolEntrySt *next; -} uffs_PoolEntry; - -/** - * \struct uffs_PoolSt - * \brief Memory pool. - */ -typedef struct uffs_PoolSt { - u8 *mem; //!< memory pool - u32 buf_size; //!< size of a buffer - u32 num_bufs; //!< number of buffers in the pool - uffs_PoolEntry *free_list; //!< linked list of free buffers - OSSEM sem; //!< buffer lock -} uffs_Pool; - -URET uffs_PoolInit(uffs_Pool *pool, void *mem, u32 mem_size, u32 buf_size, u32 num_bufs); -URET uffs_PoolRelease(uffs_Pool *pool); - -UBOOL uffs_PoolVerify(uffs_Pool *pool, void *p); - -void *uffs_PoolGet(uffs_Pool *pool); -void *uffs_PoolGetLocked(uffs_Pool *pool); - -int uffs_PoolPut(uffs_Pool *pool, void *p); -int uffs_PoolPutLocked(uffs_Pool *pool, void *p); - -void *uffs_PoolGetBufByIndex(uffs_Pool *pool, u32 index); -u32 uffs_PoolGetIndex(uffs_Pool *pool, void *p); -UBOOL uffs_PoolCheckFreeList(uffs_Pool *pool, void *p); - -void * uffs_PoolFindNextAllocated(uffs_Pool *pool, void *from); - -int uffs_PoolGetFreeCount(uffs_Pool *pool); -int uffs_PoolPutAll(uffs_Pool *pool); - -#ifdef __cplusplus -} -#endif - -#endif // _UFFS_POOL_H_ diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_public.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_public.h deleted file mode 100644 index 9c22004898..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_public.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_public.h - * \brief public data structures for uffs - * \author Ricky Zheng - */ - -#ifndef _UFFS_PUBLIC_H_ -#define _UFFS_PUBLIC_H_ - -#include "uffs/uffs_types.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs.h" -#include "uffs/uffs_pool.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])) -#endif - -#ifndef offsetof -# define offsetof(T, x) ((size_t) &((T *)0)->x) -#endif -#ifndef container_of -#define container_of(p, T, x) ((T *)((char *)(p) - offsetof(T,x))) -#endif - -/** - * \def MAX_FILENAME_LENGTH - * \note Be careful: it's part of the physical format (see: uffs_FileInfoSt.name) - * !!DO NOT CHANGE IT AFTER FILE SYSTEM IS FORMATED!! - */ -#define MAX_FILENAME_LENGTH 128 - -/** \note 8-bits attr goes to uffs_dirent::d_type */ -#define FILE_ATTR_DIR (1 << 7) //!< attribute for directory -#define FILE_ATTR_WRITE (1 << 0) //!< writable - - -/** - * \structure uffs_FileInfoSt - * \brief file/dir entry info in physical storage format - */ -struct uffs_FileInfoSt { - u32 attr; //!< file/dir attribute - u32 create_time; - u32 last_modify; - u32 access; - u32 reserved; - u32 name_len; //!< length of file/dir name - char name[MAX_FILENAME_LENGTH]; -}; //6*4 + sizeof(name) = 24 + 128 = 152 Bytes -typedef struct uffs_FileInfoSt uffs_FileInfo; - -/** - * \struct uffs_ObjectInfoSt - * \brief object info - */ -typedef struct uffs_ObjectInfoSt { - uffs_FileInfo info; - u32 len; //!< length of file - u16 serial; //!< object serial num -} uffs_ObjectInfo; - - -/** - * \struct uffs_TagStoreSt - * \brief uffs tag, 8 bytes, will be store in page spare area. - */ -struct uffs_TagStoreSt { - u32 dirty:1; //!< 0: dirty, 1: clear - u32 valid:1; //!< 0: valid, 1: invalid - u32 type:2; //!< block type: #UFFS_TYPE_DIR, #UFFS_TYPE_FILE, #UFFS_TYPE_DATA - u32 block_ts:2; //!< time stamp of block; - u32 data_len:12; //!< length of page data - u32 serial:14; //!< serial number - - u32 parent:10; //!< parent's serial number - u32 page_id:6; //!< page id - u32 reserved:4; //!< reserved, for UFFS2 - u32 tag_ecc:12; //!< tag ECC -}; - -#define TAG_ECC_DEFAULT (0xFFF) //!< 12-bit '1' - - -/** - * \struct uffs_TagsSt - */ -struct uffs_TagsSt { - struct uffs_TagStoreSt s; /* store must be the first member */ - - /** data_sum for file or dir name */ - u16 data_sum; - - /** internal used */ - u8 seal_byte; //!< seal byte. -}; - -/** - * \struct uffs_MiniHeaderSt - * \brief the mini header resides on the head of page data - */ -struct uffs_MiniHeaderSt { - u8 status; - u8 reserved; - u16 crc; -}; - - -/** uffs_TagsSt.dirty */ -#define TAG_VALID 0 -#define TAG_INVALID 1 - -/** uffs_TagsSt.valid */ -#define TAG_DIRTY 0 -#define TAG_CLEAR 1 - -#define TAG_IS_DIRTY(tag) (*((u32 *) &((tag)->s)) != 0xFFFFFFFF) // tag is dirty if first 4 bytes not all 0xFF -#define TAG_IS_VALID(tag) ((tag)->s.valid == TAG_VALID) -#define TAG_IS_SEALED(tag) ((tag)->seal_byte != 0xFF) - -#define TAG_IS_GOOD(tag) (TAG_IS_SEALED(tag) && TAG_IS_VALID(tag)) - -#define TAG_VALID_BIT(tag) (tag)->s.valid -#define TAG_DIRTY_BIT(tag) (tag)->s.dirty -#define TAG_SERIAL(tag) (tag)->s.serial -#define TAG_PARENT(tag) (tag)->s.parent -#define TAG_PAGE_ID(tag) (tag)->s.page_id -#define TAG_DATA_LEN(tag) (tag)->s.data_len -#define TAG_TYPE(tag) (tag)->s.type -#define TAG_BLOCK_TS(tag) (tag)->s.block_ts -#define SEAL_TAG(tag) (tag)->seal_byte = 0 - -int uffs_GetFirstBlockTimeStamp(void); -int uffs_GetNextBlockTimeStamp(int prev); -UBOOL uffs_IsSrcNewerThanObj(int src, int obj); - - -#include "uffs_device.h" - - - -/********************************** debug & error *************************************/ -#define UFFS_MSG_NOISY -1 -#define UFFS_MSG_NORMAL 0 -#define UFFS_MSG_SERIOUS 1 -#define UFFS_MSG_DEAD 2 -#define UFFS_MSG_NOMSG 100 - -#define TENDSTR "\n" - -#if !defined(RT_THREAD) -struct uffs_DebugMsgOutputSt; -URET uffs_InitDebugMessageOutput(struct uffs_DebugMsgOutputSt *ops, int msg_level); -void uffs_DebugSetMessageLevel(int msg_level); - -void uffs_DebugMessage(int level, const char *prefix, const char *suffix, const char *errFmt, ...); -void uffs_AssertCall(const char *file, int line, const char *msg, ...); -#else - -#define UFFS_DBG_LEVEL UFFS_MSG_NORMAL - -#ifdef CONFIG_ENABLE_UFFS_DEBUG_MSG -#define uffs_DebugMessage(level, prefix, suffix, errFmt, ...) do { \ - if (level >= UFFS_DBG_LEVEL) \ - rt_kprintf(prefix errFmt suffix, ##__VA_ARGS__); \ -} while(0) - -#define uffs_AssertCall(file, line, msg, ...) \ - rt_kprintf("ASSERT %s:%d - :" msg "\n", (const char *)file, (int)line, ##__VA_ARGS__) -#else -#define uffs_DebugMessage(level, prefix, suffix, errFmt, ...) -#define uffs_AssertCall(file, line, msg, ...) -#endif //CONFIG_ENABLE_UFFS_DEBUG_MSG -#endif //RT_THREAD - -#ifdef _COMPILER_DO_NOT_SUPPORT_MACRO_VALIST_REPLACE_ -/* For those compilers do not support valist parameter replace in macro define */ -void uffs_Perror(int level, const char *fmt, ...); -void uffs_PerrorRaw(int level, const char *fmt, ...); -UBOOL uffs_Assert(UBOOL expr, const char *fmt, ...); -#else - -#if !defined(RT_THREAD) -#define uffs_Perror(level, fmt, ... ) \ - uffs_DebugMessage(level, PFX, TENDSTR, fmt, ## __VA_ARGS__) - -#define uffs_PerrorRaw(level, fmt, ... ) \ - uffs_DebugMessage(level, NULL, NULL, fmt, ## __VA_ARGS__) - -#else - -#ifdef CONFIG_ENABLE_UFFS_DEBUG_MSG - -#define uffs_Perror(level, fmt, ... ) do{\ - if (level >= UFFS_DBG_LEVEL) \ - rt_kprintf(PFX fmt TENDSTR, ##__VA_ARGS__); \ -} while(0) - -#define uffs_PerrorRaw(level, fmt, ... ) do{\ - if (level >= UFFS_DBG_LEVEL) \ - rt_kprintf(fmt, ##__VA_ARGS__); \ -} while(0) -#else -#define uffs_Perror(level, fmt, ... ) -#define uffs_PerrorRaw(level, fmt, ... ) -#endif // CONFIG_ENABLE_UFFS_DEBUG_MSG -#endif // RT_THREAD - -#define uffs_Assert(expr, msg, ...) \ - ((expr) ? U_TRUE : (uffs_AssertCall(__FILE__, __LINE__, msg, ## __VA_ARGS__), U_FALSE)) - -#endif //_COMPILER_DO_NOT_SUPPORT_MACRO_VALIST_REPLACE_ - -#define uffs_Panic() \ - do { \ - uffs_AssertCall(__FILE__, __LINE__, "Bam !!\n"); \ - while(1); \ - } while(0) - -/********************************** NAND **********************************************/ -//NAND flash specific file must implement these interface -URET uffs_LoadPageSpare(uffs_Device *dev, int block, int page, uffs_Tags *tag); -URET uffs_WritePageSpare(uffs_Device *dev, int block, int page, uffs_Tags *tag); -URET uffs_MakePageValid(uffs_Device *dev, int block, int page, uffs_Tags *tag); -UBOOL uffs_IsBlockBad(uffs_Device *dev, uffs_BlockInfo *bc); - -/********************************** Public defines *****************************/ -/** - * \def UFFS_ALL_PAGES - * \brief UFFS_ALL_PAGES if this value presented, that means the objects are all pages in the block - */ -#define UFFS_ALL_PAGES (0xffff) - -/** - * \def UFFS_INVALID_PAGE - * \brief macro for invalid page number - */ -#define UFFS_INVALID_PAGE (0xfffe) - -/** - * \def UFFS_INVALID_BLOCK - * \brief macro for invalid block number - */ -#define UFFS_INVALID_BLOCK (0xfffe) - - -URET uffs_NewBlock(uffs_Device *dev, u16 block, uffs_Tags *tag, uffs_Buf *buf); -URET uffs_BlockRecover(uffs_Device *dev, uffs_BlockInfo *old, u16 newBlock); -URET uffs_PageRecover(uffs_Device *dev, - uffs_BlockInfo *bc, - u16 oldPage, - u16 newPage, - uffs_Buf *buf); -int uffs_FindFreePageInBlock(uffs_Device *dev, uffs_BlockInfo *bc); -u16 uffs_FindBestPageInBlock(uffs_Device *dev, uffs_BlockInfo *bc, u16 page); -u16 uffs_FindFirstFreePage(uffs_Device *dev, uffs_BlockInfo *bc, u16 pageFrom); -u16 uffs_FindPageInBlockWithPageId(uffs_Device *dev, uffs_BlockInfo *bc, u16 page_id); - -u8 uffs_MakeSum8(const void *p, int len); -u16 uffs_MakeSum16(const void *p, int len); -URET uffs_CreateNewFile(uffs_Device *dev, u16 parent, u16 serial, uffs_BlockInfo *bc, uffs_FileInfo *fi); - -int uffs_GetBlockFileDataLength(uffs_Device *dev, uffs_BlockInfo *bc, u8 type); -UBOOL uffs_IsPageErased(uffs_Device *dev, uffs_BlockInfo *bc, u16 page); -int uffs_GetFreePagesCount(uffs_Device *dev, uffs_BlockInfo *bc); -UBOOL uffs_IsDataBlockReguFull(uffs_Device *dev, uffs_BlockInfo *bc); -UBOOL uffs_IsThisBlockUsed(uffs_Device *dev, uffs_BlockInfo *bc); - -int uffs_GetBlockTimeStamp(uffs_Device *dev, uffs_BlockInfo *bc); - -int uffs_GetDeviceUsed(uffs_Device *dev); -int uffs_GetDeviceFree(uffs_Device *dev); -int uffs_GetDeviceTotal(uffs_Device *dev); - -URET uffs_LoadMiniHeader(uffs_Device *dev, int block, u16 page, struct uffs_MiniHeaderSt *header); - - -/* some functions from uffs_fd.c */ -void uffs_FdSignatureIncrease(void); -URET uffs_DirEntryBufInit(void); -URET uffs_DirEntryBufRelease(void); -uffs_Pool * uffs_DirEntryBufGetPool(void); -int uffs_DirEntryBufPutAll(uffs_Device *dev); - - -/************************************************************************/ -/* init functions */ -/************************************************************************/ -URET uffs_InitDevice(uffs_Device *dev); -URET uffs_ReleaseDevice(uffs_Device *dev); - -URET uffs_InitFileSystemObjects(void); -URET uffs_ReleaseFileSystemObjects(void); - - -#ifdef __cplusplus -} -#endif -#endif // _UFFS_PUBLIC_H_ - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_tree.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_tree.h deleted file mode 100644 index 6a505a839f..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_tree.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -#ifndef _UFFS_TREE_H_ -#define _UFFS_TREE_H_ - -#include "uffs/uffs_types.h" -#include "uffs/uffs_pool.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_core.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#define UFFS_TYPE_DIR 0 -#define UFFS_TYPE_FILE 1 -#define UFFS_TYPE_DATA 2 -#define UFFS_TYPE_RESV 3 -#define UFFS_TYPE_INVALID 0xFF - -struct uffs_NodeTypeNameMapSt { - int type; - const char *name; -}; - -#define UFFS_TYPE_NAME_MAP { \ - {UFFS_TYPE_DIR, "DIR"}, \ - {UFFS_TYPE_FILE, "FILE"}, \ - {UFFS_TYPE_DATA, "DATA"}, \ - {UFFS_TYPE_RESV, "RESV"}, \ - {UFFS_TYPE_INVALID, "INVALID"} \ -} - -struct BlockListSt { /* 12 bytes */ - struct uffs_TreeNodeSt * next; - struct uffs_TreeNodeSt * prev; - u16 block; - union { - u16 serial; /* for suspended block list */ - u8 need_check; /* for erased block list */ - } u; -}; - -struct DirhSt { /* 8 bytes */ - u16 checksum; /* check sum of dir name */ - u16 block; - u16 parent; - u16 serial; -}; - - -struct FilehSt { /* 12 bytes */ - u16 block; - u16 checksum; /* check sum of file name */ - u16 parent; - u16 serial; - u32 len; /* file length total */ -}; - -struct FdataSt { /* 10 bytes */ - u16 block; - u16 parent; - u32 len; /* file data length on this block */ - u16 serial; -}; - -//UFFS TreeNode (14 or 16 bytes) -typedef struct uffs_TreeNodeSt { - union { - struct BlockListSt list; - struct DirhSt dir; - struct FilehSt file; - struct FdataSt data; - } u; - u16 hash_next; - u16 hash_prev; -} TreeNode; - - -//TODO: UFFS2 Tree structures -/* -struct FdataSt { - u32 len; -}; - -struct filebSt { - u16 bls; //how many blocks this file contents ... - u8 offs; //the offset of this file header on FILE block - u8 sum; //short sum of file name -}; - -//Extra data structure for storing file length information -struct FilehSt { - u32 len; -}; - -//UFFS2 TreeNode (12 bytes) -typedef struct uffs_TreeNodeSt { - u16 nextIdx; - u16 block; - u16 parent; - u16 serial; - union { - struct FilehSt h; - struct filedSt file; - struct data; - } u; -} TreeNode; - -*/ - - -#define EMPTY_NODE 0xffff //!< special index num of empty node. - -#define ROOT_DIR_SERIAL 0 //!< serial num of root dir -#define MAX_UFFS_FSN 0x3ff //!< maximum dir|file serial number (uffs_TagStore#parent: 10 bits) -#define MAX_UFFS_FDN 0x3fff //!< maximum file data block serial numbers (uffs_TagStore#serial: 14 bits) -#define PARENT_OF_ROOT 0xfffd //!< parent of ROOT ? kidding me ... -#define INVALID_UFFS_SERIAL 0xffff //!< invalid serial num - -#define DIR_NODE_HASH_MASK 0x1f -#define DIR_NODE_ENTRY_LEN (DIR_NODE_HASH_MASK + 1) - -#define FILE_NODE_HASH_MASK 0x3f -#define FILE_NODE_ENTRY_LEN (FILE_NODE_HASH_MASK + 1) - -#define DATA_NODE_HASH_MASK 0x1ff -#define DATA_NODE_ENTRY_LEN (DATA_NODE_HASH_MASK + 1) -#define FROM_IDX(idx, pool) ((TreeNode *)uffs_PoolGetBufByIndex(pool, idx)) -#define TO_IDX(p, pool) ((u16)uffs_PoolGetIndex(pool, (void *) p)) - - -#define GET_FILE_HASH(serial) (serial & FILE_NODE_HASH_MASK) -#define GET_DIR_HASH(serial) (serial & DIR_NODE_HASH_MASK) -#define GET_DATA_HASH(parent, serial) ((parent + serial) & DATA_NODE_HASH_MASK) - - -struct uffs_TreeSt { - TreeNode *erased; //!< erased block list head - TreeNode *erased_tail; //!< erased block list tail - TreeNode *suspend; //!< suspended block list - int erased_count; //!< erased block counter - TreeNode *bad; //!< bad block list - int bad_count; //!< bad block count - u16 dir_entry[DIR_NODE_ENTRY_LEN]; - u16 file_entry[FILE_NODE_ENTRY_LEN]; - u16 data_entry[DATA_NODE_ENTRY_LEN]; - u16 max_serial; -}; - - -URET uffs_TreeInit(uffs_Device *dev); -URET uffs_TreeRelease(uffs_Device *dev); -URET uffs_BuildTree(uffs_Device *dev); -u16 uffs_FindFreeFsnSerial(uffs_Device *dev); -TreeNode * uffs_TreeFindFileNode(uffs_Device *dev, u16 serial); -TreeNode * uffs_TreeFindFileNodeWithParent(uffs_Device *dev, u16 parent); -TreeNode * uffs_TreeFindDirNode(uffs_Device *dev, u16 serial); -TreeNode * uffs_TreeFindDirNodeWithParent(uffs_Device *dev, u16 parent); -TreeNode * uffs_TreeFindFileNodeByName(uffs_Device *dev, const char *name, u32 len, u16 sum, u16 parent); -TreeNode * uffs_TreeFindDirNodeByName(uffs_Device *dev, const char *name, u32 len, u16 sum, u16 parent); -TreeNode * uffs_TreeFindDataNode(uffs_Device *dev, u16 parent, u16 serial); - - -TreeNode * uffs_TreeFindDirNodeByBlock(uffs_Device *dev, u16 block); -TreeNode * uffs_TreeFindFileNodeByBlock(uffs_Device *dev, u16 block); -TreeNode * uffs_TreeFindDataNodeByBlock(uffs_Device *dev, u16 block); -TreeNode * uffs_TreeFindErasedNodeByBlock(uffs_Device *dev, u16 block); -TreeNode * uffs_TreeFindBadNodeByBlock(uffs_Device *dev, u16 block); - -void uffs_TreeSuspendAdd(uffs_Device *dev, TreeNode *node); -TreeNode * uffs_TreeFindSuspendNode(uffs_Device *dev, u16 serial); -void uffs_TreeRemoveSuspendNode(uffs_Device *dev, TreeNode *node); - -#define SEARCH_REGION_DIR 1 -#define SEARCH_REGION_FILE 2 -#define SEARCH_REGION_DATA 4 -#define SEARCH_REGION_BAD 8 -#define SEARCH_REGION_ERASED 16 -TreeNode * uffs_TreeFindNodeByBlock(uffs_Device *dev, u16 block, int *region); - - - -UBOOL uffs_TreeCompareFileName(uffs_Device *dev, const char *name, u32 len, u16 sum, TreeNode *node, int type); - -TreeNode * uffs_TreeGetErasedNode(uffs_Device *dev); - -void uffs_InsertNodeToTree(uffs_Device *dev, u8 type, TreeNode *node); -void uffs_InsertToErasedListHead(uffs_Device *dev, TreeNode *node); -void uffs_TreeInsertToErasedListTail(uffs_Device *dev, TreeNode *node); -void uffs_TreeInsertToErasedListTailEx(uffs_Device *dev, TreeNode *node, int need_check); -void uffs_TreeInsertToBadBlockList(uffs_Device *dev, TreeNode *node); - -void uffs_BreakFromEntry(uffs_Device *dev, u8 type, TreeNode *node); - -void uffs_TreeSetNodeBlock(u8 type, TreeNode *node, u16 block); - - -#ifdef __cplusplus -} -#endif - - - -#endif - - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_types.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_types.h deleted file mode 100644 index c81b37970b..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_types.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -#ifndef _UFFS_TYPES_H_ -#define _UFFS_TYPES_H_ - -#ifdef __CDT_PARSER__ -#undef __cplusplus -#endif - -#ifdef __cplusplus -extern "C"{ -#endif - -#ifdef _UBASE_ -#include -#endif - -/** - * \file uffs_types.h - * \brief basic types used on uffs - * \author Ricky Zheng - */ - -/* basic types */ - -/** \typedef i8 - * \brief 8 bit integer - */ -typedef char i8; - -/** \typedef u8 - * \brief 8 bit unsigned integer - */ -typedef unsigned char u8; - -/** \typedef i16 - * \brief 16 bit integer - */ -typedef short int i16; - - -/** \typedef u16 - * \brief 16 bit unsigned integer - */ -typedef unsigned short int u16; - - -/** \typedef i32 - * \brief 32 bit integer - */ -typedef int i32; - -/** \typedef u32 - * \brief 32 bit unsigned integer - */ -typedef unsigned int u32; - - -#ifndef _UBASE_ - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -/* boolean type */ - -/** \typedef UBOOL - * \brief boolean type for uffs, the value would be: #U_TRUE or #U_FALSE - */ -typedef int UBOOL; - -/** \def U_TRUE - * \brief boolean true for uffs - */ -#define U_TRUE (TRUE) - - -/** \def U_FALSE - * \brief boolean false for uffs - */ -#define U_FALSE (FALSE) - - -/** \typedef URET - * \brief return type for uffs, should be #U_FAIL or #U_SUCC - */ -typedef int URET; - -/** \def U_FAIL - * \brief indicator of fail - */ -#define U_FAIL -1 - -/** \def U_SUCC - * \brief indicator of successful - */ -#define U_SUCC 0 - -/** \def IS_SUCC(ret) - * \brief is it successful ? - */ -#define IS_SUCC(ret) (ret >= 0 ? U_TRUE : U_FALSE) - - -/** \def IS_FAIL(ret) - * \brief is it fail ? - */ -#define IS_FAIL(ret) (ret < 0 ? U_TRUE : U_FALSE) - -#ifndef NULL -/** \def NULL - * \brief zero for pointer - */ -#define NULL 0 -#endif - -#endif // _UBASE_ - - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_utils.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_utils.h deleted file mode 100644 index ae03cb4ab1..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_utils.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -#ifndef _UFFS_UTILS_H_ -#define _UFFS_UTILS_H_ - -#include "uffs/uffs_types.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_core.h" - -#ifdef __cplusplus -extern "C"{ -#endif - - -//get UFFS disk version, if fail, return 0 -int uffs_GetUFFSVersion(struct uffs_DeviceSt *dev); - -void uffs_InitGlobalFsLock(void); -void uffs_ReleaseGlobalFsLock(void); -void uffs_GlobalFsLockLock(void); -void uffs_GlobalFsLockUnlock(void); - -URET uffs_FormatDevice(uffs_Device *dev, UBOOL force); - -#ifdef __cplusplus -} -#endif - -typedef void dump_msg_cb(struct uffs_DeviceSt *dev, const char *fmt, ...); - -void uffs_DumpDevice(struct uffs_DeviceSt *dev, dump_msg_cb *dump); - -#endif - diff --git a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_version.h b/components/dfs/filesystems/uffs/src/inc/uffs/uffs_version.h deleted file mode 100644 index 9ea3154205..0000000000 --- a/components/dfs/filesystems/uffs/src/inc/uffs/uffs_version.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -#ifndef _UFFS_VERSION_H_ -#define _UFFS_VERSION_H_ - -#ifdef __cplusplus -extern "C"{ -#endif - - -#define UFFS_VERSION 0x01030400 //"01.03.0400" - -const char * uffs_Version2Str(int ver); -int uffs_GetVersion(void); -int uffs_GetMainVersion(int ver); -int uffs_GetMinorVersion(int ver); -int uffs_GetTrivialVersion(int ver); - -#ifdef __cplusplus -} -#endif - - -#endif - diff --git a/components/dfs/filesystems/uffs/src/platform/CMakeLists.txt b/components/dfs/filesystems/uffs/src/platform/CMakeLists.txt deleted file mode 100644 index dd33c737e5..0000000000 --- a/components/dfs/filesystems/uffs/src/platform/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -IF (UNIX) - SET (libplatform_SRCS posix/uffs_os.c posix/uffs_config.h) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/posix) -ENDIF() - -IF (WIN32) - SET (libplatform_SRCS win32/uffs_os.c win32/uffs_config.h) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/win32) -ENDIF() - -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/inc) -ADD_LIBRARY(platform STATIC ${libplatform_SRCS} ) - diff --git a/components/dfs/filesystems/uffs/src/platform/posix/uffs_config.h b/components/dfs/filesystems/uffs/src/platform/posix/uffs_config.h deleted file mode 100644 index 2f0b6992bb..0000000000 --- a/components/dfs/filesystems/uffs/src/platform/posix/uffs_config.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_config.h - * \brief basic configuration of uffs - * \author Ricky Zheng - */ - -#ifndef _UFFS_CONFIG_H_ -#define _UFFS_CONFIG_H_ - -/** - * \def UFFS_MAX_PAGE_SIZE - * \note maximum page size UFFS support - */ -#define UFFS_MAX_PAGE_SIZE 2048 - -/** - * \def UFFS_MAX_SPARE_SIZE - */ -#define UFFS_MAX_SPARE_SIZE ((UFFS_MAX_PAGE_SIZE / 256) * 8) - -/** - * \def UFFS_MAX_ECC_SIZE - */ -#define UFFS_MAX_ECC_SIZE ((UFFS_MAX_PAGE_SIZE / 256) * 5) - -/** - * \def MAX_CACHED_BLOCK_INFO - * \note uffs cache the block info for opened directories and files, - * a practical value is 5 ~ MAX_OBJECT_HANDLE - */ -#define MAX_CACHED_BLOCK_INFO 50 - -/** - * \def MAX_PAGE_BUFFERS - * \note the bigger value will bring better read/write performance. - * but few writing performance will be improved when this - * value is become larger than 'max pages per block' - */ -#define MAX_PAGE_BUFFERS 40 - - -/** - * \def CLONE_BUFFER_THRESHOLD - * \note reserve buffers for clone. 1 or 2 should be enough. - */ -#define CLONE_BUFFERS_THRESHOLD 2 - -/** - * \def MAX_SPARE_BUFFERS - * \note spare buffers are used for lower level flash operations, - * 5 should be enough. - */ -#define MAX_SPARE_BUFFERS 5 - - -/** - * \def MAX_DIRTY_PAGES_IN_A_BLOCK - * \note this value should be between '2' and the lesser of - * 'max pages per block' and (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD - 1). - * - * the smaller the value the frequently the buffer will be flushed. - */ -#define MAX_DIRTY_PAGES_IN_A_BLOCK 32 - -/** - * \def MAX_DIRTY_BUF_GROUPS - */ -#define MAX_DIRTY_BUF_GROUPS 3 - -/** - * \def CONFIG_ENABLE_UFFS_DEBUG_MSG - * \note Enable debug message output. You must call uffs_InitDebugMessageOutput() - * to initialize debug apart from enable debug feature. - */ -#define CONFIG_ENABLE_UFFS_DEBUG_MSG - -/** - * \def CONFIG_USE_GLOBAL_FS_LOCK - * \note use global lock instead of per-device lock. - * this is required if you use fd APIs in multi-thread environment. - */ -#define CONFIG_USE_GLOBAL_FS_LOCK - - -/** - * \def CONFIG_USE_PER_DEVICE_LOCK - * \note use per-device lock. - * this is required if you use fs APIs in multi-thread environment. - */ -//#define CONFIG_USE_PER_DEVICE_LOCK - - - -/** - * \def CONFIG_USE_STATIC_MEMORY_ALLOCATOR - * \note uffs will use static memory allocator if this is defined. - * to use static memory allocator, you need to provide memory - * buffer when creating uffs_Device. - * - * use UFFS_STATIC_BUFF_SIZE() to calculate memory buffer size. - */ -#define CONFIG_USE_STATIC_MEMORY_ALLOCATOR 0 - -/** - * \def CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR - * \note using system platform's 'malloc' and 'free'. - */ -#define CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR 1 - - - -/** - * \def CONFIG_FLUSH_BUF_AFTER_WRITE - * \note UFFS will write all data directly into flash in - * each 'write' call if you enable this option. - * (which means lesser data lost when power failure but - * poorer writing performance). - * It's not recommended to open this define for normal applications. - */ -#define CONFIG_FLUSH_BUF_AFTER_WRITE - - -/** - * \def CONFIG_UFFS_AUTO_LAYOUT_MTD_COMP - * \note Use Linux MTD compatiable spare placement for UFFS_LAYOUT_AUTO, - * only valid for page data size 512 or 2048. - */ -//#define CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME - - -/** - * \def MAX_OBJECT_HANDLE - * maximum number of object handle - */ -#define MAX_OBJECT_HANDLE 50 -#define FD_SIGNATURE_SHIFT 6 - - -/** - * \def MAX_DIR_HANDLE - * maximum number of uffs_DIR - */ -#define MAX_DIR_HANDLE 10 - -/** - * \def MINIMUN_ERASED_BLOCK - * UFFS will not allow appending or creating new files when the free/erased block - * is lower then MINIMUN_ERASED_BLOCK. - */ -#define MINIMUN_ERASED_BLOCK 2 - -/** - * \def CONFIG_CHANGE_MODIFY_TIME - * \note If defined, closing a file which is opened for writing/appending will - * update the file's modify time as well. Disable this feature will save a - * lot of writing activities if you frequently open files for write and close it. - */ -//#define CONFIG_CHANGE_MODIFY_TIME - - -/** - * \def CONFIG_ENABLE_BAD_BLOCK_VERIFY - * \note allow erase and verify block marked as 'bad' when format UFFS partition. - * it's not recommended for most NAND flash. - */ -#define CONFIG_ENABLE_BAD_BLOCK_VERIFY - -/** - * \def CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - * \note erase block again before mark bad block - */ -//#define CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - -/** - * \def CONFIG_PAGE_WRITE_VERIFY - * \note verify page data after write, for extra safe data storage. - */ -#define CONFIG_PAGE_WRITE_VERIFY - -/** - * \def CONFIG_BAD_BLOCK_POLICY_STRICT - * \note If this is enabled, UFFS will report the block as 'bad' if any bit-flips found; - * otherwise, UFFS report bad block only when ECC failed or reported - * by low level flash driver. - * - * \note Enable this will ensure your data always be stored on completely good blocks. - */ -#define CONFIG_BAD_BLOCK_POLICY_STRICT - - -/** - * \def CONFIG_ENABLE_PAGE_DATA_CRC - * \note If this is enabled, UFFS save page data CRC16 sum in mini header, - * it provides extra protection for data integrity. - */ -#define CONFIG_ENABLE_PAGE_DATA_CRC - - -/** micros for calculating buffer sizes */ - -/** - * \def UFFS_BLOCK_INFO_BUFFER_SIZE - * \brief calculate memory bytes for block info caches - */ -#define UFFS_BLOCK_INFO_BUFFER_SIZE(n_pages_per_block) \ - ( \ - ( \ - sizeof(uffs_BlockInfo) + \ - sizeof(uffs_PageSpare) * n_pages_per_block \ - ) * MAX_CACHED_BLOCK_INFO \ - ) - -/** - * \def UFFS_PAGE_BUFFER_SIZE - * \brief calculate memory bytes for page buffers - */ -#define UFFS_PAGE_BUFFER_SIZE(n_page_size) \ - ( \ - ( \ - sizeof(uffs_Buf) + n_page_size \ - ) * MAX_PAGE_BUFFERS \ - ) - -/** - * \def UFFS_TREE_BUFFER_SIZE - * \brief calculate memory bytes for tree nodes - */ -#define UFFS_TREE_BUFFER_SIZE(n_blocks) (sizeof(TreeNode) * n_blocks) - - -#define UFFS_SPARE_BUFFER_SIZE (MAX_SPARE_BUFFERS * UFFS_MAX_SPARE_SIZE) - - -/** - * \def UFFS_STATIC_BUFF_SIZE - * \brief calculate total memory usage of uffs system - */ -#define UFFS_STATIC_BUFF_SIZE(n_pages_per_block, n_page_size, n_blocks) \ - ( \ - UFFS_BLOCK_INFO_BUFFER_SIZE(n_pages_per_block) + \ - UFFS_PAGE_BUFFER_SIZE(n_page_size) + \ - UFFS_TREE_BUFFER_SIZE(n_blocks) + \ - UFFS_SPARE_BUFFER_SIZE \ - ) - - - -/* config check */ -#if (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD) < 3 -#error "MAX_PAGE_BUFFERS is too small" -#endif - -#if (MAX_DIRTY_PAGES_IN_A_BLOCK < 2) -#error "MAX_DIRTY_PAGES_IN_A_BLOCK should >= 2" -#endif - -#if (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD - 1 < MAX_DIRTY_PAGES_IN_A_BLOCK) -#error "MAX_DIRTY_PAGES_IN_A_BLOCK should < (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD)" -#endif - -#if defined(CONFIG_PAGE_WRITE_VERIFY) && (CLONE_BUFFERS_THRESHOLD < 2) -#error "CLONE_BUFFERS_THRESHOLD should >= 2 when CONFIG_PAGE_WRITE_VERIFY is enabled." -#endif - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR + CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 1 -#error "Please enable ONLY one memory allocator" -#endif - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR + CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR == 0 -#error "Please enable ONE of memory allocators" -#endif - -#if defined(CONFIG_USE_GLOBAL_FS_LOCK) && defined(CONFIG_USE_PER_DEVICE_LOCK) -#error "enable either CONFIG_USE_GLOBAL_FS_LOCK or CONFIG_USE_PER_DEVICE_LOCK, not both" -#endif - -#if (MAX_OBJECT_HANDLE > (1 << FD_SIGNATURE_SHIFT)) -#error "Please increase FD_SIGNATURE_SHIFT !" -#endif - -#ifdef WIN32 -# pragma warning(disable : 4996) -# pragma warning(disable : 4244) -# pragma warning(disable : 4214) -# pragma warning(disable : 4127) -# pragma warning(disable : 4389) -# pragma warning(disable : 4100) -#endif - -#endif diff --git a/components/dfs/filesystems/uffs/src/platform/posix/uffs_os.c b/components/dfs/filesystems/uffs/src/platform/posix/uffs_os.c deleted file mode 100644 index 170c457ad4..0000000000 --- a/components/dfs/filesystems/uffs/src/platform/posix/uffs_os.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_os_posix.c - * \brief Emulation on POSIX host. This is just a dumb implementation, does not really create semaphores. - * \author Ricky Zheng - */ - -#include "uffs_config.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -#include -#include -#include -#include -#include - -#define PFX "os : " - -int uffs_SemCreate(OSSEM *sem) -{ - pthread_mutex_t *mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); - int ret = -1; - - if (mutex) { - ret = pthread_mutex_init(mutex, NULL /* default attr */); - if (ret == 0) { - *sem = (OSSEM *)mutex; - } - else { - free(mutex); - } - } - - return ret; -} - -int uffs_SemWait(OSSEM sem) -{ - return pthread_mutex_lock((pthread_mutex_t *)sem); -} - -int uffs_SemSignal(OSSEM sem) -{ - return pthread_mutex_unlock((pthread_mutex_t *)sem);; -} - -int uffs_SemDelete(OSSEM *sem) -{ - pthread_mutex_t *mutex = (pthread_mutex_t *) (*sem); - int ret = -1; - - if (mutex) { - ret = pthread_mutex_destroy(mutex); - if (ret == 0) { - free(mutex); - *sem = 0; - } - } - return ret; -} - -int uffs_OSGetTaskId(void) -{ - //TODO: ... return current task ID ... - return 0; -} - -unsigned int uffs_GetCurDateTime(void) -{ - // FIXME: return system time, please modify this for your platform ! - // or just return 0 if you don't care about file time. - time_t tvalue; - - tvalue = time(NULL); - - return (unsigned int)tvalue; -} - -#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0 -static void * sys_malloc(struct uffs_DeviceSt *dev, unsigned int size) -{ - dev = dev; - uffs_Perror(UFFS_MSG_NORMAL, "system memory alloc %d bytes", size); - return malloc(size); -} - -static URET sys_free(struct uffs_DeviceSt *dev, void *p) -{ - dev = dev; - free(p); - return U_SUCC; -} - -void uffs_MemSetupSystemAllocator(uffs_MemAllocator *allocator) -{ - allocator->malloc = sys_malloc; - allocator->free = sys_free; -} -#endif - - -/* debug message output throught 'printf' */ -static void output_dbg_msg(const char *msg); -static struct uffs_DebugMsgOutputSt m_dbg_ops = { - output_dbg_msg, - NULL, -}; - -static void output_dbg_msg(const char *msg) -{ - printf("%s", msg); -} - -void uffs_SetupDebugOutput(void) -{ - uffs_InitDebugMessageOutput(&m_dbg_ops, UFFS_MSG_NOISY); -} diff --git a/components/dfs/filesystems/uffs/src/platform/win32/uffs_config.h b/components/dfs/filesystems/uffs/src/platform/win32/uffs_config.h deleted file mode 100644 index 3f9daa9cd4..0000000000 --- a/components/dfs/filesystems/uffs/src/platform/win32/uffs_config.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_config.h - * \brief basic configuration of uffs - * \author Ricky Zheng - */ - -#ifndef _UFFS_CONFIG_H_ -#define _UFFS_CONFIG_H_ - -/** - * \def UFFS_MAX_PAGE_SIZE - * \note maximum page size UFFS support - */ -#define UFFS_MAX_PAGE_SIZE 2048 - -/** - * \def UFFS_MAX_SPARE_SIZE - */ -#define UFFS_MAX_SPARE_SIZE ((UFFS_MAX_PAGE_SIZE / 256) * 8) - -/** - * \def UFFS_MAX_ECC_SIZE - */ -#define UFFS_MAX_ECC_SIZE ((UFFS_MAX_PAGE_SIZE / 256) * 5) - -/** - * \def MAX_CACHED_BLOCK_INFO - * \note uffs cache the block info for opened directories and files, - * a practical value is 5 ~ MAX_OBJECT_HANDLE - */ -#define MAX_CACHED_BLOCK_INFO 50 - -/** - * \def MAX_PAGE_BUFFERS - * \note the bigger value will bring better read/write performance. - * but few writing performance will be improved when this - * value is become larger than 'max pages per block' - */ -#define MAX_PAGE_BUFFERS 40 - - -/** - * \def CLONE_BUFFER_THRESHOLD - * \note reserve buffers for clone. 1 or 2 should be enough. - */ -#define CLONE_BUFFERS_THRESHOLD 2 - -/** - * \def MAX_SPARE_BUFFERS - * \note spare buffers are used for lower level flash operations, - * 5 should be enough. - */ -#define MAX_SPARE_BUFFERS 5 - - -/** - * \def MAX_DIRTY_PAGES_IN_A_BLOCK - * \note this value should be between '2' and the lesser of - * 'max pages per block' and (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD - 1). - * - * the smaller the value the frequently the buffer will be flushed. - */ -#define MAX_DIRTY_PAGES_IN_A_BLOCK 32 - -/** - * \def CONFIG_ENABLE_UFFS_DEBUG_MSG - * \note Enable debug message output. You must call uffs_InitDebugMessageOutput() - * to initialize debug apart from enable debug feature. - */ -#define CONFIG_ENABLE_UFFS_DEBUG_MSG - -/** - * \def CONFIG_USE_GLOBAL_FS_LOCK - * \note use global lock instead of per-device lock. - * this is required if you use fd APIs in multi-thread environment. - */ -#define CONFIG_USE_GLOBAL_FS_LOCK - - -/** - * \def CONFIG_USE_PER_DEVICE_LOCK - * \note use per-device lock. - * this is required if you use fs APIs in multi-thread environment. - */ -//#define CONFIG_USE_PER_DEVICE_LOCK - - - -/** - * \def CONFIG_USE_STATIC_MEMORY_ALLOCATOR - * \note uffs will use static memory allocator if this is defined. - * to use static memory allocator, you need to provide memory - * buffer when creating uffs_Device. - * - * use UFFS_STATIC_BUFF_SIZE() to calculate memory buffer size. - */ -#define CONFIG_USE_STATIC_MEMORY_ALLOCATOR 0 - -/** - * \def CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR - * \note using system platform's 'malloc' and 'free'. - */ -#define CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR 1 - - - -/** - * \def CONFIG_FLUSH_BUF_AFTER_WRITE - * \note UFFS will write all data directly into flash in - * each 'write' call if you enable this option. - * (which means lesser data lost when power failure but - * poorer writing performance). - * It's not recommended to open this define for normal applications. - */ -//#define CONFIG_FLUSH_BUF_AFTER_WRITE - - -/** - * \def CONFIG_UFFS_AUTO_LAYOUT_MTD_COMP - * \note Use Linux MTD compatiable spare placement for UFFS_LAYOUT_AUTO, - * only valid for page data size 512 or 2048. - */ -//#define CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME - - -/** - * \def MAX_OBJECT_HANDLE - * maximum number of object handle - */ -#define MAX_OBJECT_HANDLE 50 -#define FD_SIGNATURE_SHIFT 6 - - -/** - * \def MAX_DIR_HANDLE - * maximum number of uffs_DIR - */ -#define MAX_DIR_HANDLE 10 - -/** - * \def MINIMUN_ERASED_BLOCK - * UFFS will not allow appending or creating new files when the free/erased block - * is lower then MINIMUN_ERASED_BLOCK. - */ -#define MINIMUN_ERASED_BLOCK 2 - -/** - * \def CONFIG_CHANGE_MODIFY_TIME - * \note If defined, closing a file which is opened for writing/appending will - * update the file's modify time as well. Disable this feature will save a - * lot of writing activities if you frequently open files for write and close it. - */ -//#define CONFIG_CHANGE_MODIFY_TIME - - -/** - * \def CONFIG_ENABLE_BAD_BLOCK_VERIFY - * \note allow erase and verify block marked as 'bad' when format UFFS partition. - * it's not recommended for most NAND flash. - */ -#define CONFIG_ENABLE_BAD_BLOCK_VERIFY - -/** - * \def CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - * \note erase block again before mark bad block - */ -//#define CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - -/** - * \def CONFIG_PAGE_WRITE_VERIFY - * \note verify page data after write, for extra safe data storage. - */ -#define CONFIG_PAGE_WRITE_VERIFY - -/** - * \def CONFIG_BAD_BLOCK_POLICY_STRICT - * \note If this is enabled, UFFS will report the block as 'bad' if any bit-flips found; - * otherwise, UFFS report bad block only when ECC failed or reported - * by low level flash driver. - * - * \note Enable this will ensure your data always be stored on completely good blocks. - */ -#define CONFIG_BAD_BLOCK_POLICY_STRICT - - -/** - * \def CONFIG_ENABLE_PAGE_DATA_CRC - * \note If this is enabled, UFFS save page data CRC16 sum in mini header, - * it provides extra protection for data integrity. - */ -//#define CONFIG_ENABLE_PAGE_DATA_CRC - - -/** micros for calculating buffer sizes */ - -/** - * \def UFFS_BLOCK_INFO_BUFFER_SIZE - * \brief calculate memory bytes for block info caches - */ -#define UFFS_BLOCK_INFO_BUFFER_SIZE(n_pages_per_block) \ - ( \ - ( \ - sizeof(uffs_BlockInfo) + \ - sizeof(uffs_PageSpare) * n_pages_per_block \ - ) * MAX_CACHED_BLOCK_INFO \ - ) - -/** - * \def UFFS_PAGE_BUFFER_SIZE - * \brief calculate memory bytes for page buffers - */ -#define UFFS_PAGE_BUFFER_SIZE(n_page_size) \ - ( \ - ( \ - sizeof(uffs_Buf) + n_page_size \ - ) * MAX_PAGE_BUFFERS \ - ) - -/** - * \def UFFS_TREE_BUFFER_SIZE - * \brief calculate memory bytes for tree nodes - */ -#define UFFS_TREE_BUFFER_SIZE(n_blocks) (sizeof(TreeNode) * n_blocks) - - -#define UFFS_SPARE_BUFFER_SIZE (MAX_SPARE_BUFFERS * UFFS_MAX_SPARE_SIZE) - - -/** - * \def UFFS_STATIC_BUFF_SIZE - * \brief calculate total memory usage of uffs system - */ -#define UFFS_STATIC_BUFF_SIZE(n_pages_per_block, n_page_size, n_blocks) \ - ( \ - UFFS_BLOCK_INFO_BUFFER_SIZE(n_pages_per_block) + \ - UFFS_PAGE_BUFFER_SIZE(n_page_size) + \ - UFFS_TREE_BUFFER_SIZE(n_blocks) + \ - UFFS_SPARE_BUFFER_SIZE \ - ) - - - -/* config check */ -#if (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD) < 3 -#error "MAX_PAGE_BUFFERS is too small" -#endif - -#if (MAX_DIRTY_PAGES_IN_A_BLOCK < 2) -#error "MAX_DIRTY_PAGES_IN_A_BLOCK should >= 2" -#endif - -#if (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD - 1 < MAX_DIRTY_PAGES_IN_A_BLOCK) -#error "MAX_DIRTY_PAGES_IN_A_BLOCK should < (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD)" -#endif - -#if defined(CONFIG_PAGE_WRITE_VERIFY) && (CLONE_BUFFERS_THRESHOLD < 2) -#error "CLONE_BUFFERS_THRESHOLD should >= 2 when CONFIG_PAGE_WRITE_VERIFY is enabled." -#endif - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR + CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 1 -#error "Please enable ONLY one memory allocator" -#endif - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR + CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR == 0 -#error "Please enable ONE of memory allocators" -#endif - -#if defined(CONFIG_USE_GLOBAL_FS_LOCK) && defined(CONFIG_USE_PER_DEVICE_LOCK) -#error "enable either CONFIG_USE_GLOBAL_FS_LOCK or CONFIG_USE_PER_DEVICE_LOCK, not both" -#endif - -#if (MAX_OBJECT_HANDLE > (1 << FD_SIGNATURE_SHIFT)) -#error "Please increase FD_SIGNATURE_SHIFT !" -#endif - -#ifdef WIN32 -# pragma warning(disable : 4996) -# pragma warning(disable : 4244) -# pragma warning(disable : 4214) -# pragma warning(disable : 4127) -# pragma warning(disable : 4389) -# pragma warning(disable : 4100) -#endif - -#endif diff --git a/components/dfs/filesystems/uffs/src/platform/win32/uffs_os.c b/components/dfs/filesystems/uffs/src/platform/win32/uffs_os.c deleted file mode 100644 index d05c44abb9..0000000000 --- a/components/dfs/filesystems/uffs/src/platform/win32/uffs_os.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_os.c - * \brief Emulation on win32 host - * \author Ricky Zheng - */ - -#include "uffs_config.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -#include -#include -#include -#include -#include - -#define PFX "os : " - -int uffs_SemCreate(OSSEM *sem) -{ - HANDLE mutex = CreateMutex( - NULL, // default security attributes - FALSE, // initially not owned - NULL); // unnamed mutex - - if (mutex == NULL) { - printf("Create mutex failed !\n"); - return -1; - } - else { - *sem = (OSSEM)mutex; - } - - return 0; -} - -int uffs_SemWait(OSSEM sem) -{ - DWORD result; - - result = WaitForSingleObject( - (HANDLE)sem, // handle to mutex - INFINITE); // no time-out interval - - return result == WAIT_ABANDONED ? -1 : 0; -} - -int uffs_SemSignal(OSSEM sem) -{ - return ReleaseMutex((HANDLE)sem) ? 0 : -1; -} - -int uffs_SemDelete(OSSEM *sem) -{ - if (CloseHandle((HANDLE)(*sem))) { - *sem = 0; - return 0; - } - else - return -1; -} - -int uffs_OSGetTaskId(void) -{ - return 0; -} - -unsigned int uffs_GetCurDateTime(void) -{ - // FIXME: return system time, please modify this for your platform ! - // or just return 0 if you don't care about file time. - time_t tvalue; - - tvalue = time(NULL); - - return (unsigned int)tvalue; -} - -#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0 -static void * sys_malloc(struct uffs_DeviceSt *dev, unsigned int size) -{ - dev = dev; - uffs_Perror(UFFS_MSG_NORMAL, "system memory alloc %d bytes", size); - return malloc(size); -} - -static URET sys_free(struct uffs_DeviceSt *dev, void *p) -{ - dev = dev; - free(p); - return U_SUCC; -} - -void uffs_MemSetupSystemAllocator(uffs_MemAllocator *allocator) -{ - allocator->malloc = sys_malloc; - allocator->free = sys_free; -} -#endif - - -/* debug message output throught 'printf' */ -static void output_dbg_msg(const char *msg); -static struct uffs_DebugMsgOutputSt m_dbg_ops = { - output_dbg_msg, - NULL, -}; - -static void output_dbg_msg(const char *msg) -{ - printf("%s", msg); -} - -void uffs_SetupDebugOutput(void) -{ - uffs_InitDebugMessageOutput(&m_dbg_ops, UFFS_MSG_NOISY); -} diff --git a/components/dfs/filesystems/uffs/src/uffs/CMakeLists.txt b/components/dfs/filesystems/uffs/src/uffs/CMakeLists.txt deleted file mode 100644 index 24b726b8cb..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -SET (libuffs_SRCS - uffs_badblock.c - uffs_blockinfo.c - uffs_buf.c - uffs_debug.c - uffs_device.c - uffs_ecc.c - uffs_fd.c - uffs_fs.c - uffs_init.c - uffs_mem.c - uffs_pool.c - uffs_public.c - uffs_tree.c - uffs_utils.c - uffs_mtb.c - uffs_find.c - uffs_flash.c - uffs_version.c - uffs_crc.c - ) - -SET (HDR ${uffs_SOURCE_DIR}/src/inc/uffs) - -SET (libuffs_HEADS - ${HDR}/uffs.h - ${HDR}/uffs_badblock.h - ${HDR}/uffs_blockinfo.h - ${HDR}/uffs_buf.h - ${HDR}/uffs_core.h - ${HDR}/uffs_device.h - ${HDR}/uffs_ecc.h - ${HDR}/uffs_fd.h - ${HDR}/uffs_fs.h - ${HDR}/uffs_mem.h - ${HDR}/uffs_os.h - ${HDR}/uffs_pool.h - ${HDR}/uffs_public.h - ${HDR}/uffs_tree.h - ${HDR}/uffs_types.h - ${HDR}/uffs_utils.h - ${HDR}/uffs_mtb.h - ${HDR}/uffs_find.h - ${HDR}/uffs_flash.h - ${HDR}/uffs_version.h - ${HDR}/uffs_crc.h - ) - -IF (UNIX) -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/posix) -ENDIF() - -IF (WIN32) -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/win32) -ENDIF() - -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/inc) - -ADD_LIBRARY( uffs STATIC ${libuffs_SRCS} ${libuffs_HEADS} ) diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_badblock.c b/components/dfs/filesystems/uffs/src/uffs/uffs_badblock.c deleted file mode 100644 index 6145b9e547..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_badblock.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_badblock.c - * \brief bad block checking and recovering - * \author Ricky Zheng, created in 13th Jun, 2005 - */ -#include "uffs_config.h" -#include "uffs/uffs_fs.h" -#include "uffs/uffs_ecc.h" -#include "uffs/uffs_badblock.h" -#include - -#define PFX "bbl : " - -void uffs_BadBlockInit(uffs_Device *dev) -{ - dev->bad.block = UFFS_INVALID_BLOCK; -} - - -/** - * \brief process bad block: erase bad block, mark it as 'bad' - * and put the node to bad block list. - * \param[in] dev uffs device - * \param[in] node bad block tree node - * (before the block turn 'bad', it must belong to something ...) - */ -void uffs_BadBlockProcess(uffs_Device *dev, TreeNode *node) -{ - if (HAVE_BADBLOCK(dev)) { - // mark the bad block - uffs_FlashMarkBadBlock(dev, dev->bad.block); - - // and put it into bad block list - if (node != NULL) - uffs_TreeInsertToBadBlockList(dev, node); - - //clear bad block mark. - dev->bad.block = UFFS_INVALID_BLOCK; - - } -} - -/** - * \brief process bad block and put the node in 'suspend' list. - * \param[in] dev uffs device - * \param[in] node bad block tree node - */ -void uffs_BadBlockProcessSuspend(uffs_Device *dev, TreeNode *node) -{ - if (HAVE_BADBLOCK(dev)) { - // mark the bad block - uffs_FlashMarkBadBlock(dev, dev->bad.block); - - // and put it into bad block list - if (node != NULL) - uffs_TreeSuspendAdd(dev, node); - - //clear bad block mark. - dev->bad.block = UFFS_INVALID_BLOCK; - } -} - -/** - * \brief recover bad block - * \param[in] dev uffs device - */ -void uffs_BadBlockRecover(uffs_Device *dev) -{ - TreeNode *good, *bad; - uffs_Buf *buf; - u16 i; - u16 page; - uffs_BlockInfo *bc = NULL; - uffs_Tags *tag; - uffs_Tags newTag; - UBOOL succRecov; - UBOOL goodBlockIsDirty = U_FALSE; - int ret; - int region; - u8 type; - - if (dev->bad.block == UFFS_INVALID_BLOCK) - return; - - // pick up an erased good block - good = uffs_TreeGetErasedNode(dev); - if (good == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "no free block to replace bad block!"); - return; - } - - //recover block - bc = uffs_BlockInfoGet(dev, dev->bad.block); - - if (bc == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get bad block info"); - return; - } - - succRecov = U_TRUE; - for (i = 0; i < dev->attr->pages_per_block; i++) { - page = uffs_FindPageInBlockWithPageId(dev, bc, i); - if (page == UFFS_INVALID_PAGE) { - break; //end of last valid page, normal break - } - page = uffs_FindBestPageInBlock(dev, bc, page); - if (page == UFFS_INVALID_PAGE) { - // got an invalid page ? it's bad block anyway ... - uffs_Perror(UFFS_MSG_SERIOUS, "bad block recover (block %d) not finished", bc->block); - break; - } - tag = GET_TAG(bc, page); - buf = uffs_BufClone(dev, NULL); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Can't clone a new buf!"); - succRecov = U_FALSE; - break; - } - //NOTE: since this is a bad block, we can't guarantee the data is ECC ok, - // so just load data even ECC is not OK. - ret = uffs_LoadPhyDataToBufEccUnCare(dev, buf, bc->block, page); - if (ret == U_FAIL) { - uffs_Perror(UFFS_MSG_SERIOUS, "I/O error ?"); - uffs_BufFreeClone(dev, buf); - succRecov = U_FALSE; - break; - } - buf->data_len = TAG_DATA_LEN(tag); - if (buf->data_len > dev->com.pg_data_size) { - uffs_Perror(UFFS_MSG_NOISY, "data length over flow!!!"); - buf->data_len = dev->com.pg_data_size; - } - - buf->parent = TAG_PARENT(tag); - buf->serial = TAG_SERIAL(tag); - buf->type = TAG_TYPE(tag); - buf->page_id = TAG_PAGE_ID(tag); - - // new tag copied from old tag, and increase time-stamp. - newTag = *tag; - TAG_BLOCK_TS(&newTag) = uffs_GetNextBlockTimeStamp(TAG_BLOCK_TS(tag)); - - ret = uffs_FlashWritePageCombine(dev, good->u.list.block, i, buf, &newTag); - - goodBlockIsDirty = U_TRUE; - uffs_BufFreeClone(dev, buf); - - if (ret == UFFS_FLASH_IO_ERR) { - uffs_Perror(UFFS_MSG_NORMAL, "I/O error ?"); - succRecov = U_FALSE; - break; - } - } - - - if (succRecov == U_TRUE) { - // successful recover bad block, so need to mark bad block, - // and replace with good one - - region = SEARCH_REGION_DIR|SEARCH_REGION_FILE|SEARCH_REGION_DATA; - bad = uffs_TreeFindNodeByBlock(dev, dev->bad.block, ®ion); - if (bad != NULL) { - switch (region) { - case SEARCH_REGION_DIR: - bad->u.dir.block = good->u.list.block; - type = UFFS_TYPE_DIR; - break; - case SEARCH_REGION_FILE: - bad->u.file.block = good->u.list.block; - type = UFFS_TYPE_FILE; - break; - case SEARCH_REGION_DATA: - bad->u.data.block = good->u.list.block; - type = UFFS_TYPE_DATA; - } - - //from now, the 'bad' is actually good block :))) - uffs_Perror(UFFS_MSG_NOISY, - "new bad block %d found, and replaced by %d, type %d!", - dev->bad.block, good->u.list.block, type); - uffs_BlockInfoExpire(dev, bc, UFFS_ALL_PAGES); - //we reuse the 'good' node as bad block node, and process the bad block. - good->u.list.block = dev->bad.block; - uffs_BadBlockProcess(dev, good); - } - else { - uffs_Perror(UFFS_MSG_SERIOUS, - "can't find the reported bad block(%d) in the tree???", - dev->bad.block); - if (goodBlockIsDirty == U_TRUE) - dev->ops->EraseBlock(dev, good->u.list.block); - uffs_TreeInsertToErasedListTail(dev, good); - } - } - else { - if (goodBlockIsDirty == U_TRUE) - dev->ops->EraseBlock(dev, good->u.list.block); - uffs_TreeInsertToErasedListTail(dev, good); //put back to erased list - } - - uffs_BlockInfoPut(dev, bc); - -} - - -/** put a new block to the bad block waiting list */ -void uffs_BadBlockAdd(uffs_Device *dev, int block) -{ - if (dev->bad.block == block) - return; - - if (dev->bad.block != UFFS_INVALID_BLOCK) - uffs_Perror(UFFS_MSG_SERIOUS, "Can't add more then one bad block !"); - else - dev->bad.block = block; -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_blockinfo.c b/components/dfs/filesystems/uffs/src/uffs/uffs_blockinfo.c deleted file mode 100644 index f80bc6113e..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_blockinfo.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_blockinfo.c - * \brief block information cache system manipulations - * \author Ricky Zheng, created 10th May, 2005 - */ - -#include "uffs_config.h" -#include "uffs/uffs_blockinfo.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_os.h" - -#include - -#define PFX "bc : " - -#define UFFS_CLONE_BLOCK_INFO_NEXT ((uffs_BlockInfo *)(-2)) - -/** - * \brief before block info cache is enable, - * this function should be called to initialize it - * - * \param[in] dev uffs device - * \param[in] maxCachedBlocks maximum cache buffers to be allocated - * \return result of initialization - * \retval U_SUCC successful - * \retval U_FAIL failed - */ -URET uffs_BlockInfoInitCache(uffs_Device *dev, int maxCachedBlocks) -{ - uffs_BlockInfo * blockInfos = NULL; - uffs_PageSpare * pageSpares = NULL; - void * buf = NULL; - uffs_BlockInfo *work = NULL; - int size, i, j; - - if (dev->bc.head != NULL) { - uffs_Perror(UFFS_MSG_NOISY, - "block info cache has been inited already, " - "now release it first."); - uffs_BlockInfoReleaseCache(dev); - } - - size = ( - sizeof(uffs_BlockInfo) + - sizeof(uffs_PageSpare) * dev->attr->pages_per_block - ) * maxCachedBlocks; - - if (dev->mem.blockinfo_pool_size == 0) { - if (dev->mem.malloc) { - dev->mem.blockinfo_pool_buf = dev->mem.malloc(dev, size); - if (dev->mem.blockinfo_pool_buf) - dev->mem.blockinfo_pool_size = size; - } - } - if (size > dev->mem.blockinfo_pool_size) { - uffs_Perror(UFFS_MSG_DEAD, - "Block cache buffer require %d but only %d available.", - size, dev->mem.blockinfo_pool_size); - return U_FAIL; - } - - uffs_Perror(UFFS_MSG_NOISY, "alloc info cache %d bytes.", size); - - buf = dev->mem.blockinfo_pool_buf; - - memset(buf, 0, size); - - dev->bc.mem_pool = buf; - - size = 0; - blockInfos = (uffs_BlockInfo *)buf; - size += sizeof(uffs_BlockInfo) * maxCachedBlocks; - - pageSpares = (uffs_PageSpare *)((char *)buf + size); - - //initialize block info - work = &(blockInfos[0]); - dev->bc.head = work; - work->ref_count = 0; - work->prev = NULL; - work->next = &(blockInfos[1]); - work->block = UFFS_INVALID_BLOCK; - - for (i = 0; i < maxCachedBlocks - 2; i++) { - work = &(blockInfos[i+1]); - work->prev = &(blockInfos[i]); - work->next = &(blockInfos[i+2]); - work->ref_count = 0; - work->block = UFFS_INVALID_BLOCK; - } - //the last node - work = &(blockInfos[i+1]); - work->prev = &(blockInfos[i]); - work->next = NULL; - work->block = UFFS_INVALID_BLOCK; - work->ref_count = 0; - dev->bc.tail = work; - - //initialize spares - work = dev->bc.head; - for (i = 0; i < maxCachedBlocks; i++) { - work->spares = &(pageSpares[i*dev->attr->pages_per_block]); - for (j = 0; j < dev->attr->pages_per_block; j++) { - work->spares[j].expired = 1; - } - work->expired_count = dev->attr->pages_per_block; - work = work->next; - } - return U_SUCC; -} - -/** - * \brief release all allocated memory of block info cache, - * this function should be called when unmount file system - * \param[in] dev uffs device - */ -URET uffs_BlockInfoReleaseCache(uffs_Device *dev) -{ - uffs_BlockInfo *work; - - if (dev->bc.head) { - for (work = dev->bc.head; work != NULL; work = work->next) { - if (work->ref_count != 0) { - uffs_Perror(UFFS_MSG_SERIOUS, - "There have refed block info cache, release cache fail."); - return U_FAIL; - } - } - if (dev->mem.free) { - dev->mem.free(dev, dev->bc.mem_pool); - dev->mem.blockinfo_pool_size = 0; - } - } - - dev->bc.head = dev->bc.tail = NULL; - dev->bc.mem_pool = NULL; - - return U_SUCC; -} - -static void _BreakBcFromList(uffs_Device *dev, uffs_BlockInfo *bc) -{ - if (bc->prev) - bc->prev->next = bc->next; - - if (bc->next) - bc->next->prev = bc->prev; - - if (dev->bc.head == bc) - dev->bc.head = bc->next; - - if (dev->bc.tail == bc) - dev->bc.tail = bc->prev; -} - -static void _InsertToBcListTail(uffs_Device *dev, uffs_BlockInfo *bc) -{ - bc->next = NULL; - bc->prev = dev->bc.tail; - bc->prev->next = bc; - dev->bc.tail = bc; -} - -static void _MoveBcToTail(uffs_Device *dev, uffs_BlockInfo *bc) -{ - _BreakBcFromList(dev, bc); - _InsertToBcListTail(dev, bc); -} - - -/** - * \brief load page spare data to given block info structure - * with given page number - * \param[in] dev uffs device - * \param[in] work given block info to be filled with - * \param[in] page given page number to be read from, - * if #UFFS_ALL_PAGES is presented, it will read - * all pages, otherwise it will read only one given page. - * \return load result - * \retval U_SUCC successful - * \retval U_FAIL fail to load - * \note work->block must be set before load block info - */ -URET uffs_BlockInfoLoad(uffs_Device *dev, uffs_BlockInfo *work, int page) -{ - int i, ret; - uffs_PageSpare *spare; - - if (page == UFFS_ALL_PAGES) { - for (i = 0; i < dev->attr->pages_per_block; i++) { - spare = &(work->spares[i]); - if (spare->expired == 0) - continue; - - ret = uffs_FlashReadPageTag(dev, work->block, i, - &(spare->tag)); - if (UFFS_FLASH_HAVE_ERR(ret)) { - uffs_Perror(UFFS_MSG_SERIOUS, - "load block %d page %d spare fail.", - work->block, i); - return U_FAIL; - } - spare->expired = 0; - work->expired_count--; - } - } - else { - if (page < 0 || page >= dev->attr->pages_per_block) { - uffs_Perror(UFFS_MSG_SERIOUS, "page out of range !"); - return U_FAIL; - } - spare = &(work->spares[page]); - if (spare->expired != 0) { - ret = uffs_FlashReadPageTag(dev, work->block, page, - &(spare->tag)); - if (UFFS_FLASH_HAVE_ERR(ret)) { - uffs_Perror(UFFS_MSG_SERIOUS, - "load block %d page %d spare fail.", - work->block, page); - return U_FAIL; - } - spare->expired = 0; - work->expired_count--; - } - } - return U_SUCC; -} - - -/** - * \brief find a block cache with given block number - * \param[in] dev uffs device - * \param[in] block block number - * \return found block cache - * \retval NULL cache not found - * \retval non-NULL found cache pointer - */ -uffs_BlockInfo * uffs_BlockInfoFindInCache(uffs_Device *dev, int block) -{ - uffs_BlockInfo *work; - - //search cached block - for (work = dev->bc.head; work != NULL; work = work->next) { - if (work->block == block) { - work->ref_count++; - return work; - } - } - return NULL; -} - - -/** - * \brief Find a cached block in cache pool, - * if the cached block exist then return the pointer, - * if the block does not cached already, find a non-used cache. - * if all of cached are used out, return NULL. - * \param[in] dev uffs device - * \param[in] block block number to be found - * \return found block cache buffer - * \retval NULL caches used out - * \retval non-NULL buffer pointer of given block - */ -uffs_BlockInfo * uffs_BlockInfoGet(uffs_Device *dev, int block) -{ - uffs_BlockInfo *work; - int i; - - //search cached block - if ((work = uffs_BlockInfoFindInCache(dev, block)) != NULL) { - _MoveBcToTail(dev, work); - return work; - } - - //can't find block from cache, need to find a free(unlocked) cache - for (work = dev->bc.head; work != NULL; work = work->next) { - if(work->ref_count == 0) break; - } - if (work == NULL) { - //caches used out ! - uffs_Perror(UFFS_MSG_SERIOUS, "insufficient block info cache"); - return NULL; - } - - work->block = block; - work->expired_count = dev->attr->pages_per_block; - for (i = 0; i < dev->attr->pages_per_block; i++) { - work->spares[i].expired = 1; - - // TODO: init tag - } - - work->ref_count = 1; - - _MoveBcToTail(dev, work); - - return work; -} - -/** - * \brief put block info buffer back to pool, - * should be called with #uffs_BlockInfoGet in pairs. - * \param[in] dev uffs device - * \param[in] p pointer of block info buffer - */ -void uffs_BlockInfoPut(uffs_Device *dev, uffs_BlockInfo *p) -{ - dev = dev; - if (p) - { - if (p->ref_count == 0) { - uffs_Perror(UFFS_MSG_SERIOUS, - "Put an unused block info cache back ?"); - } - else { - p->ref_count--; - } - } -} - - -/** - * \brief make the given pages expired in given block info buffer - * \param[in] dev uffs device - * \param[in] p pointer of block info buffer - * \param[in] page given page number. - * if #UFFS_ALL_PAGES presented, all pages in the block should be made expired. - */ -void uffs_BlockInfoExpire(uffs_Device *dev, uffs_BlockInfo *p, int page) -{ - int i; - uffs_PageSpare *spare; - - if (page == UFFS_ALL_PAGES) { - for (i = 0; i < dev->attr->pages_per_block; i++) { - spare = &(p->spares[i]); - if (spare->expired == 0) { - spare->expired = 1; - p->expired_count++; - } - } - } - else { - if (page >= 0 && page < dev->attr->pages_per_block) { - spare = &(p->spares[page]); - if (spare->expired == 0) { - spare->expired = 1; - p->expired_count++; - } - } - } -} - -/** - * Is all blcok info cache free (not referenced) ? - */ -UBOOL uffs_BlockInfoIsAllFree(uffs_Device *dev) -{ - uffs_BlockInfo *work; - - work = dev->bc.head; - while (work) { - if (work->ref_count != 0) - return U_FALSE; - work = work->next; - } - - return U_TRUE; -} - -void uffs_BlockInfoExpireAll(uffs_Device *dev) -{ - uffs_BlockInfo *bc; - - bc = dev->bc.head; - while (bc) { - uffs_BlockInfoExpire(dev, bc, UFFS_ALL_PAGES); - bc = bc->next; - } - return; -} diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_buf.c b/components/dfs/filesystems/uffs/src/uffs/uffs_buf.c deleted file mode 100644 index fd646aa73e..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_buf.c +++ /dev/null @@ -1,1799 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ -/** - * \file uffs_buf.c - * \brief uffs page buffers manipulations - * \author Ricky Zheng - * \note Created in 11th May, 2005 - */ -#include "uffs_config.h" -#include "uffs/uffs_types.h" -#include "uffs/uffs_buf.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_pool.h" -#include "uffs/uffs_ecc.h" -#include "uffs/uffs_badblock.h" -#include - -#define PFX "pbuf: " - - -URET _BufFlush(struct uffs_DeviceSt *dev, UBOOL force_block_recover, int slot); - - -/** - * \brief inspect (print) uffs page buffers. - * \param[in] dev uffs device to be inspected. - */ -void uffs_BufInspect(uffs_Device *dev) -{ - struct uffs_PageBufDescSt *pb = &dev->buf; - uffs_Buf *buf; - - uffs_PerrorRaw(UFFS_MSG_NORMAL, - "------------- page buffer inspect ---------" TENDSTR); - uffs_PerrorRaw(UFFS_MSG_NORMAL, "all buffers: " TENDSTR); - for (buf = pb->head; buf; buf = buf->next) { - if (buf->mark != 0) { - uffs_PerrorRaw(UFFS_MSG_NORMAL, - "\tF:%04x S:%04x P:%02d R:%02d D:%03d M:%c EM:%d" TENDSTR, - buf->parent, buf->serial, - buf->page_id, buf->ref_count, - buf->data_len, buf->mark == UFFS_BUF_VALID ? 'V' : 'D', - buf->ext_mark); - } - } - uffs_PerrorRaw(UFFS_MSG_NORMAL, - "--------------------------------------------" TENDSTR); -} - -/** - * \brief initialize page buffers for device - * in UFFS, each device has one buffer pool - * \param[in] dev uffs device - * \param[in] buf_max maximum buffer number, normally use #MAX_PAGE_BUFFERS - * \param[in] dirty_buf_max maximum dirty buffer allowed, - * if the dirty buffer over this number, - * than need to be flush to flash - */ -URET uffs_BufInit(uffs_Device *dev, int buf_max, int dirty_buf_max) -{ - void *pool; - u8 *data; - uffs_Buf *buf; - int size; - int i, slot; - - if (!dev) - return U_FAIL; - - //init device common parameters, which are needed by page buffers - dev->com.pg_size = dev->attr->page_data_size; // we use the whole page. - dev->com.header_size = sizeof(struct uffs_MiniHeaderSt); // mini header - dev->com.pg_data_size = dev->com.pg_size - dev->com.header_size; - - if (dev->buf.pool != NULL) { - uffs_Perror(UFFS_MSG_NORMAL, - "buf.pool is not NULL, buf already inited ?"); - return U_FAIL; - } - - size = (sizeof(uffs_Buf) + dev->com.pg_size) * buf_max; - if (dev->mem.pagebuf_pool_size == 0) { - if (dev->mem.malloc) { - dev->mem.pagebuf_pool_buf = dev->mem.malloc(dev, size); - if (dev->mem.pagebuf_pool_buf) - dev->mem.pagebuf_pool_size = size; - } - } - if (size > dev->mem.pagebuf_pool_size) { - uffs_Perror(UFFS_MSG_DEAD, - "page buffers require %d but only %d available.", - size, dev->mem.pagebuf_pool_size); - return U_FAIL; - } - pool = dev->mem.pagebuf_pool_buf; - - uffs_Perror(UFFS_MSG_NOISY, "alloc %d bytes.", size); - dev->buf.pool = pool; - - for (i = 0; i < buf_max; i++) { - buf = (uffs_Buf *)((u8 *)pool + (sizeof(uffs_Buf) * i)); - memset(buf, 0, sizeof(uffs_Buf)); - data = (u8 *)pool + (sizeof(uffs_Buf) * buf_max) + (dev->com.pg_size * i); - buf->header = data; - buf->data = data + dev->com.header_size; - buf->mark = UFFS_BUF_EMPTY; - memset(buf->header, 0, dev->com.pg_size); - if (i == 0) { - buf->prev = NULL; - dev->buf.head = buf; - } - else { - buf->prev = (uffs_Buf *)((u8 *)buf - sizeof(uffs_Buf)); - } - - if (i == (buf_max - 1)) { - buf->next = NULL; - dev->buf.tail = buf; - } - else { - buf->next = (uffs_Buf *)((u8 *)buf + sizeof(uffs_Buf)); - } - } - - dev->buf.buf_max = buf_max; - dev->buf.dirty_buf_max = (dirty_buf_max > dev->attr->pages_per_block ? - dev->attr->pages_per_block : dirty_buf_max); - - for (slot = 0; slot < dev->cfg.dirty_groups; slot++) { - dev->buf.dirtyGroup[slot].dirty = NULL; - dev->buf.dirtyGroup[slot].count = 0; - } - return U_SUCC; -} - -/** - * \brief flush all buffers - */ -URET uffs_BufFlushAll(struct uffs_DeviceSt *dev) -{ - int slot; - for (slot = 0; slot < dev->cfg.dirty_groups; slot++) { - if(_BufFlush(dev, FALSE, slot) != U_SUCC) { - uffs_Perror(UFFS_MSG_NORMAL, - "fail to flush buffer(slot %d)", slot); - return U_FAIL; - } - } - return U_SUCC; -} - -/** - * \brief release all page buffer, this function should be called - when unmounting a uffs device - * \param[in] dev uffs device - * \note if there are page buffers in used, it may cause fail to release - */ -URET uffs_BufReleaseAll(uffs_Device *dev) -{ - uffs_Buf *p; - - if (!dev) - return U_FAIL; - - //now release all buffer - p = dev->buf.head; - while (p) { - if (p->ref_count != 0) { - uffs_Perror(UFFS_MSG_NORMAL, PFX - "can't release buffers, parent:%d, serial:%d, \ - page_id:%d still in used.\n", - p->parent, p->serial, p->page_id); - return U_FAIL; - } - p = p->next; - } - - if (uffs_BufFlushAll(dev) != U_SUCC) { - uffs_Perror(UFFS_MSG_NORMAL, - "can't release buf, fail to flush buffer"); - return U_FAIL; - } - - if (dev->mem.free) { - dev->mem.free(dev, dev->buf.pool); - dev->mem.pagebuf_pool_size = 0; - } - - dev->buf.pool = NULL; - dev->buf.head = dev->buf.tail = NULL; - - return U_SUCC; -} - - -static void _BreakFromBufList(uffs_Device *dev, uffs_Buf *buf) -{ - if(buf->next) - buf->next->prev = buf->prev; - - if(buf->prev) - buf->prev->next = buf->next; - - if(dev->buf.head == buf) - dev->buf.head = buf->next; - - if(dev->buf.tail == buf) - dev->buf.tail = buf->prev; - -} - -static void _LinkToBufListHead(uffs_Device *dev, uffs_Buf *buf) -{ - if (buf == dev->buf.head) - return; - - buf->prev = NULL; - buf->next = dev->buf.head; - - if (dev->buf.head) - dev->buf.head->prev = buf; - - if (dev->buf.tail == NULL) - dev->buf.tail = buf; - - dev->buf.head = buf; -} - -static void _LinkToBufListTail(uffs_Device *dev, uffs_Buf *buf) -{ - if (dev->buf.tail == buf) - return; - - buf->prev = dev->buf.tail; - buf->next = NULL; - - if (dev->buf.tail) - dev->buf.tail->next = buf; - - if (dev->buf.head == NULL) - dev->buf.head = buf; - - dev->buf.tail = buf; -} - -//move a node which linked in the list to the head of list -static void _MoveNodeToHead(uffs_Device *dev, uffs_Buf *p) -{ - if (p == dev->buf.head) - return; - - //break from list - _BreakFromBufList(dev, p); - - //link to head - _LinkToBufListHead(dev, p); -} - -// check if the buf is already in dirty list -static UBOOL _IsBufInInDirtyList(uffs_Device *dev, int slot, uffs_Buf *buf) -{ - uffs_Buf *work; - work = dev->buf.dirtyGroup[slot].dirty; - while (work) { - if (work == buf) - return U_TRUE; - work = work->next_dirty; - } - - return U_FALSE; -} - -static void _LinkToDirtyList(uffs_Device *dev, int slot, uffs_Buf *buf) -{ - - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "Try to insert a NULL node into dirty list ?"); - return; - } - - buf->mark = UFFS_BUF_DIRTY; - buf->prev_dirty = NULL; - buf->next_dirty = dev->buf.dirtyGroup[slot].dirty; - - if (dev->buf.dirtyGroup[slot].dirty) - dev->buf.dirtyGroup[slot].dirty->prev_dirty = buf; - - dev->buf.dirtyGroup[slot].dirty = buf; - dev->buf.dirtyGroup[slot].count++; -} - -static int CountFreeBuf(uffs_Device *dev) -{ - int count = 0; - - uffs_Buf *buf = dev->buf.head; - - while (buf) { - - if (buf->ref_count == 0 && - buf->mark != UFFS_BUF_DIRTY) - count++; - - buf = buf->next; - } - - return count; -} - -static uffs_Buf * _FindFreeBufEx(uffs_Device *dev, int clone) -{ - uffs_Buf *buf; - - if (!clone && CountFreeBuf(dev) <= CLONE_BUFFERS_THRESHOLD) - return NULL; - -#if 0 - buf = dev->buf.head; - while (buf) { - - if (buf->ref_count == 0 && - buf->mark != UFFS_BUF_DIRTY) - return buf; - - buf = buf->next; - } -#else - buf = dev->buf.tail; - while (buf) { - - if(buf->ref_count == 0 && - buf->mark != UFFS_BUF_DIRTY) - return buf; - - buf = buf->prev; - } -#endif - - return buf; -} - -static uffs_Buf * _FindFreeBuf(uffs_Device *dev) -{ - return _FindFreeBufEx(dev, 0); -} - - -/** - * load psychical page data into buf and do ecc check - * \param[in] dev uffs device - * \param[in] buf buf to be load in - * \param[in] block psychical block number - * \param[in] page psychical page number - * \return return U_SUCC if no error, - * return U_FAIL if I/O error or ecc check fail - */ -URET uffs_BufLoadPhyData(uffs_Device *dev, uffs_Buf *buf, u32 block, u32 page) -{ - int ret; - - ret = uffs_FlashReadPage(dev, block, page, buf, U_FALSE); - - if (UFFS_FLASH_HAVE_ERR(ret)) { - buf->mark = UFFS_BUF_EMPTY; - return U_FAIL; - } - else { - buf->mark = UFFS_BUF_VALID; - return U_SUCC; - } -} - -/** - * \brief load psychical page data into buf and ignore ECC result - * - * \param[in] dev uffs device - * \param[in] buf buf to be load in - * \param[in] block psychical block number - * \param[in] page psychical page number - * - * \return return U_SUCC if no error, return U_FAIL if I/O error - * \note this function should be only used when doing bad block recover. - */ -URET uffs_LoadPhyDataToBufEccUnCare(uffs_Device *dev, - uffs_Buf *buf, u32 block, u32 page) -{ - int ret; - - ret = uffs_FlashReadPage(dev, block, page, buf, U_TRUE); - - if (ret == UFFS_FLASH_IO_ERR) { - buf->mark = UFFS_BUF_EMPTY; - return U_FAIL; - } - else { - buf->mark = UFFS_BUF_VALID; - return U_SUCC; - } -} - -/** - * find a buffer in the pool - * \param[in] dev uffs device - * \param[in] start buf to search from - * \param[in] parent parent serial num - * \param[in] serial serial num - * \param[in] page_id page_id (if page_id == UFFS_ALL_PAGES then any page would match) - * \return return found buffer, return NULL if buffer not found - */ -uffs_Buf * uffs_BufFindFrom(uffs_Device *dev, uffs_Buf *start, - u16 parent, u16 serial, u16 page_id) -{ - uffs_Buf *p = start; - - while (p) { - if( p->parent == parent && - p->serial == serial && - (page_id == UFFS_ALL_PAGES || p->page_id == page_id) && - p->mark != UFFS_BUF_EMPTY) - { - //they have match one - return p; - } - p = p->next; - } - - return NULL; //buffer not found -} - -/** - * find a buffer in the pool - * \param[in] dev uffs device - * \param[in] parent parent serial num - * \param[in] serial serial num - * \param[in] page_id page_id (if page_id == UFFS_ALL_PAGES then any page would match) - * \return return found buffer, return NULL if buffer not found - */ -uffs_Buf * uffs_BufFind(uffs_Device *dev, - u16 parent, u16 serial, u16 page_id) -{ - uffs_Buf *p = dev->buf.head; - - return uffs_BufFindFrom(dev, p, parent, serial, page_id); -} - - -static uffs_Buf * _FindBufInDirtyList(uffs_Buf *dirty, u16 page_id) -{ - while(dirty) { - if (dirty->page_id == page_id) - return dirty; - dirty = dirty->next_dirty; - } - return NULL; -} - -static URET _BreakFromDirty(uffs_Device *dev, uffs_Buf *dirtyBuf) -{ - int slot = -1; - - if (dirtyBuf->mark != UFFS_BUF_DIRTY) { - uffs_Perror(UFFS_MSG_NORMAL, - "try to break a non-dirty buf from dirty list ?"); - return U_FAIL; - } - - slot = uffs_BufFindGroupSlot(dev, dirtyBuf->parent, dirtyBuf->serial); - if (slot < 0) { - uffs_Perror(UFFS_MSG_NORMAL, "no dirty list exit ?"); - return U_FAIL; - } - - // break from the link - if (dirtyBuf->next_dirty) { - dirtyBuf->next_dirty->prev_dirty = dirtyBuf->prev_dirty; - } - - if (dirtyBuf->prev_dirty) { - dirtyBuf->prev_dirty->next_dirty = dirtyBuf->next_dirty; - } - - // check if it's the link head ... - if (dev->buf.dirtyGroup[slot].dirty == dirtyBuf) { - dev->buf.dirtyGroup[slot].dirty = dirtyBuf->next_dirty; - } - - dirtyBuf->next_dirty = dirtyBuf->prev_dirty = NULL; // clear dirty link - - dev->buf.dirtyGroup[slot].count--; - - return U_SUCC; -} - -static u16 _GetDirOrFileNameSum(uffs_Device *dev, uffs_Buf *buf) -{ - u16 data_sum = 0; //default: 0 - uffs_FileInfo *fi; - - dev = dev; - //FIXME: We use the same schema for both dir and file. - if (buf->type == UFFS_TYPE_FILE || buf->type == UFFS_TYPE_DIR) { - if (buf->page_id == 0) { - fi = (uffs_FileInfo *)(buf->data); - data_sum = uffs_MakeSum16(fi->name, fi->name_len); - } - } - - return data_sum; -} - - -static URET _CheckDirtyList(uffs_Buf *dirty) -{ - u16 parent; - u16 serial; - - if (dirty == NULL) { - return U_SUCC; - } - - parent = dirty->parent; - serial = dirty->serial; - dirty = dirty->next_dirty; - - while (dirty) { - if (parent != dirty->parent || - serial != dirty->serial) { - uffs_Perror(UFFS_MSG_SERIOUS, - "parent or serial in dirty pages buffer are not the same ?"); - return U_FAIL; - } - if (dirty->mark != UFFS_BUF_DIRTY) { - uffs_Perror(UFFS_MSG_SERIOUS, - "non-dirty page buffer in dirty buffer list ?"); - return U_FAIL; - } - dirty = dirty->next_dirty; - } - return U_SUCC; -} - -/** find a page in dirty list, which has minimum page_id */ -uffs_Buf * _FindMinimunPageIdFromDirtyList(uffs_Buf *dirtyList) -{ - uffs_Buf * work = dirtyList; - uffs_Buf * buf = dirtyList; - - if (buf) { - work = work->next_dirty; - while (work) { - if (work->page_id < buf->page_id) - buf = work; - work = work->next_dirty; - } - - uffs_Assert(buf->mark == UFFS_BUF_DIRTY, - "buf (serial = %d, parent = %d, page_id = %d, type = %d) in dirty list but mark is 0x%x ?", - buf->serial, buf->parent, buf->page_id, buf->type, buf->mark); - } - - return buf; -} - - -/** - * \brief flush buffer with block recover - * - * Scenario: - * 1. get a free (erased) block --> newNode
- * 2. copy from old block ---> oldNode, or copy from dirty list,
- * sorted by page_id, to new block. Skips the invalid pages when copy pages.
- * 3. erased old block. set new info to oldNode, set newNode->block = old block,
- * and put newNode to erased list.
- * \note IT'S IMPORTANT TO KEEP OLD NODE IN THE LIST, - * so you don't need to update the obj->node :-) - */ -static URET uffs_BufFlush_Exist_With_BlockCover( - uffs_Device *dev, - int slot, //!< dirty group slot - TreeNode *node, //!< old data node on tree - uffs_BlockInfo *bc //!< old data block info - ) -{ - u16 i; - u8 type, timeStamp; - u16 page, parent, serial; - uffs_Buf *buf; - TreeNode *newNode; - uffs_BlockInfo *newBc; - uffs_Tags *tag, *oldTag; - int x; - u16 newBlock; - UBOOL succRecover; //U_TRUE: recover successful, erase old block, - //U_FALSE: fail to recover, erase new block - UBOOL flash_op_err; - u16 data_sum = 0xFFFF; - - UBOOL useCloneBuf; - - type = dev->buf.dirtyGroup[slot].dirty->type; - parent = dev->buf.dirtyGroup[slot].dirty->parent; - serial = dev->buf.dirtyGroup[slot].dirty->serial; - -retry: - uffs_BlockInfoLoad(dev, bc, UFFS_ALL_PAGES); - - flash_op_err = UFFS_FLASH_NO_ERR; - succRecover = U_FALSE; - - newNode = uffs_TreeGetErasedNode(dev); - if (newNode == NULL) { - uffs_Perror(UFFS_MSG_NOISY, "no enough erased block!"); - goto ext; - } - newBlock = newNode->u.list.block; - newBc = uffs_BlockInfoGet(dev, newBlock); - if (newBc == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "get block info fail!"); - uffs_InsertToErasedListHead(dev, newNode); //put node back to erased list - //because it doesn't use, so put to head - goto ext; - } - - //uffs_Perror(UFFS_MSG_NOISY, "flush buffer with block cover to %d", newBlock); - -#if 0 - // this assert seems not necessary ... - if (!uffs_Assert(newBc->expired_count == dev->attr->pages_per_block, - "We have block cache for erased block ? expired_count = %d, block = %d\n", - newBc->expired_count, newBc->block)) { - uffs_BlockInfoExpire(dev, newBc, UFFS_ALL_PAGES); - } -#endif - - uffs_BlockInfoLoad(dev, newBc, UFFS_ALL_PAGES); - timeStamp = uffs_GetNextBlockTimeStamp(uffs_GetBlockTimeStamp(dev, bc)); - -// uffs_Perror(UFFS_MSG_NOISY, "Flush buffers with Block Recover, from %d to %d", -// bc->block, newBc->block); - - for (i = 0; i < dev->attr->pages_per_block; i++) { - tag = GET_TAG(newBc, i); - TAG_DIRTY_BIT(tag) = TAG_DIRTY; - TAG_VALID_BIT(tag) = TAG_VALID; - TAG_BLOCK_TS(tag) = timeStamp; - TAG_PARENT(tag) = parent; - TAG_SERIAL(tag) = serial; - TAG_TYPE(tag) = type; - TAG_PAGE_ID(tag) = (u8)(i & 0xFF); // now, page_id = page. - // FIX ME!! if more than 256 pages in a block - - SEAL_TAG(tag); - - buf = _FindBufInDirtyList(dev->buf.dirtyGroup[slot].dirty, i); - if (buf != NULL) { - if (i == 0) - data_sum = _GetDirOrFileNameSum(dev, buf); - - TAG_DATA_LEN(tag) = buf->data_len; - - if (buf->data_len == 0 || (buf->ext_mark & UFFS_BUF_EXT_MARK_TRUNC_TAIL)) { // this only happen when truncating a file - - // when truncating a file, the last dirty buf will be - // set as UFFS_BUF_EXT_MARK_TAIL. so that we don't do page recovery - // for the rest pages in the block. (file is ended at this page) - - if (!uffs_Assert((buf->ext_mark & UFFS_BUF_EXT_MARK_TRUNC_TAIL) != 0, - "buf->data == 0 but not the last page of truncating ? block = %d, page_id = %d", - bc->block, i)) { - - // We can't do more about it for now ... - } - - if (buf->data_len > 0) { - flash_op_err = uffs_FlashWritePageCombine(dev, newBlock, i, buf, tag); - } - else { - // data_len == 0, no I/O needed. - flash_op_err = UFFS_FLASH_NO_ERR; - } - succRecover = U_TRUE; - break; - } - else - flash_op_err = uffs_FlashWritePageCombine(dev, newBlock, i, buf, tag); - - if (flash_op_err != UFFS_FLASH_NO_ERR) { - if (flash_op_err == UFFS_FLASH_BAD_BLK) { - uffs_Perror(UFFS_MSG_NORMAL, - "new bad block %d discovered.", newBlock); - break; - } - else if (flash_op_err == UFFS_FLASH_IO_ERR) { - uffs_Perror(UFFS_MSG_NORMAL, - "writing to block %d page %d, I/O error ?", - (int)newBlock, (int)i); - break; - } - else { - uffs_Perror(UFFS_MSG_SERIOUS, "Unhandled flash op result: %d", flash_op_err); - break; - } - } - } - else { - page = uffs_FindPageInBlockWithPageId(dev, bc, i); - if (page == UFFS_INVALID_PAGE) { - succRecover = U_TRUE; - break; //end of last page, normal break - } - page = uffs_FindBestPageInBlock(dev, bc, page); - - if (!uffs_Assert(page != UFFS_INVALID_PAGE, "got an invalid page ?\n")) - break; - - oldTag = GET_TAG(bc, page); - - // First, try to find existing cached buffer. - // Note: do not call uffs_BufGetEx() as it may trigger buf flush and result in infinite loop - buf = uffs_BufGet(dev, parent, serial, i); - - if (buf == NULL) { // no cached page buffer, use clone buffer. - useCloneBuf = U_TRUE; - buf = uffs_BufClone(dev, NULL); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Can't clone a new buf!"); - break; - } - x = uffs_BufLoadPhyData(dev, buf, bc->block, page); - if (x == U_FAIL) { - if (HAVE_BADBLOCK(dev) && dev->bad.block == bc->block) { - // the old block is a bad block, we'll process it later. - uffs_Perror(UFFS_MSG_SERIOUS, - "the old block %d is a bad block, \ - but ignore it for now.", - bc->block); - } - else { - uffs_Perror(UFFS_MSG_SERIOUS, "I/O error ?"); - uffs_BufFreeClone(dev, buf); - flash_op_err = UFFS_FLASH_IO_ERR; - break; - } - } - - buf->type = type; - buf->parent = parent; - buf->serial = serial; - buf->page_id = TAG_PAGE_ID(oldTag); - buf->data_len = TAG_DATA_LEN(oldTag); - - } - else { - useCloneBuf = U_FALSE; - - uffs_Assert(buf->page_id == TAG_PAGE_ID(oldTag), "buf->page_id = %d, tag page id: %d", buf->page_id, TAG_PAGE_ID(oldTag)); - uffs_Assert(buf->data_len == TAG_DATA_LEN(oldTag), "buf->data_len = %d, tag data len: %d", buf->data_len, TAG_DATA_LEN(oldTag)); - } - - if (buf->data_len > dev->com.pg_data_size) { - uffs_Perror(UFFS_MSG_NOISY, "data length over flow, truncated !"); - buf->data_len = dev->com.pg_data_size; - } - - if (!uffs_Assert(buf->data_len != 0, "data_len == 0 ? block %d, page %d, serial %d, parent %d", - bc->block, page, buf->serial, buf->parent)) { - // this could be some error on flash ? we can't do more about it for now ... - } - - TAG_DATA_LEN(tag) = buf->data_len; - - if (i == 0) - data_sum = _GetDirOrFileNameSum(dev, buf); - - flash_op_err = uffs_FlashWritePageCombine(dev, newBlock, i, buf, tag); - - if (buf) { - if (useCloneBuf) - uffs_BufFreeClone(dev, buf); - else - uffs_BufPut(dev, buf); - } - - if (flash_op_err == UFFS_FLASH_BAD_BLK) { - uffs_Perror(UFFS_MSG_NORMAL, - "new bad block %d discovered.", newBlock); - break; - } - else if (flash_op_err == UFFS_FLASH_IO_ERR) { - uffs_Perror(UFFS_MSG_NORMAL, "I/O error ?", newBlock); - break; - } - } - } //end of for - - if (i == dev->attr->pages_per_block) - succRecover = U_TRUE; - else { - // expire last page info cache in case the 'tag' is not written. - uffs_BlockInfoExpire(dev, newBc, i); - } - - if (flash_op_err == UFFS_FLASH_BAD_BLK) { - uffs_BlockInfoExpire(dev, newBc, UFFS_ALL_PAGES); - uffs_BlockInfoPut(dev, newBc); - if (newNode->u.list.block == dev->bad.block) { - // the recovered block is a BAD block (buy me a lotto, please :-), we need to - // deal with it immediately (mark it as 'bad' and put into bad block list). - uffs_BadBlockProcess(dev, newNode); - } - - uffs_Perror(UFFS_MSG_NORMAL, "Retry block cover ..."); - - goto retry; // retry on a new erased block ... - } - - if (succRecover == U_TRUE) { - // now it's time to clean the dirty buffers - for (i = 0; i < dev->attr->pages_per_block; i++) { - buf = _FindBufInDirtyList(dev->buf.dirtyGroup[slot].dirty, i); - if (buf) { - if (_BreakFromDirty(dev, buf) == U_SUCC) { - buf->mark = UFFS_BUF_VALID; - buf->ext_mark &= ~UFFS_BUF_EXT_MARK_TRUNC_TAIL; - _MoveNodeToHead(dev, buf); - } - } - } - - // swap the old block node and new block node. - // it's important that we 'swap' the block and keep the node unchanged - // so that allowing someone hold the node pointer unawared. - switch (type) { - case UFFS_TYPE_DIR: - node->u.dir.parent = parent; - node->u.dir.serial = serial; - node->u.dir.block = newBlock; - node->u.dir.checksum = data_sum; - break; - case UFFS_TYPE_FILE: - node->u.file.parent = parent; - node->u.file.serial = serial; - node->u.file.block = newBlock; - node->u.file.checksum = data_sum; - break; - case UFFS_TYPE_DATA: - node->u.data.parent = parent; - node->u.data.serial = serial; - node->u.data.block = newBlock; - break; - default: - uffs_Perror(UFFS_MSG_SERIOUS, "UNKNOW TYPE"); - break; - } - - newNode->u.list.block = bc->block; - - // if the recovered block is a bad block, it's time to process it. - if (HAVE_BADBLOCK(dev) && dev->bad.block == newNode->u.list.block) { - //uffs_Perror(UFFS_MSG_SERIOUS, "Still have bad block ?"); - uffs_BadBlockProcess(dev, newNode); - } - else { - // erase recovered block, put it back to erased block list. - if (uffs_IsThisBlockUsed(dev, bc)) { - uffs_FlashEraseBlock(dev, bc->block); - } - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, newNode); - else - uffs_TreeInsertToErasedListTail(dev, newNode); - } - } - else { - - uffs_BlockInfoExpire(dev, bc, UFFS_ALL_PAGES); // FIXME: this might not be necessary ... - - uffs_FlashEraseBlock(dev, newBlock); - newNode->u.list.block = newBlock; - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, newNode); - else - uffs_TreeInsertToErasedListTail(dev, newNode); - } - - if (dev->buf.dirtyGroup[slot].dirty != NULL || - dev->buf.dirtyGroup[slot].count != 0) { - uffs_Perror(UFFS_MSG_NORMAL, "still have dirty buffer ?"); - } - - uffs_BlockInfoPut(dev, newBc); - -ext: - return (succRecover == U_TRUE ? U_SUCC : U_FAIL); - -} - - - -/** - * \brief flush buffer to a new block which is not registered in tree - * - * Scenario: - * 1. get a new block - * 2. write pages in dirty list to new block, sorted by page_id - * 3. insert new block to tree - */ -static URET _BufFlush_NewBlock(uffs_Device *dev, int slot) -{ - u8 type; - TreeNode *node; - uffs_BlockInfo *bc; - URET ret; - - ret = U_FAIL; - - node = uffs_TreeGetErasedNode(dev); - if (node == NULL) { - uffs_Perror(UFFS_MSG_NOISY, "no erased block!"); - goto ext; - } - bc = uffs_BlockInfoGet(dev, node->u.list.block); - if (bc == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "get block info fail!"); - uffs_InsertToErasedListHead(dev, node); //put node back to erased list - goto ext; - } - - type = dev->buf.dirtyGroup[slot].dirty->type; - - ret = uffs_BufFlush_Exist_With_BlockCover(dev, slot, node, bc); - - if (ret == U_SUCC) - uffs_InsertNodeToTree(dev, type, node); - else { - uffs_FlashEraseBlock(dev, bc->block); - uffs_TreeInsertToErasedListTail(dev, node); - } - - uffs_BlockInfoPut(dev, bc); -ext: - return ret; -} - - -/** - * \brief flush buffer to a block with enough free pages - * - * pages in dirty list must be sorted by page_id to write to flash - */ -static -URET - uffs_BufFlush_Exist_With_Enough_FreePage( - uffs_Device *dev, - int slot, //!< dirty group slot - TreeNode *node, //!< tree node - uffs_BlockInfo *bc //!< block info (Source, also destination) - ) -{ - u16 page; - uffs_Buf *buf; - uffs_Tags *tag; - URET ret = U_FAIL; - int x; - -// uffs_Perror(UFFS_MSG_NOISY, -// "Flush buffers with Enough Free Page to block %d", -// bc->block); - - for (page = 1; // page 0 won't be a free page, so we start from 1. - page < dev->attr->pages_per_block && - dev->buf.dirtyGroup[slot].count > 0; //still has dirty pages? - page++) { - - // locate to the free page (make sure the page is a erased page, so an unclean page won't sneak in) - for (; page < dev->attr->pages_per_block; page++) { - if (uffs_IsPageErased(dev, bc, page)) - break; - } - - if (!uffs_Assert(page < dev->attr->pages_per_block, "no free page? buf flush not finished.")) - break; - - buf = _FindMinimunPageIdFromDirtyList(dev->buf.dirtyGroup[slot].dirty); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "count > 0, but no dirty pages in list ?"); - goto ext; - } - - //write the dirty page (id: buf->page_id) to page (free page) - tag = GET_TAG(bc, page); - TAG_DIRTY_BIT(tag) = TAG_DIRTY; - TAG_VALID_BIT(tag) = TAG_VALID; - TAG_BLOCK_TS(tag) = uffs_GetBlockTimeStamp(dev, bc); - TAG_DATA_LEN(tag) = buf->data_len; - TAG_TYPE(tag) = buf->type; - TAG_PARENT(tag) = buf->parent; - TAG_SERIAL(tag) = buf->serial; - TAG_PAGE_ID(tag) = (u8)(buf->page_id); - - SEAL_TAG(tag); - - x = uffs_FlashWritePageCombine(dev, bc->block, page, buf, tag); - if (x == UFFS_FLASH_IO_ERR) { - uffs_Perror(UFFS_MSG_NORMAL, "I/O error <1>?"); - goto ext; - } - else if (x == UFFS_FLASH_BAD_BLK) { - uffs_Perror(UFFS_MSG_NORMAL, "Bad blcok found, start block cover ..."); - ret = uffs_BufFlush_Exist_With_BlockCover(dev, slot, node, bc); - goto ext; - } - else { - if(_BreakFromDirty(dev, buf) == U_SUCC) { - buf->mark = UFFS_BUF_VALID; - _MoveNodeToHead(dev, buf); - } - } - } //end of for - - if (dev->buf.dirtyGroup[slot].dirty != NULL || - dev->buf.dirtyGroup[slot].count != 0) { - uffs_Perror(UFFS_MSG_NORMAL, "still has dirty buffer ?"); - } - else { - ret = U_SUCC; - } - -ext: - return ret; -} - - -URET _BufFlush(struct uffs_DeviceSt *dev, - UBOOL force_block_recover, int slot) -{ - uffs_Buf *dirty; - TreeNode *node; - uffs_BlockInfo *bc; - u16 n; - URET ret; - u8 type; - u16 parent; - u16 serial; - int block; - - if (dev->buf.dirtyGroup[slot].count == 0) { - return U_SUCC; - } - - dirty = dev->buf.dirtyGroup[slot].dirty; - - if (_CheckDirtyList(dirty) == U_FAIL) - return U_FAIL; - - type = dirty->type; - parent = dirty->parent; - serial = dirty->serial; - - switch (type) { - case UFFS_TYPE_DIR: - node = uffs_TreeFindDirNode(dev, serial); - break; - case UFFS_TYPE_FILE: - node = uffs_TreeFindFileNode(dev, serial); - break; - case UFFS_TYPE_DATA: - node = uffs_TreeFindDataNode(dev, parent, serial); - break; - default: - uffs_Perror(UFFS_MSG_SERIOUS, "unknown type"); - return U_FAIL; - } - - if (node == NULL) { - //not found in the tree, need to generate a new block - ret = _BufFlush_NewBlock(dev, slot); - } - else { - switch (type) { - case UFFS_TYPE_DIR: - block = node->u.dir.block; - break; - case UFFS_TYPE_FILE: - block = node->u.file.block; - break; - case UFFS_TYPE_DATA: - block = node->u.data.block; - break; - default: - uffs_Perror(UFFS_MSG_SERIOUS, "unknown type."); - return U_FAIL; - } - bc = uffs_BlockInfoGet(dev, block); - if(bc == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "get block info fail."); - return U_FAIL; - } - - ret = uffs_BlockInfoLoad(dev, bc, UFFS_ALL_PAGES); - if (ret == U_SUCC) { - - n = uffs_GetFreePagesCount(dev, bc); - - if (n >= dev->buf.dirtyGroup[slot].count && !force_block_recover) { - //The free pages are enough for the dirty pages - ret = uffs_BufFlush_Exist_With_Enough_FreePage(dev, slot, node, bc); - } - else { - ret = uffs_BufFlush_Exist_With_BlockCover(dev, slot, node, bc); - } - } - uffs_BlockInfoPut(dev, bc); - } - - return ret; -} - -static int _FindMostDirtyGroup(struct uffs_DeviceSt *dev) -{ - int i, slot = -1; - int max_count = 0; - - for (i = 0; i < dev->cfg.dirty_groups; i++) { - if (dev->buf.dirtyGroup[i].dirty && - dev->buf.dirtyGroup[i].lock == 0) { - if (dev->buf.dirtyGroup[i].count > max_count) { - max_count = dev->buf.dirtyGroup[i].count; - slot = i; - } - } - } - - return slot; -} - -/** lock dirty group */ -URET uffs_BufLockGroup(struct uffs_DeviceSt *dev, int slot) -{ - URET ret = U_FAIL; - if (slot >= 0 && slot < dev->cfg.dirty_groups) { - dev->buf.dirtyGroup[slot].lock++; - ret = U_SUCC; - } - return ret; -} - -/** unlock dirty group */ -URET uffs_BufUnLockGroup(struct uffs_DeviceSt *dev, int slot) -{ - URET ret = U_FAIL; - - if (slot >= 0 && slot < dev->cfg.dirty_groups) { - if (dev->buf.dirtyGroup[slot].lock > 0) - dev->buf.dirtyGroup[slot].lock--; - else { - uffs_Perror(UFFS_MSG_SERIOUS, "Try to unlock an unlocked group ?"); - } - ret = U_SUCC; - } - return ret; -} - - -/** - * flush buffers to flash. - * this will flush all dirty groups. - * \param[in] dev uffs device - */ -URET uffs_BufFlush(struct uffs_DeviceSt *dev) -{ - int slot; - - slot = uffs_BufFindFreeGroupSlot(dev); - if (slot >= 0) - return U_SUCC; // do nothing if there is free slot - else - return uffs_BufFlushMostDirtyGroup(dev); -} - -/** - * flush most dirty group - * \param[in] dev uffs device - */ -URET uffs_BufFlushMostDirtyGroup(struct uffs_DeviceSt *dev) -{ - int slot; - - slot = _FindMostDirtyGroup(dev); - if (slot >= 0) { - return _BufFlush(dev, U_FALSE, slot); - } - return U_SUCC; -} - -/** - * flush buffers to flash - * this will pick up a most dirty group, - * and flush it if there is no free dirty group slot. - * - * \param[in] dev uffs device - * \param[in] force_block_recover #U_TRUE: force a block recover - * even there are enough free pages - */ -URET uffs_BufFlushEx(struct uffs_DeviceSt *dev, UBOOL force_block_recover) -{ - int slot; - - slot = uffs_BufFindFreeGroupSlot(dev); - if (slot >= 0) { - return U_SUCC; //there is free slot, do nothing. - } - else { - slot = _FindMostDirtyGroup(dev); - return _BufFlush(dev, force_block_recover, slot); - } -} - -/** - * flush buffer group with given parent/serial num. - * - * \param[in] dev uffs device - * \param[in] parent parent num of the group - * \param[in] serial serial num of the group - */ -URET uffs_BufFlushGroup(struct uffs_DeviceSt *dev, u16 parent, u16 serial) -{ - int slot; - - slot = uffs_BufFindGroupSlot(dev, parent, serial); - if (slot >= 0) { - return _BufFlush(dev, U_FALSE, slot); - } - - return U_SUCC; -} - -/** - * flush buffer group with given parent/serial num - * and force_block_recover indicator. - * - * \param[in] dev uffs device - * \param[in] parent parent num of the group - * \param[in] serial serial num of group - * \param[in] force_block_recover indicator - */ -URET uffs_BufFlushGroupEx(struct uffs_DeviceSt *dev, - u16 parent, u16 serial, UBOOL force_block_recover) -{ - int slot; - - slot = uffs_BufFindGroupSlot(dev, parent, serial); - if (slot >= 0) { - return _BufFlush(dev, force_block_recover, slot); - } - - return U_SUCC; -} - - -/** - * flush buffer group/groups which match given parent num. - * - * \param[in] dev uffs device - * \param[in] parent parent num of the group - * \param[in] serial serial num of group - * \param[in] force_block_recover indicator - */ -URET uffs_BufFlushGroupMatchParent(struct uffs_DeviceSt *dev, u16 parent) -{ - int slot; - uffs_Buf *buf; - URET ret = U_SUCC; - - for (slot = 0; slot < dev->cfg.dirty_groups && ret == U_SUCC; slot++) { - if (dev->buf.dirtyGroup[slot].dirty) { - buf = dev->buf.dirtyGroup[slot].dirty; - if (buf->parent == parent) { - ret = _BufFlush(dev, U_FALSE, slot); - } - } - } - - return ret; -} - -/** - * find a free dirty group slot - * - * \param[in] dev uffs device - * \return slot index (0 to MAX_DIRTY_BUF_GROUPS - 1) if found one, - * otherwise return -1. - */ -int uffs_BufFindFreeGroupSlot(struct uffs_DeviceSt *dev) -{ - int i, slot = -1; - - for (i = 0; i < dev->cfg.dirty_groups; i++) { - if (dev->buf.dirtyGroup[i].dirty == NULL) { - slot = i; - break; - } - } - return slot; -} - -/** - * find a dirty group slot with given parent/serial num. - * - * \param[in] dev uffs device - * \param[in] parent parent num of the group - * \param[in] serial serial num of group - * \return slot index (0 to MAX_DIRTY_BUF_GROUPS - 1) if found one, - * otherwise return -1. - */ -int uffs_BufFindGroupSlot(struct uffs_DeviceSt *dev, u16 parent, u16 serial) -{ - uffs_Buf *buf; - int i, slot = -1; - - for (i = 0; i < dev->cfg.dirty_groups; i++) { - if (dev->buf.dirtyGroup[i].dirty) { - buf = dev->buf.dirtyGroup[i].dirty; - if (buf->parent == parent && buf->serial == serial) { - slot = i; - break; - } - } - } - return slot; -} - -/** - * \brief get a page buffer - * \param[in] dev uffs device - * \param[in] parent parent serial num - * \param[in] serial serial num - * \param[in] page_id page_id - * \return return the buffer found in buffer list, if not found, return NULL. - */ -uffs_Buf * uffs_BufGet(struct uffs_DeviceSt *dev, - u16 parent, u16 serial, u16 page_id) -{ - uffs_Buf *p; - - //first, check whether the buffer exist in buf list ? - p = uffs_BufFind(dev, parent, serial, page_id); - - if (p) { - p->ref_count++; - _MoveNodeToHead(dev, p); - } - - return p; -} - -/** - * New generate a buffer - */ -uffs_Buf *uffs_BufNew(struct uffs_DeviceSt *dev, - u8 type, u16 parent, u16 serial, u16 page_id) -{ - uffs_Buf *buf; - - buf = uffs_BufGet(dev, parent, serial, page_id); - if (buf) { - if (buf->ref_count > 1) { - uffs_Perror(UFFS_MSG_SERIOUS, "When create new buf, \ - an exist buffer has ref count %d, possibly bug!", - buf->ref_count); - } - else { - buf->data_len = 0; - } - _MoveNodeToHead(dev, buf); - return buf; - } - - buf = _FindFreeBuf(dev); - if (buf == NULL) { - uffs_BufFlushMostDirtyGroup(dev); - buf = _FindFreeBuf(dev); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "no free page buf!"); - return NULL; - } - } - - buf->mark = UFFS_BUF_EMPTY; - buf->type = type; - buf->parent = parent; - buf->serial = serial; - buf->page_id = page_id; - buf->data_len = 0; - buf->ref_count++; - memset(buf->data, 0xff, dev->com.pg_data_size); - - _MoveNodeToHead(dev, buf); - - return buf; -} - - - -/** - * get a page buffer - * \param[in] dev uffs device - * \param[in] type dir, file or data ? - * \param[in] node node on the tree - * \param[in] page_id page_id - * \param[in] oflag the open flag of current file/dir object - * \return return the buffer if found in buffer list, if not found in - * buffer list, it will get a free buffer, and load data from flash. - * return NULL if not free buffer. - */ -uffs_Buf *uffs_BufGetEx(struct uffs_DeviceSt *dev, - u8 type, TreeNode *node, u16 page_id, int oflag) -{ - uffs_Buf *buf; - u16 parent, serial, block, page; - uffs_BlockInfo *bc; - - switch (type) { - case UFFS_TYPE_DIR: - parent = node->u.dir.parent; - serial = node->u.dir.serial; - block = node->u.dir.block; - break; - case UFFS_TYPE_FILE: - parent = node->u.file.parent; - serial = node->u.file.serial; - block = node->u.file.block; - break; - case UFFS_TYPE_DATA: - parent = node->u.data.parent; - serial = node->u.data.serial; - block = node->u.data.block; - break; - default: - uffs_Perror(UFFS_MSG_SERIOUS, "unknown type"); - return NULL; - } - - buf = uffs_BufFind(dev, parent, serial, page_id); - if (buf) { - buf->ref_count++; - return buf; - } - - buf = _FindFreeBuf(dev); - if (buf == NULL) { - uffs_BufFlushMostDirtyGroup(dev); - buf = _FindFreeBuf(dev); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "no free page buf!"); - return NULL; - } - - /* Note: if uffs_BufFlushMostDirtyGroup() flush the same block as we'll write to, - * the block will be changed to a new one! (and the content of 'node' is changed). - * So here we need to update block number from the new 'node'. - */ - switch (type) { - case UFFS_TYPE_DIR: - block = node->u.dir.block; - break; - case UFFS_TYPE_FILE: - block = node->u.file.block; - break; - case UFFS_TYPE_DATA: - block = node->u.data.block; - break; - default: - uffs_Perror(UFFS_MSG_SERIOUS, "unknown type"); - return NULL; - } - } - - bc = uffs_BlockInfoGet(dev, block); - if (bc == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Can't get block info!"); - return NULL; - } - - page = uffs_FindPageInBlockWithPageId(dev, bc, page_id); - if (page == UFFS_INVALID_PAGE) { - uffs_BlockInfoPut(dev, bc); - uffs_Perror(UFFS_MSG_SERIOUS, "can't find right page ? block %d page_id %d", bc->block, page_id); - return NULL; - } - page = uffs_FindBestPageInBlock(dev, bc, page); - if (!uffs_Assert(page != UFFS_INVALID_PAGE, "got an invalid page?\n")) - return NULL; - - uffs_BlockInfoPut(dev, bc); - - buf->mark = UFFS_BUF_EMPTY; - buf->type = type; - buf->parent = parent; - buf->serial = serial; - buf->page_id = page_id; - - if (UFFS_FLASH_HAVE_ERR(uffs_FlashReadPage(dev, block, page, buf, oflag & UO_NOECC ? U_TRUE : U_FALSE))) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't load page from flash !"); - return NULL; - } - - buf->data_len = TAG_DATA_LEN(GET_TAG(bc, page)); - buf->mark = UFFS_BUF_VALID; - buf->ref_count++; - - _MoveNodeToHead(dev, buf); - - return buf; - -} - -/** - * \brief Put back a page buffer, make reference count decrease by one - * \param[in] dev uffs device - * \param[in] buf buffer to be put back - */ -URET uffs_BufPut(uffs_Device *dev, uffs_Buf *buf) -{ - URET ret = U_FAIL; - - dev = dev; - if (buf == NULL) { - uffs_Perror(UFFS_MSG_NORMAL, "Can't put an NULL buffer!"); - } - else if (buf->ref_count == 0) { - uffs_Perror(UFFS_MSG_NORMAL, "Putting an unused page buffer ? "); - } - else if (buf->ref_count == CLONE_BUF_MARK) { - uffs_Perror(UFFS_MSG_NORMAL, "Putting an cloned page buffer ? "); - ret = uffs_BufFreeClone(dev, buf); - } - else { - buf->ref_count--; - ret = U_SUCC; - } - - return ret; -} - - -/** - * \brief clone from an exist buffer. - allocate memory for new buffer, and copy data from original buffer if - original buffer is not NULL. - * \param[in] dev uffs device - * \param[in] buf page buffer to be clone from. - * if NULL presented here, data copy will not be processed - * \return return the cloned page buffer, all data copied from source - * \note the cloned buffer is not linked in page buffer list in uffs device, - * so you should use #uffs_BufFreeClone instead of #uffs_BufPut - * when you put back or release buffer - */ -uffs_Buf * uffs_BufClone(uffs_Device *dev, uffs_Buf *buf) -{ - uffs_Buf *p; - - p = _FindFreeBufEx(dev, 1); - if (p == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "no enough free pages for clone! " \ - "Please increase Clone Buffer Count threshold."); - } - else { - _BreakFromBufList(dev, p); - - if (buf) { - p->parent = buf->parent; - p->type = buf->type; - p->serial = buf->serial; - p->page_id = buf->page_id; - - p->data_len = buf->data_len; - //athough the valid data length is .data_len, - //but we still need copy the whole buffer, include header - memcpy(p->header, buf->header, dev->com.pg_size); - } - p->next = p->prev = NULL; // the cloned one is not linked to device buffer - p->next_dirty = p->prev_dirty = NULL; - p->ref_count = CLONE_BUF_MARK; // CLONE_BUF_MARK indicates that - // this is an cloned buffer - } - - return p; -} - -/** - * \brief release cloned buffer - * \param[in] dev uffs device - * \param[in] buf cloned buffer - */ -URET uffs_BufFreeClone(uffs_Device *dev, uffs_Buf *buf) -{ - dev = dev; //make compiler happy - if (!buf) - return U_FAIL; - - if (buf->ref_count != CLONE_BUF_MARK) { - /* a cloned buffer must have a ref_count of CLONE_BUF_MARK */ - uffs_Perror(UFFS_MSG_SERIOUS, - "Try to release a non-cloned page buffer ?"); - return U_FAIL; - } - - buf->ref_count = 0; - buf->mark = UFFS_BUF_EMPTY; - _LinkToBufListTail(dev, buf); - - return U_SUCC; -} - - - -UBOOL uffs_BufIsAllFree(struct uffs_DeviceSt *dev) -{ - uffs_Buf *buf = dev->buf.head; - - while (buf) { - if(buf->ref_count != 0) return U_FALSE; - buf = buf->next; - } - - return U_TRUE; -} - -UBOOL uffs_BufIsAllEmpty(struct uffs_DeviceSt *dev) -{ - uffs_Buf *buf = dev->buf.head; - - while (buf) { - if(buf->mark != UFFS_BUF_EMPTY) return U_FALSE; - buf = buf->next; - } - - return U_TRUE; -} - - -URET uffs_BufSetAllEmpty(struct uffs_DeviceSt *dev) -{ - uffs_Buf *buf = dev->buf.head; - - while (buf) { - buf->mark = UFFS_BUF_EMPTY; - buf = buf->next; - } - return U_SUCC; -} - - -void uffs_BufIncRef(uffs_Buf *buf) -{ - buf->ref_count++; -} - -void uffs_BufDecRef(uffs_Buf *buf) -{ - if (buf->ref_count > 0) - buf->ref_count--; -} - -/** mark buffer as #UFFS_BUF_EMPTY if ref_count == 0, - and discard all data it holds */ -void uffs_BufMarkEmpty(uffs_Device *dev, uffs_Buf *buf) -{ - if (buf->mark != UFFS_BUF_EMPTY) { - if (buf->ref_count == 0) { - if (buf->mark == UFFS_BUF_DIRTY) - _BreakFromDirty(dev, buf); - buf->mark = UFFS_BUF_EMPTY; - } - } -} - -#if 0 -static UBOOL _IsBufInDirtyList(struct uffs_DeviceSt *dev, uffs_Buf *buf) -{ - uffs_Buf *p = dev->buf.dirtyGroup[slot].dirty; - - while (p) { - if(p == buf) return U_TRUE; - p = p->next_dirty; - } - - return U_FALSE; -} -#endif - -URET uffs_BufWrite(struct uffs_DeviceSt *dev, - uffs_Buf *buf, void *data, u32 ofs, u32 len) -{ - int slot; - - if(ofs + len > dev->com.pg_data_size) { - uffs_Perror(UFFS_MSG_SERIOUS, - "data length out of range! %d+%d", ofs, len); - return U_FAIL; - } - - slot = uffs_BufFindGroupSlot(dev, buf->parent, buf->serial); - - if (slot < 0) { - // need to take a free slot - slot = uffs_BufFindFreeGroupSlot(dev); - if (slot < 0) { - // no free slot ? flush buffer - if (uffs_BufFlushMostDirtyGroup(dev) != U_SUCC) - return U_FAIL; - - slot = uffs_BufFindFreeGroupSlot(dev); - if (slot < 0) { - // still no free slot ?? - uffs_Perror(UFFS_MSG_SERIOUS, "no free slot ?"); - return U_FAIL; - } - } - } - - if (data) - memcpy(buf->data + ofs, data, len); - else - memset(buf->data + ofs, 0, len); // if data == NULL, then fill all '\0'. - - if (ofs + len > buf->data_len) - buf->data_len = ofs + len; - - if (_IsBufInInDirtyList(dev, slot, buf) == U_FALSE) { - _LinkToDirtyList(dev, slot, buf); - } - - if (dev->buf.dirtyGroup[slot].count >= dev->buf.dirty_buf_max) { - if (uffs_BufFlushGroup(dev, buf->parent, buf->serial) != U_SUCC) { - return U_FAIL; - } - } - - return U_SUCC; -} - -URET uffs_BufRead(struct uffs_DeviceSt *dev, - uffs_Buf *buf, void *data, u32 ofs, u32 len) -{ - u32 readSize; - u32 pg_data_size = dev->com.pg_data_size; - - readSize = (ofs >= pg_data_size ? - 0 : (ofs + len >= pg_data_size ? pg_data_size - ofs : len) - ); - - if (readSize > 0) - memcpy(data, buf->data + ofs, readSize); - - return U_SUCC; -} - - - - - - - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_crc.c b/components/dfs/filesystems/uffs/src/uffs/uffs_crc.c deleted file mode 100644 index 0ef95bf7f1..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_crc.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ -/** - * \file uffs_crc.c - * \brief simple CRC functions - * \author Ricky Zheng - * \note Created in 23 Nov, 2011 - */ - -#include "uffs/uffs_crc.h" - -/* CRC16 Table */ -static const u16 CRC16_TBL[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -#define CRC16(v, x) v = ((v) >> 8) ^ CRC16_TBL[((v) ^ (x)) & 0x00ff] - -u16 uffs_crc16update(const void *data, int length, u16 crc) -{ - int i; - const u8 *p = (const u8 *)data; - for (i = 0; i < length; i++, p++) { - CRC16(crc, *p); - } - - return crc; -} - -u16 uffs_crc16sum(const void *data, int length) -{ - return uffs_crc16update(data, length, 0xFFFF); -} diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_debug.c b/components/dfs/filesystems/uffs/src/uffs/uffs_debug.c deleted file mode 100644 index 5f6c1558e4..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_debug.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_debug.c - * \brief output debug messages - * \author Ricky Zheng, created 10th May, 2005 - */ -#include "uffs_config.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" - -#if !defined(RT_THREAD) -#include -#include -#include - -#define MAX_DEBUG_MSG_LINE_LENGTH 128 - -static struct uffs_DebugMsgOutputSt * m_ops = NULL; -static int m_msg_level = UFFS_MSG_NORMAL; - -static void uffs_vprintf(const char *fmt, va_list args) -{ - char line_buf[MAX_DEBUG_MSG_LINE_LENGTH]; - - if (m_ops && m_ops->output) { -#ifdef _COMPILER_CLIB_DO_NOT_HAVE_VSNPRINTF_ - vsprintf(line_buf, fmt, args); -#else - vsnprintf(line_buf, MAX_DEBUG_MSG_LINE_LENGTH, fmt, args); -#endif - m_ops->output(line_buf); - } -} - -/** - * \brief Initialize debug message output functions - */ -URET uffs_InitDebugMessageOutput(struct uffs_DebugMsgOutputSt *ops, int msg_level) -{ - m_ops = ops; - - if (m_ops == NULL || m_ops->output == NULL) { - m_ops = NULL; - return U_FAIL; - } - else if (m_ops->vprintf == NULL) - m_ops->vprintf = uffs_vprintf; - - m_msg_level = msg_level; - - return U_SUCC; -} - -void uffs_DebugSetMessageLevel(int msg_level) -{ - m_msg_level = msg_level; -} -#endif - -#ifdef CONFIG_ENABLE_UFFS_DEBUG_MSG - -/** - * \brief The main debug message output function - */ -#if !defined(RT_THREAD) -void uffs_DebugMessage(int level, const char *prefix, - const char *suffix, const char *errFmt, ...) -{ - va_list arg; - - if (m_ops && level >= m_msg_level) { - if (prefix) - m_ops->output(prefix); - - va_start(arg, errFmt); - m_ops->vprintf(errFmt, arg); - va_end(arg); - - if (suffix) - m_ops->output(suffix); - } -} - -/** - * \brief Called when an assert occurred. - * This method is called when an assert occurred and should stop the - * application from running, as this there is a severe error condition. - * \param[in] file Source filename - * \param[in] line Source line of code - * \param[in] msg Assert message - */ -void uffs_AssertCall(const char *file, int line, const char *msg, ...) -{ - va_list args; - char buf[32]; - - if (m_ops && m_msg_level < UFFS_MSG_NOMSG) { - m_ops->output("ASSERT "); - m_ops->output(file); - sprintf(buf, ":%d - :", line); - m_ops->output(buf); - va_start(args, msg); - m_ops->vprintf(msg, args); - va_end(args); - m_ops->output(TENDSTR); - } -} -#endif - -#ifdef _COMPILER_DO_NOT_SUPPORT_MACRO_VALIST_REPLACE_ -void uffs_Perror(int level, const char *fmt, ...) -{ - va_list args; - if (m_ops && level >= m_msg_level) { - va_start(args, fmt); - m_ops->vprintf(fmt, args); - va_end(args); - m_ops->output(TENDSTR); - } -} - -void uffs_PerrorRaw(int level, const char *fmt, ...) -{ - va_list args; - if (m_ops && level >= m_msg_level) { - va_start(args, fmt); - m_ops->vprintf(fmt, args); - va_end(args); - } -} - -UBOOL uffs_Assert(UBOOL expr, const char *fmt, ...) -{ - va_list args; - if (m_ops && !expr && m_msg_level < UFFS_MSG_NOMSG) { - m_ops->output("ASSERT FAILED: "); - va_start(args, fmt); - m_ops->vprintf(fmt, args); - va_end(args); - m_ops->output(TENDSTR); - } - return expr ? U_TRUE : U_FALSE; -} -#endif - -#else - -void uffs_DebugMessage(int level, const char *prefix, const char *suffix, const char *errFmt, ...) {}; -void uffs_AssertCall(const char *file, int line, const char *msg, ...) {}; - -#ifdef _COMPILER_DO_NOT_SUPPORT_MACRO_VALIST_REPLACE_ -void uffs_Perror(int level, const char *fmt, ...) {} -void uffs_PerrorRaw(int level, const char *fmt, ...) {} -UBOOL uffs_Assert(UBOOL expr, const char *fmt, ...) { return expr ? U_TRUE : U_FALSE; } -#endif - -#endif diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_device.c b/components/dfs/filesystems/uffs/src/uffs/uffs_device.c deleted file mode 100644 index 7b6a14de81..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_device.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_device.c - * \brief uffs device operation - * \author Ricky Zheng, created 10th May, 2005 - */ -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_mtb.h" -#include - -#define PFX "dev : " - - -#ifdef CONFIG_USE_PER_DEVICE_LOCK -void uffs_DeviceInitLock(uffs_Device *dev) -{ - uffs_SemCreate(&dev->lock.sem); - dev->lock.task_id = UFFS_TASK_ID_NOT_EXIST; - dev->lock.counter = 0; -} - -void uffs_DeviceReleaseLock(uffs_Device *dev) -{ - uffs_SemDelete(&dev->lock.sem); -} - -void uffs_DeviceLock(uffs_Device *dev) -{ - uffs_SemWait(dev->lock.sem); - - if (dev->lock.counter != 0) { - uffs_Perror(UFFS_MSG_NORMAL, - "Lock device, counter %d NOT zero?!", dev->lock.counter); - } - - dev->lock.counter++; -} - -void uffs_DeviceUnLock(uffs_Device *dev) -{ - dev->lock.counter--; - - if (dev->lock.counter != 0) { - uffs_Perror(UFFS_MSG_NORMAL, - "Unlock device, counter %d NOT zero?!", dev->lock.counter); - } - - uffs_SemSignal(dev->lock.sem); -} - -#else - -/* dummy stubs */ -void uffs_DeviceInitLock(uffs_Device *dev) {} -void uffs_DeviceReleaseLock(uffs_Device *dev) {} -void uffs_DeviceLock(uffs_Device *dev) {} -void uffs_DeviceUnLock(uffs_Device *dev) {} - -#endif diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_ecc.c b/components/dfs/filesystems/uffs/src/uffs/uffs_ecc.c deleted file mode 100644 index 3d10c2d3f0..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_ecc.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_ecc.c - * \brief ecc maker and correct - * \author Ricky Zheng, created in 12th Jun, 2005 - */ -#include "uffs_config.h" -#include "uffs/uffs_fs.h" -#include - -#define PFX "ecc : " - -static const u8 bits_tbl[256] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, -}; - -static const u8 line_parity_tbl[16] = { - 0x00, 0x02, 0x08, 0x0a, 0x20, 0x22, 0x28, 0x2a, - 0x80, 0x82, 0x88, 0x8a, 0xa0, 0xa2, 0xa8, 0xaa -}; - -static const u8 line_parity_prime_tbl[16] = { - 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, - 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 -}; - -static const u8 column_parity_tbl[256] = { - 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, - 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, - 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, - 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, - 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, - 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, - 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, - 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, - 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, - 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, - 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, - 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, - 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, - 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, - 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, - 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, - 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, - 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, - 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, - 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, - 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, - 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, - 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, - 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, - 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, - 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, - 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, - 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, - 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, - 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, - 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, - 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, -}; - -/** - * calculate 3 bytes ECC for 256 bytes data. - * - * \param[in] data input data - * \param[out] ecc output ecc - * \param[in] length of data in bytes - */ -static void uffs_EccMakeChunk256(const void *data, void *ecc, u16 len) -{ - u8 *pecc = (u8 *)ecc; - const u8 *p = (const u8 *)data; - u8 b, col_parity = 0, line_parity = 0, line_parity_prime = 0; - u16 i; - - for (i = 0; i < len; i++) { - b = column_parity_tbl[*p++]; - col_parity ^= b; - if (b & 0x01) { // odd number of bits in the byte - line_parity ^= i; - line_parity_prime ^= ~i; - } - } - - // ECC layout: - // Byte[0] P64 | P64' | P32 | P32' | P16 | P16' | P8 | P8' - // Byte[1] P1024 | P1024' | P512 | P512' | P256 | P256' | P128 | P128' - // Byte[2] P4 | P4' | P2 | P2' | P1 | P1' | 1 | 1 - pecc[0] = ~(line_parity_tbl[line_parity & 0xf] | - line_parity_prime_tbl[line_parity_prime & 0xf]); - pecc[1] = ~(line_parity_tbl[line_parity >> 4] | - line_parity_prime_tbl[line_parity_prime >> 4]); - pecc[2] = (~col_parity) | 0x03; - -} - - -/** - * calculate ECC. (3 bytes ECC per 256 data) - * - * \param[in] data input data - * \param[in] data_len length of data in byte - * \param[out] ecc output ecc - * - * \return length of ECC in byte. (3 bytes ECC per 256 data) - */ -int uffs_EccMake(const void *data, int data_len, void *ecc) -{ - const u8 *p_data = (const u8 *)data; - u8 *p_ecc = (u8 *)ecc; - int len; - - if (data == NULL || ecc == NULL) - return 0; - - while (data_len > 0) { - len = data_len > 256 ? 256 : data_len; - uffs_EccMakeChunk256(p_data, p_ecc, len); - data_len -= len; - p_data += len; - p_ecc += 3; - } - - return p_ecc - (u8 *)ecc; -} - -/** - * perform ECC error correct for 256 bytes data chunk. - * - * \param[in|out] data input data to be corrected - * \param[in] read_ecc 3 bytes ECC read from storage - * \param[in] test_ecc 3 bytes ECC calculated from data - * \param[in] errtop top position of error - * - * \return: 0 -- no error - * -1 -- can not be corrected - * >0 -- how many bits corrected - */ -static int uffs_EccCorrectChunk256(void *data, void *read_ecc, - const void *test_ecc, int errtop) -{ - u8 d0, d1, d2; /* deltas */ - u8 *p = (u8 *)data; - u8 *pread_ecc = (u8 *)read_ecc, *ptest_ecc = (u8 *)test_ecc; - - d0 = pread_ecc[0] ^ ptest_ecc[0]; - d1 = pread_ecc[1] ^ ptest_ecc[1]; - d2 = pread_ecc[2] ^ ptest_ecc[2]; - - if ((d0 | d1 | d2) == 0) - return 0; - - if( ((d0 ^ (d0 >> 1)) & 0x55) == 0x55 && - ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 && - ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) - { - // Single bit (recoverable) error in data - - u8 b; - u8 bit; - - bit = b = 0; - - if(d1 & 0x80) b |= 0x80; - if(d1 & 0x20) b |= 0x40; - if(d1 & 0x08) b |= 0x20; - if(d1 & 0x02) b |= 0x10; - if(d0 & 0x80) b |= 0x08; - if(d0 & 0x20) b |= 0x04; - if(d0 & 0x08) b |= 0x02; - if(d0 & 0x02) b |= 0x01; - - if(d2 & 0x80) bit |= 0x04; - if(d2 & 0x20) bit |= 0x02; - if(d2 & 0x08) bit |= 0x01; - - if (b >= errtop) return -1; - - p[b] ^= (1 << bit); - - return 1; - } - - if ((bits_tbl[d0] + bits_tbl[d1] + bits_tbl[d2]) == 1) { - // error in ecc, no action need - return 1; - } - - // Unrecoverable error - return -1; -} - -/** - * perform ECC error correct - * - * \param[in|out] data input data to be corrected - * \param[in] data_len length of data in byte - * \param[in] read_ecc ECC read from storage - * \param[in] test_ecc ECC calculated from data - * - * \return: 0 -- no error - * -1 -- can not be corrected - * >0 -- how many bits corrected - */ - -int uffs_EccCorrect(void *data, int data_len, - void *read_ecc, const void *test_ecc) -{ - u8 *p_data = (u8 *)data; - u8 *p_read_ecc = (u8 *)read_ecc; - u8 *p_test_ecc = (u8 *)test_ecc; - int total = 0, ret, len; - - if (data == NULL || read_ecc == NULL || test_ecc == NULL) - return -1; - - while (data_len > 0) { - len = (data_len > 256 ? 256 : data_len); - ret = uffs_EccCorrectChunk256(p_data, p_read_ecc, p_test_ecc, len); - if (ret < 0) { - total = ret; - break; - } - else - total += ret; - - p_data += len; - p_read_ecc += 3; - p_test_ecc += 3; - data_len -= len; - } - - return total; - -} - -/** - * generate 12 bit ecc for 8 bytes data. - * (use 0xFF padding if the data length is less then 8 bytes) - * - * \param[in] data input data - * \param[in] data_len length of data in byte - * - * \return 12 bits ECC data (lower 12 bits). - */ -u16 uffs_EccMake8(void *data, int data_len) -{ - u8 *p = (u8 *)data; - u8 b, col_parity = 0, line_parity = 0, line_parity_prime = 0; - u8 i; - u16 ecc = 0; - - - data_len = (data_len > 8 ? 8 : data_len); - - for (i = 0; i < data_len; i++) { - b = column_parity_tbl[*p++]; - col_parity ^= b; - if (b & 0x01) { // odd number of bits in the byte - line_parity ^= i; - line_parity_prime ^= ~i; - } - } - - // ECC layout: - // row: (1) | (1) | P32 | P32' | P16 | P16' | P8 | P8' - // column: P4 | P4' | P2 | P2' | P1 | P1' | (1) | (1) - // 12-bit ecc: P32 | P32' | P16 | P16' | P8 | P8' | P4 | P4' | P2 | P2' | P1 | P1' | - ecc = (~( - line_parity_tbl[line_parity & 0xf] | - line_parity_prime_tbl[line_parity_prime & 0xf] - )) << 6; - ecc |= (((~col_parity) >> 2) & 0x3f); - - return ecc & 0xfff; -} - -/** - * correct 8 bytes data from 12 bits ECC - * - * \param[in|out] data input data - * \param[in] read_ecc ecc read from storage - * \param[in] test_ecc ecc calculated from data - * \param[in] errtop top position of error. - * - * \return: 0 -- no error - * -1 -- can not be corrected - * >0 -- how many bits corrected - */ -int uffs_EccCorrect8(void *data, u16 read_ecc, u16 test_ecc, int errtop) -{ - u8 d0, d1; /* deltas */ - u8 *p = (u8 *)data; - - read_ecc &= 0xfff; - test_ecc &= 0xfff; - - d0 = (read_ecc >> 6) ^ (test_ecc >> 6); - d1 = (read_ecc & 0x3f) ^ (test_ecc & 0x3f); - - if ((d0 | d1) == 0) - return 0; - - if( ((d0 ^ (d0 >> 1)) & 0x15) == 0x15 && - ((d1 ^ (d1 >> 1)) & 0x15) == 0x15) - { - // Single bit (recoverable) error in data - - u8 b; - u8 bit; - - bit = b = 0; - - if(d0 & 0x20) b |= 0x04; - if(d0 & 0x08) b |= 0x02; - if(d0 & 0x02) b |= 0x01; - - if(d1 & 0x20) bit |= 0x04; - if(d1 & 0x08) bit |= 0x02; - if(d1 & 0x02) bit |= 0x01; - - if (b >= (u8)errtop) return -1; - if (bit >= 8) return -1; - - p[b] ^= (1 << bit); - - return 1; - } - - if ((bits_tbl[d0] + bits_tbl[d1]) == 1) { - // error in ecc, no action need - return 1; - } - - // Unrecoverable error - return -1; -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c b/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c deleted file mode 100644 index bbc1bb880d..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fd.c - * \brief POSIX like, hight level file operations - * \author Ricky Zheng, created 8th Jun, 2005 - */ - -#include -#include "uffs_config.h" -#include "uffs/uffs_fs.h" -#include "uffs/uffs_fd.h" -#include "uffs/uffs_utils.h" -#include "uffs/uffs_version.h" -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_find.h" - -#define PFX "fd : " - -/** - * \brief POSIX DIR - */ -struct uffs_dirSt { - struct uffs_ObjectSt *obj; /* dir object */ - struct uffs_FindInfoSt f; /* find info */ - struct uffs_ObjectInfoSt info; /* object info */ - struct uffs_dirent dirent; /* dir entry */ -}; - - -#define FD_OFFSET 3 //!< just make file handler more like POSIX (0, 1, 2 for stdin/stdout/stderr) - -#define OBJ2FD(obj) \ - ( \ - ( \ - uffs_PoolGetIndex(uffs_GetObjectPool(), obj) | \ - (_fd_signature << FD_SIGNATURE_SHIFT) \ - ) \ - + FD_OFFSET \ - ) - -/** - * check #fd signature, convert #fd to #obj - * if success, hold global file system lock, otherwise return with #ret - */ -#define CHK_OBJ_LOCK(fd, obj, ret) \ - do { \ - uffs_GlobalFsLockLock(); \ - fd -= FD_OFFSET; \ - if ( (fd >> FD_SIGNATURE_SHIFT) != _fd_signature ) { \ - uffs_set_error(-UEBADF); \ - uffs_Perror(UFFS_MSG_NOISY, "invalid fd: %d (sig: %d, expect: %d)", \ - fd + FD_OFFSET, fd >> FD_SIGNATURE_SHIFT, _fd_signature); \ - uffs_GlobalFsLockUnlock(); \ - return (ret); \ - } \ - fd = fd & ((1 << FD_SIGNATURE_SHIFT) - 1); \ - obj = (uffs_Object *)uffs_PoolGetBufByIndex(uffs_GetObjectPool(), fd); \ - if ((obj) == NULL || \ - uffs_PoolVerify(uffs_GetObjectPool(), (obj)) == U_FALSE || \ - uffs_PoolCheckFreeList(uffs_GetObjectPool(), (obj)) == U_TRUE) { \ - uffs_set_error(-UEBADF); \ - uffs_Perror(UFFS_MSG_NOISY, "invalid obj"); \ - uffs_GlobalFsLockUnlock(); \ - return (ret); \ - } \ - } while(0) - -/** - * check #dirp signature, - * if success, hold global file system lock, - * otherwise return with #ret - */ -#define CHK_DIR_LOCK(dirp, ret) \ - do { \ - uffs_GlobalFsLockLock(); \ - if ((dirp) == NULL || \ - uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \ - uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \ - uffs_set_error(-UEBADF); \ - uffs_Perror(UFFS_MSG_NOISY, "invalid dirp"); \ - uffs_GlobalFsLockUnlock(); \ - return (ret); \ - } \ - } while(0) - -/** - * check #dirp signature, - * if success, hold global file system lock, - * otherwise return void - */ -#define CHK_DIR_VOID_LOCK(dirp) \ - do { \ - uffs_GlobalFsLockLock(); \ - if ((dirp) == NULL || \ - uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \ - uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \ - uffs_set_error(-UEBADF); \ - uffs_Perror(UFFS_MSG_NOISY, "invalid dirp"); \ - uffs_GlobalFsLockUnlock(); \ - return; \ - } \ - } while(0) - - -static int _dir_pool_data[sizeof(uffs_DIR) * MAX_DIR_HANDLE / sizeof(int)]; -static uffs_Pool _dir_pool; -static int _uffs_errno = 0; - - -// -// What is fd signature ? fd signature is for detecting file system get formated by other party. -// A thread open a file, read()...sleep()...write()...sleep()... -// B thread format UFFS partition, increase fd signature. -// A thread ...sleep()...read() --> Opps, fd signature changed ! read() return error(expected). -// -#define MAX_FD_SIGNATURE_ROUND (100) -static int _fd_signature = 0; - -// -// only get called when formating UFFS partition -// -void uffs_FdSignatureIncrease(void) -{ - if (_fd_signature++ > MAX_FD_SIGNATURE_ROUND) - _fd_signature = 0; -} - -/** - * initialise uffs_DIR buffers, called by UFFS internal - */ -URET uffs_DirEntryBufInit(void) -{ - return uffs_PoolInit(&_dir_pool, _dir_pool_data, - sizeof(_dir_pool_data), - sizeof(uffs_DIR), MAX_DIR_HANDLE); -} - -/** - * Release uffs_DIR buffers, called by UFFS internal - */ -URET uffs_DirEntryBufRelease(void) -{ - return uffs_PoolRelease(&_dir_pool); -} - -/** - * Put all dir entry buf match dev - */ -int uffs_DirEntryBufPutAll(uffs_Device *dev) -{ - int count = 0; - uffs_DIR *dirp = NULL; - - do { - dirp = (uffs_DIR *) uffs_PoolFindNextAllocated(&_dir_pool, dirp); - if (dirp && dirp->obj && dirp->obj->dev && - dirp->obj->dev->dev_num == dev->dev_num) { - uffs_PoolPut(&_dir_pool, dirp); - count++; - } - } while (dirp); - - return count; -} - - -uffs_Pool * uffs_DirEntryBufGetPool(void) -{ - return &_dir_pool; -} - -static uffs_DIR * GetDirEntry(void) -{ - uffs_DIR *dirp = (uffs_DIR *) uffs_PoolGet(&_dir_pool); - - if (dirp) - memset(dirp, 0, sizeof(uffs_DIR)); - - return dirp; -} - -static void PutDirEntry(uffs_DIR *p) -{ - uffs_PoolPut(&_dir_pool, p); -} - - -/** get global errno - */ -int uffs_get_error(void) -{ - return _uffs_errno; -} - -/** set global errno - */ -int uffs_set_error(int err) -{ - return (_uffs_errno = err); -} - -/* POSIX compliant file system APIs */ - -int uffs_open(const char *name, int oflag, ...) -{ - uffs_Object *obj; - int ret = 0; - - uffs_GlobalFsLockLock(); - - obj = uffs_GetObject(); - if (obj == NULL) { - uffs_set_error(-UEMFILE); - ret = -1; - } - else { - if (uffs_OpenObject(obj, name, oflag) == U_FAIL) { - uffs_set_error(-uffs_GetObjectErr(obj)); - uffs_PutObject(obj); - ret = -1; - } - else { - ret = OBJ2FD(obj); - } - } - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_close(int fd) -{ - int ret = 0; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - - uffs_ClearObjectErr(obj); - if (uffs_CloseObject(obj) == U_FAIL) { - uffs_set_error(-uffs_GetObjectErr(obj)); - ret = -1; - } - else { - uffs_PutObject(obj); - ret = 0; - } - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_read(int fd, void *data, int len) -{ - int ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - uffs_ClearObjectErr(obj); - ret = uffs_ReadObject(obj, data, len); - uffs_set_error(-uffs_GetObjectErr(obj)); - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_write(int fd, const void *data, int len) -{ - int ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - uffs_ClearObjectErr(obj); - ret = uffs_WriteObject(obj, data, len); - uffs_set_error(-uffs_GetObjectErr(obj)); - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -long uffs_seek(int fd, long offset, int origin) -{ - int ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - uffs_ClearObjectErr(obj); - ret = uffs_SeekObject(obj, offset, origin); - uffs_set_error(-uffs_GetObjectErr(obj)); - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -long uffs_tell(int fd) -{ - long ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - uffs_ClearObjectErr(obj); - ret = (long) uffs_GetCurOffset(obj); - uffs_set_error(-uffs_GetObjectErr(obj)); - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_eof(int fd) -{ - int ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - uffs_ClearObjectErr(obj); - ret = uffs_EndOfFile(obj); - uffs_set_error(-uffs_GetObjectErr(obj)); - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_flush(int fd) -{ - int ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - uffs_ClearObjectErr(obj); - ret = (uffs_FlushObject(obj) == U_SUCC) ? 0 : -1; - uffs_set_error(-uffs_GetObjectErr(obj)); - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_rename(const char *old_name, const char *new_name) -{ - int err = 0; - int ret = 0; - - uffs_GlobalFsLockLock(); - ret = (uffs_RenameObject(old_name, new_name, &err) == U_SUCC) ? 0 : -1; - uffs_set_error(-err); - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_remove(const char *name) -{ - int err = 0; - int ret = 0; - struct uffs_stat st; - - if (uffs_stat(name, &st) < 0) { - err = UENOENT; - ret = -1; - } - else if (st.st_mode & US_IFDIR) { - err = UEISDIR; - ret = -1; - } - else { - uffs_GlobalFsLockLock(); - if (uffs_DeleteObject(name, &err) == U_SUCC) { - ret = 0; - } - else { - ret = -1; - } - uffs_GlobalFsLockUnlock(); - } - - uffs_set_error(-err); - return ret; -} - -int uffs_ftruncate(int fd, long remain) -{ - int ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - uffs_ClearObjectErr(obj); - ret = (uffs_TruncateObject(obj, remain) == U_SUCC) ? 0 : -1; - uffs_set_error(-uffs_GetObjectErr(obj)); - uffs_GlobalFsLockUnlock(); - - return ret; -} - -static int do_stat(uffs_Object *obj, struct uffs_stat *buf) -{ - uffs_ObjectInfo info; - int ret = 0; - int err = 0; - - if (uffs_GetObjectInfo(obj, &info, &err) == U_FAIL) { - ret = -1; - } - else { - buf->st_dev = obj->dev->dev_num; - buf->st_ino = info.serial; - buf->st_nlink = 0; - buf->st_uid = 0; - buf->st_gid = 0; - buf->st_rdev = 0; - buf->st_size = info.len; - buf->st_blksize = obj->dev->com.pg_data_size; - buf->st_blocks = 0; - buf->st_atime = info.info.last_modify; - buf->st_mtime = info.info.last_modify; - buf->st_ctime = info.info.create_time; - buf->st_mode = (info.info.attr & FILE_ATTR_DIR ? US_IFDIR : US_IFREG); - if (info.info.attr & FILE_ATTR_WRITE) - buf->st_mode |= US_IRWXU; - } - - uffs_set_error(-err); - return ret; -} - -int uffs_stat(const char *name, struct uffs_stat *buf) -{ - uffs_Object *obj; - int ret = 0; - int err = 0; - URET result; - - uffs_GlobalFsLockLock(); - - obj = uffs_GetObject(); - if (obj) { - if (*name && name[strlen(name) - 1] == '/') { - result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR); - } - else { - if ((result = uffs_OpenObject(obj, name, UO_RDONLY)) != U_SUCC) // try file - result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR); // then try dir - } - if (result == U_SUCC) { - ret = do_stat(obj, buf); - uffs_CloseObject(obj); - } - else { - err = uffs_GetObjectErr(obj); - ret = -1; - } - uffs_PutObject(obj); - } - else { - err = UENOMEM; - ret = -1; - } - - uffs_set_error(-err); - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_lstat(const char *name, struct uffs_stat *buf) -{ - return uffs_stat(name, buf); -} - -int uffs_fstat(int fd, struct uffs_stat *buf) -{ - int ret; - uffs_Object *obj; - - CHK_OBJ_LOCK(fd, obj, -1); - - ret = do_stat(obj, buf); - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_closedir(uffs_DIR *dirp) -{ - CHK_DIR_LOCK(dirp, -1); - - uffs_FindObjectClose(&dirp->f); - if (dirp->obj) { - uffs_CloseObject(dirp->obj); - uffs_PutObject(dirp->obj); - } - PutDirEntry(dirp); - uffs_GlobalFsLockUnlock(); - - return 0; -} - -uffs_DIR * uffs_opendir(const char *path) -{ - int err = 0; - uffs_DIR *ret = NULL; - uffs_DIR *dirp; - - uffs_GlobalFsLockLock(); - - dirp = GetDirEntry(); - - if (dirp) { - dirp->obj = uffs_GetObject(); - if (dirp->obj) { - if (uffs_OpenObject(dirp->obj, path, UO_RDONLY | UO_DIR) == U_SUCC) { - if (uffs_FindObjectOpen(&dirp->f, dirp->obj) == U_SUCC) { - ret = dirp; - goto ext; - } - else { - uffs_CloseObject(dirp->obj); - } - } - else { - err = uffs_GetObjectErr(dirp->obj); - } - uffs_PutObject(dirp->obj); - dirp->obj = NULL; - } - else { - err = UEMFILE; - } - PutDirEntry(dirp); - } - else { - err = UEMFILE; - } -ext: - uffs_set_error(-err); - uffs_GlobalFsLockUnlock(); - - return ret; -} - -struct uffs_dirent * uffs_readdir(uffs_DIR *dirp) -{ - struct uffs_dirent *ent = NULL; - - CHK_DIR_LOCK(dirp, NULL); - - if (uffs_FindObjectNext(&dirp->info, &dirp->f) == U_SUCC) { - ent = &dirp->dirent; - ent->d_ino = dirp->info.serial; - ent->d_namelen = dirp->info.info.name_len < (sizeof(ent->d_name) - 1) ? dirp->info.info.name_len : (sizeof(ent->d_name) - 1); - memcpy(ent->d_name, dirp->info.info.name, ent->d_namelen); - ent->d_name[ent->d_namelen] = '\0'; - ent->d_off = dirp->f.pos; - ent->d_reclen = sizeof(struct uffs_dirent); - ent->d_type = dirp->info.info.attr; - } - uffs_GlobalFsLockUnlock(); - - return ent; -} - -void uffs_rewinddir(uffs_DIR *dirp) -{ - CHK_DIR_VOID_LOCK(dirp); - - uffs_FindObjectRewind(&dirp->f); - - uffs_GlobalFsLockUnlock(); -} - - -int uffs_mkdir(const char *name, ...) -{ - uffs_Object *obj; - int ret = 0; - int err = 0; - - uffs_GlobalFsLockLock(); - - obj = uffs_GetObject(); - if (obj) { - if (uffs_CreateObject(obj, name, UO_CREATE|UO_DIR) != U_SUCC) { - err = obj->err; - ret = -1; - } - else { - uffs_CloseObject(obj); - ret = 0; - } - uffs_PutObject(obj); - } - else { - err = UEMFILE; - ret = -1; - } - - uffs_set_error(-err); - uffs_GlobalFsLockUnlock(); - - return ret; -} - -int uffs_rmdir(const char *name) -{ - int err = 0; - int ret = 0; - struct uffs_stat st; - - if (uffs_stat(name, &st) < 0) { - err = UENOENT; - ret = -1; - } - else if ((st.st_mode & US_IFDIR) == 0) { - err = UENOTDIR; - ret = -1; - } - else { - uffs_GlobalFsLockLock(); - if (uffs_DeleteObject(name, &err) == U_SUCC) { - ret = 0; - } - else { - ret = -1; - } - uffs_GlobalFsLockUnlock(); - } - uffs_set_error(-err); - return ret; -} - -int uffs_version(void) -{ - return uffs_GetVersion(); -} - -int uffs_format(const char *mount_point) -{ - uffs_Device *dev = NULL; - URET ret = U_FAIL; - - dev = uffs_GetDeviceFromMountPoint(mount_point); - if (dev) { - uffs_GlobalFsLockLock(); - ret = uffs_FormatDevice(dev, U_TRUE); - uffs_GlobalFsLockUnlock(); - } - - return ret == U_SUCC ? 0 : -1; -} - -long uffs_space_total(const char *mount_point) -{ - uffs_Device *dev = NULL; - long ret = -1L; - - dev = uffs_GetDeviceFromMountPoint(mount_point); - if (dev) { - uffs_GlobalFsLockLock(); - ret = (long) uffs_GetDeviceTotal(dev); - uffs_GlobalFsLockUnlock(); - } - - return ret; -} - -long uffs_space_used(const char *mount_point) -{ - uffs_Device *dev = NULL; - long ret = -1L; - - dev = uffs_GetDeviceFromMountPoint(mount_point); - if (dev) { - uffs_GlobalFsLockLock(); - ret = (long) uffs_GetDeviceUsed(dev); - uffs_GlobalFsLockUnlock(); - } - - return ret; -} - -long uffs_space_free(const char *mount_point) -{ - uffs_Device *dev = NULL; - long ret = -1L; - - dev = uffs_GetDeviceFromMountPoint(mount_point); - if (dev) { - uffs_GlobalFsLockLock(); - ret = (long) uffs_GetDeviceFree(dev); - uffs_GlobalFsLockUnlock(); - } - - return ret; -} - - -void uffs_flush_all(const char *mount_point) -{ - uffs_Device *dev = NULL; - - dev = uffs_GetDeviceFromMountPoint(mount_point); - if (dev) { - uffs_GlobalFsLockLock(); - uffs_BufFlushAll(dev); - uffs_PutDevice(dev); - uffs_GlobalFsLockUnlock(); - } -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_find.c b/components/dfs/filesystems/uffs/src/uffs/uffs_find.c deleted file mode 100644 index e79da042f7..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_find.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_find.c - * \brief find objects under dir - * \author Ricky Zheng, created 13th July, 2009 - */ - -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_find.h" - -#define TPOOL(dev) &((dev)->mem.tree_pool) - -static void ResetFindInfo(uffs_FindInfo *f) -{ - f->hash = 0; - f->work = NULL; - f->step = 0; - f->pos = 0; -} - -static URET _LoadObjectInfo(uffs_Device *dev, - TreeNode *node, - uffs_ObjectInfo *info, - int type, - int *err) -{ - uffs_Buf *buf; - - buf = uffs_BufGetEx(dev, (u8)type, node, 0, 0); - - if (buf == NULL) { - if (err) - *err = UENOMEM; - return U_FAIL; - } - - memcpy(&(info->info), buf->data, sizeof(uffs_FileInfo)); - - if (type == UFFS_TYPE_DIR) { - info->len = 0; - info->serial = node->u.dir.serial; - } - else { - info->len = node->u.file.len; - info->serial = node->u.file.serial; - } - - uffs_BufPut(dev, buf); - - return U_SUCC; -} - -/** - * get object information - * - * \param[in] obj the object to be revealed - * \param[out] info object information will be loaded to info - * \param[out] err return error code if failed - * - * \return U_SUCC or U_FAIL - * - * \node the obj should be openned before call this function. - */ -URET uffs_GetObjectInfo(uffs_Object *obj, uffs_ObjectInfo *info, int *err) -{ - uffs_Device *dev = obj->dev; - URET ret = U_FAIL; - - uffs_DeviceLock(dev); - - if (obj && dev && info) { - if (obj->parent == PARENT_OF_ROOT) { - // this is ROOT. UFFS does not physically has root, just fake it ... - memset(info, 0, sizeof(uffs_ObjectInfo)); - info->serial = obj->serial; - info->info.attr |= (FILE_ATTR_DIR | FILE_ATTR_WRITE); - if (err) - *err = UENOERR; - ret = U_SUCC; - } - else - ret = _LoadObjectInfo(dev, obj->node, info, obj->type, err); - } - else { - if (err) - *err = UEINVAL; - } - - uffs_DeviceUnLock(dev); - - return ret; -} - - -/** - * Open a FindInfo for finding objects under dir - * - * \param[out] f uffs_FindInfo structure - * \param[in] dir an openned dir object (openned by uffs_OpenObject() ). - * - * \return U_SUCC if success, U_FAIL if invalid param or the dir - * is not been openned. - */ -URET uffs_FindObjectOpen(uffs_FindInfo *f, uffs_Object *dir) -{ - if (f == NULL || dir == NULL || - dir->dev == NULL || dir->open_succ != U_TRUE) - return U_FAIL; - - f->dev = dir->dev; - f->serial = dir->serial; - ResetFindInfo(f); - - return U_SUCC; -} - -/** - * Open a FindInfo for finding objects under dir - * - * \param[out] f uffs_FindInfo structure - * \param[in] dev uffs device - * \param[in] dir serial number of the dir to be searched - * - * \return U_SUCC if success, U_FAIL if invalid param or the dir - * serial number is not valid. - */ -URET uffs_FindObjectOpenEx(uffs_FindInfo *f, uffs_Device *dev, int dir) -{ - TreeNode *node; - - if (f == NULL || dev == NULL) - return U_FAIL; - - node = uffs_TreeFindDirNode(dev, dir); - - if (node == NULL) - return U_FAIL; - - f->serial = dir; - f->dev = dev; - ResetFindInfo(f); - - return U_SUCC; -} - - -static URET do_FindObject(uffs_FindInfo *f, uffs_ObjectInfo *info, u16 x) -{ - URET ret = U_SUCC; - TreeNode *node; - uffs_Device *dev = f->dev; - - if (f->step == 0) { //!< working on dirs - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.dir.parent == f->serial) { - f->work = node; - f->pos++; - if (info) - ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR, NULL); - goto ext; - } - x = node->hash_next; - } - - f->hash++; //come to next hash entry - - for (; f->hash < DIR_NODE_ENTRY_LEN; f->hash++) { - x = dev->tree.dir_entry[f->hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.dir.parent == f->serial) { - f->work = node; - f->pos++; - if (info) - ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR, NULL); - goto ext; - } - x = node->hash_next; - } - } - - //no subdirs, then lookup files .. - f->step++; - f->hash = 0; - x = dev->tree.file_entry[f->hash]; - } - - if (f->step == 1) { - - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.file.parent == f->serial) { - f->work = node; - f->pos++; - if (info) - ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE, NULL); - goto ext; - } - x = node->hash_next; - } - - f->hash++; //come to next hash entry - - for (; f->hash < FILE_NODE_ENTRY_LEN; f->hash++) { - x = dev->tree.file_entry[f->hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.file.parent == f->serial) { - f->work = node; - f->pos++; - if (info) - ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE, NULL); - goto ext; - } - x = node->hash_next; - } - } - - //no any files, stopped. - f->step++; - } - - ret = U_FAIL; -ext: - - return ret; - -} - - -/** - * Find the first object - * - * \param[out] info the object information will be filled to info. - * if info is NULL, then skip this object. - * \param[in] f uffs_FindInfo structure, openned by uffs_FindObjectOpen(). - * - * \return U_SUCC if an object is found, U_FAIL if no object is found. - */ -URET uffs_FindObjectFirst(uffs_ObjectInfo * info, uffs_FindInfo * f) -{ - uffs_Device *dev = f->dev; - URET ret = U_SUCC; - - uffs_DeviceLock(dev); - ResetFindInfo(f); - ret = do_FindObject(f, info, dev->tree.dir_entry[0]); - uffs_DeviceUnLock(dev); - - return ret; -} - -/** - * Find the next object. - * - * \param[out] info the object information will be filled to info. - * if info is NULL, then skip this object. - * \param[in] f uffs_FindInfo structure, openned by uffs_FindObjectOpen(). - * - * \return U_SUCC if an object is found, U_FAIL if no object is found. - * - * \note uffs_FindObjectFirst() should be called before uffs_FindObjectNext(). - */ -URET uffs_FindObjectNext(uffs_ObjectInfo *info, uffs_FindInfo * f) -{ - uffs_Device *dev = f->dev; - URET ret = U_SUCC; - - if (dev == NULL || f->step > 1) - return U_FAIL; - - if (f->work == NULL) - return uffs_FindObjectFirst(info, f); - - uffs_DeviceLock(dev); - ret = do_FindObject(f, info, f->work->hash_next); - uffs_DeviceUnLock(dev); - - return ret; -} - -/** - * Rewind a find object process. - * - * \note After rewind, you can call uffs_FindObjectFirst() to - * start find object process. - */ -URET uffs_FindObjectRewind(uffs_FindInfo *f) -{ - if (f == NULL) - return U_FAIL; - - ResetFindInfo(f); - - return U_SUCC; -} - -/** - * Close Find Object. - * - * \param[in] f uffs_FindInfo structure, openned by uffs_FindObjectOpen(). - * - * \return U_SUCC if success, U_FAIL if invalid param. - */ -URET uffs_FindObjectClose(uffs_FindInfo * f) -{ - if (f == NULL) - return U_FAIL; - - f->dev = NULL; - ResetFindInfo(f); - - return U_SUCC; -} - -/** - * Count objects - * - * \param[in] f uffs_FindInfo structure, openned by uffs_FindObjectOpen(). - * - * \return object counts - * \note after call this function, you need to call - * uffs_FindObjectRewind() to start finding process. - */ -int uffs_FindObjectCount(uffs_FindInfo *f) -{ - if (uffs_FindObjectFirst(NULL, f) == U_SUCC) { - while (uffs_FindObjectNext(NULL, f) == U_SUCC) { }; - } - return f->pos; -} - -/** - * Return current finding position - * - * \param[in] f uffs_FindInfo structure, openned by uffs_FindObjectOpen(). - * - * \return current finding position - */ -int uffs_FindObjectTell(uffs_FindInfo *f) -{ - return f->pos; -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_flash.c b/components/dfs/filesystems/uffs/src/uffs/uffs_flash.c deleted file mode 100644 index be4f4246dc..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_flash.c +++ /dev/null @@ -1,1034 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_flash.c - * \brief UFFS flash interface - * \author Ricky Zheng, created 17th July, 2009 - */ -#include "uffs_config.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_ecc.h" -#include "uffs/uffs_flash.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_badblock.h" -#include "uffs/uffs_crc.h" -#include - -#define PFX "flsh: " - -#define SPOOL(dev) &((dev)->mem.spare_pool) -#define HEADER(buf) ((struct uffs_MiniHeaderSt *)(buf)->header) - -#define ECC_SIZE(dev) ((dev)->attr->ecc_size) -#define NOMINAL_ECC_SIZE(dev) (3 * ((((dev)->attr->page_data_size - 1) / 256) + 1)) - -#define TAG_STORE_SIZE (sizeof(struct uffs_TagStoreSt)) - -#define SEAL_BYTE(dev, spare) spare[(dev)->mem.spare_data_size - 1] // seal byte is the last byte of spare data - -#if defined(CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME) -/** Linux MTD spare layout for 512 and 2K page size */ -static const u8 MTD512_LAYOUT_ECC[] = {0, 4, 6, 2, 0xFF, 0}; -static const u8 MTD512_LAYOUT_DATA[] = {8, 8, 0xFF, 0}; -static const u8 MTD2K_LAYOUT_ECC[] = {40, 24, 0xFF, 0}; -static const u8 MTD2K_LAYOUT_DATA[] = {2, 38, 0xFF, 0}; -#endif - -static void TagMakeEcc(struct uffs_TagStoreSt *ts) -{ - ts->tag_ecc = 0xFFF; - ts->tag_ecc = uffs_EccMake8(ts, sizeof(struct uffs_TagStoreSt)); -} - -static int TagEccCorrect(struct uffs_TagStoreSt *ts) -{ - u16 ecc_store, ecc_read; - int ret; - - ecc_store = ts->tag_ecc; - ts->tag_ecc = 0xFFF; - ecc_read = uffs_EccMake8(ts, sizeof(struct uffs_TagStoreSt)); - ret = uffs_EccCorrect8(ts, ecc_read, ecc_store, sizeof(struct uffs_TagStoreSt)); - ts->tag_ecc = ecc_store; // restore tag ecc - - return ret; - -} - -/** setup UFFS spare data & ecc layout */ -static void InitSpareLayout(uffs_Device *dev) -{ - u8 s; // status byte offset - u8 *p; - - s = dev->attr->block_status_offs; - - if (s < TAG_STORE_SIZE) { /* status byte is within 0 ~ TAG_STORE_SIZE-1 */ - - /* spare data layout */ - p = dev->attr->_uffs_data_layout; - if (s > 0) { - *p++ = 0; - *p++ = s; - } - *p++ = s + 1; - *p++ = TAG_STORE_SIZE - s; - *p++ = 0xFF; - *p++ = 0; - - /* spare ecc layout */ - p = dev->attr->_uffs_ecc_layout; - if (dev->attr->ecc_opt != UFFS_ECC_NONE) { - *p++ = TAG_STORE_SIZE + 1; - *p++ = ECC_SIZE(dev); - } - *p++ = 0xFF; - *p++ = 0; - } - else { /* status byte > TAG_STORE_SIZE-1 */ - - /* spare data layout */ - p = dev->attr->_uffs_data_layout; - *p++ = 0; - *p++ = TAG_STORE_SIZE; - *p++ = 0xFF; - *p++ = 0; - - /* spare ecc layout */ - p = dev->attr->_uffs_ecc_layout; - if (dev->attr->ecc_opt != UFFS_ECC_NONE) { - if (s < TAG_STORE_SIZE + ECC_SIZE(dev)) { - if (s > TAG_STORE_SIZE) { - *p++ = TAG_STORE_SIZE; - *p++ = s - TAG_STORE_SIZE; - } - *p++ = s + 1; - *p++ = TAG_STORE_SIZE + ECC_SIZE(dev) - s; - } - else { - *p++ = TAG_STORE_SIZE; - *p++ = ECC_SIZE(dev); - } - } - *p++ = 0xFF; - *p++ = 0; - } - - dev->attr->data_layout = dev->attr->_uffs_data_layout; - dev->attr->ecc_layout = dev->attr->_uffs_ecc_layout; -} - -static int CalculateSpareDataSize(uffs_Device *dev) -{ - const u8 *p; - int ecc_last = 0, tag_last = 0; - int ecc_size, tag_size; - int n; - - ecc_size = (dev->attr->ecc_opt == UFFS_ECC_NONE ? 0 : ECC_SIZE(dev)); - - p = dev->attr->ecc_layout; - if (p) { - while (*p != 0xFF && ecc_size > 0) { - n = (p[1] > ecc_size ? ecc_size : p[1]); - ecc_last = p[0] + n; - ecc_size -= n; - p += 2; - } - } - - tag_size = TAG_STORE_SIZE; - p = dev->attr->data_layout; - if (p) { - while (*p != 0xFF && tag_size > 0) { - n = (p[1] > tag_size ? tag_size : p[1]); - tag_last = p[0] + n; - tag_size -= n; - p += 2; - } - } - - n = (ecc_last > tag_last ? ecc_last : tag_last); - n = (n > dev->attr->block_status_offs + 1 ? - n : dev->attr->block_status_offs + 1); - - return n + 1; // plus one seal byte. -} - - -/** - * Initialize UFFS flash interface - */ -URET uffs_FlashInterfaceInit(uffs_Device *dev) -{ - URET ret = U_FAIL; - struct uffs_StorageAttrSt *attr = dev->attr; - uffs_Pool *pool = SPOOL(dev); - - if (dev->mem.spare_pool_size == 0) { - if (dev->mem.malloc) { - dev->mem.spare_pool_buf = dev->mem.malloc(dev, UFFS_SPARE_BUFFER_SIZE); - if (dev->mem.spare_pool_buf) - dev->mem.spare_pool_size = UFFS_SPARE_BUFFER_SIZE; - } - } - - if (UFFS_SPARE_BUFFER_SIZE > dev->mem.spare_pool_size) { - uffs_Perror(UFFS_MSG_DEAD, - "Spare buffer require %d but only %d available.", - UFFS_SPARE_BUFFER_SIZE, dev->mem.spare_pool_size); - memset(pool, 0, sizeof(uffs_Pool)); - goto ext; - } - - uffs_Perror(UFFS_MSG_NOISY, - "alloc spare buffers %d bytes.", - UFFS_SPARE_BUFFER_SIZE); - uffs_PoolInit(pool, dev->mem.spare_pool_buf, - dev->mem.spare_pool_size, - UFFS_MAX_SPARE_SIZE, MAX_SPARE_BUFFERS); - - // init flash driver - if (dev->ops->InitFlash) { - if (dev->ops->InitFlash(dev) < 0) - goto ext; - } - - if (dev->ops->WritePage == NULL && dev->ops->WritePageWithLayout == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Flash driver must provide 'WritePage' or 'WritePageWithLayout' function!"); - goto ext; - } - - if (dev->ops->ReadPage == NULL && dev->ops->ReadPageWithLayout == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Flash driver must provide 'ReadPage' or 'ReadPageWithLayout' function!"); - goto ext; - } - - if (dev->attr->layout_opt == UFFS_LAYOUT_UFFS) { - /* sanity check */ - - if (dev->attr->ecc_size == 0 && dev->attr->ecc_opt != UFFS_ECC_NONE) { - dev->attr->ecc_size = NOMINAL_ECC_SIZE(dev); - } - - uffs_Perror(UFFS_MSG_NORMAL, "ECC size %d", dev->attr->ecc_size); - - if ((dev->attr->data_layout && !dev->attr->ecc_layout) || - (!dev->attr->data_layout && dev->attr->ecc_layout)) { - uffs_Perror(UFFS_MSG_SERIOUS, - "Please setup data_layout and ecc_layout, " - "or leave them all NULL !"); - goto ext; - } - - if (!attr->data_layout && !attr->ecc_layout) { -#if defined(CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME) - switch(attr->page_data_size) { - case 512: - attr->ecc_layout = MTD512_LAYOUT_ECC; - attr->data_layout = MTD512_LAYOUT_DATA; - break; - case 2048: - attr->ecc_layout = MTD2K_LAYOUT_ECC; - attr->data_layout = MTD2K_LAYOUT_DATA; - break; - default: - InitSpareLayout(dev); - break; - } -#else - InitSpareLayout(dev); -#endif - } - } - else if (dev->attr->layout_opt == UFFS_LAYOUT_FLASH) { - if (dev->ops->WritePageWithLayout == NULL || dev->ops->ReadPageWithLayout == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "When using UFFS_LAYOUT_FLASH option, " - "flash driver must provide 'WritePageWithLayout' and 'ReadPageWithLayout' function!"); - goto ext; - } - } - else { - uffs_Perror(UFFS_MSG_SERIOUS, "Invalid layout_opt: %d", dev->attr->layout_opt); - goto ext; - } - - if (dev->ops->EraseBlock == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Flash driver MUST implement 'EraseBlock()' function !"); - goto ext; - } - - dev->mem.spare_data_size = CalculateSpareDataSize(dev); - uffs_Perror(UFFS_MSG_NORMAL, "UFFS consume spare data size %d", dev->mem.spare_data_size); - - if (dev->mem.spare_data_size > dev->attr->spare_size) { - uffs_Perror(UFFS_MSG_SERIOUS, "NAND spare(%dB) can't hold UFFS spare data(%dB) !", - dev->attr->spare_size, dev->mem.spare_data_size); - goto ext; - } - - ret = U_SUCC; -ext: - return ret; -} - -/** - * Release UFFS flash interface - */ -URET uffs_FlashInterfaceRelease(uffs_Device *dev) -{ - uffs_Pool *pool; - - pool = SPOOL(dev); - if (pool->mem && dev->mem.free) { - dev->mem.free(dev, pool->mem); - pool->mem = NULL; - dev->mem.spare_pool_size = 0; - } - uffs_PoolRelease(pool); - memset(pool, 0, sizeof(uffs_Pool)); - - // release flash driver - if (dev->ops->ReleaseFlash) { - if (dev->ops->ReleaseFlash(dev) < 0) - return U_FAIL; - } - - return U_SUCC; -} - -/** - * unload spare to tag and ecc. - */ -void uffs_FlashUnloadSpare(uffs_Device *dev, - const u8 *spare, struct uffs_TagStoreSt *ts, u8 *ecc) -{ - u8 *p_tag = (u8 *)ts; - int tag_size = TAG_STORE_SIZE; - int ecc_size = dev->attr->ecc_size; - int n; - const u8 *p; - - // unload ecc - p = dev->attr->ecc_layout; - if (p && ecc) { - while (*p != 0xFF && ecc_size > 0) { - n = (p[1] > ecc_size ? ecc_size : p[1]); - memcpy(ecc, spare + p[0], n); - ecc_size -= n; - ecc += n; - p += 2; - } - } - - // unload tag - if (ts) { - p = dev->attr->data_layout; - while (*p != 0xFF && tag_size > 0) { - n = (p[1] > tag_size ? tag_size : p[1]); - memcpy(p_tag, spare + p[0], n); - tag_size -= n; - p_tag += n; - p += 2; - } - } -} - -/** - * Read tag from page spare - * - * \param[in] dev uffs device - * \param[in] block flash block num - * \param[in] page flash page num - * \param[out] tag tag to be filled - * - * \return #UFFS_FLASH_NO_ERR: success and/or has no flip bits. - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_ECC_FAIL: spare data has flip bits and ecc correct failed. - * #UFFS_FLASH_ECC_OK: spare data has flip bits and corrected by ecc. -*/ -int uffs_FlashReadPageTag(uffs_Device *dev, - int block, int page, uffs_Tags *tag) -{ - uffs_FlashOps *ops = dev->ops; - u8 * spare_buf; - int ret = UFFS_FLASH_UNKNOWN_ERR; - int tmp_ret; - UBOOL is_bad = U_FALSE; - - spare_buf = (u8 *) uffs_PoolGet(SPOOL(dev)); - if (spare_buf == NULL) - goto ext; - - if (ops->ReadPageWithLayout) { - ret = ops->ReadPageWithLayout(dev, block, page, NULL, 0, NULL, tag ? &tag->s : NULL, NULL); - if (tag) - tag->seal_byte = (ret == UFFS_FLASH_NOT_SEALED ? 0xFF : 0); - } - else { - ret = ops->ReadPage(dev, block, page, NULL, 0, NULL, - spare_buf, dev->mem.spare_data_size); - - if (tag) { - tag->seal_byte = SEAL_BYTE(dev, spare_buf); - - if (!UFFS_FLASH_HAVE_ERR(ret)) - uffs_FlashUnloadSpare(dev, spare_buf, &tag->s, NULL); - } - } - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - is_bad = U_TRUE; - - if (UFFS_FLASH_HAVE_ERR(ret)) - goto ext; - - if (tag) { - if (!TAG_IS_SEALED(tag)) // not sealed ? don't try tag ECC correction - goto ext; - - if (!TAG_IS_VALID(tag)) { - if (dev->attr->ecc_opt != UFFS_ECC_NONE) { - /* - * There could be a special case if: - * a) tag is sealed (so we are here), and - * b) s.valid == 1 and this bit is a 'bad' bit, and - * c) after tag ECC (corrected by tag ECC) s.valid == 0. - * - * So we need to try tag ECC (don't treat it as bad block if ECC failed) - */ - - struct uffs_TagStoreSt s; - - memcpy(&s, &tag->s, sizeof(s)); - tmp_ret = TagEccCorrect(&s); - - if (tmp_ret <= 0 || !TAG_IS_VALID(tag)) // can not corrected by ECC. - goto ext; - } - else { - goto ext; - } - } - - // do tag ecc correction - if (dev->attr->ecc_opt != UFFS_ECC_NONE) { - ret = TagEccCorrect(&tag->s); - ret = (ret < 0 ? UFFS_FLASH_ECC_FAIL : - (ret > 0 ? UFFS_FLASH_ECC_OK : UFFS_FLASH_NO_ERR)); - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - is_bad = U_TRUE; - - if (UFFS_FLASH_HAVE_ERR(ret)) - goto ext; - } - } - -ext: - if (is_bad) { - uffs_BadBlockAdd(dev, block); - uffs_Perror(UFFS_MSG_NORMAL, - "A new bad block (%d) is detected.", block); - } - - if (spare_buf) - uffs_PoolPut(SPOOL(dev), spare_buf); - - return ret; -} - -/** - * Read page data to buf (do ECC error correction if needed) - * \param[in] dev uffs device - * \param[in] block flash block num - * \param[in] page flash page num of the block - * \param[out] buf holding the read out data - * \param[in] skip_ecc skip ecc when reading data from flash - * - * \return #UFFS_FLASH_NO_ERR: success and/or has no flip bits. - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_ECC_FAIL: spare data has flip bits and ecc correct failed. - * #UFFS_FLASH_ECC_OK: spare data has flip bits and corrected by ecc. - * #UFFS_FLASH_CRC_ERR: CRC verification failed. - * #UFFS_FLASH_UNKNOWN_ERR: - * - * \note if skip_ecc is U_TRUE, skip CRC as well. - */ -int uffs_FlashReadPage(uffs_Device *dev, int block, int page, uffs_Buf *buf, UBOOL skip_ecc) -{ - uffs_FlashOps *ops = dev->ops; - struct uffs_StorageAttrSt *attr = dev->attr; - int size = dev->com.pg_size; - u8 ecc_buf[UFFS_MAX_ECC_SIZE]; - u8 ecc_store[UFFS_MAX_ECC_SIZE]; - UBOOL is_bad = U_FALSE; -#ifdef CONFIG_ENABLE_PAGE_DATA_CRC - UBOOL crc_ok = U_TRUE; -#endif - u8 * spare; - - int ret = UFFS_FLASH_UNKNOWN_ERR; - - spare = (u8 *) uffs_PoolGet(SPOOL(dev)); - if (spare == NULL) - goto ext; - - if (ops->ReadPageWithLayout) { - if (skip_ecc) - ret = ops->ReadPageWithLayout(dev, block, page, buf->header, size, NULL, NULL, NULL); - else - ret = ops->ReadPageWithLayout(dev, block, page, buf->header, size, ecc_buf, NULL, ecc_store); - } - else { - if (skip_ecc) - ret = ops->ReadPage(dev, block, page, buf->header, size, NULL, NULL, 0); - else - ret = ops->ReadPage(dev, block, page, buf->header, size, ecc_buf, spare, dev->mem.spare_data_size); - } - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - is_bad = U_TRUE; - - if (UFFS_FLASH_HAVE_ERR(ret)) - goto ext; - -#ifdef CONFIG_ENABLE_PAGE_DATA_CRC - if (!skip_ecc) { - crc_ok = (HEADER(buf)->crc == uffs_crc16sum(buf->data, size - sizeof(struct uffs_MiniHeaderSt)) ? U_TRUE : U_FALSE); - - if (crc_ok) - goto ext; // CRC is matched, no need to do ECC correction. - else { - if (dev->attr->ecc_opt == UFFS_ECC_NONE || dev->attr->ecc_opt == UFFS_ECC_HW_AUTO) { - // ECC is not enabled or ecc correction already done, error return immediately, - // otherwise, we try CRC check again after ecc correction. - ret = UFFS_FLASH_CRC_ERR; - goto ext; - } - } - } -#endif - - // make ECC for UFFS_ECC_SOFT - if (attr->ecc_opt == UFFS_ECC_SOFT && !skip_ecc) - uffs_EccMake(buf->header, size, ecc_buf); - - // unload ecc_store if driver doesn't do the layout - if (ops->ReadPageWithLayout == NULL) { - if (!skip_ecc && (attr->ecc_opt == UFFS_ECC_SOFT || attr->ecc_opt == UFFS_ECC_HW)) - uffs_FlashUnloadSpare(dev, spare, NULL, ecc_store); - } - - // check page data ecc - if (!skip_ecc && (dev->attr->ecc_opt == UFFS_ECC_SOFT || dev->attr->ecc_opt == UFFS_ECC_HW)) { - - ret = uffs_EccCorrect(buf->header, size, ecc_store, ecc_buf); - ret = (ret < 0 ? UFFS_FLASH_ECC_FAIL : - (ret > 0 ? UFFS_FLASH_ECC_OK : UFFS_FLASH_NO_ERR)); - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - is_bad = U_TRUE; - - if (UFFS_FLASH_HAVE_ERR(ret)) - goto ext; - } - -#ifdef CONFIG_ENABLE_PAGE_DATA_CRC - if (!skip_ecc && !UFFS_FLASH_HAVE_ERR(ret)) { - // Everything seems ok, do CRC check again. - if (HEADER(buf)->crc == uffs_crc16sum(buf->data, size - sizeof(struct uffs_MiniHeaderSt))) { - ret = UFFS_FLASH_CRC_ERR; - goto ext; - } - } -#endif - -ext: - switch(ret) { - case UFFS_FLASH_IO_ERR: - uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d I/O error", block, page); - break; - case UFFS_FLASH_ECC_FAIL: - uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d ECC failed", block, page); - ret = UFFS_FLASH_BAD_BLK; // treat ECC FAIL as BAD BLOCK - is_bad = U_TRUE; - break; - case UFFS_FLASH_ECC_OK: - uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d bit flip corrected by ECC", block, page); - break; - case UFFS_FLASH_BAD_BLK: - uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d BAD BLOCK found", block, page); - break; - case UFFS_FLASH_UNKNOWN_ERR: - uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d UNKNOWN error!", block, page); - break; - case UFFS_FLASH_CRC_ERR: - uffs_Perror(UFFS_MSG_NORMAL, "Read block %d page %d CRC failed", block, page); - break; - default: - break; - } - - if (is_bad) - uffs_BadBlockAdd(dev, block); - - if (spare) - uffs_PoolPut(SPOOL(dev), spare); - - - return ret; -} - -/** - * make spare from tag and ecc - * - * \param[in] dev uffs dev - * \param[in] ts uffs tag store, NULL if don't pack tag store - * \param[in] ecc ecc of data, NULL if don't pack ecc - * \param[out] spare output buffer - * \note spare buffer size: dev->mem.spare_data_size, - * all unpacked bytes will be inited 0xFF - */ -void uffs_FlashMakeSpare(uffs_Device *dev, - const uffs_TagStore *ts, const u8 *ecc, u8* spare) -{ - u8 *p_ts = (u8 *)ts; - int ts_size = TAG_STORE_SIZE; - int ecc_size = ECC_SIZE(dev); - int n; - const u8 *p; - - if (!uffs_Assert(spare != NULL, "invalid param")) - return; - - memset(spare, 0xFF, dev->mem.spare_data_size); // initialize as 0xFF. - SEAL_BYTE(dev, spare) = 0; // set seal byte = 0. - - // load ecc - p = dev->attr->ecc_layout; - if (p && ecc) { - while (*p != 0xFF && ecc_size > 0) { - n = (p[1] > ecc_size ? ecc_size : p[1]); - memcpy(spare + p[0], ecc, n); - ecc_size -= n; - ecc += n; - p += 2; - } - } - - p = dev->attr->data_layout; - while (*p != 0xFF && ts_size > 0) { - n = (p[1] > ts_size ? ts_size : p[1]); - memcpy(spare + p[0], p_ts, n); - ts_size -= n; - p_ts += n; - p += 2; - } - - uffs_Assert(SEAL_BYTE(dev, spare) == 0, "Make spare fail!"); -} - -/** - * write the whole page, include data and tag - * - * \param[in] dev uffs device - * \param[in] block - * \param[in] page - * \param[in] buf contains data to be wrote - * \param[in] tag tag to be wrote - * - * \return #UFFS_FLASH_NO_ERR: success. - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_BAD_BLK: a new bad block detected. - */ -int uffs_FlashWritePageCombine(uffs_Device *dev, - int block, int page, - uffs_Buf *buf, uffs_Tags *tag) -{ - uffs_FlashOps *ops = dev->ops; - int size = dev->com.pg_size; - u8 ecc_buf[UFFS_MAX_ECC_SIZE]; - u8 *ecc = NULL; - u8 *spare; - struct uffs_MiniHeaderSt *header; - int ret = UFFS_FLASH_UNKNOWN_ERR; - UBOOL is_bad = U_FALSE; - uffs_Buf *verify_buf; -#ifdef CONFIG_PAGE_WRITE_VERIFY - uffs_Tags chk_tag; -#endif - - spare = (u8 *) uffs_PoolGet(SPOOL(dev)); - if (spare == NULL) - goto ext; - - // setup header - header = HEADER(buf); - memset(header, 0xFF, sizeof(struct uffs_MiniHeaderSt)); - header->status = 0; -#ifdef CONFIG_ENABLE_PAGE_DATA_CRC - header->crc = uffs_crc16sum(buf->data, size - sizeof(struct uffs_MiniHeaderSt)); -#endif - - // setup tag - TAG_DIRTY_BIT(tag) = TAG_DIRTY; //!< set dirty bit - TAG_VALID_BIT(tag) = TAG_VALID; //!< set valid bit - SEAL_TAG(tag); //!< seal tag (the real seal byte will be set in uffs_FlashMakeSpare()) - - if (dev->attr->ecc_opt != UFFS_ECC_NONE) - TagMakeEcc(&tag->s); - else - tag->s.tag_ecc = TAG_ECC_DEFAULT; - - if (dev->attr->ecc_opt == UFFS_ECC_SOFT) { - uffs_EccMake(buf->header, size, ecc_buf); - ecc = ecc_buf; - } - else if (dev->attr->ecc_opt == UFFS_ECC_HW) { - ecc = ecc_buf; - } - - if (ops->WritePageWithLayout) { - ret = ops->WritePageWithLayout(dev, block, page, - buf->header, size, ecc, &tag->s); - } - else { - - if (!uffs_Assert(!(dev->attr->layout_opt == UFFS_LAYOUT_FLASH || - dev->attr->ecc_opt == UFFS_ECC_HW || - dev->attr->ecc_opt == UFFS_ECC_HW_AUTO), "WritePageWithLayout() not implemented ?")) { - ret = UFFS_FLASH_IO_ERR; - goto ext; - } - - uffs_FlashMakeSpare(dev, &tag->s, ecc, spare); - - ret = ops->WritePage(dev, block, page, buf->header, size, spare, dev->mem.spare_data_size); - - } - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - is_bad = U_TRUE; - - if (UFFS_FLASH_HAVE_ERR(ret)) - goto ext; - -#ifdef CONFIG_PAGE_WRITE_VERIFY - verify_buf = uffs_BufClone(dev, NULL); - if (verify_buf) { - ret = uffs_FlashReadPage(dev, block, page, verify_buf, U_FALSE); - if (!UFFS_FLASH_HAVE_ERR(ret)) { - if (memcmp(buf->header, verify_buf->header, size) != 0) { - uffs_Perror(UFFS_MSG_NORMAL, - "Page write verify failed (block %d page %d)", - block, page); - ret = UFFS_FLASH_BAD_BLK; - } - } - - uffs_BufFreeClone(dev, verify_buf); - } - else { - uffs_Perror(UFFS_MSG_SERIOUS, "Insufficient buf, clone buf failed."); - } - - ret = uffs_FlashReadPageTag(dev, block, page, &chk_tag); - if (UFFS_FLASH_HAVE_ERR(ret)) - goto ext; - - if (memcmp(&tag->s, &chk_tag.s, sizeof(uffs_TagStore)) != 0) { - uffs_Perror(UFFS_MSG_NORMAL, "Page tag write verify failed (block %d page %d)", - block, page); - ret = UFFS_FLASH_BAD_BLK; - } - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - is_bad = U_TRUE; - -#endif -ext: - if (is_bad) - uffs_BadBlockAdd(dev, block); - - if (spare) - uffs_PoolPut(SPOOL(dev), spare); - - return ret; -} - -/** - * mark a clean page tag as 'dirty' and 'invalid'. - * - * \param[in] dev uffs device - * \param[in] bc block info - * \param[in] page - * - * \return #UFFS_FLASH_NO_ERR: success. - * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? - * #UFFS_FLASH_BAD_BLK: a new bad block detected. - */ -int uffs_FlashMarkDirtyPage(uffs_Device *dev, uffs_BlockInfo *bc, int page) -{ - u8 *spare; - uffs_FlashOps *ops = dev->ops; - UBOOL is_bad = U_FALSE; - int ret = UFFS_FLASH_UNKNOWN_ERR; - int block = bc->block; - uffs_Tags *tag = GET_TAG(bc, page); - struct uffs_TagStoreSt *ts = &tag->s; - - spare = (u8 *) uffs_PoolGet(SPOOL(dev)); - if (spare == NULL) - goto ext; - - memset(ts, 0xFF, sizeof(struct uffs_TagStoreSt)); - ts->dirty = TAG_DIRTY; // set only 'dirty' bit, leave 'valid' bit to 1 (invalid). - - if (dev->attr->ecc_opt != UFFS_ECC_NONE) - TagMakeEcc(ts); - - if (ops->WritePageWithLayout) { - ret = ops->WritePageWithLayout(dev, block, page, NULL, 0, NULL, ts); - } - else { - uffs_FlashMakeSpare(dev, ts, NULL, spare); - ret = ops->WritePage(dev, block, page, NULL, 0, spare, dev->mem.spare_data_size); - } - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - is_bad = U_TRUE; - -ext: - if (is_bad) - uffs_BadBlockAdd(dev, block); - - if (spare) - uffs_PoolPut(SPOOL(dev), spare); - - return ret; -} - -/** Mark this block as bad block */ -URET uffs_FlashMarkBadBlock(uffs_Device *dev, int block) -{ - int ret; - uffs_BlockInfo *bc; - - uffs_Perror(UFFS_MSG_NORMAL, "Mark bad block: %d", block); - - bc = uffs_BlockInfoGet(dev, block); - if (bc) { - uffs_BlockInfoExpire(dev, bc, UFFS_ALL_PAGES); // expire this block, just in case it's been cached before - uffs_BlockInfoPut(dev, bc); - } - - if (dev->ops->MarkBadBlock) - return dev->ops->MarkBadBlock(dev, block) == 0 ? U_SUCC : U_FAIL; - -#ifdef CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - ret = dev->ops->EraseBlock(dev, block); - if (ret != UFFS_FLASH_IO_ERR) { - // note: even EraseBlock return UFFS_FLASH_BAD_BLK, - // we still process it ... not recommended for most NAND flash. -#endif - if (dev->ops->WritePageWithLayout) - ret = dev->ops->WritePageWithLayout(dev, block, 0, NULL, 0, NULL, NULL); - else - ret = dev->ops->WritePage(dev, block, 0, NULL, 0, NULL, 0); - -#ifdef CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - } -#endif - - return ret == UFFS_FLASH_NO_ERR ? U_SUCC : U_FAIL; -} - -/** Is this block a bad block ? */ -UBOOL uffs_FlashIsBadBlock(uffs_Device *dev, int block) -{ - struct uffs_FlashOpsSt *ops = dev->ops; - UBOOL ret = U_FALSE; - - if (ops->IsBadBlock) { - /* if flash driver provide 'IsBadBlock' function, call it */ - ret = (ops->IsBadBlock(dev, block) == 0 ? U_FALSE : U_TRUE); - } - else { - /* otherwise we call ReadPage[WithLayout]() to get bad block status byte */ - /* check the first page */ - if (ops->ReadPageWithLayout) { - ret = (ops->ReadPageWithLayout(dev, block, 0, NULL, 0, NULL, NULL, NULL) - == UFFS_FLASH_BAD_BLK ? U_TRUE : U_FALSE); - } - else { - ret = (ops->ReadPage(dev, block, 0, NULL, 0, NULL, NULL, 0) - == UFFS_FLASH_BAD_BLK ? U_TRUE : U_FALSE); - } - - if (ret == U_FALSE) { - /* check the second page */ - if (ops->ReadPageWithLayout) { - ret = (ops->ReadPageWithLayout(dev, block, 0, NULL, 0, NULL, NULL, NULL) - == UFFS_FLASH_BAD_BLK ? U_TRUE : U_FALSE); - } - else { - ret = (ops->ReadPage(dev, block, 0, NULL, 0, NULL, NULL, 0) - == UFFS_FLASH_BAD_BLK ? U_TRUE : U_FALSE); - } - } - } - - //uffs_Perror(UFFS_MSG_NOISY, "Block %d is %s", block, ret ? "BAD" : "GOOD"); - - return ret; -} - -/** Erase flash block */ -URET uffs_FlashEraseBlock(uffs_Device *dev, int block) -{ - int ret; - uffs_BlockInfo *bc; - - ret = dev->ops->EraseBlock(dev, block); - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - uffs_BadBlockAdd(dev, block); - - bc = uffs_BlockInfoGet(dev, block); - if (bc) { - uffs_BlockInfoExpire(dev, bc, UFFS_ALL_PAGES); - uffs_BlockInfoPut(dev, bc); - } - return UFFS_FLASH_HAVE_ERR(ret) ? U_FAIL : U_SUCC; -} - -/** - * Check the block by reading all pages. - * - * \return U_SUCC - all pages are clean, - * U_FAIL - block is not clean - */ -URET uffs_FlashCheckErasedBlock(uffs_Device *dev, int block) -{ - u8 *spare = NULL; - uffs_FlashOps *ops = dev->ops; - int ret = U_SUCC; - int page; - int flash_ret; - u8 ecc_store[UFFS_MAX_ECC_SIZE]; - uffs_TagStore ts; - uffs_Buf *buf = NULL; - int size = dev->com.pg_size; - int i; - u8 *p; - - spare = (u8 *) uffs_PoolGet(SPOOL(dev)); - - if (spare == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Can't allocate spare buf."); - goto ext; - } - - buf = uffs_BufClone(dev, NULL); - - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "Can't clone buf."); - goto ext; - } - - for (page = 0; page < dev->attr->pages_per_block; page++) { - if (ops->ReadPageWithLayout) { - - flash_ret = ops->ReadPageWithLayout(dev, block, page, buf->header, size, NULL, &ts, ecc_store); - - if (flash_ret != UFFS_FLASH_IO_ERR) { - // check page tag, should be all 0xFF - for (i = 0, p = (u8 *)(&ts); i < sizeof(ts); i++, p++) { - if (*p != 0xFF) { - ret = U_FAIL; - goto ext; - } - } - - // for hw or soft ecc, check stored ecc, should be all 0xFF - if (dev->attr->ecc_opt == UFFS_ECC_HW || - dev->attr->ecc_opt == UFFS_ECC_SOFT) - { - for (i = 0, p = ecc_store; i < ECC_SIZE(dev); i++, p++) { - if (*p != 0xFF) { - ret = U_FAIL; - goto ext; - } - } - } - } - } - else { - - flash_ret = ops->ReadPage(dev, block, page, buf->header, size, NULL, spare, dev->attr->spare_size); - if (flash_ret != UFFS_FLASH_IO_ERR) { - // check spare data, should be all 0xFF - for (i = 0, p = spare; i < dev->attr->spare_size; i++, p++) { - if (*p != 0xFF) { - ret = U_FAIL; - goto ext; - } - } - } - } - - if (flash_ret != UFFS_FLASH_IO_ERR) { - // check page data, should be all 0xFF - for (i = 0, p = buf->header; i < size; i++, p++) { - if (*p != 0xFF) { - ret = U_FAIL; - goto ext; - } - } - } - - } - - -ext: - if (spare) - uffs_PoolPut(SPOOL(dev), spare); - - if (buf) - uffs_BufFreeClone(dev, buf); - - - return ret; -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_fs.c b/components/dfs/filesystems/uffs/src/uffs/uffs_fs.c deleted file mode 100644 index d467c3ec97..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_fs.c +++ /dev/null @@ -1,1944 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_fs.c - * \brief basic file operations - * \author Ricky Zheng, created 12th May, 2005 - */ -#include "uffs_config.h" -#include "uffs/uffs_fs.h" -#include "uffs/uffs_pool.h" -#include "uffs/uffs_ecc.h" -#include "uffs/uffs_badblock.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_utils.h" -#include -#include - -#define PFX "fs : " - -#define GET_OBJ_NODE_SERIAL(obj) \ - ( \ - (obj)->type == UFFS_TYPE_DIR ? \ - (obj)->node->u.dir.serial : (obj)->node->u.file.serial \ - ) - -#define GET_OBJ_NODE_FATHER(obj) \ - ( \ - (obj)->type == UFFS_TYPE_DIR ? \ - (obj)->node->u.dir.parent : (obj)->node->u.file.parent \ - ) - -#define GET_SERIAL_FROM_OBJECT(obj) \ - ((obj)->node ? GET_OBJ_NODE_SERIAL(obj) : obj->serial) - -#define GET_FATHER_FROM_OBJECT(obj) \ - ((obj)->node ? GET_OBJ_NODE_FATHER(obj) : obj->parent) - - -#define GET_BLOCK_FROM_NODE(obj) \ - ( \ - (obj)->type == UFFS_TYPE_DIR ? \ - (obj)->node->u.dir.block : (obj)->node->u.file.block \ - ) - -typedef enum { - eDRY_RUN = 0, - eREAL_RUN, -} RunOptionE; - - -static void do_ReleaseObjectResource(uffs_Object *obj); -static URET do_TruncateObject(uffs_Object *obj, u32 remain, RunOptionE run_opt); - - -static int _object_data[(sizeof(struct uffs_ObjectSt) * MAX_OBJECT_HANDLE) / sizeof(int)]; - -static uffs_Pool _object_pool; - - -uffs_Pool * uffs_GetObjectPool(void) -{ - return &_object_pool; -} - -/** - * initialise object buffers, called by UFFS internal - */ -URET uffs_InitObjectBuf(void) -{ - return uffs_PoolInit(&_object_pool, _object_data, sizeof(_object_data), - sizeof(uffs_Object), MAX_OBJECT_HANDLE); -} - -/** - * Release object buffers, called by UFFS internal - */ -URET uffs_ReleaseObjectBuf(void) -{ - return uffs_PoolRelease(&_object_pool); -} - -/** - * Get free object handlers - */ -int uffs_GetFreeObjectHandlers(void) -{ - int count = 0; - - uffs_GlobalFsLockLock(); - count = uffs_PoolGetFreeCount(&_object_pool); - uffs_GlobalFsLockUnlock(); - - return count; -} - -/** - * Put all object which match dev - */ -int uffs_PutAllObjectBuf(uffs_Device *dev) -{ - int count = 0; - uffs_Object * obj = NULL; - - do { - obj = (uffs_Object *) uffs_PoolFindNextAllocated(&_object_pool, (void *)obj); - if (obj && obj->dev && obj->dev->dev_num == dev->dev_num) { - uffs_PutObject(obj); - count++; - } - } while (obj); - - return count; -} - -/** - * alloc a new object structure - * \return the new object - */ -uffs_Object * uffs_GetObject(void) -{ - uffs_Object * obj; - - obj = (uffs_Object *) uffs_PoolGet(&_object_pool); - if (obj) { - memset(obj, 0, sizeof(uffs_Object)); - obj->attr_loaded = U_FALSE; - obj->open_succ = U_FALSE; - } - - return obj; -} - -/** - * re-initialize an object. - * - * \return U_SUCC or U_FAIL if the object is openned. - */ -URET uffs_ReInitObject(uffs_Object *obj) -{ - if (obj == NULL) - return U_FAIL; - - if (obj->open_succ == U_TRUE) - return U_FAIL; // can't re-init an openned object. - - memset(obj, 0, sizeof(uffs_Object)); - obj->attr_loaded = U_FALSE; - obj->open_succ = U_FALSE; - - return U_SUCC; -} - -/** - * put the object struct back to system - */ -void uffs_PutObject(uffs_Object *obj) -{ - if (obj) - uffs_PoolPut(&_object_pool, obj); -} - -/** - * \return the internal index num of object - */ -int uffs_GetObjectIndex(uffs_Object *obj) -{ - return uffs_PoolGetIndex(&_object_pool, obj); -} - -/** - * \return the object by the internal index - */ -uffs_Object * uffs_GetObjectByIndex(int idx) -{ - return (uffs_Object *) uffs_PoolGetBufByIndex(&_object_pool, idx); -} - -#ifdef CONFIG_PER_DEVICE_LOCK -static void uffs_ObjectDevLock(uffs_Object *obj) -{ - if (obj) { - if (obj->dev) { - uffs_DeviceLock(obj->dev); - obj->dev_lock_count++; - } - } -} - -static void uffs_ObjectDevUnLock(uffs_Object *obj) -{ - if (obj) { - if (obj->dev) { - obj->dev_lock_count--; - uffs_DeviceUnLock(obj->dev); - } - } -} -#else -#define uffs_ObjectDevLock(obj) do { } while (0) -#define uffs_ObjectDevUnLock(obj) do { } while (0) - -#endif - - - -/** - * create a new object and open it if success - */ -URET uffs_CreateObject(uffs_Object *obj, const char *fullname, int oflag) -{ - URET ret = U_FAIL; - - oflag |= UO_CREATE; - - if (uffs_ParseObject(obj, fullname) == U_SUCC) - uffs_CreateObjectEx(obj, obj->dev, obj->parent, - obj->name, obj->name_len, oflag); - - if (obj->err == UENOERR) { - ret = U_SUCC; - } - else { - if (obj->dev) { - uffs_PutDevice(obj->dev); - obj->dev = NULL; - } - ret = U_FAIL; - } - - return ret; -} - - - -/** - * return the dir length from a path. - * for example, path = "abc/def/xyz", return 8 ("abc/def/") - */ -static int GetDirLengthFromPath(const char *path, int path_len) -{ - const char *p = path; - - if (path_len > 0) { - if (path[path_len - 1] == '/') - path_len--; // skip the last '/' - - p = path + path_len - 1; - while (p > path && *p != '/') - p--; - } - - return p - path; -} - -/** - * Create an object under the given dir. - * - * \param[in|out] obj to be created, obj is returned from uffs_GetObject() - * \param[in] dev uffs device - * \param[in] dir object parent dir serial NO. - * \param[in] name point to the object name - * \param[in] name_len object name length - * \param[in] oflag open flag. UO_DIR should be passed for an dir object. - * - * \return U_SUCC or U_FAIL (error code in obj->err). - */ -URET uffs_CreateObjectEx(uffs_Object *obj, uffs_Device *dev, - int dir, const char *name, int name_len, int oflag) -{ - uffs_Buf *buf = NULL; - uffs_FileInfo fi; - TreeNode *node; - - obj->dev = dev; - obj->parent = dir; - obj->type = (oflag & UO_DIR ? UFFS_TYPE_DIR : UFFS_TYPE_FILE); - obj->name = name; - obj->name_len = name_len; - - if (obj->type == UFFS_TYPE_DIR) { - if (name[obj->name_len - 1] == '/') // get rid of ending '/' for dir - obj->name_len--; - } - else { - if (name[obj->name_len - 1] == '/') { // file name can't end with '/' - obj->err = UENOENT; - goto ext; - } - } - - if (obj->name_len == 0) { // empty name ? - obj->err = UENOENT; - goto ext; - } - - obj->sum = uffs_MakeSum16(obj->name, obj->name_len); - - uffs_ObjectDevLock(obj); - - if (obj->type == UFFS_TYPE_DIR) { - //find out whether have file with the same name - node = uffs_TreeFindFileNodeByName(obj->dev, obj->name, - obj->name_len, obj->sum, - obj->parent); - if (node != NULL) { - obj->err = UEEXIST; // we can't create a dir has the - // same name with exist file. - goto ext_1; - } - obj->node = uffs_TreeFindDirNodeByName(obj->dev, obj->name, - obj->name_len, obj->sum, - obj->parent); - if (obj->node != NULL) { - obj->err = UEEXIST; // we can't create a dir already exist. - goto ext_1; - } - } - else { - //find out whether have dir with the same name - node = uffs_TreeFindDirNodeByName(obj->dev, obj->name, - obj->name_len, obj->sum, - obj->parent); - if (node != NULL) { - obj->err = UEEXIST; - goto ext_1; - } - obj->node = uffs_TreeFindFileNodeByName(obj->dev, obj->name, - obj->name_len, obj->sum, - obj->parent); - if (obj->node) { - /* file already exist, truncate it to zero length */ - obj->serial = GET_OBJ_NODE_SERIAL(obj); - obj->open_succ = U_TRUE; // set open_succ to U_TRUE before - // call do_TruncateObject() - if (do_TruncateObject(obj, 0, eDRY_RUN) == U_SUCC) - do_TruncateObject(obj, 0, eREAL_RUN); - goto ext_1; - } - } - - /* dir|file does not exist, create a new one */ - obj->serial = uffs_FindFreeFsnSerial(obj->dev); - if (obj->serial == INVALID_UFFS_SERIAL) { - uffs_Perror(UFFS_MSG_SERIOUS, "No free serial num!"); - obj->err = UENOMEM; - goto ext_1; - } - - if (obj->dev->tree.erased_count < obj->dev->cfg.reserved_free_blocks) { - uffs_Perror(UFFS_MSG_NOISY, - "insufficient block in create obj"); - obj->err = UENOMEM; - goto ext_1; - } - - buf = uffs_BufNew(obj->dev, obj->type, obj->parent, obj->serial, 0); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "Can't create new buffer when create obj!"); - goto ext_1; - } - - memset(&fi, 0, sizeof(uffs_FileInfo)); - fi.name_len = obj->name_len < sizeof(fi.name) ? obj->name_len : sizeof(fi.name) - 1; - memcpy(fi.name, obj->name, fi.name_len); - fi.name[fi.name_len] = '\0'; - - fi.access = 0; - fi.attr |= FILE_ATTR_WRITE; - - if (obj->type == UFFS_TYPE_DIR) - fi.attr |= FILE_ATTR_DIR; - - fi.create_time = fi.last_modify = uffs_GetCurDateTime(); - - uffs_BufWrite(obj->dev, buf, &fi, 0, sizeof(uffs_FileInfo)); - uffs_BufPut(obj->dev, buf); - - // flush buffer immediately, - // so that the new node will be inserted into the tree - uffs_BufFlushGroup(obj->dev, obj->parent, obj->serial); - - // update obj->node: after buf flushed, - // the NEW node can be found in the tree - if (obj->type == UFFS_TYPE_DIR) - obj->node = uffs_TreeFindDirNode(obj->dev, obj->serial); - else - obj->node = uffs_TreeFindFileNode(obj->dev, obj->serial); - - if (obj->node == NULL) { - uffs_Perror(UFFS_MSG_NOISY, "Can't find the node in the tree ?"); - obj->err = UEIOERR; - goto ext_1; - } - - if (obj->type == UFFS_TYPE_FILE) - obj->node->u.file.len = 0; //init the length to 0 - - if (HAVE_BADBLOCK(obj->dev)) - uffs_BadBlockRecover(obj->dev); - - obj->open_succ = U_TRUE; - -ext_1: - uffs_ObjectDevUnLock(obj); -ext: - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - -/** - * Open object under the given dir. - * - * \param[in|out] obj to be open, obj is returned from uffs_GetObject() - * \param[in] dev uffs device - * \param[in] dir object parent dir serial NO. - * \param[in] name point to the object name - * \param[in] name_len object name length - * \param[in] oflag open flag. UO_DIR should be passed for an dir object. - * - * \return U_SUCC or U_FAIL (error code in obj->err). - */ -URET uffs_OpenObjectEx(uffs_Object *obj, uffs_Device *dev, - int dir, const char *name, int name_len, int oflag) -{ - - obj->err = UENOERR; - obj->open_succ = U_FALSE; - - if (dev == NULL) { - obj->err = UEINVAL; - goto ext; - } - - if ((oflag & (UO_WRONLY | UO_RDWR)) == (UO_WRONLY | UO_RDWR)) { - /* UO_WRONLY and UO_RDWR can't appear together */ - uffs_Perror(UFFS_MSG_NOISY, - "UO_WRONLY and UO_RDWR can't appear together"); - obj->err = UEINVAL; - goto ext; - } - - obj->oflag = oflag; - obj->parent = dir; - obj->type = (oflag & UO_DIR ? UFFS_TYPE_DIR : UFFS_TYPE_FILE); - obj->pos = 0; - obj->dev = dev; - obj->name = name; - obj->name_len = name_len; - - // adjust the name length - if (obj->type == UFFS_TYPE_DIR) { - if (obj->name_len > 0 && name[obj->name_len - 1] == '/') - obj->name_len--; // truncate the ending '/' for dir - } - - obj->sum = (obj->name_len > 0 ? uffs_MakeSum16(name, obj->name_len) : 0); - obj->head_pages = obj->dev->attr->pages_per_block - 1; - - if (obj->type == UFFS_TYPE_DIR) { - if (obj->name_len == 0) { - if (dir != PARENT_OF_ROOT) { - uffs_Perror(UFFS_MSG_SERIOUS, "Bad parent for root dir!"); - obj->err = UEINVAL; - } - else { - obj->serial = ROOT_DIR_SERIAL; - } - goto ext; - } - } - else { - if (obj->name_len == 0 || name[obj->name_len - 1] == '/') { - uffs_Perror(UFFS_MSG_SERIOUS, "Bad file name."); - obj->err = UEINVAL; - } - } - - - uffs_ObjectDevLock(obj); - - if (obj->type == UFFS_TYPE_DIR) { - obj->node = uffs_TreeFindDirNodeByName(obj->dev, obj->name, - obj->name_len, obj->sum, - obj->parent); - } - else { - obj->node = uffs_TreeFindFileNodeByName(obj->dev, obj->name, - obj->name_len, obj->sum, - obj->parent); - } - - if (obj->node == NULL) { // dir or file not exist - if (obj->oflag & UO_CREATE) { // expect to create a new one - uffs_ObjectDevUnLock(obj); - if (obj->name == NULL || obj->name_len == 0) - obj->err = UEEXIST; - else - uffs_CreateObjectEx(obj, dev, dir, obj->name, obj->name_len, oflag); - goto ext; - } - else { - obj->err = UENOENT; - goto ext_1; - } - } - - if ((obj->oflag & (UO_CREATE | UO_EXCL)) == (UO_CREATE | UO_EXCL)){ - obj->err = UEEXIST; - goto ext_1; - } - - obj->serial = GET_OBJ_NODE_SERIAL(obj); - obj->open_succ = U_TRUE; - - if (obj->oflag & UO_TRUNC) - if (do_TruncateObject(obj, 0, eDRY_RUN) == U_SUCC) { - //NOTE: obj->err will be set in do_TruncateObject() if failed. - do_TruncateObject(obj, 0, eREAL_RUN); - } - -ext_1: - uffs_ObjectDevUnLock(obj); -ext: - obj->open_succ = (obj->err == UENOERR ? U_TRUE : U_FALSE); - - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - - -/** - * Parse the full path name, initialize obj. - * - * \param[out] obj object to be initialize. - * \param[in] name full path name. - * - * \return U_SUCC if the name is parsed correctly, - * U_FAIL if failed, and obj->err is set. - * - * \note the following fields in obj will be initialized: - * obj->dev - * obj->parent - * obj->name - * obj->name_len - */ -URET uffs_ParseObject(uffs_Object *obj, const char *name) -{ - int len, m_len, d_len; - uffs_Device *dev; - const char *start, *p, *dname; - u16 dir; - TreeNode *node; - u16 sum; - - if (uffs_ReInitObject(obj) == U_FAIL) - return U_FAIL; - - len = strlen(name); - m_len = uffs_GetMatchedMountPointSize(name); - dev = uffs_GetDeviceFromMountPointEx(name, m_len); - - if (dev) { - start = name + m_len; - d_len = GetDirLengthFromPath(start, len - m_len); - p = start; - obj->dev = dev; - if (m_len == len) { - obj->parent = PARENT_OF_ROOT; - obj->name = NULL; - obj->name_len = 0; - } - else { - dir = ROOT_DIR_SERIAL; - dname = start; - while (p - start < d_len) { - while (*p != '/') p++; - sum = uffs_MakeSum16(dname, p - dname); - node = uffs_TreeFindDirNodeByName(dev, dname, p - dname, sum, dir); - if (node == NULL) { - obj->err = UENOENT; - break; - } - else { - dir = node->u.dir.serial; - p++; // skip the '/' - dname = p; - } - } - obj->parent = dir; - obj->name = start + (d_len > 0 ? d_len + 1 : 0); - obj->name_len = len - (d_len > 0 ? d_len + 1 : 0) - m_len; - } - - if (obj->err != UENOERR) { - uffs_PutDevice(obj->dev); - obj->dev = NULL; - } - } - else { - obj->err = UENOENT; - } - - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - - -static void do_ReleaseObjectResource(uffs_Object *obj) -{ - if (obj) { - if (obj->dev) { - if (HAVE_BADBLOCK(obj->dev)) - uffs_BadBlockRecover(obj->dev); - if (obj->dev_lock_count > 0) { - uffs_ObjectDevUnLock(obj); - } - uffs_PutDevice(obj->dev); - obj->dev = NULL; - obj->open_succ = U_FALSE; - } - } -} - -/** - * Open a UFFS object - * - * \param[in|out] obj the object to be open - * \param[in] name the full name of the object - * \param[in] oflag open flag - * - * \return U_SUCC if object is opened successfully, - * U_FAIL if failed, error code will be set to obj->err. - */ -URET uffs_OpenObject(uffs_Object *obj, const char *name, int oflag) -{ - URET ret; - - if (obj == NULL) - return U_FAIL; - - if ((ret = uffs_ParseObject(obj, name)) == U_SUCC) { - ret = uffs_OpenObjectEx(obj, obj->dev, obj->parent, - obj->name, obj->name_len, oflag); - } - if (ret != U_SUCC) - do_ReleaseObjectResource(obj); - - return ret; -} - -static URET do_FlushObject(uffs_Object *obj) -{ - uffs_Device *dev; - URET ret = U_SUCC; - TreeNode *node = NULL; - - dev = obj->dev; - if (obj->node) { - node = obj->node; - if (obj->type == UFFS_TYPE_DIR) - ret = uffs_BufFlushGroup(dev, obj->node->u.dir.parent, - obj->node->u.dir.serial); - else { - ret = ( - uffs_BufFlushGroupMatchParent(dev, obj->node->u.file.serial) == U_SUCC && - uffs_BufFlushGroup(dev, obj->node->u.file.parent, obj->node->u.file.serial) == U_SUCC - ) ? U_SUCC : U_FAIL; - } - uffs_Assert(node == obj->node, "obj->node change!\n"); - } - - return ret; -} - -/** - * Flush object data. - * - * \param[in] obj object to be flushed - * \return U_SUCC or U_FAIL (error code in obj->err). - */ -URET uffs_FlushObject(uffs_Object *obj) -{ - if(obj->dev == NULL || obj->open_succ != U_TRUE) { - obj->err = UEBADF; - goto ext; - } - - uffs_ObjectDevLock(obj); - - if (do_FlushObject(obj) != U_SUCC) - obj->err = UEIOERR; - - uffs_ObjectDevUnLock(obj); - -ext: - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - -/** - * Close an openned object. - * - * \param[in] obj object to be closed - * \return U_SUCC or U_FAIL (error code in obj->err). - */ -URET uffs_CloseObject(uffs_Object *obj) -{ -#ifdef CONFIG_CHANGE_MODIFY_TIME - uffs_Device *dev; - uffs_Buf *buf; - uffs_FileInfo fi; -#endif - - if(obj->dev == NULL || obj->open_succ != U_TRUE) { - obj->err = UEBADF; - goto ext; - } - - - uffs_ObjectDevLock(obj); - - if (obj->oflag & (UO_WRONLY|UO_RDWR|UO_APPEND|UO_CREATE|UO_TRUNC)) { - -#ifdef CONFIG_CHANGE_MODIFY_TIME - dev = obj->dev; - if (obj->node) { - //need to change the last modify time stamp - if (obj->type == UFFS_TYPE_DIR) - buf = uffs_BufGetEx(dev, UFFS_TYPE_DIR, obj->node, 0, obj->oflag); - else - buf = uffs_BufGetEx(dev, UFFS_TYPE_FILE, obj->node, 0, obj->oflag); - - if(buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get file header"); - do_FlushObject(obj); - uffs_ObjectDevUnLock(obj); - goto ext; - } - uffs_BufRead(dev, buf, &fi, 0, sizeof(uffs_FileInfo)); - fi.last_modify = uffs_GetCurDateTime(); - uffs_BufWrite(dev, buf, &fi, 0, sizeof(uffs_FileInfo)); - uffs_BufPut(dev, buf); - } -#endif - do_FlushObject(obj); - } - - uffs_ObjectDevUnLock(obj); - -ext: - do_ReleaseObjectResource(obj); - - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - -static u16 GetFdnByOfs(uffs_Object *obj, u32 ofs) -{ - uffs_Device *dev = obj->dev; - - if (ofs < (u32)(obj->head_pages * dev->com.pg_data_size)) { - return 0; - } - else { - ofs -= obj->head_pages * dev->com.pg_data_size; - return (ofs / (dev->com.pg_data_size * dev->attr->pages_per_block)) + 1; - } -} - - -static u32 GetStartOfDataBlock(uffs_Object *obj, u16 fdn) -{ - if (fdn == 0) { - return 0; - } - else { - return (obj->head_pages * obj->dev->com.pg_data_size) + - (fdn - 1) * (obj->dev->com.pg_data_size * - obj->dev->attr->pages_per_block); - } -} - - -static int do_WriteNewBlock(uffs_Object *obj, - const void *data, u32 len, - u16 parent, - u16 serial) -{ - uffs_Device *dev = obj->dev; - u16 page_id; - int wroteSize = 0; - int size; - uffs_Buf *buf; - URET ret; - - for (page_id = 0; page_id < dev->attr->pages_per_block; page_id++) { - size = (len - wroteSize) > dev->com.pg_data_size ? - dev->com.pg_data_size : len - wroteSize; - if (size <= 0) - break; - - buf = uffs_BufNew(dev, UFFS_TYPE_DATA, parent, serial, page_id); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't create a new page ?"); - break; - } - // Note: if data == NULL, we will fill '\0' - ret = uffs_BufWrite(dev, buf, data == NULL ? NULL : (u8 *)data + wroteSize, 0, size); - uffs_BufPut(dev, buf); - - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "write data fail!"); - break; - } - wroteSize += size; - obj->node->u.file.len += size; - } - - return wroteSize; -} - -static int do_WriteInternalBlock(uffs_Object *obj, - TreeNode *node, - u16 fdn, - const void *data, - u32 len, - u32 blockOfs) -{ - uffs_Device *dev = obj->dev; - u16 maxPageID; - u16 page_id; - u32 size; - u32 pageOfs; - u32 wroteSize = 0; - URET ret; - uffs_Buf *buf; - u32 block_start; - u8 type; - u16 parent, serial; - - block_start = GetStartOfDataBlock(obj, fdn); - - if (fdn == 0) { - type = UFFS_TYPE_FILE; - parent = node->u.file.parent; - serial = node->u.file.serial; - } - else { - type = UFFS_TYPE_DATA; - parent = node->u.data.parent; - serial = fdn; - } - - if (fdn == 0) - maxPageID = obj->head_pages; - else - maxPageID = dev->attr->pages_per_block - 1; - - - while (wroteSize < len) { - page_id = blockOfs / dev->com.pg_data_size; - if (fdn == 0) - page_id++; //in file header, page_id start from 1, not 0. - if (page_id > maxPageID) - break; - - pageOfs = blockOfs % dev->com.pg_data_size; - size = (len - wroteSize + pageOfs) > dev->com.pg_data_size ? - (dev->com.pg_data_size - pageOfs) : (len - wroteSize); - - if ((obj->node->u.file.len % dev->com.pg_data_size) == 0 && - (blockOfs + block_start) == obj->node->u.file.len) { - - buf = uffs_BufNew(dev, type, parent, serial, page_id); - - if(buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can create a new buf!"); - break; - } - } - else { - buf = uffs_BufGetEx(dev, type, node, page_id, obj->oflag); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get buffer ?"); - break; - } - } - - // Note: if data == NULL, then we will fill '\0' - ret = uffs_BufWrite(dev, buf, data == NULL ? NULL : (u8 *)data + wroteSize, pageOfs, size); - - uffs_BufPut(dev, buf); - - if (ret == U_FAIL) { - uffs_Perror(UFFS_MSG_SERIOUS, "write inter data fail!"); - break; - } - - wroteSize += size; - blockOfs += size; - - if (block_start + blockOfs > obj->node->u.file.len) - obj->node->u.file.len = block_start + blockOfs; - - } - - return wroteSize; -} - - -/** - * write data to obj, return remain data (0 if all data been written). - */ -static int do_WriteObject(uffs_Object *obj, const void *data, int len) -{ - uffs_Device *dev = obj->dev; - TreeNode *fnode = obj->node; - int remain = len; - u16 fdn; - u32 write_start; - TreeNode *dnode; - u32 size; - - while (remain > 0) { - write_start = obj->pos + len - remain; - if (write_start > fnode->u.file.len) { - uffs_Perror(UFFS_MSG_SERIOUS, "write point out of file ?"); - break; - } - - fdn = GetFdnByOfs(obj, write_start); - - if (write_start == fnode->u.file.len && fdn > 0 && - write_start == GetStartOfDataBlock(obj, fdn)) { - if (dev->tree.erased_count < dev->cfg.reserved_free_blocks) { - uffs_Perror(UFFS_MSG_NOISY, "insufficient block in write obj, new block"); - break; - } - size = do_WriteNewBlock(obj, data ? (u8 *)data + len - remain : NULL, - remain, fnode->u.file.serial, fdn); - - // - // Flush the new block buffers immediately, so that the new data node will be - // created and put in the tree. - // - // But before do that, we need to make sure the previous - // data block (if exist) been flushed first. - // - if (fdn > 1) { - uffs_BufFlushGroup(dev, fnode->u.file.serial, fdn - 1); - } - else { - uffs_BufFlushGroup(dev, fnode->u.file.parent, fnode->u.file.serial); - } - // Now flush the new block. - uffs_BufFlushGroup(dev, fnode->u.file.serial, fdn); - - if (size == 0) - break; - - remain -= size; - } - else { - - if(fdn == 0) - dnode = obj->node; - else - dnode = uffs_TreeFindDataNode(dev, fnode->u.file.serial, fdn); - - if(dnode == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't find data node in tree ?"); - obj->err = UEUNKNOWN_ERR; - break; - } - size = do_WriteInternalBlock(obj, dnode, fdn, - data ? (u8 *)data + len - remain : NULL, remain, - write_start - GetStartOfDataBlock(obj, fdn)); -#ifdef CONFIG_FLUSH_BUF_AFTER_WRITE - if (fdn == 0) - uffs_BufFlushGroup(dev, fnode->u.file.parent, fnode->u.file.serial); - else - uffs_BufFlushGroup(dev, fnode->u.file.serial, fdn); -#endif - if (size == 0) - break; - - remain -= size; - } - } - - uffs_Assert(fnode == obj->node, "obj->node change!\n"); - - return remain; -} - - -/** - * write data to obj, from obj->pos - * - * \param[in] obj file obj - * \param[in] data data pointer - * \param[in] len length of data to be write - * - * \return bytes wrote to obj - */ -int uffs_WriteObject(uffs_Object *obj, const void *data, int len) -{ - uffs_Device *dev = obj->dev; - TreeNode *fnode = NULL; - int remain; - u32 pos; - int wrote = 0; - - if (obj == NULL) - return 0; - - if (obj->dev == NULL || obj->open_succ != U_TRUE) { - obj->err = UEBADF; - return 0; - } - - if (obj->type == UFFS_TYPE_DIR) { - uffs_Perror(UFFS_MSG_NOISY, "Can't write to an dir object!"); - obj->err = UEACCES; - return 0; - } - - if (obj->oflag == UO_RDONLY) { - obj->err = UEACCES; // can't write to 'read only' mode opened file - return 0; - } - - fnode = obj->node; - - uffs_ObjectDevLock(obj); - - if (obj->oflag & UO_APPEND) - obj->pos = fnode->u.file.len; - else { - if (obj->pos > fnode->u.file.len) { - // current pos pass over the end of file, need to fill the gap with '\0' - pos = obj->pos; // save desired pos - obj->pos = fnode->u.file.len; // filling gap from the end of the file. - remain = do_WriteObject(obj, NULL, pos - fnode->u.file.len); // Write filling bytes. Note: the filling data does not count as 'wrote' in this write operation. - obj->pos = pos - remain; - if (remain > 0) // fail to fill the gap ? stop. - goto ext; - } - } - - remain = do_WriteObject(obj, data, len); - wrote = len - remain; - obj->pos += wrote; - -ext: - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockRecover(dev); - - uffs_ObjectDevUnLock(obj); - - uffs_Assert(fnode == obj->node, "obj->node change!\n"); - - return wrote; -} - -/** - * read data from obj - * - * \param[in] obj uffs object - * \param[out] data output data buffer - * \param[in] len required length of data to be read from object->pos - * - * \return return bytes of data have been read - */ -int uffs_ReadObject(uffs_Object *obj, void *data, int len) -{ - uffs_Device *dev = obj->dev; - TreeNode *fnode = NULL; - u32 remain = len; - u16 fdn; - u32 read_start; - TreeNode *dnode; - u32 size; - uffs_Buf *buf; - u32 blockOfs; - u16 page_id; - u8 type; - u32 pageOfs; - - if (obj == NULL) - return 0; - - fnode = obj->node; - - if (obj->dev == NULL || obj->open_succ == U_FALSE) { - obj->err = UEBADF; - return 0; - } - - if (obj->type == UFFS_TYPE_DIR) { - uffs_Perror(UFFS_MSG_NOISY, "Can't read data from a dir object!"); - obj->err = UEBADF; - return 0; - } - - if (obj->pos > fnode->u.file.len) { - return 0; //can't read file out of range - } - - if (obj->oflag & UO_WRONLY) { - obj->err = UEACCES; - return 0; - } - - uffs_ObjectDevLock(obj); - - while (remain > 0) { - read_start = obj->pos + len - remain; - if (read_start >= fnode->u.file.len) { - //uffs_Perror(UFFS_MSG_NOISY, "read point out of file ?"); - break; - } - - fdn = GetFdnByOfs(obj, read_start); - if (fdn == 0) { - dnode = obj->node; - type = UFFS_TYPE_FILE; - } - else { - type = UFFS_TYPE_DATA; - dnode = uffs_TreeFindDataNode(dev, fnode->u.file.serial, fdn); - if (dnode == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get data node in entry!"); - obj->err = UEUNKNOWN_ERR; - break; - } - } - - blockOfs = GetStartOfDataBlock(obj, fdn); - page_id = (read_start - blockOfs) / dev->com.pg_data_size; - - if (fdn == 0) { - /** - * fdn == 0: this means that the reading is start from the first block, - * since the page 0 is for file attr, so we move to the next page ID. - */ - page_id++; - } - - buf = uffs_BufGetEx(dev, type, dnode, (u16)page_id, obj->oflag); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get buffer when read obj."); - obj->err = UEIOERR; - break; - } - - pageOfs = read_start % dev->com.pg_data_size; - if (pageOfs >= buf->data_len) { - //uffs_Perror(UFFS_MSG_NOISY, "read data out of page range ?"); - uffs_BufPut(dev, buf); - break; - } - size = (remain + pageOfs > buf->data_len ? buf->data_len - pageOfs : remain); - - uffs_BufRead(dev, buf, (u8 *)data + len - remain, pageOfs, size); - uffs_BufPut(dev, buf); - - remain -= size; - } - - obj->pos += (len - remain); - - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockRecover(dev); - - uffs_ObjectDevUnLock(obj); - - uffs_Assert(fnode == obj->node, "obj->node change!\n"); - - return len - remain; -} - -/** - * move the file pointer - * - * \param[in] obj uffs object - * \param[in] offset offset from origin - * \param[in] origin the origin position, one of: - * #USEEK_CUR, #USEEK_SET or #USEEK_END - * - * \return the new file pointer position if success, - * or -1 if the new position would be negative. - */ -long uffs_SeekObject(uffs_Object *obj, long offset, int origin) -{ - if (obj->type == UFFS_TYPE_DIR) { - uffs_Perror(UFFS_MSG_NOISY, "Can't seek a dir object!"); - obj->err = UEACCES; - } - else { - uffs_ObjectDevLock(obj); - switch (origin) { - case USEEK_CUR: - if ((long)obj->pos + offset < 0) { - obj->err = UEINVAL; - } - else { - obj->pos += offset; - } - break; - case USEEK_SET: - if (offset < 0) { - obj->err = UEINVAL; - } - else { - obj->pos = offset; - } - break; - case USEEK_END: - if ((long)obj->node->u.file.len + offset < 0) { - obj->err = UEINVAL; - } - else { - obj->pos = obj->node->u.file.len + offset; - } - break; - } - uffs_ObjectDevUnLock(obj); - } - - return (obj->err == UENOERR ? (long)obj->pos : -1); -} - -/** - * get current file pointer - * - * \param[in] obj uffs object - * - * \return return the file pointer position if the obj is valid, - * return -1 if obj is invalid. - */ -int uffs_GetCurOffset(uffs_Object *obj) -{ - if (obj) { - if (obj->dev && obj->open_succ == U_TRUE) - return obj->pos; - } - return -1; -} - -/** - * check whether the file pointer is at the end of file - * - * \param[in] obj uffs object - * - * \return return 1 if file pointer is at the end of file, - * return -1 if error occur, else return 0. - */ -int uffs_EndOfFile(uffs_Object *obj) -{ - if (obj) { - if (obj->dev && obj->type == UFFS_TYPE_FILE && obj->open_succ == U_TRUE) { - if (obj->pos >= obj->node->u.file.len) { - return 1; - } - else { - return 0; - } - } - } - - return -1; -} - -// -// To trancate the file, this is the last block to be trancated. -// We need to discard one or more pages within this block, hence requires 'block recover'. -// -static URET do_TruncateInternalWithBlockRecover(uffs_Object *obj, - u16 fdn, u32 remain, RunOptionE run_opt) -{ - uffs_Device *dev = obj->dev; - TreeNode *fnode = obj->node; - u16 page_id, max_page_id; - TreeNode *node; - uffs_Buf *buf = NULL; - u8 type; - u32 block_start; - u16 parent, serial; - int slot; - uffs_BlockInfo *bc = NULL; - int block = -1; - - if (fdn == 0) { - node = fnode; - type = UFFS_TYPE_FILE; - max_page_id = obj->head_pages; - block_start = 0; - parent = node->u.file.parent; - serial = node->u.file.serial; - block = node->u.file.block; - } - else { - node = uffs_TreeFindDataNode(dev, fnode->u.file.serial, fdn); - if (node == NULL) { - obj->err = UEIOERR; - uffs_Perror(UFFS_MSG_SERIOUS, - "can't find data node when truncate obj"); - goto ext; - } - block = node->u.data.block; - type = UFFS_TYPE_DATA; - max_page_id = dev->attr->pages_per_block - 1; - block_start = obj->head_pages * dev->com.pg_data_size + - (fdn - 1) * dev->com.pg_data_size * - dev->attr->pages_per_block; - parent = node->u.data.parent; - serial = node->u.data.serial; - } - - if (run_opt == eDRY_RUN) { - // checking the buffer. this is the main reason why we need the 'dry run' mode. - for (page_id = 0; page_id <= max_page_id; page_id++) { - buf = uffs_BufFind(dev, parent, serial, page_id); - if (buf) { - //!< ok, the buffer was loaded before ... - if (uffs_BufIsFree(buf) == U_FALSE) { - obj->err = UEEXIST; - break; //!< and someone is still holding the buffer, - // can't truncate it !!! - } - } - } - buf = NULL; - goto ext; - } - - // find the last page *after* truncate - for (page_id = (fdn == 0 ? 1 : 0); page_id <= max_page_id; page_id++) { - if (block_start + (page_id + 1) * dev->com.pg_data_size >= remain) - break; - } - - if (!uffs_Assert(page_id <= max_page_id, "fdn = %d, block_start = %d, remain = %d\n", fdn, block_start, remain)) { - obj->err = UEUNKNOWN_ERR; - goto ext; - } - - // flush buffer before performing block recovery - uffs_BufFlushGroup(dev, parent, serial); - - // load the last page - buf = uffs_BufGetEx(dev, type, node, page_id, obj->oflag); - if (buf == NULL) { - obj->err = UENOMEM; - uffs_Perror(UFFS_MSG_SERIOUS, "Can't get buf"); - goto ext; - } - - uffs_BufWrite(dev, buf, NULL, 0, 0); // just make this buf dirty - - // lock the group - slot = uffs_BufFindGroupSlot(dev, parent, serial); - uffs_BufLockGroup(dev, slot); - - if (remain == 0) // remain == 0: means discard all data in this block. - buf->data_len = 0; - else { - remain = (remain % dev->com.pg_data_size); - // remain == 0: means that we need to keep all data in this page. - buf->data_len = (remain == 0 ? dev->com.pg_data_size : remain); - } - - /* mark this buf as UFFS_BUF_EXT_MARK_TRUNC_TAIL, when flushing - dirty buffers, UFFS will not do page recover for pages after - this buf page id (because this file is ended at this page) */ - buf->ext_mark |= UFFS_BUF_EXT_MARK_TRUNC_TAIL; - - uffs_BufPut(dev, buf); - - // invalidate the rest page buf - page_id++; - for (; page_id <= max_page_id; page_id++) { - buf = uffs_BufFind(dev, parent, serial, page_id); - if (buf) - uffs_BufMarkEmpty(dev, buf); - } - - // flush dirty buffer immediately, forcing block recovery. - uffs_BufFlushGroupEx(dev, parent, serial, U_TRUE); - - // unlock the group - uffs_BufUnLockGroup(dev, slot); - - // Invalidate block info cache for the 'old' block - bc = uffs_BlockInfoGet(dev, block); - if (bc) { - uffs_BlockInfoExpire(dev, bc, UFFS_ALL_PAGES); - uffs_BlockInfoPut(dev, bc); - } - -ext: - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - -/** - * truncate an object - * - * \param[in] obj object to be truncated - * \param[in] remain data bytes to be remained in this object - * - * \return U_SUCC or U_FAIL (error code in obj->err) - */ -URET uffs_TruncateObject(uffs_Object *obj, u32 remain) -{ - uffs_ObjectDevLock(obj); - if (do_TruncateObject(obj, remain, eDRY_RUN) == U_SUCC) - do_TruncateObject(obj, remain, eREAL_RUN); - uffs_ObjectDevUnLock(obj); - - uffs_FlushObject(obj); - - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - -/** truncate obj without lock device */ -static URET do_TruncateObject(uffs_Object *obj, u32 remain, RunOptionE run_opt) -{ - uffs_Device *dev = obj->dev; - TreeNode *fnode = obj->node; - u16 fdn; - u32 flen; - u32 block_start; - TreeNode *node; - uffs_BlockInfo *bc; - uffs_Buf *buf; - u16 page; - int pos; - - pos = obj->pos; // save current file position - - if (obj->dev == NULL || obj->open_succ == U_FALSE || fnode == NULL) { - obj->err = UEBADF; - goto ext; - } - - /* can't truncate a dir */ - /* TODO: delete files under dir ? */ - if (obj->type == UFFS_TYPE_DIR) { - obj->err = UEEXIST; - goto ext; - } - - if (remain >= fnode->u.file.len) { - goto ext; //!< nothing to do ... - } - - flen = fnode->u.file.len; - - if (flen < remain) { - // file is shorter than 'reamin', fill the gap with '\0' - if (run_opt == eREAL_RUN) { - obj->pos = flen; // move file pointer to the end - if (do_WriteObject(obj, NULL, remain - flen) > 0) { // fill '\0' ... - uffs_Perror(UFFS_MSG_SERIOUS, "Write object not finished. expect %d but only %d wrote.", - remain - flen, fnode->u.file.len - flen); - obj->err = UEIOERR; // likely be an I/O error. - } - flen = obj->node->u.file.len; - } - } - else { - while (flen > remain) { - fdn = GetFdnByOfs(obj, flen - 1); - - //uffs_BufFlushGroup(dev, obj->serial, fdn); //!< flush the buffer - - block_start = GetStartOfDataBlock(obj, fdn); - if (remain <= block_start && fdn > 0) { - node = uffs_TreeFindDataNode(dev, obj->serial, fdn); - if (node == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "can't find data node when trancate obj."); - obj->err = UEIOERR; - goto ext; - } - bc = uffs_BlockInfoGet(dev, node->u.data.block); - if (bc == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "can't get block info when trancate obj."); - obj->err = UEIOERR; - goto ext; - } - - for (page = 0; page < dev->attr->pages_per_block; page++) { - buf = uffs_BufFind(dev, fnode->u.file.serial, fdn, page); - if (buf) { - //!< ok, the buffer was loaded before ... - if (uffs_BufIsFree(buf) == U_FALSE) { - uffs_BlockInfoPut(dev, bc); - goto ext; //!< and someone is still holding the buffer, - // can't truncate it !!! - } - else if (run_opt == eREAL_RUN) - uffs_BufMarkEmpty(dev, buf); //!< discard the buffer - } - } - - if (run_opt == eREAL_RUN) { - uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, node); - uffs_FlashEraseBlock(dev, bc->block); - node->u.list.block = bc->block; - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, node); - else - uffs_TreeInsertToErasedListTail(dev, node); - - fnode->u.file.len = block_start; - } - - flen = block_start; - uffs_BlockInfoPut(dev, bc); - } - else { - if (do_TruncateInternalWithBlockRecover(obj, fdn, - remain, run_opt) == U_SUCC) { - if (run_opt == eREAL_RUN) - fnode->u.file.len = remain; - flen = remain; - } - } - } - } - - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockRecover(dev); -ext: - obj->pos = pos; // keep file pointer offset not changed. - - uffs_Assert(fnode == obj->node, "obj->node change!\n"); - - return (obj->err == UENOERR ? U_SUCC : U_FAIL); - -} - -/** - * \brief check if there are anyone holding buf of this obj. - * If no one holding the buffers, expire the buffer. - * \return - * 0 : no one holding any buf of this obj - * >0 : the ref_count of buf which refer to this obj. - */ -int _CheckObjBufRef(uffs_Object *obj) -{ - uffs_Device *dev = obj->dev; - uffs_Buf *buf; - TreeNode *node = obj->node; - u16 parent, serial, last_serial; - - // check the DIR or FILE block - for (buf = uffs_BufFind(dev, obj->parent, obj->serial, UFFS_ALL_PAGES); - buf != NULL; - buf = uffs_BufFindFrom(dev, buf->next, obj->parent, obj->serial, UFFS_ALL_PAGES)) - { - if (buf->ref_count > 0) { - // oops ... - uffs_Perror(UFFS_MSG_SERIOUS, "someone still hold buf parent = %d, serial = %d, ref_count", - obj->parent, obj->serial, buf->ref_count); - - return buf->ref_count; - } - else { - buf->mark = UFFS_BUF_EMPTY; - } - } - - if (buf == NULL || buf->ref_count == 0) { - // check the DATA block - if (obj->type == UFFS_TYPE_FILE && node->u.file.len > 0) { - - parent = obj->serial; - last_serial = GetFdnByOfs(obj, node->u.file.len - 1); - for (serial = 1; serial <= last_serial; serial++) { - - for (buf = uffs_BufFind(dev, parent, serial, UFFS_ALL_PAGES); - buf != NULL; - buf = uffs_BufFindFrom(dev, buf->next, parent, serial, UFFS_ALL_PAGES)) - { - if (buf->ref_count != 0) { - // oops ... - uffs_Perror(UFFS_MSG_SERIOUS, "someone still hold buf parent = %d, serial = %d, ref_count", - parent, serial, buf->ref_count); - - return buf->ref_count; - } - else { - buf->mark = UFFS_BUF_EMPTY; - } - } - } - } - } - - return 0; -} - - - -/** - * \brief delete uffs object - * - * \param[in] name full name of object - * \param[out] err return error code - * - * \return U_SUCC if object is deleted successfully. - * return U_FAIL if error happen, error code is set to *err. - */ -URET uffs_DeleteObject(const char * name, int *err) -{ - uffs_Object *obj, *work; - TreeNode *node, *d_node; - uffs_Device *dev = NULL; - u16 block; - u16 serial, parent, last_serial; - UBOOL bad = U_FALSE; - URET ret = U_FAIL; - - obj = uffs_GetObject(); - if (obj == NULL) { - if (err) - *err = UEMFILE; - goto ext_unlock; - } - - if (uffs_OpenObject(obj, name, UO_RDWR|UO_DIR) == U_FAIL) { - if (uffs_OpenObject(obj, name, UO_RDWR) == U_FAIL) { - if (err) - *err = UENOENT; - goto ext_unlock; - } - } - - dev = obj->dev; - - // working throught object pool see if the object is opened ... - uffs_ObjectDevLock(obj); - work = NULL; - while ((work = (uffs_Object *)uffs_PoolFindNextAllocated(&_object_pool, work)) != NULL) { - if (work != obj && - work->dev && - work->dev == obj->dev && - work->node && - work->node == obj->node) { - // this object is opened, can't delete it. - if (err) - *err = UEACCES; - goto ext_lock; - } - } - - if (obj->type == UFFS_TYPE_DIR) { - // if the dir is not empty, can't delete it. - node = uffs_TreeFindDirNodeWithParent(dev, obj->serial); - if (node != NULL) { - if (err) - *err = UEACCES; - goto ext_lock; //have sub dirs ? - } - - node = uffs_TreeFindFileNodeWithParent(dev, obj->serial); - if (node != NULL) { - if (err) - *err = UEACCES; - goto ext_lock; //have sub files ? - } - } - - // before erase the block, we need to take care of the buffer ... - uffs_BufFlushAll(dev); - - if (_CheckObjBufRef(obj) > 0) { - if (err) - *err = UEACCES; - goto ext_lock; - } - - node = obj->node; - - // ok, now we are safe to erase DIR/FILE block :-) - block = GET_BLOCK_FROM_NODE(obj); - parent = obj->serial; - last_serial = (obj->type == UFFS_TYPE_FILE && node->u.file.len > 0 ? GetFdnByOfs(obj, node->u.file.len - 1) : 0); - - uffs_BreakFromEntry(dev, obj->type, node); - uffs_FlashEraseBlock(dev, block); - node->u.list.block = block; - node->u.list.u.serial = obj->serial; - - // From now on, the object is gone physically, - // but we need to 'suspend' this node so that no one will re-use - // the serial number during deleting the reset part of object. - - if (HAVE_BADBLOCK(dev)) { - uffs_BadBlockProcessSuspend(dev, node); - bad = U_TRUE; // will be put into 'bad' list later - } - else { - uffs_TreeSuspendAdd(dev, node); - bad = U_FALSE; // will be put into erased list later - } - - // now erase DATA blocks - if (obj->type == UFFS_TYPE_FILE && last_serial > 0) { - for (serial = 1; serial <= last_serial; serial++) { - - uffs_ObjectDevUnLock(obj); - ; // yield CPU to improve responsive when deleting large file. - uffs_ObjectDevLock(obj); - - d_node = uffs_TreeFindDataNode(dev, parent, serial); - if (uffs_Assert(d_node != NULL, "Can't find DATA node parent = %d, serial = %d\n", parent, serial)) { - uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, d_node); - block = d_node->u.data.block; - uffs_FlashEraseBlock(dev, block); - d_node->u.list.block = block; - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, d_node); - else - uffs_TreeInsertToErasedListTail(dev, d_node); - } - } - } - - // now process the suspend node - uffs_TreeRemoveSuspendNode(dev, node); - if (bad) - uffs_TreeInsertToBadBlockList(dev, node); - else - uffs_TreeInsertToErasedListTail(dev, node); - - ret = U_SUCC; - -ext_lock: - uffs_ObjectDevUnLock(obj); -ext_unlock: - do_ReleaseObjectResource(obj); - - uffs_PutObject(obj); - - return ret; -} - -/** - * Remove object under a new parent, change object name. - * - * \param[in|out] obj - * \param[in] new_parent new parent's serial number - * \param[in] new_name new name of the object. - * if new_name == NULL, keep the old name. - * \param[in] name_len new name length. - * - * \return U_SUCC or U_FAIL (obj->err for the reason) - */ -URET uffs_MoveObjectEx(uffs_Object *obj, - int new_parent, const char *new_name, int name_len) -{ - uffs_Buf *buf; - uffs_FileInfo fi; - uffs_Device *dev = obj->dev; - TreeNode *node = obj->node; - - if (dev == NULL || node == NULL || obj->open_succ != U_TRUE) { - obj->err = UEBADF; - goto ext; - } - - uffs_ObjectDevLock(obj); - - obj->parent = new_parent; - - if (name_len > 0) { - - buf = uffs_BufGetEx(dev, obj->type, node, 0, obj->oflag); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get buf when rename!"); - obj->err = UEIOERR; - goto ext_1; - } - - memcpy(&fi, buf->data, sizeof(uffs_FileInfo)); - - if (new_name[name_len-1] == '/') - name_len--; - - memcpy(fi.name, new_name, name_len); - fi.name[name_len] = 0; - fi.name_len = name_len; - fi.last_modify = uffs_GetCurDateTime(); - - buf->parent = new_parent; // !! need to manually change the 'parent' !! - uffs_BufWrite(dev, buf, &fi, 0, sizeof(uffs_FileInfo)); - uffs_BufPut(dev, buf); - - // !! force a block recover so that all old tag will be expired !! - // This is important so we only need to check - // the first spare when mount UFFS :) - uffs_BufFlushGroupEx(dev, obj->parent, obj->serial, U_TRUE); - - obj->name = new_name; - obj->name_len = name_len; - obj->sum = uffs_MakeSum16(fi.name, fi.name_len); - } - - //update the check sum and new parent of tree node - if (obj->type == UFFS_TYPE_DIR) { - obj->node->u.dir.checksum = obj->sum; - obj->node->u.dir.parent = new_parent; - } - else { - obj->node->u.file.checksum = obj->sum; - obj->node->u.file.parent = new_parent; - } - -ext_1: - uffs_ObjectDevUnLock(obj); -ext: - - return (obj->err == UENOERR ? U_SUCC : U_FAIL); -} - -/** - * \brief rename(move) file or dir. - * \return U_SUCC if success, otherwise return U_FAIL and set error code to *err. - * \note rename/move file between different mount point is not allowed. - */ -URET uffs_RenameObject(const char *old_name, const char *new_name, int *err) -{ - uffs_Object *obj = NULL, *new_obj = NULL; - URET ret = U_FAIL; - int oflag; - - obj = uffs_GetObject(); - new_obj = uffs_GetObject(); - - if (obj == NULL || new_obj == NULL) { - if (err) - *err = UEINVAL; - goto ext; - } - - oflag = UO_RDONLY; - if (uffs_OpenObject(new_obj, new_name, oflag) == U_SUCC) { - uffs_CloseObject(new_obj); - uffs_Perror(UFFS_MSG_NOISY, "new object already exist!"); - if (err) - *err = UEEXIST; - goto ext; - } - oflag |= UO_DIR; - if (uffs_OpenObject(new_obj, new_name, oflag) == U_SUCC) { - uffs_CloseObject(new_obj); - uffs_Perror(UFFS_MSG_NOISY, "new object already exist!"); - if (err) - *err = UEEXIST; - goto ext; - } - - if (uffs_ParseObject(new_obj, new_name) != U_SUCC) { - uffs_Perror(UFFS_MSG_NOISY, "parse new name fail !"); - if (err) - *err = UENOENT; - goto ext; - } - - if (new_obj->name_len == 0) { - uffs_Perror(UFFS_MSG_NOISY, "invalid new name"); - if (err) - *err = UEINVAL; - goto ext; - } - - oflag = UO_RDONLY; - if (uffs_OpenObject(obj, old_name, oflag) != U_SUCC) { - oflag |= UO_DIR; - if (uffs_OpenObject(obj, old_name, oflag) != U_SUCC) { - uffs_Perror(UFFS_MSG_NOISY, "Can't open old object !"); - if (err) - *err = UEACCES; - goto ext; - } - } - - if (obj->dev != new_obj->dev) { - uffs_Perror(UFFS_MSG_NOISY, - "Can't move object between different mount point"); - if (err) - *err = UEACCES; - } - else { - ret = uffs_MoveObjectEx(obj, new_obj->parent, - new_obj->name, new_obj->name_len); - if (ret == U_FAIL && err) - *err = obj->err; - } - - uffs_CloseObject(obj); - -ext: - if (obj) uffs_PutObject(obj); - if (new_obj) { - do_ReleaseObjectResource(new_obj); - uffs_PutObject(new_obj); - } - - return ret; -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_init.c b/components/dfs/filesystems/uffs/src/uffs/uffs_init.c deleted file mode 100644 index bc0a5ca893..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_init.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_init.c - * \brief initialize uffs file system device - * \author Ricky Zheng, created 12th May, 2005 - */ - -#include "uffs_config.h" -#include "uffs/uffs_types.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_tree.h" -#include "uffs/uffs_fs.h" -#include "uffs/uffs_badblock.h" -#include "uffs/uffs_utils.h" -#include - -#define PFX "init: " - -static URET uffs_InitDeviceConfig(uffs_Device *dev) -{ - if (dev->cfg.dirty_groups == 0) - dev->cfg.dirty_groups = MAX_DIRTY_BUF_GROUPS; - - if (!uffs_Assert(dev->cfg.dirty_groups >= 1 && dev->cfg.dirty_groups <= MAX_DIRTY_BUF_GROUPS, - "invalid config: dirty_groups = %d\n", dev->cfg.dirty_groups)) - return U_FAIL; - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR > 0 - dev->cfg.bc_caches = MAX_CACHED_BLOCK_INFO; - dev->cfg.page_buffers = MAX_PAGE_BUFFERS; - dev->cfg.dirty_pages = MAX_DIRTY_PAGES_IN_A_BLOCK; - dev->cfg.reserved_free_blocks = MINIMUN_ERASED_BLOCK; -#else - if (dev->cfg.bc_caches == 0) - dev->cfg.bc_caches = MAX_CACHED_BLOCK_INFO; - if (dev->cfg.page_buffers == 0) - dev->cfg.page_buffers = MAX_PAGE_BUFFERS; - if (dev->cfg.dirty_pages == 0) - dev->cfg.dirty_pages = MAX_DIRTY_PAGES_IN_A_BLOCK; - if (dev->cfg.reserved_free_blocks == 0) - dev->cfg.reserved_free_blocks = MINIMUN_ERASED_BLOCK; - - if (!uffs_Assert(dev->cfg.page_buffers - CLONE_BUFFERS_THRESHOLD >= 3, "invalid config: page_buffers = %d\n", dev->cfg.page_buffers)) - return U_FAIL; - -#endif - return U_SUCC; -} - -URET uffs_InitDevice(uffs_Device *dev) -{ - URET ret; - - ret = uffs_InitDeviceConfig(dev); - if (ret != U_SUCC) - return U_FAIL; - - if (dev->mem.init) { - if (dev->mem.init(dev) != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "Init memory allocator fail."); - return U_FAIL; - } - } - - memset(&(dev->st), 0, sizeof(uffs_FlashStat)); - - uffs_DeviceInitLock(dev); - uffs_BadBlockInit(dev); - - - if (uffs_FlashInterfaceInit(dev) != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "Can't initialize flash interface !"); - goto fail; - } - - uffs_Perror(UFFS_MSG_NOISY, "init page buf"); - ret = uffs_BufInit(dev, dev->cfg.page_buffers, dev->cfg.dirty_pages); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_DEAD, "Initialize page buffers fail"); - goto fail; - } - uffs_Perror(UFFS_MSG_NOISY, "init block info cache"); - ret = uffs_BlockInfoInitCache(dev, dev->cfg.bc_caches); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_DEAD, "Initialize block info fail"); - goto fail; - } - - ret = uffs_TreeInit(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "fail to init tree buffers"); - goto fail; - } - - ret = uffs_BuildTree(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "fail to build tree"); - goto fail; - } - - return U_SUCC; - -fail: - uffs_DeviceReleaseLock(dev); - - return U_FAIL; -} - -URET uffs_ReleaseDevice(uffs_Device *dev) -{ - URET ret; - - ret = uffs_BlockInfoReleaseCache(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "fail to release block info."); - goto ext; - } - - ret = uffs_BufReleaseAll(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "fail to release page buffers"); - goto ext; - } - - ret = uffs_TreeRelease(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "fail to release tree buffers!"); - goto ext; - } - - ret = uffs_FlashInterfaceRelease(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "fail to release tree buffers!"); - goto ext; - } - - if (dev->mem.release) - ret = dev->mem.release(dev); - - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "fail to release memory allocator!"); - } - - uffs_DeviceReleaseLock(dev); - -ext: - return ret; - -} - -URET uffs_InitFileSystemObjects(void) -{ - if (uffs_InitObjectBuf() == U_SUCC) { - if (uffs_DirEntryBufInit() == U_SUCC) { - uffs_InitGlobalFsLock(); - return U_SUCC; - } - } - - return U_FAIL; -} - -URET uffs_ReleaseFileSystemObjects(void) -{ - if (uffs_ReleaseObjectBuf() == U_SUCC) { - if (uffs_DirEntryBufRelease() == U_SUCC) { - uffs_ReleaseGlobalFsLock(); - return U_SUCC; - } - } - - return U_FAIL; -} diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_mem.c b/components/dfs/filesystems/uffs/src/uffs/uffs_mem.c deleted file mode 100644 index 9763cd7c43..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_mem.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_mem.c - * \brief uffs static memory allocator - * \author Ricky Zheng, created 23th Feb, 2007 - */ - -#include -#include "uffs_config.h" -#include "uffs/uffs_types.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_mem.h" - -#define PFX "mem : " - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR > 0 -static void * static_malloc(struct uffs_DeviceSt *dev, unsigned int size) -{ - struct uffs_memAllocatorSt *mem = &dev->mem; - void *p = NULL; - - size += (size % sizeof(long) ? sizeof(long) - (size % sizeof(long)) : 0); - - if (mem->buf_size - mem->pos < (int)size) { - uffs_Perror(UFFS_MSG_SERIOUS, - "Memory alloc failed! (alloc %d, free %d)", - size, mem->buf_size - mem->pos); - } - else { - p = mem->buf_start + mem->pos; - mem->pos += size; - uffs_Perror(UFFS_MSG_NOISY, - "0x%p: Allocated %d, free %d", - p, size, mem->buf_size - mem->pos); - } - - return p; -} - -void uffs_MemSetupStaticAllocator(uffs_MemAllocator *allocator, - void *pool, int size) -{ - allocator->buf_start = (char *)pool; - allocator->buf_size = size; - allocator->pos = 0; - allocator->malloc = static_malloc; - allocator->free = NULL; //never free memory for static memory allocator - - uffs_Perror(UFFS_MSG_NOISY, - "System static memory: %d bytes", allocator->buf_size); - -} - -#endif - - - - - - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_mtb.c b/components/dfs/filesystems/uffs/src/uffs/uffs_mtb.c deleted file mode 100644 index ca7f197249..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_mtb.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_mtb.c - * \brief mount table operations - * \author Ricky Zheng, created 11th July, 2009 - */ -#include "uffs_config.h" -#include "uffs/uffs_types.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_tree.h" -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_fd.h" -#include "uffs/uffs_utils.h" -#include "uffs/uffs_fs.h" -#include - -#define PFX "mtb : " - -static struct uffs_MountTableEntrySt *m_head = NULL; // list of mounted entries -static struct uffs_MountTableEntrySt *m_free_head = NULL; // list of unmounted entries - -/** Return mounted entries header */ -uffs_MountTable * uffs_MtbGetMounted(void) -{ - return m_head; -} - -/** Return unmounted entries header */ -uffs_MountTable * uffs_MtbGetUnMounted(void) -{ - return m_free_head; -} - -/** - * \brief Register mount table - * \param mtb mount table entry - * \return 0 succ - * -1 failed (e.g. already registered and mounted) - */ -int uffs_RegisterMountTable(uffs_MountTable *mtb) -{ - uffs_MountTable *work = NULL; - static int dev_num = 0; - - if (mtb == NULL) - return -1; - - for (work = m_head; work; work = work->next) { - if (work == mtb) - return -1; // already mounted ? - } - - for (work = m_free_head; work; work = work->next) { - if (work == mtb) - return 0; // already registered. - } - - /* replace the free head */ - if (m_free_head) - m_free_head->prev = mtb; - mtb->prev = NULL; - mtb->next = m_free_head; - m_free_head = mtb; - - mtb->dev->dev_num = ++dev_num; - - return 0; -} - -/** - * \brief Remove mount entry from the table - * \param mtb mount table entry - * \return 0 removed succ - * -1 entry in used or not in the 'unmounted' list - */ -int uffs_UnRegisterMountTable(uffs_MountTable *mtb) -{ - uffs_MountTable *work = NULL; - - if (mtb == NULL) - return -1; - - for (work = m_head; work; work = work->next) { - if (work == mtb) - return -1; // in the mounted list ? busy, return - } - - for (work = m_free_head; work; work = work->next) { - if (work == mtb) { - // found, remove it from the list - if (work->next) - work->next->prev = work->prev; - if (work->prev) - work->prev->next = work->next; - if (work == m_free_head) - m_free_head = work->next; - - break; - } - } - - return work ? 0 : -1; -} - -static uffs_MountTable * uffs_GetMountTableByMountPoint(const char *mount, uffs_MountTable *head) -{ - uffs_MountTable *work = NULL; - - for (work = head; work; work = work->next) { - if (strcmp(work->mount, mount) == 0) - break; - } - return work; -} - -/** - * \brief mount partition - * \param[in] mount partition mount point - * \return 0 succ - * <0 fail - * - * \note use uffs_RegisterMountTable() register mount entry before you can mount it. - * mount point should ended with '/', e.g. '/sys/' - */ -int uffs_Mount(const char *mount) -{ - uffs_MountTable *mtb; - - if (uffs_GetMountTableByMountPoint(mount, m_head) != NULL) { - uffs_Perror(UFFS_MSG_NOISY, "'%s' already mounted", mount); - return -1; // already mounted ? - } - - mtb = uffs_GetMountTableByMountPoint(mount, m_free_head); - if (mtb == NULL) { - uffs_Perror(UFFS_MSG_NOISY, "'%s' not registered", mount); - return -1; // not registered ? - } - - uffs_Perror(UFFS_MSG_NOISY, - "init device for mount point %s ...", - mtb->mount); - - mtb->dev->par.start = mtb->start_block; - if (mtb->end_block < 0) { - mtb->dev->par.end = - mtb->dev->attr->total_blocks + mtb->end_block; - } - else { - mtb->dev->par.end = mtb->end_block; - } - - if (mtb->dev->Init(mtb->dev) == U_FAIL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "init device for mount point %s fail", - mtb->mount); - return -1; - } - - uffs_Perror(UFFS_MSG_NOISY, "mount partiton: %d,%d", - mtb->dev->par.start, mtb->dev->par.end); - - if (uffs_InitDevice(mtb->dev) != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "init device fail !"); - return -1; - } - - /* now break it from unmounted list */ - if (mtb->prev) - mtb->prev->next = mtb->next; - if (mtb->next) - mtb->next->prev = mtb->prev; - if (m_free_head == mtb) - m_free_head = mtb->next; - - /* link to mounted list */ - mtb->prev = NULL; - mtb->next = m_head; - if (m_head) - m_head->prev = mtb; - m_head = mtb; - - return 0; -} - -/** - * \brief unmount parttion - * \param[in] mount partition mount point - * \return 0 succ - * <0 fail - */ -int uffs_UnMount(const char *mount) -{ - uffs_MountTable *mtb = uffs_GetMountTableByMountPoint(mount, m_head); - - if (mtb == NULL) { - uffs_Perror(UFFS_MSG_NOISY, "'%s' not mounted ?", mount); - return -1; // not mounted ? - } - - if (uffs_GetMountTableByMountPoint(mount, m_free_head) != NULL) { - uffs_Perror(UFFS_MSG_NOISY, "'%s' already unmounted ?", mount); - return -1; // already unmounted ? - } - - if (mtb->dev->ref_count != 0) { - uffs_Perror(UFFS_MSG_NORMAL, "Can't unmount '%s' - busy", mount); - return -1; - } - - if (uffs_ReleaseDevice(mtb->dev) == U_FAIL) { - uffs_Perror(UFFS_MSG_NORMAL, "Can't release device for mount point '%s'", mount); - return -1; - } - - mtb->dev->Release(mtb->dev); - - // break from mounted list - if (mtb->prev) - mtb->prev->next = mtb->next; - if (mtb->next) - mtb->next->prev = mtb->prev; - if (mtb == m_head) - m_head = mtb->next; - - // put to unmounted list - mtb->prev = NULL; - mtb->next = m_free_head; - if (m_free_head) - m_free_head->prev = mtb; - m_free_head = mtb; - - return 0; -} - -/** - * find the matched mount point from a given full absolute path. - * - * \param[in] path full path - * \return the length of mount point. - */ -int uffs_GetMatchedMountPointSize(const char *path) -{ - int pos; - uffs_Device *dev; - - if (path[0] != '/') - return 0; - - pos = strlen(path); - - while (pos > 0) { - if ((dev = uffs_GetDeviceFromMountPointEx(path, pos)) != NULL ) { - uffs_PutDevice(dev); - return pos; - } - else { - if (path[pos-1] == '/') - pos--; - //back forward search the next '/' - for (; pos > 0 && path[pos-1] != '/'; pos--) - ; - } - } - - return pos; -} - -/** - * get device from mount point. - * - * \param[in] mount mount point name. - * \return NULL if mount point is not found. - */ -uffs_Device * uffs_GetDeviceFromMountPoint(const char *mount) -{ - uffs_MountTable *mtb = uffs_GetMountTableByMountPoint(mount, m_head); - - if (mtb) { - mtb->dev->ref_count++; - return mtb->dev; - } - - return NULL; -} - -/** - * get device from mount point. - * - * \param[in] mount mount point name. - * \param[in] len mount point name length. - * \return NULL if mount point is not found. - */ -uffs_Device * uffs_GetDeviceFromMountPointEx(const char *mount, int len) -{ - uffs_MountTable *work = NULL; - - for (work = m_head; work; work = work->next) { - if (strlen(work->mount) == len && - strncmp(mount, work->mount, len) == 0) { - work->dev->ref_count++; - return work->dev; - } - } - - return NULL; -} - - -/** - * return mount point from device - * - * \param[in] dev uffs device - * \return NULL if mount point is not found, - * otherwise return mount point name in mount table. - */ -const char * uffs_GetDeviceMountPoint(uffs_Device *dev) -{ - uffs_MountTable *work = NULL; - - for (work = m_head; work; work = work->next) { - if (work->dev == dev) { - return work->mount; - } - } - - return NULL; -} - -void uffs_PutDevice(uffs_Device *dev) -{ - dev->ref_count--; -} - - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_pool.c b/components/dfs/filesystems/uffs/src/uffs/uffs_pool.c deleted file mode 100644 index 22adc53f30..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_pool.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_pool.c - * \brief Fast fixed size memory pool management. - * \author Ricky Zheng, Simon Kallweit - */ - -#include "uffs_config.h" -#include "uffs/uffs_types.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_pool.h" - -/* - - usage: - - #define BUF_SIZE 32 - #define NUM_BUFS 1024 - - static int pool_mem[NUM_BUFS * BUF_SIZE / sizeof(int)]; - static uffs_Pool pool; - - uffs_PoolInit(&pool, pool_mem, sizeof(pool_mem), BUF_SIZE, NUM_BUFS); - - void * p; - p = uffs_PoolGet(&pool); - ... - uffs_PoolPut(p, &pool); - - notice: - - uffs_PoolInit will assert when NUM_BUFS is not at least 1, or BUF_SIZE is - not aligned to the platforms pointer size. - -*/ - - -/** - * \brief Initializes the memory pool. - * \param[in] pool memory pool - * \param[in] mem pool memory - * \param[in] mem_size size of pool memory - * \param[in] buf_size size of a single buffer - * \param[in] num_bufs number of buffers - * \return Returns U_SUCC if successful. - */ -URET uffs_PoolInit(uffs_Pool *pool, - void *mem, u32 mem_size, u32 buf_size, u32 num_bufs) -{ - unsigned int i; - uffs_PoolEntry *e1, *e2; - - if (!uffs_Assert(pool != NULL, "pool missing") || - !uffs_Assert(mem != NULL, "pool memory missing") || - !uffs_Assert(num_bufs > 0, "not enough buffers") || - !uffs_Assert(buf_size % sizeof(void *) == 0, - "buffer size not aligned to pointer size") || - !uffs_Assert(mem_size == num_bufs * buf_size, - "pool memory size is wrong")) - { - return U_FAIL; - } - - pool->mem = (u8 *)mem; - pool->buf_size = buf_size; - pool->num_bufs = num_bufs; - - uffs_SemCreate(&pool->sem); - uffs_SemWait(pool->sem); - - // Initialize the free_list - e1 = e2 = pool->free_list = (uffs_PoolEntry *) pool->mem; - for (i = 1; i < pool->num_bufs; i++) { - e2 = (uffs_PoolEntry *) (pool->mem + i * pool->buf_size); - e1->next = e2; - e1 = e2; - } - e2->next = NULL; - - uffs_SemSignal(pool->sem); - - return U_SUCC; -} - -/** - * \brief verify pointer validity aganist memory pool - * \return U_TRUE if valid, U_FALSE if invalid. - */ -UBOOL uffs_PoolVerify(uffs_Pool *pool, void *p) -{ - return p && - (u8 *)p >= pool->mem && - (u8 *)p < pool->mem + (pool->buf_size * pool->num_bufs) && - (((u8 *)p - pool->mem) % pool->buf_size) == 0 ? U_TRUE : U_FALSE; -} - -/** - * \brief Releases the memory pool. - * \param[in] pool memory pool - * \return Returns U_SUCC if successful. - */ -URET uffs_PoolRelease(uffs_Pool *pool) -{ - if (!uffs_Assert(pool != NULL, "pool missing")) - return U_FAIL; - - uffs_SemDelete(&pool->sem); - - return U_SUCC; -} - -/** - * \brief Get a buffer from the memory pool. - * \param[in] pool memory pool - * \return Returns a pointer to the buffer or NULL if none is available. - */ -void *uffs_PoolGet(uffs_Pool *pool) -{ - uffs_PoolEntry *e; - - if (!uffs_Assert(pool != NULL, "pool missing")) - return NULL; - - e = pool->free_list; - if (e) - pool->free_list = e->next; - - return e; -} - -/** - * \brief Get a buffer from the memory pool. - * This version is locked and should be used when multiple threads access the - * same memory pool. - * \param[in] pool memory pool - * \return Returns a pointer to the buffer or NULL if none is available. - */ -void *uffs_PoolGetLocked(uffs_Pool *pool) -{ - uffs_PoolEntry *e; - - if (!uffs_Assert(pool != NULL, "pool missing")) - return NULL; - - uffs_SemWait(pool->sem); - e = pool->free_list; - if (e) - pool->free_list = e->next; - uffs_SemSignal(pool->sem); - - return e; -} - -/** - * \brief Puts a buffer back to the memory pool. - * \param[in] pool memory pool - * \param[in] p buffer to put back - * \return Returns 0 if successful. - */ -int uffs_PoolPut(uffs_Pool *pool, void *p) -{ - uffs_PoolEntry *e = (uffs_PoolEntry *)p; - - if (!uffs_Assert(pool != NULL, "pool missing")) - return -1; - - if (e) { - e->next = pool->free_list; - pool->free_list = e; - return 0; - } - - return -1; -} - -/** - * \brief Puts a buffer back to the memory pool. - * This version is locked and should be used when multiple threads access the - * same memory pool. - * \param[in] pool memory pool - * \param[in] p buffer to put back - * \return Returns 0 if successful. - */ -int uffs_PoolPutLocked(uffs_Pool *pool, void *p) -{ - uffs_PoolEntry *e = (uffs_PoolEntry *)p; - - if (!uffs_Assert(pool != NULL, "pool missing")) - return -1; - - if (e) { - uffs_SemWait(pool->sem); - e->next = pool->free_list; - pool->free_list = e; - uffs_SemSignal(pool->sem); - return 0; - } - - return -1; -} - -/** - * \brief Gets a buffer by index (offset). - * This method returns a buffer from the memory pool by index. - * \param[in] pool memory pool - * \param[in] index index - * \return Returns a pointer to the buffer. - */ -void *uffs_PoolGetBufByIndex(uffs_Pool *pool, u32 index) -{ - if (!uffs_Assert(pool != NULL, "pool missing") || - !uffs_Assert(index < pool->num_bufs, - "index(%d) out of range(max %d)", index, pool->num_bufs)) - { - return NULL; - } - - return (u8 *) pool->mem + index * pool->buf_size; -} - -/** - * \brief Gets the index (offset) of a buffer. - * This method returns the index of a buffer from the memory pool. - * \param[in] pool memory pool - * \param[in] p buffer to get index from - * \return Returns the index of the buffer. - */ -u32 uffs_PoolGetIndex(uffs_Pool *pool, void *p) -{ - if (!uffs_Assert(pool != NULL, "pool missing") || - !uffs_Assert(p >= (void *) pool->mem && - p < (void *) (pool->mem + pool->num_bufs * pool->buf_size), - "pointer out of range")) - { - uffs_Panic(); - } - - return ((u8 *) p - pool->mem) / pool->buf_size; -} - -/** - * \brief Check given buffer in free list - * \return U_TRUE if it's in free list, U_FALSE if not. - */ -UBOOL uffs_PoolCheckFreeList(uffs_Pool *pool, void *p) -{ - uffs_PoolEntry *e; - for (e = pool->free_list; e; e = e->next) { - if ((void *)e == p) - return U_TRUE; - } - return U_FALSE; -} - -/** - * \brief this is more efficient version for small nodes number memory pool (< 32) - */ -static void * FindNextAllocatedInSmallPool(uffs_Pool *pool, void *from) -{ - u32 map = 0; - uffs_PoolEntry *e; - u32 i; - - for (e = pool->free_list; e; e = e->next) - map |= (1 << uffs_PoolGetIndex(pool, e)); - - for (i = uffs_PoolGetIndex(pool, from); - (map & (1 << i)) && i < 32 && i < pool->num_bufs; - i++); - - return i < 32 && i < pool->num_bufs ? - uffs_PoolGetBufByIndex(pool, i) : NULL; -} - - -/** - * \brief Find next allocated memory block - * - * \param[in] pool memory pool - * \param[in] from search start address, if NULL, from pool->mem - * - * \return next allocated memory block, NULL if not found. - * - * \note This is NOT efficient, don't do it on a pool with large free nodes ! - */ -void * uffs_PoolFindNextAllocated(uffs_Pool *pool, void *from) -{ - uffs_PoolEntry *e = NULL; - u8 *p = (u8 *)from; - - if (p == NULL) - p = pool->mem; - else - p += pool->buf_size; - - if (pool->num_bufs < 32) - return FindNextAllocatedInSmallPool(pool, p); - - // work through the free list, stop if not in free list, - // otherwise move to next entry and search free list again. - - if (pool->free_list) { - while (uffs_PoolVerify(pool, p)) { - e = pool->free_list; - while (e) { - if (p == (u8 *)e) { - p += pool->buf_size; // in free list, move to next entry - break; - } - e = e->next; - } - if (e == NULL) // not in free_list, gotcha - break; - } - } - - return uffs_PoolVerify(pool, p) ? p : NULL ; -} - -/** - * \brief get free memory block count - */ -int uffs_PoolGetFreeCount(uffs_Pool *pool) -{ - int count = 0; - uffs_PoolEntry *e; - - e = pool->free_list; - while (e) { - count++; - e = e->next; - } - - return count; -} - -/** - * \brief put all memory block back, return how many memory blocks were put back - */ -int uffs_PoolPutAll(uffs_Pool *pool) -{ - void *p = NULL; - int count = 0; - - do { - p = uffs_PoolFindNextAllocated(pool, p); - if (p) { - uffs_PoolPut(pool, p); - count++; - } - } while (p); - - return count; -} diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_public.c b/components/dfs/filesystems/uffs/src/uffs/uffs_public.c deleted file mode 100644 index 348b7892d3..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_public.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_public.c - * \brief public and miscellaneous functions - * \author Ricky Zheng, created 10th May, 2005 - */ - -#include "uffs_config.h" -#include "uffs/uffs_types.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_crc.h" - -#include - -#define PFX "pub : " - - -int uffs_GetFirstBlockTimeStamp(void) -{ - return 0; -} - -int uffs_GetNextBlockTimeStamp(int prev) -{ - return (prev + 1) % 3; -} - -UBOOL uffs_IsSrcNewerThanObj(int src, int obj) -{ - switch (src - obj) { - case 0: - uffs_Perror(UFFS_MSG_SERIOUS, - "the two block have the same time stamp ?"); - break; - case 1: - case -2: - return U_TRUE; - case -1: - case 2: - return U_FALSE; - default: - uffs_Perror(UFFS_MSG_SERIOUS, "time stamp out of range !"); - break; - } - - return U_FALSE; -} - - -/** - * \brief given a page, search the block to find - * a better page with the same page id - * - * \param[in] dev uffs device - * \param[in] bc block info - * \param[in] page page number to be compared with - * - * \return the better page number, could be the same with the given page. - * if the given page does not have good tag, return UFFS_INVALID_PAGE. - */ -u16 uffs_FindBestPageInBlock(uffs_Device *dev, uffs_BlockInfo *bc, u16 page) -{ - int i; - uffs_Tags *tag, *tag_old; - - if (!uffs_Assert(page != UFFS_INVALID_PAGE, "invalid param !")) - return page; // just in case ... - - uffs_BlockInfoLoad(dev, bc, page); // load old page - tag_old = GET_TAG(bc, page); - - if (!uffs_Assert(TAG_IS_GOOD(tag_old), "try to find a invalid page ?")) - return UFFS_INVALID_PAGE; - - if (page == dev->attr->pages_per_block - 1) // already the last page ? - return page; - - for (i = dev->attr->pages_per_block - 1; i > page; i--) { - uffs_BlockInfoLoad(dev, bc, i); - tag = GET_TAG(bc, i); - if (TAG_IS_GOOD(tag) && - TAG_PAGE_ID(tag) == TAG_PAGE_ID(tag_old) && - TAG_PARENT(tag) == TAG_PARENT(tag_old) && - TAG_SERIAL(tag) == TAG_SERIAL(tag_old)) - { - break; - } - } - - return i; -} - -/** - * \brief find a valid page with given page_id - * \param[in] dev uffs device - * \param[in] bc block info - * \param[in] page_id page_id to be find - * \return the valid page number which has given page_id - * \retval >=0 page number - * \retval UFFS_INVALID_PAGE page not found - */ -u16 uffs_FindPageInBlockWithPageId(uffs_Device *dev, - uffs_BlockInfo *bc, u16 page_id) -{ - u16 page; - uffs_Tags *tag; - - //Indeed, the page which has page_id, should ahead of page_id ... - for (page = page_id; page < dev->attr->pages_per_block; page++) { - uffs_BlockInfoLoad(dev, bc, page); - tag = &(bc->spares[page].tag); - if (TAG_IS_GOOD(tag) && TAG_PAGE_ID(tag) == page_id) - return page; - } - - return UFFS_INVALID_PAGE; -} - -/** - * Are all the pages in the block used ? - */ -UBOOL uffs_IsBlockPagesFullUsed(uffs_Device *dev, uffs_BlockInfo *bc) -{ - uffs_Tags *tag; - - // if the last page is dirty, then the whole block is full - uffs_BlockInfoLoad(dev, bc, dev->attr->pages_per_block - 1); - tag = GET_TAG(bc, dev->attr->pages_per_block - 1); - - return TAG_IS_GOOD(tag) ? U_TRUE : U_FALSE; -} - -/** - * Is this block used ? - * \param[in] dev uffs device - * \param[in] bc block info - * \retval U_TRUE block is used - * \retval U_FALSE block is free - */ -UBOOL uffs_IsThisBlockUsed(uffs_Device *dev, uffs_BlockInfo *bc) -{ - uffs_Tags *tag; - - // if the first page is dirty, then this block is used. - uffs_BlockInfoLoad(dev, bc, 0); - tag = GET_TAG(bc, 0); - - return TAG_IS_DIRTY(tag) ? U_TRUE : U_FALSE; -} - -/** - * get block time stamp from a exist block - * \param[in] dev uffs device - * \param[in] bc block info - */ -int uffs_GetBlockTimeStamp(uffs_Device *dev, uffs_BlockInfo *bc) -{ - if(uffs_IsThisBlockUsed(dev, bc) == U_FALSE) - return uffs_GetFirstBlockTimeStamp(); - else{ - uffs_BlockInfoLoad(dev, bc, 0); - return TAG_BLOCK_TS(GET_TAG(bc, 0)); - } - -} - -/** - * find first free page from 'pageFrom' - * \param[in] dev uffs device - * \param[in] bc block info - * \param[in] pageFrom search from this page - * \return return first free page number from 'pageFrom' - * \retval UFFS_INVALID_PAGE no free page found - * \retval >=0 the first free page number - */ -u16 uffs_FindFirstFreePage(uffs_Device *dev, - uffs_BlockInfo *bc, u16 pageFrom) -{ - u16 i; - - for (i = pageFrom; i < dev->attr->pages_per_block; i++) { - uffs_BlockInfoLoad(dev, bc, i); - if (uffs_IsPageErased(dev, bc, i) == U_TRUE) - return i; - } - - return UFFS_INVALID_PAGE; //free page not found -} - - -/** - * calculate sum of data, 8bit version - * \param[in] p data pointer - * \param[in] len length of data - * \return return sum of data, 8bit - */ -u8 uffs_MakeSum8(const void *p, int len) -{ - return uffs_crc16sum(p, len) & 0xFF; -} - -/** - * calculate sum of datam, 16bit version - * \param[in] p data pointer - * \param[in] len length of data - * \return return sum of data, 16bit - */ -u16 uffs_MakeSum16(const void *p, int len) -{ - return uffs_crc16sum(p, len); -} - -/** - * create a new file on a free block - * \param[in] dev uffs device - * \param[in] parent parent dir serial num - * \param[in] serial serial num of this new file - * \param[in] bc block information - * \param[in] fi file information - * \note parent, serial, bc must be provided before, - * and all information in fi should be filled well before. - */ -URET uffs_CreateNewFile(uffs_Device *dev, - u16 parent, u16 serial, - uffs_BlockInfo *bc, uffs_FileInfo *fi) -{ - uffs_Tags *tag; - uffs_Buf *buf; - - uffs_BlockInfoLoad(dev, bc, 0); - - tag = GET_TAG(bc, 0); - TAG_PARENT(tag) = parent; - TAG_SERIAL(tag) = serial; - TAG_DATA_LEN(tag) = sizeof(uffs_FileInfo); - - buf = uffs_BufGet(dev, parent, serial, 0); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "get buf fail."); - return U_FAIL; - } - - memcpy(buf->data, fi, TAG_DATA_LEN(tag)); - buf->data_len = TAG_DATA_LEN(tag); - - return uffs_BufPut(dev, buf); -} - - -/** - * \brief calculate data length of a file block - * \param[in] dev uffs device - * \param[in] bc block info - */ -int uffs_GetBlockFileDataLength(uffs_Device *dev, uffs_BlockInfo *bc, u8 type) -{ - u16 page_id; - u16 i; - uffs_Tags *tag; - int size = 0; - u16 page; - u16 lastPage = dev->attr->pages_per_block - 1; - - uffs_BlockInfoLoad(dev, bc, lastPage); - tag = GET_TAG(bc, lastPage); - - if (TAG_IS_GOOD(tag)) { - // First try the last page. - // if it's the full loaded file/data block, then we have a quick path. - if (type == UFFS_TYPE_FILE) { - if (TAG_PAGE_ID(tag) == (lastPage - 1)) { - size = dev->com.pg_data_size * (dev->attr->pages_per_block - 2) + TAG_DATA_LEN(tag); - return size; - } - } - if (type == UFFS_TYPE_DATA) { - if (TAG_PAGE_ID(tag) == lastPage) { - size = dev->com.pg_data_size * (dev->attr->pages_per_block - 1) + TAG_DATA_LEN(tag); - return size; - } - } - } - - // ok, it's not the full loaded file/data block, - // need to read all spares.... - uffs_BlockInfoLoad(dev, bc, UFFS_ALL_PAGES); - tag = GET_TAG(bc, 0); - if (uffs_Assert(TAG_IS_GOOD(tag), "block %d page 0 does not have good tag ?", bc->block)) { - if (TAG_TYPE(tag) == UFFS_TYPE_FILE) { - page_id = 1; //In file header block, file data page_id from 1 - i = 1; //search from page 1 - } - else { - page_id = 0; //in normal file data block, page_id from 0 - i = 0; //in normal file data block, search from page 0 - } - for (; i < dev->attr->pages_per_block; i++) { - tag = GET_TAG(bc, i); - if (TAG_IS_GOOD(tag)) { - if (page_id == TAG_PAGE_ID(tag)) { - page = uffs_FindBestPageInBlock(dev, bc, i); - if (uffs_Assert(page != UFFS_INVALID_PAGE, "got an invalid page ?")) { - size += TAG_DATA_LEN(GET_TAG(bc, page)); - page_id++; - } - } - } - } - } - - return size; -} - -/** - * get free pages number - * \param[in] dev uffs device - * \param[in] bc block info - */ -int uffs_GetFreePagesCount(uffs_Device *dev, uffs_BlockInfo *bc) -{ - int count = 0; - int i; - - // search from the last page ... to first page - for (i = dev->attr->pages_per_block - 1; i >= 0; i--) { - uffs_BlockInfoLoad(dev, bc, i); - if (uffs_IsPageErased(dev, bc, (u16)i) == U_TRUE) { - count++; - } - else { - if (TAG_IS_GOOD(GET_TAG(bc, i))) // it won't be any free page if we see a good tag. - break; - } - } - - return count; -} -/** - * \brief Is the block erased ? - * \param[in] dev uffs device - * \param[in] bc block info - * \param[in] page page number to be check - * \retval U_TRUE block is erased, ready to use - * \retval U_FALSE block is dirty, maybe use by file - */ -UBOOL uffs_IsPageErased(uffs_Device *dev, uffs_BlockInfo *bc, u16 page) -{ - uffs_Tags *tag; - - uffs_BlockInfoLoad(dev, bc, page); - tag = GET_TAG(bc, page); - - if (!TAG_IS_SEALED(tag) && - !TAG_IS_DIRTY(tag) && - !TAG_IS_VALID(tag)) { - return U_TRUE; - } - - return U_FALSE; -} - -/** - * get partition used (bytes) - */ -int uffs_GetDeviceUsed(uffs_Device *dev) -{ - return (dev->par.end - dev->par.start + 1 - - dev->tree.bad_count - dev->tree.erased_count - ) * - dev->attr->page_data_size * - dev->attr->pages_per_block; -} - -/** - * get partition free (bytes) - */ -int uffs_GetDeviceFree(uffs_Device *dev) -{ - return dev->tree.erased_count * - dev->attr->page_data_size * - dev->attr->pages_per_block; -} - -/** - * get partition total size (bytes) - */ -int uffs_GetDeviceTotal(uffs_Device *dev) -{ - return (dev->par.end - dev->par.start + 1) * - dev->attr->page_data_size * - dev->attr->pages_per_block; -} - -/** - * load mini hader from flash - */ -URET uffs_LoadMiniHeader(uffs_Device *dev, - int block, u16 page, struct uffs_MiniHeaderSt *header) -{ - int ret; - struct uffs_FlashOpsSt *ops = dev->ops; - - if (ops->ReadPageWithLayout) { - ret = ops->ReadPageWithLayout(dev, block, page, (u8 *)header, - sizeof(struct uffs_MiniHeaderSt), NULL, NULL, NULL); - } - else { - ret = ops->ReadPage(dev, block, page, (u8 *)header, sizeof(struct uffs_MiniHeaderSt), NULL, NULL, 0); - } - - dev->st.page_header_read_count++; - - return UFFS_FLASH_HAVE_ERR(ret) ? U_FAIL : U_SUCC; -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_tree.c b/components/dfs/filesystems/uffs/src/uffs/uffs_tree.c deleted file mode 100644 index 7e51a9275f..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_tree.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_tree.c - * \brief seting up uffs tree data structure - * \author Ricky Zheng, created 13th May, 2005 - */ - -#include "uffs_config.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_pool.h" -#include "uffs/uffs_flash.h" -#include "uffs/uffs_badblock.h" - -#include - -#define TPOOL(dev) &(dev->mem.tree_pool) - -#define PFX "tree: " - -static void uffs_InsertToFileEntry(uffs_Device *dev, TreeNode *node); -static void uffs_InsertToDirEntry(uffs_Device *dev, TreeNode *node); -static void uffs_InsertToDataEntry(uffs_Device *dev, TreeNode *node); - -static TreeNode * uffs_TreeGetErasedNodeNoCheck(uffs_Device *dev); - - -struct BlockTypeStatSt { - int dir; - int file; - int data; -}; - -/** - * \brief initialize tree buffers - * \param[in] dev uffs device - */ -URET uffs_TreeInit(uffs_Device *dev) -{ - int size; - int num; - uffs_Pool *pool; - int i; - - size = sizeof(TreeNode); - num = dev->par.end - dev->par.start + 1; - - pool = &(dev->mem.tree_pool); - - if (dev->mem.tree_nodes_pool_size == 0) { - if (dev->mem.malloc) { - dev->mem.tree_nodes_pool_buf = dev->mem.malloc(dev, size * num); - if (dev->mem.tree_nodes_pool_buf) - dev->mem.tree_nodes_pool_size = size * num; - } - } - if (size * num > dev->mem.tree_nodes_pool_size) { - uffs_Perror(UFFS_MSG_DEAD, - "Tree buffer require %d but only %d available.", - size * num, dev->mem.tree_nodes_pool_size); - memset(pool, 0, sizeof(uffs_Pool)); - return U_FAIL; - } - uffs_Perror(UFFS_MSG_NOISY, "alloc tree nodes %d bytes.", size * num); - - uffs_PoolInit(pool, dev->mem.tree_nodes_pool_buf, - dev->mem.tree_nodes_pool_size, size, num); - - dev->tree.erased = NULL; - dev->tree.erased_tail = NULL; - dev->tree.erased_count = 0; - dev->tree.bad = NULL; - dev->tree.bad_count = 0; - - for (i = 0; i < DIR_NODE_ENTRY_LEN; i++) { - dev->tree.dir_entry[i] = EMPTY_NODE; - } - - for (i = 0; i < FILE_NODE_ENTRY_LEN; i++) { - dev->tree.file_entry[i] = EMPTY_NODE; - } - - for (i = 0; i < DATA_NODE_ENTRY_LEN; i++) { - dev->tree.data_entry[i] = EMPTY_NODE; - } - - dev->tree.max_serial = ROOT_DIR_SERIAL; - - return U_SUCC; -} -/** - * \brief release tree buffers, call this function when unmount - * \param[in] dev uffs device - */ -URET uffs_TreeRelease(uffs_Device *dev) -{ - uffs_Pool *pool; - - pool = &(dev->mem.tree_pool); - if (pool->mem && dev->mem.free) { - dev->mem.free(dev, pool->mem); - pool->mem = NULL; - dev->mem.tree_nodes_pool_size = 0; - } - uffs_PoolRelease(pool); - memset(pool, 0, sizeof(uffs_Pool)); - - return U_SUCC; -} - -static u16 _GetBlockFromNode(u8 type, TreeNode *node) -{ - switch (type) { - case UFFS_TYPE_DIR: - return node->u.dir.block; - case UFFS_TYPE_FILE: - return node->u.file.block; - case UFFS_TYPE_DATA: - return node->u.data.block; - } - uffs_Perror(UFFS_MSG_SERIOUS, "unkown type, X-block"); - return UFFS_INVALID_BLOCK; -} - -#if 0 -static u16 _GetParentFromNode(u8 type, TreeNode *node) -{ - switch (type) { - case UFFS_TYPE_DIR: - return node->u.dir.parent; - case UFFS_TYPE_FILE: - return node->u.file.parent; - case UFFS_TYPE_DATA: - return node->u.data.parent; - } - uffs_Perror(UFFS_MSG_SERIOUS, "unkown type, X-parent"); - return INVALID_UFFS_SERIAL; -} - - -static u16 _GetSerialFromNode(u8 type, TreeNode *node) -{ - switch (type) { - case UFFS_TYPE_DIR: - return node->u.dir.serial; - case UFFS_TYPE_FILE: - return node->u.file.serial; - case UFFS_TYPE_DATA: - return node->u.data.serial; - } - uffs_Perror(UFFS_MSG_SERIOUS, "unkown type, X-serial"); - return INVALID_UFFS_SERIAL; -} -#endif - -/** - * insert a TreeNode *node to tree - * \param[in] dev uffs device - * \param[in] type type of node - * \param[in] node node to be insert to - */ -void uffs_InsertNodeToTree(uffs_Device *dev, u8 type, TreeNode *node) -{ - switch (type) { - case UFFS_TYPE_DIR: - uffs_InsertToDirEntry(dev, node); - break; - case UFFS_TYPE_FILE: - uffs_InsertToFileEntry(dev, node); - break; - case UFFS_TYPE_DATA: - uffs_InsertToDataEntry(dev, node); - break; - default: - uffs_Perror(UFFS_MSG_SERIOUS, - "unkown type, can't insert to tree"); - break; - } -} - -/** - * find a node from tree - * \param[in] dev uffs device - * \param[in] type type of node - * \param[in] parent parent serial num - * \param[in] serial serial num - */ -TreeNode * uffs_FindFromTree(uffs_Device *dev, - u8 type, u16 parent, u16 serial) -{ - switch (type) { - case UFFS_TYPE_DIR: - return uffs_TreeFindDirNode(dev, serial); - case UFFS_TYPE_FILE: - return uffs_TreeFindFileNode(dev, serial); - case UFFS_TYPE_DATA: - return uffs_TreeFindDataNode(dev, parent, serial); - } - uffs_Perror(UFFS_MSG_SERIOUS, - "unkown type, can't find node"); - return NULL; -} - - - -static URET _BuildValidTreeNode(uffs_Device *dev, - TreeNode *node, //!< empty node - uffs_BlockInfo *bc, - struct BlockTypeStatSt *st) -{ - uffs_Tags *tag; - TreeNode *node_alt; - u16 block, parent, serial, block_alt, block_save; - uffs_BlockInfo *bc_alt; - u8 type; - int page; - UBOOL needToInsertToTree = U_FALSE; - uffs_Buf *buf = NULL; - uffs_FileInfo *info; - u16 data_sum = 0; - - // check the first page on the block ... - uffs_BlockInfoLoad(dev, bc, 0); - - tag = GET_TAG(bc, 0); //get first page's tag - - if (!TAG_IS_DIRTY(tag)) { - // should never go here ... unless mark dirty page failed ? - uffs_Perror(UFFS_MSG_NORMAL, - "First page is clean in a non-erased block ?"); - return U_FAIL; - } - - if (!TAG_IS_VALID(tag)) { - //first page is invalid ? should be erased now! - uffs_Perror(UFFS_MSG_NORMAL, - "first page in block %d is invalid, will be erased now!", - bc->block); - goto process_invalid_block; - } - - block = bc->block; - parent = TAG_PARENT(tag); - serial = TAG_SERIAL(tag); - type = TAG_TYPE(tag); - - // check if there is an 'alternative block' - // (node which has the same serial number) in tree ? - node_alt = uffs_FindFromTree(dev, type, parent, serial); - - if (node_alt != NULL) { - //find a alternate node ! need to check the timestamp ! - - block_alt = _GetBlockFromNode(type, node_alt); - - uffs_Perror(UFFS_MSG_NORMAL, - "Process unclean block (%d vs %d)", block, block_alt); - - if (block_alt == INVALID_UFFS_SERIAL) { - uffs_Perror(UFFS_MSG_SERIOUS, "invalid block ?"); - return U_FAIL; - } - - bc_alt = uffs_BlockInfoGet(dev, block_alt); - if (bc_alt == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get block info "); - return U_FAIL; - } - uffs_BlockInfoLoad(dev, bc_alt, 0); - if (uffs_IsSrcNewerThanObj ( - TAG_BLOCK_TS(tag), - TAG_BLOCK_TS(GET_TAG(bc_alt, 0))) == U_TRUE) { - - //the node is newer than node_alt, so keep node_alt, and erase node - uffs_FlashEraseBlock(dev, block); - node->u.list.block = block; - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, node); - else - uffs_TreeInsertToErasedListTail(dev, node); - - uffs_BlockInfoPut(dev, bc_alt); //put back bc_alt before we return. - return U_SUCC; - } - else { - //the node is older than node_alt, so keep node, and erase node_alt - //we use node as erased node to insert to erased list - - block_save = _GetBlockFromNode(type, node_alt); - uffs_FlashEraseBlock(dev, block_save); - node->u.list.block = block_save; - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, node); - else - uffs_TreeInsertToErasedListTail(dev, node); - - //put back bc_alt because we don't need it anymore. - uffs_BlockInfoPut(dev, bc_alt); - - //use node_alt to store new informations in following - node = node_alt; - - needToInsertToTree = U_FALSE; - } - } - else { - needToInsertToTree = U_TRUE; - } - - if (type == UFFS_TYPE_DIR || type == UFFS_TYPE_FILE) { - buf = uffs_BufClone(dev, NULL); - if (buf == NULL) - return U_FAIL; - uffs_BlockInfoLoad(dev, bc, UFFS_ALL_PAGES); - page = uffs_FindPageInBlockWithPageId(dev, bc, 0); - if (page == UFFS_INVALID_PAGE) { - uffs_BufFreeClone(dev, buf); - uffs_Perror(UFFS_MSG_SERIOUS, - "Can't find any valid page for page_id=0 ? invalid block !" - "this might be caused by the tag layout change.\n"); - goto process_invalid_block; - } - page = uffs_FindBestPageInBlock(dev, bc, page); - uffs_FlashReadPage(dev, block, page, buf, U_FALSE); - info = (uffs_FileInfo *) (buf->data); - data_sum = uffs_MakeSum16(info->name, info->name_len); - uffs_BufFreeClone(dev, buf); - } - - switch (type) { - case UFFS_TYPE_DIR: - node->u.dir.block = bc->block; - node->u.dir.checksum = data_sum; - node->u.dir.parent = TAG_PARENT(tag); - node->u.dir.serial = TAG_SERIAL(tag); - st->dir++; - break; - case UFFS_TYPE_FILE: - node->u.file.block = bc->block; - node->u.file.checksum = data_sum; - node->u.file.parent = TAG_PARENT(tag); - node->u.file.serial = TAG_SERIAL(tag); - node->u.file.len = uffs_GetBlockFileDataLength(dev, bc, UFFS_TYPE_FILE); - st->file++; - break; - case UFFS_TYPE_DATA: - node->u.data.block = bc->block; - node->u.data.parent = TAG_PARENT(tag); - node->u.data.serial = TAG_SERIAL(tag); - node->u.data.len = uffs_GetBlockFileDataLength(dev, bc, UFFS_TYPE_DATA); - st->data++; - break; - } - - if (needToInsertToTree == U_TRUE) { - uffs_InsertNodeToTree(dev, type, node); - } - - return U_SUCC; - -process_invalid_block: - /* erase the invalid block */ - uffs_FlashEraseBlock(dev, bc->block); - - node->u.list.block = bc->block; - - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, node); - else - uffs_TreeInsertToErasedListTail(dev, node); - - return U_SUCC; -} - - -static URET _ScanAndFixUnCleanPage(uffs_Device *dev, uffs_BlockInfo *bc) -{ - int page; - uffs_Tags *tag; - struct uffs_MiniHeaderSt header; - - /* in most case, the valid block contents fewer free page, - so it's better scan from the last page ... to page 1. - note: scanning page 0 is not necessary, will check it later. - - The worse case: read (pages_per_block - 1) * (mini header + spares) ! - most case: read one spare. - */ - for (page = dev->attr->pages_per_block - 1; page > 0; page--) { - uffs_BlockInfoLoad(dev, bc, page); - tag = GET_TAG(bc, page); - - if (TAG_IS_SEALED(tag)) - break; // tag sealed, no unclean page in this block. - - if (TAG_IS_DIRTY(tag) || TAG_IS_VALID(tag)) { // tag not sealed but dirty/valid ? - uffs_Perror(UFFS_MSG_NORMAL, - "unclean page found, block %d page %d", - bc->block, page); - - // ok, an unclean page found. - // This unclean page can be identified by tag. - // We can leave it as it is, but performing a block recover would be good ? - // There won't be another unclean page in this block ... stop here. - break; - } - - // now we have a clean tag (all 0xFF ?). Need to check mini header to see if it's an unclean page. - if (uffs_LoadMiniHeader(dev, bc->block, page, &header) == U_FAIL) - return U_FAIL; - - if (header.status != 0xFF) { - // page data is dirty? this is an unclean page and we should explicitly mark tag as 'dirty and invalid'. - // This writing does not violate "no partial program" claim, because we are writing to a clean page spare. - uffs_Perror(UFFS_MSG_NORMAL, - "unclean page found, block %d page %d, mark it.", - bc->block, page); - uffs_FlashMarkDirtyPage(dev, bc, page); - } - } - - return U_SUCC; -} - - -static URET _BuildTreeStepOne(uffs_Device *dev) -{ - int block_lt; - uffs_BlockInfo *bc = NULL; - TreeNode *node; - struct uffs_TreeSt *tree; - uffs_Pool *pool; - struct uffs_MiniHeaderSt header; - URET ret = U_SUCC; - struct BlockTypeStatSt st = {0, 0, 0}; - - tree = &(dev->tree); - pool = TPOOL(dev); - - tree->bad = NULL; - tree->bad_count = 0; - tree->erased = NULL; - tree->erased_tail = NULL; - tree->erased_count = 0; - - uffs_Perror(UFFS_MSG_NOISY, "build tree step one"); - -// printf("s:%d e:%d\n", dev->par.start, dev->par.end); - for (block_lt = dev->par.start; block_lt <= dev->par.end; block_lt++) { - bc = uffs_BlockInfoGet(dev, block_lt); - if (bc == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "step one:fail to get block info"); - ret = U_FAIL; - break; - } - node = (TreeNode *)uffs_PoolGet(pool); - if (node == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "insufficient tree node!"); - ret = U_FAIL; - break; - } - - // Need to check bad block at first ! - if (uffs_FlashIsBadBlock(dev, block_lt) == U_TRUE) { - node->u.list.block = block_lt; - uffs_TreeInsertToBadBlockList(dev, node); - uffs_Perror(UFFS_MSG_NORMAL, "found bad block %d", block_lt); - } - else if (uffs_IsPageErased(dev, bc, 0) == U_TRUE) { //@ read one spare: 0 - // page 0 tag shows it's an erased block, we need to check the mini header status to make sure it is clean. - if (uffs_LoadMiniHeader(dev, block_lt, 0, &header) == U_FAIL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "I/O error when reading mini header !" - "block %d page %d", - block_lt, 0); - ret = U_FAIL; - break; - } - - if (header.status != 0xFF) { - // page 0 tag is clean but page data is dirty ??? - // this block should be erased immediately ! - uffs_FlashEraseBlock(dev, block_lt); - } - node->u.list.block = block_lt; - if (HAVE_BADBLOCK(dev)) { - uffs_Perror(UFFS_MSG_NORMAL, - "New bad block (%d) discovered.", block_lt); - uffs_BadBlockProcess(dev, node); - } - else { - // page 0 is clean does not means all pages in this block are clean, - // need to check this block later before use it. - uffs_TreeInsertToErasedListTailEx(dev, node, 1); - } - } - else { - - // this block have valid data page(s). - - ret = _ScanAndFixUnCleanPage(dev, bc); - if (ret == U_FAIL) - break; - - ret = _BuildValidTreeNode(dev, node, bc, &st); - if (ret == U_FAIL) - break; - - } - uffs_BlockInfoPut(dev, bc); - } //end of for - - if(ret == U_FAIL) - uffs_BlockInfoPut(dev, bc); - - uffs_Perror(UFFS_MSG_NORMAL, - "DIR %d, FILE %d, DATA %d", st.dir, st.file, st.data); - - return ret; -} - -static URET _BuildTreeStepTwo(uffs_Device *dev) -{ - //Randomise the start point of erased block to implement wear levelling - u32 startCount = 0; - u32 endPoint; - TreeNode *node; - - uffs_Perror(UFFS_MSG_NOISY, "build tree step two"); - - endPoint = uffs_GetCurDateTime() % (dev->tree.erased_count + 1); - while (startCount < endPoint) { - node = uffs_TreeGetErasedNodeNoCheck(dev); - if (node == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "No erased block ?"); - return U_FAIL; - } - uffs_TreeInsertToErasedListTailEx(dev, node, -1); - startCount++; - } - - return U_SUCC; -} - -TreeNode * uffs_TreeFindFileNode(uffs_Device *dev, u16 serial) -{ - int hash; - u16 x; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - - hash = serial & FILE_NODE_HASH_MASK; - x = tree->file_entry[hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.file.serial == serial) { - return node; - } - else { - x = node->hash_next; - } - } - return NULL; -} - -/** add a node into suspend list */ -void uffs_TreeSuspendAdd(uffs_Device *dev, TreeNode *node) -{ - node->u.list.next = dev->tree.suspend; - node->u.list.prev = NULL; - - if (dev->tree.suspend) - dev->tree.suspend->u.list.prev = node; - dev->tree.suspend = node; -} - -/** search suspend list */ -TreeNode * uffs_TreeFindSuspendNode(uffs_Device *dev, u16 serial) -{ - TreeNode *node = dev->tree.suspend; - while (node) { - if (node->u.list.u.serial == serial) - break; - - node = node->u.list.next; - } - - return node; -} - -/** remove a node from suspend list */ -void uffs_TreeRemoveSuspendNode(uffs_Device *dev, TreeNode *node) -{ - if (node->u.list.prev) - node->u.list.prev->u.list.next = node->u.list.next; - if (node->u.list.next) - node->u.list.next->u.list.prev = node->u.list.prev; - if (node == dev->tree.suspend) - dev->tree.suspend = NULL; -} - -TreeNode * uffs_TreeFindFileNodeWithParent(uffs_Device *dev, u16 parent) -{ - int hash; - u16 x; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - - for (hash = 0; hash < FILE_NODE_ENTRY_LEN; hash++) { - x = tree->file_entry[hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.file.parent == parent) { - return node; - } - else { - x = node->hash_next; - } - } - } - - return NULL; -} - -TreeNode * uffs_TreeFindDirNode(uffs_Device *dev, u16 serial) -{ - int hash; - u16 x; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - - hash = serial & DIR_NODE_HASH_MASK; - x = tree->dir_entry[hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.dir.serial == serial) { - return node; - } - else { - x = node->hash_next; - } - } - return NULL; -} - -TreeNode * uffs_TreeFindDirNodeWithParent(uffs_Device *dev, u16 parent) -{ - int hash; - u16 x; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - - for (hash = 0; hash < DIR_NODE_ENTRY_LEN; hash++) { - x = tree->dir_entry[hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.dir.parent == parent) { - return node; - } - else { - x = node->hash_next; - } - } - } - - return NULL; -} - -TreeNode * uffs_TreeFindFileNodeByName(uffs_Device *dev, - const char *name, - u32 len, - u16 sum, u16 parent) -{ - int i; - u16 x; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - - for (i = 0; i < FILE_NODE_ENTRY_LEN; i++) { - x = tree->file_entry[i]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.file.checksum == sum && node->u.file.parent == parent) { - //read file name from flash, and compare... - if (uffs_TreeCompareFileName(dev, name, len, sum, - node, UFFS_TYPE_FILE) == U_TRUE) { - //Got it! - return node; - } - } - x = node->hash_next; - } - } - - return NULL; -} - -TreeNode * uffs_TreeFindDataNode(uffs_Device *dev, u16 parent, u16 serial) -{ - int hash; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - u16 x; - - hash = GET_DATA_HASH(parent, serial); - x = tree->data_entry[hash]; - while(x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - - if(node->u.data.parent == parent && - node->u.data.serial == serial) - return node; - - x = node->hash_next; - } - - return NULL; -} - -TreeNode * uffs_TreeFindDirNodeByBlock(uffs_Device *dev, u16 block) -{ - int hash; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - u16 x; - - for (hash = 0; hash < DIR_NODE_ENTRY_LEN; hash++) { - x = tree->dir_entry[hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.dir.block == block) - return node; - x = node->hash_next; - } - } - - return NULL; -} - -TreeNode * uffs_TreeFindErasedNodeByBlock(uffs_Device *dev, u16 block) -{ - TreeNode *node; - node = dev->tree.erased; - - while (node) { - if (node->u.list.block == block) - return node; - node = node->u.list.next; - } - - return NULL; -} - -TreeNode * uffs_TreeFindBadNodeByBlock(uffs_Device *dev, u16 block) -{ - TreeNode *node; - node = dev->tree.bad; - - while (node) { - if (node->u.list.block == block) - return node; - node = node->u.list.next; - } - - return NULL; -} - -TreeNode * uffs_TreeFindFileNodeByBlock(uffs_Device *dev, u16 block) -{ - int hash; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - u16 x; - - for (hash = 0; hash < FILE_NODE_ENTRY_LEN; hash++) { - x = tree->file_entry[hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.file.block == block) - return node; - x = node->hash_next; - } - } - - return NULL; -} - -TreeNode * uffs_TreeFindDataNodeByBlock(uffs_Device *dev, u16 block) -{ - int hash; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - u16 x; - - for (hash = 0; hash < DATA_NODE_ENTRY_LEN; hash++) { - x = tree->data_entry[hash]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.data.block == block) - return node; - x = node->hash_next; - } - } - - return NULL; -} - -TreeNode * uffs_TreeFindNodeByBlock(uffs_Device *dev, u16 block, int *region) -{ - TreeNode *node = NULL; - - if (*region & SEARCH_REGION_DATA) { - node = uffs_TreeFindDataNodeByBlock(dev, block); - if (node) { - *region &= SEARCH_REGION_DATA; - return node; - } - } - if (*region & SEARCH_REGION_FILE) { - node = uffs_TreeFindFileNodeByBlock(dev, block); - if (node) { - *region &= SEARCH_REGION_FILE; - return node; - } - } - if (*region & SEARCH_REGION_DIR) { - node = uffs_TreeFindDirNodeByBlock(dev, block); - if (node) { - *region &= SEARCH_REGION_DIR; - return node; - } - } - if (*region & SEARCH_REGION_ERASED) { - node = uffs_TreeFindErasedNodeByBlock(dev, block); - if (node) { - *region &= SEARCH_REGION_ERASED; - return node; - } - } - if (*region & SEARCH_REGION_BAD) { - node = uffs_TreeFindBadNodeByBlock(dev, block); - if (node) { - *region &= SEARCH_REGION_BAD; - return node; - } - } - - return node; -} - -TreeNode * uffs_TreeFindDirNodeByName(uffs_Device *dev, - const char *name, u32 len, - u16 sum, u16 parent) -{ - int i; - u16 x; - TreeNode *node; - struct uffs_TreeSt *tree = &(dev->tree); - - for (i = 0; i < DIR_NODE_ENTRY_LEN; i++) { - x = tree->dir_entry[i]; - while (x != EMPTY_NODE) { - node = FROM_IDX(x, TPOOL(dev)); - if (node->u.dir.checksum == sum && - node->u.dir.parent == parent) { - //read file name from flash, and compare... - if (uffs_TreeCompareFileName(dev, name, len, sum, - node, UFFS_TYPE_DIR) == U_TRUE) { - //Got it! - return node; - } - } - x = node->hash_next; - } - } - - return NULL; - -} - -UBOOL uffs_CompareFileName(const char *src, int src_len, const char *des) -{ - while (src_len-- > 0) { - if(*src++ != *des++) - return U_FALSE; - } - - return U_TRUE; -} - -/** compare [name] with tree [node] represented object name by loading - uffs_FileInfo from storage */ -UBOOL uffs_TreeCompareFileName(uffs_Device *dev, - const char *name, u32 len, u16 sum, - TreeNode *node, int type) -{ - UBOOL matched = U_FALSE; - uffs_FileInfo *fi; - uffs_Buf *buf; - u16 data_sum; - - buf = uffs_BufGetEx(dev, type, node, 0, 0); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, "can't get buf !\n "); - goto ext; - } - fi = (uffs_FileInfo *)(buf->data); - data_sum = uffs_MakeSum16(fi->name, fi->name_len); - - if (data_sum != sum) { - uffs_Perror(UFFS_MSG_NORMAL, - "the obj's sum in storage is different with given sum!"); - goto ext; - } - - if (fi->name_len == len) { - if(uffs_CompareFileName(fi->name, fi->name_len, name) == U_TRUE) { - matched = U_TRUE; - } - } -ext: - if (buf) - uffs_BufPut(dev, buf); - - return matched; -} - - -/* calculate file length, etc */ -static URET _BuildTreeStepThree(uffs_Device *dev) -{ - int i; - u16 x; - TreeNode *work; - TreeNode *node; - struct uffs_TreeSt *tree; - uffs_Pool *pool; - u16 blockSave; - - TreeNode *cache = NULL; - u16 cacheSerial = INVALID_UFFS_SERIAL; - - tree = &(dev->tree); - pool = TPOOL(dev); - - uffs_Perror(UFFS_MSG_NOISY, "build tree step three"); - - for (i = 0; i < DATA_NODE_ENTRY_LEN; i++) { - x = tree->data_entry[i]; - while (x != EMPTY_NODE) { - work = FROM_IDX(x, pool); - if (work->u.data.parent == cacheSerial) { - node = cache; - } - else { - node = uffs_TreeFindFileNode(dev, work->u.data.parent); - cache = node; - cacheSerial = work->u.data.parent; - } - if (node == NULL) { - x = work->hash_next; - //this data block does not belong to any file ? - //should be erased. - uffs_Perror(UFFS_MSG_NORMAL, - "find a orphan data block:%d, " - "parent:%d, serial:%d, will be erased!", - work->u.data.block, - work->u.data.parent, work->u.data.serial); - - uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, work); - blockSave = work->u.data.block; - work->u.list.block = blockSave; - uffs_FlashEraseBlock(dev, blockSave); - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, work); - else - uffs_TreeInsertToErasedListTail(dev, work); - } - else { - node->u.file.len += work->u.data.len; - x = work->hash_next; - } - } - } - - return U_SUCC; -} - -/** - * \brief build tree structure from flash - * \param[in] dev uffs device - */ -URET uffs_BuildTree(uffs_Device *dev) -{ - URET ret; - - /***** step one: scan all page spares, classify DIR/FILE/DATA nodes, - check bad blocks/uncompleted(conflicted) blocks as well *****/ - - /* if the disk is big and full filled of data this step could be - the most time consuming .... */ - - ret = _BuildTreeStepOne(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "build tree step one fail!"); - return ret; - } - - /***** step two: randomize the erased blocks, for ware-leveling purpose *****/ - /* this step is very fast :) */ - ret = _BuildTreeStepTwo(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "build tree step two fail!"); - return ret; - } - - /***** step three: check DATA nodes, find orphan nodes and erase them *****/ - /* if there are a lot of files and disk is fully filled, this step - could be very time consuming ... */ - ret = _BuildTreeStepThree(dev); - if (ret != U_SUCC) { - uffs_Perror(UFFS_MSG_SERIOUS, "build tree step three fail!"); - return ret; - } - - return U_SUCC; -} - -/** - * find a free file or dir serial NO - * \param[in] dev uffs device - * \return if no free serial found, return #INVALID_UFFS_SERIAL - */ -u16 uffs_FindFreeFsnSerial(uffs_Device *dev) -{ - u16 i; - TreeNode *node; - - //TODO!! Do we need a faster serial number generating method? - // it depends on how often creating files or directories - - for (i = ROOT_DIR_SERIAL + 1; i < MAX_UFFS_FSN; i++) { - node = uffs_TreeFindDirNode(dev, i); - if (node == NULL) { - node = uffs_TreeFindFileNode(dev, i); - if (node == NULL) { - node = uffs_TreeFindSuspendNode(dev, i); - if (node == NULL) - return i; - } - } - } - - return INVALID_UFFS_SERIAL; -} - -static TreeNode * uffs_TreeGetErasedNodeNoCheck(uffs_Device *dev) -{ - TreeNode *node = NULL; - if (dev->tree.erased) { - node = dev->tree.erased; - dev->tree.erased->u.list.prev = NULL; - dev->tree.erased = dev->tree.erased->u.list.next; - if(dev->tree.erased == NULL) - dev->tree.erased_tail = NULL; - dev->tree.erased_count--; - } - - return node; -} - -TreeNode * uffs_TreeGetErasedNode(uffs_Device *dev) -{ - TreeNode *node = uffs_TreeGetErasedNodeNoCheck(dev); - u16 block; - - if (node && node->u.list.u.need_check) { - block = node->u.list.block; - if (uffs_FlashCheckErasedBlock(dev, block) != U_SUCC) { - // Hmm, this block is not fully erased ? erase it immediately. - uffs_FlashEraseBlock(dev, block); - node->u.list.u.need_check = 0; - } - } - return node; -} - -static void _InsertToEntry(uffs_Device *dev, u16 *entry, - int hash, TreeNode *node) -{ - node->hash_next = entry[hash]; - node->hash_prev = EMPTY_NODE; - if (entry[hash] != EMPTY_NODE) { - FROM_IDX(entry[hash], TPOOL(dev))->hash_prev = TO_IDX(node, TPOOL(dev)); - } - entry[hash] = TO_IDX(node, TPOOL(dev)); -} - - -/** - * break the node from entry - */ -void uffs_BreakFromEntry(uffs_Device *dev, u8 type, TreeNode *node) -{ - u16 *entry; - int hash; - TreeNode *work; - - switch (type) { - case UFFS_TYPE_DIR: - hash = GET_DIR_HASH(node->u.dir.serial); - entry = &(dev->tree.dir_entry[hash]); - break; - case UFFS_TYPE_FILE: - hash = GET_FILE_HASH(node->u.file.serial); - entry = &(dev->tree.file_entry[hash]); - break; - case UFFS_TYPE_DATA: - hash = GET_DATA_HASH(node->u.data.parent, node->u.data.serial); - entry = &(dev->tree.data_entry[hash]); - break; - default: - uffs_Perror(UFFS_MSG_SERIOUS, "unknown type when break..."); - return; - } - - if (node->hash_prev != EMPTY_NODE) { - work = FROM_IDX(node->hash_prev, &(dev->mem.tree_pool)); - work->hash_next = node->hash_next; - } - if (node->hash_next != EMPTY_NODE) { - work = FROM_IDX(node->hash_next, &(dev->mem.tree_pool)); - work->hash_prev = node->hash_prev; - } - - if (*entry == TO_IDX(node, &(dev->mem.tree_pool))) { - *entry = node->hash_next; - } -} - -static void uffs_InsertToFileEntry(uffs_Device *dev, TreeNode *node) -{ - _InsertToEntry(dev, dev->tree.file_entry, - GET_FILE_HASH(node->u.file.serial), - node); -} - -static void uffs_InsertToDirEntry(uffs_Device *dev, TreeNode *node) -{ - _InsertToEntry(dev, dev->tree.dir_entry, - GET_DIR_HASH(node->u.dir.serial), - node); -} - -static void uffs_InsertToDataEntry(uffs_Device *dev, TreeNode *node) -{ - _InsertToEntry(dev, dev->tree.data_entry, - GET_DATA_HASH(node->u.data.parent, node->u.data.serial), - node); -} - -void uffs_InsertToErasedListHead(uffs_Device *dev, TreeNode *node) -{ - struct uffs_TreeSt *tree; - tree = &(dev->tree); - - node->u.list.next = tree->erased; - node->u.list.prev = NULL; - - if (tree->erased) { - tree->erased->u.list.prev = node; - } - - tree->erased = node; - if (node->u.list.next == tree->erased_tail) { - tree->erased_tail = node; - } - tree->erased_count++; -} - -/** - * insert node to erased list. - * \param need_check: 0 - no need to check later - * 1 - need to check later - * < 0 - keep 'node->u.list.need_check' value - */ -void uffs_TreeInsertToErasedListTailEx(uffs_Device *dev, TreeNode *node, int need_check) -{ - struct uffs_TreeSt *tree; - tree = &(dev->tree); - - if (need_check >= 0) - node->u.list.u.need_check = need_check; - - node->u.list.next = NULL; - node->u.list.prev = tree->erased_tail; - if (tree->erased_tail) { - tree->erased_tail->u.list.next = node; - } - - tree->erased_tail = node; - if(tree->erased == NULL) { - tree->erased = node; - } - tree->erased_count++; -} - -void uffs_TreeInsertToErasedListTail(uffs_Device *dev, TreeNode *node) -{ - // this function is called after the block is erased, so don't need to check. - uffs_TreeInsertToErasedListTailEx(dev, node, 0); -} - -void uffs_TreeInsertToBadBlockList(uffs_Device *dev, TreeNode *node) -{ - struct uffs_TreeSt *tree; - - tree = &(dev->tree); - node->u.list.prev = NULL; - node->u.list.next = tree->bad; - - if (tree->bad) { - tree->bad->u.list.prev = node; - } - - tree->bad = node; - tree->bad_count++; -} - -/** - * set tree node block value - */ -void uffs_TreeSetNodeBlock(u8 type, TreeNode *node, u16 block) -{ - switch (type) { - case UFFS_TYPE_FILE: - node->u.file.block = block; - break; - case UFFS_TYPE_DIR: - node->u.dir.block = block; - break; - case UFFS_TYPE_DATA: - node->u.data.block = block; - break; - } -} - diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_utils.c b/components/dfs/filesystems/uffs/src/uffs/uffs_utils.c deleted file mode 100644 index bf3ea3b6d1..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_utils.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_utils.c - * \brief utilities of uffs - * \author Ricky Zheng, created 12th May, 2005 - */ -#include "uffs_config.h" -#include "uffs/uffs_device.h" -#include "uffs/uffs_utils.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_version.h" -#include "uffs/uffs_badblock.h" -#include "uffs/uffs_fd.h" -#include "uffs/uffs_fs.h" - -#include -#include - -#define PFX "util: " - -#define SPOOL(dev) &((dev)->mem.spare_pool) - -#ifdef CONFIG_USE_GLOBAL_FS_LOCK -static OSSEM _global_lock = OSSEM_NOT_INITED; - -/* global file system lock */ -void uffs_InitGlobalFsLock(void) -{ - uffs_SemCreate(&_global_lock); -} - -void uffs_ReleaseGlobalFsLock(void) -{ - uffs_SemDelete(&_global_lock); -} - -void uffs_GlobalFsLockLock(void) -{ - uffs_SemWait(_global_lock); -} - -void uffs_GlobalFsLockUnlock(void) -{ - uffs_SemSignal(_global_lock); -} - -#else - -void uffs_InitGlobalFsLock(void) {} -void uffs_ReleaseGlobalFsLock(void) {} -void uffs_GlobalFsLockLock(void) {} -void uffs_GlobalFsLockUnlock(void) {} - -#endif - - -#ifdef CONFIG_ENABLE_BAD_BLOCK_VERIFY -static void _ForceFormatAndCheckBlock(uffs_Device *dev, int block) -{ - int i, j; - uffs_Buf *buf = NULL; - UBOOL bad = U_TRUE; - URET ret; - struct uffs_FlashOpsSt *ops = dev->ops; - struct uffs_TagStoreSt ts; - u8 *spare = NULL; - - buf = uffs_BufClone(dev, NULL); - if (buf == NULL) { - uffs_Perror(UFFS_MSG_SERIOUS, - "Alloc page buffer fail ! Format stoped."); - goto ext; - } - - spare = (u8 *)uffs_PoolGet(SPOOL(dev)); - if (spare == NULL) - goto ext; - - //step 1: Erase, fully fill with 0x0, and check - ret = uffs_FlashEraseBlock(dev, block); - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - goto bad_out; - - memset(buf->header, 0, dev->com.pg_size); - memset(&ts, 0, sizeof(ts)); - memset(spare, 0, dev->attr->spare_size); - - for (i = 0; i < dev->attr->pages_per_block; i++) { - if (ops->WritePageWithLayout) - ret = ops->WritePageWithLayout(dev, block, i, buf->header, dev->com.pg_size, NULL, &ts); - else - ret = ops->WritePage(dev, block, i, buf->header, dev->com.pg_size, spare, dev->attr->spare_size); - - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - goto bad_out; - } - for (i = 0; i < dev->attr->pages_per_block; i++) { - memset(buf->header, 0xFF, dev->com.pg_size); - memset(&ts, 0xFF, sizeof(ts)); - memset(spare, 0xFF, dev->attr->spare_size); - - if (ops->ReadPageWithLayout) { - ret = ops->ReadPageWithLayout(dev, block, i, buf->header, dev->com.pg_size, NULL, &ts, NULL); - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - goto bad_out; - for (j = 0; j < dev->com.pg_size; j++) - if (buf->header[j] != 0) - goto bad_out; - for (j = 0; j < sizeof(ts); j++) - if (((u8 *)&ts)[j] != 0) - goto bad_out; - } - else { - ret = ops->ReadPage(dev, block, i, buf->header, dev->com.pg_size, NULL, spare, dev->attr->spare_size); - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - goto bad_out; - for (j = 0; j < dev->com.pg_size; j++) - if (buf->header[j] != 0) - goto bad_out; - for (j = 0; j < dev->attr->spare_size; j++) - if (spare[j] != 0) - goto bad_out; - } - } - - //step 2: Erase, and check - ret = uffs_FlashEraseBlock(dev, block); - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - goto bad_out; - - for (i = 0; i < dev->attr->pages_per_block; i++) { - memset(buf->header, 0, dev->com.pg_size); - memset(&ts, 0, sizeof(ts)); - memset(spare, 0, dev->attr->spare_size); - - if (ops->ReadPageWithLayout) { - ret = ops->ReadPageWithLayout(dev, block, i, buf->header, dev->com.pg_size, NULL, &ts, NULL); - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - goto bad_out; - for (j = 0; j < dev->com.pg_size; j++) - if (buf->header[j] != 0xFF) - goto bad_out; - for (j = 0; j < sizeof(ts); j++) - if (((u8 *)&ts)[j] != 0xFF) - goto bad_out; - } - else { - ret = ops->ReadPage(dev, block, i, buf->header, dev->com.pg_size, NULL, spare, dev->attr->spare_size); - if (UFFS_FLASH_IS_BAD_BLOCK(ret)) - goto bad_out; - for (j = 0; j < dev->com.pg_size; j++) - if (buf->header[j] != 0xFF) - goto bad_out; - for (j = 0; j < dev->attr->spare_size; j++) - if (spare[j] != 0xFF) - goto bad_out; - } - } - - // format succ - bad = U_FALSE; - -bad_out: - if (bad == U_TRUE) - uffs_FlashMarkBadBlock(dev, block); -ext: - if (buf) - uffs_BufFreeClone(dev, buf); - - if (spare) - uffs_PoolPut(SPOOL(dev), spare); - - return; -} -#endif - - - -URET uffs_FormatDevice(uffs_Device *dev, UBOOL force) -{ - u16 i, slot; - URET ret = U_SUCC; - - if (dev == NULL) - return U_FAIL; - - if (dev->ops == NULL) - return U_FAIL; - - uffs_GlobalFsLockLock(); - - ret = uffs_BufFlushAll(dev); - - if (dev->ref_count > 1 && !force) { - uffs_Perror(UFFS_MSG_NORMAL, - "can't format when dev->ref_count = %d", - dev->ref_count); - ret = U_FAIL; - } - - if (ret == U_SUCC && force) { - uffs_DirEntryBufPutAll(dev); - uffs_PutAllObjectBuf(dev); - uffs_FdSignatureIncrease(); - } - - if (ret == U_SUCC && - uffs_BufIsAllFree(dev) == U_FALSE && - !force) - { - uffs_Perror(UFFS_MSG_NORMAL, "some page still in used!"); - ret = U_FAIL; - } - - if (!force) { - for (slot = 0; ret == U_SUCC && slot < dev->cfg.dirty_groups; slot++) { - if (dev->buf.dirtyGroup[slot].count > 0) { - uffs_Perror(UFFS_MSG_SERIOUS, "there still have dirty pages!"); - ret = U_FAIL; - } - } - } - - if (ret == U_SUCC) - uffs_BufSetAllEmpty(dev); - - - if (ret == U_SUCC && uffs_BlockInfoIsAllFree(dev) == U_FALSE && !force) { - uffs_Perror(UFFS_MSG_NORMAL, - "there still have block info cache ? fail to format"); - ret = U_FAIL; - } - - if (ret == U_SUCC) - uffs_BlockInfoExpireAll(dev); - - for (i = dev->par.start; ret == U_SUCC && i <= dev->par.end; i++) { - if (uffs_FlashIsBadBlock(dev, i) == U_FALSE) { - uffs_FlashEraseBlock(dev, i); - if (HAVE_BADBLOCK(dev)) - uffs_BadBlockProcess(dev, NULL); - } - else { -#ifdef CONFIG_ENABLE_BAD_BLOCK_VERIFY - _ForceFormatAndCheckBlock(dev, i); -#endif - } - } - - if (ret == U_SUCC && uffs_TreeRelease(dev) == U_FAIL) { - ret = U_FAIL; - } - - if (ret == U_SUCC && uffs_TreeInit(dev) == U_FAIL) { - ret = U_FAIL; - } - - if (ret == U_SUCC && uffs_BuildTree(dev) == U_FAIL) { - ret = U_FAIL; - } - - uffs_GlobalFsLockUnlock(); - - return ret; -} - -static const char * GetTagName(struct uffs_TagStoreSt *s) -{ - const char *name = "UNKNOWN"; - struct uffs_NodeTypeNameMapSt maps[] = UFFS_TYPE_NAME_MAP; - int i; - - for (i = 0; i < ARRAY_SIZE(maps); i++) { - if (s->type == maps[i].type) - name = maps[i].name; - } - - return name; -} - -static void DumpBufHex(struct uffs_DeviceSt *dev, const u8* buf, int len, dump_msg_cb *dump) -{ - int i; - for (i = 0; i < len; i++) - dump(dev, "%02X ", buf[i]); -} - -// return -1 if do not need to read next tag -static int DumpTag(struct uffs_DeviceSt *dev, int block, int page, uffs_Tags *tag, dump_msg_cb *dump) -{ - struct uffs_TagStoreSt *s = &tag->s; - struct uffs_MiniHeaderSt header; - URET ret; - - if (!TAG_IS_DIRTY(tag)) { - // is a clean page ? - ret = uffs_LoadMiniHeader(dev, block, page, &header); - if (ret == U_FAIL) { - dump(dev, "Fail to load mini header from page 0\n"); - } - else { - if (header.status == 0xFF) - dump(dev, "page %d CLEAN\n", page); - else { - dump(dev, "page %d NOT clean ! header: ", page); - DumpBufHex(dev, (u8 *)&header, sizeof(header), dump); - dump(dev, ", tag: "); - DumpBufHex(dev, (u8 *)s, sizeof(struct uffs_TagStoreSt), dump); - dump(dev, "\n"); - } - } - return -1; - } - - dump(dev, " - page %2d/%2d %s %d/%d len%4d\n", page, s->page_id, GetTagName(s), s->serial, s->parent, s->data_len); - - return 0; -} - -static void DumpBlock(struct uffs_DeviceSt *dev, int block, dump_msg_cb *dump) -{ - int i; - struct uffs_StorageAttrSt *attr = dev->attr; - uffs_Tags tag; - URET ret; - - dump(dev, "--- Block %d ---\n", block); - - if (uffs_FlashIsBadBlock(dev, block)) { - dump(dev, "Bad block\n\n"); - return; - } - - for (i = 0; i < attr->pages_per_block; i++) { - - memset(&tag, 0xFF, sizeof(tag)); - ret = uffs_FlashReadPageTag(dev, block, i, &tag); - - if (ret == UFFS_FLASH_IO_ERR) { - dump(dev, "page %d tag I/O error\n", i); - continue; - } - else if (ret == UFFS_FLASH_ECC_FAIL) { - dump(dev, "page %d tag ECC error\n", i); - continue; - } - else if (ret == UFFS_FLASH_NO_ERR || ret == UFFS_FLASH_ECC_OK) { - if (ret == UFFS_FLASH_ECC_OK) - dump(dev, "page %d tag has bit flip, corrected by ECC\n", i); - - if (DumpTag(dev, block, i, &tag, dump) == 0) - continue; - else - break; - } - else { - dump(dev, "read page %d tag return unexpected: %d\n", i, ret); - continue; - } - } - dump(dev, "\n"); -} - -void uffs_DumpDevice(struct uffs_DeviceSt *dev, dump_msg_cb *dump) -{ - int i; - for (i = dev->par.start; i <= dev->par.end; i++) { - DumpBlock(dev, i, dump); - } -} diff --git a/components/dfs/filesystems/uffs/src/uffs/uffs_version.c b/components/dfs/filesystems/uffs/src/uffs/uffs_version.c deleted file mode 100644 index e6cd98e3f3..0000000000 --- a/components/dfs/filesystems/uffs/src/uffs/uffs_version.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_version.c - * \brief uffs version information - * \author Ricky Zheng, created 8th May, 2005 - */ - -#include "uffs_config.h" -#include "uffs/uffs_version.h" - -#include -#define PFX "ver : " - - -static char version_buf[16]; - -const char * uffs_Version2Str(int ver) -{ - sprintf(version_buf, "%1d.%02d.%04d", - (ver & 0xff000000) >> 24, (ver & 0xff0000) >> 16, (ver & 0xffff)); - return version_buf; -} - -int uffs_GetVersion(void) -{ - return UFFS_VERSION; -} - -int uffs_GetMainVersion(int ver) -{ - return (ver & 0xff000000) >> 24; -} - -int uffs_GetMinorVersion(int ver) -{ - return (ver & 0xff0000) >> 16; -} - -int uffs_GetTrivialVersion(int ver) -{ - return (ver & 0xff00) >> 8; -} \ No newline at end of file diff --git a/components/dfs/filesystems/uffs/src/utils/CMakeLists.txt b/components/dfs/filesystems/uffs/src/utils/CMakeLists.txt deleted file mode 100644 index 37660d6f47..0000000000 --- a/components/dfs/filesystems/uffs/src/utils/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -IF (UNIX) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/posix) -ENDIF() -IF (WIN32) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/win32) -ENDIF() -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/inc) -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/emu) - -LINK_DIRECTORIES(${uffs_BINARY_DIR}/src/emu) -LINK_DIRECTORIES(${uffs_BINARY_DIR}/src/uffs) - -SET(mkuffs_SRCS mkuffs.c) -ADD_EXECUTABLE(mkuffs ${mkuffs_SRCS}) -TARGET_LINK_LIBRARIES(mkuffs emu uffs emu platform apitest_server) -IF (UNIX) - TARGET_LINK_LIBRARIES(mkuffs pthread) -ENDIF () - - diff --git a/components/dfs/filesystems/uffs/src/utils/mkuffs.c b/components/dfs/filesystems/uffs/src/utils/mkuffs.c deleted file mode 100644 index 3f92069fe2..0000000000 --- a/components/dfs/filesystems/uffs/src/utils/mkuffs.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_test.c - * \brief uffs test main entry - * \author Ricky Zheng - */ - -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_fs.h" -#include "uffs/uffs_utils.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs_mtb.h" - -#include "cmdline.h" -#include "uffs_fileem.h" - -#define PFX NULL -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR > 0 -int main() -{ - MSGLN("Static memory allocator is not supported."); - return 0; -} -#else - -extern struct cli_commandset * get_helper_cmds(void); -extern struct cli_commandset * get_test_cmds(void); -extern void femu_init_uffs_device(uffs_Device *dev); - -static int conf_command_line_mode = 0; -static int conf_verbose_mode = 0; - -static int conf_exec_script = 0; -static char script_command[256]; - -#define DEFAULT_EMU_FILENAME "uffsemfile.bin" -const char * conf_emu_filename = DEFAULT_EMU_FILENAME; - - -/* default basic parameters of the NAND device */ -#define PAGES_PER_BLOCK_DEFAULT 32 -#define PAGE_DATA_SIZE_DEFAULT 512 -#define PAGE_SPARE_SIZE_DEFAULT 16 -#define STATUS_BYTE_OFFSET_DEFAULT 5 -#define TOTAL_BLOCKS_DEFAULT 128 -#define ECC_OPTION_DEFAULT UFFS_ECC_SOFT -//#define ECC_OPTION_DEFAULT UFFS_ECC_HW -//#define ECC_OPTION_DEFAULT UFFS_ECC_HW_AUTO - -#define MAX_MOUNT_TABLES 10 -#define MAX_MOUNT_POINT_NAME 32 - -static int conf_pages_per_block = PAGES_PER_BLOCK_DEFAULT; -static int conf_page_data_size = PAGE_DATA_SIZE_DEFAULT; -static int conf_page_spare_size = PAGE_SPARE_SIZE_DEFAULT; -static int conf_status_byte_offset = STATUS_BYTE_OFFSET_DEFAULT; -static int conf_total_blocks = TOTAL_BLOCKS_DEFAULT; -static int conf_ecc_option = ECC_OPTION_DEFAULT; -static int conf_ecc_size = 0; // 0 - Let UFFS choose the size - -static const char *g_ecc_option_strings[] = UFFS_ECC_OPTION_STRING; - -static struct uffs_MountTableEntrySt conf_mounts[MAX_MOUNT_TABLES] = {{0}}; -static uffs_Device conf_devices[MAX_MOUNT_TABLES] = {{0}}; -static char mount_point_name[MAX_MOUNT_TABLES][MAX_MOUNT_POINT_NAME] = {{0}}; - -static void setup_storage(struct uffs_StorageAttrSt *attr) -{ - attr->total_blocks = conf_total_blocks; /* total blocks */ - attr->page_data_size = conf_page_data_size; /* page data size */ - attr->spare_size = conf_page_spare_size; /* page spare size */ - attr->pages_per_block = conf_pages_per_block; /* pages per block */ - - attr->block_status_offs = conf_status_byte_offset; /* block status offset is 5th byte in spare */ - attr->ecc_opt = conf_ecc_option; /* ECC option */ - attr->ecc_size = conf_ecc_size; /* ECC size */ - attr->layout_opt = UFFS_LAYOUT_UFFS; /* let UFFS handle layout */ -} - - -static void setup_device(uffs_Device *dev) -{ - dev->Init = femu_InitDevice; - dev->Release = femu_ReleaseDevice; - dev->attr = femu_GetStorage(); -} - -static void setup_emu_private(uffs_FileEmu *emu) -{ - memset(emu, 0, sizeof(uffs_FileEmu)); - emu->emu_filename = conf_emu_filename; -} - -static int init_uffs_fs(void) -{ - static int bIsFileSystemInited = 0; - struct uffs_MountTableEntrySt *mtbl = &(conf_mounts[0]); - struct uffs_ConfigSt cfg = { - 0, // bc_caches - default - 0, // page_buffers - default - 0, // dirty_pages - default - 0, // dirty_groups - default - 0, // reserved_free_blocks - default - }; - - if (bIsFileSystemInited) - return -4; - - bIsFileSystemInited = 1; - - while (mtbl->dev) { - - memcpy(&mtbl->dev->cfg, &cfg, sizeof(struct uffs_ConfigSt)); - -#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0 - uffs_MemSetupSystemAllocator(&mtbl->dev->mem); -#endif - setup_device(mtbl->dev); - uffs_RegisterMountTable(mtbl); - mtbl++; - } - - // mount partitions - for (mtbl = &(conf_mounts[0]); mtbl->mount != NULL; mtbl++) { - uffs_Mount(mtbl->mount); - } - - return uffs_InitFileSystemObjects() == U_SUCC ? 0 : -1; -} - -static int release_uffs_fs(void) -{ - int ret = 0; - uffs_MountTable *mtb; - - for (mtb = &(conf_mounts[0]); ret == 0 && mtb->mount != NULL; mtb++) { - uffs_UnMount(mtb->mount); - } - - if (ret == 0) - ret = (uffs_ReleaseFileSystemObjects() == U_SUCC ? 0 : -1); - - return ret; -} - -/* mount point arg: /sys/,100,-1 */ -static int parse_mount_point(char *arg, int m_idx) -{ - int start = 0, end = -1; - char *p = arg; - struct uffs_MountTableEntrySt *mtbl = &(conf_mounts[m_idx]); - - while(*p && *p != ',' && *p != ' ' && *p != '\t') - p++; - - if (*p == 0 || p == arg) - return -1; - - mtbl->mount = &(mount_point_name[m_idx][0]); - memcpy((char *)mtbl->mount, arg, p - arg); - ((char *)(mtbl->mount))[p - arg] = 0; - - p++; - arg = p; - while(*p && *p != ',' && *p != ' ' && *p != '\t') - p++; - - if (p != arg) { - if (sscanf(arg, "%i", &start) < 1) - return -1; - p++; - arg = p; - - while(*p && *p != ',' && *p != ' ' && *p != '\t') - p++; - - if (p != arg) { - if (sscanf(arg, "%i", &end) < 1) - return -1; - } - } - mtbl->start_block = start; - mtbl->end_block = end; - mtbl->dev = &(conf_devices[m_idx]); - - return 0; -} - -static int parse_options(int argc, char *argv[]) -{ - int iarg; - int usage = 0; - int m_idx = 0; - static char em_file[128]; - int i; - - for (iarg = 1; iarg < argc && !usage; iarg++) { - const char *arg = argv[iarg]; - - if (arg[0] == '-') { - if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) { - usage++; - } - else if (!strcmp(arg, "-f") || !strcmp(arg, "--file")) { - if (++iarg >= argc) - usage++; - else { - strcpy(em_file, argv[iarg]); - conf_emu_filename = (const char *)em_file; - } - } - else if (!strcmp(arg, "-c") || !strcmp(arg, "--command-line")) { - conf_command_line_mode = 1; - } - else if (!strcmp(arg, "-p") || !strcmp(arg, "--page-size")) { - if (++iarg >= argc) - usage++; - else if (sscanf(argv[iarg], "%i", &conf_page_data_size) < 1) - usage++; - if (conf_page_data_size <= 0 || conf_page_data_size > UFFS_MAX_PAGE_SIZE) { - MSGLN("ERROR: Invalid page data size"); - usage++; - } - } - else if (!strcmp(arg, "-s") || !strcmp(arg, "--spare-size")) { - if (++iarg >= argc) - usage++; - else if (sscanf(argv[iarg], "%i", &conf_page_spare_size) < 1) - usage++; - if (conf_page_spare_size < sizeof(struct uffs_TagStoreSt) + 1 || - (conf_page_spare_size % 4) != 0 || conf_page_spare_size > UFFS_MAX_SPARE_SIZE) { - MSGLN("ERROR: Invalid spare size"); - usage++; - } - } - else if (!strcmp(arg, "-o") || !strcmp(arg, "--status-offset")) { - if (++iarg >= argc) - usage++; - else if (sscanf(argv[iarg], "%i", &conf_status_byte_offset) < 1) - usage++; - if (conf_status_byte_offset < 0) - usage++; - } - else if (!strcmp(arg, "-b") || !strcmp(arg, "--block-pages")) { - if (++iarg >= argc) - usage++; - else if (sscanf(argv[iarg], "%i", &conf_pages_per_block) < 1) - usage++; - if (conf_pages_per_block < 2) - usage++; - } - else if (!strcmp(arg, "-t") || !strcmp(arg, "--total-blocks")) { - if (++iarg >= argc) - usage++; - else if (sscanf(argv[iarg], "%i", &conf_total_blocks) < 1) - usage++; - if (conf_total_blocks < 2) - usage++; - } - else if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) { - conf_verbose_mode++; - } - else if (!strcmp(arg, "-m") || !strcmp(arg, "--mount")) { - if (++iarg > argc) - usage++; - else if (parse_mount_point(argv[iarg], m_idx) < 0) - usage++; - m_idx++; - } - else if (!strcmp(arg, "-e") || !strcmp(arg, "--exec")) { - if (++iarg > argc) - usage++; - else { - sprintf(script_command, "script %s", argv[iarg]); - conf_exec_script = 1; - } - } - else if (!strcmp(arg, "-x") || !strcmp(arg, "--ecc-option")) { - if (++iarg > argc) - usage++; - else { - for (i = 0; i < ARRAY_SIZE(g_ecc_option_strings); i++) { - if (!strcmp(argv[iarg], g_ecc_option_strings[i])) { - conf_ecc_option = i; - break; - } - } - if (i == ARRAY_SIZE(g_ecc_option_strings)) { - MSGLN("ERROR: Invalid ECC option"); - usage++; - } - } - } - else if (!strcmp(arg, "-z") || !strcmp(arg, "--ecc-size")) { - if (++iarg >= argc) - usage++; - else if (sscanf(argv[iarg], "%i", &conf_ecc_size) < 1) - usage++; - if (conf_ecc_size < 0 || conf_ecc_size > UFFS_MAX_ECC_SIZE) { - MSGLN("ERROR: Invalid ecc size"); - usage++; - } - } - else { - MSGLN("Unknown option: %s, try %s --help", arg, argv[0]); - return -1; - } - } - else { - MSGLN("Unexpected parameter: %s, try %s --help", arg, argv[0]); - return -1; - } - } - - if (usage) { - MSGLN("Usage: %s [options]", argv[0]); - MSGLN(" -h --help show usage"); - MSGLN(" -c --command-line command line mode"); - MSGLN(" -v --verbose verbose mode"); - MSGLN(" -f --file uffs image file"); - MSGLN(" -p --page-size page data size, default=%d", PAGE_DATA_SIZE_DEFAULT); - MSGLN(" -s --spare-size page spare size, default=%d", PAGE_SPARE_SIZE_DEFAULT); - MSGLN(" -o --status-offset status byte offset, default=%d", STATUS_BYTE_OFFSET_DEFAULT); - MSGLN(" -b --block-pages pages per block, default=%d", PAGES_PER_BLOCK_DEFAULT); - MSGLN(" -t --total-blocks total blocks"); - MSGLN(" -m --mount , for example: -m /,0,-1"); - MSGLN(" -x --ecc-option ECC option, default=%s", g_ecc_option_strings[ECC_OPTION_DEFAULT]); - MSGLN(" -z --ecc-size ECC size, default=0 (auto)"); - MSGLN(" -e --exec execute a script file"); - MSGLN(""); - - return -1; - } - - if (m_idx == 0) { - // if not given mount information, use default ('/' for whole partition) - parse_mount_point("/,0,-1", 0); - } - - return 0; -} - - -static void print_mount_points(void) -{ - struct uffs_MountTableEntrySt *m; - - m = &(conf_mounts[0]); - while (m->dev) { - MSGLN ("Mount point: %s, start: %d, end: %d", m->mount, m->start_block, m->end_block); - m++; - } -} - -static void print_params(void) -{ - MSGLN("Parameters summary:"); - MSGLN(" uffs image file: %s", conf_emu_filename); - MSGLN(" page size: %d", conf_page_data_size); - MSGLN(" page spare size: %d", conf_page_spare_size); - MSGLN(" pages per block: %d", conf_pages_per_block); - MSGLN(" total blocks: %d", conf_total_blocks); - MSGLN(" ecc option: %d (%s)", conf_ecc_option, g_ecc_option_strings[conf_ecc_option]); - MSGLN(" ecc size: %d%s", conf_ecc_size, conf_ecc_size == 0 ? " (auto)" : ""); - MSGLN(" bad block status offset: %d", conf_status_byte_offset); - MSGLN(""); -} - -#ifdef UNIX -#include -#include -void crash_handler(int sig) -{ - void *array[10]; - size_t size; - - // get void*'s for all entries on the stack - size = backtrace(array, 10); - - // print out all the frames to stderr - fprintf(stderr, "Error: signal %d:\n", sig); - backtrace_symbols_fd(array, size, 2); - exit(1); -} -#endif - -int main(int argc, char *argv[]) -{ - int ret; - -#ifdef UNIX - signal(SIGSEGV, crash_handler); -#endif - - uffs_SetupDebugOutput(); // setup debug output as early as possible - - if (parse_options(argc, argv) < 0) { - return -1; - } - - if (conf_verbose_mode) { - #if 1 - MSGLN("Internal data structure size:"); - MSGLN(" TreeNode: %d", sizeof(TreeNode)); - MSGLN(" struct BlockListSt: %d", sizeof(struct BlockListSt)); - MSGLN(" struct DirhSt: %d", sizeof(struct DirhSt)); - MSGLN(" struct FilehSt: %d", sizeof(struct FilehSt)); - MSGLN(" struct FdataSt: %d", sizeof(struct FdataSt)); - MSGLN(" struct uffs_TagStoreSt: %d", sizeof(struct uffs_TagStoreSt)); - MSGLN(" uffs_Buf: %d", sizeof(uffs_Buf)); - MSGLN(" struct uffs_BlockInfoSt: %d", sizeof(struct uffs_BlockInfoSt)); - MSGLN(""); - #endif - print_params(); - print_mount_points(); - } - - // setup file emulator storage with parameters from command line - setup_storage(femu_GetStorage()); - - // setup file emulator private data - setup_emu_private(femu_GetPrivate()); - - ret = init_uffs_fs(); - if (ret != 0) { - MSGLN ("Init file system fail: %d", ret); - return -1; - } - - cli_add_commandset(get_helper_cmds()); - cli_add_commandset(get_test_cmds()); - if (conf_command_line_mode) { - if (conf_exec_script) { - cli_interpret(script_command); - } - cli_main_entry(); - } - else { - if (conf_exec_script) { - cli_interpret(script_command); - } - else { - cli_main_entry(); - } - } - - release_uffs_fs(); - - return 0; -} -#endif - - - diff --git a/components/dfs/filesystems/uffs/tools/chomp_uffs_perror.rb b/components/dfs/filesystems/uffs/tools/chomp_uffs_perror.rb deleted file mode 100644 index e8b9460ae5..0000000000 --- a/components/dfs/filesystems/uffs/tools/chomp_uffs_perror.rb +++ /dev/null @@ -1,25 +0,0 @@ -#usage: -# find . -name "*.c" | xargs /usr/bin/ruby path/to/chomp_uffs_perror.rb -# - -ARGV.each do |file| - lines = [] - count = 0 - File.open(file).each_line do |line| - if line =~ /^(.*uffs_Perror.+)PFX(\s*".+)$/ - lines << ($1 + $2) - count += 1 - #puts ($1 + $2) - else - lines << line - end - end - if count > 0 - f = File.open(file, "w") - lines.each do |s| - f.puts s - end - f.close - puts "Fix file #{file}, modified lines: #{count}" - end -end diff --git a/components/dfs/filesystems/uffs/tools/format_code.rb b/components/dfs/filesystems/uffs/tools/format_code.rb deleted file mode 100644 index 7847db236a..0000000000 --- a/components/dfs/filesystems/uffs/tools/format_code.rb +++ /dev/null @@ -1,24 +0,0 @@ -#usage: -# find . -name "*.c" | xargs /usr/bin/ruby path/to/format_code.rb -# - -ARGV.each do |file| - lines = [] - count = 0 - File.open(file).each_line do |line| - if line =~ /^(.*)\s$/ - lines << $1.dup - count += 1 - else - lines << line - end - end - if count > 0 - f = File.open(file, "w") - lines.each do |s| - f.puts s - end - f.close - puts "Fix file #{file}, modified lines: #{count}" - end -end diff --git a/components/dfs/filesystems/uffs/tools/make_package.sh b/components/dfs/filesystems/uffs/tools/make_package.sh deleted file mode 100644 index a78c3fa2fd..0000000000 --- a/components/dfs/filesystems/uffs/tools/make_package.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -git ls-tree --name-only --full-name -r $1 | xargs tar -jcvf uffs-$1.tar.bz2 \ No newline at end of file diff --git a/components/dfs/filesystems/uffs/uffs_config.h b/components/dfs/filesystems/uffs/uffs_config.h deleted file mode 100644 index 2f0b6992bb..0000000000 --- a/components/dfs/filesystems/uffs/uffs_config.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_config.h - * \brief basic configuration of uffs - * \author Ricky Zheng - */ - -#ifndef _UFFS_CONFIG_H_ -#define _UFFS_CONFIG_H_ - -/** - * \def UFFS_MAX_PAGE_SIZE - * \note maximum page size UFFS support - */ -#define UFFS_MAX_PAGE_SIZE 2048 - -/** - * \def UFFS_MAX_SPARE_SIZE - */ -#define UFFS_MAX_SPARE_SIZE ((UFFS_MAX_PAGE_SIZE / 256) * 8) - -/** - * \def UFFS_MAX_ECC_SIZE - */ -#define UFFS_MAX_ECC_SIZE ((UFFS_MAX_PAGE_SIZE / 256) * 5) - -/** - * \def MAX_CACHED_BLOCK_INFO - * \note uffs cache the block info for opened directories and files, - * a practical value is 5 ~ MAX_OBJECT_HANDLE - */ -#define MAX_CACHED_BLOCK_INFO 50 - -/** - * \def MAX_PAGE_BUFFERS - * \note the bigger value will bring better read/write performance. - * but few writing performance will be improved when this - * value is become larger than 'max pages per block' - */ -#define MAX_PAGE_BUFFERS 40 - - -/** - * \def CLONE_BUFFER_THRESHOLD - * \note reserve buffers for clone. 1 or 2 should be enough. - */ -#define CLONE_BUFFERS_THRESHOLD 2 - -/** - * \def MAX_SPARE_BUFFERS - * \note spare buffers are used for lower level flash operations, - * 5 should be enough. - */ -#define MAX_SPARE_BUFFERS 5 - - -/** - * \def MAX_DIRTY_PAGES_IN_A_BLOCK - * \note this value should be between '2' and the lesser of - * 'max pages per block' and (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD - 1). - * - * the smaller the value the frequently the buffer will be flushed. - */ -#define MAX_DIRTY_PAGES_IN_A_BLOCK 32 - -/** - * \def MAX_DIRTY_BUF_GROUPS - */ -#define MAX_DIRTY_BUF_GROUPS 3 - -/** - * \def CONFIG_ENABLE_UFFS_DEBUG_MSG - * \note Enable debug message output. You must call uffs_InitDebugMessageOutput() - * to initialize debug apart from enable debug feature. - */ -#define CONFIG_ENABLE_UFFS_DEBUG_MSG - -/** - * \def CONFIG_USE_GLOBAL_FS_LOCK - * \note use global lock instead of per-device lock. - * this is required if you use fd APIs in multi-thread environment. - */ -#define CONFIG_USE_GLOBAL_FS_LOCK - - -/** - * \def CONFIG_USE_PER_DEVICE_LOCK - * \note use per-device lock. - * this is required if you use fs APIs in multi-thread environment. - */ -//#define CONFIG_USE_PER_DEVICE_LOCK - - - -/** - * \def CONFIG_USE_STATIC_MEMORY_ALLOCATOR - * \note uffs will use static memory allocator if this is defined. - * to use static memory allocator, you need to provide memory - * buffer when creating uffs_Device. - * - * use UFFS_STATIC_BUFF_SIZE() to calculate memory buffer size. - */ -#define CONFIG_USE_STATIC_MEMORY_ALLOCATOR 0 - -/** - * \def CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR - * \note using system platform's 'malloc' and 'free'. - */ -#define CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR 1 - - - -/** - * \def CONFIG_FLUSH_BUF_AFTER_WRITE - * \note UFFS will write all data directly into flash in - * each 'write' call if you enable this option. - * (which means lesser data lost when power failure but - * poorer writing performance). - * It's not recommended to open this define for normal applications. - */ -#define CONFIG_FLUSH_BUF_AFTER_WRITE - - -/** - * \def CONFIG_UFFS_AUTO_LAYOUT_MTD_COMP - * \note Use Linux MTD compatiable spare placement for UFFS_LAYOUT_AUTO, - * only valid for page data size 512 or 2048. - */ -//#define CONFIG_UFFS_AUTO_LAYOUT_USE_MTD_SCHEME - - -/** - * \def MAX_OBJECT_HANDLE - * maximum number of object handle - */ -#define MAX_OBJECT_HANDLE 50 -#define FD_SIGNATURE_SHIFT 6 - - -/** - * \def MAX_DIR_HANDLE - * maximum number of uffs_DIR - */ -#define MAX_DIR_HANDLE 10 - -/** - * \def MINIMUN_ERASED_BLOCK - * UFFS will not allow appending or creating new files when the free/erased block - * is lower then MINIMUN_ERASED_BLOCK. - */ -#define MINIMUN_ERASED_BLOCK 2 - -/** - * \def CONFIG_CHANGE_MODIFY_TIME - * \note If defined, closing a file which is opened for writing/appending will - * update the file's modify time as well. Disable this feature will save a - * lot of writing activities if you frequently open files for write and close it. - */ -//#define CONFIG_CHANGE_MODIFY_TIME - - -/** - * \def CONFIG_ENABLE_BAD_BLOCK_VERIFY - * \note allow erase and verify block marked as 'bad' when format UFFS partition. - * it's not recommended for most NAND flash. - */ -#define CONFIG_ENABLE_BAD_BLOCK_VERIFY - -/** - * \def CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - * \note erase block again before mark bad block - */ -//#define CONFIG_ERASE_BLOCK_BEFORE_MARK_BAD - -/** - * \def CONFIG_PAGE_WRITE_VERIFY - * \note verify page data after write, for extra safe data storage. - */ -#define CONFIG_PAGE_WRITE_VERIFY - -/** - * \def CONFIG_BAD_BLOCK_POLICY_STRICT - * \note If this is enabled, UFFS will report the block as 'bad' if any bit-flips found; - * otherwise, UFFS report bad block only when ECC failed or reported - * by low level flash driver. - * - * \note Enable this will ensure your data always be stored on completely good blocks. - */ -#define CONFIG_BAD_BLOCK_POLICY_STRICT - - -/** - * \def CONFIG_ENABLE_PAGE_DATA_CRC - * \note If this is enabled, UFFS save page data CRC16 sum in mini header, - * it provides extra protection for data integrity. - */ -#define CONFIG_ENABLE_PAGE_DATA_CRC - - -/** micros for calculating buffer sizes */ - -/** - * \def UFFS_BLOCK_INFO_BUFFER_SIZE - * \brief calculate memory bytes for block info caches - */ -#define UFFS_BLOCK_INFO_BUFFER_SIZE(n_pages_per_block) \ - ( \ - ( \ - sizeof(uffs_BlockInfo) + \ - sizeof(uffs_PageSpare) * n_pages_per_block \ - ) * MAX_CACHED_BLOCK_INFO \ - ) - -/** - * \def UFFS_PAGE_BUFFER_SIZE - * \brief calculate memory bytes for page buffers - */ -#define UFFS_PAGE_BUFFER_SIZE(n_page_size) \ - ( \ - ( \ - sizeof(uffs_Buf) + n_page_size \ - ) * MAX_PAGE_BUFFERS \ - ) - -/** - * \def UFFS_TREE_BUFFER_SIZE - * \brief calculate memory bytes for tree nodes - */ -#define UFFS_TREE_BUFFER_SIZE(n_blocks) (sizeof(TreeNode) * n_blocks) - - -#define UFFS_SPARE_BUFFER_SIZE (MAX_SPARE_BUFFERS * UFFS_MAX_SPARE_SIZE) - - -/** - * \def UFFS_STATIC_BUFF_SIZE - * \brief calculate total memory usage of uffs system - */ -#define UFFS_STATIC_BUFF_SIZE(n_pages_per_block, n_page_size, n_blocks) \ - ( \ - UFFS_BLOCK_INFO_BUFFER_SIZE(n_pages_per_block) + \ - UFFS_PAGE_BUFFER_SIZE(n_page_size) + \ - UFFS_TREE_BUFFER_SIZE(n_blocks) + \ - UFFS_SPARE_BUFFER_SIZE \ - ) - - - -/* config check */ -#if (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD) < 3 -#error "MAX_PAGE_BUFFERS is too small" -#endif - -#if (MAX_DIRTY_PAGES_IN_A_BLOCK < 2) -#error "MAX_DIRTY_PAGES_IN_A_BLOCK should >= 2" -#endif - -#if (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD - 1 < MAX_DIRTY_PAGES_IN_A_BLOCK) -#error "MAX_DIRTY_PAGES_IN_A_BLOCK should < (MAX_PAGE_BUFFERS - CLONE_BUFFERS_THRESHOLD)" -#endif - -#if defined(CONFIG_PAGE_WRITE_VERIFY) && (CLONE_BUFFERS_THRESHOLD < 2) -#error "CLONE_BUFFERS_THRESHOLD should >= 2 when CONFIG_PAGE_WRITE_VERIFY is enabled." -#endif - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR + CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 1 -#error "Please enable ONLY one memory allocator" -#endif - -#if CONFIG_USE_STATIC_MEMORY_ALLOCATOR + CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR == 0 -#error "Please enable ONE of memory allocators" -#endif - -#if defined(CONFIG_USE_GLOBAL_FS_LOCK) && defined(CONFIG_USE_PER_DEVICE_LOCK) -#error "enable either CONFIG_USE_GLOBAL_FS_LOCK or CONFIG_USE_PER_DEVICE_LOCK, not both" -#endif - -#if (MAX_OBJECT_HANDLE > (1 << FD_SIGNATURE_SHIFT)) -#error "Please increase FD_SIGNATURE_SHIFT !" -#endif - -#ifdef WIN32 -# pragma warning(disable : 4996) -# pragma warning(disable : 4244) -# pragma warning(disable : 4214) -# pragma warning(disable : 4127) -# pragma warning(disable : 4389) -# pragma warning(disable : 4100) -#endif - -#endif diff --git a/components/dfs/filesystems/uffs/uffs_nandif.c b/components/dfs/filesystems/uffs/uffs_nandif.c deleted file mode 100644 index 00e1bee8d5..0000000000 --- a/components/dfs/filesystems/uffs/uffs_nandif.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * RT-Thread Device Interface for uffs - */ - -#include -#include -#include "dfs_uffs.h" - -static int nand_init_flash(uffs_Device *dev) -{ - return UFFS_FLASH_NO_ERR; -} - -static int nand_release_flash(uffs_Device *dev) -{ - return UFFS_FLASH_NO_ERR; -} -static int nand_erase_block(uffs_Device *dev, unsigned block) -{ - int res; - - res = rt_mtd_nand_erase_block(RT_MTD_NAND_DEVICE(dev->_private), block); - - return res == RT_EOK ? UFFS_FLASH_NO_ERR : UFFS_FLASH_IO_ERR; -} - -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) -static int nand_check_block(uffs_Device *dev, unsigned block) -{ - int res; - - res = rt_mtd_nand_check_block(RT_MTD_NAND_DEVICE(dev->_private), block); - - return res == RT_EOK ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK; -} - -static int nand_mark_badblock(uffs_Device *dev, unsigned block) -{ - int res; - - res = rt_mtd_nand_mark_badblock(RT_MTD_NAND_DEVICE(dev->_private), block); - - return res == RT_EOK ? UFFS_FLASH_NO_ERR : UFFS_FLASH_IO_ERR; -} -#endif - -#if (RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_NONE) || (RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_SOFT) -static int nand_read_page(uffs_Device *dev, - u32 block, - u32 page, - u8 *data, - int data_len, - u8 *ecc, - rt_uint8_t *spare, - int spare_len) -{ - int res; - - page = block * dev->attr->pages_per_block + page; - if (data == NULL && spare == NULL) - { -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) - RT_ASSERT(0); //should not be here -#else - /* check block status: bad or good */ - rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; - - rt_memset(spare, 0, UFFS_MAX_SPARE_SIZE); - - rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), - page, RT_NULL, 0, - spare, dev->attr->spare_size);//dev->mem.spare_data_size - - res = spare[dev->attr->block_status_offs] == 0xFF ? - UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK; - - return res; -#endif - } - - rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), - page, data, data_len, spare, spare_len); - - return UFFS_FLASH_NO_ERR; -} - -static int nand_write_page(uffs_Device *dev, - u32 block, - u32 page, - const u8 *data, - int data_len, - const u8 *spare, - int spare_len) -{ - int res; - - RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size); - - page = block * dev->attr->pages_per_block + page; - - if (data == NULL && spare == NULL) - { -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) - RT_ASSERT(0); //should not be here -#else - /* mark bad block */ - rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; - - rt_memset(spare, 0xFF, UFFS_MAX_SPARE_SIZE); - spare[dev->attr->block_status_offs] = 0x00; - - res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), - page, RT_NULL, 0, - spare, dev->attr->spare_size);//dev->mem.spare_data_size - if (res != RT_EOK) - goto __error; -#endif - } - - res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), - page, data, data_len, spare, spare_len); - if (res != RT_EOK) - goto __error; - - return UFFS_FLASH_NO_ERR; - -__error: - return UFFS_FLASH_IO_ERR; -} - -const uffs_FlashOps nand_ops = -{ - nand_init_flash, /* InitFlash() */ - nand_release_flash, /* ReleaseFlash() */ - nand_read_page, /* ReadPage() */ - NULL, /* ReadPageWithLayout */ - nand_write_page, /* WritePage() */ - NULL, /* WritePageWithLayout */ -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) - nand_check_block, - nand_mark_badblock, -#else - NULL, /* IsBadBlock(), let UFFS take care of it. */ - NULL, /* MarkBadBlock(), let UFFS take care of it. */ -#endif - nand_erase_block, /* EraseBlock() */ -}; - -void uffs_setup_storage(struct uffs_StorageAttrSt *attr, - struct rt_mtd_nand_device *nand) -{ - rt_memset(attr, 0, sizeof(struct uffs_StorageAttrSt)); - -// attr->total_blocks = nand->end_block - nand->start_block + 1;/* no use */ - attr->page_data_size = nand->page_size; /* page data size */ - attr->pages_per_block = nand->pages_per_block; /* pages per block */ - attr->spare_size = nand->oob_size; /* page spare size */ - attr->ecc_opt = RT_CONFIG_UFFS_ECC_MODE; /* ecc option */ - attr->ecc_size = 0; /* ecc size is 0 , the uffs will calculate the ecc size*/ - attr->block_status_offs = attr->ecc_size; /* indicate block bad or good, offset in spare */ - attr->layout_opt = RT_CONFIG_UFFS_LAYOUT; /* let UFFS do the spare layout */ -} - -#elif RT_CONFIG_UFFS_ECC_MODE == UFFS_ECC_HW_AUTO -static int WritePageWithLayout(uffs_Device *dev, - u32 block, - u32 page, - const u8 *data, - int data_len, - const u8 *ecc, //NULL - const uffs_TagStore *ts) -{ - int res; - int spare_len; - rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; - - RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size); - - page = block * dev->attr->pages_per_block + page; - spare_len = dev->mem.spare_data_size; - - if (data == NULL && ts == NULL) - { -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) - RT_ASSERT(0); //should not be here -#else - /* mark bad block */ - rt_memset(spare, 0xFF, UFFS_MAX_SPARE_SIZE); - spare[dev->attr->block_status_offs] = 0x00; - - res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), - page, RT_NULL, 0, - spare, dev->attr->spare_size);//dev->mem.spare_data_size - if (res != RT_EOK) - goto __error; - - dev->st.io_write++; - return UFFS_FLASH_NO_ERR; -#endif - } - - if (data != NULL && data_len != 0) - { - RT_ASSERT(data_len == dev->attr->page_data_size); - - dev->st.page_write_count++; - dev->st.io_write += data_len; - } - - if (ts != RT_NULL) - { - uffs_FlashMakeSpare(dev, ts, RT_NULL, (u8 *)spare); - dev->st.spare_write_count++; - dev->st.io_write += spare_len; - } - - res = rt_mtd_nand_write(RT_MTD_NAND_DEVICE(dev->_private), - page, data, data_len, spare, spare_len); - if (res != RT_EOK) - goto __error; - - return UFFS_FLASH_NO_ERR; - -__error: - return UFFS_FLASH_IO_ERR; -} - -static URET ReadPageWithLayout(uffs_Device *dev, - u32 block, - u32 page, - u8 *data, - int data_len, - u8 *ecc, //NULL - uffs_TagStore *ts, - u8 *ecc_store) //NULL -{ - int res = UFFS_FLASH_NO_ERR; - int spare_len; - rt_uint8_t spare[UFFS_MAX_SPARE_SIZE]; - - RT_ASSERT(UFFS_MAX_SPARE_SIZE >= dev->attr->spare_size); - - page = block * dev->attr->pages_per_block + page; - spare_len = dev->mem.spare_data_size; - - if (data == RT_NULL && ts == RT_NULL) - { -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) - RT_ASSERT(0); //should not be here -#else - /* check block good or bad */ - - rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), - page, RT_NULL, 0, - spare, dev->attr->spare_size);//dev->mem.spare_data_size - - dev->st.io_read++; - - res = spare[dev->attr->block_status_offs] == 0xFF ? - UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK; - return res; -#endif - } - - if (data != RT_NULL) - { - dev->st.io_read += data_len; - dev->st.page_read_count++; - } - - res = rt_mtd_nand_read(RT_MTD_NAND_DEVICE(dev->_private), - page, data, data_len, spare, spare_len); - if (res == 0) - res = UFFS_FLASH_NO_ERR; - else if (res == -1) - { - //TODO ecc correct, add code to use hardware do ecc correct - res = UFFS_FLASH_ECC_OK; - } - else - res = UFFS_FLASH_ECC_FAIL; - - if (ts != RT_NULL) - { - // unload ts and ecc from spare, you can modify it if you like - uffs_FlashUnloadSpare(dev, (const u8 *)spare, ts, RT_NULL); - - if ((spare[spare_len - 1] == 0xFF) && (res == UFFS_FLASH_NO_ERR)) - res = UFFS_FLASH_NOT_SEALED; - - dev->st.io_read += spare_len; - dev->st.spare_read_count++; - } - - return res; -} - -const uffs_FlashOps nand_ops = -{ - nand_init_flash, /* InitFlash() */ - nand_release_flash, /* ReleaseFlash() */ - NULL, /* ReadPage() */ - ReadPageWithLayout, /* ReadPageWithLayout */ - NULL, /* WritePage() */ - WritePageWithLayout,/* WritePageWithLayout */ - -#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) - nand_check_block, - nand_mark_badblock, -#else - NULL, /* IsBadBlock(), let UFFS take care of it. */ - NULL, /* MarkBadBlock(), let UFFS take care of it. */ -#endif - nand_erase_block, /* EraseBlock() */ -}; - -static rt_uint8_t hw_flash_data_layout[UFFS_SPARE_LAYOUT_SIZE] = -{ - 0x05, 0x08, 0xFF, 0x00 -}; - -static rt_uint8_t hw_flash_ecc_layout[UFFS_SPARE_LAYOUT_SIZE] = -{ - 0x00, 0x04, 0xFF, 0x00 -}; - -RT_WEAK void uffs_setup_storage(struct uffs_StorageAttrSt *attr, - struct rt_mtd_nand_device *nand) -{ - rt_memset(attr, 0, sizeof(struct uffs_StorageAttrSt)); - -// attr->total_blocks = nand->end_block - nand->start_block + 1;/* no use */ - attr->page_data_size = nand->page_size; /* page data size */ - attr->pages_per_block = nand->pages_per_block; /* pages per block */ - attr->spare_size = nand->oob_size; /* page spare size */ - attr->ecc_opt = RT_CONFIG_UFFS_ECC_MODE; /* ecc option */ - attr->ecc_size = nand->oob_size-nand->oob_free; /* ecc size */ - attr->block_status_offs = attr->ecc_size; /* indicate block bad or good, offset in spare */ - attr->layout_opt = RT_CONFIG_UFFS_LAYOUT; /* let UFFS do the spare layout */ - - /* calculate the ecc layout array */ - hw_flash_data_layout[0] = attr->ecc_size + 1; /* ecc size + 1byte block status */ - hw_flash_data_layout[1] = 0x08; - hw_flash_data_layout[2] = 0xFF; - hw_flash_data_layout[3] = 0x00; - - hw_flash_ecc_layout[0] = 0; - hw_flash_ecc_layout[1] = attr->ecc_size; - hw_flash_ecc_layout[2] = 0xFF; - hw_flash_ecc_layout[3] = 0x00; - - /* initialize _uffs_data_layout and _uffs_ecc_layout */ - rt_memcpy(attr->_uffs_data_layout, hw_flash_data_layout, UFFS_SPARE_LAYOUT_SIZE); - rt_memcpy(attr->_uffs_ecc_layout, hw_flash_ecc_layout, UFFS_SPARE_LAYOUT_SIZE); - - attr->data_layout = attr->_uffs_data_layout; - attr->ecc_layout = attr->_uffs_ecc_layout; -} -#endif diff --git a/components/dfs/filesystems/uffs/uffs_rtthread.c b/components/dfs/filesystems/uffs/uffs_rtthread.c deleted file mode 100644 index bad456f04c..0000000000 --- a/components/dfs/filesystems/uffs/uffs_rtthread.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file uffs_os_posix.c - * \brief Emulation on POSIX host. This is just a dumb implementation, does not really create semaphores. - * \author Ricky Zheng - */ - -#include "uffs_config.h" -#include "uffs/uffs_os.h" -#include "uffs/uffs_public.h" -//#include - -#define PFX "os : " - -int uffs_SemCreate(OSSEM *sem) -{ - static int count = 0; - char name [RT_NAME_MAX+1]; - struct rt_mutex *mutex = RT_NULL; - - rt_snprintf(name, sizeof(name), "usem%d", count++); - mutex = rt_mutex_create(name, RT_IPC_FLAG_FIFO); - if (mutex != RT_NULL) - { - *sem = (OSSEM *)mutex; - return 0; - } - uffs_Perror(UFFS_MSG_SERIOUS, "can't get a semphore"); - return -1; -} - -int uffs_SemWait(OSSEM sem) -{ - return rt_mutex_take((struct rt_mutex *)sem, RT_WAITING_FOREVER); -} - -int uffs_SemSignal(OSSEM sem) -{ - return rt_mutex_release((struct rt_mutex *)sem); -} - -int uffs_SemDelete(OSSEM *sem) -{ - int ret = -1; - - if (sem) { - ret = rt_mutex_delete((struct rt_mutex *)(*sem)); - if (ret == RT_EOK) { - *sem = 0; - } - } - return ret; -} - -int uffs_OSGetTaskId(void) -{ - //TODO: ... return current task ID ... - return 0; -} - -unsigned int uffs_GetCurDateTime(void) -{ - // FIXME: return system time, please modify this for your platform ! - // or just return 0 if you don't care about file time. -#if 0 - time_t tvalue; - - tvalue = time(NULL); - - return (unsigned int)tvalue; -#endif - return 0; -} - -#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0 -static void * sys_malloc(struct uffs_DeviceSt *dev, unsigned int size) -{ - dev = dev; - uffs_Perror(UFFS_MSG_NORMAL, "system memory alloc %d bytes", size); - return rt_malloc(size); -} - -static URET sys_free(struct uffs_DeviceSt *dev, void *p) -{ - dev = dev; - rt_free(p); - return U_SUCC; -} - -void uffs_MemSetupSystemAllocator(uffs_MemAllocator *allocator) -{ - allocator->malloc = sys_malloc; - allocator->free = sys_free; -} -#endif - -#if !defined(RT_THREAD) -/* debug message output throught 'printf' */ -static void output_dbg_msg(const char *msg); -static struct uffs_DebugMsgOutputSt m_dbg_ops = { - output_dbg_msg, - NULL, -}; - -static void output_dbg_msg(const char *msg) -{ - rt_kprintf("%s", msg); -} - -void uffs_SetupDebugOutput(void) -{ - uffs_InitDebugMessageOutput(&m_dbg_ops, UFFS_MSG_NOISY); -} -#else - -void uffs_SetupDebugOutput(void) -{ -} -#endif From 3ec59a8865b9503f5daa4e6c894b0fc502a43068 Mon Sep 17 00:00:00 2001 From: yangjie Date: Mon, 15 Mar 2021 13:44:25 +0800 Subject: [PATCH 2/2] =?UTF-8?q?[components][dfs/Kconfig]=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9help=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/dfs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index 3d70820173..39eca3c507 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -115,7 +115,7 @@ if RT_USING_DFS int "Maximum sector size to be handled." default 512 help - if you use some spi nor flash for fatfs, please set this the erase sector size, for example 4096. + If you use some spi nor flash for fatfs, please set this the erase sector size, for example 4096. config RT_DFS_ELM_USE_ERASE bool "Enable sector erase feature"

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 diff --git a/components/dfs/filesystems/uffs/src/CMakeLists.txt b/components/dfs/filesystems/uffs/src/CMakeLists.txt deleted file mode 100644 index 7d744d16ee..0000000000 --- a/components/dfs/filesystems/uffs/src/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -ADD_SUBDIRECTORY(emu) -ADD_SUBDIRECTORY(uffs) -ADD_SUBDIRECTORY(utils) -ADD_SUBDIRECTORY(example) -ADD_SUBDIRECTORY(platform) -ADD_SUBDIRECTORY(test/api_test) -ADD_SUBDIRECTORY(test/clients) diff --git a/components/dfs/filesystems/uffs/src/emu/CMakeLists.txt b/components/dfs/filesystems/uffs/src/emu/CMakeLists.txt deleted file mode 100644 index f70deff7a2..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -SET (libemu_SRCS - cmdline.c - cmdline.h - helper_cmds.c - uffs_fileem.c - uffs_fileem_share.c - uffs_fileem_wrap.c - uffs_fileem_ecc_soft.c - uffs_fileem_ecc_hw.c - uffs_fileem_ecc_hw_auto.c - uffs_fileem.h - test_cmds.c - ) - -IF (UNIX) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/posix) -ENDIF() -IF (WIN32) - INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/platform/win32) -ENDIF() -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/inc) -INCLUDE_DIRECTORIES(${uffs_SOURCE_DIR}/src/test/api_test) -ADD_LIBRARY(emu STATIC ${libemu_SRCS} ) - diff --git a/components/dfs/filesystems/uffs/src/emu/cmdline.c b/components/dfs/filesystems/uffs/src/emu/cmdline.c deleted file mode 100644 index 9774a11ca1..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/cmdline.c +++ /dev/null @@ -1,643 +0,0 @@ -/* -This file is part of UFFS, the Ultra-low-cost Flash File System. - -Copyright (C) 2005-2009 Ricky Zheng - -UFFS is free software; you can redistribute it and/or modify it under -the GNU Library General Public License as published by the Free Software -Foundation; either version 2 of the License, or (at your option) any -later version. - -UFFS is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -or GNU Library General Public License, as applicable, for more details. - -You should have received a copy of the GNU General Public License -and GNU Library General Public License along with UFFS; if not, write -to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. - -As a special exception, if other files instantiate templates or use -macros or inline functions from this file, or you compile this file -and link it with other works to produce a work based on this file, -this file does not by itself cause the resulting work to be covered -by the GNU General Public License. However the source code for this -file must still be made available in accordance with section (3) of -the GNU General Public License v2. - -This exception does not invalidate any other reasons why a work based -on this file might be covered by the GNU General Public License. -*/ - -/** -* \file cmdline.c -* \brief command line test interface -* \author Ricky Zheng, created in 22th Feb, 2007 -*/ - -#include -#include -//#include -#include "uffs_config.h" -#include "cmdline.h" -#include "uffs/uffs_fs.h" - -#define PROMPT "UFFS>" - -#define PFX "cli : " -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - -#define MAX_CLI_ARGS_BUF_LEN 120 -#define MAX_CLI_ARGS_NUM 20 -#define MAX_CLI_ENV_NUM 11 // '?', '0' - '9' - - -struct cli_arg { - int argc; - char *argv[MAX_CLI_ARGS_NUM]; - char _buf[MAX_CLI_ARGS_BUF_LEN]; -}; - -static BOOL m_exit = FALSE; -static BOOL m_abort = FALSE; -static struct cli_commandset *m_cmdset_head = NULL; - -// Note: last command return code stored in env 0. -static int m_cli_envs[MAX_CLI_ENV_NUM] = {0}; // cli environment variables - -static const struct cli_command * cli_find(const char *cmd); -static int cmd_help(int argc, char *argv[]); - - -#define FOR_EACH_CLI_CMD(set, cmd) \ - for (set = m_cmdset_head; set && set->cmds; set = set->next) \ - for (cmd = set->cmds; cmd && cmd->handler; cmd++) - - -/*** filter out leading and tailing spaces, discard comments - * return pointer to start of new command line - */ -static char * cli_process_line(char *p) -{ - char *s; - char *x; - - if (!p) - return NULL; - - // skip leading spaces - while (p && (*p == ' ' || *p == '\t')) - p++; - - for (s = x = p; *p; x++, p++) { - switch(*p) { - case '\\': - p++; - if (*p) { - switch(*p) { - case 'n': - *x = '\n'; - break; - case 'r': - *x = '\r'; - break; - case 't': - *x = '\t'; - break; - case 'b': - *x = '\b'; - break; - default: - if (*p >= '0' && *p <= '9') - *x = *p - '0'; - else - *x = *p; - break; - } - } - break; - default: - if (*p == '\r' || *p == '\n' || *p == '#') *p = '\0'; - *x = *p; - break; - } - - if (*p == 0) - break; - } - - // trim tailing spaces - p--; - while (p > s && (*p == ' ' || *p == '\t')) - *p-- = '\0'; - - return s; -} - -static int cli_env_to_idx(char env) -{ - int idx = -1; - - if (env >= '0' && env <= '9') { - idx = env - '0' + 1; - } - else if (env == '?') { - idx = 0; - } - - return idx; -} - -int cli_env_set(char env, int val) -{ - int idx = cli_env_to_idx(env); - - if (idx >= 0) { - m_cli_envs[idx] = val; - return 0; - } - else - return -1; -} - -int cli_env_get(char env) -{ - int idx = cli_env_to_idx(env); - - return idx >= 0 ? m_cli_envs[idx] : 0; -} - -/** exec command times: - * exec [...] - */ -static int cmd_exec(int argc, char *argv[]) -{ - int n = 0; - const struct cli_command *cmd; - - CHK_ARGC(3, 0); - - if (sscanf(argv[1], "%d", &n) != 1) - return CLI_INVALID_ARG; - if (n <= 0) - return CLI_INVALID_ARG; - - cmd = cli_find(argv[2]); - if (cmd == NULL) { - MSG("Unknown command '%s'\n", argv[2]); - return -1; - } - else { - argv += 2; - while (n-- >= 0) { - if (cmd->handler(argc - 2, argv) != 0) - return -1; - } - } - - return 0; -} - -/** - * test expression - * test - * for example: - * test 1 > 0 ==> return 0 - * test 1 <= 0 ==> return -1 - */ -static int cmd_test(int argc, char *argv[]) -{ - int a, b; - char *op; - BOOL tst = FALSE; - - CHK_ARGC(4, 4); - - if (sscanf(argv[1], "%d", &a) != 1 || - sscanf(argv[3], "%d", &b) != 1) - { - return CLI_INVALID_ARG; - } - - op = argv[2]; - if (!strcmp(op, ">")) { - tst = (a > b); - } - else if (!strcmp(op, "<")) { - tst = (a < b); - } - else if (!strcmp(op, "==")) { - tst = (a == b); - } - else if (!strcmp(op, ">=")) { - tst = (a >= b); - } - else if (!strcmp(op, "<=")) { - tst = (a <= b); - } - else if (!strcmp(op, "!=")) { - tst = (a != b); - } - else { - return CLI_INVALID_ARG; - } - - return tst ? 0 : -1; -} - -/** if last command failed (return != 0), run - * ! - */ -static int cmd_failed(int argc, char *argv[]) -{ - const struct cli_command *cmd; - - CHK_ARGC(2, 0); - - cmd = cli_find(argv[1]); - if (cmd == NULL) { - MSG("Unknown command '%s'\n", argv[1]); - return -1; - } - else { - argv++; - return (cli_env_get('?') == 0 ? 0 : cmd->handler(argc - 1, argv)); - } -} - -/** print messages - * echo [ ...] - */ -static int cmd_echo(int argc, char *argv[]) -{ - int i; - - for (i = 1; i < argc; i++) { - MSG("%s%s", i > 1 ? " " : "", argv[i]); - } - MSG("\n"); - - return 0; -} - -/** set cli environment variable - * set - */ -static int cmd_set(int argc, char *argv[]) -{ - int val; - int ret = -1; - - CHK_ARGC(3, 0); - - if (sscanf(argv[2], "%d", &val) == 1) { - ret = cli_env_set(argv[1][0], val); - } - - return ret; -} - -/** evaluation the expresstion, result to $1 - * evl - */ -static int cmd_evl(int argc, char *argv[]) -{ - int val1, val2, result = 0; - int ret = -1; - - CHK_ARGC(4, 4); - - if (sscanf(argv[1], "%d", &val1) == 1 && - sscanf(argv[3], "%d", &val2) == 1) { - ret = 0; - switch(argv[2][0]) { - case '+': - result = val1 + val2; - break; - case '-': - result = val1 - val2; - break; - case '*': - result = val1 * val2; - break; - case '/': - if (val2 == 0) - ret = -1; - else - result = val1 / val2; - break; - case '%': - if (val2 == 0) - ret = -1; - else - result = val1 % val2; - break; - default: - ret = CLI_INVALID_ARG; - break; - } - } - - if (ret == 0) - ret = cli_env_set('1', result); - - return ret; -} - -static int cmd_exit(int argc, char *argv[]) -{ - m_exit = TRUE; - return 0; -} - -/** Abort current script - * abort [...] - */ -static int cmd_abort(int argc, char *argv[]) -{ - if (argc > 1) { - cmd_echo(argc, argv); - } - - m_abort = TRUE; - - return 0; -} - -/** run local file system's script - * script - */ -static int cmd_script(int argc, char *argv[]) -{ - char line_buf[256]; - char *p; - FILE *fp; - const char *name; - int ret = 0; - static int stack = 0; - - CHK_ARGC(2, 0); - - if (stack++ == 0) - m_abort = FALSE; - - name = argv[1]; - fp = fopen(name, "r"); - - if (fp) { - memset(line_buf, 0, sizeof(line_buf)); - while (!m_abort && fgets(line_buf, sizeof(line_buf) - 1, fp)) { - p = line_buf + sizeof(line_buf) - 1; - while (*p == 0 && p > line_buf) - p--; - while ((*p == '\r' || *p == '\n') && p > line_buf) { - *p-- = 0; - } - p = cli_process_line(line_buf); - if (*p) - ret = cli_interpret(p); - memset(line_buf, 0, sizeof(line_buf)); - } - fclose(fp); - } - else { - MSG("Can't open host script file '%s' for read\n", name); - ret = -1; - } - - stack--; - - return ret; -} - - - -static const struct cli_command default_cmds[] = -{ - { cmd_help, "help|?", "[]", "show commands or help on one command" }, - { cmd_exit, "exit", NULL, "exit command line" }, - { cmd_exec, "*", " [...]>", "run times" }, - { cmd_failed, "!", " [...]", "run if last command failed" }, - { cmd_echo, "echo", "[...]", "print messages" }, - { cmd_set, "set", " ", "set env variable" }, - { cmd_evl, "evl", " ", "evaluation expresstion" }, - { cmd_test, "test", " ", "test expression: " }, - { cmd_script, "script", "", "run host script " }, - { cmd_abort, "abort", NULL, "abort from the running script" }, - { NULL, NULL, NULL, NULL } -}; - -static struct cli_commandset default_cmdset = { - default_cmds, -}; - -static BOOL match_cmd(const char *src, int start, int end, const char *des) -{ - while (src[start] == ' ' && start < end) - start++; - - while (src[end] == ' ' && start < end) - end--; - - if ((int)strlen(des) == (end - start + 1)) { - if (memcmp(src + start, des, end - start + 1) == 0) { - return TRUE; - } - } - - return FALSE; -} - -static BOOL check_cmd(const char *cmds, const char *cmd) -{ - int start, end; - - for (start = end = 0; cmds[end] != 0 && cmds[end] != '|'; end++); - - while (end > start) { - if (match_cmd(cmds, start, end - 1, cmd) == TRUE) - return TRUE; - if (cmds[end] == 0) - break; - if (cmds[end] == '|') { - end++; - for (start = end; cmds[end] != 0 && cmds[end] != '|'; end++); - } - } - - return FALSE; -} - -static const struct cli_command * cli_find(const char *cmd) -{ - struct cli_commandset *work; - const struct cli_command *s; - - FOR_EACH_CLI_CMD(work, s) { - if (check_cmd(s->cmd, cmd) == TRUE) - return s; - } - - return NULL; -} - -static void show_cmd_usage(const struct cli_command *cmd) -{ - MSG("%s: %s\n", cmd->cmd, cmd->descr); - MSG("Usage: %s %s\n", cmd->cmd, cmd->args ? cmd->args : ""); -} - -static int cmd_help(int argc, char *argv[]) -{ - const struct cli_command *cmd; - struct cli_commandset *cmdset; - int i, n; - - if (argc < 2) { - MSG("Available commands:\n"); - n = 0; - FOR_EACH_CLI_CMD(cmdset, cmd) { - MSG("%s", cmd->cmd); - for (i = strlen(cmd->cmd); i%10; i++, MSG(" ")); - if ((++n % 5) == 0) MSG("\n"); - } - MSG("\n"); - } - else { - cmd = cli_find(argv[1]); - if (cmd == NULL) { - MSG("No such command\n"); - return -1; - } - else { - show_cmd_usage(cmd); - } - } - - return 0; -} - -static void cli_parse_args(const char *cmd, struct cli_arg *arg) -{ - char *p; - int val; - - if (arg) { - arg->argc = 0; - if (cmd) { - p = arg->_buf; - while (*cmd && arg->argc < MAX_CLI_ARGS_NUM && (p - arg->_buf < MAX_CLI_ARGS_BUF_LEN)) { - while(*cmd && (*cmd == ' ' || *cmd == '\t')) - cmd++; - - arg->argv[arg->argc] = p; - while (*cmd && (*cmd != ' ' && *cmd != '\t') && (p - arg->_buf < MAX_CLI_ARGS_BUF_LEN)) { - if (*cmd == '$') { - // command env replacement - cmd++; - val = cli_env_get(*cmd++); - if (p - arg->_buf < MAX_CLI_ARGS_BUF_LEN - 12) { // 12 is long enough for 32bit 'int' - p += sprintf(p, "%d", val & 0xFFFFFFFF); - } - } - else - *p++ = *cmd++; - } - *p++ = '\0'; - - if (*(arg->argv[arg->argc]) == '\0') - break; - arg->argc++; - } - } - } -} - -int cli_interpret(const char *line) -{ - struct cli_arg arg = {0}; - const struct cli_command *cmd; - int ret = -1; - - cli_parse_args(line, &arg); - - if (arg.argc > 0) { - cmd = cli_find(arg.argv[0]); - if (cmd == NULL) { - MSG("Unknown command '%s'\n", arg.argv[0]); - } - else { - ret = cmd->handler(arg.argc, arg.argv); - if (ret == CLI_INVALID_ARG) { - MSG("\n"); - show_cmd_usage(cmd); - } - } - } - - cli_env_set('?', ret); // $? = last command return code - - return ret; -} - -void cli_add_commandset(struct cli_commandset *set) -{ - if (set) { - set->next = m_cmdset_head; - m_cmdset_head = set; - } -} - -void cli_main_entry() -{ - char line[80]; - int linelen = 0; - char *p; - - MSG("$ "); - cli_add_commandset(&default_cmdset); - - while (!m_exit) { - char ch; - if (linelen >= sizeof(line)) - continue; - ch = getc(stdin); - switch (ch) { - case 8: - case 127: - if (linelen > 0) { - --linelen; - MSG("\x08 \x08"); - } - break; - - case '\r': - case '\n': - //MSG("\r\n"); - if (linelen > 0) { - line[linelen] = 0; - p = cli_process_line(line); - if (*p) - cli_interpret(p); - linelen = 0; - } - MSG("$ "); - break; - - case 21: - while (linelen > 0) { - --linelen; - MSG("\x08 \x08"); - } - break; - - default: - if (ch >= ' ' && ch < 127 && linelen < sizeof(line) - 1) { - line[linelen++] = ch; - //MSG("%c", ch); - } - } - } -} diff --git a/components/dfs/filesystems/uffs/src/emu/cmdline.h b/components/dfs/filesystems/uffs/src/emu/cmdline.h deleted file mode 100644 index 284d68eaea..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/cmdline.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - - -#ifndef _UFFS_CLI_H_ -#define _UFFS_CLI_H_ - -#ifndef BOOL -#define BOOL int -#endif - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define CLI_INVALID_ARG -100 - -typedef int command_t(int argc, char *argv[]); - -struct cli_command { - command_t *handler; - const char *cmd; - const char *args; - const char *descr; -}; - -struct cli_commandset { - const struct cli_command *cmds; - struct cli_commandset *next; -}; - -void cli_add_commandset(struct cli_commandset *set); -int cli_interpret(const char *line); -int cli_env_get(char env); -int cli_env_set(char env, int val); -void cli_main_entry(); - -#define u_assert(x) \ - ((x) ? TRUE : \ - (uffs_PerrorRaw(UFFS_MSG_NORMAL, \ - "Assert failed at %s:%s:%d: '%s' is not true.\n", \ - __FILE__, __FUNCTION__, __LINE__, #x), FALSE)) - - -#define CHK_ARGC(min, max) \ - if (argc < min || (max > 0 && argc > max)) \ - return CLI_INVALID_ARG - -#endif - - diff --git a/components/dfs/filesystems/uffs/src/emu/helper_cmds.c b/components/dfs/filesystems/uffs/src/emu/helper_cmds.c deleted file mode 100644 index 1526c441ca..0000000000 --- a/components/dfs/filesystems/uffs/src/emu/helper_cmds.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - This file is part of UFFS, the Ultra-low-cost Flash File System. - - Copyright (C) 2005-2009 Ricky Zheng - - UFFS is free software; you can redistribute it and/or modify it under - the GNU Library General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - - UFFS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - or GNU Library General Public License, as applicable, for more details. - - You should have received a copy of the GNU General Public License - and GNU Library General Public License along with UFFS; if not, write - to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - As a special exception, if other files instantiate templates or use - macros or inline functions from this file, or you compile this file - and link it with other works to produce a work based on this file, - this file does not by itself cause the resulting work to be covered - by the GNU General Public License. However the source code for this - file must still be made available in accordance with section (3) of - the GNU General Public License v2. - - This exception does not invalidate any other reasons why a work based - on this file might be covered by the GNU General Public License. -*/ - -/** - * \file helper_cmds.c - * \brief helper commands for test uffs - * \author Ricky Zheng - */ -#include -#include -#include -#include -#include "uffs_config.h" -#include "uffs/uffs_public.h" -#include "uffs/uffs_fs.h" -#include "uffs/uffs_utils.h" -#include "uffs/uffs_core.h" -#include "uffs/uffs_mtb.h" -#include "uffs/uffs_find.h" -#include "cmdline.h" -#include "uffs/uffs_fd.h" -#include "uffs/uffs_mtb.h" -#include "uffs_fileem.h" - -#define PFX "cmd : " - -#define MAX_PATH_LENGTH 128 - -#define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) -#define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__) - -/** format [] */ -static int cmd_format(int argc, char *argv[]) -{ - URET ret; - const char *mount = "/"; - uffs_Device *dev; - UBOOL force = U_FALSE; - - if (argc > 1) { - mount = argv[1]; - if (argc > 2 && strcmp(argv[2], "-f") == 0) - force = U_TRUE; - } - MSGLN("Formating %s ... ", mount); - - dev = uffs_GetDeviceFromMountPoint(mount); - if (dev == NULL) { - MSGLN("Can't get device from mount point."); - return -1; - } - else { - ret = uffs_FormatDevice(dev, force); - if (ret != U_SUCC) { - MSGLN("Format fail."); - return -1; - } - else { - MSGLN("Format succ."); - } - uffs_PutDevice(dev); - } - - return 0; -} - -/** mkf */ -static int cmd_mkf(int argc, char *argv[]) -{ - int fd; - const char *name; - int oflags = UO_RDWR | UO_CREATE; - - CHK_ARGC(2, 2); - - name = argv[1]; - fd = uffs_open(name, oflags); - if (fd < 0) { - MSGLN("Create %s fail, err: %d", name, uffs_get_error()); - return -1; - } - else { - MSGLN("Create %s succ.", name); - uffs_close(fd); - } - - return 0; -} - -/** mkdir