diff options
Diffstat (limited to 'fs')
34 files changed, 197 insertions, 46 deletions
diff --git a/fs/btrfs/dev.c b/fs/btrfs/dev.c index cb3b9713a5f..e27a032c9f6 100644 --- a/fs/btrfs/dev.c +++ b/fs/btrfs/dev.c @@ -5,7 +5,6 @@ * 2017 Marek BehĂșn, CZ.NIC, kabel@kernel.org */ -#include <common.h> #include <blk.h> #include <compiler.h> #include <fs_internal.h> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7eaa7e94960..e5bfaf461c2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -#include <common.h> #include <fs_internal.h> #include <log.h> #include <uuid.h> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 7d4095d9ca8..8ec545eded7 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ #include <stdlib.h> -#include <common.h> +#include <errno.h> #include <fs_internal.h> #include "ctree.h" #include "disk-io.h" diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 714f4baafc9..ad5583233bb 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -3,10 +3,10 @@ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. */ -#include <common.h> #include <cbfs.h> #include <log.h> #include <malloc.h> +#include <linux/errno.h> #include <asm/byteorder.h> /* Offset of master header from the start of a coreboot ROM */ diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index abb2de34eb0..22148ff8fe2 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -24,7 +24,7 @@ * The actual compression is based on zlib, see the other files. */ -#include <common.h> +#include <stdio.h> #include <malloc.h> #include <asm/byteorder.h> #include <linux/stat.h> diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c index 0d071b69f4c..2141edf22e4 100644 --- a/fs/cramfs/uncompress.c +++ b/fs/cramfs/uncompress.c @@ -20,7 +20,7 @@ * then is used by multiple filesystems. */ -#include <common.h> +#include <stdio.h> #include <cyclic.h> #include <malloc.h> #include <watchdog.h> diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index ee4e777c5c8..c8463357ca2 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -19,3 +19,18 @@ config FS_EROFS_ZIP help Enable fixed-sized output compression for EROFS. If you don't want to enable compression feature, say N. + +config FS_EROFS_ZIP_DEFLATE + bool "EROFS DEFLATE compressed data support" + depends on FS_EROFS_ZIP + select ZLIB + help + Saying Y here includes support for reading EROFS file systems + containing DEFLATE compressed data. It gives better compression + ratios than the default LZ4 format, while it costs more CPU + overhead. + + DEFLATE support is an experimental feature for now and so most + file systems will be readable without selecting this option. + + If unsure, say N. diff --git a/fs/erofs/decompress.c b/fs/erofs/decompress.c index e04e5c34a8d..ec74816534c 100644 --- a/fs/erofs/decompress.c +++ b/fs/erofs/decompress.c @@ -1,6 +1,85 @@ // SPDX-License-Identifier: GPL-2.0+ #include "decompress.h" +#if IS_ENABLED(CONFIG_ZLIB) +#include <u-boot/zlib.h> + +/* report a zlib or i/o error */ +static int zerr(int ret) +{ + switch (ret) { + case Z_STREAM_ERROR: + return -EINVAL; + case Z_DATA_ERROR: + return -EIO; + case Z_MEM_ERROR: + return -ENOMEM; + case Z_ERRNO: + default: + return -EFAULT; + } +} + +static int z_erofs_decompress_deflate(struct z_erofs_decompress_req *rq) +{ + u8 *dest = (u8 *)rq->out; + u8 *src = (u8 *)rq->in; + u8 *buff = NULL; + unsigned int inputmargin = 0; + z_stream strm; + int ret; + + while (!src[inputmargin & (erofs_blksiz() - 1)]) + if (!(++inputmargin & (erofs_blksiz() - 1))) + break; + + if (inputmargin >= rq->inputsize) + return -EFSCORRUPTED; + + if (rq->decodedskip) { + buff = malloc(rq->decodedlength); + if (!buff) + return -ENOMEM; + dest = buff; + } + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -15); + if (ret != Z_OK) { + free(buff); + return zerr(ret); + } + + strm.next_in = src + inputmargin; + strm.avail_in = rq->inputsize - inputmargin; + strm.next_out = dest; + strm.avail_out = rq->decodedlength; + + ret = inflate(&strm, rq->partial_decoding ? Z_SYNC_FLUSH : Z_FINISH); + if (ret != Z_STREAM_END || strm.total_out != rq->decodedlength) { + if (ret != Z_OK || !rq->partial_decoding) { + ret = zerr(ret); + goto out_inflate_end; + } + } + + if (rq->decodedskip) + memcpy(rq->out, dest + rq->decodedskip, + rq->decodedlength - rq->decodedskip); + +out_inflate_end: + inflateEnd(&strm); + if (buff) + free(buff); + return ret; +} +#endif + #if IS_ENABLED(CONFIG_LZ4) #include <u-boot/lz4.h> static int z_erofs_decompress_lz4(struct z_erofs_decompress_req *rq) @@ -94,5 +173,9 @@ int z_erofs_decompress(struct z_erofs_decompress_req *rq) if (rq->alg == Z_EROFS_COMPRESSION_LZ4) return z_erofs_decompress_lz4(rq); #endif +#if IS_ENABLED(CONFIG_ZLIB) + if (rq->alg == Z_EROFS_COMPRESSION_DEFLATE) + return z_erofs_decompress_deflate(rq); +#endif return -EOPNOTSUPP; } diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 158e2c68a1a..5bac4fe1a1d 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -304,6 +304,7 @@ enum { enum { Z_EROFS_COMPRESSION_LZ4 = 0, Z_EROFS_COMPRESSION_LZMA = 1, + Z_EROFS_COMPRESSION_DEFLATE = 2, Z_EROFS_COMPRESSION_MAX }; diff --git a/fs/ext4/dev.c b/fs/ext4/dev.c index 168443de1ff..3fd8980b1d6 100644 --- a/fs/ext4/dev.c +++ b/fs/ext4/dev.c @@ -22,7 +22,6 @@ * fs/ext2/dev.c file in uboot. */ -#include <common.h> #include <blk.h> #include <config.h> #include <fs_internal.h> diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 365c5147c4b..857c15d878e 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -18,7 +18,6 @@ * ext4write : Based on generic ext4 protocol. */ -#include <common.h> #include <blk.h> #include <ext_common.h> #include <ext4fs.h> @@ -765,11 +764,6 @@ int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags) struct ext2_inode *first_inode = NULL; struct ext2_inode temp_inode; - if (*dirname != '/') { - printf("Please supply Absolute path\n"); - return -1; - } - /* TODO: input validation make equivalent to linux */ depth_dirname = zalloc(strlen(dirname) + 1); if (!depth_dirname) diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c index 1a340b4764c..02c4ac2cb93 100644 --- a/fs/ext4/ext4_journal.c +++ b/fs/ext4/ext4_journal.c @@ -13,7 +13,6 @@ * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved */ -#include <common.h> #include <blk.h> #include <ext4fs.h> #include <log.h> @@ -430,7 +429,7 @@ int ext4fs_check_journal_state(int recovery_flag) printf("Recovery required\n"); } else { if (recovery_flag == RECOVER) - printf("File System is consistent\n"); + log_debug("File System is consistent\n"); goto end; } diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index ea4c5d4157c..38da3923c47 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -21,7 +21,6 @@ */ -#include <common.h> #include <blk.h> #include <log.h> #include <malloc.h> @@ -847,6 +846,7 @@ int ext4fs_write(const char *fname, const char *buffer, { int ret = 0; struct ext2_inode *file_inode = NULL; + struct ext2_inode *existing_file_inode = NULL; unsigned char *inode_buffer = NULL; int parent_inodeno; int inodeno; @@ -900,6 +900,15 @@ int ext4fs_write(const char *fname, const char *buffer, /* check if the filename is already present in root */ existing_file_inodeno = ext4fs_filename_unlink(filename); if (existing_file_inodeno != -1) { + existing_file_inode = (struct ext2_inode *)zalloc(fs->inodesz); + if (!existing_file_inode) + goto fail; + ret = ext4fs_iget(existing_file_inodeno, existing_file_inode); + if (ret) { + free(existing_file_inode); + goto fail; + } + ret = ext4fs_delete_file(existing_file_inodeno); fs->first_pass_bbmap = 0; fs->curr_blkno = 0; @@ -948,9 +957,15 @@ int ext4fs_write(const char *fname, const char *buffer, sizebytes = 0; } } else { - file_inode->mode = cpu_to_le16(S_IFREG | S_IRWXU | S_IRGRP | - S_IROTH | S_IXGRP | S_IXOTH); + if (existing_file_inode) { + file_inode->mode = existing_file_inode->mode; + } else { + file_inode->mode = cpu_to_le16(S_IFREG | S_IRWXU | S_IRGRP | + S_IROTH | S_IXGRP | S_IXOTH); + } } + if (existing_file_inode) + free(existing_file_inode); /* ToDo: Update correct time */ file_inode->mtime = cpu_to_le32(timestamp); file_inode->atime = cpu_to_le32(timestamp); diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index 33e200ffa3c..da59cb008fc 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -20,7 +20,6 @@ * ext4write : Based on generic ext4 protocol. */ -#include <common.h> #include <blk.h> #include <ext_common.h> #include <ext4fs.h> diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 14e53cf2d5a..e2570e81676 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -10,7 +10,6 @@ #define LOG_CATEGORY LOGC_FS -#include <common.h> #include <blk.h> #include <config.h> #include <exports.h> @@ -1254,7 +1253,7 @@ out: static void __maybe_unused fat2rtc(u16 date, u16 time, struct rtc_time *tm) { tm->tm_mday = date & 0x1f; - tm->tm_mon = (date & 0x1e0) >> 4; + tm->tm_mon = (date & 0x1e0) >> 5; tm->tm_year = (date >> 9) + 1980; tm->tm_sec = (time & 0x1f) << 1; diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 8b5d669b005..ea877ee9171 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -7,7 +7,6 @@ #define LOG_CATEGORY LOGC_FS -#include <common.h> #include <command.h> #include <config.h> #include <div64.h> @@ -18,6 +17,7 @@ #include <rand.h> #include <asm/byteorder.h> #include <asm/cache.h> +#include <dm/uclass.h> #include <linux/ctype.h> #include <linux/math64.h> #include "fat.c" @@ -1152,6 +1152,41 @@ getit: } /** + * dentry_set_time() - set change time + * + * @dentptr: directory entry + */ +static void dentry_set_time(dir_entry *dentptr) +{ + if (CONFIG_IS_ENABLED(DM_RTC)) { + struct udevice *dev; + struct rtc_time tm; + u16 date; + u16 time; + + uclass_first_device(UCLASS_RTC, &dev); + if (!dev) + goto err; + if (dm_rtc_get(dev, &tm)) + goto err; + if (tm.tm_year < 1980 || tm.tm_year > 2107) + goto err; + date = (tm.tm_mday & 0x1f) | + ((tm.tm_mon & 0xf) << 5) | + ((tm.tm_year - 1980) << 9); + time = (tm.tm_sec > 1) | + ((tm.tm_min & 0x3f) << 5) | + (tm.tm_hour << 11); + dentptr->date = date; + dentptr->time = time; + return; + } +err: + dentptr->date = 0x2821; /* 2000-01-01 */ + dentptr->time = 0; +} + +/** * fill_dentry() - fill directory entry with shortname * * @mydata: private filesystem parameters @@ -1171,6 +1206,12 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, dentptr->attr = attr; + /* Set change date */ + dentry_set_time(dentptr); + /* Set creation date */ + dentptr->cdate = dentptr->date; + dentptr->ctime = dentptr->time; + memcpy(&dentptr->nameext, shortname, SHORT_NAME_SIZE); } @@ -1376,6 +1417,8 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer, /* Update file size in a directory entry */ retdent->size = cpu_to_le32(pos + size); + /* Update change date */ + dentry_set_time(retdent); } else { /* Create a new file */ char shortname[SHORT_NAME_SIZE]; @@ -9,7 +9,6 @@ #include <config.h> #include <display_options.h> #include <errno.h> -#include <common.h> #include <env.h> #include <lmb.h> #include <log.h> @@ -21,6 +20,7 @@ #include <fs.h> #include <sandboxfs.h> #include <semihostingfs.h> +#include <time.h> #include <ubifs_uboot.h> #include <btrfs.h> #include <asm/global_data.h> diff --git a/fs/fs_internal.c b/fs/fs_internal.c index 111f91b355d..51c1719361b 100644 --- a/fs/fs_internal.c +++ b/fs/fs_internal.c @@ -7,7 +7,6 @@ #define LOG_CATEGORY LOGC_CORE -#include <common.h> #include <blk.h> #include <compiler.h> #include <log.h> diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index d306b6dc4cf..e1e3c15e75e 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -35,8 +35,6 @@ * */ -#include <common.h> -#include <config.h> #include <jffs2/jffs2.h> #include <jffs2/mini_inflate.h> diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 49ba82ef959..5b7d7f4ae88 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -111,7 +111,6 @@ */ -#include <common.h> #include <config.h> #include <malloc.h> #include <div64.h> diff --git a/fs/jffs2/mergesort.c b/fs/jffs2/mergesort.c index fca77aa6511..495937d792d 100644 --- a/fs/jffs2/mergesort.c +++ b/fs/jffs2/mergesort.c @@ -7,7 +7,6 @@ * http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html */ -#include <common.h> #include "jffs2_private.h" int sort_list(struct b_list *list) diff --git a/fs/sandbox/host_bootdev.c b/fs/sandbox/host_bootdev.c index 3ef53627608..3f74972a9f8 100644 --- a/fs/sandbox/host_bootdev.c +++ b/fs/sandbox/host_bootdev.c @@ -6,7 +6,6 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <common.h> #include <bootdev.h> #include <bootflow.h> #include <bootmeth.h> diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index 4ae41d5b4db..773b583fa43 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -3,7 +3,7 @@ * Copyright (c) 2012, Google Inc. */ -#include <common.h> +#include <stdio.h> #include <fs.h> #include <malloc.h> #include <os.h> diff --git a/fs/semihostingfs.c b/fs/semihostingfs.c index 3592338a686..77e39ca407e 100644 --- a/fs/semihostingfs.c +++ b/fs/semihostingfs.c @@ -4,7 +4,7 @@ * Copyright (c) 2012, Google Inc. */ -#include <common.h> +#include <stdio.h> #include <fs.h> #include <malloc.h> #include <os.h> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 3e7160352e6..788f88f0495 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -29,7 +29,6 @@ #include <linux/writeback.h> #else -#include <common.h> #include <malloc.h> #include <memalign.h> #include <linux/bitops.h> diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index a509584e5d7..75de01e95f7 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -11,7 +11,6 @@ * Adrian Hunter */ -#include <common.h> #include <env.h> #include <gzip.h> #include <log.h> diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c index 50fed2d4b15..0eec22bc4a5 100644 --- a/fs/yaffs2/yaffs_mtdif.c +++ b/fs/yaffs2/yaffs_mtdif.c @@ -12,7 +12,6 @@ */ /* XXX U-BOOT XXX */ -#include <common.h> #include "yportenv.h" diff --git a/fs/yaffs2/yaffs_mtdif2.c b/fs/yaffs2/yaffs_mtdif2.c index 81a4d964f3e..2bf171f99f1 100644 --- a/fs/yaffs2/yaffs_mtdif2.c +++ b/fs/yaffs2/yaffs_mtdif2.c @@ -14,7 +14,6 @@ /* mtd interface for YAFFS2 */ /* XXX U-BOOT XXX */ -#include <common.h> #include <linux/bug.h> #include <linux/errno.h> diff --git a/fs/yaffs2/yaffs_uboot_glue.c b/fs/yaffs2/yaffs_uboot_glue.c index 0a920561149..deddbaac51e 100644 --- a/fs/yaffs2/yaffs_uboot_glue.c +++ b/fs/yaffs2/yaffs_uboot_glue.c @@ -19,7 +19,6 @@ * This version now uses the ydevconfig mechanism to set up partitions. */ -#include <common.h> #include <div64.h> #include <malloc.h> #include <linux/printk.h> diff --git a/fs/zfs/dev.c b/fs/zfs/dev.c index 251e7d1f74f..722c6a86176 100644 --- a/fs/zfs/dev.c +++ b/fs/zfs/dev.c @@ -8,7 +8,6 @@ */ -#include <common.h> #include <config.h> #include <fs_internal.h> #include <zfs_common.h> @@ -26,5 +25,5 @@ void zfs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info) int zfs_devread(int sector, int byte_offset, int byte_len, char *buf) { return fs_devread(zfs_blk_desc, part_info, sector, byte_offset, - byte_len, buf); + byte_len, buf) ? 0 : 1; } diff --git a/fs/zfs/zfs.c b/fs/zfs/zfs.c index 1fec96cd5ce..c44e7ece5df 100644 --- a/fs/zfs/zfs.c +++ b/fs/zfs/zfs.c @@ -10,7 +10,6 @@ * Copyright 2004 Sun Microsystems, Inc. */ -#include <common.h> #include <log.h> #include <malloc.h> #include <linux/stat.h> @@ -655,7 +654,7 @@ dmu_read(dnode_end_t *dn, uint64_t blkid, void **buf, dn->endian) << SPA_MINBLOCKSHIFT; *buf = malloc(size); - if (*buf) { + if (!*buf) { err = ZFS_ERR_OUT_OF_MEMORY; break; } @@ -1559,6 +1558,10 @@ nvlist_find_value(char *nvlist, char *name, int valtype, char **val, return 0; } +int is_word_aligned_ptr(void *ptr) { + return ((uintptr_t)ptr & (sizeof(void *) - 1)) == 0; +} + int zfs_nvlist_lookup_uint64(char *nvlist, char *name, uint64_t *out) { @@ -1574,6 +1577,20 @@ zfs_nvlist_lookup_uint64(char *nvlist, char *name, uint64_t *out) return ZFS_ERR_BAD_FS; } + /* On arm64, calling be64_to_cpu() on a value stored at a memory address + * that's not 8-byte aligned causes the CPU to reset. Avoid that by copying the + * value somewhere else if needed. + */ + if (!is_word_aligned_ptr((void *)nvpair)) { + uint64_t *alignedptr = malloc(sizeof(uint64_t)); + if (!alignedptr) + return 0; + memcpy(alignedptr, nvpair, sizeof(uint64_t)); + *out = be64_to_cpu(*alignedptr); + free(alignedptr); + return 1; + } + *out = be64_to_cpu(*(uint64_t *) nvpair); return 1; } @@ -1617,6 +1634,11 @@ zfs_nvlist_lookup_nvlist(char *nvlist, char *name) &size, 0); if (!found) return 0; + + /* Allocate 12 bytes in addition to the nvlist size: One uint32 before the + * nvlist to hold the encoding method, and two zero uint32's after the + * nvlist as the NULL terminator. + */ ret = calloc(1, size + 3 * sizeof(uint32_t)); if (!ret) return 0; @@ -2112,7 +2134,7 @@ zfs_read(zfs_file_t file, char *buf, uint64_t len) * Find requested blkid and the offset within that block. */ uint64_t blkid = file->offset + red; - blkid = do_div(blkid, blksz); + uint64_t blkoff = do_div(blkid, blksz); free(data->file_buf); data->file_buf = 0; @@ -2127,8 +2149,7 @@ zfs_read(zfs_file_t file, char *buf, uint64_t len) movesize = min(length, data->file_end - (int)file->offset - red); - memmove(buf, data->file_buf + file->offset + red - - data->file_start, movesize); + memmove(buf, data->file_buf + blkoff, movesize); buf += movesize; length -= movesize; red += movesize; diff --git a/fs/zfs/zfs_fletcher.c b/fs/zfs/zfs_fletcher.c index 008a303ec79..b06c335626a 100644 --- a/fs/zfs/zfs_fletcher.c +++ b/fs/zfs/zfs_fletcher.c @@ -8,7 +8,6 @@ * Use is subject to license terms. */ -#include <common.h> #include <malloc.h> #include <linux/stat.h> #include <linux/time.h> diff --git a/fs/zfs/zfs_lzjb.c b/fs/zfs/zfs_lzjb.c index b42d4980129..e79c5b4278f 100644 --- a/fs/zfs/zfs_lzjb.c +++ b/fs/zfs/zfs_lzjb.c @@ -8,7 +8,6 @@ * Use is subject to license terms. */ -#include <common.h> #include <malloc.h> #include <linux/stat.h> #include <linux/time.h> diff --git a/fs/zfs/zfs_sha256.c b/fs/zfs/zfs_sha256.c index cb5b1c06834..602d75254ff 100644 --- a/fs/zfs/zfs_sha256.c +++ b/fs/zfs/zfs_sha256.c @@ -8,7 +8,6 @@ * Use is subject to license terms. */ -#include <common.h> #include <malloc.h> #include <linux/stat.h> #include <linux/time.h> |
