summaryrefslogtreecommitdiff
path: root/release/src/linux/linux
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 13:58:15 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 13:58:15 +0100
commit4aca87515a5083ae0e31ce3177189fd43b6d05ac (patch)
tree7b1d9a31393ca090757dc6f0d3859b4fcd93f271 /release/src/linux/linux
parent008d0be72b2f160382c6e880765e96b64a050c65 (diff)
downloadtomato-4aca87515a5083ae0e31ce3177189fd43b6d05ac.tar.gz
tomato-4aca87515a5083ae0e31ce3177189fd43b6d05ac.tar.bz2
patch to Vanilla Tomato 1.28
Diffstat (limited to 'release/src/linux/linux')
-rw-r--r--release/src/linux/linux/.config176
-rw-r--r--release/src/linux/linux/Documentation/Configure.help14116
-rw-r--r--release/src/linux/linux/Documentation/filesystems/00-INDEX2
-rw-r--r--release/src/linux/linux/Documentation/filesystems/cifs.txt51
-rw-r--r--release/src/linux/linux/Makefile6
-rw-r--r--release/src/linux/linux/arch/mips/Makefile2
-rw-r--r--release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c41
-rw-r--r--release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c43
-rw-r--r--release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/setup.c245
-rw-r--r--release/src/linux/linux/arch/mips/kernel/branch.c2
-rw-r--r--release/src/linux/linux/arch/mips/kernel/mips_ksyms.c1
-rw-r--r--release/src/linux/linux/arch/mips/math-emu/cp1emu.c5
-rw-r--r--release/src/linux/linux/drivers/char/serial.c4
-rw-r--r--release/src/linux/linux/drivers/mtd/chips/gen_probe.c1
-rw-r--r--release/src/linux/linux/drivers/net/Config.in5
-rw-r--r--release/src/linux/linux/drivers/net/Makefile15
-rwxr-xr-x[-rw-r--r--]release/src/linux/linux/drivers/net/hnd/shared_ksyms.sh6
-rw-r--r--release/src/linux/linux/drivers/net/imq.c321
-rw-r--r--release/src/linux/linux/drivers/net/ppp_generic.c47
-rw-r--r--release/src/linux/linux/fs/Config.in15
-rw-r--r--release/src/linux/linux/fs/Makefile3
-rw-r--r--release/src/linux/linux/fs/buffer.c5
-rw-r--r--release/src/linux/linux/fs/cifs/AUTHORS37
-rw-r--r--release/src/linux/linux/fs/cifs/CHANGES572
-rw-r--r--release/src/linux/linux/fs/cifs/Makefile10
-rw-r--r--release/src/linux/linux/fs/cifs/README356
-rw-r--r--release/src/linux/linux/fs/cifs/TODO106
-rw-r--r--release/src/linux/linux/fs/cifs/asn1.c614
-rw-r--r--release/src/linux/linux/fs/cifs/cifs_debug.c797
-rw-r--r--release/src/linux/linux/fs/cifs/cifs_debug.h66
-rw-r--r--release/src/linux/linux/fs/cifs/cifs_fs_sb.h32
-rw-r--r--release/src/linux/linux/fs/cifs/cifs_unicode.c87
-rw-r--r--release/src/linux/linux/fs/cifs/cifs_unicode.h353
-rw-r--r--release/src/linux/linux/fs/cifs/cifs_uniupr.h253
-rw-r--r--release/src/linux/linux/fs/cifs/cifsencrypt.c204
-rw-r--r--release/src/linux/linux/fs/cifs/cifserr.c70
-rw-r--r--release/src/linux/linux/fs/cifs/cifsfs.c769
-rw-r--r--release/src/linux/linux/fs/cifs/cifsfs.h97
-rw-r--r--release/src/linux/linux/fs/cifs/cifsglob.h413
-rw-r--r--release/src/linux/linux/fs/cifs/cifspdu.h1793
-rw-r--r--release/src/linux/linux/fs/cifs/cifsproto.h254
-rw-r--r--release/src/linux/linux/fs/cifs/cifssmb.c3016
-rw-r--r--release/src/linux/linux/fs/cifs/connect.c2925
-rw-r--r--release/src/linux/linux/fs/cifs/dir.c425
-rw-r--r--release/src/linux/linux/fs/cifs/file.c2185
-rw-r--r--release/src/linux/linux/fs/cifs/inode.c1079
-rw-r--r--release/src/linux/linux/fs/cifs/link.c328
-rw-r--r--release/src/linux/linux/fs/cifs/md4.c203
-rw-r--r--release/src/linux/linux/fs/cifs/md5.c363
-rw-r--r--release/src/linux/linux/fs/cifs/md5.h38
-rw-r--r--release/src/linux/linux/fs/cifs/misc.c463
-rw-r--r--release/src/linux/linux/fs/cifs/netmisc.c905
-rw-r--r--release/src/linux/linux/fs/cifs/nterr.c687
-rw-r--r--release/src/linux/linux/fs/cifs/nterr.h556
-rw-r--r--release/src/linux/linux/fs/cifs/ntlmssp.h101
-rw-r--r--release/src/linux/linux/fs/cifs/rfc1002pdu.h79
-rw-r--r--release/src/linux/linux/fs/cifs/smbdes.c408
-rw-r--r--release/src/linux/linux/fs/cifs/smbencrypt.c295
-rw-r--r--release/src/linux/linux/fs/cifs/smberr.c240
-rw-r--r--release/src/linux/linux/fs/cifs/smberr.h113
-rw-r--r--release/src/linux/linux/fs/cifs/transport.c434
-rw-r--r--release/src/linux/linux/fs/nls/Config.in1
-rw-r--r--release/src/linux/linux/fs/squashfs/LzmaDecode.c663
-rw-r--r--release/src/linux/linux/fs/squashfs/LzmaDecode.h100
-rw-r--r--release/src/linux/linux/fs/squashfs/Makefile6
-rw-r--r--release/src/linux/linux/fs/squashfs/inode.c2401
-rw-r--r--release/src/linux/linux/fs/squashfs/squashfs.h85
-rw-r--r--release/src/linux/linux/fs/squashfs/squashfs2_0.c751
-rw-r--r--release/src/linux/linux/include/linux/fs.h2
-rw-r--r--release/src/linux/linux/include/linux/imq.h9
-rw-r--r--release/src/linux/linux/include/linux/jhash.h143
-rw-r--r--release/src/linux/linux/include/linux/list.h27
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack.h52
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_h323.h1
-rw-r--r--[-rwxr-xr-x]release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_esp.h0
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h4
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h1
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ip_tables.h3
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_BCOUNT.h16
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CLASSIFY.h8
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CONNMARK.h26
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_IMQ.h8
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_MACSAVE.h16
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h23
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_TTL.h21
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_account.h26
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_bcount.h18
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_condition.h11
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connlimit.h12
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connmark.h18
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_exp.h15
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_geoip.h51
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h31
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_iprange.h23
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_layer7.h26
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_macsave.h17
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_quota.h12
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_recent.h28
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_string.h21
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_time.h10
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_u32.h40
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv4/ipt_web.h30
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_IMQ.h8
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h23
-rw-r--r--release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_condition.h11
-rw-r--r--release/src/linux/linux/include/linux/pkt_sched.h59
-rw-r--r--release/src/linux/linux/include/linux/rbtree.h6
-rw-r--r--release/src/linux/linux/include/linux/skbuff.h8
-rw-r--r--release/src/linux/linux/include/linux/squashfs_fs.h777
-rw-r--r--release/src/linux/linux/include/linux/squashfs_fs_i.h27
-rw-r--r--release/src/linux/linux/include/linux/squashfs_fs_sb.h43
-rw-r--r--release/src/linux/linux/include/linux/sysctl.h6
-rw-r--r--release/src/linux/linux/include/net/pkt_cls.h6
-rw-r--r--release/src/linux/linux/include/net/pkt_sched.h15
-rw-r--r--release/src/linux/linux/include/net/sock.h14
-rw-r--r--release/src/linux/linux/include/net/tcp.h59
-rw-r--r--release/src/linux/linux/lib/Config.in2
-rw-r--r--release/src/linux/linux/lib/rbtree.c73
-rw-r--r--release/src/linux/linux/net/core/skbuff.c16
-rw-r--r--release/src/linux/linux/net/ipv4/arp.c24
-rw-r--r--release/src/linux/linux/net/ipv4/igmp.c5
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/Config.in63
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/Makefile41
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/arp_tables.c13
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_core.c185
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_h323.c34
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c150
-rw-r--r--[-rwxr-xr-x]release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_esp.c0
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c55
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c8
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c30
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_standalone.c550
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_nat_core.c7
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_nat_h323.c12
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_nat_helper.c38
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_nat_pptp.c265
-rw-r--r--[-rwxr-xr-x]release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_esp.c0
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_gre.c21
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_udp.c3
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ip_tables.c33
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_BCOUNT.c63
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_CLASSIFY.c82
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_CONNMARK.c128
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_IMQ.c78
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_MACSAVE.c65
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c422
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_TRIGGER.c14
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_TTL.c110
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_account.c942
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_bcount.c59
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_condition.c256
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c222
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_connmark.c83
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_exp.c57
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_geoip.c272
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c868
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_iprange.c101
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_layer7.c570
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_mac.c6
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_macsave.c62
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_mport.c4
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_quota.c88
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_recent.c998
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_string.c218
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_time.c46
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_u32.c211
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/ipt_web.c246
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.c1195
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.h40
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/regexp/regmagic.h5
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/regexp/regsub.c95
-rw-r--r--release/src/linux/linux/net/ipv4/netfilter/tomato_ct.c181
-rw-r--r--release/src/linux/linux/net/ipv4/route.c10
-rw-r--r--release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c12
-rw-r--r--release/src/linux/linux/net/ipv4/tcp_input.c311
-rw-r--r--release/src/linux/linux/net/ipv4/tcp_minisocks.c3
-rw-r--r--release/src/linux/linux/net/ipv4/tcp_output.c20
-rw-r--r--release/src/linux/linux/net/ipv6/netfilter/Config.in4
-rw-r--r--release/src/linux/linux/net/ipv6/netfilter/Makefile3
-rw-r--r--release/src/linux/linux/net/ipv6/netfilter/ip6_tables.c6
-rw-r--r--release/src/linux/linux/net/ipv6/netfilter/ip6t_IMQ.c78
-rw-r--r--release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c308
-rw-r--r--release/src/linux/linux/net/ipv6/netfilter/ip6t_condition.c254
-rw-r--r--release/src/linux/linux/net/sched/Config.in3
-rw-r--r--release/src/linux/linux/net/sched/Makefile1
-rw-r--r--release/src/linux/linux/net/sched/sch_api.c3
-rw-r--r--release/src/linux/linux/net/sched/sch_esfq.c652
-rw-r--r--release/src/linux/linux/net/sched/sch_fifo.c15
-rw-r--r--release/src/linux/linux/net/sched/sch_generic.c13
-rw-r--r--release/src/linux/linux/net/sched/sch_hfsc.c1817
-rw-r--r--release/src/linux/linux/net/sched/sch_htb.c255
-rw-r--r--release/src/linux/linux/net/sched/sch_ingress.c4
-rw-r--r--release/src/linux/linux/net/sched/sch_sfq.c8
-rw-r--r--release/src/linux/linux/net/socket.c3
-rw-r--r--release/src/linux/linux/scripts/squashfs/Makefile34
-rw-r--r--release/src/linux/linux/scripts/squashfs/global.h46
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/7zC.txt235
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/7zFormat.txt471
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.c70
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.h20
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.c29
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.h19
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.c76
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.h24
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.c150
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.h21
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.c116
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.h40
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.c5
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.h55
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.c1292
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.h55
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.c133
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.h90
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMain.c223
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.c14
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.h18
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zTypes.h61
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsp178
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsw29
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile55
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile.gcc50
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.cpp251
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.h98
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.cpp80
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.h76
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.cpp117
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.h64
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StdAfx.h9
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.cpp44
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.h11
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.cpp16
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.cpp16
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.c26
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.c35
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.cpp18
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.h54
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.c65
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.c36
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.c36
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.c101
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.h19
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.cpp16
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.cpp17
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.cpp17
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.h10
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/StdAfx.h8
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.cpp18
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.h19
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.cpp412
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.h133
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h55
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h12
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h16
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h16
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h18
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4b.h20
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h444
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC.h55
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC2.h13
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC3.h17
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4.h19
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4b.h21
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h350
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/IMatchFinder.h63
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.cpp102
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.h84
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp17
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.h64
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat.h318
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2.h22
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2H.h24
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2R.h20
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat3H.h24
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat4H.h24
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/PatMain.h989
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/StdAfx.h6
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMA.h82
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp342
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.h249
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp1504
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h416
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/StdAfx.h8
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp523
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw29
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp509
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp508
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h11
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp228
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h46
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c79
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h55
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp3
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h8
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile100
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc113
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c588
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h131
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c716
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c521
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h115
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c195
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c342
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile43
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile.gcc23
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/ZLib.cpp273
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/makefile92
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h205
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp80
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h120
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h161
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h31
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/StdAfx.h6
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/ICoder.h156
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/7zip/IStream.h62
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.cpp118
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.h29
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.cpp61
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.h36
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.cpp78
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.h45
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/ComTry.h17
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.cpp263
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.h82
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/Defs.h20
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyCom.h203
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyGuidDef.h54
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyInitGuid.h13
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyUnknown.h24
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyWindows.h183
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.cpp114
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.h14
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/StdAfx.h9
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.cpp198
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.h631
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.cpp93
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.h71
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.cpp68
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.h17
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/Types.h19
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.cpp74
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.h211
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Windows/Defs.h18
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.cpp245
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.h98
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/C/Windows/StdAfx.h9
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/CPL.html224
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/LGPL.txt504
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/Methods.txt114
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/history.txt147
-rw-r--r--release/src/linux/linux/scripts/squashfs/lzma/lzma.txt637
-rw-r--r--release/src/linux/linux/scripts/squashfs/mksquashfs.c1317
-rw-r--r--release/src/linux/linux/scripts/squashfs/mksquashfs.h3
-rw-r--r--release/src/linux/linux/scripts/squashfs/read_fs.c344
-rw-r--r--release/src/linux/linux/scripts/squashfs/read_fs.h3
-rw-r--r--release/src/linux/linux/scripts/squashfs/sort.c227
-rw-r--r--release/src/linux/linux/scripts/squashfs/sort.h56
-rw-r--r--release/src/linux/linux/scripts/squashfs/squashfs_fs.h735
-rw-r--r--release/src/linux/linux/scripts/squashfs/unsquashfs.c946
368 files changed, 77757 insertions, 3476 deletions
diff --git a/release/src/linux/linux/.config b/release/src/linux/linux/.config
index bae6dc5a..6334c2f4 100644
--- a/release/src/linux/linux/.config
+++ b/release/src/linux/linux/.config
@@ -1,5 +1,5 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
#
CONFIG_MIPS=y
CONFIG_MIPS32=y
@@ -152,6 +152,10 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
CONFIG_MTD_CHAR=y
# CONFIG_MTD_BLOCK is not set
CONFIG_MTD_BLOCK_RO=y
@@ -207,6 +211,10 @@ CONFIG_MTD_SFLASH=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
# CONFIG_MTD_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
@@ -274,7 +282,8 @@ CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE=y
# CONFIG_IP_PIMSM_V1 is not set
# CONFIG_IP_PIMSM_V2 is not set
@@ -286,71 +295,102 @@ CONFIG_SYN_COOKIES=y
# IP: Netfilter Configuration
#
CONFIG_IP_NF_CONNTRACK=y
-CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_TFTP=y
-CONFIG_IP_NF_H323=y
# CONFIG_IP_NF_IRC is not set
-CONFIG_IP_NF_RTSP=y
+# CONFIG_IP_NF_CUSEEME is not set
+# CONFIG_IP_NF_QUAKE3 is not set
+CONFIG_IP_NF_RTSP=m
# CONFIG_IP_NF_MMS is not set
-CONFIG_IP_NF_SIP=y
-CONFIG_IP_NF_CT_PROTO_GRE=y
-CONFIG_IP_NF_PPTP=y
-CONFIG_IP_NF_CT_PROTO_ESP=y
+CONFIG_IP_NF_CT_PROTO_GRE=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_SIP=m
+# CONFIG_IP_NF_CT_PROTO_ESP is not set
# CONFIG_IP_NF_QUEUE is not set
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_LIMIT=y
+CONFIG_IP_NF_MATCH_IPP2P=m
+# CONFIG_IP_NF_MATCH_GEOIP is not set
+# CONFIG_IP_NF_MATCH_QUOTA is not set
+CONFIG_IP_NF_MATCH_IPRANGE=y
# CONFIG_IP_NF_POOL is not set
CONFIG_IP_NF_MATCH_MAC=y
# CONFIG_IP_NF_MATCH_PKTTYPE is not set
CONFIG_IP_NF_MATCH_MARK=y
-# CONFIG_IP_NF_MATCH_MULTIPORT is not set
-# CONFIG_IP_NF_MATCH_MPORT is not set
-CONFIG_IP_NF_MATCH_TOS=y
-CONFIG_IP_NF_MATCH_TIME=y
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_MPORT=y
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+# CONFIG_IP_NF_MATCH_ACCOUNT is not set
+CONFIG_IP_NF_MATCH_CONDITION=m
+CONFIG_IP_NF_MATCH_TIME=m
# CONFIG_IP_NF_MATCH_ECN is not set
-# CONFIG_IP_NF_MATCH_DSCP is not set
+CONFIG_IP_NF_MATCH_DSCP=m
# CONFIG_IP_NF_MATCH_AH_ESP is not set
-# CONFIG_IP_NF_MATCH_LENGTH is not set
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_U32=m
# CONFIG_IP_NF_MATCH_TTL is not set
CONFIG_IP_NF_MATCH_TCPMSS=y
# CONFIG_IP_NF_MATCH_HELPER is not set
CONFIG_IP_NF_MATCH_STATE=y
+CONFIG_IP_NF_MATCH_CONNLIMIT=y
+CONFIG_IP_NF_MATCH_CONNMARK=y
# CONFIG_IP_NF_MATCH_CONNTRACK is not set
# CONFIG_IP_NF_MATCH_UNCLEAN is not set
-CONFIG_IP_NF_MATCH_WEBSTR=y
+# CONFIG_IP_NF_MATCH_STRING is not set
+# CONFIG_IP_NF_MATCH_WEBSTR is not set
# CONFIG_IP_NF_MATCH_OWNER is not set
+CONFIG_IP_NF_MATCH_LAYER7=m
+# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
+CONFIG_IP_NF_MATCH_WEB=m
+CONFIG_IP_NF_TARGET_BCOUNT=y
+CONFIG_IP_NF_MATCH_BCOUNT=y
+# CONFIG_IP_NF_TARGET_MACSAVE is not set
+# CONFIG_IP_NF_MATCH_MACSAVE is not set
+# CONFIG_IP_NF_MATCH_EXP is not set
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
# CONFIG_IP_NF_TARGET_MIRROR is not set
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_AUTOFW=y
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_H323=m
+# CONFIG_IP_NF_AUTOFW is not set
CONFIG_IP_NF_TARGET_TRIGGER=y
-CONFIG_IP_NF_NAT_H323=y
-CONFIG_IP_NF_NAT_PPTP=y
-CONFIG_IP_NF_NAT_SIP=y
-CONFIG_IP_NF_NAT_PROTO_GRE=y
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_NAT_PROTO_GRE=m
# CONFIG_IP_NF_NAT_LOCAL is not set
# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_RTSP=m
+CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=y
-CONFIG_IP_NF_NAT_RTSP=y
-CONFIG_IP_NF_NAT_PROTO_ESP=y
CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_TOS=y
+CONFIG_IP_NF_TARGET_TOS=m
# CONFIG_IP_NF_TARGET_ECN is not set
-CONFIG_IP_NF_TARGET_DSCP=y
+CONFIG_IP_NF_TARGET_DSCP=m
CONFIG_IP_NF_TARGET_MARK=y
+CONFIG_IP_NF_TARGET_ROUTE=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_IMQ=m
CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_CONNMARK=y
+CONFIG_IP_NF_TARGET_TTL=m
# CONFIG_IP_NF_TARGET_ULOG is not set
CONFIG_IP_NF_TARGET_TCPMSS=y
# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_TOMATOCT=m
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
CONFIG_VLAN_8021Q=y
+
+#
+#
+#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
@@ -393,27 +433,29 @@ CONFIG_BRIDGE=y
# QoS and/or fair queueing
#
CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=y
+# CONFIG_NET_SCH_CBQ is not set
CONFIG_NET_SCH_HTB=y
# CONFIG_NET_SCH_CSZ is not set
+CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_PRIO=y
# CONFIG_NET_SCH_RED is not set
CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_ESFQ=m
# CONFIG_NET_SCH_TEQL is not set
-# CONFIG_NET_SCH_TBF is not set
+CONFIG_NET_SCH_TBF=m
# CONFIG_NET_SCH_GRED is not set
# CONFIG_NET_SCH_DSMARK is not set
-# CONFIG_NET_SCH_INGRESS is not set
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_QOS=y
CONFIG_NET_ESTIMATOR=y
CONFIG_NET_CLS=y
# CONFIG_NET_CLS_TCINDEX is not set
# CONFIG_NET_CLS_ROUTE4 is not set
-# CONFIG_NET_CLS_FW is not set
+CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
# CONFIG_NET_CLS_RSVP is not set
# CONFIG_NET_CLS_RSVP6 is not set
-# CONFIG_NET_CLS_POLICE is not set
+CONFIG_NET_CLS_POLICE=y
#
# Network testing
@@ -467,7 +509,7 @@ CONFIG_WL_AP="wlconfig_lx_router_ap"
CONFIG_WL_STA="wlconfig_lx_router_sta"
CONFIG_WL_APSTA="wlconfig_lx_router_apsta"
CONFIG_WL_DNGL="wlconfig_lx_router_dongle"
-CONFIG_WL_LINK="AP"
+CONFIG_WL_LINK="APSTA"
#
# ARCnet devices
@@ -476,7 +518,8 @@ CONFIG_WL_LINK="AP"
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_IMQ=m
+CONFIG_TUN=m
# CONFIG_ETHERTAP is not set
#
@@ -610,6 +653,14 @@ CONFIG_UNIX98_PTY_COUNT=16
# Joysticks
#
# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
@@ -655,9 +706,11 @@ CONFIG_UNIX98_PTY_COUNT=16
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
# CONFIG_TMPFS is not set
CONFIG_RAMFS=y
# CONFIG_ZLIB_FS_INFLATE is not set
@@ -701,6 +754,9 @@ CONFIG_DEVFS_MOUNT=y
# CONFIG_NFSD_TCP is not set
# CONFIG_SUNRPC is not set
# CONFIG_LOCKD is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_POSIX is not set
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -729,7 +785,49 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
#
# Multimedia devices
@@ -771,5 +869,5 @@ CONFIG_MAGIC_SYSRQ=y
#
# Library routines
#
-CONFIG_ZLIB_INFLATE=y
-# CONFIG_ZLIB_DEFLATE is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/release/src/linux/linux/Documentation/Configure.help b/release/src/linux/linux/Documentation/Configure.help
index 9d556610..1f6261d7 100644
--- a/release/src/linux/linux/Documentation/Configure.help
+++ b/release/src/linux/linux/Documentation/Configure.help
@@ -232,23 +232,23 @@ CONFIG_CRIS
Unsynced TSC support
CONFIG_X86_TSC_DISABLE
- This option is used for getting Linux to run on a NUMA multi-node
- boxes, laptops and other systems suffering from unsynced TSCs or
- TSC drift, which can cause gettimeofday to return non-monotonic values.
+ This option is used for getting Linux to run on a NUMA multi-node
+ boxes, laptops and other systems suffering from unsynced TSCs or
+ TSC drift, which can cause gettimeofday to return non-monotonic values.
Choosing this option will disable the CONFIG_X86_TSC optimization,
- and allows you to then specify "notsc" as a boot option regardless of
- which processor you have compiled for.
-
+ and allows you to then specify "notsc" as a boot option regardless of
+ which processor you have compiled for.
+
NOTE: If your system hangs when init should run, you are probably
- using a i686 compiled glibc which reads the TSC without checking for
- availability. Boot without "notsc" and install a i386 compiled glibc
+ using a i686 compiled glibc which reads the TSC without checking for
+ availability. Boot without "notsc" and install a i386 compiled glibc
to solve the problem.
If unsure, say N.
Multiquad support for NUMA systems
CONFIG_MULTIQUAD
- This option is used for getting Linux to run on a (IBM/Sequent) NUMA
+ This option is used for getting Linux to run on a (IBM/Sequent) NUMA
multiquad box. This changes the way that processors are bootstrapped,
and uses Clustered Logical APIC addressing mode instead of Flat Logical.
You will need a new lynxer.elf file to flash your firmware with - send
@@ -1428,8 +1428,8 @@ CONFIG_BLK_DEV_FALCON_IDE
Amiga Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)
CONFIG_BLK_DEV_BUDDHA
- This is the IDE driver for the IDE interfaces on the Buddha,
- Catweasel and X-Surf expansion boards. It supports up to two interfaces
+ This is the IDE driver for the IDE interfaces on the Buddha,
+ Catweasel and X-Surf expansion boards. It supports up to two interfaces
on the Buddha, three on the Catweasel and two on the X-Surf.
Say Y if you have a Buddha or Catweasel expansion board and want to
@@ -2145,7 +2145,7 @@ CONFIG_SIBYTE_CFE_CONSOLE
configured.
Support SWARM (BCM912500A) peripherals
-CONFIG_SIBYTE_SWARM
+CONFIG_SIBYTE_SWARM
Indicates that the target is a SWARM board. Most devices (IDE,
video decoder, audio codec, etc) still require additional
configuration options under the appropriate sections.
@@ -2280,7 +2280,7 @@ CONFIG_TC
# Choice: galileo_clock
75
CONFIG_SYSCLK_75
- Configure the kernel for clock speed of your Galileo board.
+ Configure the kernel for clock speed of your Galileo board.
The choices are 75MHz, 83.3MHz, and 100MHz.
83.3
@@ -2620,6 +2620,33 @@ CONFIG_IP_NF_IRC
If you want to compile it as a module, say 'M' here and read
Documentation/modules.txt. If unsure, say 'N'.
+Per connection mark support
+CONFIG_IP_NF_CONNTRACK_MARK
+ This option enables support for connection marks, used by the
+ `CONNMARK' target and `connmark' match. Similar to the mark value
+ of packets, but this mark value is kept in the conntrack session
+ instead of the individual packets.
+
+CONNMARK target support
+CONFIG_IP_NF_TARGET_CONNMARK
+ This option adds a `CONNMARK' target, which allows one to manipulate
+ the connection mark value. Similar to the MARK target, but
+ affects the connection mark value rather than the packet mark value.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The module will be called
+ ipt_CONNMARK.o. If unsure, say `N'.
+
+connmark match support
+CONFIP_IP_NF_MATCH_CONNMARK
+ This option adds a `connmark' match, which allows you to match the
+ connection mark value previously set for the session by `CONNMARK'.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The module will be called
+ ipt_connmark.o. If unsure, say `N'.
+
+
FTP protocol support
CONFIG_IP_NF_FTP
Tracking FTP connections is problematic: special helpers are
@@ -2629,6 +2656,16 @@ CONFIG_IP_NF_FTP
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `Y'.
+H.323 (netmeeting) support
+CONFIG_IP_NF_H323
+ H.323 is a standard signalling protocol used by teleconferencing
+ softwares like netmeeting. With the ip_conntrack_h323 and
+ the ip_nat_h323 modules you can support the protocol on a connection
+ tracking/NATing firewall.
+
+ If you want to compile it as a module, say 'M' here and read
+ Documentation/modules.txt. If unsure, say 'N'.
+
User space queueing via NETLINK
CONFIG_IP_NF_QUEUE
Netfilter has the ability to queue packets to user space: the
@@ -2641,19 +2678,22 @@ IP tables support (required for filtering/masq/NAT)
CONFIG_IP_NF_IPTABLES
iptables is a general, extensible packet identification framework.
The packet filtering and full NAT (masquerading, port forwarding,
- etc) subsystems now use this: say 'Y' or 'M' here if you want to use
+ etc) subsystems now use this: say `Y' or `M' here if you want to use
either of those.
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
-RTSP protocol support
-CONFIG_IP_NF_RTSP
- Support the RTSP protocol. This allows UDP transports to be setup
- properly, including RTP and RDT.
+recent match support
+CONFIG_IP_NF_MATCH_RECENT
+ This match is used for creating one or many lists of recently
+ used addresses and then matching against that/those list(s).
- If you want to compile it as a module, say 'M' here and read
- Documentation/modules.txt. If unsure, say 'Y'.
+ Short options are available by using 'iptables -m recent -h'
+ Official Website: <http://snowman.net/projects/ipt_recent/>
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
limit match support
CONFIG_IP_NF_MATCH_LIMIT
@@ -2664,14 +2704,21 @@ CONFIG_IP_NF_MATCH_LIMIT
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+quota match support
+CONFIG_IP_NF_MATCH_QUOTA
+ This match implements network quotas.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
skb->pkt_type packet match support
CONFIG_IP_NF_MATCH_PKTTYPE
This patch allows you to match packet in accrodance
to its "class", eg. BROADCAST, MULTICAST, ...
-
+
Typical usage:
iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
-
+
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
@@ -2701,6 +2748,14 @@ CONFIG_IP_NF_MATCH_MULTIPORT
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+Multiple port with ranges match support
+CONFIG_IP_NF_MATCH_MPORT
+ This is an enhanced multiport match which supports port
+ ranges as well as single ports.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
TTL match support
CONFIG_IP_NF_MATCH_TTL
This adds CONFIG_IP_NF_MATCH_TTL option, which enabled the user
@@ -2709,6 +2764,18 @@ CONFIG_IP_NF_MATCH_TTL
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
+U32 patch support
+CONFIG_IP_NF_MATCH_U32
+ U32 allows you to extract quantities of up to 4 bytes from a packet,
+ AND them with specified masks, shift them by specified amounts and
+ test whether the results are in any of a set of specified ranges.
+ The specification of what to extract is general enough to skip over
+ headers with lengths stored in the packet, as in IP or TCP header
+ lengths.
+
+ Details and examples are in the kernel module source.
+
+
LENGTH match support
CONFIG_IP_NF_MATCH_LENGTH
This option allows you to match the length of a packet against a
@@ -2717,6 +2784,18 @@ CONFIG_IP_NF_MATCH_LENGTH
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+TIME patch support
+CONFIG_IP_NF_MATCH_TIME
+ This option adds a `time' match, which allows you
+ to match based on the packet arrival time/date
+ (arrival time/date at the machine which netfilter is running on) or
+ departure time/date (for locally generated packets).
+
+ If you say Y here, try iptables -m time --help for more information.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
AH/ESP match support
CONFIG_IP_NF_MATCH_AH_ESP
These two match extensions (`ah' and `esp') allow you to match a
@@ -2735,7 +2814,7 @@ CONFIG_IP_NF_MATCH_DSCP
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
-
+
ECN match support
CONFIG_IP_NF_MATCH_ECN
@@ -2745,7 +2824,7 @@ CONFIG_IP_NF_MATCH_ECN
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
-
+
TOS match support
CONFIG_IP_NF_MATCH_TOS
@@ -2755,6 +2834,43 @@ CONFIG_IP_NF_MATCH_TOS
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+IPP2P match support
+CONFIG_IP_NF_MATCH_IPP2P
+ This option makes possible to match some P2P packets
+ therefore helps controlling such traffic.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+geoip match support
+CONFIG_IP_NF_MATCH_GEOIP
+ This option allows you to match a packet by its source or
+ destination country. Basically, you need a country's
+ database containing all subnets and associated countries.
+
+ For the complete procedure and understanding, read :
+ http://people.netfilter.org/peejix/geoip/howto/geoip-HOWTO.html
+
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+Condition variable match support
+CONFIG_IP_NF_MATCH_CONDITION
+ This option allows you to match firewall rules against condition
+ variables stored in the /proc/net/ipt_condition directory.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
+iprange match support
+CONFIG_IP_NF_MATCH_IPRANGE
+ This option makes possible to match IP addresses against
+ IP address ranges.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
conntrack match support
CONFIG_IP_NF_MATCH_CONNTRACK
This is a general conntrack match module, a superset of the state match.
@@ -2776,6 +2892,22 @@ CONFIG_IP_NF_MATCH_STATE
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+Connections/IP limit match support
+CONFIG_IP_NF_MATCH_CONNLIMIT
+ This match allows you to restrict the number of parallel TCP
+ connections to a server per client IP address (or address block).
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
+String match support (EXPERIMENTAL)
+CONFIG_IP_NF_MATCH_STRING
+ String matching alows you to match packets which contain a
+ specified string of characters.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
Unclean match support
CONFIG_IP_NF_MATCH_UNCLEAN
Unclean packet matching matches any strange or invalid packets, by
@@ -2820,7 +2952,7 @@ CONFIG_IP_NF_TARGET_MIRROR
Local NAT support
CONFIG_IP_NF_NAT_LOCAL
- This option enables support for NAT of locally originated connections.
+ This option enables support for NAT of locally originated connections.
Enable this if you need to use destination NAT on connections
originating from local processes on the nat box itself.
@@ -2897,12 +3029,12 @@ CONFIG_IP_NF_TARGET_DSCP
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
-
+
ECN target support
CONFIG_IP_NF_TARGET_ECN
This option adds a `ECN' target, which can be used in the iptables mangle
- table.
+ table.
You can use this target to remove the ECN bits from the IPv4 header of
an IP packet. This is particularly useful, if you need to work around
@@ -2912,7 +3044,7 @@ CONFIG_IP_NF_TARGET_ECN
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
-
+
TOS target support
CONFIG_IP_NF_TARGET_TOS
@@ -2923,6 +3055,22 @@ CONFIG_IP_NF_TARGET_TOS
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+IMQ target support
+CONFIG_IP_NF_TARGET_IMQ
+ This option adds a `IMQ' target which is used to specify if and
+ to which imq device packets should get enqueued/dequeued.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+IMQ target support
+CONFIG_IP6_NF_TARGET_IMQ
+ This option adds a `IMQ' target which is used to specify if and
+ to which imq device packets should get enqueued/dequeued.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
MARK target support
CONFIG_IP_NF_TARGET_MARK
This option adds a `MARK' target, which allows you to create rules
@@ -2935,6 +3083,21 @@ CONFIG_IP_NF_TARGET_MARK
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+ROUTE target support
+CONFIG_IP_NF_TARGET_ROUTE
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. For example, the ROUTE lets you route a received packet through
+ an interface or towards a host, even if the regular destination of the
+ packet is the router itself. The ROUTE target is also able to change the
+ incoming interface of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The module will be called ipt_ROUTE.o.
+ If unsure, say `N'.
+
TCPMSS target support
CONFIG_IP_NF_TARGET_TCPMSS
This option adds a `TCPMSS' target, which allows you to alter the
@@ -2990,6 +3153,26 @@ CONFIG_IP_NF_TARGET_ULOG
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
+TTL target support
+CONFIG_IP_NF_TARGET_TTL
+ This option adds a `TTL' target, which enables the user to set
+ the TTL value or increment / decrement the TTL value by a given
+ amount.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
+CLASSIFY target support
+CONFIG_IP_NF_TARGET_CLASSIFY
+ This option adds a `CLASSIFY' target, which enables the user to set
+ the priority of a packet. Some qdiscs can use this value for classification,
+ among these are:
+
+ atm, cbq, dsmark, pfifo_fast, htb, prio
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
LOG target support
CONFIG_IP_NF_TARGET_LOG
This option adds a `LOG' target, which allows you to create rules in
@@ -3054,6 +3237,14 @@ CONFIG_IP6_NF_MATCH_MARK
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+Condition variable match support
+CONFIG_IP6_NF_MATCH_CONDITION
+ This option allows you to match firewall rules against condition
+ variables stored in the /proc/net/ipt_condition directory.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
Multiple port match support
CONFIG_IP6_NF_MATCH_MULTIPORT
Multiport matching allows you to match TCP or UDP packets based on
@@ -3118,6 +3309,17 @@ CONFIG_IP6_NF_TARGET_MARK
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+ROUTE target support
+CONFIG_IP6_NF_TARGET_ROUTE
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. The ROUTE target is also able to change the incoming interface
+ of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ Not working as a module.
+
TCP Explicit Congestion Notification support
CONFIG_INET_ECN
Explicit Congestion Notification (ECN) allows routers to notify
@@ -3527,7 +3729,7 @@ CONFIG_SGI_DS1286
Indy/I2 Hardware Watchdog
CONFIG_INDYDOG
Hardwaredriver for the Indy's/I2's watchdog. This is a
- watchdog timer that will reboot the machine after a 60 second
+ watchdog timer that will reboot the machine after a 60 second
timer expired and no process has written to /dev/watchdog during
that time.
@@ -3623,7 +3825,7 @@ CONFIG_AGP_I460
chipset, the first to support Intel Itanium processors, is new and
this option is correspondingly a little experimental.
- If you don't have a 460GX based machine (such as BigSur) with an AGP
+ If you don't have a 460GX based machine (such as BigSur) with an AGP
slot then this option isn't going to do you much good. If you're
dying to do Direct Rendering on IA-64, this is what you're looking for.
@@ -3662,7 +3864,7 @@ CONFIG_AGP_SIS
Serverworks LE/HE support
CONFIG_AGP_SWORKS
- Say Y here to support the Serverworks AGP card. See
+ Say Y here to support the Serverworks AGP card. See
<http://www.serverworks.com/> for product descriptions and images.
ALI chipset support
@@ -4560,8 +4762,8 @@ CONFIG_FB_PMAG_BA
PMAGB-B TURBOchannel framebuffer support
CONFIG_FB_PMAGB_B
Support for the PMAGB-B TURBOchannel framebuffer card used mainly
- in the MIPS-based DECstation series. The card is currently only
- supported in 1280x1024x8 mode.
+ in the MIPS-based DECstation series. The card is currently only
+ supported in 1280x1024x8 mode.
FutureTV PCI card
CONFIG_ARCH_FTVPCI
@@ -4603,7 +4805,7 @@ CONFIG_FB_L7200
NeoMagic display support (EXPERIMENTAL)
CONFIG_FB_NEOMAGIC
This driver supports notebooks with NeoMagic PCI chips.
- Say Y if you have such a graphics card.
+ Say Y if you have such a graphics card.
The driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want). The
@@ -4817,7 +5019,7 @@ Matrox unified accelerated driver
CONFIG_FB_MATROX
Say Y here if you have a Matrox Millennium, Millennium II, Mystique,
Mystique 220, Productiva G100, Mystique G200, Millennium G200,
- Matrox G400, G450 or G550 card in your box. At this time, support for
+ Matrox G400, G450 or G550 card in your box. At this time, support for
the G-series digital output is almost non-existant.
This driver is also available as a module ( = code which can be
@@ -4857,7 +5059,7 @@ CONFIG_FB_MATROX_G100
"I2C support" and "I2C bit-banging support" in the character devices
section, and then to "Matrox I2C support" and "G400 second head
support" here in the framebuffer section.
-
+
If you have G550, you must also compile support for G450/G550 secondary
head into kernel, otherwise picture will be shown only on the output you
are probably not using...
@@ -4953,10 +5155,10 @@ CONFIG_FB_MATROX_MULTIHEAD
3Dfx Voodoo Graphics / Voodoo2 frame buffer support
CONFIG_FB_VOODOO1
- Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
+ Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
Voodoo2 (cvg) based graphics card.
- This driver is also available as a module ( = code which can be
+ This driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want).
The module will be called sstfb.o. If you want to compile it as
a module, say M here and read Documentation/modules.txt.
@@ -5087,14 +5289,14 @@ CONFIG_FB_ATY_CT
Sony Vaio Picturebook laptop LCD panel support
CONFIG_FB_ATY_CT_VAIO_LCD
- Say Y here if you want to use the full width of the Sony Vaio
+ Say Y here if you want to use the full width of the Sony Vaio
Picturebook laptops LCD panels (you will get a 128x30 console).
Note that you need to activate this mode using the 'vga=0x301'
option from your boot loader (lilo or loadlin). See the
documentation of your boot loader about how to pass options to the
kernel.
-
+
Mach64 GX support
CONFIG_FB_ATY_GX
Say Y here to support use of the ATI Mach64 Graphics Expression
@@ -5143,6 +5345,15 @@ CONFIG_FBCON_ADVANCED
If unsure, say N.
+CONFIG_NET_SCH_HFSC
+ Say Y here if you want to use the Hierarchical Fair Service Curve
+ (HFSC) packet scheduling algorithm for some of your network devices.
+
+ This code is also available as a module called sch_hfsc.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
Monochrome support
CONFIG_FBCON_MFB
This is the low level frame buffer console driver for monochrome
@@ -5339,7 +5550,13711 @@ CONFIG_PARPORT_1284
want to use a device that uses enhanced parallel port transfer modes
such as EPP and ECP, say Y here to enable advanced IEEE 1284
transfer modes. Also say Y if you want device ID information to
- appear in /proc/sys/dev/parportYYDELETEMEYYmsr - Model-specific register support
+ appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N.
+
+Enable loadable module support
+CONFIG_MODULES
+ Kernel modules are small pieces of compiled code which can be
+ inserted in or removed from the running kernel, using the programs
+ insmod and rmmod. This is described in the file
+ <file:Documentation/modules.txt>, including the fact that you have
+ to say "make modules" in order to compile the modules that you chose
+ during kernel configuration. Modules can be device drivers, file
+ systems, binary executable formats, and so on. If you think that you
+ may want to make use of modules with this kernel in the future, then
+ say Y here. If unsure, say Y.
+
+Set version information on all symbols for modules
+CONFIG_MODVERSIONS
+ Usually, modules have to be recompiled whenever you switch to a new
+ kernel. Saying Y here makes it possible, and safe, to use the
+ same modules even after compiling a new kernel; this requires the
+ program modprobe. All the software needed for module support is in
+ the modutils package (check the file <file:Documentation/Changes>
+ for location and latest version). NOTE: if you say Y here but don't
+ have the program genksyms (which is also contained in the above
+ mentioned modutils package), then the building of your kernel will
+ fail. If you are going to use modules that are generated from
+ non-kernel sources, you would benefit from this option. Otherwise
+ it's not that important. So, N ought to be a safe bet.
+
+Kernel module loader support
+CONFIG_KMOD
+ Normally when you have selected some drivers and/or file systems to
+ be created as loadable modules, you also have the responsibility to
+ load the corresponding modules (using the programs insmod or
+ modprobe) before you can use them. If you say Y here however, the
+ kernel will be able to load modules for itself: when a part of the
+ kernel needs a module, it runs modprobe with the appropriate
+ arguments, thereby loading the module if it is available. (This is a
+ replacement for kerneld.) Say Y here and read about configuring it
+ in <file:Documentation/kmod.txt>.
+
+ARP daemon support
+CONFIG_ARPD
+ Normally, the kernel maintains an internal cache which maps IP
+ addresses to hardware addresses on the local network, so that
+ Ethernet/Token Ring/ etc. frames are sent to the proper address on
+ the physical networking layer. For small networks having a few
+ hundred directly connected hosts or less, keeping this address
+ resolution (ARP) cache inside the kernel works well. However,
+ maintaining an internal ARP cache does not work well for very large
+ switched networks, and will use a lot of kernel memory if TCP/IP
+ connections are made to many machines on the network.
+
+ If you say Y here, the kernel's internal ARP cache will never grow
+ to more than 256 entries (the oldest entries are expired in a LIFO
+ manner) and communication will be attempted with the user space ARP
+ daemon arpd. Arpd then answers the address resolution request either
+ from its own cache or by asking the net.
+
+ This code is experimental and also obsolete. If you want to use it,
+ you need to find a version of the daemon arpd on the net somewhere,
+ and you should also say Y to "Kernel/User network link driver",
+ below. If unsure, say N.
+
+TCP/IP networking
+CONFIG_INET
+ These are the protocols used on the Internet and on most local
+ Ethernets. It is highly recommended to say Y here (this will enlarge
+ your kernel by about 144 KB), since some programs (e.g. the X window
+ system) use TCP/IP even if your machine is not connected to any
+ other computer. You will get the so-called loopback device which
+ allows you to ping yourself (great fun, that!).
+
+ For an excellent introduction to Linux networking, please read the
+ NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This option is also necessary if you want to use the full power of
+ term (term is a program which gives you almost full Internet
+ connectivity if you have a regular dial up shell account on some
+ Internet connected Unix computer; for more information, read
+ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
+
+ If you say Y here and also to "/proc file system support" and
+ "Sysctl support" below, you can change various aspects of the
+ behaviour of the TCP/IP code by writing to the (virtual) files in
+ /proc/sys/net/ipv4/*; the options are explained in the file
+ <file:Documentation/networking/ip-sysctl.txt>.
+
+ Short answer: say Y.
+
+IP multicasting
+CONFIG_IP_MULTICAST
+ This is code for addressing several networked computers at once,
+ enlarging your kernel by about 2 KB. You need multicasting if you
+ intend to participate in the MBONE, a high bandwidth network on top
+ of the Internet which carries audio and video broadcasts. More
+ information about the MBONE is on the WWW at
+ <http://www-itg.lbl.gov/mbone/>. Information about the multicast
+ capabilities of the various network cards is contained in
+ <file:Documentation/networking/multicast.txt>. For most people, it's
+ safe to say N.
+
+Advanced router
+CONFIG_IP_ADVANCED_ROUTER
+ If you intend to run your Linux box mostly as a router, i.e. as a
+ computer that forwards and redistributes network packets, say Y; you
+ will then be presented with several options that allow more precise
+ control about the routing process.
+
+ The answer to this question won't directly affect the kernel:
+ answering N will just cause the configurator to skip all the
+ questions about advanced routing.
+
+ Note that your box can only act as a router if you enable IP
+ forwarding in your kernel; you can do that by saying Y to "/proc
+ file system support" and "Sysctl support" below and executing the
+ line
+
+ echo "1" > /proc/sys/net/ipv4/ip_forward
+
+ at boot time after the /proc file system has been mounted.
+
+ If you turn on IP forwarding, you will also get the rp_filter, which
+ automatically rejects incoming packets if the routing table entry
+ for their source address doesn't match the network interface they're
+ arriving on. This has security advantages because it prevents the
+ so-called IP spoofing, however it can pose problems if you use
+ asymmetric routing (packets from you to a host take a different path
+ than packets from that host to you) or if you operate a non-routing
+ host which has several IP addresses on different interfaces. To turn
+ rp_filter off use:
+
+ echo 0 > /proc/sys/net/ipv4/conf/<device>/rp_filter
+ or
+ echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
+
+ If unsure, say N here.
+
+Policy routing
+CONFIG_IP_MULTIPLE_TABLES
+ Normally, a router decides what to do with a received packet based
+ solely on the packet's final destination address. If you say Y here,
+ the Linux router will also be able to take the packet's source
+ address into account. Furthermore, if you also say Y to "Use TOS
+ value as routing key" below, the TOS (Type-Of-Service) field of the
+ packet can be used for routing decisions as well. In addition, if
+ you say Y here and to "Fast network address translation" below,
+ the router will also be able to modify source and destination
+ addresses of forwarded packets.
+
+ If you are interested in this, please see the preliminary
+ documentation at <http://www.compendium.com.ar/policy-routing.txt>
+ and <ftp://post.tepkom.ru/pub/vol2/Linux/docs/advanced-routing.tex>.
+ You will need supporting software from
+ <ftp://ftp.inr.ac.ru/ip-routing/>.
+
+ If unsure, say N.
+
+Equal cost multipath
+CONFIG_IP_ROUTE_MULTIPATH
+ Normally, the routing tables specify a single action to be taken in
+ a deterministic manner for a given packet. If you say Y here
+ however, it becomes possible to attach several actions to a packet
+ pattern, in effect specifying several alternative paths to travel
+ for those packets. The router considers all these paths to be of
+ equal "cost" and chooses one of them in a non-deterministic fashion
+ if a matching packet arrives.
+
+Use TOS value as routing key
+CONFIG_IP_ROUTE_TOS
+ The header of every IP packet carries a TOS (Type Of Service) value
+ with which the packet requests a certain treatment, e.g. low
+ latency (for interactive traffic), high throughput, or high
+ reliability. If you say Y here, you will be able to specify
+ different routes for packets with different TOS values.
+
+Use netfilter MARK value as routing key
+CONFIG_IP_ROUTE_FWMARK
+ If you say Y here, you will be able to specify different routes for
+ packets with different mark values (see iptables(8), MARK target).
+
+Verbose route monitoring
+CONFIG_IP_ROUTE_VERBOSE
+ If you say Y here, which is recommended, then the kernel will print
+ verbose messages regarding the routing, for example warnings about
+ received packets which look strange and could be evidence of an
+ attack or a misconfigured system somewhere. The information is
+ handled by the klogd daemon which is responsible for kernel messages
+ ("man klogd").
+
+Large routing tables
+CONFIG_IP_ROUTE_LARGE_TABLES
+ If you have routing zones that grow to more than about 64 entries,
+ you may want to say Y here to speed up the routing process.
+
+Fast network address translation
+CONFIG_IP_ROUTE_NAT
+ If you say Y here, your router will be able to modify source and
+ destination addresses of packets that pass through it, in a manner
+ you specify. General information about Network Address Translation
+ can be gotten from the document
+ <http://www.csn.tu-chemnitz.de/~mha/linux-ip-nat/diplom/nat.html>.
+
+Kernel level IP autoconfiguration
+CONFIG_IP_PNP
+ This enables automatic configuration of IP addresses of devices and
+ of the routing table during kernel boot, based on either information
+ supplied on the kernel command line or by BOOTP or RARP protocols.
+ You need to say Y only for diskless machines requiring network
+ access to boot (in which case you want to say Y to "Root file system
+ on NFS" as well), because all other machines configure the network
+ in their startup scripts.
+
+BOOTP support
+CONFIG_IP_PNP_BOOTP
+ If you want your Linux box to mount its whole root file system (the
+ one containing the directory /) from some other computer over the
+ net via NFS and you want the IP address of your computer to be
+ discovered automatically at boot time using the BOOTP protocol (a
+ special protocol designed for doing this job), say Y here. In case
+ the boot ROM of your network card was designed for booting Linux and
+ does BOOTP itself, providing all necessary information on the kernel
+ command line, you can say N here. If unsure, say Y. Note that if you
+ want to use BOOTP, a BOOTP server must be operating on your network.
+ Read <file:Documentation/nfsroot.txt> for details.
+
+DHCP support
+CONFIG_IP_PNP_DHCP
+ If you want your Linux box to mount its whole root file system (the
+ one containing the directory /) from some other computer over the
+ net via NFS and you want the IP address of your computer to be
+ discovered automatically at boot time using the DHCP protocol (a
+ special protocol designed for doing this job), say Y here. In case
+ the boot ROM of your network card was designed for booting Linux and
+ does DHCP itself, providing all necessary information on the kernel
+ command line, you can say N here.
+
+ If unsure, say Y. Note that if you want to use DHCP, a DHCP server
+ must be operating on your network. Read
+ <file:Documentation/nfsroot.txt> for details.
+
+RARP support
+CONFIG_IP_PNP_RARP
+ If you want your Linux box to mount its whole root file system (the
+ one containing the directory /) from some other computer over the
+ net via NFS and you want the IP address of your computer to be
+ discovered automatically at boot time using the RARP protocol (an
+ older protocol which is being obsoleted by BOOTP and DHCP), say Y
+ here. Note that if you want to use RARP, a RARP server must be
+ operating on your network. Read <file:Documentation/nfsroot.txt> for
+ details.
+
+IP tunneling
+CONFIG_NET_IPIP
+ Tunneling means encapsulating data of one protocol type within
+ another protocol and sending it over a channel that understands the
+ encapsulating protocol. This particular tunneling driver implements
+ encapsulation of IP within IP, which sounds kind of pointless, but
+ can be useful if you want to make your (or some other) machine
+ appear on a different network than it physically is, or to use
+ mobile-IP facilities (allowing laptops to seamlessly move between
+ networks without changing their IP addresses; check out
+ <http://anchor.cs.binghamton.edu/~mobileip/LJ/index.html>).
+
+ Saying Y to this option will produce two modules ( = code which can
+ be inserted in and removed from the running kernel whenever you
+ want). Most people won't need this and can say N.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ipip.o
+
+GRE tunnels over IP
+CONFIG_NET_IPGRE
+ Tunneling means encapsulating data of one protocol type within
+ another protocol and sending it over a channel that understands the
+ encapsulating protocol. This particular tunneling driver implements
+ GRE (Generic Routing Encapsulation) and at this time allows
+ encapsulating of IPv4 or IPv6 over existing IPv4 infrastructure.
+ This driver is useful if the other endpoint is a Cisco router: Cisco
+ likes GRE much better than the other Linux tunneling driver ("IP
+ tunneling" above). In addition, GRE allows multicast redistribution
+ through the tunnel.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ip_gre.o
+
+Broadcast GRE over IP
+CONFIG_NET_IPGRE_BROADCAST
+ One application of GRE/IP is to construct a broadcast WAN (Wide Area
+ Network), which looks like a normal Ethernet LAN (Local Area
+ Network), but can be distributed all over the Internet. If you want
+ to do that, say Y here and to "IP multicast routing" below.
+
+IP multicast routing
+CONFIG_IP_MROUTE
+ This is used if you want your machine to act as a router for IP
+ packets that have several destination addresses. It is needed on the
+ MBONE, a high bandwidth network on top of the Internet which carries
+ audio and video broadcasts. In order to do that, you would most
+ likely run the program mrouted. Information about the multicast
+ capabilities of the various network cards is contained in
+ <file:Documentation/networking/multicast.txt>. If you haven't heard
+ about it, you don't need it.
+
+PIM-SM version 1 support
+CONFIG_IP_PIMSM_V1
+ Kernel side support for Sparse Mode PIM (Protocol Independent
+ Multicast) version 1. This multicast routing protocol is used widely
+ because Cisco supports it. You need special software to use it
+ (pimd-v1). Please see <http://netweb.usc.edu/pim/> for more
+ information about PIM.
+
+ Say Y if you want to use PIM-SM v1. Note that you can say N here if
+ you just want to use Dense Mode PIM.
+
+PIM-SM version 2 support
+CONFIG_IP_PIMSM_V2
+ Kernel side support for Sparse Mode PIM version 2. In order to use
+ this, you need an experimental routing daemon supporting it (pimd or
+ gated-5). This routing protocol is not used widely, so say N unless
+ you want to play with it.
+
+Unix domain sockets
+CONFIG_UNIX
+ If you say Y here, you will include support for Unix domain sockets;
+ sockets are the standard Unix mechanism for establishing and
+ accessing network connections. Many commonly used programs such as
+ the X Window system and syslog use these sockets even if your
+ machine is not connected to any network. Unless you are working on
+ an embedded system or something similar, you therefore definitely
+ want to say Y here.
+
+ However, the socket support is also available as a module ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>. The module will be
+ called unix.o. If you try building this as a module and you have
+ said Y to "Kernel module loader support" above, be sure to add
+ 'alias net-pf-1 unix' to your /etc/modules.conf file. Note that
+ several important services won't work correctly if you say M here
+ and then neglect to load the module.
+
+ Say Y unless you know what you are doing.
+
+The IPv6 protocol
+CONFIG_IPV6
+ This is experimental support for the next version of the Internet
+ Protocol: IP version 6 (also called IPng "IP next generation").
+ Features of this new protocol include: expanded address space,
+ authentication and privacy, and seamless interoperability with the
+ current version of IP (IP version 4). For general information about
+ IPv6, see <http://playground.sun.com/pub/ipng/html/ipng-main.html>;
+ for specific information about IPv6 under Linux read the HOWTO at
+ <http://www.bieringer.de/linux/IPv6/> and the file net/ipv6/README
+ in the kernel source.
+
+ If you want to use IPv6, please upgrade to the newest net-tools as
+ given in <file:Documentation/Changes>. You will still be able to do
+ regular IPv4 networking as well.
+
+ This protocol support is also available as a module ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want). The module will be called ipv6.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+ It is safe to say N here for now.
+
+Kernel httpd acceleration
+CONFIG_KHTTPD
+ The kernel httpd acceleration daemon (kHTTPd) is a (limited) web
+ server built into the kernel. It is limited since it can only serve
+ files from the file system and cannot deal with executable content
+ such as CGI scripts. Serving files is sped up if you use kHTTPd.
+ If kHTTPd is not able to fulfill a request, it can transparently
+ pass it through to a user space web server such as apache.
+
+ Saying "M" here builds the kHTTPd module; this is NOT enough to have
+ a working kHTTPd. For safety reasons, the module has to be activated
+ by doing a "echo 1 > /proc/sys/net/khttpd/start" after inserting the
+ module.
+
+ Before using this, read the README in net/khttpd !
+
+ The kHTTPd is experimental. Be careful when using it on a production
+ machine. Also note that kHTTPd doesn't support virtual servers yet.
+
+The IPX protocol
+CONFIG_IPX
+ This is support for the Novell networking protocol, IPX, commonly
+ used for local networks of Windows machines. You need it if you
+ want to access Novell NetWare file or print servers using the Linux
+ Novell client ncpfs (available from
+ <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from
+ within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>). In order
+ to do the former, you'll also have to say Y to "NCP file system
+ support", below.
+
+ IPX is similar in scope to IP, while SPX, which runs on top of IPX,
+ is similar to TCP. There is also experimental support for SPX in
+ Linux (see "SPX networking", below).
+
+ To turn your Linux box into a fully featured NetWare file server and
+ IPX router, say Y here and fetch either lwared from
+ <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or
+ mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more
+ information, read the IPX-HOWTO available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ General information about how to connect Linux, Windows machines and
+ Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
+
+ The IPX driver would enlarge your kernel by about 16 KB. This driver
+ is also available as a module ( = code which can be inserted in and
+ removed from the running kernel whenever you want). The module will
+ be called ipx.o. If you want to compile it as a module, say M here
+ and read <file:Documentation/modules.txt>. Unless you want to
+ integrate your Linux box with a local Novell network, say N.
+
+Full internal IPX network
+CONFIG_IPX_INTERN
+ Every IPX network has an address that identifies it. Sometimes it is
+ useful to give an IPX "network" address to your Linux box as well
+ (for example if your box is acting as a file server for different
+ IPX networks: it will then be accessible from everywhere using the
+ same address). The way this is done is to create a virtual internal
+ "network" inside your box and to assign an IPX address to this
+ network. Say Y here if you want to do this; read the IPX-HOWTO at
+ <http://www.tldp.org/docs.html#howto> for details.
+
+ The full internal IPX network enables you to allocate sockets on
+ different virtual nodes of the internal network. This is done by
+ evaluating the field sipx_node of the socket address given to the
+ bind call. So applications should always initialize the node field
+ to 0 when binding a socket on the primary network. In this case the
+ socket is assigned the default node that has been given to the
+ kernel when the internal network was created. By enabling the full
+ internal IPX network the cross-forwarding of packets targeted at
+ 'special' sockets to sockets listening on the primary network is
+ disabled. This might break existing applications, especially RIP/SAP
+ daemons. A RIP/SAP daemon that works well with the full internal net
+ can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/>.
+
+ If you don't know what you are doing, say N.
+
+#(We're told this will come back someday)
+
+SPX networking
+CONFIG_SPX
+ * Orphaned entry retained 20 April 2001 by Petr Vandrovec *
+ * If you read this note from the configurator, please contact *
+ * the Configure.help maintainers. *
+ The Sequenced Packet eXchange protocol is a transport layer protocol
+ built on top of IPX. It is used in Novell NetWare systems for
+ client-server applications and is similar to TCP (which runs on top
+ of IP).
+
+ Note that Novell NetWare file sharing does not use SPX; it uses a
+ protocol called NCP, for which separate Linux support is available
+ ("NCP file system support" below for the client side, and the user
+ space programs lwared or mars_nwe for the server side).
+
+ Say Y here if you have use for SPX; read the IPX-HOWTO at
+ <http://www.tldp.org/docs.html#howto> for details.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called af_spx.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+DECnet networking
+CONFIG_DECNET
+ The DECnet networking protocol was used in many products made by
+ Digital (now Compaq). It provides reliable stream and sequenced
+ packet communications over which run a variety of services similar
+ to those which run over TCP/IP.
+
+ To find some tools to use with the kernel layer support, please
+ look at Patrick Caulfield's web site:
+ <http://linux.dreamtime.org/decnet/>.
+
+ More detailed documentation is available in
+ <file:Documentation/networking/decnet.txt>.
+
+ Be sure to say Y to "/proc file system support" and "Sysctl support"
+ below when using DECnet, since you will need sysctl support to aid
+ in configuration at run time.
+
+ The DECnet code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called decnet.o.
+
+DECnet SIOCFIGCONF support
+CONFIG_DECNET_SIOCGIFCONF
+ This option should only be turned on if you are really sure that
+ you know what you are doing. It can break other applications which
+ use this system call and the proper way to get the information
+ provided by this call is to use rtnetlink.
+
+ If unsure, say N.
+
+DECnet router support
+CONFIG_DECNET_ROUTER
+ Add support for turning your DECnet Endnode into a level 1 or 2
+ router. This is an unfinished option for developers only. If you
+ do say Y here, then make sure that you also say Y to "Kernel/User
+ network link driver", "Routing messages" and "Network packet
+ filtering". The first two are required to allow configuration via
+ rtnetlink (currently you need Alexey Kuznetsov's iproute2 package
+ from <ftp://ftp.inr.ac.ru/>). The "Network packet filtering" option
+ will be required for the forthcoming routing daemon to work.
+
+ See <file:Documentation/networking/decnet.txt> for more information.
+
+Use FWMARK value as DECnet routing key
+CONFIG_DECNET_ROUTE_FWMARK
+ If you say Y here, you will be able to specify different routes for
+ packets with different FWMARK ("firewalling mark") values
+ (see ipchains(8), "-m" argument).
+
+AppleTalk interfaces support
+CONFIG_DEV_APPLETALK
+ AppleTalk is the protocol that Apple computers can use to communicate
+ on a network. If your Linux box is connected to such a network, and wish
+ to do IP over it, or you have a LocalTalk card and wish to use it to
+ connect to the AppleTalk network, say Y.
+
+AppleTalk protocol support
+CONFIG_ATALK
+ AppleTalk is the protocol that Apple computers can use to communicate
+ on a network. If your Linux box is connected to such a network and you
+ wish to connect to it, say Y. You will need to use the netatalk package
+ so that your Linux box can act as a print and file server for Macs as
+ well as access AppleTalk printers. Check out
+ <http://www.zettabyte.net/netatalk/> on the WWW for details.
+ EtherTalk is the name used for AppleTalk over Ethernet and the
+ cheaper and slower LocalTalk is AppleTalk over a proprietary Apple
+ network using serial links. EtherTalk and LocalTalk are fully
+ supported by Linux.
+
+ General information about how to connect Linux, Windows machines and
+ Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>. The
+ NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, contains valuable
+ information as well.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called appletalk.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. You
+ almost certainly want to compile it as a module so you can restart
+ your AppleTalk stack without rebooting your machine. I hear that
+ the GNU boycott of Apple is over, so even politically correct people
+ are allowed to say Y here.
+
+AppleTalk-IP driver support
+CONFIG_IPDDP
+ This allows IP networking for users who only have AppleTalk
+ networking available. This feature is experimental. With this
+ driver, you can encapsulate IP inside AppleTalk (e.g. if your Linux
+ box is stuck on an AppleTalk only network) or decapsulate (e.g. if
+ you want your Linux box to act as an Internet gateway for a zoo of
+ AppleTalk connected Macs). Please see the file
+ <file:Documentation/networking/ipddp.txt> for more information.
+
+ If you say Y here, the AppleTalk-IP support will be compiled into
+ the kernel. In this case, you can either use encapsulation or
+ decapsulation, but not both. With the following two questions, you
+ decide which one you want.
+
+ If you say M here, the AppleTalk-IP support will be compiled as a
+ module ( = code which can be inserted in and removed from the
+ running kernel whenever you want, read
+ <file:Documentation/modules.txt>). The module is called ipddp.o.
+ In this case, you will be able to use both encapsulation and
+ decapsulation simultaneously, by loading two copies of the module
+ and specifying different values for the module option ipddp_mode.
+
+IP to AppleTalk-IP Encapsulation support
+CONFIG_IPDDP_ENCAP
+ If you say Y here, the AppleTalk-IP code will be able to encapsulate
+ IP packets inside AppleTalk frames; this is useful if your Linux box
+ is stuck on an AppleTalk network (which hopefully contains a
+ decapsulator somewhere). Please see
+ <file:Documentation/networking/ipddp.txt> for more information. If
+ you said Y to "AppleTalk-IP driver support" above and you say Y
+ here, then you cannot say Y to "AppleTalk-IP to IP Decapsulation
+ support", below.
+
+AppleTalk-IP to IP Decapsulation support
+CONFIG_IPDDP_DECAP
+ If you say Y here, the AppleTalk-IP code will be able to decapsulate
+ AppleTalk-IP frames to IP packets; this is useful if you want your
+ Linux box to act as an Internet gateway for an AppleTalk network.
+ Please see <file:Documentation/networking/ipddp.txt> for more
+ information. If you said Y to "AppleTalk-IP driver support" above
+ and you say Y here, then you cannot say Y to "IP to AppleTalk-IP
+ Encapsulation support", above.
+
+Apple/Farallon LocalTalk PC card support
+CONFIG_LTPC
+ This allows you to use the AppleTalk PC card to connect to LocalTalk
+ networks. The card is also known as the Farallon PhoneNet PC card.
+ If you are in doubt, this card is the one with the 65C02 chip on it.
+ You also need version 1.3.3 or later of the netatalk package.
+ This driver is experimental, which means that it may not work.
+ See the file <file:Documentation/networking/ltpc.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ltpc.o
+
+COPS LocalTalk PC card support
+CONFIG_COPS
+ This allows you to use COPS AppleTalk cards to connect to LocalTalk
+ networks. You also need version 1.3.3 or later of the netatalk
+ package. This driver is experimental, which means that it may not
+ work. This driver will only work if you choose "AppleTalk DDP"
+ networking support, above.
+ Please read the file <file:Documentation/networking/cops.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ cops.o
+
+Dayna firmware support
+CONFIG_COPS_DAYNA
+ Support COPS compatible cards with Dayna style firmware (Dayna
+ DL2000/ Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC
+ III, Farallon PhoneNET PC II).
+
+Tangent firmware support
+CONFIG_COPS_TANGENT
+ Support COPS compatible cards with Tangent style firmware (Tangent
+ ATB_II, Novell NL-1000, Daystar Digital LT-200.
+
+Amateur Radio support
+CONFIG_HAMRADIO
+ If you want to connect your Linux box to an amateur radio, answer Y
+ here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> and
+ the AX25-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about amateur radio.
+
+Amateur Radio AX.25 Level 2 protocol
+CONFIG_AX25
+ This is the protocol used for computer communication over amateur
+ radio. It is either used by itself for point-to-point links, or to
+ carry other protocols such as tcp/ip. To use it, you need a device
+ that connects your Linux box to your amateur radio. You can either
+ use a low speed TNC (a Terminal Node Controller acts as a kind of
+ modem connecting your computer's serial port to your radio's
+ microphone input and speaker output) supporting the KISS protocol or
+ one of the various SCC cards that are supported by the generic Z8530
+ or the DMA SCC driver. Another option are the Baycom modem serial
+ and parallel port hacks or the sound card modem (supported by their
+ own drivers). If you say Y here, you also have to say Y to one of
+ those drivers.
+
+ Information about where to get supporting software for Linux amateur
+ radio as well as information about how to configure an AX.25 port is
+ contained in the AX25-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. You might also want to
+ check out the file <file:Documentation/networking/ax25.txt> in the
+ kernel source. More information about digital amateur radio in
+ general is on the WWW at
+ <http://www.tapr.org/tapr/html/pkthome.html>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ax25.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+AX.25 DAMA Slave support
+CONFIG_AX25_DAMA_SLAVE
+ DAMA is a mechanism to prevent collisions when doing AX.25
+ networking. A DAMA server (called "master") accepts incoming traffic
+ from clients (called "slaves") and redistributes it to other slaves.
+ If you say Y here, your Linux box will act as a DAMA slave; this is
+ transparent in that you don't have to do any special DAMA
+ configuration. (Linux cannot yet act as a DAMA server.) If unsure,
+ say N.
+
+AX.25 DAMA Master support
+CONFIG_AX25_DAMA_MASTER
+ DAMA is a mechanism to prevent collisions when doing AX.25
+ networking. A DAMA server (called "master") accepts incoming traffic
+ from clients (called "slaves") and redistributes it to other
+ slaves. If you say Y here, your Linux box will act as a DAMA server.
+ If unsure, say N.
+
+Amateur Radio NET/ROM support
+CONFIG_NETROM
+ NET/ROM is a network layer protocol on top of AX.25 useful for
+ routing.
+
+ A comprehensive listing of all the software for Linux amateur radio
+ users as well as information about how to configure an AX.25 port is
+ contained in the AX25-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. You also might want to
+ check out the file <file:Documentation/networking/ax25.txt>. More
+ information about digital amateur radio in general is on the WWW at
+ <http://www.tapr.org/tapr/html/pkthome.html>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called netrom.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Amateur Radio X.25 PLP (Rose)
+CONFIG_ROSE
+ The Packet Layer Protocol (PLP) is a way to route packets over X.25
+ connections in general and amateur radio AX.25 connections in
+ particular, essentially an alternative to NET/ROM.
+
+ A comprehensive listing of all the software for Linux amateur radio
+ users as well as information about how to configure an AX.25 port is
+ contained in the AX25-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. You also might want to
+ check out the file <file:Documentation/networking/ax25.txt>. More
+ information about digital amateur radio in general is on the WWW at
+ <http://www.tapr.org/tapr/html/pkthome.html>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called rose.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Serial port KISS driver for AX.25
+CONFIG_MKISS
+ KISS is a protocol used for the exchange of data between a computer
+ and a Terminal Node Controller (a small embedded system commonly
+ used for networking over AX.25 amateur radio connections; it
+ connects the computer's serial port with the radio's microphone
+ input and speaker output).
+
+ Although KISS is less advanced than the 6pack protocol, it has
+ the advantage that it is already supported by most modern TNCs
+ without the need for a firmware upgrade.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called mkiss.o.
+
+Serial port 6PACK driver for AX.25
+CONFIG_6PACK
+ 6pack is a transmission protocol for the data exchange between your
+ PC and your TNC (the Terminal Node Controller acts as a kind of
+ modem connecting your computer's serial port to your radio's
+ microphone input and speaker output). This protocol can be used as
+ an alternative to KISS for networking over AX.25 amateur radio
+ connections, but it has some extended functionality.
+
+ Note that this driver is still experimental and might cause
+ problems. For details about the features and the usage of the
+ driver, read <file:Documentation/networking/6pack.txt>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called 6pack.o.
+
+BPQ Ethernet driver
+CONFIG_BPQETHER
+ AX.25 is the protocol used for computer communication over amateur
+ radio. If you say Y here, you will be able to send and receive AX.25
+ traffic over Ethernet (also called "BPQ AX.25"), which could be
+ useful if some other computer on your local network has a direct
+ amateur radio connection.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called bpqether.o.
+
+High-speed (DMA) SCC driver for AX.25
+CONFIG_DMASCC
+ This is a driver for high-speed SCC boards, i.e. those supporting
+ DMA on one port. You usually use those boards to connect your
+ computer to an amateur radio modem (such as the WA4DSY 56kbps
+ modem), in order to send and receive AX.25 packet radio network
+ traffic.
+
+ Currently, this driver supports Ottawa PI/PI2, Paccomm/Gracilis
+ PackeTwin, and S5SCC/DMA boards. They are detected automatically.
+ If you have one of these cards, say Y here and read the AX25-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver can operate multiple boards simultaneously. If you
+ compile it as a module (by saying M instead of Y), it will be called
+ dmascc.o. If you don't pass any parameter to the driver, all
+ possible I/O addresses are probed. This could irritate other devices
+ that are currently not in use. You may specify the list of addresses
+ to be probed by "dmascc=addr1,addr2,..." (when compiled into the
+ kernel image) or "io=addr1,addr2,..." (when loaded as a module). The
+ network interfaces will be called dmascc0 and dmascc1 for the board
+ detected first, dmascc2 and dmascc3 for the second one, and so on.
+
+ Before you configure each interface with ifconfig, you MUST set
+ certain parameters, such as channel access timing, clock mode, and
+ DMA channel. This is accomplished with a small utility program,
+ dmascc_cfg, available at
+ <http://www.nt.tuwien.ac.at/~kkudielk/Linux/>. Please be sure to get
+ at least version 1.27 of dmascc_cfg, as older versions will not
+ work with the current driver.
+
+Z8530 SCC driver for AX.25
+CONFIG_SCC
+ These cards are used to connect your Linux box to an amateur radio
+ in order to communicate with other computers. If you want to use
+ this, read <file:Documentation/networking/z8530drv.txt> and the
+ AX25-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Also make sure to say Y
+ to "Amateur Radio AX.25 Level 2" support.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called scc.o.
+
+Support for TRX that feedback the tx signal to rx
+CONFIG_SCC_TRXECHO
+ Some transmitters feed the transmitted signal back to the receive
+ line. Say Y here to foil this by explicitly disabling the receiver
+ during data transmission. If in doubt, say Y.
+
+Additional delay for PA0HZP OptoSCC compatible boards
+CONFIG_SCC_DELAY
+ Say Y here if you experience problems with the SCC driver not
+ working properly; please read
+ <file:Documentation/networking/z8530drv.txt> for details. If unsure,
+ say N.
+
+YAM driver for AX.25
+CONFIG_YAM
+ The YAM is a modem for packet radio which connects to the serial
+ port and includes some of the functions of a Terminal Node
+ Controller. If you have one of those, say Y here.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called yam.o.
+
+BAYCOM picpar and par96 driver for AX.25
+CONFIG_BAYCOM_PAR
+ This is a driver for Baycom style simple amateur radio modems that
+ connect to a parallel interface. The driver supports the picpar and
+ par96 designs. To configure the driver, use the sethdlc utility
+ available in the standard ax25 utilities package. For information on
+ the modems, see <http://www.baycom.de/> and the file
+ <file:Documentation/networking/baycom.txt>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_par.o.
+
+BAYCOM EPP driver for AX.25
+CONFIG_BAYCOM_EPP
+ This is a driver for Baycom style simple amateur radio modems that
+ connect to a parallel interface. The driver supports the EPP
+ designs. To configure the driver, use the sethdlc utility available
+ in the standard ax25 utilities package. For information on the
+ modems, see <http://www.baycom.de/> and the file
+ <file:Documentation/networking/baycom.txt>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_par.o.
+
+BAYCOM ser12 full-duplex driver for AX.25
+CONFIG_BAYCOM_SER_FDX
+ This is one of two drivers for Baycom style simple amateur radio
+ modems that connect to a serial interface. The driver supports the
+ ser12 design in full-duplex mode. In addition, it allows the
+ baudrate to be set between 300 and 4800 baud (however not all modems
+ support all baudrates). This is the preferred driver. The next
+ driver, "BAYCOM ser12 half-duplex driver for AX.25" is the old
+ driver and still provided in case this driver does not work with
+ your serial interface chip. To configure the driver, use the sethdlc
+ utility available in the standard ax25 utilities package. For
+ information on the modems, see <http://www.baycom.de/> and
+ <file:Documentation/networking/baycom.txt>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_ser_fdx.o.
+
+BAYCOM ser12 half-duplex driver for AX.25
+CONFIG_BAYCOM_SER_HDX
+ This is one of two drivers for Baycom style simple amateur radio
+ modems that connect to a serial interface. The driver supports the
+ ser12 design in full-duplex mode. This is the old driver. It is
+ still provided in case your serial interface chip does not work with
+ the full-duplex driver. This driver is depreciated. To configure
+ the driver, use the sethdlc utility available in the standard ax25
+ utilities package. For information on the modems, see
+ <http://www.baycom.de/> and
+ <file:Documentation/networking/baycom.txt>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called baycom_ser_hdx.o.
+
+Sound card modem driver for AX.25
+CONFIG_SOUNDMODEM
+ This experimental driver allows a standard Sound Blaster or
+ WindowsSoundSystem compatible sound card to be used as a packet
+ radio modem (NOT as a telephone modem!), to send digital traffic
+ over amateur radio.
+
+ To configure the driver, use the sethdlc, smdiag and smmixer
+ utilities available in the standard ax25 utilities package. For
+ information on how to key the transmitter, see
+ <http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html> and
+ <file:Documentation/networking/soundmodem.txt>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called soundmodem.o.
+
+Sound card modem support for Sound Blaster and compatible cards
+CONFIG_SOUNDMODEM_SBC
+ This option enables the soundmodem driver to use Sound Blaster and
+ compatible cards. If you have a dual mode card (i.e. a WSS cards
+ with a Sound Blaster emulation) you should say N here and Y to
+ "Sound card modem support for WSS and Crystal cards", below, because
+ this usually results in better performance. This option also
+ supports SB16/32/64 in full-duplex mode.
+
+Sound card modem support for WSS and Crystal cards
+CONFIG_SOUNDMODEM_WSS
+ This option enables the soundmodem driver to use WindowsSoundSystem
+ compatible cards. These cards feature a codec chip from either
+ Analog Devices (such as AD1848, AD1845, AD1812) or Crystal
+ Semiconductors (such as CS4248, CS423x). This option also supports
+ the WSS full-duplex operation which currently works with Crystal
+ CS423x chips. If you don't need full-duplex operation, do not enable
+ it to save performance.
+
+Sound card modem support for 1200 baud AFSK modulation
+CONFIG_SOUNDMODEM_AFSK1200
+ This option enables the soundmodem driver 1200 baud AFSK modem,
+ compatible to popular modems using TCM3105 or AM7911. The
+ demodulator requires about 12% of the CPU power of a Pentium 75 CPU
+ per channel.
+
+Sound card modem support for 2400 baud AFSK modulation (7.3728MHz crystal)
+CONFIG_SOUNDMODEM_AFSK2400_7
+ This option enables the soundmodem driver 2400 baud AFSK modem,
+ compatible to TCM3105 modems (over-)clocked with a 7.3728MHz
+ crystal. Note that the availability of this driver does _not_ imply
+ that I recommend building such links. It is only here since users
+ especially in eastern Europe have asked me to do so. In fact this
+ modulation scheme has many disadvantages, mainly its incompatibility
+ with many transceiver designs and the fact that the TCM3105 (if
+ used) is operated widely outside its specifications.
+
+Sound card modem support for 2400 baud AFSK modulation (8MHz crystal)
+CONFIG_SOUNDMODEM_AFSK2400_8
+ This option enables the soundmodem driver 2400 baud AFSK modem,
+ compatible to TCM3105 modems (over-)clocked with an 8MHz crystal.
+ Note that the availability of this driver does _not_ imply that I
+ recommend building such links. It is only here since users
+ especially in eastern Europe have asked me to do so. In fact this
+ modulation scheme has many disadvantages, mainly its incompatibility
+ with many transceiver designs and the fact that the TCM3105 (if
+ used) is operated widely outside its specifications.
+
+Sound card modem support for 2666 baud AFSK modulation
+CONFIG_SOUNDMODEM_AFSK2666
+ This option enables the soundmodem driver 2666 baud AFSK modem.
+ This modem is experimental, and not compatible to anything
+ else I know of.
+
+Sound card modem support for 4800 baud 8PSK modulation
+CONFIG_SOUNDMODEM_PSK4800
+ This option enables the soundmodem driver 4800 baud 8PSK modem.
+ This modem is experimental, and not compatible to anything
+ else I know of.
+
+Sound card modem support for 4800 baud HAPN-1 modulation
+CONFIG_SOUNDMODEM_HAPN4800
+ This option enables the soundmodem driver 4800 baud HAPN-1
+ compatible modem. This modulation seems to be widely used 'down
+ under' and in the Netherlands. Here, nobody uses it, so I could not
+ test if it works. It is compatible to itself, however :-)
+
+Sound card modem support for 9600 baud FSK G3RUH modulation
+CONFIG_SOUNDMODEM_FSK9600
+ This option enables the soundmodem driver 9600 baud FSK modem,
+ compatible to the G3RUH standard. The demodulator requires about 4%
+ of the CPU power of a Pentium 75 CPU per channel. You can say Y to
+ both 1200 baud AFSK and 9600 baud FSK if you want (but obviously you
+ can only use one protocol at a time, depending on what the other end
+ can understand).
+
+CCITT X.25 Packet Layer
+CONFIG_X25
+ X.25 is a set of standardized network protocols, similar in scope to
+ frame relay; the one physical line from your box to the X.25 network
+ entry point can carry several logical point-to-point connections
+ (called "virtual circuits") to other computers connected to the X.25
+ network. Governments, banks, and other organizations tend to use it
+ to connect to each other or to form Wide Area Networks (WANs). Many
+ countries have public X.25 networks. X.25 consists of two
+ protocols: the higher level Packet Layer Protocol (PLP) (say Y here
+ if you want that) and the lower level data link layer protocol LAPB
+ (say Y to "LAPB Data Link Driver" below if you want that).
+
+ You can read more about X.25 at <http://www.sangoma.com/x25.htm> and
+ <http://www.cisco.com/univercd/data/doc/software/11_0/rpcg/cx25.htm>.
+ Information about X.25 for Linux is contained in the files
+ <file:Documentation/networking/x25.txt> and
+ <file:Documentation/networking/x25-iface.txt>.
+
+ One connects to an X.25 network either with a dedicated network card
+ using the X.21 protocol (not yet supported by Linux) or one can do
+ X.25 over a standard telephone line using an ordinary modem (say Y
+ to "X.25 async driver" below) or over Ethernet using an ordinary
+ Ethernet card and either the 802.2 LLC protocol (say Y to "802.2
+ LLC" below) or LAPB over Ethernet (say Y to "LAPB Data Link Driver"
+ and "LAPB over Ethernet driver" below).
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called x25.o. If unsure, say N.
+
+LAPB Data Link Driver
+CONFIG_LAPB
+ Link Access Procedure, Balanced (LAPB) is the data link layer (i.e.
+ the lower) part of the X.25 protocol. It offers a reliable
+ connection service to exchange data frames with one other host, and
+ it is used to transport higher level protocols (mostly X.25 Packet
+ Layer, the higher part of X.25, but others are possible as well).
+ Usually, LAPB is used with specialized X.21 network cards, but Linux
+ currently supports LAPB only over Ethernet connections. If you want
+ to use LAPB connections over Ethernet, say Y here and to "LAPB over
+ Ethernet driver" below. Read
+ <file:Documentation/networking/lapb-module.txt> for technical
+ details.
+
+ If you want to compile this driver as a module though ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called lapb.o. If unsure, say N.
+
+802.2 LLC
+CONFIG_LLC
+ This is a Logical Link Layer protocol used for X.25 connections over
+ Ethernet, using ordinary Ethernet cards.
+
+Frame Diverter
+CONFIG_NET_DIVERT
+ The Frame Diverter allows you to divert packets from the
+ network, that are not aimed at the interface receiving it (in
+ promisc. mode). Typically, a Linux box setup as an Ethernet bridge
+ with the Frames Diverter on, can do some *really* transparent www
+ caching using a Squid proxy for example.
+
+ This is very useful when you don't want to change your router's
+ config (or if you simply don't have access to it).
+
+ The other possible usages of diverting Ethernet Frames are
+ numberous:
+ - reroute smtp traffic to another interface
+ - traffic-shape certain network streams
+ - transparently proxy smtp connections
+ - etc...
+
+ For more informations, please refer to:
+ <http://diverter.sourceforge.net/>
+ <http://perso.wanadoo.fr/magpie/EtherDivert.html>
+
+ If unsure, say N.
+
+802.1d Ethernet Bridging
+CONFIG_BRIDGE
+ If you say Y here, then your Linux box will be able to act as an
+ Ethernet bridge, which means that the different Ethernet segments it
+ is connected to will appear as one Ethernet to the participants.
+ Several such bridges can work together to create even larger
+ networks of Ethernets using the IEEE 802.1 spanning tree algorithm.
+ As this is a standard, Linux bridges will cooperate properly with
+ other third party bridge products.
+
+ In order to use the Ethernet bridge, you'll need the bridge
+ configuration tools; see <file:Documentation/networking/bridge.txt>
+ for location. Please read the Bridge mini-HOWTO for more
+ information.
+
+ Note that if your box acts as a bridge, it probably contains several
+ Ethernet devices, but the kernel is not able to recognize more than
+ one at boot time without help; for details read the Ethernet-HOWTO,
+ available from in <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this code as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called bridge.o.
+
+ If unsure, say N.
+
+Packet socket
+CONFIG_PACKET
+ The Packet protocol is used by applications which communicate
+ directly with network devices without an intermediate network
+ protocol implemented in the kernel, e.g. tcpdump. If you want them
+ to work, choose Y.
+
+ This driver is also available as a module called af_packet.o ( =
+ code which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>; if you use modprobe
+ or kmod, you may also want to add "alias net-pf-17 af_packet" to
+ /etc/modules.conf.
+
+ If unsure, say Y.
+
+Packet socket: mmapped IO
+CONFIG_PACKET_MMAP
+ If you say Y here, the Packet protocol driver will use an IO
+ mechanism that results in faster communication.
+
+ If unsure, say N.
+
+Netlink device emulation
+CONFIG_NETLINK_DEV
+ This option will be removed soon. Any programs that want to use
+ character special nodes like /dev/tap0 or /dev/route (all with major
+ number 36) need this option, and need to be rewritten soon to use
+ the real netlink socket.
+ This is a backward compatibility option, choose Y for now.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ netlink_dev.o
+
+Asynchronous Transfer Mode (ATM)
+CONFIG_ATM
+ ATM is a high-speed networking technology for Local Area Networks
+ and Wide Area Networks. It uses a fixed packet size and is
+ connection oriented, allowing for the negotiation of minimum
+ bandwidth requirements.
+
+ In order to participate in an ATM network, your Linux box needs an
+ ATM networking card. If you have that, say Y here and to the driver
+ of your ATM card below.
+
+ Note that you need a set of user-space programs to actually make use
+ of ATM. See the file <file:Documentation/networking/atm.txt> for
+ further details.
+
+Classical IP over ATM
+CONFIG_ATM_CLIP
+ Classical IP over ATM for PVCs and SVCs, supporting InARP and
+ ATMARP. If you want to communication with other IP hosts on your ATM
+ network, you will typically either say Y here or to "LAN Emulation
+ (LANE)" below.
+
+Do NOT send ICMP if no neighbour
+CONFIG_ATM_CLIP_NO_ICMP
+ Normally, an "ICMP host unreachable" message is sent if a neighbour
+ cannot be reached because there is no VC to it in the kernel's
+ ATMARP table. This may cause problems when ATMARP table entries are
+ briefly removed during revalidation. If you say Y here, packets to
+ such neighbours are silently discarded instead.
+
+RFC1483/2684 Bridged protocols
+CONFIG_ATM_BR2684
+ ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483)
+ This device will act like an ethernet from the kernels point of view,
+ with the traffic being carried by ATM PVCs (currently 1 PVC/device).
+ This is sometimes used over DSL lines. If in doubt, say N.
+
+Per-VC IP filter kludge
+CONFIG_ATM_BR2684_IPFILTER
+ This is an experimental mechanism for users who need to terminating a
+ large number of IP-only vcc's. Do not enable this unless you are sure
+ you know what you are doing.
+
+LAN Emulation (LANE) support
+CONFIG_ATM_LANE
+ LAN Emulation emulates services of existing LANs across an ATM
+ network. Besides operating as a normal ATM end station client, Linux
+ LANE client can also act as an proxy client bridging packets between
+ ELAN and Ethernet segments. You need LANE if you want to try MPOA.
+
+Multi-Protocol Over ATM (MPOA) support
+CONFIG_ATM_MPOA
+ Multi-Protocol Over ATM allows ATM edge devices such as routers,
+ bridges and ATM attached hosts establish direct ATM VCs across
+ subnetwork boundaries. These shortcut connections bypass routers
+ enhancing overall network performance.
+
+ATM over TCP
+CONFIG_ATM_TCP
+ ATM over TCP driver. Useful mainly for development and for
+ experiments. If unsure, say N.
+
+Efficient Networks ENI155P
+CONFIG_ATM_ENI
+ Driver for the Efficient Networks ENI155p series and SMC ATM
+ Power155 155 Mbps ATM adapters. Both, the versions with 512KB and
+ 2MB on-board RAM (Efficient calls them "C" and "S", respectively),
+ and the FPGA and the ASIC Tonga versions of the board are supported.
+ The driver works with MMF (-MF or ...F) and UTP-5 (-U5 or ...D)
+ adapters.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called eni.o.
+
+Enable extended debugging
+CONFIG_ATM_ENI_DEBUG
+ Extended debugging records various events and displays that list
+ when an inconsistency is detected. This mechanism is faster than
+ generally using printks, but still has some impact on performance.
+ Note that extended debugging may create certain race conditions
+ itself. Enable this ONLY if you suspect problems with the driver.
+
+Fine-tune burst settings
+CONFIG_ATM_ENI_TUNE_BURST
+ In order to obtain good throughput, the ENI NIC can transfer
+ multiple words of data per PCI bus access cycle. Such a multi-word
+ transfer is called a burst.
+
+ The default settings for the burst sizes are suitable for most PCI
+ chipsets. However, in some cases, large bursts may overrun buffers
+ in the PCI chipset and cause data corruption. In such cases, large
+ bursts must be disabled and only (slower) small bursts can be used.
+ The burst sizes can be set independently in the send (TX) and
+ receive (RX) direction.
+
+ Note that enabling many different burst sizes in the same direction
+ may increase the cost of setting up a transfer such that the
+ resulting throughput is lower than when using only the largest
+ available burst size.
+
+ Also, sometimes larger bursts lead to lower throughput, e.g. on an
+ Intel 440FX board, a drop from 135 Mbps to 103 Mbps was observed
+ when going from 8W to 16W bursts.
+
+Enable 16W TX bursts (discouraged)
+CONFIG_ATM_ENI_BURST_TX_16W
+ Burst sixteen words at once in the send direction. This may work
+ with recent PCI chipsets, but is known to fail with older chipsets.
+
+Enable 8W TX bursts (recommended)
+CONFIG_ATM_ENI_BURST_TX_8W
+ Burst eight words at once in the send direction. This is the default
+ setting.
+
+Enable 4W TX bursts (optional)
+CONFIG_ATM_ENI_BURST_TX_4W
+ Burst four words at once in the send direction. You may want to try
+ this if you have disabled 8W bursts. Enabling 4W if 8W is also set
+ may or may not improve throughput.
+
+Enable 2W TX bursts (optional)
+CONFIG_ATM_ENI_BURST_TX_2W
+ Burst two words at once in the send direction. You may want to try
+ this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or 8W
+ are also set may or may not improve throughput.
+
+Enable 16W RX bursts (discouraged)
+CONFIG_ATM_ENI_BURST_RX_16W
+ Burst sixteen words at once in the receive direction. This may work
+ with recent PCI chipsets, but is known to fail with older chipsets.
+
+Enable 8W RX bursts (discouraged)
+CONFIG_ATM_ENI_BURST_RX_8W
+ Burst eight words at once in the receive direction. This may work
+ with recent PCI chipsets, but is known to fail with older chipsets,
+ such as the Intel Neptune series.
+
+Enable 4W RX bursts (recommended)
+CONFIG_ATM_ENI_BURST_RX_4W
+ Burst four words at once in the receive direction. This is the
+ default setting. Enabling 4W if 8W is also set may or may not
+ improve throughput.
+
+Enable 2W RX bursts (optional)
+CONFIG_ATM_ENI_BURST_RX_2W
+ Burst two words at once in the receive direction. You may want to
+ try this if you have disabled 4W and 8W bursts. Enabling 2W if 4W or
+ 8W are also set may or may not improve throughput.
+
+ZeitNet ZN1221/ZN1225
+CONFIG_ATM_ZATM
+ Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM
+ adapters.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called zatm.o.
+
+Enable extended debugging
+CONFIG_ATM_ZATM_DEBUG
+ Extended debugging records various events and displays that list
+ when an inconsistency is detected. This mechanism is faster than
+ generally using printks, but still has some impact on performance.
+ Note that extended debugging may create certain race conditions
+ itself. Enable this ONLY if you suspect problems with the driver.
+
+Fujitsu FireStream (FS50/FS155)
+CONFIG_ATM_FIRESTREAM
+ Driver for the Fujitsu FireStream 155 (MB86697) and
+ FireStream 50 (MB86695) ATM PCI chips.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ firestream.o.
+
+Enable usec resolution timestamps
+CONFIG_ATM_ZATM_EXACT_TS
+ The uPD98401 SAR chip supports a high-resolution timer (approx. 30
+ MHz) that is used for very accurate reception timestamps. Because
+ that timer overflows after 140 seconds, and also to avoid timer
+ drift, time measurements need to be periodically synchronized with
+ the normal system time. Enabling this feature will add some general
+ overhead for timer synchronization and also per-packet overhead for
+ time conversion.
+
+IDT 77201/11 (NICStAR) (ForeRunnerLE)
+CONFIG_ATM_NICSTAR
+ The NICStAR chipset family is used in a large number of ATM NICs for
+ 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE
+ series. Say Y if you have one of those.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ nicstar.o.
+
+Use suni PHY driver (155Mbps)
+CONFIG_ATM_NICSTAR_USE_SUNI
+ Support for the S-UNI and compatible PHYsical layer chips. These are
+ found in most 155Mbps NICStAR based ATM cards, namely in the
+ ForeRunner LE155 cards. This driver provides detection of cable~
+ removal and reinsertion and provides some statistics. This driver
+ doesn't have removal capability when compiled as a module, so if you
+ need that capability don't include S-UNI support (it's not needed to
+ make the card work).
+
+Use IDT77015 PHY driver (25Mbps)
+CONFIG_ATM_NICSTAR_USE_IDT77105
+ Support for the PHYsical layer chip in ForeRunner LE25 cards. In
+ addition to cable removal/reinsertion detection, this driver allows
+ you to control the loopback mode of the chip via a dedicated IOCTL.
+ This driver is required for proper handling of temporary carrier
+ loss, so if you have a 25Mbps NICStAR based ATM card you must say Y.
+
+IDT 77252 (NICStAR II)
+CONFIG_ATM_IDT77252
+ Driver for the IDT 77252 ATM PCI chips.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called idt77252.o
+
+Enable debugging messages
+CONFIG_ATM_IDT77252_DEBUG
+ Somewhat useful debugging messages are available. The choice of
+ messages is controlled by a bitmap. This may be specified as a
+ module argument. See the file <file:drivers/atm/idt77252.h> for
+ the meanings of the bits in the mask.
+
+ When active, these messages can have a significant impact on the
+ speed of the driver, and the size of your syslog files! When
+ inactive, they will have only a modest impact on performance.
+
+Receive ALL cells in raw queue
+CONFIG_ATM_IDT77252_RCV_ALL
+ Enable receiving of all cells on the ATM link, that do not match
+ an open connection in the raw cell queue of the driver. Useful
+ for debugging or special applications only, so the safe answer is N.
+
+Madge Ambassador (Collage PCI 155 Server)
+CONFIG_ATM_AMBASSADOR
+ This is a driver for ATMizer based ATM card produced by Madge
+ Networks Ltd. Say Y (or M to compile as a module named ambassador.o)
+ here if you have one of these cards.
+
+Enable debugging messages
+CONFIG_ATM_AMBASSADOR_DEBUG
+ Somewhat useful debugging messages are available. The choice of
+ messages is controlled by a bitmap. This may be specified as a
+ module argument (kernel command line argument as well?), changed
+ dynamically using an ioctl (not yet) or changed by sending the
+ string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file
+ <file:drivers/atm/ambassador.h> for the meanings of the bits in the
+ mask.
+
+ When active, these messages can have a significant impact on the
+ speed of the driver, and the size of your syslog files! When
+ inactive, they will have only a modest impact on performance.
+
+Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)
+CONFIG_ATM_HORIZON
+ This is a driver for the Horizon chipset ATM adapter cards once
+ produced by Madge Networks Ltd. Say Y (or M to compile as a module
+ named horizon.o) here if you have one of these cards.
+
+Enable debugging messages
+CONFIG_ATM_HORIZON_DEBUG
+ Somewhat useful debugging messages are available. The choice of
+ messages is controlled by a bitmap. This may be specified as a
+ module argument (kernel command line argument as well?), changed
+ dynamically using an ioctl (not yet) or changed by sending the
+ string "Dxxxx" to VCI 1023 (where x is a hex digit). See the file
+ <file:drivers/atm/horizon.h> for the meanings of the bits in the
+ mask.
+
+ When active, these messages can have a significant impact on the
+ speed of the driver, and the size of your syslog files! When
+ inactive, they will have only a modest impact on performance.
+
+Interphase ATM PCI x575/x525/x531
+CONFIG_ATM_IA
+ This is a driver for the Interphase (i)ChipSAR adapter cards
+ which include a variety of variants in term of the size of the
+ control memory (128K-1KVC, 512K-4KVC), the size of the packet
+ memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3,
+ UTP155, UTP25, DS3 and E3). Go to:
+ <http://www.iphase.com/products/ClassSheet.cfm?ClassID=ATM>
+ for more info about the cards. Say Y (or M to compile as a module
+ named iphase.o) here if you have one of these cards.
+
+ See the file <file:Documentation/networking/iphase.txt> for further
+ details.
+
+Enable debugging messages
+CONFIG_ATM_IA_DEBUG
+ Somewhat useful debugging messages are available. The choice of
+ messages is controlled by a bitmap. This may be specified as a
+ module argument (kernel command line argument as well?), changed
+ dynamically using an ioctl (Get the debug utility, iadbg, from
+ <ftp://ftp.iphase.com/pub/atm/pci/>).
+
+ See the file <file:drivers/atm/iphase.h> for the meanings of the
+ bits in the mask.
+
+ When active, these messages can have a significant impact on the
+ speed of the driver, and the size of your syslog files! When
+ inactive, they will have only a modest impact on performance.
+
+Efficient Networks Speedstream 3010
+CONFIG_ATM_LANAI
+ Supports ATM cards based on the Efficient Networks "Lanai"
+ chipset such as the Speedstream 3010 and the ENI-25p. The
+ Speedstream 3060 is currently not supported since we don't
+ have the code to drive the on-board Alcatel DSL chipset (yet).
+
+Linux telephony support
+CONFIG_PHONE
+ Say Y here if you have a telephony card, which for example allows
+ you to use a regular phone for voice-over-IP applications.
+
+ Note: this has nothing to do with modems. You do not need to say Y
+ here in order to be able to use a modem under Linux.
+
+ This support is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ phonedev.o.
+
+Compaq Smart Array support
+CONFIG_BLK_CPQ_CISS_DA
+ This is the driver for Compaq Smart Array 5xxx controllers.
+ Everyone using these boards should say Y here.
+ See <file:Documentation/cciss.txt> for the current list of
+ boards supported by this driver, and for further information
+ on the use of this driver.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ cciss.o
+
+SCSI tape drive support for Smart Array 5xxx
+CONFIG_CISS_SCSI_TAPE
+ When enabled (Y), this option allows SCSI tape drives and SCSI medium
+ changers (tape robots) to be accessed via a Compaq 5xxx array
+ controller. (See Documentation/cciss.txt for more details.)
+
+ "SCSI support" and "SCSI tape support" must also be enabled for this
+ option to work.
+
+ When this option is disabled (N), the SCSI portion of the driver
+ is not compiled.
+
+QuickNet Internet LineJack/PhoneJack support
+CONFIG_PHONE_IXJ
+ Say M if you have a telephony card manufactured by Quicknet
+ Technologies, Inc. These include the Internet PhoneJACK and
+ Internet LineJACK Telephony Cards. You will get a module called
+ ixj.o.
+
+ For the ISA versions of these products, you can configure the
+ cards using the isapnp tools (pnpdump/isapnp) or you can use the
+ isapnp support. Please read <file:Documentation/telephony/ixj.txt>.
+
+ For more information on these cards, see Quicknet's web site at:
+ <http://www.quicknet.net/>.
+
+ If you do not have any Quicknet telephony cards, you can safely
+ say N here.
+
+QuickNet Internet LineJack/PhoneJack PCMCIA support
+CONFIG_PHONE_IXJ_PCMCIA
+ Say Y here to configure in PCMCIA service support for the Quicknet
+ cards manufactured by Quicknet Technologies, Inc. This builds an
+ additional support module for the PCMCIA version of the card.
+
+FORE Systems 200E-series
+CONFIG_ATM_FORE200E_MAYBE
+ This is a driver for the FORE Systems 200E-series ATM adapter
+ cards. It simultaneously supports PCA-200E and SBA-200E models
+ on PCI and SBUS hosts. Say Y (or M to compile as a module
+ named fore_200e.o) here if you have one of these ATM adapters.
+
+ Note that the driver will actually be compiled only if you
+ additionally enable the support for PCA-200E and/or SBA-200E
+ cards.
+
+ See the file <file:Documentation/networking/fore200e.txt> for
+ further details.
+
+Enable PCA-200E card support on PCI-based hosts
+CONFIG_ATM_FORE200E_PCA
+ Say Y here if you want your PCA-200E cards to be probed.
+
+Use default PCA-200E firmware
+CONFIG_ATM_FORE200E_PCA_DEFAULT_FW
+ Use the default PCA-200E firmware data shipped with the driver.
+
+ Normal users do not have to deal with the firmware stuff, so
+ they should say Y here.
+
+Pathname of user-supplied binary firmware
+CONFIG_ATM_FORE200E_PCA_FW
+ This defines the pathname of an alternative PCA-200E binary
+ firmware image supplied by the user. This pathname may be
+ absolute or relative to the drivers/atm directory.
+
+ The driver comes with an adequate firmware image, so normal users do
+ not have to supply an alternative one. They just say Y to "Use
+ default PCA-200E firmware" instead.
+
+Enable SBA-200E card support on SBUS-based hosts
+CONFIG_ATM_FORE200E_SBA
+ Say Y here if you want your SBA-200E cards to be probed.
+
+Use default SBA-200E firmware
+CONFIG_ATM_FORE200E_SBA_DEFAULT_FW
+ Use the default SBA-200E firmware data shipped with the driver.
+
+ Normal users do not have to deal with the firmware stuff, so
+ they should say Y here.
+
+Pathname of user-supplied binary firmware
+CONFIG_ATM_FORE200E_SBA_FW
+ This defines the pathname of an alternative SBA-200E binary
+ firmware image supplied by the user. This pathname may be
+ absolute or relative to the drivers/atm directory.
+
+ The driver comes with an adequate firmware image, so normal users do
+ not have to supply an alternative one. They just say Y to "Use
+ default SBA-200E firmware", above.
+
+Maximum number of tx retries
+CONFIG_ATM_FORE200E_TX_RETRY
+ Specifies the number of times the driver attempts to transmit
+ a message before giving up, if the transmit queue of the ATM card
+ is transiently saturated.
+
+ Saturation of the transmit queue may occur only under extreme
+ conditions, e.g. when a fast host continuously submits very small
+ frames (<64 bytes) or raw AAL0 cells (48 bytes) to the ATM adapter.
+
+ Note that under common conditions, it is unlikely that you encounter
+ a saturation of the transmit queue, so the retry mechanism never
+ comes into play.
+
+Debugging level (0-3)
+CONFIG_ATM_FORE200E_DEBUG
+ Specifies the level of debugging messages issued by the driver.
+ The verbosity of the driver increases with the value of this
+ parameter.
+
+ When active, these messages can have a significant impact on
+ the performances of the driver, and the size of your syslog files!
+ Keep the debugging level to 0 during normal operations.
+
+PPP over ATM
+CONFIG_PPPOATM
+ Support PPP (Point to Point Protocol) encapsulated in ATM frames.
+ This implementation does not yet comply with section 8 of RFC2364,
+ which can lead to bad results idf the ATM peer loses state and
+ changes its encapsulation unilaterally.
+
+Fusion MPT device support
+CONFIG_FUSION
+ LSI Logic Fusion(TM) Message Passing Technology (MPT) device support
+ provides high performance SCSI host initiator, and LAN [1] interface
+ services to a host system. The Fusion architecture is capable of
+ duplexing these protocols on high-speed Fibre Channel
+ (up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320)
+ physical medium.
+
+ [1] LAN is not supported on parallel SCSI medium.
+
+ These drivers require a Fusion MPT compatible PCI adapter installed
+ in the host system. MPT adapters contain specialized I/O processors
+ to handle I/O workload, and more importantly to offload this work
+ from the host CPU(s).
+
+ If you have Fusion MPT hardware and want to use it, you can say
+ Y or M here to add MPT (base + ScsiHost) drivers.
+ <Y> = build lib (fusion.o), and link [static] into the kernel [2]
+ proper
+ <M> = compiled as [dynamic] modules [3] named: (mptbase.o,
+ mptscsih.o)
+
+ [2] In order enable capability to boot the linux kernel
+ natively from a Fusion MPT target device, you MUST
+ answer Y here! (currently requires CONFIG_BLK_DEV_SD)
+ [3] This support is also available as a module ( = code
+ which can be inserted in and removed from the running
+ kernel whenever you want). If you want to compile as
+ modules, say M here and read
+ <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+
+ If you say Y or M here you will get a choice of these
+ additional protocol and support module options: Module Name:
+ <M> Enhanced SCSI error reporting (isense.o)
+ <M> Fusion MPT misc device (ioctl) driver (mptctl.o)
+ <M> Fusion MPT LAN driver (mptlan.o)
+
+ ---
+ Fusion MPT is trademark of LSI Logic Corporation, and its
+ architecture is based on LSI Logic's Message Passing Interface (MPI)
+ specification.
+
+Fusion MPT enhanced SCSI error reporting [optional] module
+CONFIG_FUSION_ISENSE
+ The isense module (roughly stands for Interpret SENSE data) is
+ completely optional. It simply provides extra English readable
+ strings in SCSI Error Report(s) that might be generated from the
+ Fusion MPT SCSI Host driver, for example when a target device
+ returns a SCSI check condition on a I/O. Without this module
+ loaded you might see:
+
+ SCSI Error Report =-=-= (ioc0,scsi5:0)
+ SCSI_Status=02h (CHECK_CONDITION)
+ Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00
+ SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
+ SenseKey=2h (NOT READY); FRU=02h
+ ASC/ASCQ=29h/00h
+
+ Where otherwise, if this module had been loaded, you would see:
+
+ SCSI Error Report =-=-= (ioc0,scsi5:0)
+ SCSI_Status=02h (CHECK_CONDITION)
+ Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - "WRITE(10)"
+ SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
+ SenseKey=2h (NOT READY); FRU=02h
+ ASC/ASCQ=29h/00h "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"
+
+ Say M for "Enhanced SCSI error reporting" to compile this optional module,
+ creating a driver named: isense.o.
+
+ NOTE: Support for building this feature into the kernel is not
+ available, due to kernel size considerations.
+
+Fusion MPT misc device (ioctl) driver [optional] module
+CONFIG_FUSION_CTL
+ The Fusion MPT misc device driver provides specialized control
+ of MPT adapters via system ioctl calls. Use of ioctl calls to
+ the MPT driver requires that you create and use a misc device
+ node ala:
+ mknod /dev/mptctl c 10 240
+
+ One use of this ioctl interface is to perform an upgrade (reflash)
+ of the MPT adapter firmware. Refer to readme file(s) distributed
+ with the Fusion MPT linux driver for additional details.
+
+ If enabled by saying M to this, a driver named: mptctl.o
+ will be compiled.
+
+ If unsure whether you really want or need this, say N.
+
+Fusion MPT LAN driver [optional]
+CONFIG_FUSION_LAN
+ This module supports LAN IP traffic over Fibre Channel port(s)
+ on Fusion MPT compatible hardware (LSIFC9xx chips).
+ The physical interface used is defined in RFC 2625.
+ Please refer to that document for details.
+
+ Installing this driver requires the knowledge to configure and
+ activate a new network interface, "fc0", using standard Linux tools.
+
+ If enabled by saying M to this, a driver named: mptlan.o
+ will be compiled.
+
+ If unsure whether you really want or need this, say N.
+
+ NOTES: This feature is NOT available nor supported for linux-2.2.x
+ kernels. You must be building a linux-2.3.x or linux-2.4.x kernel
+ in order to configure this option.
+ Support for building this feature into the linux kernel is not
+ yet available.
+
+SCSI support
+CONFIG_SCSI
+ If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
+ any other SCSI device under Linux, say Y and make sure that you know
+ the name of your SCSI host adapter (the card inside your computer
+ that "speaks" the SCSI protocol, also called SCSI controller),
+ because you will be asked for it.
+
+ You also need to say Y here if you want support for the parallel
+ port version of the 100 MB IOMEGA ZIP drive.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called scsi_mod.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>. However, do not compile this as a
+ module if your root file system (the one containing the directory /)
+ is located on a SCSI device.
+
+SCSI disk support
+CONFIG_BLK_DEV_SD
+ If you want to use a SCSI hard disk or the SCSI or parallel port
+ version of the IOMEGA ZIP drive under Linux, say Y and read the
+ SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. This is NOT for SCSI
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called sd_mod.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>. Do not compile this driver as a
+ module if your root file system (the one containing the directory /)
+ is located on a SCSI disk. In this case, do not compile the driver
+ for your SCSI host adapter (below) as a module either.
+
+Maximum number of SCSI disks that can be loaded as modules
+CONFIG_SD_EXTRA_DEVS
+ This controls the amount of additional space allocated in tables for
+ drivers that are loaded as modules after the kernel is booted. In
+ the event that the SCSI core itself was loaded as a module, this
+ value is the number of additional disks that can be loaded after the
+ first host driver is loaded.
+
+ Admittedly this isn't pretty, but there are tons of race conditions
+ involved with resizing the internal arrays on the fly. Someday this
+ flag will go away, and everything will work automatically.
+
+ If you don't understand what's going on, go with the default.
+
+Maximum number of SCSI tapes that can be loaded as modules
+CONFIG_ST_EXTRA_DEVS
+ This controls the amount of additional space allocated in tables for
+ drivers that are loaded as modules after the kernel is booted. In
+ the event that the SCSI core itself was loaded as a module, this
+ value is the number of additional tapes that can be loaded after the
+ first host driver is loaded.
+
+ Admittedly this isn't pretty, but there are tons of race conditions
+ involved with resizing the internal arrays on the fly. Someday this
+ flag will go away, and everything will work automatically.
+
+ If you don't understand what's going on, go with the default.
+
+SCSI tape support
+CONFIG_CHR_DEV_ST
+ If you want to use a SCSI tape drive under Linux, say Y and read the
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, and
+ <file:drivers/scsi/README.st> in the kernel source. This is NOT for
+ SCSI CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called st.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>.
+
+OnStream SC-x0 SCSI tape support
+CONFIG_CHR_DEV_OSST
+ The OnStream SC-x0 SCSI tape drives can not be driven by the
+ standard st driver, but instead need this special osst driver and
+ use the /dev/osstX char device nodes (major 206). Via usb-storage
+ and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives
+ as well. Note that there is also a second generation of OnStream
+ tape drives (ADR-x0) that supports the standard SCSI-2 commands for
+ tapes (QIC-157) and can be driven by the standard driver st.
+ For more information, you may have a look at the SCSI-HOWTO
+ <http://www.tldp.org/docs.html#howto> and
+ <file:drivers/scsi/README.osst> in the kernel source.
+ More info on the OnStream driver may be found on
+ <http://linux1.onstream.nl/test/>
+ Please also have a look at the standard st docu, as most of it
+ applies to osst as well.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called osst.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>.
+
+SCSI CD-ROM support
+CONFIG_BLK_DEV_SR
+ If you want to use a SCSI CD-ROM under Linux, say Y and read the
+ SCSI-HOWTO and the CD-ROM-HOWTO at
+ <http://www.tldp.org/docs.html#howto>. Also make sure to say Y
+ or M to "ISO 9660 CD-ROM file system support" later.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called sr_mod.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>.
+
+Maximum number of CD-ROM devices that can be loaded as modules
+CONFIG_SR_EXTRA_DEVS
+ This controls the amount of additional space allocated in tables for
+ drivers that are loaded as modules after the kernel is booted. In
+ the event that the SCSI core itself was loaded as a module, this
+ value is the number of additional CD-ROMs that can be loaded after
+ the first host driver is loaded.
+
+ Admittedly this isn't pretty, but there are tons of race conditions
+ involved with resizing the internal arrays on the fly. Someday this
+ flag will go away, and everything will work automatically.
+
+ If you don't understand what's going on, go with the default.
+
+Enable vendor-specific extensions (for SCSI CD-ROM)
+CONFIG_BLK_DEV_SR_VENDOR
+ This enables the usage of vendor specific SCSI commands. This is
+ required to support multisession CDs with old NEC/TOSHIBA cdrom
+ drives (and HP Writers). If you have such a drive and get the first
+ session only, try saying Y here; everybody else says N.
+
+SCSI generic support
+CONFIG_CHR_DEV_SG
+ If you want to use SCSI scanners, synthesizers or CD-writers or just
+ about anything having "SCSI" in its name other than hard disks,
+ CD-ROMs or tapes, say Y here. These won't be supported by the kernel
+ directly, so you need some additional software which knows how to
+ talk to these devices using the SCSI protocol:
+
+ For scanners, look at SANE (<http://www.mostang.com/sane/>). For CD
+ writer software look at Cdrtools
+ (<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/cdrecord.html>)
+ and for burning a "disk at once": CDRDAO
+ (<http://cdrdao.sourceforge.net/>). Cdparanoia is a high
+ quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
+ For other devices, it's possible that you'll have to write the
+ driver software yourself. Please read the file
+ <file:Documentation/scsi-generic.txt> for more information.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>. The module will be called sg.o. If unsure,
+ say N.
+
+Probe all LUNs on each SCSI device
+CONFIG_SCSI_MULTI_LUN
+ If you have a SCSI device that supports more than one LUN (Logical
+ Unit Number), e.g. a CD jukebox, and only one LUN is detected, you
+ can say Y here to force the SCSI driver to probe for multiple LUNs.
+ A SCSI device with multiple LUNs acts logically like multiple SCSI
+ devices. The vast majority of SCSI devices have only one LUN, and
+ so most people can say N here and should in fact do so, because it
+ is safer.
+
+Verbose SCSI error reporting (kernel size +=12K)
+CONFIG_SCSI_CONSTANTS
+ The error messages regarding your SCSI hardware will be easier to
+ understand if you say Y here; it will enlarge your kernel by about
+ 12 KB. If in doubt, say Y.
+
+SCSI logging facility
+CONFIG_SCSI_LOGGING
+ This turns on a logging facility that can be used to debug a number
+ of SCSI related problems.
+
+ If you say Y here, no logging output will appear by default, but you
+ can enable logging by saying Y to "/proc file system support" and
+ "Sysctl support" below and executing the command
+
+ echo "scsi log token [level]" > /proc/scsi/scsi
+
+ at boot time after the /proc file system has been mounted.
+
+ There are a number of things that can be used for 'token' (you can
+ find them in the source: <file:drivers/scsi/scsi.c>), and this
+ allows you to select the types of information you want, and the
+ level allows you to select the level of verbosity.
+
+ If you say N here, it may be harder to track down some types of SCSI
+ problems. If you say Y here your kernel will be somewhat larger, but
+ there should be no noticeable performance impact as long as you have
+ logging turned off.
+
+SGI WD93C93 SCSI Driver
+CONFIG_SCSI_SGIWD93
+ Say Y here to support the on-board WD93C93 SCSI controller found (a)
+ on the Indigo2 and other MIPS-based SGI machines, and (b) on ARCS
+ ARM-based machines.
+
+DEC NCR53C94 SCSI Driver
+CONFIG_SCSI_DECNCR
+ Say Y here to support the NCR53C94 SCSI controller chips on IOASIC
+ based TURBOchannel DECstations and TURBOchannel PMAZ-A cards.
+
+AdvanSys SCSI support
+CONFIG_SCSI_ADVANSYS
+ This is a driver for all SCSI host adapters manufactured by
+ AdvanSys. It is documented in the kernel source in
+ <file:drivers/scsi/advansys.c>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ advansys.o.
+
+Adaptec AHA152X/2825 support
+CONFIG_SCSI_AHA152X
+ This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825
+ SCSI host adapters. It also works for the AVA-1505, but the IRQ etc.
+ must be manually specified in this case.
+
+ It is explained in section 3.3 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. You might also want to
+ read the file <file:drivers/scsi/README.aha152x>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aha152x.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Adaptec AHA1542 support
+CONFIG_SCSI_AHA1542
+ This is support for a SCSI host adapter. It is explained in section
+ 3.4 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that Trantor was
+ purchased by Adaptec, and some former Trantor products are being
+ sold under the Adaptec name. If it doesn't work out of the box, you
+ may have to change some settings in <file:drivers/scsi/aha1542.h>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called aha1542.o.
+
+Adaptec AHA1740 support
+CONFIG_SCSI_AHA1740
+ This is support for a SCSI host adapter. It is explained in section
+ 3.5 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. If it doesn't work out
+ of the box, you may have to change some settings in
+ <file:drivers/scsi/aha1740.h>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aha1740.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Adaptec AIC7xxx support
+CONFIG_SCSI_AIC7XXX
+ This driver supports all of Adaptec's PCI based SCSI controllers
+ (not the hardware RAID controllers though) as well as the aic7770
+ based EISA and VLB SCSI controllers (the 274x and 284x series).
+ This is an Adaptec sponsored driver written by Justin Gibbs. It is
+ intended to replace the previous aic7xxx driver maintained by Doug
+ Ledford since Doug is no longer maintaining that driver.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called aic7xxx.o.
+
+Adaptec I2O RAID support
+CONFIG_SCSI_DPT_I2O
+ This driver supports all of Adaptec's I2O based RAID controllers as
+ well as the DPT SmartRaid V cards. This is an Adaptec maintained
+ driver by Deanna Bonds. See <file:drivers/scsi/README.dpti>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ dpt_i2o.o.
+
+Default number of TCQ commands per device
+CONFIG_AIC7XXX_CMDS_PER_DEVICE
+ Specify the number of commands you would like to allocate per SCSI
+ device when Tagged Command Queueing (TCQ) is enabled on that device.
+
+ This is an upper bound value for the number of tagged transactions
+ to be used for any device. The aic7xxx driver will automatically
+ vary this number based on device behaviour. For devices with a
+ fixed maximum, the driver will eventually lock to this maximum
+ and display a console message indicating this value.
+
+ Note: Unless you experience some type of device failure, the default
+ value, no enforced limit, should work for you.
+
+ Default: 253
+
+Delay in seconds after SCSI bus reset
+CONFIG_AIC7XXX_RESET_DELAY_MS
+ The number of milliseconds to delay after an initial bus reset.
+ The bus settle delay following all error recovery actions is
+ dictated by the SCSI layer and is not affected by this value.
+
+ Default: 15000 (15 seconds)
+
+Build Adapter Firmware with Kernel Build
+CONFIG_AIC7XXX_BUILD_FIRMWARE
+ This option should only be enabled if you are modifying the firmware
+ source to the aic7xxx driver and wish to have the generated firmware
+ include files updated during a normal kernel build. The assembler
+ for the firmware requires lex and yacc or their equivalents, as well
+ as the db v1 library. You may have to install additional packages
+ or modify the assembler make file or the files it includes if your
+ build environment is different than that of the author.
+
+Old Adaptec AIC7xxx support
+CONFIG_SCSI_AIC7XXX_OLD
+ WARNING This driver is an older aic7xxx driver and is no longer
+ under active development. Adaptec, Inc. is writing a new driver to
+ take the place of this one, and it is recommended that whenever
+ possible, people should use the new Adaptec written driver instead
+ of this one. This driver will eventually be phased out entirely.
+
+ This is support for the various aic7xxx based Adaptec SCSI
+ controllers. These include the 274x EISA cards; 284x VLB cards;
+ 2902, 2910, 293x, 294x, 394x, 3985 and several other PCI and
+ motherboard based SCSI controllers from Adaptec. It does not support
+ the AAA-13x RAID controllers from Adaptec, nor will it likely ever
+ support them. It does not support the 2920 cards from Adaptec that
+ use the Future Domain SCSI controller chip. For those cards, you
+ need the "Future Domain 16xx SCSI support" driver.
+
+ In general, if the controller is based on an Adaptec SCSI controller
+ chip from the aic777x series or the aic78xx series, this driver
+ should work. The only exception is the 7810 which is specifically
+ not supported (that's the RAID controller chip on the AAA-13x
+ cards).
+
+ Note that the AHA2920 SCSI host adapter is *not* supported by this
+ driver; choose "Future Domain 16xx SCSI support" instead if you have
+ one of those.
+
+ Information on the configuration options for this controller can be
+ found by checking the help file for each of the available
+ configuration options. You should read
+ <file:drivers/scsi/aic7xxx_old/README.aic7xxx> at a minimum before
+ contacting the maintainer with any questions. The SCSI-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>, can also
+ be of great help.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called aic7xxx_old.o.
+
+Enable tagged command queueing (TCQ) by default
+CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT
+ This option causes the aic7xxx driver to attempt to use Tagged
+ Command Queueing (TCQ) on all devices that claim to support it.
+
+ TCQ is a feature of SCSI-2 which improves performance: the host
+ adapter can send several SCSI commands to a device's queue even if
+ previous commands haven't finished yet. Because the device is
+ intelligent, it can optimize its operations (like head positioning)
+ based on its own request queue. Not all devices implement this
+ correctly.
+
+ If you say Y here, you can still turn off TCQ on troublesome devices
+ with the use of the tag_info boot parameter. See the file
+ <file:drivers/scsi/README.aic7xxx> for more information on that and
+ other aic7xxx setup commands. If this option is turned off, you may
+ still enable TCQ on known good devices by use of the tag_info boot
+ parameter.
+
+ If you are unsure about your devices then it is safest to say N
+ here.
+
+ However, TCQ can increase performance on some hard drives by as much
+ as 50% or more, so it is recommended that if you say N here, you
+ should at least read the <file:drivers/scsi/README.aic7xxx> file so
+ you will know how to enable this option manually should your drives
+ prove to be safe in regards to TCQ.
+
+ Conversely, certain drives are known to lock up or cause bus resets
+ when TCQ is enabled on them. If you have a Western Digital
+ Enterprise SCSI drive for instance, then don't even bother to enable
+ TCQ on it as the drive will become unreliable, and it will actually
+ reduce performance.
+
+Default number of TCQ commands per device
+CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE
+ Specify the number of commands you would like to allocate per SCSI
+ device when Tagged Command Queueing (TCQ) is enabled on that device.
+
+ Reasonable figures are in the range of 8 to 24 commands per device,
+ but depending on hardware could be increased or decreased from that
+ figure. If the number is too high for any particular device, the
+ driver will automatically compensate usually after only 10 minutes
+ of uptime. It will not hinder performance if some of your devices
+ eventually have their command depth reduced, but is a waste of
+ memory if all of your devices end up reducing this number down to a
+ more reasonable figure.
+
+ NOTE: Certain very broken drives are known to lock up when given
+ more commands than they like to deal with. Quantum Fireball drives
+ are the most common in this category. For the Quantum Fireball
+ drives it is suggested to use no more than 8 commands per device.
+
+ Default: 8
+
+Collect statistics to report in /proc
+CONFIG_AIC7XXX_OLD_PROC_STATS
+ This option tells the driver to keep track of how many commands have
+ been sent to each particular device and report that information to
+ the user via the /proc/scsi/aic7xxx/n file, where n is the number of
+ the aic7xxx controller you want the information on. This adds a
+ small amount of overhead to each and every SCSI command the aic7xxx
+ driver handles, so if you aren't really interested in this
+ information, it is best to leave it disabled. This will only work if
+ you also say Y to "/proc file system support", below.
+
+ If unsure, say N.
+
+IBM ServeRAID support
+CONFIG_SCSI_IPS
+ This is support for the IBM ServeRAID hardware RAID controllers.
+ See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html>
+ for more information. If this driver does not work correctly
+ without modification please contact the author by email at
+ ipslinux@us.ibm.com.
+
+ You can build this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ but only a single instance may be loaded. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ The module will be called ips.o.
+
+BusLogic SCSI support
+CONFIG_SCSI_BUSLOGIC
+ This is support for BusLogic MultiMaster and FlashPoint SCSI Host
+ Adapters. Consult the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, and the files
+ <file:drivers/scsi/README.BusLogic> and
+ <file:drivers/scsi/README.FlashPoint> for more information. If this
+ driver does not work correctly without modification, please contact
+ the author, Leonard N. Zubkoff, by email to lnz@dandelion.com.
+
+ You can also build this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ but only a single instance may be loaded. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ The module will be called BusLogic.o.
+
+Omit BusLogic SCSI FlashPoint support
+CONFIG_SCSI_OMIT_FLASHPOINT
+ This option allows you to omit the FlashPoint support from the
+ BusLogic SCSI driver. The FlashPoint SCCB Manager code is
+ substantial, so users of MultiMaster Host Adapters may wish to omit
+ it.
+
+Compaq Fibre Channel 64-bit/66Mhz HBA support
+CONFIG_SCSI_CPQFCTS
+ Say Y here to compile in support for the Compaq StorageWorks Fibre
+ Channel 64-bit/66Mhz Host Bus Adapter.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called cpqfc.o.
+
+DMX3191D SCSI support
+CONFIG_SCSI_DMX3191D
+ This is support for Domex DMX3191D SCSI Host Adapters.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dmx3191d.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+DTC3180/3280 SCSI support
+CONFIG_SCSI_DTC3280
+ This is support for DTC 3180/3280 SCSI Host Adapters. Please read
+ the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, and the file
+ <file:drivers/scsi/README.dtc3x80>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dtc.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support
+CONFIG_SCSI_EATA_DMA
+ This is support for the EATA-DMA protocol compliant SCSI Host
+ Adapters like the SmartCache III/IV, SmartRAID controller families
+ and the DPT PM2011B and PM2012B controllers.
+
+ Note that this driver is obsolete; if you have one of the above
+ SCSI Host Adapters, you should normally say N here and Y to "EATA
+ ISA/EISA/PCI support", below. Please read the SCSI-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called eata_dma.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+EATA-PIO (old DPT PM2001, PM2012A) support
+CONFIG_SCSI_EATA_PIO
+ This driver supports all EATA-PIO protocol compliant SCSI Host
+ Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant
+ host adapters could also use this driver but are discouraged from
+ doing so, since this driver only supports hard disks and lacks
+ numerous features. You might want to have a look at the SCSI-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called eata_pio.o.
+
+UltraStor 14F/34F support
+CONFIG_SCSI_U14_34F
+ This is support for the UltraStor 14F and 34F SCSI-2 host adapters.
+ The source at <file:drivers/scsi/u14-34f.c> contains some
+ information about this hardware. If the driver doesn't work out of
+ the box, you may have to change some settings in
+ <file: drivers/scsi/u14-34f.c>. Read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that there is also
+ another driver for the same hardware: "UltraStor SCSI support",
+ below. You should say Y to both only if you want 24F support as
+ well.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called u14-34f.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+enable elevator sorting
+CONFIG_SCSI_U14_34F_LINKED_COMMANDS
+ This option enables elevator sorting for all probed SCSI disks and
+ CD-ROMs. It definitely reduces the average seek distance when doing
+ random seeks, but this does not necessarily result in a noticeable
+ performance improvement: your mileage may vary...
+
+ The safe answer is N.
+
+maximum number of queued commands
+CONFIG_SCSI_U14_34F_MAX_TAGS
+ This specifies how many SCSI commands can be maximally queued for
+ each probed SCSI device. You should reduce the default value of 8
+ only if you have disks with buggy or limited tagged command support.
+ Minimum is 2 and maximum is 14. This value is also the window size
+ used by the elevator sorting option above. The effective value used
+ by the driver for each probed SCSI device is reported at boot time.
+
+Future Domain 16xx SCSI/AHA-2920A support
+CONFIG_SCSI_FUTURE_DOMAIN
+ This is support for Future Domain's 16-bit SCSI host adapters
+ (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and
+ other adapters based on the Future Domain chipsets (Quantum
+ ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board).
+ It is explained in section 3.7 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip
+ and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI
+ controller support"). This Future Domain driver works with the older
+ Adaptec AHA-2920A boards with a Future Domain chip on them.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called fdomain.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Future Domain MCS-600/700 SCSI support
+CONFIG_SCSI_FD_MCS
+ This is support for Future Domain MCS 600/700 MCA SCSI adapters.
+ Some PS/2 computers are equipped with IBM Fast SCSI Adapter/A which
+ is identical to the MCS 700 and hence also supported by this driver.
+ This driver also supports the Reply SB16/SCSI card (the SCSI part).
+ It supports multiple adapters in the same system.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called fd_mcs.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Generic NCR5380/53c400 SCSI support
+CONFIG_SCSI_GENERIC_NCR5380
+ This is the generic NCR family of SCSI controllers, not to be
+ confused with the NCR 53c7 or 8xx controllers. It is explained in
+ section 3.8 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. If it doesn't work out
+ of the box, you may have to change some settings in
+ <file:drivers/scsi/g_NCR5380.h>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called g_NCR5380.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Enable NCR53c400 extensions
+CONFIG_SCSI_GENERIC_NCR53C400
+ This enables certain optimizations for the NCR53c400 SCSI cards.
+ You might as well try it out. Note that this driver will only probe
+ for the Trantor T130B in its default configuration; you might have
+ to pass a command line option to the kernel at boot time if it does
+ not detect your card. See the file
+ <file:drivers/scsi/README.g_NCR5380> for details.
+
+# Choice: ncr5380
+NCR5380/53c400 mapping method (use Port for T130B)
+CONFIG_SCSI_G_NCR5380_PORT
+ The NCR5380 and NCR53c400 SCSI controllers come in two varieties:
+ port or memory mapped. You should know what you have. The most
+ common card, Trantor T130B, uses port mapped mode.
+
+NCR Dual 700 MCA SCSI support
+CONFIG_SCSI_NCR_D700
+ This is a driver for the MicroChannel Dual 700 card produced by
+ NCR and commonly used in 345x/35xx/4100 class machines. It always
+ tries to negotiate sync and uses tag command queueing.
+
+ Unless you have an NCR manufactured machine, the chances are that
+ you do not have this SCSI card, so say N.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called NCR_D700.o.
+
+HP LASI SCSI support for 53c700/710
+CONFIG_SCSI_LASI700
+ This is a driver for the lasi baseboard in some parisc machines
+ which is based on the 53c700 chip. Will also support LASI subsystems
+ based on the 710 chip using 700 emulation mode.
+
+ Unless you know you have a 53c700 or 53c710 based lasi, say N here
+
+NCR53c7,8xx SCSI support
+CONFIG_SCSI_NCR53C7xx
+ This is a driver for the 53c7 and 8xx NCR family of SCSI
+ controllers, not to be confused with the NCR 5380 controllers. It
+ is explained in section 3.8 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. If it doesn't work out
+ of the box, you may have to change some settings in
+ <file:drivers/scsi/53c7,8xx.h>. Please read
+ <file:drivers/scsi/README.ncr53c7xx> for the available boot time
+ command line options.
+
+ Note: there is another driver for the 53c8xx family of controllers
+ ("NCR53C8XX SCSI support" below). If you want to use them both, you
+ need to say M to both and build them as modules, but only one may be
+ active at a time. If you have a 53c8xx board, it's better to use the
+ other driver.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 53c7,8xx.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Always negotiate synchronous transfers
+CONFIG_SCSI_NCR53C7xx_sync
+ In general, this is good; however, it is a bit dangerous since there
+ are some broken SCSI devices out there. Take your chances. Safe bet
+ is N.
+
+Allow FAST-SCSI [10MHz]
+CONFIG_SCSI_NCR53C7xx_FAST
+ This will enable 10MHz FAST-SCSI transfers with your host
+ adapter. Some systems have problems with that speed, so it's safest
+ to say N here.
+
+Allow DISCONNECT
+CONFIG_SCSI_NCR53C7xx_DISCONNECT
+ This enables the disconnect/reconnect feature of the NCR SCSI
+ controller. When you say Y here, a slow SCSI device will not lock
+ the SCSI bus while processing a request, allowing simultaneous use
+ of e.g. a SCSI hard disk and SCSI tape or CD-ROM drive, and
+ providing much better performance when using slow and fast SCSI
+ devices at the same time. Some devices, however, do not operate
+ properly with this option enabled, and will cause your SCSI system
+ to hang, which might cause a system crash. The safe answer
+ therefore is to say N.
+
+SYM53C8XX Version 2 SCSI support
+CONFIG_SCSI_SYM53C8XX_2
+ This driver supports the whole NCR53C8XX/SYM53C8XX family of
+ PCI-SCSI controllers. It also supports the subset of LSI53C10XX
+ Ultra-160 controllers that are based on the SYM53C8XX SCRIPTS
+ language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI
+ controllers.
+
+ If your system has problems using this new major version of the
+ SYM53C8XX driver, you may switch back to driver version 1.
+
+ Please read <file:drivers/scsi/sym53c8xx_2/Documentation.txt> for more
+ information.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called sym53c8xx.o.
+
+PCI DMA addressing mode
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
+ This option only applies to PCI-SCSI chip that are PCI DAC capable
+ (875A, 895A, 896, 1010-33, 1010-66, 1000).
+
+ When set to 0, only PCI 32 bit DMA addressing (SAC) will be performed.
+ When set to 1, 40 bit DMA addressing (with upper 24 bits of address
+ set to zero) is supported. The addressable range is here 1 TB.
+ When set to 2, full 64 bits of address for DMA are supported, but only
+ 16 segments of 4 GB can be addressed. The addressable range is so
+ limited to 64 GB.
+
+ The safest value is 0 (32 bit DMA addressing) that is guessed to still
+ fit most of real machines.
+
+ The preferred value 1 (40 bit DMA addressing) should make happy
+ properly engineered PCI DAC capable host bridges. You may configure
+ this option for Intel platforms with more than 4 GB of memory.
+
+ The still experimental value 2 (64 bit DMA addressing with 16 x 4GB
+ segments limitation) can be used on systems that require PCI address
+ bits past bit 39 to be set for the addressing of memory using PCI
+ DAC cycles.
+
+use normal IO
+CONFIG_SCSI_SYM53C8XX_IOMAPPED
+ If you say Y here, the driver will preferently use normal IO rather than
+ memory mapped IO.
+
+maximum number of queued commands
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS
+ This option allows you to specify the maximum number of commands
+ that can be queued to any device, when tagged command queuing is
+ possible. The driver supports up to 256 queued commands per device.
+ This value is used as a compiled-in hard limit.
+
+default tagged command queue depth
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS
+ This is the default value of the command queue depth the driver will
+ announce to the generic SCSI layer for devices that support tagged
+ command queueing. This value can be changed from the boot command line.
+ This is a soft limit that cannot exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS.
+
+NCR53C8XX SCSI support
+CONFIG_SCSI_NCR53C8XX
+ This is the BSD ncr driver adapted to Linux for the NCR53C8XX family
+ of PCI-SCSI controllers. This driver supports parity checking,
+ tagged command queuing and fast synchronous data transfers up to 80
+ MB/s with wide FAST-40 LVD devices and controllers.
+
+ Recent versions of the 53C8XX chips are better supported by the
+ option "SYM53C8XX SCSI support", below.
+
+ Note: there is yet another driver for the 53c8xx family of
+ controllers ("NCR53c7,8xx SCSI support" above). If you want to use
+ them both, you need to say M to both and build them as modules, but
+ only one may be active at a time. If you have a 53c8xx board, you
+ probably do not want to use the "NCR53c7,8xx SCSI support".
+
+ Please read <file:drivers/scsi/README.ncr53c8xx> for more
+ information.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ncr53c8xx.o.
+
+SYM53C8XX Version 1 SCSI support
+CONFIG_SCSI_SYM53C8XX
+ This driver supports all the features of recent 53C8XX chips (used
+ in PCI SCSI controllers), notably the hardware phase mismatch
+ feature of the SYM53C896.
+
+ Older versions of the 53C8XX chips are not supported by this
+ driver. If your system uses either a 810 rev. < 16, a 815, or a 825
+ rev. < 16 PCI SCSI processor, you must use the generic NCR53C8XX
+ driver ("NCR53C8XX SCSI support" above) or configure both the
+ NCR53C8XX and this SYM53C8XX drivers either as module or linked to
+ the kernel image.
+
+ When both drivers are linked into the kernel, the SYM53C8XX driver
+ is called first at initialization and you can use the 'excl=ioaddr'
+ driver boot option to exclude attachment of adapters by the
+ SYM53C8XX driver. For example, entering
+ 'sym53c8xx=excl:0xb400,excl=0xc000' at the lilo prompt prevents
+ adapters at io address 0xb400 and 0xc000 from being attached by the
+ SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them.
+ The 'excl' option is also supported by the NCR53C8XX driver.
+
+ Please read <file:drivers/scsi/README.ncr53c8xx> for more
+ information.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called sym53c8xx.o.
+
+Synchronous transfer frequency in MHz
+CONFIG_SCSI_NCR53C8XX_SYNC
+ The SCSI Parallel Interface-2 Standard defines 5 classes of transfer
+ rates: FAST-5, FAST-10, FAST-20, FAST-40 and FAST-80. The numbers
+ are respectively the maximum data transfer rates in mega-transfers
+ per second for each class. For example, a FAST-20 Wide 16 device is
+ able to transfer data at 20 million 16 bit packets per second for a
+ total rate of 40 MB/s.
+
+ You may specify 0 if you want to only use asynchronous data
+ transfers. This is the safest and slowest option. Otherwise, specify
+ a value between 5 and 80, depending on the capability of your SCSI
+ controller. The higher the number, the faster the data transfer.
+ Note that 80 should normally be ok since the driver decreases the
+ value automatically according to the controller's capabilities.
+
+ Your answer to this question is ignored for controllers with NVRAM,
+ since the driver will get this information from the user set-up. It
+ also can be overridden using a boot setup option, as follows
+ (example): 'ncr53c8xx=sync:12' will allow the driver to negotiate
+ for FAST-20 synchronous data transfer (20 mega-transfers per
+ second).
+
+ The normal answer therefore is not to go with the default but to
+ select the maximum value 80 allowing the driver to use the maximum
+ value supported by each controller. If this causes problems with
+ your SCSI devices, you should come back and decrease the value.
+
+ There is no safe option other than using good cabling, right
+ terminations and SCSI conformant devices.
+
+Use normal IO
+CONFIG_SCSI_NCR53C8XX_IOMAPPED
+ If you say Y here, the driver will use normal IO, as opposed to
+ memory mapped IO. Memory mapped IO has less latency than normal IO
+ and works for most Intel-based hardware. Under Linux/Alpha only
+ normal IO is currently supported by the driver and so, this option
+ has no effect on those systems.
+
+ The normal answer therefore is N; try Y only if you encounter SCSI
+ related problems.
+
+Not allow targets to disconnect
+CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
+ This option is only provided for safety if you suspect some SCSI
+ device of yours to not support properly the target-disconnect
+ feature. In that case, you would say Y here. In general however, to
+ not allow targets to disconnect is not reasonable if there is more
+ than 1 device on a SCSI bus. The normal answer therefore is N.
+
+Default tagged command queue depth
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+ "Tagged command queuing" is a feature of SCSI-2 which improves
+ performance: the host adapter can send several SCSI commands to a
+ device's queue even if previous commands haven't finished yet.
+ Because the device is intelligent, it can optimize its operations
+ (like head positioning) based on its own request queue. Some SCSI
+ devices don't implement this properly; if you want to disable this
+ feature, enter 0 or 1 here (it doesn't matter which).
+
+ The default value is 8 and should be supported by most hard disks.
+ This value can be overridden from the boot command line using the
+ 'tags' option as follows (example):
+ 'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to
+ 4, set queue depth to 16 for target 2 and target 3 on controller 0
+ and set queue depth to 10 for target 0 / lun 2 on controller 1.
+
+ The normal answer therefore is to go with the default 8 and to use
+ a boot command line option for devices that need to use a different
+ command queue depth.
+
+ There is no safe option other than using good SCSI devices.
+
+Maximum number of queued commands
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+ This option allows you to specify the maximum number of commands
+ that can be queued to any device, when tagged command queuing is
+ possible. The default value is 32. Minimum is 2, maximum is 64.
+ Modern hard disks are able to support 64 tags and even more, but
+ do not seem to be faster when more than 32 tags are being used.
+
+ So, the normal answer here is to go with the default value 32 unless
+ you are using very large hard disks with large cache (>= 1 MB) that
+ are able to take advantage of more than 32 tagged commands.
+
+ There is no safe option and the default answer is recommended.
+
+Assume boards are SYMBIOS compatible
+CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
+ This option allows you to enable some features depending on GPIO
+ wiring. These General Purpose Input/Output pins can be used for
+ vendor specific features or implementation of the standard SYMBIOS
+ features. Genuine SYMBIOS controllers use GPIO0 in output for
+ controller LED and GPIO3 bit as a flag indicating
+ singled-ended/differential interface. The Tekram DC-390U/F boards
+ uses a different GPIO wiring.
+
+ Your answer to this question is ignored if all your controllers have
+ NVRAM, since the driver is able to detect the board type from the
+ NVRAM format.
+
+ If all the controllers in your system are genuine SYMBIOS boards or
+ use BIOS and drivers from SYMBIOS, you would want to say Y here,
+ otherwise N. N is the safe answer.
+
+Enable traffic profiling
+CONFIG_SCSI_NCR53C8XX_PROFILE
+ This option allows you to enable profiling information gathering.
+ These statistics are not very accurate due to the low frequency
+ of the kernel clock (100 Hz on i386) and have performance impact
+ on systems that use very fast devices.
+
+ The normal answer therefore is N.
+
+Include support for the NCR PQS/PDS SCSI card
+CONFIG_SCSI_NCR53C8XX_PQS_PDS
+ Say Y here if you have a special SCSI adapter produced by NCR
+ corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need
+ this if you do not have one of these adapters. However, since this
+ device is detected as a specific PCI device, this option is quite
+ safe.
+
+ The common answer here is N, but answering Y is safe.
+
+IBMMCA SCSI support
+CONFIG_SCSI_IBMMCA
+ This is support for the IBM SCSI adapter found in many of the PS/2
+ series computers. These machines have an MCA bus, so you need to
+ answer Y to "MCA support" as well and read
+ <file:Documentation/mca.txt>.
+
+ If the adapter isn't found during boot (a common problem for models
+ 56, 57, 76, and 77) you'll need to use the 'ibmmcascsi=<pun>' kernel
+ option, where <pun> is the id of the SCSI subsystem (usually 7, but
+ if that doesn't work check your reference diskette). Owners of
+ model 95 with a LED-matrix-display can in addition activate some
+ activity info like under OS/2, but more informative, by setting
+ 'ibmmcascsi=display' as an additional kernel parameter. Try "man
+ bootparam" or see the documentation of your boot loader about how to
+ pass options to the kernel.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ibmmca.o.
+
+Standard SCSI-order
+CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+ In the PC-world and in most modern SCSI-BIOS-setups, SCSI-hard disks
+ are assigned to the drive letters, starting with the lowest SCSI-id
+ (physical number -- pun) to be drive C:, as seen from DOS and
+ similar operating systems. When looking into papers describing the
+ ANSI-SCSI-standard, this assignment of drives appears to be wrong.
+ The SCSI-standard follows a hardware-hierarchy which says that id 7
+ has the highest priority and id 0 the lowest. Therefore, the host
+ adapters are still today everywhere placed as SCSI-id 7 by default.
+ In the SCSI-standard, the drive letters express the priority of the
+ disk. C: should be the hard disk, or a partition on it, with the
+ highest priority. This must therefore be the disk with the highest
+ SCSI-id (e.g. 6) and not the one with the lowest! IBM-BIOS kept the
+ original definition of the SCSI-standard as also industrial- and
+ process-control-machines, like VME-CPUs running under realtime-OSes
+ (e.g. LynxOS, OS9) do.
+
+ If you like to run Linux on your MCA-machine with the same
+ assignment of hard disks as seen from e.g. DOS or OS/2 on your
+ machine, which is in addition conformant to the SCSI-standard, you
+ must say Y here. This is also necessary for MCA-Linux users who want
+ to keep downward compatibility to older releases of the
+ IBM-MCA-SCSI-driver (older than driver-release 2.00 and older than
+ June 1997).
+
+ If you like to have the lowest SCSI-id assigned as drive C:, as
+ modern SCSI-BIOSes do, which does not conform to the standard, but
+ is widespread and common in the PC-world of today, you must say N
+ here. If unsure, say Y.
+
+Reset SCSI-devices at boot time
+CONFIG_IBMMCA_SCSI_DEV_RESET
+ By default, SCSI-devices are reset when the machine is powered on.
+ However, some devices exist, like special-control-devices,
+ SCSI-CNC-machines, SCSI-printer or scanners of older type, that do
+ not reset when switched on. If you say Y here, each device connected
+ to your SCSI-bus will be issued a reset-command after it has been
+ probed, while the kernel is booting. This may cause problems with
+ more modern devices, like hard disks, which do not appreciate these
+ reset commands, and can cause your system to hang. So say Y only if
+ you know that one of your older devices needs it; N is the safe
+ answer.
+
+NCR MCA 53C9x SCSI support
+CONFIG_SCSI_MCA_53C9X
+ Some MicroChannel machines, notably the NCR 35xx line, use a SCSI
+ controller based on the NCR 53C94. This driver will allow use of
+ the controller on the 3550, and very possibly others.
+
+ If you want to compile this as a module (= code which can be
+ inserted and removed from the running kernel whenever you want), say
+ M here and read <file:Documentation/modules.txt>. The module will
+ be called mca_53c9x.o.
+
+Always IN2000 SCSI support
+CONFIG_SCSI_IN2000
+ This is support for an ISA bus SCSI host adapter. You'll find more
+ information in <file:drivers/scsi/README.in2000>. If it doesn't work
+ out of the box, you may have to change the jumpers for IRQ or
+ address selection.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called in2000.o.
+
+Initio 91XXU(W) SCSI support
+CONFIG_SCSI_INITIO
+ This is support for the Initio 91XXU(W) SCSI host adapter. Please
+ read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called initio.o.
+
+PAS16 SCSI support
+CONFIG_SCSI_PAS16
+ This is support for a SCSI host adapter. It is explained in section
+ 3.10 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. If it doesn't work out
+ of the box, you may have to change some settings in
+ <file:drivers/scsi/pas16.h>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pas16.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Initio INI-A100U2W SCSI support
+CONFIG_SCSI_INIA100
+ This is support for the Initio INI-A100U2W SCSI host adapter.
+ Please read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called a100u2w.o.
+
+PCI2000 support
+CONFIG_SCSI_PCI2000
+ This is support for the PCI2000I EIDE interface card which acts as a
+ SCSI host adapter. Please read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module called pci2000.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+PCI2220i support
+CONFIG_SCSI_PCI2220I
+ This is support for the PCI2220i EIDE interface card which acts as a
+ SCSI host adapter. Please read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module called pci2220i.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+PSI240i support
+CONFIG_SCSI_PSI240I
+ This is support for the PSI240i EIDE interface card which acts as a
+ SCSI host adapter. Please read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module called psi240i.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Qlogic FAS SCSI support
+CONFIG_SCSI_QLOGIC_FAS
+ This is a driver for the ISA, VLB, and PCMCIA versions of the Qlogic
+ FastSCSI! cards as well as any other card based on the FASXX chip
+ (including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards).
+
+ This driver does NOT support the PCI versions of these cards. The
+ PCI versions are supported by the Qlogic ISP driver ("Qlogic ISP
+ SCSI support"), below.
+
+ Information about this driver is contained in
+ <file:drivers/scsi/README.qlogicfas>. You should also read the
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called qlogicfas.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Qlogic ISP SCSI support
+CONFIG_SCSI_QLOGIC_ISP
+ This driver works for all QLogic PCI SCSI host adapters (IQ-PCI,
+ IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter
+ card is supported by the "AM53/79C974 PCI SCSI" driver.)
+
+ If you say Y here, make sure to choose "BIOS" at the question "PCI
+ access mode".
+
+ Please read the file <file:drivers/scsi/README.qlogicisp>. You
+ should also read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called qlogicisp.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Qlogic ISP FC SCSI support
+CONFIG_SCSI_QLOGIC_FC
+ This is a driver for the QLogic ISP2100 SCSI-FCP host adapter.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called qlogicfc.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Include loadable firmware in driver
+CONFIG_SCSI_QLOGIC_FC_FIRMWARE
+ Say Y to include ISP2100 Fabric Initiator/Target Firmware, with
+ expanded LUN addressing and FcTape (FCP-2) support, in the
+ Qlogic QLA 1280 driver. This is required on some platforms.
+
+Qlogic QLA 1280 SCSI support
+CONFIG_SCSI_QLOGIC_1280
+ Say Y if you have a QLogic ISP1x80/1x160 SCSI host adapter.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called qla1280.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Seagate ST-02 and Future Domain TMC-8xx SCSI support
+CONFIG_SCSI_SEAGATE
+ These are 8-bit SCSI controllers; the ST-01 is also supported by
+ this driver. It is explained in section 3.9 of the SCSI-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>. If it
+ doesn't work out of the box, you may have to change some settings in
+ <file:drivers/scsi/seagate.h>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called seagate.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Trantor T128/T128F/T228 SCSI support
+CONFIG_SCSI_T128
+ This is support for a SCSI host adapter. It is explained in section
+ 3.11 of the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. If it doesn't work out
+ of the box, you may have to change some settings in
+ <file:drivers/scsi/t128.h>. Note that Trantor was purchased by
+ Adaptec, and some former Trantor products are being sold under the
+ Adaptec name.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called t128.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+UltraStor SCSI support
+CONFIG_SCSI_ULTRASTOR
+ This is support for the UltraStor 14F, 24F and 34F SCSI-2 host
+ adapter family. This driver is explained in section 3.12 of the
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. If it doesn't work out
+ of the box, you may have to change some settings in
+ <file:drivers/scsi/ultrastor.h>.
+
+ Note that there is also another driver for the same hardware:
+ "UltraStor 14F/34F support", above.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ultrastor.o.
+
+7000FASST SCSI support
+CONFIG_SCSI_7000FASST
+ This driver supports the Western Digital 7000 SCSI host adapter
+ family. Some information is in the source:
+ <file:drivers/scsi/wd7000.c>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called wd7000.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+ACARD SCSI support
+CONFIG_SCSI_ACARD
+ This driver supports the ACARD 870U/W SCSI host adapter.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called atp870u.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support
+CONFIG_SCSI_EATA
+ This driver supports all EATA/DMA-compliant SCSI host adapters. DPT
+ ISA and all EISA I/O addresses are probed looking for the "EATA"
+ signature. If you chose "BIOS" at the question "PCI access mode",
+ the addresses of all the PCI SCSI controllers reported by the PCI
+ subsystem are probed as well.
+
+ You want to read the start of <file:drivers/scsi/eata.c> and the
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that there is also another driver for the same hardware
+ available: "EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti,
+ Alphatronix) support". You should say Y to only one of them.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called eata.o.
+
+enable tagged command queueing
+CONFIG_SCSI_EATA_TAGGED_QUEUE
+ This is a feature of SCSI-2 which improves performance: the host
+ adapter can send several SCSI commands to a device's queue even if
+ previous commands haven't finished yet. Most EATA adapters negotiate
+ this feature automatically with the device, even if your answer is
+ N. The safe answer is N.
+
+enable elevator sorting
+CONFIG_SCSI_EATA_LINKED_COMMANDS
+ This option enables elevator sorting for all probed SCSI disks and
+ CD-ROMs. It definitely reduces the average seek distance when doing
+ random seeks, but this does not necessarily result in a noticeable
+ performance improvement: your mileage may vary...
+ The safe answer is N.
+
+maximum number of queued commands
+CONFIG_SCSI_EATA_MAX_TAGS
+ This specifies how many SCSI commands can be maximally queued for
+ each probed SCSI device. You should reduce the default value of 16
+ only if you have disks with buggy or limited tagged command support.
+ Minimum is 2 and maximum is 62. This value is also the window size
+ used by the elevator sorting option above. The effective value used
+ by the driver for each probed SCSI device is reported at boot time.
+
+NCR53c406a SCSI support
+CONFIG_SCSI_NCR53C406A
+ This is support for the NCR53c406a SCSI host adapter. For user
+ configurable parameters, check out <file:drivers/scsi/NCR53c406a.c>
+ in the kernel source. Also read the SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called NCR53c406.o.
+
+Symbios 53c416 SCSI support
+CONFIG_SCSI_SYM53C416
+ This is support for the sym53c416 SCSI host adapter, the SCSI
+ adapter that comes with some HP scanners. This driver requires that
+ the sym53c416 is configured first using some sort of PnP
+ configuration program (e.g. isapnp) or by a PnP aware BIOS. If you
+ are using isapnp then you need to compile this driver as a module
+ and then load it using insmod after isapnp has run. The parameters
+ of the configured card(s) should be passed to the driver. The format
+ is:
+
+ insmod sym53c416 sym53c416=<base>,<irq> [sym53c416_1=<base>,<irq>]
+
+ There is support for up to four adapters. If you want to compile
+ this driver as a module ( = code which can be inserted in and
+ removed from the running kernel whenever you want), say M here and
+ read <file:Documentation/modules.txt>. The module will be called
+ sym53c416.o.
+
+Simple 53c710 SCSI support (Compaq, NCR machines)
+CONFIG_SCSI_SIM710
+ This is a simple driver for NCR53c710 based SCSI host adapters.
+
+ More complex drivers for this chip are available ("NCR53c7,8xx SCSI
+ support", above), but they require that the scsi chip be able to do
+ DMA block moves between memory and on-chip registers, which can
+ cause problems under certain conditions. This driver is designed to
+ avoid these problems and is intended to work with any Intel machines
+ using 53c710 chips, including various Compaq and NCR machines.
+
+ Please read the comments at the top of the file
+ <file:drivers/scsi/sim710.c> for more information.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called sim710.o.
+
+Tekram DC390(T) and Am53/79C974 SCSI support
+CONFIG_SCSI_DC390T
+ This driver supports PCI SCSI host adapters based on the Am53C974A
+ chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
+ PCscsi/PCnet (Am53/79C974) solutions.
+
+ Documentation can be found in <file:drivers/scsi/README.tmscsim>.
+
+ Note that this driver does NOT support Tekram DC390W/U/F, which are
+ based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
+ Also note that there is another generic Am53C974 driver,
+ "AM53/79C974 PCI SCSI support" below. You can pick either one.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called tmscsim.o.
+
+Omit support for other Am53/79C974 based SCSI adapters
+CONFIG_SCSI_DC390T_NOGENSUPP
+ If you say N here, the DC390(T) SCSI driver relies on the DC390
+ EEPROM to get initial values for its settings, such as speed,
+ termination, etc. If it can't find this EEPROM, it will use
+ defaults or the user supplied boot/module parameters. For details
+ on driver configuration see <file:drivers/scsi/README.tmscsim>.
+
+ If you say Y here and if no EEPROM is found, the driver gives up and
+ thus only supports Tekram DC390(T) adapters. This can be useful if
+ you have a DC390(T) and another Am53C974 based adapter, which, for
+ some reason, you want to drive with the other AM53C974 driver.
+
+ If unsure, say N.
+
+AM53/79C974 PCI SCSI support
+CONFIG_SCSI_AM53C974
+ This is support for the AM53/79C974 SCSI host adapters. Please read
+ <file:drivers/scsi/README.AM53C974> for details. Also, the
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, is for you.
+
+ Note that there is another driver for AM53C974 based adapters:
+ "Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support", above. You
+ can pick either one.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called AM53C974.o.
+
+AMI MegaRAID support
+CONFIG_SCSI_MEGARAID
+ This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490
+ and 467 SCSI host adapters.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called megaraid.o.
+
+Intel/ICP (former GDT SCSI Disk Array) RAID Controller support
+CONFIG_SCSI_GDTH
+ Formerly called GDT SCSI Disk Array Controller Support.
+
+ This is a driver for RAID/SCSI Disk Array Controllers (EISA/ISA/PCI)
+ manufactured by Intel/ICP vortex (an Intel Company). It is documented
+ in the kernel source in <file:drivers/scsi/gdth.c> and
+ <file:drivers/scsi/gdth.h.>
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called gdth.o.
+
+IOMEGA parallel port (ppa - older drives)
+CONFIG_SCSI_PPA
+ This driver supports older versions of IOMEGA's parallel port ZIP
+ drive (a 100 MB removable media device).
+
+ Note that you can say N here if you have the SCSI version of the ZIP
+ drive: it will be supported automatically if you said Y to the
+ generic "SCSI disk support", above.
+
+ If you have the ZIP Plus drive or a more recent parallel port ZIP
+ drive (if the supplied cable with the drive is labeled "AutoDetect")
+ then you should say N here and Y to "IOMEGA parallel port (imm -
+ newer drives)", below.
+
+ For more information about this driver and how to use it you should
+ read the file <file:drivers/scsi/README.ppa>. You should also read
+ the SCSI-HOWTO, which is available from
+ <http://www.tldp.org/docs.html#howto>. If you use this driver,
+ you will still be able to use the parallel port for other tasks,
+ such as a printer; it is safe to compile both drivers into the
+ kernel.
+
+ This driver is also available as a module which can be inserted in
+ and removed from the running kernel whenever you want. To compile
+ this driver as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called ppa.o.
+
+IOMEGA parallel port (imm - newer drives)
+CONFIG_SCSI_IMM
+ This driver supports newer versions of IOMEGA's parallel port ZIP
+ drive (a 100 MB removable media device).
+
+ Note that you can say N here if you have the SCSI version of the ZIP
+ drive: it will be supported automatically if you said Y to the
+ generic "SCSI disk support", above.
+
+ If you have the ZIP Plus drive or a more recent parallel port ZIP
+ drive (if the supplied cable with the drive is labeled "AutoDetect")
+ then you should say Y here; if you have an older ZIP drive, say N
+ here and Y to "IOMEGA Parallel Port (ppa - older drives)", above.
+
+ For more information about this driver and how to use it you should
+ read the file <file:drivers/scsi/README.ppa>. You should also read
+ the SCSI-HOWTO, which is available from
+ <http://www.tldp.org/docs.html#howto>. If you use this driver,
+ you will still be able to use the parallel port for other tasks,
+ such as a printer; it is safe to compile both drivers into the
+ kernel.
+
+ This driver is also available as a module which can be inserted in
+ and removed from the running kernel whenever you want. To compile
+ this driver as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called imm.o.
+
+Force the Iomega ZIP drivers to use EPP-16
+CONFIG_SCSI_IZIP_EPP16
+ EPP (Enhanced Parallel Port) is a standard for parallel ports which
+ allows them to act as expansion buses that can handle up to 64
+ peripheral devices.
+
+ Some parallel port chipsets are slower than their motherboard, and
+ so we have to control the state of the chipset's FIFO queue every
+ now and then to avoid data loss. This will be done if you say Y
+ here.
+
+ Generally, saying Y is the safe option and slows things down a bit.
+
+Assume slow parallel port control register
+CONFIG_SCSI_IZIP_SLOW_CTR
+ Some parallel ports are known to have excessive delays between
+ changing the parallel port control register and good data being
+ available on the parallel port data/status register. This option
+ forces a small delay (1.0 usec to be exact) after changing the
+ control register to let things settle out. Enabling this option may
+ result in a big drop in performance but some very old parallel ports
+ (found in 386 vintage machines) will not work properly.
+
+ Generally, saying N is fine.
+
+SCSI debugging host simulator
+CONFIG_SCSI_DEBUG
+ This is a host adapter simulator that can be programmed to simulate
+ a large number of conditions that could occur on a real bus. The
+ advantage is that many hard to reproduce problems can be tested in a
+ controlled environment where there is reduced risk of losing
+ important data. This is primarily of use to people trying to debug
+ the middle and upper layers of the SCSI subsystem. If unsure, say N.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called scsi_debug.o.
+
+Fibre Channel and FC4 SCSI support
+CONFIG_FC4
+ Fibre Channel is a high speed serial protocol mainly used to
+ connect large storage devices to the computer; it is compatible with
+ and intended to replace SCSI.
+
+ This is an experimental support for storage arrays connected to your
+ computer using optical fibre cables and the "X3.269-199X Fibre
+ Channel Protocol for SCSI" specification. If you want to use this,
+ you need to say Y here and to "SCSI support" as well as to the
+ drivers for the storage array itself and for the interface adapter
+ such as SOC or SOC+. This subsystem could even serve for IP
+ networking, with some code extensions.
+
+ If unsure, say N.
+
+Sun SOC/Sbus
+CONFIG_FC4_SOC
+ Serial Optical Channel is an interface card with one or two Fibre
+ Optic ports, each of which can be connected to a disk array. Note
+ that if you have older firmware in the card, you'll need the
+ microcode from the Solaris driver to make it work.
+
+ This support is also available as a module called soc.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Sun SOC+ (aka SOCAL)
+CONFIG_FC4_SOCAL
+ Serial Optical Channel Plus is an interface card with up to two
+ Fibre Optic ports. This card supports FC Arbitrated Loop (usually
+ A5000 or internal FC disks in E[3-6]000 machines through the
+ Interface Board). You'll probably need the microcode from the
+ Solaris driver to make it work.
+
+ This support is also available as a module called socal.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+SparcSTORAGE Array 100 and 200 series
+CONFIG_SCSI_PLUTO
+ If you never bought a disk array made by Sun, go with N.
+
+ This support is also available as a module called pluto.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Sun Enterprise Network Array (A5000 and EX500)
+CONFIG_SCSI_FCAL
+ This driver drives FC-AL disks connected through a Fibre Channel
+ card using the drivers/fc4 layer (currently only SOCAL). The most
+ common is either A5000 array or internal disks in E[3-6]000
+ machines.
+
+ This support is also available as a module called fcal.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>. If unsure, say N.
+
+Acorn SCSI card (aka30) support
+CONFIG_SCSI_ACORNSCSI_3
+ This enables support for the Acorn SCSI card (aka30). If you have an
+ Acorn system with one of these, say Y. If unsure, say N.
+
+Support SCSI 2 Tagged queueing
+CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
+ Say Y here to enable tagged queuing support on the Acorn SCSI card.
+
+ This is a feature of SCSI-2 which improves performance: the host
+ adapter can send several SCSI commands to a device's queue even if
+ previous commands haven't finished yet. Some SCSI devices don't
+ implement this properly, so the safe answer is N.
+
+Support SCSI 2 Synchronous Transfers
+CONFIG_SCSI_ACORNSCSI_SYNC
+ Say Y here to enable synchronous transfer negotiation with all
+ targets on the Acorn SCSI card.
+
+ In general, this improves performance; however some SCSI devices
+ don't implement it properly, so the safe answer is N.
+
+ARXE SCSI support
+CONFIG_SCSI_ARXESCSI
+ Around 1991, Arxe Systems Limited released a high density floppy
+ disc interface for the Acorn Archimedes range, to allow the use of
+ HD discs from the then new A5000 on earlier models. This interface
+ was either sold on its own or with an integral SCSI controller.
+ Technical details on this NCR53c94-based device are available at
+ <http://www.cryton.demon.co.uk/acornbits/scsi_arxe.html>
+ Say Y here to compile in support for the SCSI controller.
+
+Oak SCSI support
+CONFIG_SCSI_OAK1
+ This enables support for the Oak SCSI card. If you have an Acorn
+ system with one of these, say Y. If unsure, say N.
+
+Cumana SCSI I support
+CONFIG_SCSI_CUMANA_1
+ This enables support for the Cumana SCSI I card. If you have an
+ Acorn system with one of these, say Y. If unsure, say N.
+
+Cumana SCSI II support
+CONFIG_SCSI_CUMANA_2
+ This enables support for the Cumana SCSI II card. If you have an
+ Acorn system with one of these, say Y. If unsure, say N.
+
+EcoSCSI support
+CONFIG_SCSI_ECOSCSI
+ This enables support for the EcoSCSI card -- a small card that sits
+ in the Econet socket. If you have an Acorn system with one of these,
+ say Y. If unsure, say N.
+
+EESOX SCSI support
+CONFIG_SCSI_EESOXSCSI
+ This enables support for the EESOX SCSI card. If you have an Acorn
+ system with one of these, say Y, otherwise say N.
+
+PowerTec SCSI support
+CONFIG_SCSI_POWERTECSCSI
+ This enables support for the Powertec SCSI card on Acorn systems. If
+ you have one of these, say Y. If unsure, say N.
+
+IEEE 1394 (FireWire) support
+CONFIG_IEEE1394
+ IEEE 1394 describes a high performance serial bus, which is also
+ known as FireWire(tm) or i.Link(tm) and is used for connecting all
+ sorts of devices (most notably digital video cameras) to your
+ computer.
+
+ If you have FireWire hardware and want to use it, say Y here. This
+ is the core support only, you will also need to select a driver for
+ your IEEE 1394 adapter.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ieee1394.o.
+
+Texas Instruments PCILynx support
+CONFIG_IEEE1394_PCILYNX
+ Say Y here if you have an IEEE-1394 controller with the Texas
+ Instruments PCILynx chip. Note: this driver is written for revision
+ 2 of this chip and may not work with revision 0.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called pcilynx.o.
+
+Use local RAM on PCILynx board
+CONFIG_IEEE1394_PCILYNX_LOCALRAM
+ This option makes the PCILynx driver use local RAM available on some
+ PCILynx setups for Packet Control Lists. Local RAM is random access
+ memory which resides on the PCILynx board as opposed to on your
+ computer's motherboard. Local RAM may speed up command processing
+ because no PCI transfers are necessary during use of the Packet
+ Control Lists.
+
+ Note that there are no known PCILynx systems providing local RAM
+ except for the evaluation boards by Texas Instruments and that the
+ PCILynx does not reliably report missing RAM. This means that it is
+ dangerous to say Y here if you are not absolutely sure that your
+ board provides 64KB of local RAM.
+
+ If unsure, say N.
+
+Support for non-IEEE1394 local ports
+CONFIG_IEEE1394_PCILYNX_PORTS
+ This option enables driver code to access the RAM, ROM and AUX ports
+ of the PCILynx through character devices in /dev. If you don't know
+ what this is about then you won't need it.
+
+ If unsure, say N.
+
+#Adaptec AIC-5800 IEEE 1394 support
+#CONFIG_IEEE1394_AIC5800
+# Say Y here if you have a IEEE 1394 controller using the Adaptec
+# AIC-5800 chip. All Adaptec host adapters (89xx series) use this
+# chip, as well as miro's DV boards.
+#
+# If you want to compile this as a module ( = code which can be
+# inserted in and removed from the running kernel whenever you want),
+# say M here and read <file:Documentation/modules.txt>. The module
+# will be called aic5800.o.
+#
+OHCI-1394 (Open Host Controller Interface) support
+CONFIG_IEEE1394_OHCI1394
+ Enable this driver if you have an IEEE 1394 controller based on the
+ OHCI-1394 specification. The current driver is only tested with OHCI
+ chipsets made by Texas Instruments and NEC. Most third-party vendors
+ use one of these chipsets. It should work with any OHCI-1394
+ compliant card, however.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ohci1394.o.
+
+OHCI-1394 Video support
+CONFIG_IEEE1394_VIDEO1394
+ This option enables video device usage for OHCI-1394 cards. Enable
+ this option only if you have an IEEE 1394 video device connected to
+ an OHCI-1394 card.
+
+SBP-2 support (Harddisks etc.)
+CONFIG_IEEE1394_SBP2
+ This option enables you to use SBP-2 devices connected to your IEEE
+ 1394 bus. SBP-2 devices include harddrives and DVD devices.
+
+Raw IEEE 1394 I/O support
+CONFIG_IEEE1394_RAWIO
+ Say Y here if you want support for the raw device. This is generally
+ a good idea, so you should say Y here. The raw device enables
+ direct communication of user programs with the IEEE 1394 bus and
+ thus with the attached peripherals.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called raw1394.o.
+
+Excessive debugging output
+CONFIG_IEEE1394_VERBOSEDEBUG
+ If you say Y here, you will get very verbose debugging logs from the
+ subsystem which includes a dump of the header of every sent and
+ received packet. This can amount to a high amount of data collected
+ in a very short time which is usually also saved to disk by the
+ system logging daemons.
+
+ Say Y if you really want or need the debugging output, everyone else
+ says N.
+
+Network device support
+CONFIG_NETDEVICES
+ You can say N here if you don't intend to connect your Linux box to
+ any other computer at all or if all your connections will be over a
+ telephone line with a modem either via UUCP (UUCP is a protocol to
+ forward mail and news between unix hosts over telephone lines; read
+ the UUCP-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>) or dialing up a shell
+ account or a BBS, even using term (term is a program which gives you
+ almost full Internet connectivity if you have a regular dial up
+ shell account on some Internet connected Unix computer. Read
+ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
+
+ You'll have to say Y if your computer contains a network card that
+ you want to use under Linux (make sure you know its name because you
+ will be asked for it and read the Ethernet-HOWTO (especially if you
+ plan to use more than one network card under Linux)) or if you want
+ to use SLIP (Serial Line Internet Protocol is the protocol used to
+ send Internet traffic over telephone lines or null modem cables) or
+ CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better
+ and newer replacement for SLIP) or PLIP (Parallel Line Internet
+ Protocol is mainly used to create a mini network by connecting the
+ parallel ports of two local machines) or AX.25/KISS (protocol for
+ sending Internet traffic over amateur radio links).
+
+ Make sure to read the NET-3-HOWTO. Eventually, you will have to read
+ Olaf Kirch's excellent and free book "Network Administrator's
+ Guide", to be found in <http://www.tldp.org/docs.html#guide>. If
+ unsure, say Y.
+
+Dummy net driver support
+CONFIG_DUMMY
+ This is essentially a bit-bucket device (i.e. traffic you send to
+ this device is consigned into oblivion) with a configurable IP
+ address. It is most commonly used in order to make your currently
+ inactive SLIP address seem like a real address for local programs.
+ If you use SLIP or PPP, you might want to say Y here. Since this
+ thing often comes in handy, the default is Y. It won't enlarge your
+ kernel either. What a deal. Read about it in the Network
+ Administrator's Guide, available from
+ <http://www.tldp.org/docs.html#guide>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called dummy.o. If you want to use more than one dummy
+ device at a time, you need to compile this driver as a module.
+ Instead of 'dummy', the devices will then be called 'dummy0',
+ 'dummy1' etc.
+
+Bonding driver support
+CONFIG_BONDING
+ Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
+ Channels together. This is called 'Etherchannel' by Cisco,
+ 'Trunking' by Sun, and 'Bonding' in Linux.
+
+ If you have two Ethernet connections to some other computer, you can
+ make them behave like one double speed connection using this driver.
+ Naturally, this has to be supported at the other end as well, either
+ with a similar Bonding Linux driver, a Cisco 5500 switch or a
+ SunTrunking SunSoft driver.
+
+ This is similar to the EQL driver, but it merges Ethernet segments
+ instead of serial lines.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called bonding.o.
+
+Intermediate queueing device support
+CONFIG_IMQ
+ The imq device(s) is used as placeholder for QoS queueing disciplines.
+ Every packet entering/leaving the ip stack can be directed through
+ the imq device where it's enqueued/dequeued to the attached qdisc.
+ This allows you to treat network devices as classes and distribute
+ bandwidth among them. Iptables is used to specify through which imq
+ device, if any, packets travel.
+
+ If you want to compile this as a module ( = code which ca be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called imq.o
+
+SLIP (serial line) support
+CONFIG_SLIP
+ Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
+ connect to your Internet service provider or to connect to some
+ other local Unix box or if you want to configure your Linux box as a
+ Slip/CSlip server for other people to dial in. SLIP (Serial Line
+ Internet Protocol) is a protocol used to send Internet traffic over
+ serial connections such as telephone lines or null modem cables;
+ nowadays, the protocol PPP is more commonly used for this same
+ purpose.
+
+ Normally, your access provider has to support SLIP in order for you
+ to be able to use it, but there is now a SLIP emulator called SLiRP
+ around (available from
+ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+ allows you to use SLIP over a regular dial up shell connection. If
+ you plan to use SLiRP, make sure to say Y to CSLIP, below. The
+ NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, explains how to
+ configure SLIP. Note that you don't need this option if you just
+ want to run term (term is a program which gives you almost full
+ Internet connectivity if you have a regular dial up shell account on
+ some Internet connected Unix computer. Read
+ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
+ support will enlarge your kernel by about 4 KB. If unsure, say N.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called slip.o.
+
+CSLIP compressed headers
+CONFIG_SLIP_COMPRESSED
+ This protocol is faster than SLIP because it uses compression on the
+ TCP/IP headers (not on the data itself), but it has to be supported
+ on both ends. Ask your access provider if you are not sure and
+ answer Y, just in case. You will still be able to use plain SLIP. If
+ you plan to use SLiRP, the SLIP emulator (available from
+ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+ allows you to use SLIP over a regular dial up shell connection, you
+ definitely want to say Y here. The NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, explains how to configure
+ CSLIP. This won't enlarge your kernel.
+
+Keepalive and linefill
+CONFIG_SLIP_SMART
+ Adds additional capabilities to the SLIP driver to support the
+ RELCOM line fill and keepalive monitoring. Ideal on poor quality
+ analogue lines.
+
+Six bit SLIP encapsulation
+CONFIG_SLIP_MODE_SLIP6
+ Just occasionally you may need to run IP over hostile serial
+ networks that don't pass all control characters or are only seven
+ bit. Saying Y here adds an extra mode you can use with SLIP:
+ "slip6". In this mode, SLIP will only send normal ASCII symbols over
+ the serial device. Naturally, this has to be supported at the other
+ end of the link as well. It's good enough, for example, to run IP
+ over the async ports of a Camtec JNT Pad. If unsure, say N.
+
+PPP (point-to-point protocol) support
+CONFIG_PPP
+ PPP (Point to Point Protocol) is a newer and better SLIP. It serves
+ the same purpose: sending Internet traffic over telephone (and other
+ serial) lines. Ask your access provider if they support it, because
+ otherwise you can't use it; most Internet access providers these
+ days support PPP rather than SLIP.
+
+ To use PPP, you need an additional program called pppd as described
+ in the PPP-HOWTO, available at
+ <http://www.tldp.org/docs.html#howto>. Make sure that you have
+ the version of pppd recommended in <file:Documentation/Changes>.
+ The PPP option enlarges your kernel by about 16 KB.
+
+ There are actually two versions of PPP: the traditional PPP for
+ asynchronous lines, such as regular analog phone lines, and
+ synchronous PPP which can be used over digital ISDN lines for
+ example. If you want to use PPP over phone lines or other
+ asynchronous serial lines, you need to say Y (or M) here and also to
+ the next option, "PPP support for async serial ports". For PPP over
+ synchronous lines, you should say Y (or M) here and to "Support
+ synchronous PPP", below.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you said Y to "Version information on all symbols" above, then
+ you cannot compile the PPP driver into the kernel; you can then only
+ compile it as a module. The module will be called ppp_generic.o.
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>.
+
+PPP multilink support
+CONFIG_PPP_MULTILINK
+ PPP multilink is a protocol (defined in RFC 1990) which allows you
+ to combine several (logical or physical) lines into one logical PPP
+ connection, so that you can utilize your full bandwidth.
+
+ This has to be supported at the other end as well and you need a
+ version of the pppd daemon which understands the multilink protocol.
+
+ If unsure, say N.
+
+PPP filtering
+CONFIG_PPP_FILTER
+ Say Y here if you want to be able to filter the packets passing over
+ PPP interfaces. This allows you to control which packets count as
+ activity (i.e. which packets will reset the idle timer or bring up
+ a demand-dialled link) and which packets are to be dropped entirely.
+ You need to say Y here if you wish to use the pass-filter and
+ active-filter options to pppd.
+
+ If unsure, say N.
+
+PPP support for async serial ports
+CONFIG_PPP_ASYNC
+ Say Y (or M) here if you want to be able to use PPP over standard
+ asynchronous serial ports, such as COM1 or COM2 on a PC. If you use
+ a modem (not a synchronous or ISDN modem) to contact your ISP, you
+ need this option.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ppp_async.o.
+
+ If unsure, say Y.
+
+PPP support for sync tty ports
+CONFIG_PPP_SYNC_TTY
+ Say Y (or M) here if you want to be able to use PPP over synchronous
+ (HDLC) tty devices, such as the SyncLink adapter. These devices
+ are often used for high-speed leased lines like T1/E1.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ppp_synctty.o.
+
+PPP Deflate compression
+CONFIG_PPP_DEFLATE
+ Support for the Deflate compression method for PPP, which uses the
+ Deflate algorithm (the same algorithm that gzip uses) to compress
+ each PPP packet before it is sent over the wire. The machine at the
+ other end of the PPP link (usually your ISP) has to support the
+ Deflate compression method as well for this to be useful. Even if
+ they don't support it, it is safe to say Y here.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ppp_deflate.o.
+
+PPP BSD-Compress compression
+CONFIG_PPP_BSDCOMP
+ Support for the BSD-Compress compression method for PPP, which uses
+ the LZW compression method to compress each PPP packet before it is
+ sent over the wire. The machine at the other end of the PPP link
+ (usually your ISP) has to support the BSD-Compress compression
+ method as well for this to be useful. Even if they don't support it,
+ it is safe to say Y here.
+
+ The PPP Deflate compression method ("PPP Deflate compression",
+ above) is preferable to BSD-Compress, because it compresses better
+ and is patent-free.
+
+ Note that the BSD compression code will always be compiled as a
+ module; it is called bsd_comp.o and will show up in the directory
+ modules once you have said "make modules". If unsure, say N.
+
+PPP over Ethernet
+CONFIG_PPPOE
+ Support for PPP over Ethernet.
+
+ This driver requires the current pppd from the "ppp" CVS repository
+ on cvs.samba.org. The required support will be present in the next
+ ppp release (2.4.2).
+
+Wireless LAN (non-hamradio)
+CONFIG_NET_RADIO
+ Support for wireless LANs and everything having to do with radio,
+ but not with amateur radio or FM broadcasting.
+
+ Saying Y here also enables the Wireless Extensions (creates
+ /proc/net/wireless and enables ifconfig access). The Wireless
+ Extension is a generic API allowing a driver to expose to the user
+ space configuration and statistics specific to common Wireless LANs.
+ The beauty of it is that a single set of tool can support all the
+ variations of Wireless LANs, regardless of their type (as long as
+ the driver supports Wireless Extension). Another advantage is that
+ these parameters may be changed on the fly without restarting the
+ driver (or Linux). If you wish to use Wireless Extensions with
+ wireless PCMCIA (PC-) cards, you need to say Y here; you can fetch
+ the tools from
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ Some user-level drivers for scarab devices which don't require
+ special kernel support are available from
+ <ftp://shadow.cabi.net/pub/Linux/>.
+
+STRIP (Metricom Starmode radio IP)
+CONFIG_STRIP
+ Say Y if you have a Metricom radio and intend to use Starmode Radio
+ IP. STRIP is a radio protocol developed for the MosquitoNet project
+ (on the WWW at <http://mosquitonet.stanford.edu/>) to send Internet
+ traffic using Metricom radios. Metricom radios are small, battery
+ powered, 100kbit/sec packet radio transceivers, about the size and
+ weight of a cellular telephone. (You may also have heard them called
+ "Metricom modems" but we avoid the term "modem" because it misleads
+ many people into thinking that you can plug a Metricom modem into a
+ phone line and use it as a modem.)
+
+ You can use STRIP on any Linux machine with a serial port, although
+ it is obviously most useful for people with laptop computers. If you
+ think you might get a Metricom radio in the future, there is no harm
+ in saying Y to STRIP now, except that it makes the kernel a bit
+ bigger.
+
+ You can also compile this as a module ( = code which can be inserted
+ in and removed from the running kernel whenever you want), say M
+ here and read <file:Documentation/modules.txt>. The module will be
+ called strip.o.
+
+AT&T WaveLAN & DEC RoamAbout DS support
+CONFIG_WAVELAN
+ The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is
+ a Radio LAN (wireless Ethernet-like Local Area Network) using the
+ radio frequencies 900 MHz and 2.4 GHz.
+
+ This driver support the ISA version of the WaveLAN card. A separate
+ driver for the PCMCIA (PC-card) hardware is available in David
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location).
+
+ If you want to use an ISA WaveLAN card under Linux, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Some more specific
+ information is contained in
+ <file:Documentation/networking/wavelan.txt> and in the source code
+ <file:drivers/net/wavelan.p.h>.
+
+ You will also need the wireless tools package available from
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+ Please read the man pages contained therein.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called wavelan.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Aironet Arlan 655 & IC2200 DS support
+CONFIG_ARLAN
+ Aironet makes Arlan, a class of wireless LAN adapters. These use the
+ www.Telxon.com chip, which is also used on several similar cards.
+ This driver is tested on the 655 and IC2200 series cards. Look at
+ <http://www.ylenurme.ee/~elmer/655/> for the latest information.
+
+ The driver is built as two modules, arlan and arlan-proc. The latter
+ is the /proc interface and is not needed most of time.
+
+ On some computers the card ends up in non-valid state after some
+ time. Use a ping-reset script to clear it.
+
+Aironet 4500/4800 series adapters
+CONFIG_AIRONET4500
+ www.aironet.com (recently bought by Cisco) makes these 802.11 DS
+ adapters. Driver by Elmer Joandi (elmer@ylenurme.ee).
+
+ Say Y here if you have such an adapter, and then say Y below to
+ the option that applies to your particular type of card (PCI, ISA,
+ or PCMCIA).
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aironet4500_core.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>.
+
+ quick config parameters:
+ SSID=tsunami - "The Password"
+ adhoc=1 there are no Access Points around
+ master=1 Adhoc master (the one who creates network
+ sync)
+ slave=1 Adhoc slave (btw, it is still forming own net
+ sometimes, and has problems with firmware...
+ change IbssJoinNetTimeout from /proc...)
+ channel=1..? meaningful in adhoc mode
+
+ If you have problems with screwing up card, both_bap_lock=1 is a
+ conservative value (performance hit 15%).
+
+ All other parameters can be set via the proc interface.
+
+Aironet 4500/4800 ISA/PCI/PNP/365 support
+CONFIG_AIRONET4500_NONCS
+ If you have an ISA, PCI or PCMCIA Aironet 4500/4800 wireless LAN
+ card, say Y here, and then also to the options below that apply
+ to you.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aironet4500_card.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+Aironet 4500/4800 PNP support
+CONFIG_AIRONET4500_PNP
+ If you have an ISA Aironet 4500/4800 card which you want to use in
+ PnP (Plug and Play) mode, say Y here. This is the recommended mode
+ for ISA cards. Remember however to enable the PnP jumper on the
+ board if you say Y here.
+
+Aironet 4500/4800 PCI support
+CONFIG_AIRONET4500_PCI
+ If you have an PCI Aironet 4500/4800 card, say Y here.
+
+Aironet 4500/4800 ISA broken support
+CONFIG_AIRONET4500_ISA
+ If you have an ISA Aironet 4500/4800 card which you want to run in
+ non-PnP mode, say Y here. This is not recommended and does not work
+ correctly at this point. Say N.
+
+Aironet 4500/4800 I365 broken support
+CONFIG_AIRONET4500_I365
+ If you have a PCMCIA Aironet 4500/4800 card which you want to use
+ without the standard PCMCIA cardservices provided by the pcmcia-cs
+ package, say Y here. This is not recommended, so say N.
+
+Aironet 4500/4800 PCMCIA support
+CONFIG_AIRONET4500_CS
+ Say Y here if you have a PCMCIA Aironet 4500/4800 card which you
+ want to use with the standard PCMCIA cardservices provided by the
+ pcmcia-cs package.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aironet4500_cs.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+Aironet 4500/4800 PROC interface
+CONFIG_AIRONET4500_PROC
+ If you say Y here (and to the "/proc file system" below), you will
+ be able to configure your Aironet card via the
+ /proc/sys/aironet4500 interface.
+
+ Additional info: look in <file:drivers/net/aironet4500_rid.c>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aironet4500_proc.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+ NOTE: the proc interface uses a lot of memory, so it is recommended
+ to compile it as a module and remove the module after
+ configuration.
+
+LAPB over Ethernet driver
+CONFIG_LAPBETHER
+ This is a driver for a pseudo device (typically called /dev/lapb0)
+ which allows you to open an LAPB point-to-point connection to some
+ other computer on your Ethernet network. In order to do this, you
+ need to say Y or M to the driver for your Ethernet card as well as
+ to "LAPB Data Link Driver".
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called lapbether.o. If unsure, say N.
+
+X.25 async driver
+CONFIG_X25_ASY
+ This is a driver for sending and receiving X.25 frames over regular
+ asynchronous serial lines such as telephone lines equipped with
+ ordinary modems. Experts should note that this driver doesn't
+ currently comply with the asynchronous HDLS framing protocols in
+ CCITT recommendation X.25.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called x25_asy.o. If unsure, say N.
+
+PCMCIA network device support
+CONFIG_NET_PCMCIA
+ Say Y if you would like to include support for any PCMCIA or CardBus
+ network adapters, then say Y to the driver for your particular card
+ below. PCMCIA- or PC-cards are credit-card size devices often used
+ with laptops computers; CardBus is the newer and faster version of
+ PCMCIA.
+
+ To use your PC-cards, you will need supporting software from David
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If unsure, say N.
+
+3Com 3c589 PCMCIA support
+CONFIG_PCMCIA_3C589
+ Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA
+ (PC-card) Ethernet card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 3c589_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+3Com 3c574 PCMCIA support
+CONFIG_PCMCIA_3C574
+ Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA
+ (PC-card) Fast Ethernet card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 3c574_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+Fujitsu FMV-J18x PCMCIA support
+CONFIG_PCMCIA_FMVJ18X
+ Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible
+ PCMCIA (PC-card) Ethernet card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called fmvj18x_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ If unsure, say N.
+
+NE2000 compatible PCMCIA support
+CONFIG_PCMCIA_PCNET
+ Say Y here if you intend to attach an NE2000 compatible PCMCIA
+ (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pcnet_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+Asix AX88190 PCMCIA support
+CONFIG_PCMCIA_AXNET
+ Say Y here if you intend to attach an Asix AX88190-based PCMCIA
+ (PC-card) Fast Ethernet card to your computer. These cards are
+ nearly NE2000 compatible but need a separate driver due to a few
+ misfeatures.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called axnet_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+New Media PCMCIA support
+CONFIG_PCMCIA_NMCLAN
+ Say Y here if you intend to attach a New Media Ethernet or LiveWire
+ PCMCIA (PC-card) Ethernet card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called nmclan_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+SMC 91Cxx PCMCIA support
+CONFIG_PCMCIA_SMC91C92
+ Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA
+ (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc91c92_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ If unsure, say N.
+
+Xircom 16-bit PCMCIA support
+CONFIG_PCMCIA_XIRC2PS
+ Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card)
+ Ethernet or Fast Ethernet card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called xirc2ps_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ If unsure, say N.
+
+COM20020 ARCnet PCMCIA support
+CONFIG_ARCNET_COM20020_CS
+ Say Y here if you intend to attach this type of ARCnet PCMCIA card
+ to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called com20020_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ If unsure, say N.
+
+IBM PCMCIA Token Ring adapter support
+CONFIG_PCMCIA_IBMTR
+ Say Y here if you intend to attach this type of Token Ring PCMCIA
+ card to your computer. You then also need to say Y to "Token Ring
+ driver support".
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ibmtr_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Xircom Tulip-like CardBus support (old driver)
+CONFIG_PCMCIA_XIRTULIP
+ This driver is for the Digital "Tulip" Ethernet CardBus adapters.
+ It should work with most DEC 21*4*-based chips/ethercards, as well
+ as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
+ ASIX.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called xircom_tulip_cb.o. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say N.
+
+Xircom CardBus support (new driver)
+CONFIG_PCMCIA_XIRCOM
+ This driver is for the Digital "Tulip" Ethernet CardBus adapters.
+ It should work with most DEC 21*4*-based chips/ethercards, as well
+ as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
+ ASIX.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called xircom_cb.o. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say N.
+
+PCMCIA Wireless LAN
+CONFIG_NET_PCMCIA_RADIO
+ Say Y here if you would like to use a PCMCIA (PC-card) device to
+ connect to a wireless local area network. Then say Y to the driver
+ for your particular card below.
+
+ To use your PC-cards, you will need supporting software from David
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+Hermes chipset 802.11b support (Orinoco/Prism2/Symbol cards)
+CONFIG_HERMES
+ A driver for 802.11b wireless cards based based on the "Hermes" or
+ Intersil HFA384x (Prism 2) MAC controller. This includes the vast
+ majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
+ - except for the Cisco/Aironet cards. Cards supported include the
+ Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
+ Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
+ IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
+ MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
+ PRO/Wireless, and Symbol Spectrum24 High Rate amongst others.
+
+ This option includes the guts of the driver, but in order to
+ actually use a card you will also need to enable support for PCMCIA
+ Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below.
+
+ You will also very likely also need the Wireless Tools in order to
+ configure your card and that /etc/pcmcia/wireless.opts works :
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called hermes.o.
+
+Hermes 802.11b in PLX9052 based PCI adaptor support
+CONFIG_PLX_HERMES
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco_cs) driver when used in PLX9052 based PCI adaptors. These
+ adaptors are not a full PCMCIA controller but act as a more limited
+ PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
+ 802.11b PCMCIA cards can be used in desktop machines. The Netgear
+ MA301 is such an adaptor.
+
+ Support for these adaptors is so far still incomplete and buggy.
+ You have been warned.
+
+Prism 2.5 PCI 802.11b adaptor support
+CONFIG_PCI_HERMES
+ Enable support for PCI and mini-PCI 802.11b wireless NICs based on
+ the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
+ PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
+ common. Some of the built-in wireless adaptors in laptops are of
+ this variety.
+
+Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards)
+CONFIG_PCMCIA_HERMES
+ A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
+ as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
+ EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
+ others). It should also be usable on various Prism II based cards
+ such as the Linksys, D-Link and Farallon Skyline. It should also
+ work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
+
+ To use your PC-cards, you will need supporting software from David
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ You will also very likely also need the Wireless Tools in order to
+ configure your card and that /etc/pcmcia/wireless.opts works:
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called orinoco_cs.o.
+
+Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards
+CONFIG_AIRO
+ This is the standard Linux driver to support Cisco/Aironet ISA and
+ PCI 802.11 wireless cards.
+ It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
+ - with or without encryption) as well as card before the Cisco
+ acquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
+
+ This driver support both the standard Linux Wireless Extensions
+ and Cisco proprietary API, so both the Linux Wireless Tools and the
+ Cisco Linux utilities can be used to configure the card.
+
+ The driver can be compiled as a module and will be named "airo.o".
+
+Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards
+CONFIG_AIRO_CS
+ This is the standard Linux driver to support Cisco/Aironet PCMCIA
+ 802.11 wireless cards. This driver is the same as the Aironet
+ driver part of the Linux Pcmcia package.
+ It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
+ - with or without encryption) as well as card before the Cisco
+ acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
+ supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom
+ 802.11b cards.
+
+ This driver support both the standard Linux Wireless Extensions
+ and Cisco proprietary API, so both the Linux Wireless Tools and the
+ Cisco Linux utilities can be used to configure the card.
+
+ To use your PC-cards, you will need supporting software from David
+ Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+ for location). You also want to check out the PCMCIA-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called airo_cs.o.
+
+Aviator/Raytheon 2.4MHz wireless support
+CONFIG_PCMCIA_RAYCS
+ Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
+ (PC-card) wireless Ethernet networking card to your computer.
+ Please read the file <file:Documentation/networking/ray_cs.txt> for
+ details.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ray_cs.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+Apple Airport support (built-in)
+CONFIG_APPLE_AIRPORT
+ Say Y here to support the Airport 802.11b wireless Ethernet hardware
+ built into the Macintosh iBook and other recent PowerPC-based
+ Macintosh machines. This is essentially a Lucent Orinoco card with
+ a non-standard interface
+
+Xircom Netwave AirSurfer wireless support
+CONFIG_PCMCIA_NETWAVE
+ Say Y here if you intend to attach this type of PCMCIA (PC-card)
+ wireless Ethernet networking card to your computer.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called netwave_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ If unsure, say N.
+
+AT&T/Lucent Wavelan wireless support
+CONFIG_PCMCIA_WAVELAN
+ Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
+ (PC-card) wireless Ethernet networking card to your computer. This
+ driver is for the non-IEEE-802.11 Wavelan cards.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called wavelan_cs.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+ If unsure, say N.
+
+PLIP (parallel port) support
+CONFIG_PLIP
+ PLIP (Parallel Line Internet Protocol) is used to create a
+ reasonably fast mini network consisting of two (or, rarely, more)
+ local machines. A PLIP link from a Linux box is a popular means to
+ install a Linux distribution on a machine which doesn't have a
+ CD-ROM drive (a minimal system has to be transferred with floppies
+ first). The kernels on both machines need to have this PLIP option
+ enabled for this to work.
+
+ The PLIP driver has two modes, mode 0 and mode 1. The parallel
+ ports (the connectors at the computers with 25 holes) are connected
+ with "null printer" or "Turbo Laplink" cables which can transmit 4
+ bits at a time (mode 0) or with special PLIP cables, to be used on
+ bidirectional parallel ports only, which can transmit 8 bits at a
+ time (mode 1); you can find the wiring of these cables in
+ <file:Documentation/networking/PLIP.txt>. The cables can be up to
+ 15m long. Mode 0 works also if one of the machines runs DOS/Windows
+ and has some PLIP software installed, e.g. the Crynwr PLIP packet
+ driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
+ and winsock or NCSA's telnet.
+
+ If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
+ as the NET-3-HOWTO, both available from
+ <http://www.tldp.org/docs.html#howto>. Note that the PLIP
+ protocol has been changed and this PLIP driver won't work together
+ with the PLIP support in Linux versions 1.0.x. This option enlarges
+ your kernel by about 8 KB.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called plip.o. If unsure, say Y or M, in case you buy a laptop
+ later.
+
+EQL (serial line load balancing) support
+CONFIG_EQUALIZER
+ If you have two serial connections to some other computer (this
+ usually requires two modems and two telephone lines) and you use
+ SLIP (the protocol for sending Internet traffic over telephone
+ lines) or PPP (a better SLIP) on them, you can make them behave like
+ one double speed connection using this driver. Naturally, this has
+ to be supported at the other end as well, either with a similar EQL
+ Linux driver or with a Livingston Portmaster 2e.
+
+ Say Y if you want this and read
+ <file:Documentation/networking/eql.txt>. You may also want to read
+ section 6.2 of the NET-3-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called eql.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+Universal TUN/TAP device driver support
+CONFIG_TUN
+ TUN/TAP provides packet reception and transmission for user space
+ programs. It can be viewed as a simple Point-to-Point or Ethernet
+ device, which instead of receiving packets from a physical media,
+ receives them from user space program and instead of sending packets
+ via physical media writes them to the user space program.
+
+ When a program opens /dev/net/tun, driver creates and registers
+ corresponding net device tunX or tapX. After a program closed above
+ devices, driver will automatically delete tunXX or tapXX device and
+ all routes corresponding to it.
+
+ Please read <file:Documentation/networking/tuntap.txt> for more
+ information.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tun.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+ If you don't know what to use this for, you don't need it.
+
+Ethertap network tap (OBSOLETE)
+CONFIG_ETHERTAP
+ If you say Y here (and have said Y to "Kernel/User network link
+ driver", above) and create a character special file /dev/tap0 with
+ major number 36 and minor number 16 using mknod ("man mknod"), you
+ will be able to have a user space program read and write raw
+ Ethernet frames from/to that special file. tap0 can be configured
+ with ifconfig and route like any other Ethernet device but it is not
+ connected to any physical LAN; everything written by the user to
+ /dev/tap0 is treated by the kernel as if it had come in from a LAN
+ to the device tap0; everything the kernel wants to send out over the
+ device tap0 can instead be read by the user from /dev/tap0: the user
+ mode program replaces the LAN that would be attached to an ordinary
+ Ethernet device. Please read the file
+ <file:Documentation/networking/ethertap.txt> for more information.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ethertap.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+ If you don't know what to use this for, you don't need it.
+
+Sealevel Systems 4021 support
+CONFIG_SEALEVEL_4021
+ This is a driver for the Sealevel Systems ACB 56 serial I/O adapter.
+
+ This driver can only be compiled as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to do that, say M here. The module will be called
+ sealevel.o.
+
+TMPTX3912/PR31700 serial port support
+CONFIG_SERIAL_TX3912
+ The TX3912 is a Toshiba RISC processor based o the MIPS 3900 core;
+ see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>.
+ Say Y here to enable kernel support for the on-board serial port.
+
+Console on TMPTX3912/PR31700 serial port
+CONFIG_SERIAL_TX3912_CONSOLE
+ The TX3912 is a Toshiba RISC processor based o the MIPS 3900 core;
+ see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>.
+ Say Y here to direct console I/O to the on-board serial port.
+
+Enable Au1000 serial console
+CONFIG_AU1000_SERIAL_CONSOLE
+ If you have an Alchemy AU1000 processor (MIPS based) and you want
+ to use a console on a serial port, say Y. Otherwise, say N.
+
+Enable Au1000 UART Support
+CONFIG_AU1000_UART
+ If you have an Alchemy AU1000 processor (MIPS based) and you want
+ to use serial ports, say Y. Otherwise, say N.
+
+SyncLink HDLC/SYNCPPP support
+CONFIG_SYNCLINK_SYNCPPP
+ Enables HDLC/SYNCPPP support for the SyncLink WAN driver.
+ Normally the SyncLink WAN driver works with the main PPP
+ driver (ppp.c) and pppd program. HDLC/SYNCPPP support allows use
+ of the Cisco HDLC/PPP driver (syncppp.c).
+ The SyncLink WAN driver (in character devices) must also be enabled.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called syncppp.o.
+
+FarSync T-Series X.21 (and V.35/V.24) cards
+CONFIG_FARSYNC
+ This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards
+ from FarSite Communications Ltd.
+ Synchronous communication is supported on all ports at speeds up to
+ 8Mb/s (128K on V.24) using synchronous PPP or Cisco HDLC.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want)
+ say M here and read <file:Documentation/modules.txt>.
+ The module will be called farsync.o and if you want the module to be
+ automatically loaded when the interface is referenced then you
+ should add "alias syncX farsync" to /etc/modules.conf for each
+ interface, where X is 0, 1, 2, ...
+
+Frame Relay (DLCI) support
+CONFIG_DLCI
+ This is support for the frame relay protocol; frame relay is a fast
+ low-cost way to connect to a remote Internet access provider or to
+ form a private wide area network. The one physical line from your
+ box to the local "switch" (i.e. the entry point to the frame relay
+ network, usually at the phone company) can carry several logical
+ point-to-point connections to other computers connected to the frame
+ relay network. For a general explanation of the protocol, check out
+ <http://www.frforum.com/> on the WWW. To use frame relay, you need
+ supporting hardware (called FRAD) and certain programs from the
+ net-tools package as explained in
+ <file:Documentation/networking/framerelay.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dlci.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Max open DLCI
+CONFIG_DLCI_COUNT
+ This is the maximal number of logical point-to-point frame relay
+ connections (the identifiers of which are called DCLIs) that
+ the driver can handle. The default is probably fine.
+
+Max DLCI per device
+CONFIG_DLCI_MAX
+ You can specify here how many logical point-to-point frame relay
+ connections (the identifiers of which are called DCLIs) should be
+ handled by each of your hardware frame relay access devices. Go with
+ the default.
+
+SDLA (Sangoma S502/S508) support
+CONFIG_SDLA
+ Say Y here if you need a driver for the Sangoma S502A, S502E, and
+ S508 Frame Relay Access Devices. These are multi-protocol cards, but
+ only frame relay is supported by the driver at this time. Please
+ read <file:Documentation/framerelay.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called sdla.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Acorn Econet/AUN protocols
+CONFIG_ECONET
+ Econet is a fairly old and slow networking protocol mainly used by
+ Acorn computers to access file and print servers. It uses native
+ Econet network cards. AUN is an implementation of the higher level
+ parts of Econet that runs over ordinary Ethernet connections, on
+ top of the UDP packet protocol, which in turn runs on top of the
+ Internet protocol IP.
+
+ If you say Y here, you can choose with the next two options whether
+ to send Econet/AUN traffic over a UDP Ethernet connection or over
+ a native Econet network card.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called econet.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+AUN over UDP
+CONFIG_ECONET_AUNUDP
+ Say Y here if you want to send Econet/AUN traffic over a UDP
+ connection (UDP is a packet based protocol that runs on top of the
+ Internet protocol IP) using an ordinary Ethernet network card.
+
+Native Econet
+CONFIG_ECONET_NATIVE
+ Say Y here if you have a native Econet network card installed in
+ your computer.
+
+WAN router
+CONFIG_WAN_ROUTER
+ Wide Area Networks (WANs), such as X.25, frame relay and leased
+ lines, are used to interconnect Local Area Networks (LANs) over vast
+ distances with data transfer rates significantly higher than those
+ achievable with commonly used asynchronous modem connections.
+ Usually, a quite expensive external device called a `WAN router' is
+ needed to connect to a WAN.
+
+ As an alternative, WAN routing can be built into the Linux kernel.
+ With relatively inexpensive WAN interface cards available on the
+ market, a perfectly usable router can be built for less than half
+ the price of an external router. If you have one of those cards and
+ wish to use your Linux box as a WAN router, say Y here and also to
+ the WAN driver for your card, below. You will then need the
+ wan-tools package which is available from <ftp://ftp.sangoma.com/>.
+ Read <file:Documentation/networking/wan-router.txt> for more
+ information.
+
+ The WAN routing support is also available as a module called
+ wanrouter.o ( = code which can be inserted in and removed from the
+ running kernel whenever you want). If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+
+Fast switching (read help!)
+CONFIG_NET_FASTROUTE
+ Saying Y here enables direct NIC-to-NIC (NIC = Network Interface
+ Card) data transfers on the local network, which is fast.
+
+ IMPORTANT NOTE: This option is NOT COMPATIBLE with "Network packet
+ filtering" (CONFIG_NETFILTER). Say N here if you say Y there.
+
+ However, it will work with all options in the "Advanced router"
+ section (except for "Use TOS value as routing key" and
+ "Use FWMARK value as routing key").
+
+ At the moment, few devices support fast switching (tulip is one of
+ them, a modified 8390 driver can be found at
+ <ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz>).
+
+ If unsure, say N.
+
+Forwarding between high speed interfaces
+CONFIG_NET_HW_FLOWCONTROL
+ This option enables NIC (Network Interface Card) hardware throttling
+ during periods of extremal congestion. At the moment only a couple
+ of device drivers support it (really only one -- tulip, a modified
+ 8390 driver can be found at
+ <ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz>).
+
+ Really, this option is applicable to any machine attached to a fast
+ enough network, and even a 10 Mb NIC is able to kill a not very slow
+ box, such as a 120MHz Pentium.
+
+ However, do not say Y here if you did not experience any serious
+ problems.
+
+QoS and/or fair queueing
+CONFIG_NET_SCHED
+ When the kernel has several packets to send out over a network
+ device, it has to decide which ones to send first, which ones to
+ delay, and which ones to drop. This is the job of the packet
+ scheduler, and several different algorithms for how to do this
+ "fairly" have been proposed.
+
+ If you say N here, you will get the standard packet scheduler, which
+ is a FIFO (first come, first served). If you say Y here, you will be
+ able to choose from among several alternative algorithms which can
+ then be attached to different network devices. This is useful for
+ example if some of your network devices are real time devices that
+ need a certain minimum data flow rate, or if you need to limit the
+ maximum data flow rate for traffic which matches specified criteria.
+ This code is considered to be experimental.
+
+ To administer these schedulers, you'll need the user-level utilities
+ from the package iproute2+tc at <ftp://ftp.inr.ac.ru/ip-routing/>.
+ That package also contains some documentation; for more, check out
+ <http://snafu.freedom.org/linux2.2/iproute-notes.html>.
+
+ This Quality of Service (QoS) support will enable you to use
+ Differentiated Services (diffserv) and Resource Reservation Protocol
+ (RSVP) on your Linux router if you also say Y to "QoS support",
+ "Packet classifier API" and to some classifiers below. Documentation
+ and software is at <http://icawww1.epfl.ch/linux-diffserv/>.
+
+ If you say Y here and to "/proc file system" below, you will be able
+ to read status information about packet schedulers from the file
+ /proc/net/psched.
+
+ The available schedulers are listed in the following questions; you
+ can say Y to as many as you like. If unsure, say N now.
+
+CBQ packet scheduler
+CONFIG_NET_SCH_CBQ
+ Say Y here if you want to use the Class-Based Queueing (CBQ) packet
+ scheduling algorithm for some of your network devices. This
+ algorithm classifies the waiting packets into a tree-like hierarchy
+ of classes; the leaves of this tree are in turn scheduled by
+ separate algorithms (called "disciplines" in this context).
+
+ See the top of <file:net/sched/sch_cbq.c> for references about the
+ CBQ algorithm.
+
+ CBQ is a commonly used scheduler, so if you're unsure, you should
+ say Y here. Then say Y to all the queueing algorithms below that you
+ want to use as CBQ disciplines. Then say Y to "Packet classifier
+ API" and say Y to all the classifiers you want to use; a classifier
+ is a routine that allows you to sort your outgoing traffic into
+ classes based on a certain criterion.
+
+ This code is also available as a module called sch_cbq.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+CONFIG_NET_SCH_HTB
+ Say Y here if you want to use the Hierarchical Token Buckets (HTB)
+ packet scheduling algorithm for some of your network devices. See
+ URL <http://luxik.cdi.cz/~devik/qos/htb/> for complete manual and
+ in-depth articles.
+
+ HTB is very similar to the CBQ regarding its goals however is has
+ different properties and different algorithm.
+
+ This code is also available as a module called sch_htb.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+CSZ packet scheduler
+CONFIG_NET_SCH_CSZ
+ Say Y here if you want to use the Clark-Shenker-Zhang (CSZ) packet
+ scheduling algorithm for some of your network devices. At the
+ moment, this is the only algorithm that can guarantee service for
+ real-time applications (see the top of <file:net/sched/sch_csz.c>
+ for details and references about the algorithm).
+
+ Note: this scheduler is currently broken.
+
+ This code is also available as a module called sch_csz.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+ATM pseudo-scheduler
+CONFIG_NET_SCH_ATM
+ Say Y here if you want to use the ATM pseudo-scheduler. This
+ provides a framework for invoking classifiers (aka "filters"), which
+ in turn select classes of this queuing discipline. Each class maps
+ the flow(s) it is handling to a given virtual circuit (see the top of
+ <file:net/sched/sch_atm.c>).
+
+ This code is also available as a module called sch_atm.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+The simplest PRIO pseudo-scheduler
+CONFIG_NET_SCH_PRIO
+ Say Y here if you want to use an n-band priority queue packet
+ "scheduler" for some of your network devices or as a leaf discipline
+ for the CBQ scheduling algorithm. If unsure, say Y.
+
+ This code is also available as a module called sch_prio.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Diffserv field marker
+CONFIG_NET_SCH_DSMARK
+ Say Y if you want to schedule packets according to the
+ Differentiated Services architecture proposed in RFC 2475.
+ Technical information on this method, with pointers to associated
+ RFCs, is available at <http://www.gta.ufrj.br/diffserv/>.
+
+ This code is also available as a module called sch_dsmark.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+GRED queue
+CONFIG_NET_SCH_GRED
+ Say Y here if you want to use the Generic Random Early Detection
+ (RED) packet scheduling algorithm for some of your network devices
+ (see the top of <file:net/sched/sch_red.c> for details and
+ references about the algorithm).
+
+ This code is also available as a module called sch_gred.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+RED queue
+CONFIG_NET_SCH_RED
+ Say Y here if you want to use the Random Early Detection (RED)
+ packet scheduling algorithm for some of your network devices (see
+ the top of <file:net/sched/sch_red.c> for details and references
+ about the algorithm).
+
+ This code is also available as a module called sch_red.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+SFQ queue
+CONFIG_NET_SCH_SFQ
+ Say Y here if you want to use the Stochastic Fairness Queueing (SFQ)
+ packet scheduling algorithm for some of your network devices or as a
+ leaf discipline for the CBQ scheduling algorithm (see the top of
+ <file:net/sched/sch_sfq.c> for details and references about the SFQ
+ algorithm).
+
+ This code is also available as a module called sch_sfq.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+ESFQ queue
+CONFIG_NET_SCH_ESFQ
+ Say Y here if you want to use the Stochastic Fairness Queueing (SFQ)
+ packet scheduling algorithm for some of your network devices or as a
+ leaf discipline for the CBQ scheduling algorithm (see the top of
+ <file:net/sched/sch_esfq.c> for details and references about the SFQ
+ algorithm).
+
+ This is an enchanced SFQ version which allows you to control the
+ hardcoded values in the SFQ scheduler: queue depth, hash table size,
+ queues limit. Also adds control to the hash function used to identify
+ packet flows. Hash by src or dst ip and original sfq hash.
+
+ This code is also available as a module called sch_esfq.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+TEQL queue
+CONFIG_NET_SCH_TEQL
+ Say Y here if you want to use the True Link Equalizer (TLE) packet
+ scheduling algorithm for some of your network devices or as a leaf
+ discipline for the CBQ scheduling algorithm. This queueing
+ discipline allows the combination of several physical devices into
+ one virtual device. (see the top of <file:net/sched/sch_teql.c> for
+ details).
+
+ This code is also available as a module called sch_teql.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+TBF queue
+CONFIG_NET_SCH_TBF
+ Say Y here if you want to use the Simple Token Bucket Filter (TBF)
+ packet scheduling algorithm for some of your network devices or as a
+ leaf discipline for the CBQ scheduling algorithm (see the top of
+ <file:net/sched/sch_tbf.c> for a description of the TBF algorithm).
+
+ This code is also available as a module called sch_tbf.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Ingress Qdisc
+CONFIG_NET_SCH_INGRESS
+ If you say Y here, you will be able to police incoming bandwidth
+ and drop packets when this bandwidth exceeds your desired rate.
+ If unsure, say Y.
+
+ This code is also available as a module called cls_ingress.o
+ ( = code which can be inserted in and removed from the running
+ kernel whenever you want). If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+QoS support
+CONFIG_NET_QOS
+ Say Y here if you want to include Quality Of Service scheduling
+ features, which means that you will be able to request certain
+ rate-of-flow limits for your network devices.
+
+ This Quality of Service (QoS) support will enable you to use
+ Differentiated Services (diffserv) and Resource Reservation Protocol
+ (RSVP) on your Linux router if you also say Y to "Packet classifier
+ API" and to some classifiers below. Documentation and software is at
+ <http://icawww1.epfl.ch/linux-diffserv/>.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about QoS support.
+
+Rate estimator
+CONFIG_NET_ESTIMATOR
+ In order for Quality of Service scheduling to work, the current
+ rate-of-flow for a network device has to be estimated; if you say Y
+ here, the kernel will do just that.
+
+Packet classifier API
+CONFIG_NET_CLS
+ The CBQ scheduling algorithm requires that network packets which are
+ scheduled to be sent out over a network device be classified
+ according to some criterion. If you say Y here, you will get a
+ choice of several different packet classifiers with the following
+ questions.
+
+ This will enable you to use Differentiated Services (diffserv) and
+ Resource Reservation Protocol (RSVP) on your Linux router.
+ Documentation and software is at
+ <http://icawww1.epfl.ch/linux-diffserv/>.
+
+Traffic policing (needed for in/egress)
+CONFIG_NET_CLS_POLICE
+ Say Y to support traffic policing (bandwidth limits). Needed for
+ ingress and egress rate limiting.
+
+TC index classifier
+CONFIG_NET_CLS_TCINDEX
+ If you say Y here, you will be able to classify outgoing packets
+ according to the tc_index field of the skb. You will want this
+ feature if you want to implement Differentiated Services using
+ sch_dsmark. If unsure, say Y.
+
+ This code is also available as a module called cls_tcindex.o
+ ( = code which can be inserted in and removed from the running
+ kernel whenever you want). If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+Routing tables based classifier
+CONFIG_NET_CLS_ROUTE4
+ If you say Y here, you will be able to classify outgoing packets
+ according to the route table entry they matched. If unsure, say Y.
+
+ This code is also available as a module called cls_route.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Firewall based classifier
+CONFIG_NET_CLS_FW
+ If you say Y here, you will be able to classify outgoing packets
+ according to firewall criteria you specified.
+
+ This code is also available as a module called cls_fw.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+U32 classifier
+CONFIG_NET_CLS_U32
+ If you say Y here, you will be able to classify outgoing packets
+ according to their destination address. If unsure, say Y.
+
+ This code is also available as a module called cls_u32.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Special RSVP classifier
+CONFIG_NET_CLS_RSVP
+ The Resource Reservation Protocol (RSVP) permits end systems to
+ request a minimum and maximum data flow rate for a connection; this
+ is important for real time data such as streaming sound or video.
+
+ Say Y here if you want to be able to classify outgoing packets based
+ on their RSVP requests.
+
+ This code is also available as a module called cls_rsvp.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Special RSVP classifier for IPv6
+CONFIG_NET_CLS_RSVP6
+ The Resource Reservation Protocol (RSVP) permits end systems to
+ request a minimum and maximum data flow rate for a connection; this
+ is important for real time data such as streaming sound or video.
+
+ Say Y here if you want to be able to classify outgoing packets based
+ on their RSVP requests and you are using the new Internet Protocol
+ IPv6 as opposed to the older and more common IPv4.
+
+ This code is also available as a module called cls_rsvp6.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Network code profiler
+CONFIG_NET_PROFILE
+ If you say Y here and to "/proc file system support" below, some
+ obscure and undocumented information about the network code's
+ performance will be written to /proc/net/profile. If you don't know
+ what it is about, you don't need it: say N.
+
+Network packet generator
+CONFIG_NET_PKTGEN
+ This module will inject preconfigured packets, at a configurable
+ rate, out of a given interface. It is used for network interface
+ stress testing and performance analysis. If you don't understand
+ what was just said, you don't need it: say N.
+
+ Documentation on how to use the packet generator can be found
+ at <file:Documentation/networking/pktgen.txt>.
+
+ This code is also available as a module called pktgen.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Wan interfaces support
+CONFIG_WAN
+ Wide Area Networks (WANs), such as X.25, frame relay and leased
+ lines, are used to interconnect Local Area Networks (LANs) over vast
+ distances with data transfer rates significantly higher than those
+ achievable with commonly used asynchronous modem connections.
+ Usually, a quite expensive external device called a `WAN router' is
+ needed to connect to a WAN.
+
+ As an alternative, a relatively inexpensive WAN interface card can
+ allow your Linux box to directly connect to a WAN. If you have one
+ of those cards and wish to use it under Linux, say Y here and also
+ to the WAN driver for your card, below.
+
+ If unsure, say N.
+
+Comtrol Hostess SV-11 support
+CONFIG_HOSTESS_SV11
+ This is a network card for low speed synchronous serial links, at
+ up to 256Kbps. It supports both PPP and Cisco HDLC.
+
+ At this point, the driver can only be compiled as a module.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called hostess_sv11.o.
+
+COSA/SRP sync serial board support
+CONFIG_COSA
+ This is a driver for COSA and SRP synchronous serial boards. These
+ boards allow to connect synchronous serial devices (for example
+ base-band modems, or any other device with the X.21, V.24, V.35 or
+ V.36 interface) to your Linux box. The cards can work as the
+ character device, synchronous PPP network device, or the Cisco HDLC
+ network device.
+
+ To actually use the COSA or SRP board, you will need user-space
+ utilities for downloading the firmware to the cards and to set them
+ up. Look at the <http://www.fi.muni.cz/~kas/cosa/> for more
+ information about the cards (including the pointer to the user-space
+ utilities). You can also read the comment at the top of the
+ <file:drivers/net/wan/cosa.c> for details about the cards and the driver
+ itself.
+
+ The driver will be compiled as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called cosa.o. For general information about
+ modules read <file:Documentation/modules.txt>.
+
+Etinc PCISYNC serial board support
+CONFIG_DSCC4
+ This is a driver for Etinc PCISYNC boards based on the Infineon
+ (ex. Siemens) DSCC4 chipset. It is supposed to work with the four
+ ports card. Take a look at <http://www.cogenit.fr/dscc4/>
+ for further informations about the driver and his configuration.
+
+ The driver will be compiled as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dscc4.o. For general information about
+ modules read <file:Documentation/modules.txt>.
+
+LanMedia Corp. serial boards (SSI/V.35, T1/E1, HSSI, T3)
+CONFIG_LANMEDIA
+ This is a driver for the following Lan Media family of serial
+ boards.
+
+ LMC 1000 board allows you to connect synchronous serial devices (for
+ example base-band modems, or any other device with the X.21, V.24,
+ V.35 or V.36 interface) to your Linux box.
+
+ LMC 1200 with on board DSU board allows you to connect your Linux
+ box directly to a T1 or E1 circuit.
+
+ LMC 5200 board provides a HSSI interface capable of running up to
+ 52 mbits per second.
+
+ LMC 5245 board connects directly to a T3 circuit saving the
+ additional external hardware.
+
+ To change setting such as syncPPP vs cisco HDLC or clock source you
+ will need lmcctl. It is available at <ftp://ftp.lanmedia.com/>.
+
+ This code is also available as a module called lmc.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Fibre Channel driver support
+CONFIG_NET_FC
+ Fibre Channel is a high speed serial protocol mainly used to connect
+ large storage devices to the computer; it is compatible with and
+ intended to replace SCSI.
+
+ If you intend to use Fibre Channel, you need to have a Fibre channel
+ adaptor card in your computer; say Y here and to the driver for your
+ adaptor below. You also should have said Y to "SCSI support" and
+ "SCSI generic support".
+
+Interphase 5526 Tachyon chipset based adaptor support
+CONFIG_IPHASE5526
+ Say Y here if you have a Fibre Channel adaptor of this kind.
+
+ The driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called iph5526.o. For general information about
+ modules read <file:Documentation/modules.txt>.
+
+Red Creek Hardware VPN
+CONFIG_RCPCI
+ This is a driver for hardware which provides a Virtual Private
+ Network (VPN). Say Y if you have it.
+
+ This code is also available as a module called rcpci.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Granch SBNI12 Leased Line adapter driver
+CONFIG_SBNI
+ This is a driver for ISA SBNI12-xx cards which are low cost
+ alternatives to leased line modems. Say Y if you want to insert
+ the driver into the kernel or say M to compile it as a module (the
+ module will be called sbni.o).
+
+ You can find more information and last versions of drivers and
+ utilities at <http://www.granch.ru/>. If you have any question you
+ can send email to sbni@granch.ru.
+
+ Say N if unsure.
+
+SBNI multiple-line feature support
+CONFIG_SBNI_MULTILINE
+ Schedule traffic for some parallel lines, via SBNI12 adapters.
+ If you have two computers connected with two parallel lines it's
+ possible to increase transfer rate nearly twice. You should have
+ a program named 'sbniconfig' to configure adapters.
+
+ Say N if unsure.
+
+WAN router drivers
+CONFIG_WAN_ROUTER_DRIVERS
+ If you have a WAN interface card and you want your Linux box to act
+ as a WAN router, thereby connecting you Local Area Network to the
+ outside world over the WAN connection, say Y here and then to the
+ driver for your card below. In addition, you need to say Y to "Wan
+ Router".
+
+ You will need the wan-tools package which is available from
+ <ftp://ftp.sangoma.com/>. Read
+ <file:Documentation/networking/wan-router.txt> for more information.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about WAN router drivers. If unsure, say N.
+
+Sangoma WANPIPE(tm) multiprotocol cards
+CONFIG_VENDOR_SANGOMA
+ WANPIPE from Sangoma Technologies Inc. (<http://www.sangoma.com/>)
+ is a family of intelligent multiprotocol WAN adapters with data
+ transfer rates up to 4Mbps. They are also known as Synchronous
+ Data Link Adapters (SDLA) and are designated as S514-PCI or
+ S508-ISA. These cards support
+
+ - X.25, Frame Relay, PPP, Cisco HDLC protocols.
+
+ - API support for protocols like HDLC (LAPB),
+ HDLC Streaming, X.25, Frame Relay and BiSync.
+
+ - Ethernet Bridging over Frame Relay protocol.
+
+ - MULTILINK PPP
+
+ - Async PPP (Modem Dialup)
+
+ If you have one or more of these cards, say M to this option; you
+ may then also want to read the file
+ <file:Documentation/networking/wanpipe.txt>. The next questions
+ will ask you about the protocols you want the driver to support.
+
+ The driver will be compiled as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called wanpipe.o. For general information about
+ modules read <file:Documentation/modules.txt>.
+
+WANPIPE X.25 support
+CONFIG_WANPIPE_X25
+ Say Y to this option if you are planning to connect a WANPIPE card
+ to an X.25 network. Note, this feature also includes the X.25 API
+ support used to develop custom applications over the X.25 protocol.
+ If you say N, the X.25 support will not be included in the driver.
+ The X.25 option is supported on S514-PCI and S508-ISA cards.
+
+WANPIPE Frame Relay support
+CONFIG_WANPIPE_FR
+ Say Y to this option if you are planning to connect a WANPIPE card
+ to a frame relay network, or use frame relay API to develop
+ custom applications over the Frame Relay protocol.
+ This feature also contains the Ethernet Bridging over Frame Relay,
+ where a WANPIPE frame relay link can be directly connected to the
+ Linux kernel bridge. If you say N, the frame relay support will
+ not be included in the driver. The Frame Relay option is
+ supported on S514-PCI and S508-ISA cards.
+
+WANPIPE PPP support
+CONFIG_WANPIPE_PPP
+ Say Y to this option if you are planning to connect a WANPIPE card
+ to a leased line using Point-to-Point protocol (PPP). If you say N,
+ the PPP support will not be included in the driver. The PPP option
+ is supported on S514-PCI/S508-ISA cards.
+
+WANPIPE Multi-Port PPP support
+CONFIG_WANPIPE_MULTPPP
+ Say Y to this option if you are planning to connect a WANPIPE card
+ to a leased line using Point-to-Point protocol (PPP). Note, the
+ MultiPort PPP uses the Linux Kernel SyncPPP protocol over the
+ Sangoma HDLC Streaming adapter. In this case each Sangoma adapter
+ port can support an independent PPP connection. For example, a
+ single Quad-Port PCI adapter can support up to four independent
+ PPP links. If you say N,the PPP support will not be included in the
+ driver. The PPP option is supported on S514-PCI/S508-ISA cards.
+
+WANPIPE Cisco HDLC support
+CONFIG_WANPIPE_CHDLC
+ Say Y to this option if you are planning to connect a WANPIPE card
+ to a leased line using the Cisco HDLC protocol. This now supports
+ Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards.
+ This support also allows user to build applications using the
+ HDLC streaming API.
+
+ CHDLC Streaming driver also supports MULTILINK PPP
+ support that can bind multiple WANPIPE T1 cards into
+ a single logical channel.
+
+ If you say N, the Cisco HDLC support and
+ HDLC streaming API and MULTILINK PPP will not be
+ included in the driver.
+
+MultiGate (COMX) synchronous serial board support
+CONFIG_COMX
+ Say Y if you want to use any board from the MultiGate (COMX) family.
+ These boards are synchronous serial adapters for the PC,
+ manufactured by ITConsult-Pro Co, Hungary.
+
+ Read <file:Documentation/networking/comx.txt> for help on
+ configuring and using COMX interfaces. Further info on these cards
+ can be found at <http://www.itc.hu/> or <info@itc.hu>.
+
+ You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
+ use this driver.
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called comx.o.
+
+Support for COMX/CMX/HiCOMX boards
+CONFIG_COMX_HW_COMX
+ Hardware driver for the 'CMX', 'COMX' and 'HiCOMX' boards from the
+ MultiGate family. Say Y if you have one of these.
+
+ You will need additional firmware to use these cards, which are
+ downloadable from <ftp://ftp.itc.hu/>.
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called
+ comx-hw-comx.o.
+
+Support for LoCOMX board
+CONFIG_COMX_HW_LOCOMX
+ Hardware driver for the 'LoCOMX' board from the MultiGate family.
+ Say Y if you have a board like this.
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called
+ comx-hw-locomx.o.
+
+Support for MixCOM board
+CONFIG_COMX_HW_MIXCOM
+ Hardware driver for the 'MixCOM' board from the MultiGate family.
+ Say Y if you have a board like this.
+
+ If you want to use the watchdog device on this card, you should
+ select it in the Watchdog Cards section of the Character Devices
+ configuration. The ISDN interface of this card is Teles 16.3
+ compatible, you should enable it in the ISDN configuration menu. The
+ driver for the flash ROM of this card is available separately on
+ <ftp://ftp.itc.hu/>.
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called
+ comx-hw-mixcom.o.
+
+i810 TCO timer/watchdog support
+CONFIG_I810_TCO
+ Hardware driver for the TCO timer built into the Intel i810 and i815
+ chipset family. The TCO (Total Cost of Ownership) timer is a
+ watchdog timer that will reboot the machine after its second
+ expiration. The expiration time can be configured by command
+ argument "i810_margin=<n>" where <n> is the counter initial value.
+ It is decremented every 0.6 secs, the default is 50 which gives a
+ timeout of 30 seconds and one minute until reset.
+
+ On some motherboards the driver may fail to reset the chipset's
+ NO_REBOOT flag which prevents the watchdog from rebooting the
+ machine. If this is the case you will get a kernel message like
+ "i810tco init: failed to reset NO_REBOOT flag".
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called
+ i810-tco.o.
+
+SliceCOM/PciCOM board support
+CONFIG_COMX_HW_MUNICH
+ Hardware driver for the 'SliceCOM' (channelized E1) and 'PciCOM'
+ boards (X21) from the MultiGate family.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called comx-hw-munich.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+ Read linux/Documentation/networking/slicecom.txt for help on
+ configuring and using SliceCOM interfaces. Further info on these cards
+ can be found at <http://www.itc.hu> or <info@itc.hu>.
+
+Support for HDLC and syncPPP protocols on MultiGate boards
+CONFIG_COMX_PROTO_PPP
+ Cisco-HDLC and synchronous PPP protocol driver for all MultiGate
+ boards. Say Y if you want to use either protocol on your MultiGate
+ boards.
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called
+ comx-proto-ppp.o.
+
+Support for LAPB protocol on MultiGate boards
+CONFIG_COMX_PROTO_LAPB
+ LAPB protocol driver for all MultiGate boards. Say Y if you
+ want to use this protocol on your MultiGate boards.
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called
+ comx-proto-lapb.o.
+
+Support for Frame Relay on MultiGate boards
+CONFIG_COMX_PROTO_FR
+ Frame Relay protocol driver for all MultiGate boards. Say Y if you
+ want to use this protocol on your MultiGate boards.
+
+ If you want to compile this as a module, say M and read
+ <file:Documentation/modules.txt>. The module will be called
+ comx-proto-fr.o.
+
+Cyclom 2X(tm) multiprotocol cards
+CONFIG_CYCLADES_SYNC
+ Cyclom 2X from Cyclades Corporation (<http://www.cyclades.com/> and
+ <http://www.cyclades.com.br/>) is an intelligent multiprotocol WAN
+ adapter with data transfer rates up to 512 Kbps. These cards support
+ the X.25 and SNA related protocols. If you have one or more of these
+ cards, say Y to this option. The next questions will ask you about
+ the protocols you want the driver to support (for now only X.25 is
+ supported).
+
+ While no documentation is available at this time please grab the
+ wanconfig tarball in
+ <http://www.conectiva.com.br/~acme/cycsyn-devel/> (with minor changes
+ to make it compile with the current wanrouter include files; efforts
+ are being made to use the original package available at
+ <ftp://ftp.sangoma.com/>).
+
+ Feel free to contact me or the cycsyn-devel mailing list at
+ acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for
+ additional details, I hope to have documentation available as soon
+ as possible. (Cyclades Brazil is writing the Documentation).
+
+ The driver will be compiled as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called cyclomx.o. For general information about
+ modules read <file:Documentation/modules.txt>.
+
+Cyclom 2X X.25 support
+CONFIG_CYCLOMX_X25
+ Say Y to this option if you are planning to connect a Cyclom 2X card
+ to an X.25 network.
+
+ If you say N, the X.25 support will not be included in the driver
+ (saves about 11 KB of kernel memory).
+
+Generic HDLC driver
+CONFIG_HDLC
+ Say Y to this option if your Linux box contains a WAN card supported
+ by this driver and you are planning to connect the box to a WAN
+ ( = Wide Area Network). You will need supporting software from
+ <http://hq.pm.waw.pl/hdlc/>.
+ Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame
+ Relay, synchronous Point-to-Point Protocol (PPP) and X.25.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called hdlc.o.
+
+ If unsure, say N here.
+
+Raw HDLC support
+CONFIG_HDLC_RAW
+ Say Y to this option if you want generic HDLC driver to support
+ raw HDLC over WAN (Wide Area Network) connections.
+
+ If unsure, say N here.
+
+Cisco HDLC support
+CONFIG_HDLC_CISCO
+ Say Y to this option if you want generic HDLC driver to support
+ Cisco HDLC over WAN (Wide Area Network) connections.
+
+ If unsure, say N here.
+
+Frame-Relay HDLC support
+CONFIG_HDLC_FR
+ Say Y to this option if you want generic HDLC driver to support
+ Frame-Relay protocol over WAN (Wide Area Network) connections.
+
+ If unsure, say N here.
+
+Frame-Relay bridging support
+CONFIG_HDLC_FR_BRIDGE
+ Say Y to this option if you want generic HDLC driver to support
+ bridging LAN frames over Frame-Relay links.
+
+ If unsure, say N here.
+
+Synchronous Point-to-Point Protocol (PPP) support
+CONFIG_HDLC_PPP
+ Say Y to this option if you want generic HDLC driver to support
+ PPP over WAN (Wide Area Network) connections.
+
+ If unsure, say N here.
+
+CCITT X.25 over HDLC support
+CONFIG_HDLC_X25
+ Say Y to this option if you want generic HDLC driver to support
+ X.25 protocol over WAN (Wide Area Network) connections.
+
+ If unsure, say N here.
+
+SDL RISCom/N2 support
+CONFIG_N2
+ This driver is for RISCom/N2 single or dual channel ISA cards
+ made by SDL Communications Inc. If you have such a card,
+ say Y here and see <http://hq.pm.waw.pl/pub/hdlc/>.
+
+ Note that N2csu and N2dds cards are not supported by this driver.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called n2.o.
+
+ If unsure, say N here.
+
+Moxa C101 support
+CONFIG_C101
+ This driver is for C101 SuperSync ISA cards made by Moxa
+ Technologies Co., Ltd. If you have such a card,
+ say Y here and see <http://hq.pm.waw.pl/pub/hdlc/>
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called c101.o.
+
+ If unsure, say N here.
+
+Ethernet (10 or 100Mbit)
+CONFIG_NET_ETHERNET
+ Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
+ type of Local Area Network (LAN) in universities and companies.
+
+ Common varieties of Ethernet are: 10BASE-2 or Thinnet (10 Mbps over
+ coaxial cable, linking computers in a chain), 10BASE-T or twisted
+ pair (10 Mbps over twisted pair cable, linking computers to central
+ hubs), 10BASE-F (10 Mbps over optical fiber links, using hubs),
+ 100BASE-TX (100 Mbps over two twisted pair cables, using hubs),
+ 100BASE-T4 (100 Mbps over 4 standard voice-grade twisted pair
+ cables, using hubs), 100BASE-FX (100 Mbps over optical fiber links)
+ [the 100BASE varieties are also known as Fast Ethernet], and Gigabit
+ Ethernet (1 Gbps over optical fiber or short copper links).
+
+ If your Linux machine will be connected to an Ethernet and you have
+ an Ethernet network interface card (NIC) installed in your computer,
+ say Y here and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. You will then also have
+ to say Y to the driver for your particular NIC.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Ethernet network cards. If unsure, say N.
+
+Western Digital/SMC cards
+CONFIG_NET_VENDOR_SMC
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Western Digital cards. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+WD80*3 support
+CONFIG_WD80x3
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called wd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+SMC Ultra MCA support
+CONFIG_ULTRAMCA
+ If you have a network (Ethernet) card of this type and are running
+ an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc-mca.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+SMC Ultra support
+CONFIG_ULTRA
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Important: There have been many reports that, with some motherboards
+ mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
+ such as some BusLogic models) causes corruption problems with many
+ operating systems. The Linux smc-ultra driver has a work-around for
+ this but keep it in mind if you have such a SCSI card and have
+ problems.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc-ultra.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt> as
+ well as <file:Documentation/networking/net-modules.txt>.
+
+SMC Ultra32 EISA support
+CONFIG_ULTRA32
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc-ultra32.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt> as
+ well as <file:Documentation/networking/net-modules.txt>.
+
+SMC 9194 support
+CONFIG_SMC9194
+ This is support for the SMC9xxx based Ethernet cards. Choose this
+ option if you have a DELL laptop with the docking station, or
+ another SMC9192/9194 based chipset. Say Y if you want it compiled
+ into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smc9194.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+PCI NE2000 and clones support
+CONFIG_NE2K_PCI
+ This driver is for NE2000 compatible PCI cards. It will not work
+ with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
+ support" below). If you have a PCI NE2000 network (Ethernet) card,
+ say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver also works for the following NE2000 clone cards:
+ RealTek RTL-8029 Winbond 89C940 Compex RL2000 KTI ET32P2
+ NetVin NV5000SC Via 86C926 SureCom NE34 Winbond
+ Holtek HT80232 Holtek HT80229
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ne2k-pci.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt> as
+ well as <file:Documentation/networking/net-modules.txt>.
+
+Racal-Interlan (Micom) NI cards
+CONFIG_NET_VENDOR_RACAL
+ If you have a network (Ethernet) card belonging to this class, such
+ as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about NI cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+NI5010 support
+CONFIG_NI5010
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that this is still
+ experimental code.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ni5010.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+NI5210 support
+CONFIG_NI52
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ni52.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+NI6510 support
+CONFIG_NI65
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ni65.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+RealTek RTL-8139C+ 10/100 PCI Fast Ethernet Adapter support
+CONFIG_8139CP
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the RTL8139C+ chips. If you have one of those, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read Documentation/modules.txt. This is recommended.
+ The module will be called 8139cp.o.
+
+RealTek RTL-8139 PCI Fast Ethernet Adapter support
+CONFIG_8139TOO
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the RTL8139 chips. If you have one of those, say Y and read
+ <file:Documentation/networking/8139too.txt> as well as the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called 8139too.o.
+
+Use PIO instead of MMIO
+CONFIG_8139TOO_PIO
+ This instructs the driver to use programmed I/O ports (PIO) instead
+ of PCI shared memory (MMIO). This can possibly solve some problems
+ in case your mainboard has memory consistency issues. If unsure,
+ say N.
+
+Support for uncommon RTL-8139 rev. K (automatic channel equalization)
+CONFIG_8139TOO_TUNE_TWISTER
+ This implements a function which might come in handy in case you
+ are using low quality on long cabling. It is required for RealTek
+ RTL-8139 revision K boards, and totally unused otherwise. It tries
+ to match the transceiver to the cable characteristics. This is
+ experimental since hardly documented by the manufacturer.
+ If unsure, say Y.
+
+Support for older RTL-8129/8130 boards
+CONFIG_8139TOO_8129
+ This enables support for the older and uncommon RTL-8129 and
+ RTL-8130 chips, which support MII via an external transceiver,
+ instead of an internal one. Disabling this option will save some
+ memory by making the code size smaller. If unsure, say Y.
+
+Use older RX-reset method
+CONFIG_8139_OLD_RX_RESET
+ The 8139too driver was recently updated to contain a more rapid
+ reset sequence, in the face of severe receive errors. This "new"
+ RX-reset method should be adequate for all boards. But if you
+ experience problems, you can enable this option to restore the
+ old RX-reset behavior. If unsure, say N.
+
+SiS 900/7016 PCI Fast Ethernet Adapter support
+CONFIG_SIS900
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
+ SiS 630 and SiS 540 chipsets. If you have one of those, say Y and
+ read the Ethernet-HOWTO, available at
+ <http://www.tldp.org/docs.html#howto>. Please read
+ <file:Documentation/networking/sis900.txt> and comments at the
+ beginning of <file:drivers/net/sis900.c> for more information.
+
+ This driver also supports AMD 79C901 HomePNA so that you can use
+ your phone line as a network cable.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called sis900.o.
+
+Packet Engines Yellowfin Gigabit-NIC / Symbios 53c885 support
+CONFIG_YELLOWFIN
+ Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
+ adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is
+ used by the Beowulf Linux cluster project. See
+ <http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html> for more
+ information about this driver in particular and Beowulf in general.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called yellowfin.o.
+
+General Instruments Surfboard 1000
+CONFIG_NET_SB1000
+ This is a driver for the General Instrument (also known as
+ NextLevel) SURFboard 1000 internal
+ cable modem. This is an ISA card which is used by a number of cable
+ TV companies to provide cable modem access. It's a one-way
+ downstream-only cable modem, meaning that your upstream net link is
+ provided by your regular phone modem.
+
+ At present this driver only compiles as a module, so say M here if
+ you have this card. The module will be called sb1000.o. Then read
+ <file:Documentation/networking/README.sb1000> for information on how
+ to use this module, as it needs special ppp scripts for establishing
+ a connection. Further documentation and the necessary scripts can be
+ found at:
+
+ <http://www.jacksonville.net/~fventuri/>
+ <http://home.adelphia.net/~siglercm/sb1000.html>
+ <http://linuxpower.cx/~cable/>
+
+ If you don't have this card, of course say N.
+
+Adaptec Starfire support
+CONFIG_ADAPTEC_STARFIRE
+ Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
+ adapter. The DuraLAN chip is used on the 64 bit PCI boards from
+ Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip
+ driver.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called starfire.o.
+
+Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support
+CONFIG_ACENIC
+ Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
+ GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
+ adapter. The driver allows for using the Jumbo Frame option (9000
+ bytes/frame) however it requires that your switches can handle this
+ as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
+ line.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called acenic.o.
+
+Omit support for old Tigon I based AceNICs
+CONFIG_ACENIC_OMIT_TIGON_I
+ Say Y here if you only have Tigon II based AceNICs and want to leave
+ out support for the older Tigon I based cards which are no longer
+ being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
+ version)). This will reduce the size of the driver object by
+ app. 100KB. If you are not sure whether your card is a Tigon I or a
+ Tigon II, say N here.
+
+ The safe and default value for this is N.
+
+SysKonnect SK-98xx support
+CONFIG_SK98LIN
+ Say Y here if you have a SysKonnect SK-98xx Gigabit Ethernet Server
+ Adapter. The following adapters are supported by this driver:
+ - SK-9841 (single link 1000Base-LX)
+ - SK-9842 (dual link 1000Base-LX)
+ - SK-9843 (single link 1000Base-SX)
+ - SK-9844 (dual link 1000Base-SX)
+ - SK-9821 (single link 1000Base-T)
+ - SK-9822 (dual link 1000Base-T)
+ - SK-9861 (single link Volition connector)
+ - SK-9862 (dual link Volition connector)
+ The driver also supports the following adapters from Allied Telesyn:
+ - AT2970...
+
+ The dual link adapters support a link-failover feature. Read
+ <file:Documentation/networking/sk98lin.txt> for information about
+ optional driver parameters.
+ Questions concerning this driver may be addressed to:
+ linux@syskonnect.de
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called sk98lin.o.
+
+Sun GEM support
+CONFIG_SUNGEM
+ Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
+ <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
+
+ This chip is also used by Apple under the name GMAC in all their recent
+ machines starting with the first iBook. This includes all AGP capable
+ Apple machines except some early G4s and iMacs that still used a
+ Tulip chip. This driver obsoletes the GMAC driver for these machines.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called sungem.o.
+
+Broadcom Tigon3 support
+CONFIG_TIGON3
+ This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called tg3.o.
+
+MyriCOM Gigabit Ethernet support
+CONFIG_MYRI_SBUS
+ This driver supports MyriCOM Sbus gigabit Ethernet cards.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called myri_sbus.o.
+
+D-Link 2000-based Gigabit Ethernet support
+CONFIG_DL2K
+ This driver supports D-Link 2000-based gigabit ethernet cards, which
+ includes
+ D-Link DGE-550T Gigabit Ethernet Adapter.
+ D-Link DL2000-based Gigabit Ethernet Adapter.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called dl2k.o.
+
+EtherExpress Pro/100 support (e100, Alternate Intel driver)
+CONFIG_E100
+ This driver supports Intel(R) PRO/100 family of adapters, which
+ includes:
+
+ Controller Adapter Name Board IDs
+ ---------- ------------ ---------
+
+ 82558 PRO/100+ PCI Adapter 668081-xxx,
+ 689661-xxx
+ 82558 PRO/100+ Management Adapter 691334-xxx,
+ 701738-xxx,
+ 721383-xxx
+ 82558 PRO/100+ Dual Port Server Adapter 714303-xxx,
+ 711269-xxx,
+ A28276-xxx
+ 82558 PRO/100+ PCI Server Adapter 710550-xxx
+ 82550 PRO/100 S Server Adapter 752438-xxx
+ 82559 A56831-xxx,
+ A10563-xxx,
+ A12171-xxx,
+ A12321-xxx,
+ A12320-xxx,
+ A12170-xxx
+ 748568-xxx
+ 748565-xxx
+ 82550 PRO/100 S Desktop Adapter 751767-xxx
+ 82559 748592-xxx,
+ A12167-xxx,
+ A12318-xxx,
+ A12317-xxx,
+ A12165-xxx,
+ 748569-xxx
+ 82559 PRO/100+ Server Adapter 729757-xxx
+ 82559 PRO/100 S Management Adapter 748566-xxx,
+ 748564-xxx
+ 82550 PRO/100 S Dual Port Server Adapter A56831-xxx
+ 82551 PRO/100 M Desktop Adapter A80897-xxx
+ PRO/100 S Advanced Management Adapter
+ 747842-xxx,
+ 745171-xxx
+ CNR PRO/100 VE Desktop Adapter A10386-xxx,
+ A10725-xxx,
+ A23801-xxx,
+ A19716-xxx
+ PRO/100 VM Desktop Adapter A14323-xxx,
+ A19725-xxx,
+ A23801-xxx,
+ A22220-xxx,
+ A23796-xxx
+
+
+ To verify that your adapter is supported, find the board ID number
+ on the adapter. Look for a label that has a barcode and a number
+ in the format 123456-001 (six digits hyphen three digits). Match
+ this to the list of numbers above.
+
+ For more information on how to identify your adapter, go to the
+ Adapter & Driver ID Guide at:
+
+ http://support.intel.com/support/network/adapter/pro100/21397.htm
+
+ For the latest Intel PRO/100 network driver for Linux, see:
+
+ http://appsr.intel.com/scripts-df/support_intel.asp
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/e100.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called e100.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Intel(R) PRO/1000 Gigabit Ethernet support
+CONFIG_E1000
+ This driver supports Intel(R) PRO/1000 gigabit ethernet family of
+ adapters, which includes:
+
+ Controller Adapter Name Board IDs
+ ---------- ------------ ---------
+ 82542 PRO/1000 Gigabit Server Adapter 700262-xxx,
+ 717037-xxx
+ 82543 PRO/1000 F Server Adapter 738640-xxx,
+ A38888-xxx
+ 82543 PRO/1000 T Server Adapter A19845-xxx,
+ A33948-xxx
+ 82544 PRO/1000 XT Server Adapter A51580-xxx
+ 82544 PRO/1000 XF Server Adapter A50484-xxx
+ 82544 PRO/1000 T Desktop Adapter A62947-xxx
+ 82540 PRO/1000 MT Desktop Adapter A78408-xxx
+ 82545 PRO/1000 MT Server Adapter A92165-xxx
+ 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx
+ 82545 PRO/1000 MF Server Adapter A91622-xxx
+ 82545 PRO/1000 MF Server Adapter(LX) A91624-xxx
+ 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx
+
+ For more information on how to identify your adapter, go to the
+ Adapter & Driver ID Guide at:
+
+ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+ For general information and support, go to the Intel support
+ website at:
+
+ <http://support.intel.com>
+
+ More specific information on configuring the driver is in
+ <file:Documentation/networking/e1000.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called e1000.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+AMD LANCE and PCnet (AT1500 and NE2100) support
+CONFIG_LANCE
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Some LinkSys cards are
+ of this type.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called lance.o.
+
+SGI IOC3 Ethernet
+CONFIG_SGI_IOC3_ETH
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+National Semiconductor DP83902AV support
+CONFIG_STNIC
+ Support for cards based on the National Semiconductor DP83902AV
+ ST-NIC Serial Network Interface Controller for Twisted Pair. This
+ is a 10Mbit/sec Ethernet controller. Product overview and specs at
+ <http://www.national.com/pf/DP/DP83902A.html>.
+
+ If unsure, say N.
+
+3COM cards
+CONFIG_NET_VENDOR_3COM
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about 3COM cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+3c501 "EtherLink" support
+CONFIG_EL1
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Also, consider buying a
+ new card, since the 3c501 is slow, broken, and obsolete: you will
+ have problems. Some people suggest to ping ("man ping") a nearby
+ machine every minute ("man cron") when using this card.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 3c501.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+3c503 "EtherLink II" support
+CONFIG_EL2
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 3c503.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+3c505 "EtherLink Plus" support
+CONFIG_ELPLUS
+ Information about this network (Ethernet) card can be found in
+ <file:Documentation/networking/3c505.txt>. If you have a card of
+ this type, say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called 3c505.o.
+
+3c507 (EtherLink 16) support
+CONFIG_EL16
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 3c507.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+3c523 "EtherlinkMC" support
+CONFIG_ELMC
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 3c523.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+3c527 "EtherLink/MC 32" support
+CONFIG_ELMC_II
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called 3c527.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+3c509/3c529 (MCA)/3c579 "EtherLink III" support
+CONFIG_EL3
+ If you have a network (Ethernet) card belonging to the 3Com
+ EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>.
+
+ If your card is not working you may need to use the DOS
+ setup disk to disable Plug & Play mode, and to select the default
+ media type.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called 3c509.o.
+
+3c515 ISA Fast EtherLink
+CONFIG_3C515
+ If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
+ network card, say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called 3c515.o.
+
+3c590/3c900 series (592/595/597) "Vortex/Boomerang/Cyclone" support
+CONFIG_VORTEX
+ This option enables driver support for a large number of 10mbps and
+ 10/100mbps EISA, PCI and PCMCIA 3Com network cards:
+
+ "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
+ "Boomerang" (EtherLink XL 3c900 or 3c905) PCI
+ "Cyclone" (3c540/3c900/3c905/3c980/3c575/3c656) PCI and Cardbus
+ "Tornado" (3c905) PCI
+ "Hurricane" (3c555/3cSOHO) PCI
+
+ If you have such a card, say Y and read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>. More
+ specific information is in
+ <file:Documentation/networking/vortex.txt> and in the comments at
+ the beginning of <file:drivers/net/3c59x.c>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called 3c59x.o.
+
+Other ISA cards
+CONFIG_NET_ISA
+ If your network (Ethernet) card hasn't been mentioned yet and its
+ bus system (that's the way the cards talks to the other components
+ of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y.
+ Make sure you know the name of your card. Read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If unsure, say Y.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the remaining ISA network card questions. If you say Y, you will be
+ asked for your specific card in the following questions.
+
+Generic ARCnet support
+CONFIG_ARCNET
+ If you have a network card of this type, say Y and check out the
+ (arguably) beautiful poetry in
+ <file:Documentation/networking/arcnet.txt>.
+
+ You need both this driver, and the driver for the particular ARCnet
+ chipset of your card. If you don't know, then it's probably a
+ COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset
+ support" below.
+
+ You might also want to have a look at the Ethernet-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>(even though ARCnet
+ is not really Ethernet).
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called arcnet.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Enable old ARCNet packet format (RFC 1051)
+CONFIG_ARCNET_1051
+ This allows you to use RFC1051 with your ARCnet card via the virtual
+ arc0s device. You only need arc0s if you want to talk to ARCnet
+ software complying with the "old" standard, specifically, the DOS
+ arcnet.com packet driver, Amigas running AmiTCP, and some variants
+ of NetBSD. You do not need to say Y here to communicate with
+ industry-standard RFC1201 implementations, like the arcether.com
+ packet driver or most DOS/Windows ODI drivers. RFC1201 is included
+ automatically as the arc0 device. Please read the ARCnet
+ documentation in <file:Documentation/networking/arcnet.txt> for more
+ information about using arc0e and arc0s.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called rfc1051.o.
+
+Enable standard ARCNet packet format (RFC 1201)
+CONFIG_ARCNET_1201
+ This allows you to use RFC1201 with your ARCnet card via the virtual
+ arc0 device. You need to say Y here to communicate with
+ industry-standard RFC1201 implementations, like the arcether.com
+ packet driver or most DOS/Windows ODI drivers. Please read the
+ ARCnet documentation in <file:Documentation/networking/arcnet.txt>
+ for more information about using arc0.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called rfc1201.o.
+
+Enable raw mode packet interface
+CONFIG_ARCNET_RAW
+ ARCnet "raw mode" packet encapsulation, no soft headers. Unlikely
+ to work unless talking to a copy of the same Linux arcnet driver,
+ but perhaps marginally faster in that case.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called arc-rawmode.o.
+
+ARCnet COM90xx (normal) chipset driver
+CONFIG_ARCNET_COM90xx
+ This is the chipset driver for the standard COM90xx cards. If you
+ have always used the old ARCnet driver without knowing what type of
+ card you had, this is probably the one for you.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called com90xx.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+ARCnet COM90xx (IO mapped) chipset driver
+CONFIG_ARCNET_COM90xxIO
+ This is the chipset driver for the COM90xx cards, using them in
+ IO-mapped mode instead of memory-mapped mode. This is slower than
+ the normal driver. Only use it if your card doesn't support shared
+ memory.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called com90io.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+ARCnet COM90xx (RIM I) chipset driver
+CONFIG_ARCNET_RIM_I
+ This is yet another chipset driver for the COM90xx cards, but this
+ time only using memory-mapped mode, and no IO ports at all. This
+ driver is completely untested, so if you have one of these cards,
+ please mail dwmw2@infradead.org, especially if it works!
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you
+ want). The module will be called arc-rimi.o. If you want to compile
+ it as a module, say M here and read <file:Documentation/modules.txt>
+ as well as <file:Documentation/networking/net-modules.txt>.
+
+ARCnet COM20020 chipset driver
+CONFIG_ARCNET_COM20020
+ This is the driver for the new COM20020 chipset. It supports such
+ things as promiscuous mode, so packet sniffing is possible, and
+ extra diagnostic information.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called com20020.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt> as
+ well as <file:Documentation/networking/net-modules.txt>.
+
+Cabletron E21xx support
+CONFIG_E2100
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called e2100.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+CS89x0 support (Daynaport CS and LC cards)
+CONFIG_CS89x0
+ Support for CS89x0 chipset based Ethernet cards. If you have a
+ network (Ethernet) card of this type, say Y and read the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto> as well as
+ <file:Documentation/networking/cs89x0.txt>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called cs89x.o.
+
+DEPCA, DE10x, DE200, DE201, DE202, DE422 support
+CONFIG_DEPCA
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto> as well as
+ <file:drivers/net/depca.c>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called
+ depca.o.
+
+EtherWORKS 3 (DE203, DE204, DE205) support
+CONFIG_EWRK3
+ This driver supports the DE203, DE204 and DE205 network (Ethernet)
+ cards. If this is for you, say Y and read
+ <file:Documentation/networking/ewrk3.txt> in the kernel source as
+ well as the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called ewrk3.o.
+
+SEEQ8005 support
+CONFIG_SEEQ8005
+ This is a driver for the SEEQ 8005 network (Ethernet) card. If this
+ is for you, read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called ewrk3.o.
+
+AT1700/1720 support
+CONFIG_AT1700
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called at1700.o.
+
+FMV-181/182/183/184 support
+CONFIG_FMV18X
+ If you have a Fujitsu FMV-181/182/183/184 network (Ethernet) card,
+ say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you use an FMV-183 or FMV-184 and it is not working, you may need
+ to disable Plug & Play mode of the card.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called fmv18x.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+EtherExpressPro and EtherExpress 10 (i82595) support
+CONFIG_EEXPRESS_PRO
+ If you have a network (Ethernet) card of this type, say Y. This
+ driver supports intel i82595{FX,TX} based boards. Note however
+ that the EtherExpress PRO/100 Ethernet card has its own separate
+ driver. Please read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called eepro.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+EtherExpress 16 support
+CONFIG_EEXPRESS
+ If you have an EtherExpress16 network (Ethernet) card, say Y and
+ read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that the Intel
+ EtherExpress16 card used to be regarded as a very poor choice
+ because the driver was very unreliable. We now have a new driver
+ that should do better.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called eexpress.o.
+
+Packet Engines Hamachi GNIC-II support
+CONFIG_HAMACHI
+ If you have a Gigabit Ethernet card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called hamachi.o.
+
+HP PCLAN+ (27247B and 27252A) support
+CONFIG_HPLAN_PLUS
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called hp-plus.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+HP PCLAN (27245 and other 27xxx series) support
+CONFIG_HPLAN
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called hp.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+HP 10/100VG PCLAN (ISA, EISA, PCI) support
+CONFIG_HP100
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called hp100.o.
+
+NE2000/NE1000 support
+CONFIG_NE2000
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Many Ethernet cards
+ without a specific driver are compatible with NE2000.
+
+ If you have a PCI NE2000 card however, say N here and Y to "PCI
+ NE2000 support", above. If you have a NE2000 card and are running on
+ an MCA system (a bus system used on some IBM PS/2 computers and
+ laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
+ below.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ne.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+National Semiconductor DP8381x series PCI Ethernet support
+CONFIG_NATSEMI
+ This driver is for the National Semiconductor DP83810 series,
+ which is used in cards from PureData, NetGear, Linksys
+ and others, including the 83815 chip.
+ More specific information and updates are available from
+ <http://www.scyld.com/network/natsemi.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called natsemi.o.
+
+NatSemi workaround for high errors
+CONFIG_NATSEMI_CABLE_MAGIC
+ Some systems see lots of errors with NatSemi ethernet controllers
+ on certain cables. If you are seeing lots of errors, try turning
+ this option on. Some boards have incorrect values for supporting
+ resistors that can cause this change to break. If you turn this
+ option on and your network suddenly stops working, turn this
+ option off.
+
+SK_G16 support
+CONFIG_SK_G16
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+NE/2 (ne2000 MCA version) support
+CONFIG_NE2_MCA
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ne2.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+SKnet MCA support
+CONFIG_SKMC
+ These are Micro Channel Ethernet adapters. You need to say Y to "MCA
+ support" in order to use this driver. Supported cards are the SKnet
+ Junior MC2 and the SKnet MC2(+). The driver automatically
+ distinguishes between the two cards. Note that using multiple boards
+ of different type hasn't been tested with this driver. Say Y if you
+ have one of these Ethernet adapters.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called sk_mca.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+IBM LAN Adapter/A support
+CONFIG_IBMLANA
+ This is a Micro Channel Ethernet adapter. You need to set
+ CONFIG_MCA to use this driver. It is both available as an in-kernel
+ driver and as a module ( = code which can be inserted in and removed
+ from the running kernel whenever you want). If you want to compile
+ it as a module, say M here and read <file:Documentation/modules.txt>
+ as well as <file:Documentation/networking/net-modules.txt>. The only
+ currently supported card is the IBM LAN Adapter/A for Ethernet. It
+ will both support 16K and 32K memory windows, however a 32K window
+ gives a better security against packet losses. Usage of multiple
+ boards with this driver should be possible, but has not been tested
+ up to now due to lack of hardware.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ibmlana.o.
+
+EISA, VLB, PCI and on board controllers
+CONFIG_NET_PCI
+ This is another class of network cards which attach directly to the
+ bus. If you have one of those, say Y and read the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about this class of network cards. If you say Y, you
+ will be asked for your specific card in the following questions. If
+ you are unsure, say Y.
+
+AMD PCnet32 (VLB and PCI) support
+CONFIG_PCNET32
+ If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
+ answer Y here and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pcnet32.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Ansel Communications EISA 3200 support
+CONFIG_AC3200
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ac3200.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Mylex EISA LNE390A/LNE390B support
+CONFIG_LNE390
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called lne390.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Novell/Eagle/Microdyne NE3210 EISA support
+CONFIG_NE3210
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Note that this driver
+ will NOT WORK for NE3200 cards as they are completely different.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ne3210.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Apricot Xen-II on board Ethernet
+CONFIG_APRICOT
+ If you have a network (Ethernet) controller of this type, say Y and
+ read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called apricot.o.
+
+Generic DECchip & DIGITAL EtherWORKS PCI/EISA
+CONFIG_DE4X5
+ This is support for the DIGITAL series of PCI/EISA Ethernet cards.
+ These include the DE425, DE434, DE435, DE450 and DE500 models. If
+ you have a network card of this type, say Y and read the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. More specific
+ information is contained in
+ <file:Documentation/networking/de4x5.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called de4x5.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+DECchip Tulip (dc21x4x) PCI support
+CONFIG_TULIP
+ This driver is developed for the SMC EtherPower series Ethernet
+ cards and also works with cards based on the DECchip
+ 21040/21041/21140 (Tulip series) chips. Some LinkSys PCI cards are
+ of this type. (If your card is NOT SMC EtherPower 10/100 PCI
+ (smc9332dst), you can also try the driver for "Generic DECchip"
+ cards, above. However, most people with a network card of this type
+ will say Y here.) Do read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. More specific
+ information is contained in
+ <file:Documentation/networking/tulip.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tulip.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+New Tulip bus configuration
+CONFIG_TULIP_MWI
+ This configures your Tulip card specifically for the card and
+ system cache line size type you are using.
+
+ This is experimental code, not yet tested on many boards.
+
+ If unsure, say N.
+
+Use PCI shared memory for NIC registers
+CONFIG_TULIP_MMIO
+ Use PCI shared memory for the NIC registers, rather than going through
+ the Tulip's PIO (programmed I/O ports). Faster, but could produce
+ obscure bugs if your mainboard has memory controller timing issues.
+ If in doubt, say N.
+
+Digi Intl. RightSwitch SE-X support
+CONFIG_DGRS
+ This is support for the Digi International RightSwitch series of
+ PCI/EISA Ethernet switch cards. These include the SE-4 and the SE-6
+ models. If you have a network card of this type, say Y and read the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. More specific
+ information is contained in <file:Documentation/networking/dgrs.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dgrs.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+EtherExpress Pro/100 support
+CONFIG_EEPRO100
+ If you have an Intel EtherExpress PRO/100 PCI network (Ethernet)
+ card, say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called eepro100.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt> as
+ well as <file:Documentation/networking/net-modules.txt>.
+
+Enable Power Management
+CONFIG_EEPRO100_PM
+ Many Intel EtherExpress PRO/100 PCI network cards are capable
+ of providing power management capabilities. To make use of these
+ capabilities, say Y.
+
+ WARNING: This option is intended for kernel developers and testers.
+ It is still very experimental, with some people reporting complete
+ lockups.
+
+ It is recommended to say N here.
+
+Myson MTD-8xx PCI Ethernet support
+CONFIG_FEALNX
+ Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet
+ cards. Specifications and data at
+ <http://www.myson.com.hk/mtd/datasheet/>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called fealnx.o.
+
+LP486E on board Ethernet
+CONFIG_LP486E
+ Say Y here to support the 82596-based on-board Ethernet controller
+ for the Panther motherboard, which is one of the two shipped in the
+ Intel Professional Workstation.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called lp486e.o.
+
+ICL EtherTeam 16i/32 support
+CONFIG_ETH16I
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called eth16i.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+TI ThunderLAN support
+CONFIG_TLAN
+ If you have a PCI Ethernet network card based on the ThunderLAN chip
+ which is supported by this driver, say Y and read the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Devices currently supported by this driver are Compaq Netelligent,
+ Compaq NetFlex and Olicom cards. Please read the file
+ <file:Documentation/networking/tlan.txt> for more details.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tlan.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+ Please email feedback to torben.mathiasen@compaq.com.
+
+VIA Rhine support
+CONFIG_VIA_RHINE
+ If you have a VIA "rhine" based network card (Rhine-I (3043) or
+ Rhine-2 (VT86c100A)), say Y here.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called via-rhine.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt> as
+ well as <file:Documentation/networking/net-modules.txt>.
+
+VIA Rhine MMIO support (EXPERIMENTAL)
+CONFIG_VIA_RHINE_MMIO
+ This instructs the driver to use PCI shared memory (MMIO) instead of
+ programmed I/O ports (PIO). Enabling this gives an improvement in
+ processing time in parts of the driver.
+
+ It is not known if this works reliably on all "rhine" based cards,
+ but it has been tested successfully on some DFE-530TX adapters.
+
+ If unsure, say N.
+
+Davicom DM910x/DM980x support
+CONFIG_DM9102
+ This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
+ Davicom (<http://www.davicom.com.tw/>). If you have such a network
+ (Ethernet) card, say Y. Some information is contained in the file
+ <file:Documentation/networking/dmfe.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dmfe.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+Racal-Interlan EISA ES3210 support
+CONFIG_ES3210
+ If you have a network (Ethernet) card of this type, say Y and read
+ the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called es3210.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt> as well
+ as <file:Documentation/networking/net-modules.txt>.
+
+SMC EtherPower II
+CONFIG_EPIC100
+ This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
+ which is based on the SMC83c17x (EPIC/100).
+ More specific information and updates are available from
+ <http://www.scyld.com/network/epic100.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called epic100.o.
+
+DEC LANCE Ethernet controller support
+CONFIG_DECLANCE
+ This driver is for the series of Ethernet controllers produced by
+ DEC (now Compaq) based on the AMD Lance chipset, including the
+ DEPCA series. (This chipset is better known via the NE2100 cards.)
+
+SGI Seeq Ethernet controller support
+CONFIG_SGISEEQ
+ Say Y here if you have an Seeq based Ethernet network card. This is
+ used in many Silicon Graphics machines.
+
+Sundance Alta PCI Ethernet support
+CONFIG_SUNDANCE
+ This driver is for the Sundance "Alta" chip.
+ More specific information and updates are available from
+ <http://www.scyld.com/network/sundance.html>.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called sundance.o.
+
+Sundance Alta memory-mapped I/O support
+CONFIG_SUNDANCE_MMIO
+ Enable memory-mapped I/O for interaction with Sundance NIC registers.
+ Do NOT enable this by default, PIO (enabled when MMIO is disabled)
+ is known to solve bugs on certain chips.
+
+ If unsure, say N.
+
+Sun3/Sun3x on-board LANCE support
+CONFIG_SUN3LANCE
+ Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
+ featured an AMD Lance 10Mbit Ethernet controller on board; say Y
+ here to compile in the Linux driver for this and enable Ethernet.
+ General Linux information on the Sun 3 and 3x series (now
+ discontinued) is at
+ <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+ If you're not building a kernel for a Sun 3, say N.
+
+Sun3 on-board Intel 82586 support
+CONFIG_SUN3_82586
+ This driver enables support for the on-board Intel 82586 based
+ Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
+ that this driver does not support 82586-based adapters on additional
+ VME boards.
+
+Winbond W89c840 PCI Ethernet support
+CONFIG_WINBOND_840
+ This driver is for the Winbond W89c840 chip. It also works with
+ the TX9882 chip on the Compex RL100-ATX board.
+ More specific information and updates are available from
+ <http://www.scyld.com/network/drivers.html>.
+
+Zenith Z-Note support
+CONFIG_ZNET
+ The Zenith Z-Note notebook computer has a built-in network
+ (Ethernet) card, and this is the Linux driver for it. Note that the
+ IBM Thinkpad 300 is compatible with the Z-Note and is also supported
+ by this driver. Read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+Philips SAA9730 Ethernet support
+CONFIG_LAN_SAA9730
+ The SAA9730 is a combined multimedia and peripheral controller used
+ in thin clients, Internet access terminals, and diskless
+ workstations.
+ See <http://www.semiconductors.philips.com/pip/SAA9730_flyer_1>.
+
+Pocket and portable adapters
+CONFIG_NET_POCKET
+ Cute little network (Ethernet) devices which attach to the parallel
+ port ("pocket adapters"), commonly used with laptops. If you have
+ one of those, say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to plug a network (or some other) card into the PCMCIA
+ (or PC-card) slot of your laptop instead (PCMCIA is the standard for
+ credit card size extension cards used by all modern laptops), you
+ need the pcmcia-cs package (location contained in the file
+ <file:Documentation/Changes>) and you can say N here.
+
+ Laptop users should read the Linux Laptop home page at
+ <http://www.cs.utexas.edu/users/kharker/linux-laptop/>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about this class of network devices. If you say Y, you
+ will be asked for your specific device in the following questions.
+
+AT-LAN-TEC/RealTek pocket adapter support
+CONFIG_ATP
+ This is a network (Ethernet) device which attaches to your parallel
+ port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>, if you
+ want to use this. If you intend to use this driver, you should have
+ said N to the "Parallel printer support", because the two drivers
+ don't like each other.
+
+ If you want to compile this driver as a module however ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>. The module will be called atp.o.
+
+D-Link DE600 pocket adapter support
+CONFIG_DE600
+ This is a network (Ethernet) device which attaches to your parallel
+ port. Read <file:Documentation/networking/DLINK.txt> as well as the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, if you want to use
+ this. It is possible to have several devices share a single parallel
+ port and it is safe to compile the corresponding drivers into the
+ kernel.
+
+ If you want to compile this driver as a module however ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called de600.o.
+
+D-Link DE620 pocket adapter support
+CONFIG_DE620
+ This is a network (Ethernet) device which attaches to your parallel
+ port. Read <file:Documentation/networking/DLINK.txt> as well as the
+ Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, if you want to use
+ this. It is possible to have several devices share a single parallel
+ port and it is safe to compile the corresponding drivers into the
+ kernel.
+
+ If you want to compile this driver as a module however ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called de620.o.
+
+Token Ring driver support
+CONFIG_TR
+ Token Ring is IBM's way of communication on a local network; the
+ rest of the world uses Ethernet. To participate on a Token Ring
+ network, you need a special Token ring network card. If you are
+ connected to such a Token Ring network and want to use your Token
+ Ring card under Linux, say Y here and to the driver for your
+ particular card below and read the Token-Ring mini-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>. Most people can
+ say N here.
+
+IBM Tropic chipset based adapter support
+CONFIG_IBMTR
+ This is support for all IBM Token Ring cards that don't use DMA. If
+ you have such a beast, say Y and read the Token-Ring mini-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ Warning: this driver will almost definitely fail if more than one
+ active Token Ring card is present.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ibmtr.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+IBM Olympic chipset PCI adapter support
+CONFIG_IBMOL
+ This is support for all non-Lanstreamer IBM PCI Token Ring Cards.
+ Specifically this is all IBM PCI, PCI Wake On Lan, PCI II, PCI II
+ Wake On Lan, and PCI 100/16/4 adapters.
+
+ If you have such an adapter, say Y and read the Token-Ring
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called olympic.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+ Also read <file:Documentation/networking/olympic.txt> or check the
+ Linux Token Ring Project site for the latest information at
+ <http://www.linuxtr.net/>.
+
+IBM Lanstreamer chipset PCI adapter support
+CONFIG_IBMLS
+ This is support for IBM Lanstreamer PCI Token Ring Cards.
+
+ If you have such an adapter, say Y and read the Token-Ring
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a modules ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The modules will be called lanstreamer.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+Generic TMS380 Token Ring ISA/PCI/MCA/EISA adapter support
+CONFIG_TMS380TR
+ This driver provides generic support for token ring adapters
+ based on the Texas Instruments TMS380 series chipsets. This
+ includes the SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect
+ TR4/16(+) PCI (SK-4590), SysKonnect TR4/16 PCI (SK-4591),
+ Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and several
+ Madge adapters. If you say Y here, you will be asked to select
+ which cards to support below. If you're using modules, each
+ class of card will be supported by a separate module.
+
+ If you have such an adapter and would like to use it, say Y and
+ read the Token-Ring mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Also read the file <file:Documentation/networking/tms380tr.txt> or
+ check <http://www.auk.cx/tms380tr/>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tms380tr.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+Generic TMS380 PCI support
+CONFIG_TMSPCI
+ This tms380 module supports generic TMS380-based PCI cards.
+
+ These cards are known to work:
+ - Compaq 4/16 TR PCI
+ - SysKonnect TR4/16 PCI (SK-4590/SK-4591)
+ - Thomas-Conrad TC4048 PCI 4/16
+ - 3Com Token Link Velocity
+
+ This driver is available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tmspci.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+Generic TMS380 ISA support
+CONFIG_TMSISA
+ This tms380 module supports generic TMS380-based ISA cards.
+
+ These cards are known to work:
+ - SysKonnect TR4/16 ISA (SK-4190)
+
+ This driver is available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tmsisa.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+Madge Smart 16/4 PCI Mk2 support
+CONFIG_ABYSS
+ This tms380 module supports the Madge Smart 16/4 PCI Mk2
+ cards (51-02).
+
+ This driver is available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called abyss.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+Madge Smart 16/4 Ringnode MicroChannel
+CONFIG_MADGEMC
+ This tms380 module supports the Madge Smart 16/4 MC16 and MC32
+ MicroChannel adapters.
+
+ This driver is available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called madgemc.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+SMC ISA/MCA Token Ring adapter support
+CONFIG_SMCTR
+ This is support for the ISA and MCA SMC Token Ring cards,
+ specifically SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A
+ (8115T/A) adapters.
+
+ If you have such an adapter and would like to use it, say Y or M and
+ read the Token-Ring mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto> and the file
+ <file:Documentation/networking/smctr.txt>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called smctr.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+3COM 3C359 Token Link Velocity XL PCI adapter support
+CONFIG_3C359
+ This is support for the 3Com PCI Velocity XL cards, specifically
+ the 3Com 3C359, please note this is not for the 3C339 cards, you
+ should use the tms380 driver instead.
+
+ If you have such an adapter, say Y and read the Token-Ring
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will will be called 3c359.o. If you want to compile it
+ as a module, say M here and read Documentation/modules.txt.
+
+ Also read the file <file:Documentation/networking/3c359.txt> or check the
+ Linux Token Ring Project site for the latest information at
+ <http://www.linuxtr.net>
+
+Sun Happy Meal 10/100baseT support
+CONFIG_HAPPYMEAL
+ This driver supports the "hme" interface present on most Ultra
+ systems and as an option on older Sbus systems. This driver supports
+ both PCI and Sbus devices. This driver also supports the "qfe" quad
+ 100baseT device available in both PCI and Sbus configurations.
+
+ This support is also available as a module called sunhme.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Sun Lance support
+CONFIG_SUNLANCE
+ This driver supports the "le" interface present on all 32-bit Sparc
+ systems, on some older Ultra systems and as an Sbus option. These
+ cards are based on the AMD Lance chipset, which is better known
+ via the NE2100 cards.
+
+ This support is also available as a module called sunlance.o ( =
+ code which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Sun BigMAC 10/100baseT support
+CONFIG_SUNBMAC
+ This driver supports the "be" interface available as an Sbus option.
+ This is Sun's older 100baseT Ethernet device.
+
+ This support is also available as a module called sunbmac.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Sun QuadEthernet support
+CONFIG_SUNQE
+ This driver supports the "qe" 10baseT Ethernet device, available as
+ an Sbus option. Note that this is not the same as Quad FastEthernet
+ "qfe" which is supported by the Happy Meal driver instead.
+
+ This support is also available as a module called sunqe.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+Traffic Shaper
+CONFIG_SHAPER
+ The traffic shaper is a virtual network device that allows you to
+ limit the rate of outgoing data flow over some other network device.
+ The traffic that you want to slow down can then be routed through
+ these virtual devices. See
+ <file:Documentation/networking/shaper.txt> for more information.
+
+ An alternative to this traffic shaper is the experimental
+ Class-Based Queueing (CBQ) scheduling support which you get if you
+ say Y to "QoS and/or fair queueing" above.
+
+ To set up and configure shaper devices, you need the shapecfg
+ program, available from <ftp://shadow.cabi.net/pub/Linux/> in the
+ shaper package.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called shaper.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+FDDI driver support
+CONFIG_FDDI
+ Fiber Distributed Data Interface is a high speed local area network
+ design; essentially a replacement for high speed Ethernet. FDDI can
+ run over copper or fiber. If you are connected to such a network and
+ want a driver for the FDDI card in your computer, say Y here (and
+ then also Y to the driver for your FDDI card, below). Most people
+ will say N.
+
+Digital DEFEA and DEFPA adapter support
+CONFIG_DEFXX
+ This is support for the DIGITAL series of EISA (DEFEA) and PCI
+ (DEFPA) controllers which can connect you to a local FDDI network.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called defxx.o.
+
+SysKonnect FDDI PCI support
+CONFIG_SKFP
+ Say Y here if you have a SysKonnect FDDI PCI adapter.
+ The following adapters are supported by this driver:
+ - SK-5521 (SK-NET FDDI-UP)
+ - SK-5522 (SK-NET FDDI-UP DAS)
+ - SK-5541 (SK-NET FDDI-FP)
+ - SK-5543 (SK-NET FDDI-LP)
+ - SK-5544 (SK-NET FDDI-LP DAS)
+ - SK-5821 (SK-NET FDDI-UP64)
+ - SK-5822 (SK-NET FDDI-UP64 DAS)
+ - SK-5841 (SK-NET FDDI-FP64)
+ - SK-5843 (SK-NET FDDI-LP64)
+ - SK-5844 (SK-NET FDDI-LP64 DAS)
+ - Netelligent 100 FDDI DAS Fibre SC
+ - Netelligent 100 FDDI SAS Fibre SC
+ - Netelligent 100 FDDI DAS UTP
+ - Netelligent 100 FDDI SAS UTP
+ - Netelligent 100 FDDI SAS Fibre MIC
+
+ Read <file:Documentation/networking/skfp.txt> for information about
+ the driver.
+
+ Questions concerning this driver can be addressed to:
+ linux@syskonnect.de
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called skfp.o.
+
+HIgh Performance Parallel Interface (HIPPI) support
+CONFIG_HIPPI
+ HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
+ 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
+ can run over copper (25m) or fiber (300m on multi-mode or 10km on
+ single-mode). HIPPI networks are commonly used for clusters and to
+ connect to super computers. If you are connected to a HIPPI network
+ and have a HIPPI network card in your computer that you want to use
+ under Linux, say Y here (you must also remember to enable the driver
+ for your HIPPI card below). Most people will say N here.
+
+Essential RoadRunner HIPPI PCI adapter support
+CONFIG_ROADRUNNER
+ Say Y here if this is your PCI HIPPI network card.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called rrunner.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+Use large TX/RX rings
+CONFIG_ROADRUNNER_LARGE_RINGS
+ If you say Y here, the RoadRunner driver will preallocate up to 2 MB
+ of additional memory to allow for fastest operation, both for
+ transmitting and receiving. This memory cannot be used by any other
+ kernel code or by user space programs. Say Y here only if you have
+ the memory.
+
+Acorn Ether1 support
+CONFIG_ARM_ETHER1
+ If you have an Acorn system with one of these (AKA25) network cards,
+ you should say Y to this option if you wish to use it with Linux.
+
+Acorn/ANT Ether3 support
+CONFIG_ARM_ETHER3
+ If you have an Acorn system with one of these network cards, you
+ should say Y to this option if you wish to use it with Linux.
+
+I-Cubed EtherH support
+CONFIG_ARM_ETHERH
+ If you have an Acorn system with one of these network cards, you
+ should say Y to this option if you wish to use it with Linux.
+
+EBSA-110 Ethernet interface (AM79C961A)
+CONFIG_ARM_AM79C961A
+ If you wish to compile a kernel for the EBSA-110, then you should
+ always answer Y to this.
+
+Support Thumb instructions
+CONFIG_ARM_THUMB
+ Say Y if you want to have kernel support for ARM Thumb instructions,
+ fault handlers, and system calls.
+
+ The Thumb instruction set is a compressed form of the standard ARM
+ instruction set resulting in smaller binaries at the expense of
+ slightly less efficient code.
+
+ If you don't know what this all is, saying Y is a safe choice.
+
+Support CD-ROM drives that are not SCSI or IDE/ATAPI
+CONFIG_CD_NO_IDESCSI
+ If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
+ here, otherwise N. Read the CD-ROM-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about these CD-ROM drives. If you are unsure what you
+ have, say Y and find out whether you have one of the following
+ drives.
+
+ For each of these drivers, a file Documentation/cdrom/{driver_name}
+ exists. Especially in cases where you do not know exactly which kind
+ of drive you have you should read there. Most of these drivers use a
+ file drivers/cdrom/{driver_name}.h where you can define your
+ interface parameters and switch some internal goodies.
+
+ All these CD-ROM drivers are also usable as a module ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want). If you want to compile them as module, say M instead of Y and
+ read <file:Documentation/modules.txt>.
+
+ If you want to use any of these CD-ROM drivers, you also have to
+ answer Y or M to "ISO 9660 CD-ROM file system support" below (this
+ answer will get "defaulted" for you if you enable any of the Linux
+ CD-ROM drivers).
+
+Sony CDU31A/CDU33A CD-ROM support
+CONFIG_CDU31A
+ These CD-ROM drives have a spring-pop-out caddyless drawer, and a
+ rectangular green LED centered beneath it. NOTE: these CD-ROM
+ drives will not be auto detected by the kernel at boot time; you
+ have to provide the interface address as an option to the kernel at
+ boot time as described in <file:Documentation/cdrom/cdu31a> or fill
+ in your parameters into <file:drivers/cdrom/cdu31a.c>. Try "man
+ bootparam" or see the documentation of your boot loader (lilo or
+ loadlin) about how to pass options to the kernel.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called cdu31a.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Standard Mitsumi [no XA/Multisession] CD-ROM support
+CONFIG_MCD
+ This is the older of the two drivers for the older Mitsumi models
+ LU-005, FX-001 and FX-001D. This is not the right driver for the
+ FX-001DE and the triple or quad speed models (all these are
+ IDE/ATAPI models). Please also the file
+ <file:Documentation/cdrom/mcd>.
+
+ With the old LU-005 model, the whole drive chassis slides out for cd
+ insertion. The FX-xxx models use a motorized tray type mechanism.
+ Note that this driver does not support XA or MultiSession CDs
+ (PhotoCDs). There is a new driver (next question) which can do
+ this. If you want that one, say N here.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called mcd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+IRQ channel for Mitsumi CD-ROM
+CONFIG_MCD_IRQ
+ This allows you to specify the default value of the IRQ used by the
+ driver. This setting can be overridden by passing the "mcd="
+ parameter to the kernel at boot time (or at module load time if you
+ said M to "Standard Mitsumi CD-ROM support").
+
+I/O base address for Mitsumi CD-ROM
+CONFIG_MCD_BASE
+ This allows you to specify the default value of the I/O base address
+ used by the driver. This setting can be overridden by passing the
+ "mcd=" parameter to the kernel at boot time (or at module load time
+ if you said M to "Standard Mitsumi CD-ROM support").
+
+Mitsumi [XA/MultiSession] CD-ROM support
+CONFIG_MCDX
+ Use this driver if you want to be able to read XA or MultiSession
+ CDs (PhotoCDs) as well as ordinary CDs with your Mitsumi LU-005,
+ FX-001 or FX-001D CD-ROM drive. In addition, this driver uses much
+ less kernel memory than the old one, if that is a concern. This
+ driver is able to support more than one drive, but each drive needs
+ a separate interface card. Please read the file
+ <file:Documentation/cdrom/mcdx>.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called mcdx.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Matsushita/Panasonic/Creative, Longshine, TEAC CD-ROM support
+CONFIG_SBPCD
+ This driver supports most of the drives which use the Panasonic or
+ Sound Blaster interface. Please read the file
+ <file:Documentation/cdrom/sbpcd>.
+
+ The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives
+ (sometimes labeled "Creative"), the Creative Labs CD200, the
+ Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x
+ model), the TEAC CD-55A fall under this category. Some other
+ "electrically compatible" drives (Vertos, Genoa, some Funai models)
+ are currently not supported; for the Sanyo H94A drive currently a
+ separate driver (asked later) is responsible. Most drives have a
+ uniquely shaped faceplate, with a caddyless motorized drawer, but
+ without external brand markings. The older CR-52x drives have a
+ caddy and manual loading/eject, but still no external markings. The
+ driver is able to do an extended auto-probing for interface
+ addresses and drive types; this can help to find facts in cases you
+ are not sure, but can consume some time during the boot process if
+ none of the supported drives gets found. Once your drive got found,
+ you should enter the reported parameters into
+ <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there.
+
+ This driver can support up to four CD-ROM controller cards, and each
+ card can support up to four CD-ROM drives; if you say Y here, you
+ will be asked how many controller cards you have. If compiled as a
+ module, only one controller card (but with up to four drives) is
+ usable.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called sbpcd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Matsushita/Panasonic, ... second CD-ROM controller support
+CONFIG_SBPCD2
+ Say Y here only if you have two CD-ROM controller cards of this type
+ (usually only if you have more than four drives). You should enter
+ the parameters for the second, third and fourth interface card into
+ <file:drivers/cdrom/sbpcd.h> before compiling the new kernel. Read
+ the file <file:Documentation/cdrom/sbpcd>.
+
+Matsushita/Panasonic, ... third CD-ROM controller support
+CONFIG_SBPCD3
+ Say Y here only if you have three CD-ROM controller cards of this
+ type (usually only if you have more than six drives). You should
+ enter the parameters for the second, third and fourth interface card
+ into <file:include/linux/sbpcd.h> before compiling the new kernel.
+ Read the file <file:Documentation/cdrom/sbpcd>.
+
+Matsushita/Panasonic, ... fourth CD-ROM controller support
+CONFIG_SBPCD4
+ Say Y here only if you have four CD-ROM controller cards of this
+ type (usually only if you have more than eight drives). You should
+ enter the parameters for the second, third and fourth interface card
+ into <file:include/linux/sbpcd.h> before compiling the new kernel.
+ Read the file <file:Documentation/cdrom/sbpcd>.
+
+Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CD-ROM support
+CONFIG_AZTCD
+ This is your driver if you have an Aztech CDA268-01A, Orchid
+ CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or
+ CR540 CD-ROM drive. This driver -- just like all these CD-ROM
+ drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such
+ as Aztech CDA269-031SE. Please read the file
+ <file:Documentation/cdrom/aztcd>.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aztcd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Sony CDU535 CD-ROM support
+CONFIG_CDU535
+ This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM
+ drives. Please read the file <file:Documentation/cdrom/sonycd535>.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called sonycd535.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Goldstar R420 CD-ROM support
+CONFIG_GSCD
+ If this is your CD-ROM drive, say Y here. As described in the file
+ <file:Documentation/cdrom/gscd>, you might have to change a setting
+ in the file <file:drivers/cdrom/gscd.h> before compiling the
+ kernel. Please read the file <file:Documentation/cdrom/gscd>.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called gscd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Philips/LMS CM206 CD-ROM support
+CONFIG_CM206
+ If you have a Philips/LMS CD-ROM drive cm206 in combination with a
+ cm260 host adapter card, say Y here. Please also read the file
+ <file:Documentation/cdrom/cm206>.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called cm206.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Optics Storage DOLPHIN 8000AT CD-ROM support
+CONFIG_OPTCD
+ This is the driver for the 'DOLPHIN' drive with a 34-pin Sony
+ compatible interface. It also works with the Lasermate CR328A. If
+ you have one of those, say Y. This driver does not work for the
+ Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that
+ one. Please read the file <file:Documentation/cdrom/optcd>.
+
+ If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
+ file system support" below, because that's the file system used on
+ CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called optcd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Sanyo CDR-H94A CD-ROM support
+CONFIG_SJCD
+ If this is your CD-ROM drive, say Y here and read the file
+ <file:Documentation/cdrom/sjcd>. You should then also say Y or M to
+ "ISO 9660 CD-ROM file system support" below, because that's the
+ file system used on CD-ROMs.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called sjcd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+ISP16/MAD16/Mozart soft configurable cdrom interface support
+CONFIG_ISP16_CDI
+ These are sound cards with built-in cdrom interfaces using the OPTi
+ 82C928 or 82C929 chips. Say Y here to have them detected and
+ possibly configured at boot time. In addition, You'll have to say Y
+ to a driver for the particular cdrom drive you have attached to the
+ card. Read <file:Documentation/cdrom/isp16> for details.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called isp16.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+iSeries Virtual I/O CD Support
+CONFIG_VIOCD
+ If you are running Linux on an IBM iSeries system and you want to
+ read a CD drive owned by OS/400, say Y here.
+
+Quota support
+CONFIG_QUOTA
+ If you say Y here, you will be able to set per user limits for disk
+ usage (also called disk quotas). Currently, it works only for the
+ ext2 file system. You need additional software in order to use quota
+ support; for details, read the Quota mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. Probably the quota
+ support is only useful for multi user systems. If unsure, say N.
+
+Memory Technology Device (MTD) support
+CONFIG_MTD
+ Memory Technology Devices are flash, RAM and similar chips, often
+ used for solid state file systems on embedded devices. This option
+ will provide the generic support for MTD drivers to register
+ themselves with the kernel and for potential users of MTD devices
+ to enumerate the devices which are present and obtain a handle on
+ them. It will also allow you to select individual drivers for
+ particular hardware and users of MTD devices. If unsure, say N.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ mtdcore.o
+
+MTD debugging support
+CONFIG_MTD_DEBUG
+ This turns on low-level debugging for the entire MTD sub-system.
+ Normally, you should say 'N'.
+
+MTD partitioning support
+CONFIG_MTD_PARTITIONS
+ If you have a device which needs to divide its flash chip(s) up
+ into multiple 'partitions', each of which appears to the user as
+ a separate MTD device, you require this option to be enabled. If
+ unsure, say 'Y'.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ mtdpart.o
+
+ Note, however, that you don't need this option for the DiskOnChip
+ devices. Partitioning on NFTL 'devices' is a different - that's the
+ 'normal' form of partitioning used on a block device.
+
+RedBoot partition table parsing
+CONFIG_MTD_REDBOOT_PARTS
+ RedBoot is a ROM monitor and bootloader which deals with multiple
+ 'images' in flash devices by putting a table in the last erase block
+ of the device, similar to a partition table, which gives the
+ offsets, lengths and names of all the images stored in the flash.
+
+ If you need code which can detect and parse this table, and register
+ MTD 'partitions' corresponding to each image in the table, enable
+ this option.
+
+ You will still need the parsing functions to be called by the driver
+ for your particular device. It won't happen automatically. The
+ SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
+ example.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ redboot.o
+
+Compaq bootldr partition table parsing
+CONFIG_MTD_BOOTLDR_PARTS
+ The Compaq bootldr deals with multiple 'images' in flash devices
+ by putting a table in one of the first erase blocks of the device,
+ similar to a partition table, which gives the offsets, lengths and
+ names of all the images stored in the flash.
+
+ If you need code which can detect and parse this table, and register
+ MTD 'partitions' corresponding to each image in the table, enable
+ this option.
+
+ You will still need the parsing functions to be called by the driver
+ for your particular device. It won't happen automatically. The
+ SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
+ example.
+
+ARM Firmware Suite flash layout / partition parsing
+CONFIG_MTD_AFS_PARTS
+ The ARM Firmware Suite allows the user to divide flash devices into
+ multiple 'images'. Each such image has a header containing its name
+ and offset/size etc.
+
+ If you need code which can detect and parse these tables, and
+ register MTD 'partitions' corresponding to each image detected,
+ enable this option.
+
+ You will still need the parsing functions to be called by the driver
+ for your particular device. It won't happen automatically. The
+ 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
+
+MTD debugging verbosity (0 = quiet, 3 = noisy)
+CONFIG_MTD_DEBUG_VERBOSE
+ Determines the verbosity level of the MTD debugging messages.
+
+Direct chardevice access to MTD devices
+CONFIG_MTD_CHAR
+ This provides a character device for each MTD device present in
+ the system, allowing the user to read and write directly to the
+ memory chips, and also use ioctl() to obtain information about
+ the device, or to erase parts of it.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ mtdchar.o
+
+Caching block device access to MTD devices
+CONFIG_MTD_BLOCK
+ Although most flash chips have an erase size too large to be useful
+ as block devices, it is possible to use MTD devices which are based
+ on RAM chips in this manner. This block device is a user of MTD
+ devices performing that function.
+
+ At the moment, it is also required for the Journalling Flash File
+ System(s) to obtain a handle on the MTD device when it's mounted
+ (although JFFS and JFFS2 don't actually use any of the functionality
+ of the mtdblock device).
+
+ Later, it may be extended to perform read/erase/modify/write cycles
+ on flash chips to emulate a smaller block size. Needless to say,
+ this is very unsafe, but could be useful for file systems which are
+ almost never written to.
+
+ You do not need this option for use with the DiskOnChip devices. For
+ those, enable NFTL support (CONFIG_NFTL) instead.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ mtdblock.o
+
+Readonly block device access to MTD devices
+CONFIG_MTD_BLOCK_RO
+ This allows you to mount read-only file systems (such as cramfs)
+ from an MTD device, without the overhead (and danger) of the caching
+ driver.
+
+ You do not need this option for use with the DiskOnChip devices. For
+ those, enable NFTL support (CONFIG_NFTL) instead.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ mtdblock_ro.o
+
+FTL (Flash Translation Layer) support
+CONFIG_FTL
+ This provides support for the original Flash Translation Layer which
+ is part of the PCMCIA specification. It uses a kind of pseudo-
+ file system on a flash device to emulate a block device with
+ 512-byte sectors, on top of which you put a 'normal' file system.
+
+ You may find that the algorithms used in this code are patented
+ unless you live in the Free World where software patents aren't
+ legal - in the USA you are only permitted to use this on PCMCIA
+ hardware, although under the terms of the GPL you're obviously
+ permitted to copy, modify and distribute the code as you wish. Just
+ not use it.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ftl.o
+
+NFTL (NAND Flash Translation Layer) support
+CONFIG_NFTL
+ This provides support for the NAND Flash Translation Layer which is
+ used on M-Systems' DiskOnChip devices. It uses a kind of pseudo-
+ file system on a flash device to emulate a block device with
+ 512-byte sectors, on top of which you put a 'normal' file system.
+
+ You may find that the algorithms used in this code are patented
+ unless you live in the Free World where software patents aren't
+ legal - in the USA you are only permitted to use this on DiskOnChip
+ hardware, although under the terms of the GPL you're obviously
+ permitted to copy, modify and distribute the code as you wish. Just
+ not use it.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ nftl.o
+
+Write support for NFTL (EXPERIMENTAL)
+CONFIG_NFTL_RW
+ If you're lucky, this will actually work. Don't whinge if it
+ doesn't. Send mail to the MTD mailing list
+ <linux-mtd@lists.infradead.org> if you want to help to make it more
+ reliable.
+
+Detect flash chips by Common Flash Interface (CFI) probe
+CONFIG_MTD_CFI
+ The Common Flash Interface specification was developed by Intel,
+ AMD and other flash manufactures that provides a universal method
+ for probing the capabilities of flash devices. If you wish to
+ support any device that is CFI-compliant, you need to enable this
+ option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
+ for more information on CFI.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ cfi_probe.o
+
+CFI Advanced configuration options
+CONFIG_MTD_CFI_ADV_OPTIONS
+ If you need to specify a specific endianness for access to flash
+ chips, or if you wish to reduce the size of the kernel by including
+ support for only specific arrangements of flash chips, say 'Y'. This
+ option does not directly affect the code, but will enable other
+ configuration options which allow you to do so.
+
+ If unsure, say 'N'.
+
+Specific CFI Flash geometry selection
+CONFIG_MTD_CFI_GEOMETRY
+ This option does not affect the code directly, but will enable
+ some other configuration options which would allow you to reduce
+ the size of the kernel by including support for only certain
+ arrangements of CFI chips. If unsure, say 'N' and all options
+ which are supported by the current code will be enabled.
+
+Support 8-bit buswidth
+CONFIG_MTD_CFI_B1
+ If you wish to support CFI devices on a physical bus which is
+ 8 bits wide, say 'Y'.
+
+Support 16-bit buswidth
+CONFIG_MTD_CFI_B2
+ If you wish to support CFI devices on a physical bus which is
+ 16 bits wide, say 'Y'.
+
+Support 32-bit buswidth
+CONFIG_MTD_CFI_B4
+ If you wish to support CFI devices on a physical bus which is
+ 32 bits wide, say 'Y'.
+
+Support 1-chip flash interleave
+CONFIG_MTD_CFI_I1
+ If your flash chips are not interleaved - i.e. you only have one
+ flash chip addressed by each bus cycle, then say 'Y'.
+
+Support 2-chip flash interleave
+CONFIG_MTD_CFI_I2
+ If your flash chips are interleaved in pairs - i.e. you have two
+ flash chips addressed by each bus cycle, then say 'Y'.
+
+Support 4-chip flash interleave
+CONFIG_MTD_CFI_I4
+ If your flash chips are interleaved in fours - i.e. you have four
+ flash chips addressed by each bus cycle, then say 'Y'.
+
+# Choice: mtd_data_swap
+Flash cmd/query data swapping
+CONFIG_MTD_CFI_NOSWAP
+ This option defines the way in which the CPU attempts to arrange
+ data bits when writing the 'magic' commands to the chips. Saying
+ 'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't
+ enabled, means that the CPU will not do any swapping; the chips
+ are expected to be wired to the CPU in 'host-endian' form.
+ Specific arrangements are possible with the BIG_ENDIAN_BYTE and
+ LITTLE_ENDIAN_BYTE, if the bytes are reversed.
+
+ If you have a LART, on which the data (and address) lines were
+ connected in a fashion which ensured that the nets were as short
+ as possible, resulting in a bit-shuffling which seems utterly
+ random to the untrained eye, you need the LART_ENDIAN_BYTE option.
+
+ Yes, there really exists something sicker than PDP-endian :)
+
+CFI support for Intel/Sharp Extended Command Set chips
+CONFIG_MTD_CFI_INTELEXT
+ The Common Flash Interface defines a number of different command
+ sets which a CFI-compliant chip may claim to implement. This code
+ provides support for one of those command sets, used on Intel
+ StrataFlash and other parts.
+
+CFI support for AMD/Fujitsu Standard Command Set chips
+CONFIG_MTD_CFI_AMDSTD
+ The Common Flash Interface defines a number of different command
+ sets which a CFI-compliant chip may claim to implement. This code
+ provides support for one of those command sets, used on chips
+ chips including the AMD Am29LV320.
+
+CFI support for Intel/Sharp Standard Commands
+CONFIG_MTD_CFI_INTELSTD
+ The Common Flash Interface defines a number of different command
+ sets which a CFI-compliant chip may claim to implement. This code
+ provides support for one of those command sets.
+
+pre-CFI Sharp chip support
+CONFIG_MTD_SHARP
+ This option enables support for flash chips using Sharp-compatible
+ commands, including some which are not CFI-compatible and hence
+ cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ sharp.o
+
+AMD compatible flash chip support (non-CFI)
+CONFIG_MTD_AMDSTD
+ This option enables support for flash chips using AMD-compatible
+ commands, including some which are not CFI-compatible and hence
+ cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
+
+ It also works on AMD compatible chips that do conform to CFI.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ amd_flash.o
+
+Support for RAM chips in bus mapping
+CONFIG_MTD_RAM
+ This option enables basic support for RAM chips accessed through
+ a bus mapping driver.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ map_ram.o
+
+Support for ROM chips in bus mapping
+CONFIG_MTD_ROM
+ This option enables basic support for ROM chips accessed through
+ a bus mapping driver.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ map_rom.o
+
+JEDEC device support
+CONFIG_MTD_JEDEC
+ Enable older older JEDEC flash interface devices for self
+ programming flash. It is commonly used in older AMD chips. It is
+ only called JEDEC because the JEDEC association
+ <http://www.jedec.org/> distributes the identification codes for the
+ chips. WARNING!!!! This code does not compile and is incomplete as
+ are the specific JEDEC devices drivers.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ jedec.o
+
+CFI Flash device mapped on StrongARM SA11x0
+CONFIG_MTD_SA1100
+ This enables access to the flash chips on most platforms based on
+ the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
+ If you have such a board, say 'Y'.
+
+Support for Compaq bootldr partition tables on SA11x0
+CONFIG_MTD_SA1100_REDBOOT_PARTITIONS
+ Enabling this option will cause the kernel to look for a RedBoot
+ FIS (Flash Image System) table in the last erase block of the flash
+ chips detected. If you are using RedBoot on your SA11x0-based board
+ and want Linux to present 'partitions' matching the images which
+ RedBoot has listed, say 'Y'.
+
+Support for Compaq bootldr partition tables on SA11x0
+CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS
+ Enabling this option will cause the kernel to look for a Compaq
+ bootldr partition table on the flash chips detected. If you are
+ using the Compaq bootldr on your SA11x0-based board and want Linux
+ to present 'partitions' matching the images which the bootldr has
+ listed, say 'Y'.
+
+Flash chip mapping in physical memory
+CONFIG_MTD_PHYSMAP
+ This provides a 'mapping' driver which allows the CFI probe and
+ command set driver code to communicate with flash chips which
+ are mapped physically into the CPU's memory. You will need to
+ configure the physical address and size of the flash chips on
+ your particular board as well as the bus width.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ physmap.o
+
+Physical start location of flash chip mapping
+CONFIG_MTD_PHYSMAP_START
+ This is the physical memory location at which the flash chips
+ are mapped on your particular target board. Refer to the
+ memory map which should hopefully be in the documentation for
+ your board.
+
+Physical length of flash chip mapping
+CONFIG_MTD_PHYSMAP_LEN
+ This is the total length of the mapping of the flash chips on
+ your particular board. If there is space, or aliases, in the
+ physical memory map between the chips, this could be larger
+ than the total amount of flash present. Refer to the memory
+ map which should hopefully be in the documentation for your
+ board.
+
+Buswidth of flash in bytes
+CONFIG_MTD_PHYSMAP_BUSWIDTH
+ This is the total width of the data bus of the flash devices
+ in octets. For example, if you have a data bus width of 32
+ bits, you would set the bus width octet value to 4. This is
+ used internally by the CFI drivers.
+
+Flash chip mapping on Sun Microsystems boardsets
+CONFIG_MTD_SUN_UFLASH
+ This provides a 'mapping' driver which supports the way in
+ which user-programmable flash chips are connected on various
+ Sun Microsystems boardsets. This driver will require CFI support
+ in the kernel, so if you did not enable CFI previously, do that now.
+
+Flash chip mapping on Nora
+CONFIG_MTD_NORA
+ If you had to ask, you don't have one. Say 'N'.
+
+Flash chip mapping on Photron PNC-2000
+CONFIG_MTD_PNC2000
+ PNC-2000 is the name of Network Camera product from PHOTRON
+ Ltd. in Japan. It uses CFI-compliant flash.
+
+Flash chip mapping on RPXlite or CLLF PPC board
+CONFIG_MTD_RPXLITE
+ The RPXLite PowerPC board has CFI-compliant chips mapped in
+ a strange sparse mapping. This 'mapping' driver supports that
+ arrangement, allowing the CFI probe and command set driver code
+ to communicate with the chips on the RPXLite board. More at
+ <http://www.embeddedplanet.com/rpx_lite_specification_sheet.htm>.
+
+Flash chip mapping on AMD SC520 CDP board
+CONFIG_MTD_SC520CDP
+ The SC520 CDP board has two banks of CFI-compliant chips and one
+ Dual-in-line JEDEC chip. This 'mapping' driver supports that
+ arrangement, implementing three MTD devices.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ sc520cdp.o
+
+Flash chip mapping on Arcom Control Systems SBC-MediaGX
+CONFIG_MTD_SBC_GXX
+ This provides a driver for the on-board flash of Arcom Control
+ Systems' SBC-GXn family of boards, formerly known as SBC-MediaGX.
+ By default the flash is split into 3 partitions which are accessed
+ as separate MTD devices. This board utilizes Intel StrataFlash.
+ More info at
+ <http://www.arcomcontrols.com/products/icp/pc104/processors/>.
+
+CFI Flash device mapped on D-Box2
+CONFIG_MTD_DBOX2
+ This enables access routines for the flash chips on the Nokia/Sagem
+ D-Box 2 board. If you have one of these boards and would like to use
+ the flash chips on it, say 'Y'.
+
+CFI Flash device mapped on the XScale IQ80310 board
+CONFIG_MTD_IQ80310
+ This enables access routines for the flash chips on the Intel XScale
+ IQ80310 evaluation board. If you have one of these boards and would
+ like to use the flash chips on it, say 'Y'.
+
+CFI Flash device mapped on AMD NetSc520
+CONFIG_MTD_NETSC520
+ This enables access routines for the flash chips on the AMD NetSc520
+ demonstration board. If you have one of these boards and would like
+ to use the flash chips on it, say 'Y'.
+
+Flash chip mapping on Arcom Control Systems ELAN-104NC
+CONFIG_MTD_ELAN_104NC
+ This provides a driver for the on-board flash of the Arcom Control
+ System's ELAN-104NC development board. By default the flash
+ is split into 3 partitions which are accessed as separate MTD
+ devices. This board utilizes Intel StrataFlash. More info at
+ <http://www.arcomcontrols.com/products/icp/pc104/processors/>.
+
+Flash chip mapping on Compaq iPAQ/Bitsy
+CONFIG_MTD_BITSY
+ This provides a driver for the on-board flash found in Compaq's
+ iPAQ Palm PC and their research prototype the Itsy. iPAQ info at
+ <http://www5.compaq.com/products/handhelds/pocketpc/> and the
+ Itsy <http://www.research.digital.com/wrl/projects/Itsy/index.html>.
+
+Flash chip mapping on Compaq iPAQ/Bitsy
+CONFIG_MTD_DC21285
+ This provides a driver for the flash accessed using Intel's
+ 21285 bridge used with Intel's StrongARM processors. More info at
+ <http://developer.intel.com/design/bridge/quicklist/dsc-21285.htm>.
+
+Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board
+CONFIG_MTD_CSTM_MIPS_IXX
+ This provides a mapping driver for the Integrated Tecnology Express,
+ Inc (ITE) QED-4N-S01B eval board and the Globespan IVR Reference
+ Board. It provides the necessary addressing, length, buswidth, vpp
+ code and addition setup of the flash device for these boards. In
+ addition, this mapping driver can be used for other boards via
+ setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/LEN/BUSWIDTH
+ parameters. This mapping will provide one mtd device using one
+ partition. The start address can be offset from the beginning of
+ flash and the len can be less than the total flash device size to
+ allow a window into the flash. Both CFI and JEDEC probes are
+ called.
+
+Physical start location of flash chip mapping
+CONFIG_MTD_CSTM_MIPS_IXX_START
+ This is the physical memory location that the MTD driver will
+ use for the flash chips on your particular target board.
+ Refer to the memory map which should hopefully be in the
+ documentation for your board.
+
+Physical length of flash chip mapping
+CONFIG_MTD_CSTM_MIPS_IXX_LEN
+ This is the total length that the MTD driver will use for the
+ flash chips on your particular board. Refer to the memory
+ map which should hopefully be in the documentation for your
+ board.
+
+Physical bus width of flash mapping in bytes
+CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH
+ This is the total bus width of the mapping of the flash chips
+ on your particular board.
+
+JEDEC Flash device mapped on Mixcom piggyback card
+CONFIG_MTD_MIXMEM
+ This supports the paging arrangement for access to flash chips
+ on the MixCOM piggyback card, allowing the flash chip drivers
+ to get on with their job of driving the flash chips without
+ having to know about the paging. If you have one of these boards,
+ you probably want to enable this mapping driver. More info is at
+ <http://www.itc.hu/>.
+
+JEDEC Flash device mapped on Octagon 5066 SBC
+CONFIG_MTD_OCTAGON
+ This provides a 'mapping' driver which supports the way in which
+ the flash chips are connected in the Octagon-5066 Single Board
+ Computer. More information on the board is available at
+ <http://www.octagonsystems.com/Products/5066/5066.html>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ octagon-5066.o
+
+JEDEC Flash device mapped on Tempustech VMAX SBC301
+CONFIG_MTD_VMAX
+ This provides a 'mapping' driver which supports the way in which
+ the flash chips are connected in the Tempustech VMAX SBC301 Single
+ Board Computer. More information on the board is available at
+ <http://www.tempustech.com/tt301.htm>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ vmax301.o
+
+Support for NAND flash devices
+CONFIG_MTD_NAND
+ This enables support for accessing all type of NAND flash
+ devices.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ nand.o
+
+Support for software ECC algorithm
+CONFIG_MTD_NAND_ECC
+ This enables software-based ECC for use with NAND flash chips. It
+ can detect and correct 1 bit errors per 256 byte blocks. This
+ should be used to increase the reliability of the data stored and
+ read on the device.
+
+Support for verify read after write
+CONFIG_MTD_NAND_VERIFY_WRITE
+ This adds an extra check when data is written to the flash. The
+ NAND flash device internally checks only bits transitioning
+ from 1 to 0. There is a rare possibility that even though the
+ device thinks the write was successful, a bit could have been
+ flipped accidentally due to device wear, gamma rays, whatever.
+ Enable this if you are really paranoid.
+
+Support for the SPIA board
+CONFIG_MTD_NAND_SPIA
+ If you had to ask, you don't have one. Say 'N'.
+
+M-Systems Disk-On-Chip 1000 support
+CONFIG_MTD_DOC1000
+ This provides an MTD device driver for the M-Systems DiskOnChip
+ 1000 devices, which are obsolete so you probably want to say 'N'.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ doc1000.o
+
+M-Systems Disk-On-Chip 2000 and Millennium support
+CONFIG_MTD_DOC2000
+ This provides an MTD device driver for the M-Systems DiskOnChip
+ 2000 and Millennium devices. Originally designed for the DiskOnChip
+ 2000, it also now includes support for the DiskOnChip Millennium.
+ If you have problems with this driver and the DiskOnChip Millennium,
+ you may wish to try the alternative Millennium driver below. To use
+ the alternative driver, you will need to undefine DOC_SINGLE_DRIVER
+ in the <file:drivers/mtd/devices/docprobe.c> source code.
+
+ If you use this device, you probably also want to enable the NFTL
+ 'NAND Flash Translation Layer' option below, which is used to
+ emulate a block device by using a kind of file system on the flash
+ chips.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ doc2000.o
+
+Alternative Disk-On-Chip Millennium support
+CONFIG_MTD_DOC2001
+ This provides an alternative MTD device driver for the M-Systems
+ DiskOnChip Millennium devices. Use this if you have problems with
+ the combined DiskOnChip 2000 and Millennium driver above. To get
+ the DiskOnChip probe code to load and use this driver instead of
+ the other one, you will need to undefine DOC_SINGLE_DRIVER near
+ the beginning of <file:drivers/mtd/devices/docprobe.c>.
+
+ If you use this device, you probably also want to enable the NFTL
+ 'NAND Flash Translation Layer' option below, which is used to
+ emulate a block device by using a kind of file system on the flash
+ chips.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ doc2001.o
+
+Probe for DiskOnChip devices
+CONFIG_MTD_DOCPROBE
+ This isn't a real config option, it's derived.
+
+Advanced detection options for DiskOnChip
+CONFIG_MTD_DOCPROBE_ADVANCED
+ This option allows you to specify nonstandard address at which to
+ probe for a DiskOnChip, or to change the detection options. You
+ are unlikely to need any of this unless you are using LinuxBIOS.
+ Say 'N'.
+
+Probe for 0x55 0xAA BIOS Extension Signature
+CONFIG_MTD_DOCPROBE_55AA
+ Check for the 0x55 0xAA signature of a DiskOnChip, and do not
+ continue with probing if it is absent. The signature will always be
+ present for a DiskOnChip 2000 or a normal DiskOnChip Millennium.
+ Only if you have overwritten the first block of a DiskOnChip
+ Millennium will it be absent. Enable this option if you are using
+ LinuxBIOS or if you need to recover a DiskOnChip Millennium on which
+ you have managed to wipe the first block.
+
+Physical address of DiskOnChip
+CONFIG_MTD_DOCPROBE_ADDRESS
+ By default, the probe for DiskOnChip devices will look for a
+ DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
+ This option allows you to specify a single address at which to probe
+ for the device, which is useful if you have other devices in that
+ range which get upset when they are probed.
+
+ (Note that on PowerPC, the normal probe will only check at
+ 0xE4000000.)
+
+ Normally, you should leave this set to zero, to allow the probe at
+ the normal addresses.
+
+Probe high addresses
+CONFIG_MTD_DOCPROBE_HIGH
+ By default, the probe for DiskOnChip devices will look for a
+ DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
+ This option changes to make it probe between 0xFFFC8000 and
+ 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be
+ useful to you. Say 'N'.
+
+Ramix PMC551 PCI Mezzanine ram card support
+CONFIG_MTD_PMC551
+ This provides a MTD device driver for the Ramix PMC551 RAM PCI card
+ from Ramix Inc. <http://www.ramix.com/products/memory/pmc551.html>.
+ These devices come in memory configurations from 32M - 1G. If you
+ have one, you probably want to enable this.
+
+ If this driver is compiled as a module you get the ability to select
+ the size of the aperture window pointing into the devices memory.
+ What this means is that if you have a 1G card, normally the kernel
+ will use a 1G memory map as its view of the device. As a module,
+ you can select a 1M window into the memory and the driver will
+ "slide" the window around the PMC551's memory. This was
+ particularly useful on the 2.2 kernels on PPC architectures as there
+ was limited kernel space to deal with.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ pmc551.o
+
+PMC551 256M DRAM Bugfix
+CONFIG_MTD_PMC551_BUGFIX
+ Some of Ramix's PMC551 boards with 256M configurations have invalid
+ column and row mux values. This option will fix them, but will
+ break other memory configurations. If unsure say N.
+
+PMC551 Debugging
+CONFIG_MTD_PMC551_DEBUG
+ This option makes the PMC551 more verbose during its operation and
+ is only really useful if you are developing on this driver or
+ suspect a possible hardware or driver bug. If unsure say N.
+
+Use extra onboard system memory as MTD device
+CONFIG_MTD_SLRAM
+ If your CPU cannot cache all of the physical memory in your machine,
+ you can still use it for storage or swap by using this driver to
+ present it to the system as a Memory Technology Device.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ slram.o
+
+DEC MS02-NV NVRAM module support
+CONFIG_MTD_MS02NV
+ This is a MTD driver for the DEC's MS02-type (54-20948-01) battery
+ backed-up NVRAM module. The module was originally meant as an NFS
+ accelerator. Say Y here if you have a DECstation 5000/2x0 or a
+ DECsystem 5900 equipped with such a module.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module will
+ be called ms02-nv.o.
+
+Debugging RAM test driver
+CONFIG_MTD_MTDRAM
+ This enables a test MTD device driver which uses vmalloc() to
+ provide storage. You probably want to say 'N' unless you're
+ testing stuff.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ mtdram.o
+
+MTDRAM erase block size in KB
+CONFIG_MTDRAM_ERASE_SIZE
+ This allows you to configure the size of the erase blocks in the
+ device emulated by the MTDRAM driver. If the MTDRAM driver is built
+ as a module, it is also possible to specify this as a parameter when
+ loading the module.
+
+MTDRAM device size in KB
+CONFIG_MTDRAM_TOTAL_SIZE
+ This allows you to configure the total size of the MTD device
+ emulated by the MTDRAM driver. If the MTDRAM driver is built
+ as a module, it is also possible to specify this as a parameter when
+ loading the module.
+
+SRAM Hexadecimal Absolute position or 0
+CONFIG_MTDRAM_ABS_POS
+ If you have system RAM accessible by the CPU but not used by Linux
+ in normal operation, you can give the physical address at which the
+ available RAM starts, and the MTDRAM driver will use it instead of
+ allocating space from Linux's available memory. Otherwise, leave
+ this set to zero. Most people will want to leave this as zero.
+
+CFI Flash device mapping on the Flaga Digital Module
+CONFIG_MTD_CFI_FLAGADM
+ Mapping for the Flaga digital module. If you don´t have one, ignore
+ this setting.
+
+Momenco Ocelot boot flash device
+CONFIG_MTD_OCELOT
+ This enables access routines for the boot flash device and for the
+ NVRAM on the Momenco Ocelot board. If you have one of these boards
+ and would like access to either of these, say 'Y'.
+
+Support for absent chips in bus mapping
+CONFIG_MTD_ABSENT
+ This option enables support for a dummy probing driver used to
+ allocated placeholder MTD devices on systems that have socketed
+ or removable media. Use of this driver as a fallback chip probe
+ preserves the expected registration order of MTD device nodes on
+ the system regardless of media presence. Device nodes created
+ with this driver will return -ENODEV upon access.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ map_absent.o
+
+MTD emulation using block device
+CONFIG_MTD_BLKMTD
+ This driver allows a block device to appear as an MTD. It would
+ generally be used in the following cases:
+
+ Using Compact Flash as an MTD, these usually present themselves to
+ the system as an ATA drive.
+ Testing MTD users (eg JFFS2) on large media and media that might
+ be removed during a write (using the floppy drive).
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ blkmtd.o
+
+Cirrus CDB89712 evaluation board mappings
+CONFIG_MTD_CDB89712
+ This enables access to the flash or ROM chips on the CDB89712 board.
+ (This board has 8 MB of Intel Strataflash, a 128 byte boot ROM, and 48 KB of
+ internal SRAM. This driver provides MTD devices for all three components.)
+ If you have such a board, say 'Y'.
+
+Detect non-CFI AMD/JEDEC-compatible flash chips
+CONFIG_MTD_JEDECPROBE
+ This option enables JEDEC-style probing of flash chips which are not
+ compatible with the Common Flash Interface, but will use the common
+ CFI-targetted flash drivers for any chips which are identified which
+ are in fact compatible in all but the probe method. This actually
+ covers most AMD/Fujitsu-compatible chips, and will shortly cover also
+ non-CFI Intel chips (that code is in MTD CVS and should shortly be sent
+ for inclusion in Linus' tree)
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ jedec_probe.o
+
+BIOS flash chip on Intel L440GX boards
+CONFIG_MTD_L440GX
+ Support for treating the BIOS flash chip on Intel L440GX motherboards
+ as an MTD device - with this you can reprogram your BIOS.
+
+ BE VERY CAREFUL.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ l440gx.o
+
+28F160xx flash driver for LART
+CONFIG_MTD_LART
+ This enables the flash driver for LART. Please note that you do
+ not need any mapping/chip driver for LART. This one does it all
+ for you, so go disable all of those if you enabled some of them (:
+
+Older (theoretically obsoleted now) drivers for non-CFI chips
+CONFIG_MTD_OBSOLETE_CHIPS
+ This option does not enable any code directly, but will allow you to
+ select some other chip drivers which are now considered obsolete,
+ because the generic CONFIG_JEDEC_PROBE code above should now detect
+ the chips which are supported by these drivers, and allow the generic
+ CFI-compatible drivers to drive the chips. Say 'N' here unless you have
+ already tried the CONFIG_JEDEC_PROBE method and reported its failure
+ to the MTD mailing list at <linux-mtd@lists.infradead.org>
+
+CFI Flash device mapped on Hitachi SolutionEngine
+CONFIG_MTD_SOLUTIONENGINE
+ This enables access to the flash chips on the Hitachi SolutionEngine and
+ similar boards. Say 'Y' if you are building a kernel for such a board.
+
+CFI Flash device mapped on TQM8XXL PPC board
+CONFIG_MTD_TQM8XXL
+ The TQM8xxL PowerPC board has up to two banks of CFI-compliant
+ chips, currently uses AMD one. This 'mapping' driver supports
+ that arrangement, allowing the CFI probe and command set driver
+ code to communicate with the chips on the TQM8xxL board. More at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+Darkness
+CONFIG_MEMORY_SET
+ This is an option about which you will never be asked a question.
+ Therefore, I conclude that you do not exist - go away.
+
+ There is a grue here.
+
+Physical memory size
+CONFIG_MEMORY_SIZE
+ This sets the default memory size assumed by your SH kernel. It can
+ be overridden as normal by the 'mem=' argument on the kernel command
+ line. If unsure, consult your board specifications or just leave it
+ as 0x00400000 which was the default value before this became
+ configurable.
+
+Cache and PCI noncoherent
+CONFIG_SH_PCIDMA_NONCOHERENT
+ Enable this option if your platform does not have a CPU cache which
+ remains coherent with PCI DMA. It is safest to say 'Y', although you
+ will see better performance if you can say 'N', because the PCI DMA
+ code will not have to flush the CPU's caches. If you have a PCI host
+ bridge integrated with your SH CPU, refer carefully to the chip specs
+ to see if you can say 'N' here. Otherwise, leave it as 'Y'.
+
+USB (Universal Serial Bus) support
+CONFIG_USB
+ Universal Serial Bus (USB) is a specification for a serial bus
+ subsystem which offers higher speeds and more features than the
+ traditional PC serial port. The bus supplies power to peripherals
+ and allows for hot swapping. Up to 127 USB peripherals can be
+ connected to a single USB port in a tree structure. The USB port is
+ the root of the tree, the peripherals are the leaves and the inner
+ nodes are special USB devices called hubs. Many newer PC's have USB
+ ports and newer peripherals such as scanners, keyboards, mice,
+ modems, and printers support the USB protocol and can be connected
+ to the PC via those ports.
+
+ Say Y here if your computer has a USB port and you want to use USB
+ devices. You then need to say Y to at least one of "UHCI support"
+ or "OHCI support" below (the type of interface that the USB hardware
+ in your computer provides to the operating system) and then choose
+ from among the drivers for USB peripherals. You may want to check
+ out the information provided in <file:Documentation/usb/> and
+ especially the links given in <file:Documentation/usb/usb-help.txt>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usbcore.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB verbose debug messages
+CONFIG_USB_DEBUG
+ Say Y here if you want the USB core & hub drivers to produce a bunch
+ of debug messages to the system log. Select this if you are having a
+ problem with USB support and want to see more of what is going on.
+
+USB long timeout for slow-responding devices (some MGE Ellipse UPSes)
+CONFIG_USB_LONG_TIMEOUT
+ This option makes the standard time out a bit longer. Basically,
+ some devices are just slow to respond, so this makes usb more
+ patient. There should be no harm in selecting this, but it is
+ needed for some MGE Ellipse UPSes.
+
+ If you have an MGE Ellipse UPS, or you see timeouts in HID
+ transactions, say Y; otherwise say N.
+
+EHCI (USB 2.0) support
+CONFIG_USB_EHCI_HCD
+ The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
+ "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
+ If your USB host controller supports USB 2.0, you will likely want to
+ configure this Host Controller Driver. At this writing, the primary
+ implementation of EHCI is a chip from NEC, widely available in add-on
+ PCI cards, but implementations are in the works from other vendors
+ including Intel and Philips. Motherboard support is appearing.
+
+ EHCI controllers are packaged with "companion" host controllers (OHCI
+ or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports
+ will connect to EHCI if it the device is high speed, otherwise they
+ connect to a companion controller. If you configure EHCI, you should
+ probably configure the OHCI (for NEC and some other vendors) USB Host
+ Controller Driver too.
+
+ You may want to read <file:Documentation/usb/ehci.txt>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ehci-hcd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+UHCI (Intel PIIX4, VIA, ...) support
+CONFIG_USB_UHCI
+ The Universal Host Controller Interface is a standard by Intel for
+ accessing the USB hardware in the PC (which is also called the USB
+ host controller). If your USB host controller conforms to this
+ standard, you may want to say Y, but see below. All recent boards
+ with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
+ i810, i820) conform to this standard. Also all VIA PCI chipsets
+ (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
+ 133).
+
+ Currently there exist two drivers for UHCI host controllers: this
+ one and the so-called JE driver, which you can get from
+ "UHCI alternate (JE) support", below. You need only one.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usb-uhci.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+UHCI (Intel PIIX4, VIA, ...) alternate (JE) support
+CONFIG_USB_UHCI_ALT
+ The Universal Host Controller Interface is a standard by Intel for
+ accessing the USB hardware in the PC (which is also called the USB
+ host controller). If your USB host controller conforms to this
+ standard, you may want to say Y, but see below. All recent boards
+ with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
+ i810, i820) conform to this standard. Also all VIA PCI chipsets
+ (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
+ 133). If unsure, say Y.
+
+ Currently there exist two drivers for UHCI host controllers: this
+ so-called JE driver, and the one you get from "UHCI support", above.
+ You need only one.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called uhci.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support
+CONFIG_USB_OHCI
+ The Open Host Controller Interface is a standard by
+ Compaq/Microsoft/National for accessing the USB PC hardware (also
+ called USB host controller). If your USB host controller conforms to
+ this standard, say Y. The USB host controllers on most non-Intel
+ architectures and on several x86 compatibles with non-Intel chipsets
+ -- like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V,
+ Aladdin Pro..) -- conform to this standard.
+
+ You may want to read <file:Documentation/usb/ohci.txt>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usb-ohci.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Human Interface Device (full HID) support
+CONFIG_USB_HID
+ Say Y here if you want full HID support to connect keyboards,
+ mice, joysticks, graphic tablets, or any other HID based devices
+ to your computer via USB. You also need to select HID Input layer
+ support (below) if you want to use keyboards, mice, joysticks and
+ the like.
+
+ You can't use this driver and the HIDBP (Boot Protocol) keyboard
+ and mouse drivers at the same time. More information is available:
+ <file:Documentation/input/input.txt>.
+
+ If unsure, say Y.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called hid.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB HID Input layer support
+CONFIG_USB_HIDINPUT
+ Say Y here if you want to use a USB keyboard, mouse or joystick,
+ or any other HID input device. You also need Input layer support,
+ (CONFIG_INPUT) which you select under "Input core support".
+
+ If unsure, say Y.
+
+/dev/usb/hiddev raw HID device support
+CONFIG_USB_HIDDEV
+ Say Y here if you want to support HID devices (from the USB
+ specification standpoint) that aren't strictly user interface
+ devices, like monitor controls and Uninterruptable Power Supplies.
+
+ This module supports these devices separately using a separate
+ event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
+ This driver requires CONFIG_USB_HID.
+
+ If unsure, say Y.
+
+USB HIDBP Keyboard (basic) support
+CONFIG_USB_KBD
+ Say Y here only if you are absolutely sure that you don't want
+ to use the generic HID driver for your USB keyboard and prefer
+ to use the keyboard in its limited Boot Protocol mode instead.
+
+ This is almost certainly not what you want.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usbkbd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+ If even remotely unsure, say N.
+
+USB HIDBP Mouse (basic) support
+CONFIG_USB_MOUSE
+ Say Y here only if you are absolutely sure that you don't want
+ to use the generic HID driver for your USB keyboard and prefer
+ to use the keyboard in its limited Boot Protocol mode instead.
+
+ This is almost certainly not what you want.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usbmouse.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+ If even remotely unsure, say N.
+
+Wacom Intuos/Graphire tablet support
+CONFIG_USB_WACOM
+ Say Y here if you want to use the USB version of the Wacom Intuos
+ or Graphire tablet. Make sure to say Y to "Mouse support"
+ (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+ (CONFIG_INPUT_EVDEV) as well.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called wacom.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Aiptek 6000U/8000U tablet support
+CONFIG_USB_AIPTEK
+ Say Y here if you want to use the USB version of the Aiptek 6000U/8000U
+ tablet. Make sure to say Y to "Event interface support"
+ (CONFIG_INPUT_EVDEV) as well.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called aiptek.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Use input layer for ADB devices
+CONFIG_INPUT_ADBHID
+ Say Y here if you want to have ADB (Apple Desktop Bus) HID devices
+ such as keyboards, mice, joysticks, or graphic tablets handled by
+ the input layer. If you say Y here, make sure to say Y to the
+ corresponding drivers "Keyboard support" (CONFIG_INPUT_KEYBDEV),
+ "Mouse Support" (CONFIG_INPUT_MOUSEDEV) and "Event interface
+ support" (CONFIG_INPUT_EVDEV) as well.
+
+ If you say N here, you still have the option of using the old ADB
+ keyboard and mouse drivers.
+
+ If unsure, say Y.
+
+Input core support
+CONFIG_INPUT
+ Say Y here if you want to enable any of the following options for
+ USB Human Interface Device (HID) support.
+
+ Say Y here if you want to enable any of the USB HID options in the
+ USB support section which require Input core support.
+
+ Otherwise, say N.
+
+Keyboard support
+CONFIG_INPUT_KEYBDEV
+ Say Y here if you want your USB HID keyboard (or an ADB keyboard
+ handled by the input layer) to be able to serve as a system
+ keyboard.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called keybdev.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Mouse support
+CONFIG_INPUT_MOUSEDEV
+ Say Y here if you want your USB HID mouse (or ADB mouse handled by
+ the input layer) to be accessible as char devices 13:32+ -
+ /dev/input/mouseX and 13:63 - /dev/input/mice as an emulated ImPS/2
+ mouse. That way, all user space programs will be able to use your
+ mouse.
+
+ If unsure, say Y.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called mousedev.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Horizontal screen resolution
+CONFIG_INPUT_MOUSEDEV_SCREEN_X
+ If you're using a digitizer, or a graphic tablet, and want to use
+ it as a mouse then the mousedev driver needs to know the X window
+ screen resolution you are using to correctly scale the data. If
+ you're not using a digitizer, this value is ignored.
+
+Vertical screen resolution
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y
+ If you're using a digitizer, or a graphic tablet, and want to use
+ it as a mouse then the mousedev driver needs to know the X window
+ screen resolution you are using to correctly scale the data. If
+ you're not using a digitizer, this value is ignored.
+
+Joystick support
+CONFIG_INPUT_JOYDEV
+ Say Y here if you want your USB HID joystick or gamepad to be
+ accessible as char device 13:0+ - /dev/input/jsX device.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called joydev.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Event interface support
+CONFIG_INPUT_EVDEV
+ Say Y here if you want your USB or ADB HID device events be
+ accessible under char device 13:64+ - /dev/input/eventX in a generic
+ way. This is the future ...
+
+USB Scanner support
+CONFIG_USB_SCANNER
+ Say Y here if you want to connect a USB scanner to your computer's
+ USB port. Please read <file:Documentation/usb/scanner.txt> and
+ <file:Documentation/usb/scanner-hp-sane.txt> for more information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called scanner.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+HP 5300C scanner support
+CONFIG_USB_HP5300
+ Say Y here if you want to connect a HP5300C scanner to your
+ computer's USB port.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called hp5300.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Audio support
+CONFIG_USB_AUDIO
+ Say Y here if you want to connect USB audio equipment such as
+ speakers to your computer's USB port.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called audio.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+EMI 2|6 USB Audio interface support
+CONFIG_USB_EMI26
+ This driver loads firmware to Emagic EMI 2|6 low latency USB
+ Audio interface.
+
+ After firmware load the device is handled with standard linux
+ USB Audio driver.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called audio.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Modem (CDC ACM) support
+CONFIG_USB_ACM
+ This driver supports USB modems and ISDN adapters which support the
+ Communication Device Class Abstract Control Model interface.
+ Please read <file:Documentation/usb/acm.txt> for details.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called acm.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB serial converter support
+CONFIG_USB_SERIAL
+ Say Y here if you have a USB device that provides normal serial
+ ports, or acts like a serial device, and you want to connect it to
+ your USB bus.
+
+ Please read <file:Documentation/usb/usb-serial.txt> for more
+ information on the specifics of the different devices that are
+ supported, and on how to use them.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usbserial.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Generic Serial Driver
+CONFIG_USB_SERIAL_GENERIC
+ Say Y here if you want to use the generic USB serial driver. Please
+ read <file:Documentation/usb/usb-serial.txt> for more information on
+ using this driver. It is recommended that the "USB Serial converter
+ support" be compiled as a module for this driver to be used
+ properly.
+
+USB ConnectTech WhiteHEAT Serial Driver
+CONFIG_USB_SERIAL_WHITEHEAT
+ Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+ USB to serial converter device.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called whiteheat.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Handspring Visor Driver
+CONFIG_USB_SERIAL_VISOR
+ Say Y here if you want to connect to your HandSpring Visor, Palm
+ m500 or m505 through its USB docking station. See
+ <http://usbvisor.sourceforge.net/> for more information on using this
+ driver.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called visor.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Compaq iPAQ Driver
+CONFIG_USB_SERIAL_IPAQ
+ Say Y here if you want to connect to your Compaq iPAQ, HP Jornada 548/568
+ or Casio EM500 running Windows CE 3.0 or PocketPC 2002 using a USB
+ cradle/cable. For information on using the driver,
+ read <file:Documentation/usb/usb-serial.txt>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ipaq.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB IR Dongle Serial Driver
+CONFIG_USB_SERIAL_IR
+ Say Y here if you want to enable simple serial support for USB IrDA
+ devices. This is useful if you do not want to use the full IrDA
+ stack.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ir-usb.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Belkin and Paracom Single Port Serial Driver
+CONFIG_USB_SERIAL_BELKIN
+ Say Y here if you want to use a Belkin USB Serial single port
+ adaptor (F5U103 is one of the model numbers) or the Peracom single
+ port USB to serial adapter.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called belkin_sa.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB FTDI Single Port Serial Driver
+CONFIG_USB_SERIAL_FTDI_SIO
+ Say Y here if you want to use a FTDI SIO single port USB to serial
+ converter device. The implementation I have is called the USC-1000.
+ This driver has also be tested with the 245 and 232 devices.
+
+ See <http://ftdi-usb-sio.sourceforge.net/> for more
+ information on this driver and the device.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ftdi_sio.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Keyspan PDA Single Port Serial Driver
+CONFIG_USB_SERIAL_KEYSPAN_PDA
+ Say Y here if you want to use a Keyspan PDA single port USB to
+ serial converter device. This driver makes use of firmware
+ developed from scratch by Brian Warner.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called keyspan_pda.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Xircom / Entregra Single Port Serial Driver
+CONFIG_USB_SERIAL_XIRCOM
+ Say Y here if you want to use a Xircom or Entregra single port USB to
+ serial converter device. This driver makes use of firmware
+ developed from scratch by Brian Warner.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called keyspan_pda.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Keyspan USA-xxx Serial Driver
+CONFIG_USB_SERIAL_KEYSPAN
+ Say Y here if you want to use Keyspan USB to serial converter
+ devices. This driver makes use of Keyspan's official firmware
+ and was developed with their support. You must also include
+ firmware to support your particular device(s).
+
+ See <http://misc.nu/hugh/keyspan.html> for more information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called keyspan.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Keyspan USA-28 Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA28
+ Say Y here to include firmware for the USA-28 converter.
+
+USB Keyspan USA-28X Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA28X
+ Say Y here to include firmware for the USA-28X converter.
+ Be sure you have a USA-28X, there are also 28XA and 28XB
+ models, the label underneath has the actual part number.
+
+USB Keyspan USA-28XA Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA
+ Say Y here to include firmware for the USA-28XA converter.
+ Be sure you have a USA-28XA, there are also 28X and 28XB
+ models, the label underneath has the actual part number.
+
+USB Keyspan USA-28XB Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB
+ Say Y here to include firmware for the USA-28XB converter.
+ Be sure you have a USA-28XB, there are also 28X and 28XA
+ models, the label underneath has the actual part number.
+
+USB Keyspan USA-19 Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA19
+ Say Y here to include firmware for the USA-19 converter.
+
+USB Keyspan USA-18X Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA18X
+ Say Y here to include firmware for the USA-18X converter.
+
+USB Keyspan USA-19W Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA19W
+ Say Y here to include firmware for the USA-19W converter.
+
+USB Keyspan USA-19QW Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW
+ Say Y here to include firmware for the USA-19QW converter.
+
+USB Keyspan USA-19QI Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI
+ Say Y here to include firmware for the USA-19QI converter.
+
+USB Keyspan USA-49W Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA49W
+ Say Y here to include firmware for the USA-49W converter.
+
+USB ZyXEL omni.net LCD Plus Driver
+CONFIG_USB_SERIAL_OMNINET
+ Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called omninet.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Digi International AccelePort USB Serial Driver
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT
+ Say Y here if you want to use Digi AccelePort USB 2 or 4 devices,
+ 2 port (plus parallel port) and 4 port USB serial converters. The
+ parallel port on the USB 2 appears as a third serial port on Linux.
+ The Digi Acceleport USB 8 is not yet supported by this driver.
+
+ This driver works under SMP with the usb-uhci driver. It does not
+ work under SMP with the uhci driver.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called digi_acceleport.o. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+USB Empeg empeg-car Mark I/II Driver
+CONFIG_USB_SERIAL_EMPEG
+ Say Y here if you want to connect to your Empeg empeg-car Mark I/II
+ mp3 player via USB. The driver uses a single ttyUSB{0,1,2,...}
+ device node. See <file:Documentation/usb/usb-serial.txt> for more
+ tidbits of information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called empeg.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB MCT Single Port Serial Driver
+CONFIG_USB_SERIAL_MCT_U232
+ Say Y here if you want to use a USB Serial single port adapter from
+ Magic Control Technology Corp. (U232 is one of the model numbers).
+
+ This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB
+ BAY devices.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called mct_u232.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Prolific 2303 Single Port Serial Driver
+CONFIG_USB_SERIAL_PL2303
+ Say Y here if you want to use the PL2303 USB Serial single port
+ adapter from Prolific.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pl2303.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB REINER SCT cyberJack pinpad/e-com chipcard reader
+CONFIG_USB_SERIAL_CYBERJACK
+ Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard
+ reader. This is an interface to ISO 7816 compatible contactbased
+ chipcards, e.g. GSM SIMs.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called cyberjack.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+
+USB Edgeport Serial Driver
+CONFIG_USB_SERIAL_EDGEPORT
+ Say Y here if you want to use any of the following devices from
+ Inside Out Networks (Digi):
+ Edgeport/4
+ Rapidport/4
+ Edgeport/4t
+ Edgeport/2
+ Edgeport/4i
+ Edgeport/2i
+ Edgeport/421
+ Edgeport/21
+ Edgeport/8
+ Edgeport/8 Dual
+ Edgeport/2D8
+ Edgeport/4D8
+ Edgeport/8i
+ Edgeport/2 DIN
+ Edgeport/4 DIN
+ Edgeport/16 Dual
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called io_edgeport.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+USB PalmConnect (and other KL5KUSB105-based) Single Port Serial Driver
+CONFIG_USB_SERIAL_KLSI
+ Say Y here if you want to use a KL5KUSB105 - based single port
+ serial adapter. The most widely known -- and currently the only
+ tested -- device in this category is the PalmConnect USB Serial
+ adapter sold by Palm Inc. for use with their Palm III and Palm V
+ series PDAs.
+
+ Please read <file:Documentation/usb/usb-serial.txt> for more
+ information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called kl5kusb105.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Serial Converter verbose debug
+CONFIG_USB_SERIAL_DEBUG
+ Say Y here if you want verbose debug messages from the USB Serial
+ Drivers sent to the kernel debug log.
+
+USB Printer support
+CONFIG_USB_PRINTER
+ Say Y here if you want to connect a USB printer to your computer's
+ USB port.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called printer.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB IBM (Xirlink) C-It Camera support
+CONFIG_USB_IBMCAM
+ Say Y here if you want to connect a IBM "C-It" camera, also known as
+ "Xirlink PC Camera" to your computer's USB port. For more
+ information, read <file:Documentation/usb/ibmcam.txt>.
+
+ This driver uses the Video For Linux API. You must enable
+ (Y or M in config) Video For Linux (under Character Devices)
+ to use this driver. Information on this API and pointers to
+ "v4l" programs may be found on the WWW at
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ibmcam.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. This
+ camera has several configuration options which can be specified when
+ you load the module. Read <file:Documentation/usb/ibmcam.txt> to
+ learn more.
+
+USB OV511 Camera support
+CONFIG_USB_OV511
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. See <file:Documentation/usb/ov511.txt> for more
+ information and for a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Character Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ov511.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Communication Class Ethernet device support
+CONFIG_USB_CDCETHER
+ This driver supports devices conforming to the Communication Device
+ Class Ethernet Control Model. This is used in some cable modems.
+ For more details on the specification, get the Communication Device
+ Class specification from <http://www.usb.org/>.
+
+ This driver should work with the following devices:
+ * Ericsson PipeRider (all variants)
+ * Motorola (DM100 and SB4100)
+ * Broadcom Cable Modem (reference design)
+ * Toshiba PCX1100U and possibly other cable modems
+ * Sharp Zaurus SL-5000D
+
+ The device creates a network device (ethX, where X depends on what
+ other networking devices you have in use), as for a normal PCI
+ or ISA based ethernet network card.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called CDCEther.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+NetChip 1080-based USB Host-to-Host Link
+CONFIG_USB_NET1080
+ The NetChip 1080 is a USB 1.1 host controller. NetChip has a web
+ site with technical information at <http://www.netchip.com/>.
+
+Philips webcam support
+CONFIG_USB_PWC
+ Say Y or M here if you want to use one of these Philips USB webcams:
+ PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
+ the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
+ by this driver and never will be.
+
+ This driver has an optional plugin, which is distributed as a binary
+ module only. It contains code that allow you to use higher
+ resolutions and framerates but may not be distributed as source.
+ But even without this plugin you can these cams for most
+ applications.
+
+ See <file:Documentation/usb/philips.txt> for more information and
+ installation instructions.
+
+ The built-in microphone is enabled by selecting USB Audio support.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Character Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pwc.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB SE401 Camera support
+CONFIG_USB_SE401
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. See <file:Documentation/usb/se401.txt> for more
+ information and for a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called se401.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB STV680 (Pencam) Camera support
+CONFIG_USB_STV680
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. This includes the Pencam line of cameras.
+ See <file:Documentation/usb/stv680.txt> for more information and for
+ a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called stv680.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Vicam
+CONFIG_USB_VICAM
+ Say Y here if you have 3com homeconnect camera (vicam).
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called vicam.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+
+Pegasus/Pegasus II based USB-Ethernet device support
+CONFIG_USB_PEGASUS
+ Say Y here if you know you have Pegasus or Pegasus-II based adapter.
+ If in doubt then look at linux/drivers/usb/pegasus.h for the complete
+ list of supported devices.
+ If your particular adapter is not in the list and you are _sure_ it
+ is Pegasus or Pegasus-II based then send me (pmanolov@users.sourceforge.net)
+ vendor and device IDs.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pegasus.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Realtek RTL8150 based USB-Ethernet device support
+CONFIG_USB_RTL8150
+ Say Y here if you have RTL8150 based usb-ethernet adapter.
+ Send me (petkan@users.sourceforge.net) any comments you may have.
+ You can also check for updates at <http://pegasus2.sourceforge.net/>
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called rtl8150.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB KLSI KL5USB101-based Ethernet device support
+CONFIG_USB_KAWETH
+ Say Y here if you want to use one of the following 10Mbps only
+ USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
+ 3Com 3C19250
+ ADS USB-10BT
+ ATEN USB Ethernet
+ ASANTE USB To Ethernet Adapter
+ AOX Endpoints USB Ethernet
+ Correga K.K.
+ D-Link DSB-650C and DU-E10
+ Entrega / Portgear E45
+ I-O DATA USB-ET/T
+ Jaton USB Ethernet Device Adapter
+ Kingston Technology USB Ethernet Adapter
+ Linksys USB10T
+ Mobility USB-Ethernet Adapter
+ NetGear EA-101
+ Peracom Enet and Enet2
+ Portsmith Express Ethernet Adapter
+ Shark Pocket Adapter
+ SMC 2202USB
+ Sony Vaio port extender
+
+ This driver is likely to work with most 10Mbps only USB Ethernet
+ adapters, including some "no brand" devices. It does NOT work on
+ SmartBridges smartNIC or on Belkin F5U111 devices - you should use
+ the CATC NetMate driver for those. If you are not sure which one
+ you need, select both, and the correct one should be selected for
+ you.
+
+ This driver makes the adapter appear as a normal Ethernet interface,
+ typically on eth0, if it is the only ethernet device, or perhaps on
+ eth1, if you have a PCI or ISA ethernet card installed.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called kaweth.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB CATC NetMate-based Ethernet device support
+CONFIG_USB_CATC
+ Say Y if you want to use one of the following 10Mbps USB Ethernet
+ device based on the EL1210A chip. Supported devices are:
+ Belkin F5U011
+ Belkin F5U111
+ CATC NetMate
+ CATC NetMate II
+ smartBridges smartNIC
+
+ This driver makes the adapter appear as a normal Ethernet interface,
+ typically on eth0, if it is the only ethernet device, or perhaps on
+ eth1, if you have a PCI or ISA ethernet card installed.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called catc.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Kodak DC-2xx Camera support
+CONFIG_USB_DC2XX
+ Say Y here if you want to connect this type of still camera to your
+ computer's USB port. See <file:Documentation/usb/dc2xx.txt> for
+ more information; some non-Kodak cameras may also work with this
+ driver, given application support (such as <http://www.gphoto.org/>).
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dc2xx.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Mustek MDC800 Digital Camera support
+CONFIG_USB_MDC800
+ Say Y here if you want to connect this type of still camera to
+ your computer's USB port. This driver can be used with gphoto 0.4.3
+ and higher (look at <http://www.gphoto.org/>).
+ To use it create a device node with "mknod /dev/mustek c 180 32" and
+ configure it in your software.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called mdc800.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB Mass Storage support
+CONFIG_USB_STORAGE
+ Say Y here if you want to connect USB mass storage devices to your
+ computer's USB port.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usb-storage.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+USB Mass Storage verbose debug
+CONFIG_USB_STORAGE_DEBUG
+ Say Y here in order to have the USB Mass Storage code generate
+ verbose debugging messages.
+
+ISD-200 USB/ATA Bridge support
+CONFIG_USB_STORAGE_ISD200
+ Say Y here if you want to use USB Mass Store devices based
+ on the In-Systems Design ISD-200 USB/ATA bridge.
+
+ Some of the products that use this chip are:
+
+ - Archos Jukebox 6000
+ - ISD SmartCable for Storage
+ - Taiwan Skymaster CD530U/DEL-0241 IDE bridge
+ - Sony CRX10U CD-R/RW drive
+ - CyQ've CQ8060A CDRW drive
+ - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U)
+
+USS720 parport driver
+CONFIG_USB_USS720
+ This driver is for USB parallel port adapters that use the Lucent
+ Technologies USS-720 chip. These cables are plugged into your USB
+ port and provide USB compatibility to peripherals designed with
+ parallel port interfaces.
+
+ The chip has two modes: automatic mode and manual mode. In automatic
+ mode, it looks to the computer like a standard USB printer. Only
+ printers may be connected to the USS-720 in this mode. The generic
+ USB printer driver ("USB Printer support", above) may be used in
+ that mode, and you can say N here if you want to use the chip only
+ in this mode.
+
+ Manual mode is not limited to printers, any parallel port
+ device should work. This driver utilizes manual mode.
+ Note however that some operations are three orders of magnitude
+ slower than on a PCI/ISA Parallel Port, so timing critical
+ applications might not work.
+
+ Say Y here if you own an USS-720 USB->Parport cable and intend to
+ connect anything other than a printer to it.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called uss720.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB device file system
+CONFIG_USB_DEVICEFS
+ If you say Y here (and to "/proc file system support" in the "File
+ systems section, above), you will get a file /proc/bus/usb/devices
+ which lists the devices currently connected to your USB bus or
+ busses, a file /proc/bus/usb/drivers which lists the USB kernel
+ client drivers currently loaded, and for every connected device a
+ file named "/proc/bus/usb/xxx/yyy", where xxx is the bus number and
+ yyy the device number; the latter files can be used by user space
+ programs to talk directly to the device. These files are "virtual",
+ meaning they are generated on the fly and not stored on the hard
+ drive.
+
+ You may need to mount the usbdevfs file system to see the files, use
+ mount -t usbdevfs none /proc/bus/usb
+
+ For the format of the various /proc/bus/usb/ files, please read
+ <file:Documentation/usb/proc_usb_info.txt>.
+
+ Please note that this code is completely unrelated to devfs, the
+ "/dev file system support".
+
+ Most users want to say Y here.
+
+Enforce USB bandwidth allocation
+CONFIG_USB_BANDWIDTH
+ If you say Y here, the USB subsystem enforces USB bandwidth
+ allocation and will prevent some device opens from succeeding
+ if they would cause USB bandwidth usage to go above 90% of
+ the bus bandwidth.
+
+ If you say N here, these conditions will cause warning messages
+ about USB bandwidth usage to be logged and some devices or
+ drivers may not work correctly.
+
+DABUSB driver
+CONFIG_USB_DABUSB
+ A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+ brought to you by the DAB-Team (<http://dab.in.tum.de/>). This
+ driver can be taken as an example for URB-based bulk, control, and
+ isochronous transactions. URB's are explained in
+ <file:Documentation/usb/URB.txt>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dabusb.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Host-to-Host USB networking
+CONFIG_USB_USBNET
+ This driver supports network links over USB with USB "Network"
+ or "data transfer" cables, often used to network laptops to PCs.
+ Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
+ (GeneLink), NetChip and Prolific. Intelligent USB devices could also
+ use this approach to provide Internet access, using standard USB
+ cabling. You can find these chips also on some motherboards with
+ USB PC2PC support.
+
+ These links will have names like "usb0", "usb1", etc. They act
+ like two-node Ethernets, so you can use 802.1d Ethernet Bridging
+ (CONFIG_BRIDGE) to simplify your network routing.
+
+ This code is also available as a kernel module (code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usbnet.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Freecom USB/ATAPI Bridge support
+CONFIG_USB_STORAGE_FREECOM
+ Support for the Freecom USB to IDE/ATAPI adaptor.
+ Freecom has a web page at <http://www.freecom.de/>.
+
+Microtech CompactFlash/SmartMedia reader
+CONFIG_USB_STORAGE_DPCM
+ Say Y here to support the Microtech ZiO! CompactFlash/SmartMedia
+ reader, details at <http://www.microtechint.com/zio/index.html>.
+ This driver treats the flash card as a removable storage device.
+
+SanDisk SDDR-09 (and other SmartMedia) support
+CONFIG_USB_STORAGE_SDDR09
+ Say Y here to include additional code to support the Sandisk SDDR-09
+ SmartMedia reader in the USB Mass Storage driver.
+
+SanDisk SDDR-55 SmartMedia support
+CONFIG_USB_STORAGE_SDDR55
+ Say Y here to include additional code to support the Sandisk SDDR-55
+ SmartMedia reader in the USB Mass Storage driver.
+
+USB Diamond Rio500 support
+CONFIG_USB_RIO500
+ Say Y here if you want to connect a USB Rio500 mp3 player to your
+ computer's USB port. Please read <file:Documentation/usb/rio.txt>
+ for more information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called rio500.o. If you want to compile it as
+ a module, say M here and read <file:Documenatation/modules.txt>.
+
+USB Auerswald ISDN device support
+CONFIG_USB_AUERSWALD
+ Say Y here if you want to connect an Auerswald USB ISDN Device
+ to your computer's USB port.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called auerswald.o. If you want to compile it as
+ a module, say M here and read <file:Documenatation/modules.txt>
+
+CONFIG_USB_TIGL
+ If you own a Texas Instruments graphing calculator and use a
+ TI-GRAPH LINK USB cable (aka SilverLink), then you might be
+ interested in this driver.
+
+ If you enable this driver, you will be able to communicate with
+ your calculator through a set of device nodes under /dev.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called tiglusb.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt.
+
+ If you don't know what the SilverLink cable is or what a Texas
+ Instruments graphing calculator is, then you probably don't need this
+ driver.
+
+ If unsure, say N.
+
+Tieman Voyager USB Braille display support
+CONFIG_USB_BRLVOYAGER
+ Say Y here if you want to use the Voyager USB Braille display from
+ Tieman. See <file:Documentation/usb/brlvger.txt> for more
+ information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called brlvger.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USBLCD support
+CONFIG_USB_LCD
+ Say Y here if you want to connect an USBLCD to your computer's
+ USB port. The USBLCD is a small USB interface board for
+ alphanumeric LCD modules. See <http://www.usblcd.de> for more
+ information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usblcd.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+D-Link DSB-R100 FM radio support
+CONFIG_USB_DSBR
+ Say Y here if you want to connect this type of radio to your
+ computer's USB port. Note that the audio is not digital, and
+ you must connect the line out connector to a sound card or a
+ set of speakers.
+
+ This driver uses the Video For Linux API. You must enable
+ (Y or M in config) Video For Linux (under Character Devices)
+ to use this driver. Information on this API and pointers to
+ "v4l" programs may be found on the WWW at
+ <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dsbr100.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Always do synchronous disk IO for UBD
+CONFIG_BLK_DEV_UBD_SYNC
+ The User-Mode Linux port includes a driver called UBD which will let
+ you access arbitrary files on the host computer as block devices.
+ Writes to such a block device are not immediately written to the
+ host's disk; this may cause problems if, for example, the User-Mode
+ Linux 'Virtual Machine' uses a journalling file system and the host
+ computer crashes.
+
+ Synchronous operation (i.e. always writing data to the host's disk
+ immediately) is configurable on a per-UBD basis by using a special
+ kernel command line option. Alternatively, you can say Y here to
+ turn on synchronous operation by default for all block.
+
+ If you're running a journalling file system (like reiserfs, for
+ example) in your virtual machine, you will want to say Y here. If
+ you care for the safety of the data in your virtual machine, Y is a
+ wise choice too. In all other cases (for example, if you're just
+ playing around with User-Mode Linux) you can choose N.
+
+Enable ptrace proxy
+CONFIG_PT_PROXY
+ This option enables a debugging interface which allows gdb to debug
+ the kernel without needing to actually attach to kernel threads.
+ If you want to do kernel debugging, say Y here; otherwise say N.
+
+Management console
+CONFIG_MCONSOLE
+ The user mode linux management console is a low-level interface to
+ the kernel, somewhat like the i386 SysRq interface. Since there is
+ a full-blown operating system running under every user mode linux
+ instance, there is much greater flexibility possible than with the
+ SysRq mechanism.
+
+ If you answer 'Y' to this option, to use this feature, you need the
+ mconsole client (called uml_mconsole) which is present in CVS in
+ 2.4.5-9um and later (path /tools/mconsole), and is also in the
+ distribution RPM package in 2.4.6 and later.
+
+ It is safe to say 'Y' here.
+
+Enable kernel debugging symbols
+CONFIG_DEBUGSYM
+ When this is enabled, the User-Mode Linux binary will include
+ debugging symbols. This enlarges the binary by a few megabytes,
+ but aids in tracking down kernel problems in UML. It is required
+ if you intend to do any kernel development.
+
+ If you're truly short on disk space or don't expect to report any
+ bugs back to the UML developers, say N, otherwise say Y.
+
+Enable gcov support
+CONFIG_GCOV
+ This option allows developers to retrieve coverage data from a UML
+ session.
+
+ See <http://user-mode-linux.sourceforge.net/gcov.html> for more
+ details.
+
+ If you're involved in UML kernel development and want to use gcov,
+ say Y. If you're unsure, say N.
+
+Enable gprof support
+CONFIG_GPROF
+ This allows profiling of a User-Mode Linux kernel with the gprof
+ utility.
+
+ See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ details.
+
+ If you're involved in UML kernel development and want to use gprof,
+ say Y. If you're unsure, say N.
+
+Host filesystem
+CONFIG_HOSTFS
+ While the User-Mode Linux port uses its own root file system for
+ booting and normal file access, this module lets the UML user
+ access files stored on the host. It does not require any
+ network connection between the Host and UML. An example use of
+ this might be:
+
+ mount none /tmp/fromhost -t hostfs -o /tmp/umlshare
+
+ where /tmp/fromhost is an empty directory inside UML and
+ /tmp/umlshare is a directory on the host with files the UML user
+ wishes to access.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/hostfs.html>.
+
+ If you'd like to be able to work with files stored on the host,
+ say Y or M here; otherwise say N.
+
+Example IO Memory driver
+CONFIG_MMAPPER
+ The User-Mode Linux port can provide support for IO Memory
+ emulation with this option. This allows a host file to be
+ specified as an I/O region on the kernel command line. That file
+ will be mapped into UML's kernel address space where a driver can
+ locate it and do whatever it wants with the memory, including
+ providing an interface to it for UML processes to use.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/iomem.html>.
+
+ If you'd like to be able to provide a simulated IO port space for
+ User-Mode Linux processes, say Y. If unsure, say N.
+
+Virtual Serial Line
+CONFIG_SSL
+ The User-Mode Linux environment allows you to create virtual serial
+ lines on the UML that are usually made to show up on the host as
+ ttys or ptys.
+
+ See <http://user-mode-linux.sourceforge.net/input.html> for more
+ information and command line examples of how to use this facility.
+
+ Unless you have a specific reason for disabling this, say Y.
+
+Virtual network device
+CONFIG_UML_NET
+ While the User-Mode port cannot directly talk to any physical
+ hardware devices, this choice and the following transport options
+ provide one or more virtual network devices through which the UML
+ kernels can talk to each other, the host, and with the host's help,
+ machines on the outside world.
+
+ For more information, including explanations of the networking and
+ sample configurations, see
+ <http://user-mode-linux.sourceforge.net/networking.html>.
+
+ If you'd like to be able to enable networking in the User-Mode
+ linux environment, say Y; otherwise say N. Note that you must
+ enable at least one of the following transport options to actually
+ make use of UML networking.
+
+Daemon transport
+CONFIG_UML_NET_DAEMON
+ This User-Mode Linux network transport allows one or more running
+ UMLs on a single host to communicate with each other, but not to
+ the host.
+
+ To use this form of networking, you'll need to run the UML
+ networking daemon on the host.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html> That site
+ has examples of the UML command line to use to enable Daemon
+ networking.
+
+ If you'd like to set up a network with other UMLs on a single host,
+ say Y. If you need a network between UMLs on multiple physical
+ hosts, choose the Multicast Transport. To set up a network with
+ the host and/or other IP machines, say Y to the Ethertap or Slip
+ transports. You'll need at least one of them, but may choose
+ more than one without conflict. If you don't need UML networking,
+ say N.
+
+Ethertap transport
+CONFIG_UML_NET_ETHERTAP
+ The Ethertap User-Mode Linux network transport allows a single
+ running UML to exchange packets with its host over one of the
+ host's Ethertap devices, such as /dev/tap0. Additional running
+ UMLs can use additional Ethertap devices, one per running UML.
+ While the UML believes it's on a (multi-device, broadcast) virtual
+ Ethernet network, it's in fact communicating over a point-to-point
+ link with the host.
+
+ To use this, your host kernel must have support for Ethertap
+ devices. Also, if your host kernel is 2.4.x, it must have
+ CONFIG_NETLINK_DEV configured as Y or M.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html> That site
+ has examples of the UML command line to use to enable Ethertap
+ networking.
+
+ If you'd like to set up an IP network with the host and/or the
+ outside world, say Y to this, the Daemon Transport and/or the
+ Slip Transport. You'll need at least one of them, but may choose
+ more than one without conflict. If you don't need UML networking,
+ say N.
+
+TUN/TAP transport
+CONFIG_UML_NET_TUNTAP
+ The UML TUN/TAP network transport allows a UML instance to exchange
+ packets with the host over a TUN/TAP device. This option will only
+ work with a 2.4 host, unless you've applied the TUN/TAP patch to
+ your 2.2 host kernel.
+
+ To use this transport, your host kernel must have support for TUN/TAP
+ devices, either built-in or as a module.
+
+Multicast transport
+CONFIG_UML_NET_MCAST
+ This Multicast User-Mode Linux network transport allows multiple
+ UMLs (even ones running on different host machines!) to talk to
+ each other over a virtual ethernet network. However, it requires
+ at least one UML with one of the other transports to act as a
+ bridge if any of them need to be able to talk to their hosts or any
+ other IP machines.
+
+ To use this, your host kernel(s) must support IP Multicasting.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html> That site
+ has examples of the UML command line to use to enable Multicast
+ networking, and notes about the security of this approach.
+
+ If you need UMLs on multiple physical hosts to communicate as if
+ they shared an Ethernet network, say Y. If you need to communicate
+ with other IP machines, make sure you select one of the other
+ transports (possibly in addition to Multicast; they're not
+ exclusive). If you don't need to network UMLs say N to each of
+ the transports.
+
+SLIP transport
+CONFIG_UML_NET_SLIP
+ The Slip User-Mode Linux network transport allows a running UML to
+ network with its host over a point-to-point link. Unlike Ethertap,
+ which can carry any Ethernet frame (and hence even non-IP packets),
+ the Slip transport can only carry IP packets.
+
+ To use this, your host must support Slip devices.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html>. That site
+ has examples of the UML command line to use to enable Slip
+ networking, and details of a few quirks with it.
+
+ The Ethertap Transport is preferred over Slip because of its
+ limitation. If you prefer Slip, however, say Y here. Otherwise
+ choose the Multicast transport (to network multiple UMLs on
+ multiple hosts), Ethertap (to network with the host and the
+ outside world), and/or the Daemon transport (to network multiple
+ UMLs on a single host). You may choose more than one without
+ conflict. If you don't need UML networking, say N.
+
+Microtek USB scanner support
+CONFIG_USB_MICROTEK
+ Say Y here if you want support for the Microtek X6USB and
+ possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
+ Support for anything but the X6 is experimental.
+ Please report failures and successes.
+ The scanner will appear as a scsi generic device to the rest
+ of the system. Scsi support is required for this driver to compile
+ and work. SANE 1.0.4 or newer is needed to make use of your scanner.
+ This driver can be compiled as a module.
+
+HP53xx and Minolta Dual Scanner support
+CONFIG_USB_HPUSBSCSI
+ Say Y here if you want support for the HP 53xx series of scanners
+ and the Minolta Scan Dual. This driver is experimental.
+ The scanner will be accessible as a SCSI device.
+
+USB Bluetooth support
+CONFIG_USB_BLUETOOTH
+ Say Y here if you want to connect a USB Bluetooth device to your
+ computer's USB port. You will need the Bluetooth stack (available
+ at <http://developer.axis.com/software/index.shtml>) to fully use
+ the device.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called bluetooth.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+USB MIDI support
+CONFIG_USB_MIDI
+ Say Y here if you want to connect a USB MIDI device to your
+ computer's USB port. This driver is for devices that comply with
+ 'Universal Serial Bus Device Class Definition for MIDI Device'.
+
+ The following devices are known to work:
+ * Steinberg USB2MIDI
+ * Roland MPU64
+ * Roland PC-300
+ * Roland SC8850
+ * Roland UM-1
+ * Roland UM-2
+ * Roland UA-100
+ * Yamaha MU1000
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usb-midi.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Minix fs support
+CONFIG_MINIX_FS
+ Minix is a simple operating system used in many classes about OS's.
+ The minix file system (method to organize files on a hard disk
+ partition or a floppy disk) was the original file system for Linux,
+ but has been superseded by the second extended file system ext2fs.
+ You don't want to use the minix file system on your hard disk
+ because of certain built-in restrictions, but it is sometimes found
+ on older Linux floppy disks. This option will enlarge your kernel
+ by about 28 KB. If unsure, say N.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called minix.o. Note that the file system of your root
+ partition (the one containing the directory /) cannot be compiled as
+ a module.
+
+Reiserfs support
+CONFIG_REISERFS_FS
+ Stores not just filenames but the files themselves in a balanced
+ tree. Uses journalling.
+
+ Balanced trees are more efficient than traditional file system
+ architectural foundations.
+
+ In general, ReiserFS is as fast as ext2, but is very efficient with
+ large directories and small files. Additional patches are needed
+ for NFS and quotas, please see <http://www.reiserfs.org/> for links.
+
+ It is more easily extended to have features currently found in
+ database and keyword search systems than block allocation based file
+ systems are. The next version will be so extended, and will support
+ plugins consistent with our motto ``It takes more than a license to
+ make source code open.''
+
+ Read <http://www.reiserfs.org/> to learn more about reiserfs.
+
+ Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
+
+ If you like it, you can pay us to add new features to it that you
+ need, buy a support contract, or pay us to port it to another OS.
+
+Enable extra Reiserfs consistency checks
+CONFIG_REISERFS_CHECK
+ If you set this to Y, then ReiserFS will perform every check it can
+ possibly imagine of its internal consistency throughout its
+ operation. It will also go substantially slower. More than once we
+ have forgotten that this was on, and then gone despondent over the
+ latest benchmarks.:-) Use of this option allows our team to go all
+ out in checking for consistency when debugging without fear of its
+ effect on end users. If you are on the verge of sending in a bug
+ report, say Y and you might get a useful error message. Almost
+ everyone should say N.
+
+Publish some reiserfs-specific info under /proc/fs/reiserfs
+CONFIG_REISERFS_PROC_INFO
+ Create under /proc/fs/reiserfs a hierarchy of files, displaying
+ various ReiserFS statistics and internal data at the expense of making
+ your kernel or module slightly larger (+8 KB). This also increases the
+ amount of kernel memory required for each mount by 440 bytes.
+ It isn't useful to average persons, and you probably can't measure the
+ performance cost of it. If you are fine-tuning reiserfs, say Y,
+ otherwise say N.
+
+Second extended fs support
+CONFIG_EXT2_FS
+ This is the de facto standard Linux file system (method to organize
+ files on a storage device) for hard disks.
+
+ You want to say Y here, unless you intend to use Linux exclusively
+ from inside a DOS partition using the UMSDOS file system. The
+ advantage of the latter is that you can get away without
+ repartitioning your hard drive (which often implies backing
+ everything up and restoring afterwards); the disadvantage is that
+ Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat
+ slower than ext2fs. Even if you want to run Linux in this fashion,
+ it might be a good idea to have ext2fs around: it enables you to
+ read more floppy disks and facilitates the transition to a *real*
+ Linux partition later. Another (rare) case which doesn't require
+ ext2fs is a diskless Linux box which mounts all files over the
+ network using NFS (in this case it's sufficient to say Y to "NFS
+ file system support" below). Saying Y here will enlarge your kernel
+ by about 44 KB.
+
+ The Ext2fs-Undeletion mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, gives information about
+ how to retrieve deleted files on ext2fs file systems.
+
+ To change the behaviour of ext2 file systems, you can use the tune2fs
+ utility ("man tune2fs"). To modify attributes of files and
+ directories on ext2 file systems, use chattr ("man chattr").
+
+ Ext2fs partitions can be read from within DOS using the ext2tool
+ command line tool package (available from
+ <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from
+ within Windows NT using the ext2nt command line tool package from
+ <ftp://ibiblio.org/pub/Linux/utils/dos/>. Explore2fs is a
+ graphical explorer for ext2fs partitions which runs on Windows 95
+ and Windows NT and includes experimental write support; it is
+ available from
+ <http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm>.
+
+ If you want to compile this file system as a module ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called ext2.o. Be aware however that the file system
+ of your root partition (the one containing the directory /) cannot
+ be compiled as a module, and so this could be dangerous. Most
+ everyone wants to say Y here.
+
+Ext3 journalling file system support (EXPERIMENTAL)
+CONFIG_EXT3_FS
+ This is the journalling version of the Second extended file system
+ (often called ext3), the de facto standard Linux file system
+ (method to organize files on a storage device) for hard disks.
+
+ The journalling code included in this driver means you do not have
+ to run e2fsck (file system checker) on your file systems after a
+ crash. The journal keeps track of any changes that were being made
+ at the time the system crashed, and can ensure that your file system
+ is consistent without the need for a lengthy check.
+
+ Other than adding the journal to the file system, the on-disk format
+ of ext3 is identical to ext2. It is possible to freely switch
+ between using the ext3 driver and the ext2 driver, as long as the
+ file system has been cleanly unmounted, or e2fsck is run on the file
+ system.
+
+ To add a journal on an existing ext2 file system or change the
+ behaviour of ext3 file systems, you can use the tune2fs utility ("man
+ tune2fs"). To modify attributes of files and directories on ext3
+ file systems, use chattr ("man chattr"). You need to be using
+ e2fsprogs version 1.20 or later in order to create ext3 journals
+ (available at <http://sourceforge.net/projects/e2fsprogs/>).
+
+ If you want to compile this file system as a module ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called ext3.o. Be aware however that the file system
+ of your root partition (the one containing the directory /) cannot
+ be compiled as a module, and so this may be dangerous.
+
+Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
+CONFIG_JBD
+ This is a generic journalling layer for block devices. It is
+ currently used by the ext3 file system, but it could also be used to
+ add journal support to other file systems or block devices such as
+ RAID or LVM.
+
+ If you are using the ext3 file system, you need to say Y here. If
+ you are not using ext3 then you will probably want to say N.
+
+ If you want to compile this device as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called jbd.o. If you are compiling ext3 into the kernel,
+ you cannot compile this code as a module.
+
+JBD (ext3) debugging support
+CONFIG_JBD_DEBUG
+ If you are using the ext3 journalling file system (or potentially any
+ other file system/device using JBD), this option allows you to
+ enable debugging output while the system is running, in order to
+ help track down any problems you are having. By default the
+ debugging output will be turned off.
+
+ If you select Y here, then you will be able to turn on debugging
+ with "echo N > /proc/sys/fs/jbd-debug", where N is a number between
+ 1 and 5, the higher the number, the more debugging output is
+ generated. To turn debugging off again, do
+ "echo 0 > /proc/sys/fs/jbd-debug".
+
+Buffer Head tracing (DEBUG)
+CONFIG_BUFFER_DEBUG
+ If you are a kernel developer working with file systems or in the
+ block device layer, this buffer head tracing may help you to track
+ down bugs in your code. This enables some debugging macros
+ (BUFFER_TRACE, etc.) which allow you to track the state of a buffer
+ through various layers of code. The debugging code is used
+ primarily by ext3 and JBD code.
+
+ Because this option adds considerably to the size of each buffer,
+ most people will want to say N here.
+
+BeOS filesystem support (BeFS) (read only)
+CONFIG_BEFS_FS
+ The BeOS File System (BeFS) is the native file system of Be, Inc's
+ BeOS. Notable features include support for arbitrary attributes
+ on files and directories, and database-like indices on selected
+ attributes. (Also note that this driver doesn't make those features
+ available at this time). It is a 64 bit filesystem, so it supports
+ extremely large volumes and files.
+
+ If you use this filesystem, you should also say Y to at least one
+ of the NLS (native language support) options below.
+
+ If you don't know what this is about, say N.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read Documentation/modules.txt. The module will be
+ called befs.o.
+
+Debug BeFS
+CONFIG_BEFS_DEBUG
+ If you say Y here, you can use the 'debug' mount option to enable
+ debugging output from the driver. This is unlike previous versions
+ of the driver, where enabling this option would turn on debugging
+ output automatically.
+
+ Example:
+ mount -t befs /dev/hda2 /mnt -o debug
+
+BFS file system support
+CONFIG_BFS_FS
+ Boot File System (BFS) is a file system used under SCO UnixWare to
+ allow the bootloader access to the kernel image and other important
+ files during the boot process. It is usually mounted under /stand
+ and corresponds to the slice marked as "STAND" in the UnixWare
+ partition. You should say Y if you want to read or write the files
+ on your /stand slice from within Linux. You then also need to say Y
+ to "UnixWare slices support", below. More information about the BFS
+ file system is contained in the file
+ <file:Documentation/filesystems/bfs.txt>.
+
+ If you don't know what this is about, say N.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called bfs.o. Note that the file system of your root
+ partition (the one containing the directory /) cannot be compiled as
+ a module.
+
+Compressed ROM file system support
+CONFIG_CRAMFS
+ Saying Y here includes support for CramFs (Compressed ROM File
+ System). CramFs is designed to be a simple, small, and compressed
+ file system for ROM based embedded systems. CramFs is read-only,
+ limited to 256MB file systems (with 16MB files), and doesn't support
+ 16/32 bits uid/gid, hard links and timestamps.
+
+ See <file:Documentation/filesystems/cramfs.txt> and
+ <file:fs/cramfs/README> for further information.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called cramfs.o. Note that the root file system (the one
+ containing the directory /) cannot be compiled as a module.
+
+ If unsure, say N.
+
+CMS file system support
+CONFIG_CMS_FS
+ Read only support for CMS minidisk file systems found on IBM
+ mainframe systems. Only the basic format is supported so far. If
+ you don't know what CMS is you probably don't want to know any more.
+
+# When the 2.5 version of configure.help goes away, the part of this that
+# duplicates Documentation/filesystems/tmpfs.txt can drop out.
+Virtual memory file system support
+CONFIG_TMPFS
+ Tmpfs is a file system which keeps all files in virtual memory.
+ Everything in tmpfs is temporary in the sense that no files will be
+ created on your hard drive. If you reboot, everything in tmpfs will
+ be lost.
+
+ In contrast to RAM disks, which get allocated a fixed amount of
+ physical RAM, tmpfs grows and shrinks to accommodate the files it
+ contains and is able to swap unneeded pages out to swap space.
+
+ Everything is "virtual" in the sense that no files will be created
+ on your hard drive; if you reboot, everything in tmpfs will be
+ lost.
+
+ You should mount the file system somewhere to be able to use
+ POSIX shared memory. Adding the following line to /etc/fstab should
+ take care of things:
+
+ tmpfs /dev/shm tmpfs defaults 0 0
+
+ Remember to create the directory that you intend to mount tmpfs on
+ if necessary (/dev/shm is automagically created if you use devfs).
+
+ You can set limits for the number of blocks and inodes used by the
+ file system with the mount options "size", "nr_blocks" and
+ "nr_inodes". These parameters accept a suffix k, m or g for kilo,
+ mega and giga and can be changed on remount.
+
+ The initial permissions of the root directory can be set with the
+ mount option "mode".
+
+ See <file:Documentation/filesystems/tmpfs.txt> for details.
+
+Simple RAM-based file system support
+CONFIG_RAMFS
+ Ramfs is a file system which keeps all files in RAM. It allows
+ read and write access.
+
+ It is more of an programming example than a usable file system. If
+ you need a file system which lives in RAM with limit checking use
+ tmpfs.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ramfs.o.
+
+ISO 9660 CD-ROM file system support
+CONFIG_ISO9660_FS
+ This is the standard file system used on CD-ROMs. It was previously
+ known as "High Sierra File System" and is called "hsfs" on other
+ Unix systems. The so-called Rock-Ridge extensions which allow for
+ long Unix filenames and symbolic links are also supported by this
+ driver. If you have a CD-ROM drive and want to do more with it than
+ just listen to audio CDs and watch its LEDs, say Y (and read
+ <file:Documentation/filesystems/isofs.txt> and the CD-ROM-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>), thereby
+ enlarging your kernel by about 27 KB; otherwise say N.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called isofs.o.
+
+Microsoft Joliet CD-ROM extensions
+CONFIG_JOLIET
+ Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system
+ which allows for long filenames in unicode format (unicode is the
+ new 16 bit character code, successor to ASCII, which encodes the
+ characters of almost all languages of the world; see
+ <http://www.unicode.org/> for more information). Say Y here if you
+ want to be able to read Joliet CD-ROMs under Linux.
+
+Transparent decompression extension
+CONFIG_ZISOFS
+ This is a Linux-specific extension to RockRidge which lets you store
+ data in compressed form on a CD-ROM and have it transparently
+ decompressed when the CD-ROM is accessed. See
+ <http://www.kernel.org/pub/linux/utils/fs/zisofs/> for the tools
+ necessary to create such a filesystem. Say Y here if you want to be
+ able to read such compressed CD-ROMs.
+
+UDF file system support (read-only)
+CONFIG_UDF_FS
+ This is the new file system used on some CD-ROMs and DVDs. Say Y if
+ you intend to mount DVD discs or CDRW's written in packet mode, or
+ if written to by other UDF utilities, such as DirectCD. This UDF
+ file system support is read-only. If you want to write to UDF
+ file systems on some media, you need to say Y to "UDF read-write
+ support" below in addition. Please read
+ <file:Documentation/filesystems/udf.txt>.
+
+ This file system support is also available as a module ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). The module is called udf.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+
+UDF write support (DANGEROUS)
+CONFIG_UDF_RW
+ Say Y if you want to test write support for UDF file systems.
+ Due to lack of support for writing to CDR/CDRW's, this option
+ is only supported for hard discs, DVD-RAM, and loopback files.
+
+DOS FAT fs support
+CONFIG_FAT_FS
+ If you want to use one of the FAT-based file systems (the MS-DOS,
+ VFAT (Windows 95) and UMSDOS (used to run Linux on top of an
+ ordinary DOS partition) file systems), then you must say Y or M here
+ to include FAT support. You will then be able to mount partitions or
+ diskettes with FAT-based file systems and transparently access the
+ files on them, i.e. MSDOS files will look and behave just like all
+ other Unix files.
+
+ This FAT support is not a file system in itself, it only provides
+ the foundation for the other file systems. You will have to say Y or
+ M to at least one of "MSDOS fs support" or "VFAT fs support" in
+ order to make use of it.
+
+ Another way to read and write MSDOS floppies and hard drive
+ partitions from within Linux (but not transparently) is with the
+ mtools ("man mtools") program suite. You don't need to say Y here in
+ order to do that.
+
+ If you need to move large files on floppies between a DOS and a
+ Linux box, say Y here, mount the floppy under Linux with an MSDOS
+ file system and use GNU tar's M option. GNU tar is a program
+ available for Unix and DOS ("man tar" or "info tar").
+
+ It is now also becoming possible to read and write compressed FAT
+ file systems; read <file:Documentation/filesystems/fat_cvf.txt> for
+ details.
+
+ The FAT support will enlarge your kernel by about 37 KB. If unsure,
+ say Y.
+
+ If you want to compile this as a module however ( = code which can
+ be inserted in and removed from the running kernel whenever you
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called fat.o. Note that if you compile the FAT
+ support as a module, you cannot compile any of the FAT-based file
+ systems into the kernel -- they will have to be modules as well.
+ The file system of your root partition (the one containing the
+ directory /) cannot be a module, so don't say M here if you intend
+ to use UMSDOS as your root file system.
+
+MSDOS fs support
+CONFIG_MSDOS_FS
+ This allows you to mount MSDOS partitions of your hard drive (unless
+ they are compressed; to access compressed MSDOS partitions under
+ Linux, you can either use the DOS emulator DOSEMU, described in the
+ DOSEMU-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, or try dmsdosfs in
+ <ftp://ibiblio.org/pub/Linux/system/filesystems/dosfs/>. If you
+ intend to use dosemu with a non-compressed MSDOS partition, say Y
+ here) and MSDOS floppies. This means that file access becomes
+ transparent, i.e. the MSDOS files look and behave just like all
+ other Unix files.
+
+ If you want to use UMSDOS, the Unix-like file system on top of a
+ DOS file system, which allows you to run Linux from within a DOS
+ partition without repartitioning, you'll have to say Y or M here.
+
+ If you have Windows 95 or Windows NT installed on your MSDOS
+ partitions, you should use the VFAT file system (say Y to "VFAT fs
+ support" below), or you will not be able to see the long filenames
+ generated by Windows 95 / Windows NT.
+
+ This option will enlarge your kernel by about 7 KB. If unsure,
+ answer Y. This will only work if you said Y to "DOS FAT fs support"
+ as well. If you want to compile this as a module however ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called msdos.o.
+
+VFAT (Windows-95) fs support
+CONFIG_VFAT_FS
+ This option provides support for normal Windows file systems with
+ long filenames. That includes non-compressed FAT-based file systems
+ used by Windows 95, Windows 98, Windows NT 4.0, and the Unix
+ programs from the mtools package.
+
+ You cannot use the VFAT file system for your Linux root partition
+ (the one containing the directory /); use UMSDOS instead if you
+ want to run Linux from within a DOS partition (i.e. say Y to
+ "Unix like fs on top of std MSDOS fs", below).
+
+ The VFAT support enlarges your kernel by about 10 KB and it only
+ works if you said Y to the "DOS FAT fs support" above. Please read
+ the file <file:Documentation/filesystems/vfat.txt> for details. If
+ unsure, say Y.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called vfat.o.
+
+Unix-like file system on top of standard MSDOS fs
+CONFIG_UMSDOS_FS
+ Say Y here if you want to run Linux from within an existing DOS
+ partition of your hard drive. The advantage of this is that you can
+ get away without repartitioning your hard drive (which often implies
+ backing everything up and restoring afterwards) and hence you're
+ able to quickly try out Linux or show it to your friends; the
+ disadvantage is that Linux becomes susceptible to DOS viruses and
+ that UMSDOS is somewhat slower than ext2fs. Another use of UMSDOS
+ is to write files with long unix filenames to MSDOS floppies; it
+ also allows Unix-style soft-links and owner/permissions of files on
+ MSDOS floppies. You will need a program called umssync in order to
+ make use of UMSDOS; read
+ <file:Documentation/filesystems/umsdos.txt>.
+
+ To get utilities for initializing/checking UMSDOS file system, or
+ latest patches and/or information, visit the UMSDOS home page at
+ <http://www.voyager.hr/~mnalis/umsdos/>.
+
+ This option enlarges your kernel by about 28 KB and it only works if
+ you said Y to both "DOS FAT fs support" and "MSDOS fs support"
+ above. If you want to compile this as a module ( = code which can
+ be inserted in and removed from the running kernel whenever you
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called umsdos.o. Note that the file system of your
+ root partition (the one containing the directory /) cannot be a
+ module, so saying M could be dangerous. If unsure, say N.
+
+/proc file system support
+CONFIG_PROC_FS
+ This is a virtual file system providing information about the status
+ of the system. "Virtual" means that it doesn't take up any space on
+ your hard disk: the files are created on the fly by the kernel when
+ you try to access them. Also, you cannot read the files with older
+ version of the program less: you need to use more or cat.
+
+ It's totally cool; for example, "cat /proc/interrupts" gives
+ information about what the different IRQs are used for at the moment
+ (there is a small number of Interrupt ReQuest lines in your computer
+ that are used by the attached devices to gain the CPU's attention --
+ often a source of trouble if two devices are mistakenly configured
+ to use the same IRQ). The program procinfo to display some
+ information about your system gathered from the /proc file system.
+
+ Before you can use the /proc file system, it has to be mounted,
+ meaning it has to be given a location in the directory hierarchy.
+ That location should be /proc. A command such as "mount -t proc proc
+ /proc" or the equivalent line in /etc/fstab does the job.
+
+ The /proc file system is explained in the file
+ <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage
+ ("man 5 proc").
+
+ This option will enlarge your kernel by about 67 KB. Several
+ programs depend on this, so everyone should say Y here.
+
+Support for PReP Residual Data
+CONFIG_PREP_RESIDUAL
+ Some PReP systems have residual data passed to the kernel by the
+ firmware. This allows detection of memory size, devices present and
+ other useful pieces of information. Sometimes this information is
+ not present or incorrect.
+
+ Unless you expect to boot on a PReP system, there is no need to
+ select Y.
+
+PReP residual data available in /proc/residual
+CONFIG_PROC_PREPRESIDUAL
+ Enabling this option will create a /proc/residual file which allows
+ you to get at the residual data on PReP systems. You will need a tool
+ (lsresidual) to parse it. If you aren't on a PReP system, you don't
+ want this.
+
+/dev file system support
+CONFIG_DEVFS_FS
+ This is support for devfs, a virtual file system (like /proc) which
+ provides the file system interface to device drivers, normally found
+ in /dev. Devfs does not depend on major and minor number
+ allocations. Device drivers register entries in /dev which then
+ appear automatically, which means that the system administrator does
+ not have to create character and block special device files in the
+ /dev directory using the mknod command (or MAKEDEV script) anymore.
+
+ This is work in progress. If you want to use this, you *must* read
+ the material in <file:Documentation/filesystems/devfs/>, especially
+ the file README there.
+
+ If unsure, say N.
+
+Automatically mount devfs at boot time
+CONFIG_DEVFS_MOUNT
+ This option appears if you have CONFIG_DEVFS_FS enabled. Setting
+ this to 'Y' will make the kernel automatically mount devfs onto /dev
+ when the system is booted, before the init thread is started.
+ You can override this with the "devfs=nomount" boot option.
+
+ If unsure, say N.
+
+Debug devfs
+CONFIG_DEVFS_DEBUG
+ If you say Y here, then the /dev file system code will generate
+ debugging messages. See the file
+ <file:Documentation/filesystems/devfs/boot-options> for more
+ details.
+
+ If unsure, say N.
+
+NFS file system support
+CONFIG_NFS_FS
+ If you are connected to some other (usually local) Unix computer
+ (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
+ on that computer (the NFS server) using the Network File Sharing
+ protocol, say Y. "Mounting files" means that the client can access
+ the files with usual UNIX commands as if they were sitting on the
+ client's hard disk. For this to work, the server must run the
+ programs nfsd and mountd (but does not need to have NFS file system
+ support enabled in its kernel). NFS is explained in the Network
+ Administrator's Guide, available from
+ <http://www.tldp.org/docs.html#guide>, on its man page: "man
+ nfs", and in the NFS-HOWTO.
+
+ A superior but less widely used alternative to NFS is provided by
+ the Coda file system; see "Coda file system support" below.
+
+ If you say Y here, you should have said Y to TCP/IP networking also.
+ This option would enlarge your kernel by about 27 KB.
+
+ This file system is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called nfs.o. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ If you are configuring a diskless machine which will mount its root
+ file system over NFS at boot time, say Y here and to "Kernel
+ level IP autoconfiguration" above and to "Root file system on NFS"
+ below. You cannot compile this driver as a module in this case.
+ There are two packages designed for booting diskless machines over
+ the net: netboot, available from
+ <http://ftp1.sourceforge.net/netboot/>, and Etherboot,
+ available from <http://ftp1.sourceforge.net/etherboot/>.
+
+ If you don't know what all this is about, say N.
+
+Provide NFSv3 client support
+CONFIG_NFS_V3
+ Say Y here if you want your NFS client to be able to speak the newer
+ version 3 of the NFS protocol.
+
+ If unsure, say N.
+
+Root file system on NFS
+CONFIG_ROOT_NFS
+ If you want your Linux box to mount its whole root file system (the
+ one containing the directory /) from some other computer over the
+ net via NFS (presumably because your box doesn't have a hard disk),
+ say Y. Read <file:Documentation/nfsroot.txt> for details. It is
+ likely that in this case, you also want to say Y to "Kernel level IP
+ autoconfiguration" so that your box can discover its network address
+ at boot time.
+
+ Most people say N here.
+
+NFS server support
+CONFIG_NFSD
+ If you want your Linux box to act as an NFS *server*, so that other
+ computers on your local network which support NFS can access certain
+ directories on your box transparently, you have two options: you can
+ use the self-contained user space program nfsd, in which case you
+ should say N here, or you can say Y and use the kernel based NFS
+ server. The advantage of the kernel based solution is that it is
+ faster.
+
+ In either case, you will need support software; the respective
+ locations are given in the file <file:Documentation/Changes> in the
+ NFS section.
+
+ If you say Y here, you will get support for version 2 of the NFS
+ protocol (NFSv2). If you also want NFSv3, say Y to the next question
+ as well.
+
+ Please read the NFS-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ The NFS server is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called nfsd.o. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>. If unsure,
+ say N.
+
+Provide NFSv3 server support
+CONFIG_NFSD_V3
+ If you would like to include the NFSv3 server as well as the NFSv2
+ server, say Y here. If unsure, say Y.
+
+Provide NFS over TCP server support EXPERIMENTAL
+CONFIG_NFSD_TCP
+ Enable NFS service over TCP connections. This the officially
+ still experimental, but seems to work well.
+
+OS/2 HPFS file system support
+CONFIG_HPFS_FS
+ OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
+ is the file system used for organizing files on OS/2 hard disk
+ partitions. Say Y if you want to be able to read files from and
+ write files to an OS/2 HPFS partition on your hard drive. OS/2
+ floppies however are in regular MSDOS format, so you don't need this
+ option in order to be able to read them. Read
+ <file:Documentation/filesystems/hpfs.txt>.
+
+ This file system is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called hpfs.o. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>. If unsure,
+ say N.
+
+NTFS file system support (read-only)
+CONFIG_NTFS_FS
+ NTFS is the file system of Microsoft Windows NT. Say Y if you want
+ to get read access to files on NTFS partitions of your hard drive.
+ The Linux NTFS driver supports most of the mount options of the VFAT
+ driver, see <file:Documentation/filesystems/ntfs.txt>. Saying Y here
+ will give you read-only access to NTFS partitions.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ntfs.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+NTFS write support (DANGEROUS)
+CONFIG_NTFS_RW
+ If you say Y here, you will (maybe) be able to write to NTFS file
+ systems as well as read from them. The read-write support in NTFS
+ is far from being complete and is not well tested. If you say Y
+ here, back up your NTFS volume first, since it will probably get
+ damaged. Also, download the Linux-NTFS project distribution from
+ Sourceforge at <http://linux-ntfs.sf.net/> and always run the
+ included ntfsfix utility after writing to an NTFS partition from
+ Linux to fix some of the damage done by the driver. You should run
+ ntfsfix _after_ unmounting the partition in Linux but _before_
+ rebooting into Windows. When Windows next boots, chkdsk will be
+ run automatically to fix the remaining damage.
+ Please note that write support is limited to Windows NT4 and
+ earlier versions.
+
+ If unsure, say N.
+
+System V/Xenix/V7/Coherent file system support
+CONFIG_SYSV_FS
+ SCO, Xenix and Coherent are commercial Unix systems for Intel
+ machines, and Version 7 was used on the DEC PDP-11. Saying Y
+ here would allow you to read from their floppies and hard disk
+ partitions.
+
+ If you have floppies or hard disk partitions like that, it is likely
+ that they contain binaries from those other Unix systems; in order
+ to run these binaries, you will want to install linux-abi which is a
+ a set of kernel modules that lets you run SCO, Xenix, Wyse,
+ UnixWare, Dell Unix and System V programs under Linux. It is
+ available via FTP (user: ftp) from
+ <ftp://ftp.openlinux.org/pub/people/hch/linux-abi/>).
+ NOTE: that will work only for binaries from Intel-based systems;
+ PDP ones will have to wait until somebody ports Linux to -11 ;-)
+
+ If you only intend to mount files from some other Unix over the
+ network using NFS, you don't need the System V file system support
+ (but you need NFS file system support obviously).
+
+ Note that this option is generally not needed for floppies, since a
+ good portable way to transport files and directories between unixes
+ (and even other operating systems) is given by the tar program ("man
+ tar" or preferably "info tar"). Note also that this option has
+ nothing whatsoever to do with the option "System V IPC". Read about
+ the System V file system in
+ <file:Documentation/filesystems/sysv-fs.txt>.
+ Saying Y here will enlarge your kernel by about 27 KB.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called sysv.o.
+
+ If you haven't heard about all of this before, it's safe to say N.
+
+Amiga FFS file system support
+CONFIG_AFFS_FS
+ The Fast File System (FFS) is the common file system used on hard
+ disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y
+ if you want to be able to read and write files from and to an Amiga
+ FFS partition on your hard drive. Amiga floppies however cannot be
+ read with this driver due to an incompatibility of the floppy
+ controller used in an Amiga and the standard floppy controller in
+ PCs and workstations. Read <file:Documentation/filesystems/affs.txt>
+ and <file:fs/affs/Changes>.
+
+ With this driver you can also mount disk files used by Bernd
+ Schmidt's Un*X Amiga Emulator
+ (<http://www.freiburg.linux.de/~uae/>).
+ If you want to do this, you will also need to say Y or M to "Loop
+ device support", above.
+
+ This file system is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called affs.o. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>. If unsure,
+ say N.
+
+Apple Macintosh file system support
+CONFIG_HFS_FS
+ If you say Y here, you will be able to mount Macintosh-formatted
+ floppy disks and hard drive partitions with full read-write access.
+ Please read <file:fs/hfs/HFS.txt> to learn about the available mount
+ options.
+
+ This file system support is also available as a module ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). The module is called hfs.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+ROM file system support
+CONFIG_ROMFS_FS
+ This is a very small read-only file system mainly intended for
+ initial ram disks of installation disks, but it could be used for
+ other read-only media as well. Read
+ <file:Documentation/filesystems/romfs.txt> for details.
+
+ This file system support is also available as a module ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). The module is called romfs.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. Note that the file system of your
+ root partition (the one containing the directory /) cannot be a
+ module.
+
+ If you don't know whether you need it, then you don't need it:
+ answer N.
+
+QNX4 file system support (read only)
+CONFIG_QNX4FS_FS
+ This is the file system used by the real-time operating systems
+ QNX 4 and QNX 6 (the latter is also called QNX RTP).
+ Further information is available at <http://www.qnx.com/>.
+ Say Y if you intend to mount QNX hard disks or floppies.
+ Unless you say Y to "QNX4FS read-write support" below, you will
+ only be able to read these file systems.
+
+ This file system support is also available as a module ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). The module is called qnx4.o. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+ If you don't know whether you need it, then you don't need it:
+ answer N.
+
+QNX4FS write support (DANGEROUS)
+CONFIG_QNX4FS_RW
+ Say Y if you want to test write support for QNX4 file systems.
+
+ It's currently broken, so for now:
+ answer N.
+
+Kernel automounter support
+CONFIG_AUTOFS_FS
+ The automounter is a tool to automatically mount remote file systems
+ on demand. This implementation is partially kernel-based to reduce
+ overhead in the already-mounted case; this is unlike the BSD
+ automounter (amd), which is a pure user space daemon.
+
+ To use the automounter you need the user-space tools from the autofs
+ package; you can find the location in <file:Documentation/Changes>.
+ You also want to answer Y to "NFS file system support", below.
+
+ If you want to use the newer version of the automounter with more
+ features, say N here and say Y to "Kernel automounter v4 support",
+ below.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called autofs.o.
+
+ If you are not a part of a fairly large, distributed network, you
+ probably do not need an automounter, and can say N here.
+
+Kernel automounter version 4 support (also supports v3)
+CONFIG_AUTOFS4_FS
+ The automounter is a tool to automatically mount remote file systems
+ on demand. This implementation is partially kernel-based to reduce
+ overhead in the already-mounted case; this is unlike the BSD
+ automounter (amd), which is a pure user space daemon.
+
+ To use the automounter you need the user-space tools from
+ <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also
+ want to answer Y to "NFS file system support", below.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called autofs4.o. You will need to add "alias autofs
+ autofs4" to your modules configuration file.
+
+ If you are not a part of a fairly large, distributed network or
+ don't have a laptop which needs to dynamically reconfigure to the
+ local network, you probably do not need an automounter, and can say
+ N here.
+
+EFS file system support (read-only)
+CONFIG_EFS_FS
+ EFS is an older file system used for non-ISO9660 CD-ROMs and hard
+ disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
+ uses the XFS file system for hard disk partitions however).
+
+ This implementation only offers read-only access. If you don't know
+ what all this is about, it's safe to say N. For more information
+ about EFS see its home page at <http://aeschi.ch.eu.org/efs/>.
+
+ If you want to compile the EFS file system support as a module ( =
+ code which can be inserted in and removed from the running kernel
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>. The module will be called efs.o.
+
+Journalling Flash File System (JFFS) support
+CONFIG_JFFS_FS
+ JFFS is the Journalling Flash File System developed by Axis
+ Communications in Sweden, aimed at providing a crash/powerdown-safe
+ file system for disk-less embedded devices. Further information is
+ available at (<http://developer.axis.com/software/jffs/>).
+
+JFFS debugging verbosity (0 = quiet, 3 = noisy)
+CONFIG_JFFS_FS_VERBOSE
+ Determines the verbosity level of the JFFS debugging messages.
+
+Journalling Flash File System v2 (JFFS2) support
+CONFIG_JFFS2_FS
+ JFFS2 is the second generation of the Journalling Flash File System
+ for use on diskless embedded devices. It provides improved wear
+ levelling, compression and support for hard links. You cannot use
+ this on normal block devices, only on 'MTD' devices.
+
+ Further information should be made available soon at
+ <http://sources.redhat.com/jffs2/>.
+
+JFFS2 debugging verbosity (0 = quiet, 2 = noisy)
+CONFIG_JFFS2_FS_DEBUG
+ This controls the amount of debugging messages produced by the JFFS2
+ code. Set it to zero for use in production systems. For evaluation,
+ testing and debugging, it's advisable to set it to one. This will
+ enable a few assertions and will print debugging messages at the
+ KERN_DEBUG loglevel, where they won't normally be visible. Level 2
+ is unlikely to be useful - it enables extra debugging in certain
+ areas which at one point needed debugging, but when the bugs were
+ located and fixed, the detailed messages were relegated to level 2.
+
+ If reporting bugs, please try to have available a full dump of the
+ messages at debug level 1 while the misbehaviour was occurring.
+
+JFFS stats available in /proc filesystem
+CONFIG_JFFS_PROC_FS
+ Enabling this option will cause statistics from mounted JFFS file systems
+ to be made available to the user in the /proc/fs/jffs/ directory.
+
+UFS file system support (read-only)
+CONFIG_UFS_FS
+ BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
+ OpenBSD and NeXTstep) use a file system called UFS. Some System V
+ Unixes can create and mount hard disk partitions and diskettes using
+ this file system as well. Saying Y here will allow you to read from
+ these partitions; if you also want to write to them, say Y to the
+ experimental "UFS file system write support", below. Please read the
+ file <file:Documentation/filesystems/ufs.txt> for more information.
+
+ If you only intend to mount files from some other Unix over the
+ network using NFS, you don't need the UFS file system support (but
+ you need NFS file system support obviously).
+
+ Note that this option is generally not needed for floppies, since a
+ good portable way to transport files and directories between unixes
+ (and even other operating systems) is given by the tar program ("man
+ tar" or preferably "info tar").
+
+ When accessing NeXTstep files, you may need to convert them from the
+ NeXT character set to the Latin1 character set; use the program
+ recode ("info recode") for this purpose.
+
+ If you want to compile the UFS file system support as a module ( =
+ code which can be inserted in and removed from the running kernel
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>. The module will be called ufs.o.
+
+ If you haven't heard about all of this before, it's safe to say N.
+
+UFS file system write support (DANGEROUS)
+CONFIG_UFS_FS_WRITE
+ Say Y here if you want to try writing to UFS partitions. This is
+ experimental, so you should back up your UFS partitions beforehand.
+
+Advanced partition selection
+CONFIG_PARTITION_ADVANCED
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned under an operating system running on a different
+ architecture than your Linux system.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about foreign partitioning schemes.
+
+ If unsure, say N.
+
+Acorn partition support
+CONFIG_ACORN_PARTITION
+ Support hard disks partitioned under Acorn operating systems.
+
+Native filecore partition support
+CONFIG_ACORN_PARTITION_ADFS
+ The Acorn Disc Filing System is the standard file system of the
+ RiscOS operating system which runs on Acorn's ARM-based Risc PC
+ systems and the Acorn Archimedes range of machines. If you say
+ `Y' here, Linux will support disk partitions created under ADFS.
+
+PowerTec partition support
+CONFIG_ACORN_PARTITION_POWERTEC
+ Support reading partition tables created on Acorn machines using
+ the PowerTec SCSI drive.
+
+RISCiX partition support
+CONFIG_ACORN_PARTITION_RISCIX
+ Once upon a time, there was a native Unix port for the Acorn series
+ of machines called RISCiX. If you say 'Y' here, Linux will be able
+ to read disks partitioned under RISCiX.
+
+ICS partition support
+CONFIG_ACORN_PARTITION_ICS
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned using the ICS interface on Acorn machines.
+
+Alpha OSF partition support
+CONFIG_OSF_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned on an Alpha machine.
+
+Macintosh partition map support
+CONFIG_MAC_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned on a Macintosh.
+
+Windows Logical Disk Manager (Dynamic Disk) support (EXPERIMENTAL)
+CONFIG_LDM_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned using Windows 2000's or XP's Logical Disk Manager.
+ They are also known as "Dynamic Disks".
+
+ Windows 2000 introduced the concept of Dynamic Disks to get around
+ the limitations of the PC's partitioning scheme. The Logical Disk
+ Manager allows the user to repartition a disk and create spanned,
+ mirrored, striped or RAID volumes, all without the need for
+ rebooting.
+
+ Normal partitions are now called Basic Disks under Windows 2000 and
+ XP.
+
+ Technical documentation to accompany this driver is available from:
+ <http://linux-ntfs.sf.net/ldm/>.
+
+ If unsure, say N.
+
+Windows LDM extra logging
+CONFIG_LDM_DEBUG
+ Say Y here if you would like LDM to log verbosely. This could be
+ helpful if the driver doesn't work as expected and you'd like to
+ report a bug.
+
+ If unsure, say N.
+
+PC BIOS (MSDOS partition tables) support
+CONFIG_MSDOS_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned on an x86 PC (not necessarily by DOS).
+
+Amiga partition table support
+CONFIG_AMIGA_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned under AmigaOS.
+
+Atari partition table support
+CONFIG_ATARI_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned under the Atari OS.
+
+BSD disklabel (FreeBSD partition tables) support
+CONFIG_BSD_DISKLABEL
+ FreeBSD uses its own hard disk partition scheme on your PC. It
+ requires only one entry in the primary partition table of your disk
+ and manages it similarly to DOS extended partitions, putting in its
+ first sector a new partition table in BSD disklabel format. Saying Y
+ here allows you to read these disklabels and further mount FreeBSD
+ partitions from within Linux if you have also said Y to "UFS
+ file system support", above. If you don't know what all this is
+ about, say N.
+
+Minix subpartition support
+CONFIG_MINIX_SUBPARTITION
+ Minix 2.0.0/2.0.2 subpartition table support for Linux.
+ Say Y here if you want to mount and use Minix 2.0.0/2.0.2
+ subpartitions.
+
+Sun partition table support
+CONFIG_SUN_PARTITION
+ Like most systems, SunOS uses its own hard disk partition table
+ format, incompatible with all others. Saying Y here allows you to
+ read these partition tables and further mount SunOS partitions from
+ within Linux if you have also said Y to "UFS file system support",
+ above. This is mainly used to carry data from a SPARC under SunOS to
+ your Linux box via a removable medium like magneto-optical or ZIP
+ drives; note however that a good portable way to transport files and
+ directories between unixes (and even other operating systems) is
+ given by the tar program ("man tar" or preferably "info tar"). If
+ you don't know what all this is about, say N.
+
+Solaris (x86) partition table support
+CONFIG_SOLARIS_X86_PARTITION
+ Like most systems, Solaris x86 uses its own hard disk partition
+ table format, incompatible with all others. Saying Y here allows you
+ to read these partition tables and further mount Solaris x86
+ partitions from within Linux if you have also said Y to "UFS
+ file system support", above.
+
+SGI partition support
+CONFIG_SGI_PARTITION
+ Say Y here if you would like to be able to read the hard disk
+ partition table format used by SGI machines.
+
+Intel EFI GUID partition support
+CONFIG_EFI_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned using EFI GPT. Presently only useful on the
+ IA-64 platform.
+
+Ultrix partition table support
+CONFIG_ULTRIX_PARTITION
+ Say Y here if you would like to be able to read the hard disk
+ partition table format used by DEC (now Compaq) Ultrix machines.
+ Otherwise, say N.
+
+IBM disk label and partition support
+CONFIG_IBM_PARTITION
+ You have to say Y here if you would like to be able to read volume
+ labels of IBM DASD disks. These can be ECKD DASD disks with
+ compatible disk layout (cdl) and standard Linux disk layout (ldl),
+ FBA DASD disks and CMS reserved minidisks.
+ Otherwise, say N and you will not be able to access these disks.
+
+ADFS file system support
+CONFIG_ADFS_FS
+ The Acorn Disc Filing System is the standard file system of the
+ RiscOS operating system which runs on Acorn's ARM-based Risc PC
+ systems and the Acorn Archimedes range of machines. If you say Y
+ here, Linux will be able to read from ADFS partitions on hard drives
+ and from ADFS-formatted floppy discs. If you also want to be able to
+ write to those devices, say Y to "ADFS write support" below.
+
+ The ADFS partition should be the first partition (i.e.,
+ /dev/[hs]d?1) on each of your drives. Please read the file
+ <file:Documentation/filesystems/adfs.txt> for further details.
+
+ This code is also available as a module called adfs.o ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want). If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+
+ If unsure, say N.
+
+ADFS write support (DANGEROUS)
+CONFIG_ADFS_FS_RW
+ If you say Y here, you will be able to write to ADFS partitions on
+ hard drives and ADFS-formatted floppy disks. This is experimental
+ codes, so if you're unsure, say N.
+
+JFS filesystem support
+CONFIG_JFS_FS
+ This is a port of IBM's Journalling Filesystem . More information is
+ available in the file Documentation/filesystems/jfs.txt.
+
+ If you do not intend to use the JFS filesystem, say N.
+
+JFS Debugging
+CONFIG_JFS_DEBUG
+ If you are experiencing any problems with the JFS filesystem, say
+ Y here. This will result in additional debugging messages to be
+ written to the system log. Under normal circumstances, this
+ results in very little overhead.
+
+JFS Statistics
+CONFIG_JFS_STATISTICS
+ Enabling this option will cause statistics from the JFS file system
+ to be made available to the user in the /proc/fs/jfs/ directory.
+
+/dev/pts file system for Unix98 PTYs
+CONFIG_DEVPTS_FS
+ You should say Y here if you said Y to "Unix98 PTY support" above.
+ You'll then get a virtual file system which can be mounted on
+ /dev/pts with "mount -t devpts". This, together with the pseudo
+ terminal master multiplexer /dev/ptmx, is used for pseudo terminal
+ support as described in The Open Group's Unix98 standard: in order
+ to acquire a pseudo terminal, a process opens /dev/ptmx; the number
+ of the pseudo terminal is then made available to the process and the
+ pseudo terminal slave can be accessed as /dev/pts/<number>. What was
+ traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
+
+ The GNU C library glibc 2.1 contains the requisite support for this
+ mode of operation; you also need client programs that use the Unix98
+ API. Please read <file:Documentation/Changes> for more information
+ about the Unix98 pty devices.
+
+ Note that the experimental "/dev file system support"
+ (CONFIG_DEVFS_FS) is a more general facility.
+
+FreeVxFS file system support (VERITAS VxFS(TM) compatible)
+CONFIG_VXFS_FS
+ FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
+ file system format. VERITAS VxFS(TM) is the standard file system
+ of SCO UnixWare (and possibly others) and optionally available
+ for Sunsoft Solaris, HP-UX and many other operating systems.
+ Currently only readonly access is supported.
+
+ NOTE: the file system type as used by mount(1), mount(2) and
+ fstab(5) is 'vxfs' as it describes the file system format, not
+ the actual driver.
+
+ This file system is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called freevxfs.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
+UnixWare slices support
+CONFIG_UNIXWARE_DISKLABEL
+ Like some systems, UnixWare uses its own slice table inside a
+ partition (VTOC - Virtual Table of Contents). Its format is
+ incompatible with all other OSes. Saying Y here allows you to read
+ VTOC and further mount UnixWare partitions read-only from within
+ Linux if you have also said Y to "UFS file system support" or
+ "System V and Coherent file system support", above.
+
+ This is mainly used to carry data from a UnixWare box to your
+ Linux box via a removable medium like magneto-optical, ZIP or
+ removable IDE drives. Note, however, that a good portable way to
+ transport files and directories between unixes (and even other
+ operating systems) is given by the tar program ("man tar" or
+ preferably "info tar").
+
+ If you don't know what all this is about, say N.
+
+CIFS (Common Internet File System) support
+CONFIG_CIFS
+ This is the client VFS module for the Common Internet File System
+ (CIFS) protocol which is the successor to the Server Message Block
+ (SMB) protocol, the native file sharing mechanism for most early
+ PC operating systems. CIFS is fully supported by current network
+ file servers such as Windows 2000, Windows 2003 (including
+ Windows XP) as well by Samba (which provides excellent CIFS
+ server support for Linux and many other operating systems).
+ The smbfs module should be used instead of this cifs module for
+ mounting to older SMB servers such as OS/2. The smbfs and cifs
+ modules can coexist and do not conflict.
+
+ The intent of this module is to provide the most advanced network
+ file system function for CIFS compliant servers, including better
+ POSIX compliance, secure per-user session establishment, high
+ performance safe distributed caching (oplock), optional packet
+ signing, Unicode support and other internationalization improvements
+ For more information see the project page at
+ http://us1.samba.org/samba/Linux_CIFS_client.html
+
+CIFS Debugging
+CONFIG_CIFS_DEBUG
+ If you are experiencing any problems with the CIFS filesystem, say
+ Y here. This will result in additional debugging messages to be
+ written to the system log. Under normal circumstances, this
+ results in very little overhead.
+
+SMB file system support (to mount Windows shares etc.)
+CONFIG_SMB_FS
+ SMB (Server Message Block) is the protocol Windows for Workgroups
+ (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share
+ files and printers over local networks. Saying Y here allows you to
+ mount their file systems (often called "shares" in this context) and
+ access them just like any other Unix directory. Currently, this
+ works only if the Windows machines use TCP/IP as the underlying
+ transport protocol, and not NetBEUI. For details, read
+ <file:Documentation/filesystems/smbfs.txt> and the SMB-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ Note: if you just want your box to act as an SMB *server* and make
+ files and printing services available to Windows clients (which need
+ to have a TCP/IP stack), you don't need to say Y here; you can use
+ the program SAMBA (available from <ftp://ftp.samba.org/pub/samba/>)
+ for that.
+
+ General information about how to connect Linux, Windows machines and
+ Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
+
+ If you want to compile the SMB support as a module ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want), say M here and read <file:Documentation/modules.txt>. The
+ module will be called smbfs.o. Most people say N, however.
+
+Use a default NLS
+CONFIG_SMB_NLS_DEFAULT
+ Enabling this will make smbfs use nls translations by default. You
+ need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls
+ settings and you need to give the default nls for the SMB server as
+ CONFIG_SMB_NLS_REMOTE.
+
+ The nls settings can be changed at mount time, if your smbmount
+ supports that, using the codepage and iocharset parameters.
+
+ smbmount from samba 2.2.0 or later supports this.
+
+Default Remote NLS Option
+CONFIG_SMB_NLS_REMOTE
+ This setting allows you to specify a default value for which
+ codepage the server uses. If this field is left blank no
+ translations will be done by default. The local codepage/charset
+ default to CONFIG_NLS_DEFAULT.
+
+ The nls settings can be changed at mount time, if your smbmount
+ supports that, using the codepage and iocharset parameters.
+
+ smbmount from samba 2.2.0 or later supports this.
+
+Coda file system support (advanced network fs)
+CONFIG_CODA_FS
+ Coda is an advanced network file system, similar to NFS in that it
+ enables you to mount file systems of a remote server and access them
+ with regular Unix commands as if they were sitting on your hard
+ disk. Coda has several advantages over NFS: support for
+ disconnected operation (e.g. for laptops), read/write server
+ replication, security model for authentication and encryption,
+ persistent client caches and write back caching.
+
+ If you say Y here, your Linux box will be able to act as a Coda
+ *client*. You will need user level code as well, both for the
+ client and server. Servers are currently user level, i.e. they need
+ no kernel support. Please read
+ <file:Documentation/filesystems/coda.txt> and check out the Coda
+ home page <http://www.coda.cs.cmu.edu/>.
+
+ If you want to compile the coda client support as a module ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want), say M here and read
+ <file:Documentation/modules.txt>. The module will be called coda.o.
+
+InterMezzo file system support (replicating fs)
+CONFIG_INTERMEZZO_FS
+ InterMezzo is a networked file system with disconnected operation
+ and kernel level write back caching. It is most often used for
+ replicating potentially large trees or keeping laptop/desktop copies
+ in sync.
+
+ If you say Y or M your kernel or module will provide InterMezzo
+ support. You will also need a file server daemon, which you can get
+ from <http://www.inter-mezzo.org/>.
+
+NCP file system support (to mount NetWare volumes)
+CONFIG_NCP_FS
+ NCP (NetWare Core Protocol) is a protocol that runs over IPX and is
+ used by Novell NetWare clients to talk to file servers. It is to
+ IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you
+ to mount NetWare file server volumes and to access them just like
+ any other Unix directory. For details, please read the file
+ <file:Documentation/filesystems/ncpfs.txt> in the kernel source and
+ the IPX-HOWTO from <http://www.tldp.org/docs.html#howto>.
+
+ You do not have to say Y here if you want your Linux box to act as a
+ file *server* for Novell NetWare clients.
+
+ General information about how to connect Linux, Windows machines and
+ Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called ncpfs.o. Say N unless you are connected to a Novell
+ network.
+
+Packet signatures
+CONFIG_NCPFS_PACKET_SIGNING
+ NCP allows packets to be signed for stronger security. If you want
+ security, say Y. Normal users can leave it off. To be able to use
+ packet signing you must use ncpfs > 2.0.12.
+
+Proprietary file locking
+CONFIG_NCPFS_IOCTL_LOCKING
+ Allows locking of records on remote volumes. Say N unless you have
+ special applications which are able to utilize this locking scheme.
+
+Clear remove/delete inhibit when needed
+CONFIG_NCPFS_STRONG
+ Allows manipulation of files flagged as Delete or Rename Inhibit.
+ To use this feature you must mount volumes with the ncpmount
+ parameter "-s" (ncpfs-2.0.12 and newer). Say Y unless you are not
+ mounting volumes with -f 444.
+
+Use NFS namespace if available
+CONFIG_NCPFS_NFS_NS
+ Allows you to utilize NFS namespace on NetWare servers. It brings
+ you case sensitive filenames. Say Y. You can disable it at
+ mount-time with the `-N nfs' parameter of ncpmount.
+
+Use LONG (OS/2) namespace if available
+CONFIG_NCPFS_OS2_NS
+ Allows you to utilize OS2/LONG namespace on NetWare servers.
+ Filenames in this namespace are limited to 255 characters, they are
+ case insensitive, and case in names is preserved. Say Y. You can
+ disable it at mount time with the -N os2 parameter of ncpmount.
+
+Lowercase DOS filenames on LONG namespace volume
+CONFIG_NCPFS_SMALLDOS
+ If you say Y here, every filename on a NetWare server volume using
+ the OS2/LONG namespace and created under DOS or on a volume using
+ DOS namespace will be converted to lowercase characters.
+ Saying N here will give you these filenames in uppercase.
+
+ This is only a cosmetic option since the OS2/LONG namespace is case
+ insensitive. The only major reason for this option is backward
+ compatibility when moving from DOS to OS2/LONG namespace support.
+ Long filenames (created by Win95) will not be affected.
+
+ This option does not solve the problem that filenames appear
+ differently under Linux and under Windows, since Windows does an
+ additional conversions on the client side. You can achieve similar
+ effects by saying Y to "Allow using of Native Language Support"
+ below.
+
+Use Native Language Support
+CONFIG_NCPFS_NLS
+ Allows you to use codepages and I/O charsets for file name
+ translation between the server file system and input/output. This
+ may be useful, if you want to access the server with other operating
+ systems, e.g. Windows 95. See also NLS for more Information.
+
+ To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer.
+
+Symbolic links and mode permission bits
+CONFIG_NCPFS_EXTRAS
+ This enables the use of symbolic links and an execute permission
+ bit on NCPFS. The file server need not have long name space or NFS
+ name space loaded for these to work.
+
+ To use the new attributes, it is recommended to use the flags
+ '-f 600 -d 755' on the ncpmount command line.
+
+Default NLS Option
+CONFIG_NLS_DEFAULT
+ The default NLS used when mounting file system. Note, that this is
+ the NLS used by your console, not the NLS used by a specific file
+ system (if different) to store data (filenames) on a disk.
+ Currently, the valid values are:
+ big5, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861,
+ cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936,
+ cp949, cp950, cp1250, cp1251, cp1255, euc-jp, euc-kr, gb2312, iso8859-1,
+ iso8859-2, iso8859-3, iso8859-4, iso8859-5, iso8859-6, iso8859-7,
+ iso8859-8, iso8859-9, iso8859-13, iso8859-14, iso8859-15,
+ koi8-r, koi8-ru, koi8-u, sjis, tis-620, utf8.
+ If you specify a wrong value, it will use the built-in NLS;
+ compatible with iso8859-1.
+
+ If unsure, specify it as "iso8859-1".
+
+Codepage 437 (United States, Canada)
+CONFIG_NLS_CODEPAGE_437
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored
+ in so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage that is used in
+ the United States and parts of Canada. This is recommended.
+
+Codepage 737 (Greek)
+CONFIG_NLS_CODEPAGE_737
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored
+ in so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage that is used for
+ Greek. If unsure, say N.
+
+Codepage 775 (Baltic Rim)
+CONFIG_NLS_CODEPAGE_775
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored
+ in so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage that is used
+ for the Baltic Rim Languages (Latvian and Lithuanian). If unsure,
+ say N.
+
+Codepage 850 (Europe)
+CONFIG_NLS_CODEPAGE_850
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage that is used for
+ much of Europe -- United Kingdom, Germany, Spain, Italy, and [add
+ more countries here]. It has some characters useful to many European
+ languages that are not part of the US codepage 437.
+
+ If unsure, say Y.
+
+Codepage 852 (Central/Eastern Europe)
+CONFIG_NLS_CODEPAGE_852
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the Latin 2 codepage used by DOS
+ for much of Central and Eastern Europe. It has all the required
+ characters for these languages: Albanian, Croatian, Czech, English,
+ Finnish, Hungarian, Irish, German, Polish, Rumanian, Serbian (Latin
+ transcription), Slovak, Slovenian, and Serbian.
+
+Codepage 855 (Cyrillic)
+CONFIG_NLS_CODEPAGE_855
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Cyrillic.
+
+Codepage 857 (Turkish)
+CONFIG_NLS_CODEPAGE_857
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Turkish.
+
+Codepage 860 (Portuguese)
+CONFIG_NLS_CODEPAGE_860
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Portuguese.
+
+Codepage 861 (Icelandic)
+CONFIG_NLS_CODEPAGE_861
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Icelandic.
+
+Codepage 862 (Hebrew)
+CONFIG_NLS_CODEPAGE_862
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Hebrew.
+
+Codepage 863 (Canadian French)
+CONFIG_NLS_CODEPAGE_863
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Canadian
+ French.
+
+Codepage 864 (Arabic)
+CONFIG_NLS_CODEPAGE_864
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Arabic.
+
+Codepage 865 (Norwegian, Danish)
+CONFIG_NLS_CODEPAGE_865
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for the Nordic
+ European countries.
+
+Codepage 866 (Cyrillic/Russian)
+CONFIG_NLS_CODEPAGE_866
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for
+ Cyrillic/Russian.
+
+Codepage 869 (Greek)
+CONFIG_NLS_CODEPAGE_869
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Greek.
+
+Thai charset (CP874, TIS-620)
+CONFIG_NLS_CODEPAGE_874
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Thai.
+
+Windows CP1251 (Bulgarian, Belarusian)
+CONFIG_NLS_CODEPAGE_1251
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Russian and
+ Bulgarian and Belarusian.
+
+Japanese charsets (Shift-JIS, EUC-JP)
+CONFIG_NLS_CODEPAGE_932
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Shift-JIS
+ or EUC-JP. To use EUC-JP, you can use 'euc-jp' as mount option or
+ NLS Default value during kernel configuration, instead of 'cp932'.
+
+Simplified Chinese charset (CP936, GB2312)
+CONFIG_NLS_CODEPAGE_936
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Simplified
+ Chinese(GBK).
+
+Korean charset (CP949, EUC-KR)
+CONFIG_NLS_CODEPAGE_949
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for UHC.
+
+Traditional Chinese charset (Big5)
+CONFIG_NLS_CODEPAGE_950
+ The Microsoft FAT file system family can deal with filenames in
+ native language character sets. These character sets are stored in
+ so-called DOS codepages. You need to include the appropriate
+ codepage if you want to be able to read/write these filenames on
+ DOS/Windows partitions correctly. This does apply to the filenames
+ only, not to the file contents. You can include several codepages;
+ say Y here if you want to include the DOS codepage for Traditional
+ Chinese(Big5).
+
+Central European (Codepage 1250)
+CONFIG_NLS_CODEPAGE_1250
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CDROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Windows CP-1250
+ character set, which works for most Latin-written Slavic and Central
+ European languages: Czech, German, Hungarian, Polish, Rumanian, Croatian,
+ Slovak, Slovene.
+
+NLS ISO 8859-1 (Latin 1; Western European Languages)
+CONFIG_NLS_ISO8859_1
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 1 character
+ set, which covers most West European languages such as Albanian,
+ Catalan, Danish, Dutch, English, Faeroese, Finnish, French, German,
+ Galician, Irish, Icelandic, Italian, Norwegian, Portuguese, Spanish,
+ and Swedish. It is also the default for the US. If unsure, say Y.
+
+NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages)
+CONFIG_NLS_ISO8859_2
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 2 character
+ set, which works for most Latin-written Slavic and Central European
+ languages: Czech, German, Hungarian, Polish, Rumanian, Croatian,
+ Slovak, Slovene.
+
+NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)
+CONFIG_NLS_ISO8859_3
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 3 character
+ set, which is popular with authors of Esperanto, Galician, Maltese,
+ and Turkish.
+
+NLS ISO 8859-4 (Latin 4; old Baltic charset)
+CONFIG_NLS_ISO8859_4
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 4 character
+ set which introduces letters for Estonian, Latvian, and
+ Lithuanian. It is an incomplete predecessor of Latin 7.
+
+NLS ISO 8859-5 (Cyrillic)
+CONFIG_NLS_ISO8859_5
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for ISO8859-5, a Cyrillic
+ character set with which you can type Bulgarian, Belarusian,
+ Macedonian, Russian, Serbian, and Ukrainian. Note that the charset
+ KOI8-R is preferred in Russia.
+
+NLS ISO 8859-6 (Arabic)
+CONFIG_NLS_ISO8859_6
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for ISO8859-6, the Arabic
+ character set.
+
+NLS ISO 8859-7 (Modern Greek)
+CONFIG_NLS_ISO8859_7
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for ISO8859-7, the Modern
+ Greek character set.
+
+Hebrew charsets (ISO-8859-8, CP1255)
+CONFIG_NLS_ISO8859_8
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for ISO8859-8, the Hebrew
+ character set.
+
+NLS ISO 8859-9 (Latin 5; Turkish)
+CONFIG_NLS_ISO8859_9
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 5 character
+ set, and it replaces the rarely needed Icelandic letters in Latin 1
+ with the Turkish ones. Useful in Turkey.
+
+NLS ISO 8859-10 (Latin 6; Nordic)
+CONFIG_NLS_ISO8859_10
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 6 character
+ set, which adds the last Inuit (Greenlandic) and Sami (Lappish)
+ letters that were missing in Latin 4 to cover the entire Nordic
+ area.
+
+NLS ISO 8859-13 (Latin 7; Baltic)
+CONFIG_NLS_ISO8859_13
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 7 character
+ set, which supports modern Baltic languages including Latvian
+ and Lithuanian.
+
+NLS ISO 8859-14 (Latin 8; Celtic)
+CONFIG_NLS_ISO8859_14
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 8 character
+ set, which adds the last accented vowels for Welsh (aka Cymraeg)
+ (and Manx Gaelic) that were missing in Latin 1.
+ <http://linux.speech.cymru.org/> has further information.
+
+NLS ISO 8859-15 (Latin 9; Western European languages with Euro)
+CONFIG_NLS_ISO8859_15
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the Latin 9 character
+ set, which covers most West European languages such as Albanian,
+ Catalan, Danish, Dutch, English, Estonian, Faeroese, Finnish,
+ French, German, Galician, Irish, Icelandic, Italian, Norwegian,
+ Portuguese, Spanish, and Swedish. Latin 9 is an update to
+ Latin 1 (ISO 8859-1) that removes a handful of rarely used
+ characters and instead adds support for Estonian, corrects the
+ support for French and Finnish, and adds the new Euro character.
+ If unsure, say Y.
+
+NLS KOI8-R (Russian)
+CONFIG_NLS_KOI8_R
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the preferred Russian
+ character set.
+
+NLS KOI8-U/RU (Ukrainian, Belarusian)
+CONFIG_NLS_KOI8_U
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the preferred Ukrainian
+ (koi8-u) and Belarusian (koi8-ru) character sets.
+
+NLS UTF8
+CONFIG_NLS_UTF8
+ If you want to display filenames with native language characters
+ from the Microsoft FAT file system family or from JOLIET CD-ROMs
+ correctly on the screen, you need to include the appropriate
+ input/output character sets. Say Y here for the UTF-8 encoding of
+ the Unicode/ISO9646 universal character set.
+
+Virtual terminal
+CONFIG_VT
+ If you say Y here, you will get support for terminal devices with
+ display and keyboard devices. These are called "virtual" because you
+ can run several virtual terminals (also called virtual consoles) on
+ one physical terminal. This is rather useful, for example one
+ virtual terminal can collect system messages and warnings, another
+ one can be used for a text-mode user session, and a third could run
+ an X session, all in parallel. Switching between virtual terminals
+ is done with certain key combinations, usually Alt-<function key>.
+
+ The setterm command ("man setterm") can be used to change the
+ properties (such as colors or beeping) of a virtual terminal. The
+ man page console_codes(4) ("man console_codes") contains the special
+ character sequences that can be used to change those properties
+ directly. The fonts used on virtual terminals can be changed with
+ the setfont ("man setfont") command and the key bindings are defined
+ with the loadkeys ("man loadkeys") command.
+
+ You need at least one virtual terminal device in order to make use
+ of your keyboard and monitor. Therefore, only people configuring an
+ embedded system would want to say N here in order to save some
+ memory; the only way to log into such a system is then via a serial
+ or network connection.
+
+ If unsure, say Y, or else you won't be able to do much with your new
+ shiny Linux system :-)
+
+Support for console on virtual terminal
+CONFIG_VT_CONSOLE
+ The system console is the device which receives all kernel messages
+ and warnings and which allows logins in single user mode. If you
+ answer Y here, a virtual terminal (the device used to interact with
+ a physical terminal) can be used as system console. This is the most
+ common mode of operations, so you should say Y here unless you want
+ the kernel messages be output only to a serial port (in which case
+ you should say Y to "Console on serial port", below).
+
+ If you do say Y here, by default the currently visible virtual
+ terminal (/dev/tty0) will be used as system console. You can change
+ that with a kernel command line option such as "console=tty3" which
+ would use the third virtual terminal as system console. (Try "man
+ bootparam" or see the documentation of your boot loader (lilo or
+ loadlin) about how to pass options to the kernel at boot time.)
+
+ If unsure, say Y.
+
+STI console
+CONFIG_STI_CONSOLE
+ The STI console is the builtin display/keyboard on HP-PARISC
+ machines. Say Y here to build support for it into your kernel.
+ The alternative is to use your primary serial port as a console.
+
+Use MDIO for PHY configuration
+CONFIG_USE_MDIO
+ On some boards the hardware configuration of the ethernet PHY can be
+ used without any software interaction over the MDIO interface, so
+ all MII code can be omitted. Say N here if unsure or if you don't
+ need link status reports.
+
+860T FEC Ethernet
+CONFIG_FEC_ENET
+ Enable Ethernet support via the Fast Ethernet Controller (FCC) on
+ the Motorola MPC8260.
+
+Ethernet on FCC1
+CONFIG_FCC1_ENET
+ Use MPC8260 fast Ethernet controller 1 to drive Ethernet (default).
+
+Ethernet on FCC2
+CONFIG_FCC2_ENET
+ Use MPC8260 fast Ethernet controller 2 to drive Ethernet.
+
+Ethernet on FCC3
+CONFIG_FCC3_ENET
+ Use MPC8260 fast Ethernet controller 3 to drive Ethernet.
+
+CPM SCC Ethernet
+CONFIG_SCC_ENET
+ Enable Ethernet support via the Motorola MPC8xx serial
+ communications controller.
+
+# Choice: scc_ethernet
+Ethernet on SCC1
+CONFIG_SCC1_ENET
+ Use MPC8xx serial communications controller 1 to drive Ethernet
+ (default).
+
+Ethernet on SCC2
+CONFIG_SCC2_ENET
+ Use MPC8xx serial communications controller 2 to drive Ethernet.
+
+Ethernet on SCC3
+CONFIG_SCC3_ENET
+ Use MPC8xx serial communications controller 3 to drive Ethernet.
+
+Use Big CPM Ethernet Buffers
+CONFIG_ENET_BIG_BUFFERS
+ Allocate large buffers for MPC8xx Ethernet. Increases throughput
+ and decreases the likelihood of dropped packets, but costs memory.
+
+Apple Desktop Bus (ADB) support
+CONFIG_ADB
+ Apple Desktop Bus (ADB) support is for support of devices which
+ are connected to an ADB port. ADB devices tend to have 4 pins.
+ If you have an Apple Macintosh prior to the iMac, or a
+ "Blue and White G3", you probably want to say Y here. Otherwise
+ say N.
+
+Support for CUDA based PowerMacs
+CONFIG_ADB_CUDA
+ This provides support for CUDA based Power Macintosh systems. This
+ includes most OldWorld PowerMacs, the first generation iMacs, the
+ Blue&White G3 and the Yikes G4 (PCI Graphics). All later models
+ should use CONFIG_ADB_PMU instead.
+
+ If unsure say Y.
+
+Support for PMU-based PowerMacs
+CONFIG_ADB_PMU
+ This provides support for PMU based Power Macintosh systems. This
+ includes all PowerBooks and all AGP-based machines.
+
+ If unsure say Y.
+
+Include MacIO ADB driver
+CONFIG_ADB_MACIO
+ Say Y here to include direct support for the ADB controller in the
+ Hydra chip used on PowerPC Macintoshes of the CHRP type. (The Hydra
+ also includes a MESH II SCSI controller, DBDMA controller, VIA chip,
+ OpenPIC controller and two RS422/Geoports.)
+
+Support for ADB keyboard (old driver)
+CONFIG_ADB_KEYBOARD
+ This option allows you to use an ADB keyboard attached to your
+ machine. Note that this disables any other (ie. PS/2) keyboard
+ support, even if your machine is physically capable of using both at
+ the same time.
+
+ If you use an ADB keyboard (4 pin connector), say Y here.
+ If you use a PS/2 keyboard (6 pin connector), say N here.
+
+HIL keyboard support
+CONFIG_HIL
+ The "Human Interface Loop" is a older, 8-channel USB-like controller
+ used in Hewlett Packard PA-RISC based machines. There are a few
+ cases where it is seen on PC/MAC architectures as well, usually also
+ manufactured by HP. This driver is based off MACH and BSD drivers,
+ and implements support for a keyboard attached to the HIL port.
+ Full support for the USB-like functions and non-keyboard channels of
+ the HIL is not provided for in this driver. There are vestiges of
+ mouse support in the driver, but it is probably not working. The
+ necessary hardware documentation to fully support the HIL controller
+ and interface it to the linux-input API is lacking.
+
+ Enable this option if you intend to use a HIL keyboard.
+
+Include IOP (IIfx/Quadra 9x0) ADB driver
+CONFIG_ADB_IOP
+ The I/O Processor (IOP) is an Apple custom IC designed to provide
+ intelligent support for I/O controllers. It is described at
+ <http://www.angelfire.com/ca2/dev68k/iopdesc.html> to enable direct
+ support for it, say 'Y' here.
+
+Mac II style Apple Desktop Bus support
+CONFIG_ADB_MACII
+ Say Y here if want your kernel to support Macintosh systems that use
+ the Mac II style ADB. This includes the II, IIx, IIcx, SE/30, IIci,
+ Quadra 610, Quadra 650, Quadra 700, Quadra 800, Centris 610 and
+ Centris 650.
+
+Mac IIsi style Apple Desktop Bus support
+CONFIG_ADB_MACIISI
+ Say Y here if want your kernel to support Macintosh systems that use
+ the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic
+ II, LC, LC II, LC III, Performa 460, and the Performa 600.
+
+Apple 68K PowerBook Power Management and Desktop Bus support
+CONFIG_ADB_PMU68K
+ Say Y here if want your kernel to support the m68k based Powerbooks.
+ This includes the PowerBook 140, PowerBook 145, PowerBook 150,
+ PowerBook 160, PowerBook 165, PowerBook 165c, PowerBook 170,
+ PowerBook 180, PowerBook, 180c, PowerBook 190cs, PowerBook 520,
+ PowerBook Duo 210, PowerBook Duo 230, PowerBook Duo 250,
+ PowerBook Duo 270c, PowerBook Duo 280 and PowerBook Duo 280c.
+
+Macintosh IIfx/Quadra 900/Quadra 950 floppy support
+CONFIG_BLK_DEV_SWIM_IOP
+ Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
+ floppy controller on the Macintosh IIfx and Quadra 900/950.
+
+Macintosh NS8390 based Ethernet support
+CONFIG_MAC8390
+ If you want to include a driver to support Nubus or LC-PDS
+ Ethernet cards using an NS8390 chipset or its equivalent, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+Macintosh CS89x0 based Ethernet support
+CONFIG_MAC89x0
+ Support for CS89x0 chipset based Ethernet cards. If you have a
+ Nubus or LC-PDS network (Ethernet) card of this type, say Y and
+ read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. This module will
+ be called mac89x0.o.
+
+Macintosh onboard AMD 79C940 MACE based Ethernet support
+CONFIG_MACMACE
+ Support for the onboard AMD 79C940 MACE Ethernet controller used in
+ the 660AV and 840AV Macintosh. If you have one of these Macintoshes
+ say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+Macintosh SONIC based Ethernet support (onboard, NuBus, LC, CS)
+CONFIG_MACSONIC
+ Support for NatSemi SONIC based Ethernet devices. This includes
+ the onboard Ethernet in many Quadras as well as some LC-PDS,
+ a few Nubus and all known Comm Slot Ethernet cards. If you have
+ one of these say Y and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> as well as
+ <file:Documentation/networking/net-modules.txt>. This module will
+ be called macsonic.o.
+
+Macintosh NCR5380 SCSI support
+CONFIG_MAC_SCSI
+ This is the NCR 5380 SCSI controller included on most of the 68030
+ based Macintoshes. If you have one of these say Y and read the
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+Macintosh NCR53c9[46] SCSI support
+CONFIG_SCSI_MAC_ESP
+ This is the NCR 53c9x SCSI controller found on most of the 68040
+ based Macintoshes. If you have one of these say Y and read the
+ SCSI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called mac_esp.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
+Standard/generic (8250/16550 and compatible UARTs) serial support
+CONFIG_SERIAL
+ This selects whether you want to include the driver for the standard
+ serial ports. The standard answer is Y. People who might say N
+ here are those that are setting up dedicated Ethernet WWW/FTP
+ servers, or users that have one of the various bus mice instead of a
+ serial mouse and don't intend to use their machine's standard serial
+ port for anything. (Note that the Cyclades and Stallion multi
+ serial port drivers do not need this driver built in for them to
+ work.)
+
+ If you want to compile this driver as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ serial.o.
+ [WARNING: Do not compile this driver as a module if you are using
+ non-standard serial ports, since the configuration information will
+ be lost when the driver is unloaded. This limitation may be lifted
+ in the future.]
+
+ BTW1: If you have a mouseman serial mouse which is not recognized by
+ the X window system, try running gpm first.
+
+ BTW2: If you intend to use a software modem (also called Winmodem)
+ under Linux, forget it. These modems are crippled and require
+ proprietary drivers which are only available under Windows.
+
+ Most people will say Y or M here, so that they can use serial mice,
+ modems and similar devices connecting to the standard serial ports.
+
+Support for console on serial port
+CONFIG_SERIAL_CONSOLE
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
+ kernel messages and warnings and which allows logins in single user
+ mode). This could be useful if some terminal or printer is connected
+ to that serial port.
+
+ Even if you say Y here, the currently visible virtual console
+ (/dev/tty0) will still be used as the system console by default, but
+ you can alter that using a kernel command line option such as
+ "console=ttyS1". (Try "man bootparam" or see the documentation of
+ your boot loader (lilo or loadlin) about how to pass options to the
+ kernel at boot time.)
+
+ If you don't have a VGA card installed and you say Y here, the
+ kernel will automatically use the first serial line, /dev/ttyS0, as
+ system console.
+
+ If unsure, say N.
+
+Support for PowerMac serial ports
+CONFIG_MAC_SERIAL
+ If you have Macintosh style serial ports (8 pin mini-DIN), say Y
+ here. If you also have regular serial ports and enable the driver
+ for them, you can't currently use the serial console feature.
+
+Comtrol Rocketport support
+CONFIG_ROCKETPORT
+ This is a driver for the Comtrol Rocketport cards which provide
+ multiple serial ports. You would need something like this to connect
+ more than two modems to your Linux box, for instance in order to
+ become a dial-in server.
+
+ If you want to compile this driver as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ rocket.o.
+
+Digiboard Intelligent async support
+CONFIG_DIGIEPCA
+ This is a driver for Digi International's Xx, Xeve, and Xem series
+ of cards which provide multiple serial ports. You would need
+ something like this to connect more than two modems to your Linux
+ box, for instance in order to become a dial-in server. This driver
+ supports the original PC (ISA) boards as well as PCI, and EISA. If
+ you have a card like this, say Y here and read the file
+ <file:Documentation/digiepca.txt>.
+
+ NOTE: There is another, separate driver for the Digiboard PC boards:
+ "Digiboard PC/Xx Support" below. You should (and can) only select
+ one of the two drivers.
+
+ If you want to compile this driver as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called epca.o.
+
+Digiboard PC/Xx Support
+CONFIG_DIGI
+ This is a driver for the Digiboard PC/Xe, PC/Xi, and PC/Xeve cards
+ that give you many serial ports. You would need something like this
+ to connect more than two modems to your Linux box, for instance in
+ order to become a dial-in server. If you have a card like that, say
+ Y here and read the file <file:Documentation/digiboard.txt>.
+
+ If you want to compile this driver as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called pcxx.o.
+
+SDL RISCom/8 card support
+CONFIG_RISCOM8
+ This is a driver for the SDL Communications RISCom/8 multiport card,
+ which gives you many serial ports. You would need something like
+ this to connect more than two modems to your Linux box, for instance
+ in order to become a dial-in server. If you have a card like that,
+ say Y here and read the file <file:Documentation/riscom8.txt>.
+
+ Also it's possible to say M here and compile this driver as kernel
+ loadable module; the module will be called riscom8.o.
+
+Computone IntelliPort Plus serial support
+CONFIG_COMPUTONE
+ This driver supports the entire family of Intelliport II/Plus
+ controllers with the exception of the MicroChannel controllers and
+ products previous to the Intelliport II. These are multiport cards,
+ which give you many serial ports. You would need something like this
+ to connect more than two modems to your Linux box, for instance in
+ order to become a dial-in server. If you have a card like that, say
+ Y here and read <file:Documentation/computone.txt>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. You will get
+ two modules called ip2.o and ip2main.o.
+
+Specialix IO8+ card support
+CONFIG_SPECIALIX
+ This is a driver for the Specialix IO8+ multiport card (both the
+ ISA and the PCI version) which gives you many serial ports. You
+ would need something like this to connect more than two modems to
+ your Linux box, for instance in order to become a dial-in server.
+
+ If you have a card like that, say Y here and read the file
+ <file:Documentation/specialix.txt>. Also it's possible to say M here
+ and compile this driver as kernel loadable module which will be
+ called specialix.o.
+
+Specialix DTR/RTS pin is RTS
+CONFIG_SPECIALIX_RTSCTS
+ The Specialix IO8+ card can only support either RTS or DTR. If you
+ say N here, the driver will use the pin as "DTR" when the tty is in
+ software handshake mode. If you say Y here or hardware handshake is
+ on, it will always be RTS. Read the file
+ <file:Documentation/specialix.txt> for more information.
+
+Specialix RIO system support
+CONFIG_RIO
+ This is a driver for the Specialix RIO, a smart serial card which
+ drives an outboard box that can support up to 128 ports. Product
+ information is at <http://www.sphinxcst.co.uk/perle/multi.htm>.
+ There are both ISA and PCI versions.
+
+Support really old RIO/PCI cards
+CONFIG_RIO_OLDPCI
+ Older RIO PCI cards need some initialization-time configuration to
+ determine the IRQ and some control addresses. If you have a RIO and
+ this doesn't seem to work, try setting this to Y.
+
+Cyclades async mux support
+CONFIG_CYCLADES
+ This is a driver for a card that gives you many serial ports. You
+ would need something like this to connect more than two modems to
+ your Linux box, for instance in order to become a dial-in server.
+ For information about the Cyclades-Z card, read
+ <file:drivers/char/README.cycladesZ>.
+
+ As of 1.3.9x kernels, this driver's minor numbers start at 0 instead
+ of 32.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called cyclades.o.
+
+ If you haven't heard about it, it's safe to say N.
+
+Cyclades-Z interrupt mode operation
+CONFIG_CYZ_INTR
+ The Cyclades-Z family of multiport cards allows 2 (two) driver op
+ modes: polling and interrupt. In polling mode, the driver will check
+ the status of the Cyclades-Z ports every certain amount of time
+ (which is called polling cycle and is configurable). In interrupt
+ mode, it will use an interrupt line (IRQ) in order to check the
+ status of the Cyclades-Z ports. The default op mode is polling. If
+ unsure, say N.
+
+Stallion multiport serial support
+CONFIG_STALDRV
+ Stallion cards give you many serial ports. You would need something
+ like this to connect more than two modems to your Linux box, for
+ instance in order to become a dial-in server. If you say Y here,
+ you will be asked for your specific card model in the next
+ questions. Make sure to read <file:Documentation/stallion.txt> in
+ this case. If you have never heard about all this, it's safe to
+ say N.
+
+Stallion EasyIO or EC8/32 support
+CONFIG_STALLION
+ If you have an EasyIO or EasyConnection 8/32 multiport Stallion
+ card, then this is for you; say Y. Make sure to read
+ <file:Documentation/stallion.txt>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called stallion.o.
+
+Stallion EC8/64, ONboard, Brumby support
+CONFIG_ISTALLION
+ If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
+ serial multiport card, say Y here. Make sure to read
+ <file:Documentation/stallion.txt>.
+
+ To compile it as a module ( = code which can be inserted in and
+ removed from the running kernel whenever you want), say M here and
+ read <file:Documentation/modules.txt>. The module will be called
+ istallion.o.
+
+Microgate SyncLink adapter support
+CONFIG_SYNCLINK
+ Provides support for the SyncLink ISA and PCI multiprotocol serial
+ adapters. These adapters support asynchronous and HDLC bit
+ synchronous communication up to 10Mbps (PCI adapter).
+
+ This driver can only be built as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called synclink.o. If you want to do that, say M
+ here.
+
+CONFIG_SYNCLINKMP
+ Enable support for the SyncLink Multiport (2 or 4 ports)
+ serial adapter, running asynchronous and HDLC communications up
+ to 2.048Mbps. Each ports is independently selectable for
+ RS-232, V.35, RS-449, RS-530, and X.21
+
+ This driver may be built as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called synclinkmp.o. If you want to do that, say M
+ here.
+
+Synchronous HDLC line discipline support
+CONFIG_N_HDLC
+ Allows synchronous HDLC communications with tty device drivers that
+ support synchronous HDLC such as the Microgate SyncLink adapter.
+
+ This driver can only be built as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called n_hdlc.o. If you want to do that, say M
+ here.
+
+Specialix SX (and SI) card support
+CONFIG_SX
+ This is a driver for the SX and SI multiport serial cards.
+ Please read the file <file:Documentation/sx.txt> for details.
+
+ This driver can only be built as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called sx.o. If you want to do that, say M here.
+
+Hayes ESP serial port support
+CONFIG_ESPSERIAL
+ This is a driver which supports Hayes ESP serial ports. Both single
+ port cards and multiport cards are supported. Make sure to read
+ <file:Documentation/hayes-esp.txt>.
+
+ To compile this driver as a module ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read <file:Documentation/modules.txt>. The module will be
+ called esp.o. If unsure, say N.
+
+Moxa Intellio support
+CONFIG_MOXA_INTELLIO
+ Say Y here if you have a Moxa Intellio multiport serial card.
+
+ This driver can also be built as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called moxa.o. If you want to do that, say M
+ here.
+
+Moxa SmartIO support
+CONFIG_MOXA_SMARTIO
+ Say Y here if you have a Moxa SmartIO multiport serial card.
+
+ This driver can also be built as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called mxser.o. If you want to do that, say M
+ here.
+
+Multi-Tech multiport card support
+CONFIG_ISI
+ This is a driver for the Multi-Tech cards which provide several
+ serial ports. The driver is experimental and can currently only be
+ built as a module ( = code which can be inserted in and removed from
+ the running kernel whenever you want). Please read
+ <file:Documentation/modules.txt>. The module will be called
+ isicom.o.
+
+Unix98 PTY support
+CONFIG_UNIX98_PTYS
+ A pseudo terminal (PTY) is a software device consisting of two
+ halves: a master and a slave. The slave device behaves identical to
+ a physical terminal; the master device is used by a process to
+ read data from and write data to the slave, thereby emulating a
+ terminal. Typical programs for the master side are telnet servers
+ and xterms.
+
+ Linux has traditionally used the BSD-like names /dev/ptyxx for
+ masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
+ has a number of problems. The GNU C library glibc 2.1 and later,
+ however, supports the Unix98 naming standard: in order to acquire a
+ pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
+ terminal is then made available to the process and the pseudo
+ terminal slave can be accessed as /dev/pts/<number>. What was
+ traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
+
+ The entries in /dev/pts/ are created on the fly by a virtual
+ file system; therefore, if you say Y here you should say Y to
+ "/dev/pts file system for Unix98 PTYs" as well.
+
+ If you want to say Y here, you need to have the C library glibc 2.1
+ or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*").
+ Read the instructions in <file:Documentation/Changes> pertaining to
+ pseudo terminals. It's safe to say N.
+
+Maximum number of Unix98 PTYs in use (0-2048)
+CONFIG_UNIX98_PTY_COUNT
+ The maximum number of Unix98 PTYs that can be used at any one time.
+ The default is 256, and should be enough for desktop systems. Server
+ machines which support incoming telnet/rlogin/ssh connections and/or
+ serve several X terminals may want to increase this: every incoming
+ connection and every xterm uses up one PTY.
+
+ When not in use, each additional set of 256 PTYs occupy
+ approximately 8 KB of kernel memory on 32-bit architectures.
+
+Parallel printer support
+CONFIG_PRINTER
+ If you intend to attach a printer to the parallel port of your Linux
+ box (as opposed to using a serial printer; if the connector at the
+ printer has 9 or 25 holes ["female"], then it's serial), say Y.
+ Also read the Printing-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ It is possible to share one parallel port among several devices
+ (e.g. printer and ZIP drive) and it is safe to compile the
+ corresponding drivers into the kernel. If you want to compile this
+ driver as a module however ( = code which can be inserted in and
+ removed from the running kernel whenever you want), say M here and
+ read <file:Documentation/modules.txt> and
+ <file:Documentation/parport.txt>. The module will be called lp.o.
+
+ If you have several parallel ports, you can specify which ports to
+ use with the "lp" kernel command line option. (Try "man bootparam"
+ or see the documentation of your boot loader (lilo or loadlin) about
+ how to pass options to the kernel at boot time.) The syntax of the
+ "lp" command line option can be found in <file:drivers/char/lp.c>.
+
+ If you have more than 8 printers, you need to increase the LP_NO
+ macro in lp.c and the PARPORT_MAX macro in parport.h.
+
+Support for console on line printer
+CONFIG_LP_CONSOLE
+ If you want kernel messages to be printed out as they occur, you
+ can have a console on the printer. This option adds support for
+ doing that; to actually get it to happen you need to pass the
+ option "console=lp0" to the kernel at boot time.
+
+ If the printer is out of paper (or off, or unplugged, or too
+ busy..) the kernel will stall until the printer is ready again.
+ By defining CONSOLE_LP_STRICT to 0 (at your own risk) you
+ can make the kernel continue when this happens,
+ but it'll lose the kernel messages.
+
+ If unsure, say N.
+
+Support for user-space parallel port device drivers
+CONFIG_PPDEV
+ Saying Y to this adds support for /dev/parport device nodes. This
+ is needed for programs that want portable access to the parallel
+ port, for instance deviceid (which displays Plug-and-Play device
+ IDs).
+
+ This is the parallel port equivalent of SCSI generic support (sg).
+ It is safe to say N to this -- it is not needed for normal printing
+ or parallel port CD-ROM/disk support.
+
+ This support is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ppdev.o.
+
+ If unsure, say N.
+
+Cobalt Networks support
+CONFIG_COBALT
+ Support for Cobalt Networks x86-based servers.
+
+Gen III (3000 series) system support
+CONFIG_COBALT_GEN_III
+ This option enables support for the 3000 series of Cobalt Networks
+ systems. This includes the RaQ 3, RaQ 4, and Qube 3 product lines.
+
+ This platform uses an AMD K6-2 processor, an ALI M1541/1533 chipset,
+ an optional NCR 53c875 SCSI controller, and two Intel 82559ER or
+ National Semiconductor DP83815 NICs.
+
+ Getting this option wrong will likely result in a kernel that does
+ not boot. Selecting support for more than 1 system series will add
+ bloat to your kernel, but will not cause anything bad to happen.
+
+ If you have a Cobalt Networks System, but aren't sure what kind,
+ say Y here.
+
+Gen V (5000 series) system support
+CONFIG_COBALT_GEN_V
+ This option enables support for the 5000 series of Cobalt Networks
+ systems. This includes the RaQ XTR product line.
+
+ This platform uses Intel Pentium III Coppermine FCPGA CPUs, the
+ ServerWorks LE chipset (with registered ECC DIMMs only!), two
+ HighPoint HPT370 IDE controllers, and two National Semiconductor
+ DP83815 NICs.
+
+ Getting this option wrong will likely result in a kernel that does
+ not boot. Selecting support for more than 1 system series will add
+ bloat to your kernel, but will not cause anything bad to happen.
+
+ If you have a Cobalt Networks System, but aren't sure what kind,
+ say Y here.
+
+Create legacy /proc files
+CONFIG_COBALT_OLDPROC
+ This option forces some Cobalt Networks drivers to support legacy
+ files in /proc. Older versions of these drivers exported files
+ directly in /proc, as opposed to the newer /proc/cobalt. If you say
+ N to this option, the old filenames will no longer be exported.
+ Regardless of your selection here, files in /proc/cobalt will be
+ exported. Of course, you have to include support for /proc fs, too.
+
+ It is safe to say Y here.
+
+Front panel LCD support
+CONFIG_COBALT_LCD
+ This enables support for the Cobalt Networks front panel. This is
+ for the LCD panel and buttons. The primary method for connection is
+ via the parallel port (IO base 0x370), but newer systems use an
+ I2C bus.
+
+ If you have a Cobalt Networks system, you should say Y here.
+
+Software controlled LED support
+CONFIG_COBALT_LED
+ This enables support for the software-controlled LEDs on Cobalt
+ Networks systems. This includes the fault light and front panel
+ LEDs on the RaQ XTR, the lightbar on the Qube 3, and others.
+
+ If you have a Cobalt Networks system, you should say Y here.
+
+Silicon serial number support
+CONFIG_COBALT_SERNUM
+ This enables support for the on-board serial number on Cobalt
+ Networks systems. This is a universally-unique 64-bit serial
+ number. Some systems use a Dallas DS2401 chip, others have an I2C
+ based EEPROM.
+
+ If you select Y here, the files /proc/cobalt/hostid and
+ /proc/cobalt/serialnumber will be created. The hostid file contains
+ a 32 bit integer generated from the serial number, in binary form.
+ The serialnumber file contains the hexadecimal representation of the
+ serial number, in ASCII.
+
+ If you have a Cobalt Networks system, you should say Y here.
+
+Chipset watchdog timer support
+CONFIG_COBALT_WDT
+ This enables support for the watchdog timer built into Cobalt
+ chipsets. The timer wakes up periodically, to make find out if
+ system has hung, or disabled interrupts too long. The result of
+ detecting a hang is a hard reboot.
+
+ If you have a Cobalt Networks system, you should say Y here.
+
+Thermal sensor support
+CONFIG_COBALT_THERMAL
+ This enables support for the thermal sensor(s) built into Cobalt
+ Networks systems. This driver exports /proc/cobalt/thermal_sensors.
+
+ If you have a Cobalt Networks system, you should say Y here.
+
+Fan tachometer support
+CONFIG_COBALT_FANS
+ This enables support for the fan tachometers built into some Cobalt
+ Networks systems. This driver exports /proc/cobalt/faninfo. Some
+ Cobalt software depends on this feature, and enabling it does not
+ cause any risks.
+
+ If you have a Cobalt Networks system, you should say Y here, unless
+ you are absolutely sure.
+
+Disk drive ruler support
+CONFIG_COBALT_RULER
+ This enables support for the cobalt hard drive ruler, found on some
+ Cobalt systems, including the RaQ XTR. This is the device that
+ enables swapping of drives. It is not needed for basic disk
+ operation. Enabling this on a system with no ruler will have no
+ adverse effects.
+
+ If you have a Cobalt Networks system, you should say Y here,
+ unless you are absolutely sure.
+
+IT8172G Sound
+CONFIG_SOUND_IT8172
+ Say Y here to support the on-board sound generator on the Integrated
+ Technology Express, Inc. ITE8172 SBC. Vendor page at
+ <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
+ board at <http://www.mvista.com/allies/semiconductor/ite.html>.
+
+I2C support
+CONFIG_I2C
+ I2C (pronounce: I-square-C) is a slow serial bus protocol used in
+ many micro controller applications and developed by Philips. SMBus,
+ or System Management Bus is a subset of the I2C protocol. More
+ information is contained in the directory <file:Documentation/i2c/>,
+ especially in the file called "summary" there.
+
+ Both I2C and SMBus are supported here. You will need this for
+ hardware sensors support, and also for Video For Linux support.
+ Specifically, if you want to use a BT848 based frame grabber/overlay
+ boards under Linux, say Y here and also to "I2C bit-banging
+ interfaces", below.
+
+ If you want I2C support, you should say Y here and also to the
+ specific driver for your bus adapter(s) below. If you say Y to
+ "/proc file system" below, you will then get a /proc interface which
+ is documented in <file:Documentation/i2c/proc-interface>.
+
+ This I2C support is also available as a module. If you want to
+ compile it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-core.o.
+
+UltraSPARC-III bootbus i2c controller driver
+CONFIG_BBC_I2C
+ The BBC devices on the UltraSPARC III have two I2C controllers. The
+ first I2C controller connects mainly to configuration PROMs (NVRAM,
+ CPU configuration, DIMM types, etc.). The second I2C controller
+ connects to environmental control devices such as fans and
+ temperature sensors. The second controller also connects to the
+ smartcard reader, if present. Say Y to enable support for these.
+
+I2C bit-banging interfaces
+CONFIG_I2C_ALGOBIT
+ This allows you to use a range of I2C adapters called bit-banging
+ adapters. Say Y if you own an I2C adapter belonging to this class
+ and then say Y to the specific driver for you adapter below.
+
+ This support is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-algo-bit.o.
+
+Philips style parallel port adapter
+CONFIG_I2C_PHILIPSPAR
+ This supports parallel-port I2C adapters made by Philips. Say Y if
+ you own such an adapter.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-philips-par.o.
+
+ Note that if you want support for different parallel port devices,
+ life will be much easier if you compile them all as modules.
+
+ELV adapter
+CONFIG_I2C_ELV
+ This supports parallel-port I2C adapters called ELV. Say Y if you
+ own such an adapter.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-elv.o.
+
+Velleman K9000 adapter
+CONFIG_I2C_VELLEMAN
+ This supports the Velleman K9000 parallel-port I2C adapter. Say Y
+ if you own such an adapter.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-velleman.o.
+
+I2C PCF 8584 interfaces
+CONFIG_I2C_ALGOPCF
+ This allows you to use a range of I2C adapters called PCF adapters.
+ Say Y if you own an I2C adapter belonging to this class and then say
+ Y to the specific driver for you adapter below.
+
+ This support is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-algo-pcf.o.
+
+Elektor ISA card
+CONFIG_I2C_ELEKTOR
+ This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
+ such an adapter.
+
+ This driver is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-elektor.o.
+
+ITE I2C Algorithm
+CONFIG_ITE_I2C_ALGO
+ This supports the use the ITE8172 I2C interface found on some MIPS
+ systems. Say Y if you have one of these. You should also say Y for
+ the ITE I2C peripheral driver support below.
+
+ This support is also available as a module. If you want to compile
+ it as a modules, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-algo-ite.o.
+
+ITE I2C Adapter
+CONFIG_ITE_I2C_ADAP
+ This supports the ITE8172 I2C peripheral found on some MIPS
+ systems. Say Y if you have one of these. You should also say Y for
+ the ITE I2C driver algorithm support above.
+
+ This support is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-adap-ite.o.
+
+I2C device interface
+CONFIG_I2C_CHARDEV
+ Say Y here to use i2c-* device files, usually found in the /dev
+ directory on your system. They make it possible to have user-space
+ programs use the I2C bus. Information on how to do this is
+ contained in the file <file:Documentation/i2c/dev-interface>.
+
+ This code is also available as a module. If you want to compile
+ it as a module, say M here and read
+ <file:Documentation/modules.txt>.
+ The module will be called i2c-dev.o.
+
+I2C /proc interface (required for hardware sensors)
+CONFIG_I2C_PROC
+ This provides support for i2c device entries in the /proc filesystem.
+ The entries will be found in /proc/sys/dev/sensors.
+
+ This code is also available as a module. If you want to compile
+ it as a module, say M here and read <file:Documentation/modules.txt>.
+ The module will be called i2c-proc.o.
+
+Bus Mouse Support
+CONFIG_BUSMOUSE
+ Say Y here if your machine has a bus mouse as opposed to a serial
+ mouse. Most people have a regular serial MouseSystem or
+ Microsoft mouse (made by Logitech) that plugs into a COM port
+ (rectangular with 9 or 25 pins). These people say N here.
+
+ If you have a laptop, you either have to check the documentation or
+ experiment a bit to find out whether the trackball is a serial mouse
+ or not; it's best to say Y here for you.
+
+ This is the generic bus mouse driver code. If you have a bus mouse,
+ you will have to say Y here and also to the specific driver for your
+ mouse below.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called busmouse.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Mouse Support (not serial and bus mice)
+CONFIG_MOUSE
+ This is for machines with a mouse which is neither a serial nor a
+ bus mouse. Examples are PS/2 mice (such as the track balls on some
+ laptops) and some digitizer pads. Most people have a regular serial
+ MouseSystem or Microsoft mouse (made by Logitech) that plugs into a
+ COM port (rectangular with 9 or 25 pins). These people say N here.
+ If you have something else, read the Busmouse-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>. This HOWTO contains
+ information about all non-serial mice, not just bus mice.
+
+ If you have a laptop, you either have to check the documentation or
+ experiment a bit to find out whether the trackball is a serial mouse
+ or not; it's best to say Y here for you.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about non-serial mice. If unsure, say Y.
+
+Logitech busmouse support
+CONFIG_LOGIBUSMOUSE
+ Logitech mouse connected to a proprietary interface card. It's
+ generally a round connector with 9 pins. Note that the newer mice
+ made by Logitech don't use the Logitech protocol anymore; for those,
+ you don't need this option. You want to read the Busmouse-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called busmouse.o. If you are unsure, say N and read the
+ HOWTO nevertheless: it will tell you what you have.
+
+PS/2 mouse (aka "auxiliary device") support
+CONFIG_PSMOUSE
+ The PS/2 mouse connects to a special mouse port that looks much like
+ the keyboard port (small circular connector with 6 pins). This way,
+ the mouse does not use any serial ports. This port can also be used
+ for other input devices like light pens, tablets, keypads. Compaq,
+ AST and IBM all use this as their mouse port on currently shipping
+ machines. The trackballs of some laptops are PS/2 mice also. In
+ particular, the C&T 82C710 mouse on TI Travelmates is a PS/2 mouse.
+
+ Although PS/2 mice are not technically bus mice, they are explained
+ in detail in the Busmouse-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ When using a PS/2 mouse, you can get problems if you want to use the
+ mouse both on the Linux console and under X. Using the "-R" option
+ of the Linux mouse managing program gpm (available from
+ <ftp://gnu.systemy.it/pub/gpm/>) solves this problem, or you can get
+ the "mconv2" utility from <ftp://ibiblio.org/pub/Linux/system/mouse/>.
+
+C&T 82C710 mouse port support (as on TI Travelmate)
+CONFIG_82C710_MOUSE
+ This is a certain kind of PS/2 mouse used on the TI Travelmate. If
+ you are unsure, try first to say N here and come back if the mouse
+ doesn't work. Read the Busmouse-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+PC110 digitizer pad support
+CONFIG_PC110_PAD
+ This drives the digitizer pad on the IBM PC110 palmtop. It can turn
+ the digitizer pad into a PS/2 mouse emulation with tap gestures or
+ into an absolute pad.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called pc110pad.o.
+
+Microsoft busmouse support
+CONFIG_MS_BUSMOUSE
+ These animals (also called Inport mice) are connected to an
+ expansion board using a round connector with 9 pins. If this is what
+ you have, say Y and read the Busmouse-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you are unsure, say N and read the HOWTO nevertheless: it will
+ tell you what you have. Also be aware that several vendors talk
+ about 'Microsoft busmouse' and actually mean PS/2 busmouse -- so
+ count the pins on the connector.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called msbusmouse.o.
+
+Apple Desktop Bus mouse support
+CONFIG_ADBMOUSE
+ Say Y here if you have this type of bus mouse (4 pin connector) as
+ is common on Macintoshes. You may want to read the Busmouse-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called adbmouse.o.
+
+ATIXL busmouse support
+CONFIG_ATIXL_BUSMOUSE
+ This is a rare type of busmouse that is connected to the back of an
+ ATI video card. Say Y if you have one of those. Note however that
+ most mice by ATI are actually Microsoft busmice; you should say Y to
+ "Microsoft busmouse support" above if you have one of those. Read
+ the Busmouse-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called atixlmouse.o.
+
+ If you are unsure, say N and read the HOWTO nevertheless: it will
+ tell you what you have.
+
+QIC-02 tape support
+CONFIG_QIC02_TAPE
+ If you have a non-SCSI tape drive like that, say Y. Or, if you want
+ to compile this driver as a module ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read <file:Documentation/modules.txt>. The module will be called
+ tpqic02.o.
+
+iSeries Virtual Tape Support
+CONFIG_VIOTAPE
+ If you are running Linux on an iSeries system and you want Linux
+ to read and/or write a tape drive owned by OS/400, say Y here.
+
+Do you want runtime configuration for QIC-02
+CONFIG_QIC02_DYNCONF
+ You can either configure this driver once and for all by editing a
+ header file (<file:include/linux/tpqic02.h>), in which case you
+ should say N, or you can fetch a program via anonymous FTP which is
+ able to configure this driver during runtime. The program to do
+ this is called 'qic02conf' and it is part of the
+ tpqic02-support-X.Y.tar.gz support package.
+
+ If you want to use the qic02conf program, say Y.
+
+Floppy tape drive (QIC-80/40/3010/3020/TR-1/TR-2/TR-3) support
+CONFIG_FTAPE
+ If you have a tape drive that is connected to your floppy
+ controller, say Y here.
+
+ Some tape drives (like the Seagate "Tape Store 3200" or the Iomega
+ "Ditto 3200" or the Exabyte "Eagle TR-3") come with a "high speed"
+ controller of their own. These drives (and their companion
+ controllers) are also supported if you say Y here.
+
+ If you have a special controller (such as the CMS FC-10, FC-20,
+ Mountain Mach-II, or any controller that is based on the Intel 82078
+ FDC like the high speed controllers by Seagate and Exabyte and
+ Iomega's "Ditto Dash") you must configure it by selecting the
+ appropriate entries from the "Floppy tape controllers" sub-menu
+ below and possibly modify the default values for the IRQ and DMA
+ channel and the IO base in ftape's configuration menu.
+
+ If you want to use your floppy tape drive on a PCI-bus based system,
+ please read the file <file:drivers/char/ftape/README.PCI>.
+
+ The ftape kernel driver is also available as a runtime loadable
+ module ( = code which can be inserted in and removed from the
+ running kernel whenever you want). If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. The
+ module will be called ftape.o.
+
+ Note that the Ftape-HOWTO is out of date (sorry) and documents the
+ older version 2.08 of this software but still contains useful
+ information. There is a web page with more recent documentation at
+ <http://www.instmath.rwth-aachen.de/~heine/ftape/>. This page
+ always contains the latest release of the ftape driver and useful
+ information (backup software, ftape related patches and
+ documentation, FAQ). Note that the file system interface has
+ changed quite a bit compared to previous versions of ftape. Please
+ read <file:Documentation/ftape.txt>.
+
+VFS interface for ftape
+CONFIG_ZFTAPE
+ Normally, you want to say Y or M. DON'T say N here or you
+ WON'T BE ABLE TO USE YOUR FLOPPY TAPE DRIVE.
+
+ The ftape module itself no longer contains the routines necessary
+ to interface with the kernel VFS layer (i.e. to actually write data
+ to and read data from the tape drive). Instead the file system
+ interface (i.e. the hardware independent part of the driver) has
+ been moved to a separate module.
+
+ If you say M zftape will be compiled as a runtime loadable
+ module ( = code which can be inserted in and removed from the
+ running kernel whenever you want). In this case you should read
+ <file:Documentation/modules.txt>. The module will be called
+ zftape.o.
+
+ Regardless of whether you say Y or M here, an additional runtime
+ loadable module called `zft-compressor.o' which contains code to
+ support user transparent on-the-fly compression based on Ross
+ William's lzrw3 algorithm will be produced. If you have enabled the
+ kernel module loader (i.e. have said Y to "Kernel module loader
+ support", above) then `zft-compressor.o' will be loaded
+ automatically by zftape when needed.
+
+ Despite its name, zftape does NOT use compression by default. The
+ file <file:Documentation/ftape.txt> contains a short description of
+ the most important changes in the file system interface compared to
+ previous versions of ftape. The ftape home page
+ <http://www.instmath.rwth-aachen.de/~heine/ftape/> contains
+ further information.
+
+ IMPORTANT NOTE: zftape can read archives created by previous
+ versions of ftape and provide file mark support (i.e. fast skipping
+ between tape archives) but previous version of ftape will lack file
+ mark support when reading archives produced by zftape.
+
+Default block size for zftape
+CONFIG_ZFT_DFLT_BLK_SZ
+ If unsure leave this at its default value, i.e. 10240. Note that
+ you specify only the default block size here. The block size can be
+ changed at run time using the MTSETBLK tape operation with the
+ MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the
+ shell command line).
+
+ The probably most striking difference between zftape and previous
+ versions of ftape is the fact that all data must be written or read
+ in multiples of a fixed block size. The block size defaults to
+ 10240 which is what GNU tar uses. The values for the block size
+ should be either 1 or multiples of 1024 up to a maximum value of
+ 63488 (i.e. 62 K). If you specify `1' then zftape's builtin
+ compression will be disabled.
+
+ Reasonable values are `10240' (GNU tar's default block size),
+ `5120' (afio's default block size), `32768' (default block size some
+ backup programs assume for SCSI tape drives) or `1' (no restriction
+ on block size, but disables builtin compression).
+
+Number of DMA buffers
+CONFIG_FT_NR_BUFFERS
+ Please leave this at `3' unless you REALLY know what you are doing.
+ It is not necessary to change this value. Values below 3 make the
+ proper use of ftape impossible, values greater than 3 are a waste of
+ memory. You can change the amount of DMA memory used by ftape at
+ runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer
+ wastes 32 KB of memory. Please note that this memory cannot be
+ swapped out.
+
+Enable procfs status report (+2kb)
+CONFIG_FT_PROC_FS
+ Optional. Saying Y will result in creation of a directory
+ `/proc/ftape' under the /proc file system. The files can be viewed
+ with your favorite pager (i.e. use "more /proc/ftape/history" or
+ "less /proc/ftape/history" or simply "cat /proc/ftape/history"). The
+ file will contain some status information about the inserted
+ cartridge, the kernel driver, your tape drive, the floppy disk
+ controller and the error history for the most recent use of the
+ kernel driver. Saying Y will enlarge the size of the ftape driver
+ by approximately 2 KB.
+
+ WARNING: When compiling ftape as a module (i.e. saying M to "Floppy
+ tape drive") it is dangerous to use ftape's /proc file system
+ interface. Accessing `/proc/ftape' while the module is unloaded will
+ result in a kernel Oops. This cannot be fixed from inside ftape.
+
+# Choice: ftdebug
+Controlling the amount of debugging output of ftape
+CONFIG_FT_NORMAL_DEBUG
+ This option controls the amount of debugging output the ftape driver
+ is ABLE to produce; it does not increase or diminish the debugging
+ level itself. If unsure, leave this at its default setting,
+ i.e. choose "Normal".
+
+ Ftape can print lots of debugging messages to the system console
+ resp. kernel log files. Reducing the amount of possible debugging
+ output reduces the size of the kernel module by some KB, so it might
+ be a good idea to use "None" for emergency boot floppies.
+
+ If you want to save memory then the following strategy is
+ recommended: leave this option at its default setting "Normal" until
+ you know that the driver works as expected, afterwards reconfigure
+ the kernel, this time specifying "Reduced" or "None" and recompile
+ and install the kernel as usual. Note that choosing "Excessive"
+ debugging output does not increase the amount of debugging output
+ printed to the console but only makes it possible to produce
+ "Excessive" debugging output.
+
+ Please read <file:Documentation/ftape.txt> for a short description
+ how to control the amount of debugging output.
+
+Excessive
+CONFIG_FT_FULL_DEBUG
+ Extremely verbose output for driver debugging purposes.
+
+Reduced
+CONFIG_FT_NO_TRACE
+ Reduced tape driver debugging output.
+
+None
+CONFIG_FT_NO_TRACE_AT_ALL
+ Suppress all debugging output from the tape drive.
+
+# Choice: ftcontroller
+The floppy drive controller for ftape
+CONFIG_FT_STD_FDC
+ Only change this setting if you have a special controller. If you
+ didn't plug any add-on card into your computer system but just
+ plugged the floppy tape cable into the already existing floppy drive
+ controller then you don't want to change the default setting,
+ i.e. choose "Standard".
+
+ Choose "MACH-2" if you have a Mountain Mach-2 controller.
+ Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20
+ controller.
+ Choose "Alt/82078" if you have another controller that is located at
+ an IO base address different from the standard floppy drive
+ controller's base address of `0x3f0', or uses an IRQ (interrupt)
+ channel different from `6', or a DMA channel different from
+ `2'. This is necessary for any controller card that is based on
+ Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high
+ speed" controllers.
+
+ If you choose something other than "Standard" then please make
+ sure that the settings for the IO base address and the IRQ and DMA
+ channel in the configuration menus below are correct. Use the manual
+ of your tape drive to determine the correct settings!
+
+ If you are already successfully using your tape drive with another
+ operating system then you definitely should use the same settings
+ for the IO base, the IRQ and DMA channel that have proven to work
+ with that other OS.
+
+ Note that this menu lets you specify only the default setting for
+ the hardware setup. The hardware configuration can be changed at
+ boot time (when ftape is compiled into the kernel, i.e. if you
+ have said Y to "Floppy tape drive") or module load time (i.e. if you
+ have said M to "Floppy tape drive").
+
+ Please read also the file <file:Documentation/ftape.txt> which
+ contains a short description of the parameters that can be set at
+ boot or load time. If you want to use your floppy tape drive on a
+ PCI-bus based system, please read the file
+ <file:drivers/char/ftape/README.PCI>.
+
+IO base for the floppy disk controller used with Ftape
+CONFIG_FT_FDC_BASE
+ You don't need to specify a value if the following default
+ settings for the base IO address are correct:
+ <<< MACH-2 : 0x1E0 >>>
+ <<< FC-10/FC-20: 0x180 >>>
+ <<< Secondary : 0x370 >>>
+ Secondary refers to a secondary FDC controller like the "high speed"
+ controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
+ Please make sure that the setting for the IO base address
+ specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
+ CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
+ successfully using the tape drive with another operating system then
+ you definitely should use the same settings for the IO base that has
+ proven to work with that other OS.
+
+ Note that this menu lets you specify only the default setting for
+ the IO base. The hardware configuration can be changed at boot time
+ (when ftape is compiled into the kernel, i.e. if you specified Y to
+ "Floppy tape drive") or module load time (i.e. if you have said M to
+ "Floppy tape drive").
+
+ Please read also the file <file:Documentation/ftape.txt> which
+ contains a short description of the parameters that can be set at
+ boot or load time.
+
+IRQ channel for the floppy disk controller used with Ftape
+CONFIG_FT_FDC_IRQ
+ You don't need to specify a value if the following default
+ settings for the interrupt channel are correct:
+ <<< MACH-2 : 6 >>>
+ <<< FC-10/FC-20: 9 >>>
+ <<< Secondary : 6 >>>
+ Secondary refers to secondary a FDC controller like the "high speed"
+ controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
+ Please make sure that the setting for the IO base address
+ specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
+ CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
+ successfully using the tape drive with another operating system then
+ you definitely should use the same settings for the IO base that has
+ proven to work with that other OS.
+
+ Note that this menu lets you specify only the default setting for
+ the IRQ channel. The hardware configuration can be changed at boot
+ time (when ftape is compiled into the kernel, i.e. if you said Y to
+ "Floppy tape drive") or module load time (i.e. if you said M to
+ "Floppy tape drive").
+
+ Please read also the file <file:Documentation/ftape.txt> which
+ contains a short description of the parameters that can be set at
+ boot or load time.
+
+DMA channel for the floppy disk controller used with Ftape
+CONFIG_FT_FDC_DMA
+ You don't need to specify a value if the following default
+ settings for the DMA channel are correct:
+ <<< MACH-2 : 2 >>>
+ <<< FC-10/FC-20: 3 >>>
+ <<< Secondary : 2 >>>
+ Secondary refers to a secondary FDC controller like the "high speed"
+ controllers delivered by Seagate or Exabyte or Iomega's Ditto Dash.
+ Please make sure that the setting for the IO base address
+ specified here is correct. USE THE MANUAL OF YOUR TAPE DRIVE OR
+ CONTROLLER CARD TO DETERMINE THE CORRECT SETTING. If you are already
+ successfully using the tape drive with another operating system then
+ you definitely should use the same settings for the IO base that has
+ proven to work with that other OS.
+
+ Note that this menu lets you specify only the default setting for
+ the DMA channel. The hardware configuration can be changed at boot
+ time (when ftape is compiled into the kernel, i.e. if you said Y to
+ "Floppy tape drive") or module load time (i.e. if you said M to
+ "Floppy tape drive").
+
+ Please read also the file <file:Documentation/ftape.txt> which
+ contains a short description of the parameters that can be set at
+ boot or load time.
+
+FDC FIFO Threshold before requesting DMA service
+CONFIG_FT_FDC_THR
+ Set the FIFO threshold of the FDC. If this is higher the DMA
+ controller may serve the FDC after a higher latency time. If this is
+ lower, fewer DMA transfers occur leading to less bus contention.
+ You may try to tune this if ftape annoys you with "reduced data
+ rate because of excessive overrun errors" messages. However, this
+ doesn't seem to have too much effect.
+
+ If unsure, don't touch the initial value, i.e. leave it at "8".
+
+FDC maximum data rate
+CONFIG_FT_FDC_MAX_RATE
+ With some motherboard/FDC combinations ftape will not be able to
+ run your FDC/tape drive combination at the highest available
+ speed. If this is the case you'll encounter "reduced data rate
+ because of excessive overrun errors" messages and lots of retries
+ before ftape finally decides to reduce the data rate.
+
+ In this case it might be desirable to tell ftape beforehand that
+ it need not try to run the tape drive at the highest available
+ speed. If unsure, leave this disabled, i.e. leave it at 2000
+ bits/sec.
+
+Direct Rendering Manager (XFree86 DRI support)
+CONFIG_DRM
+ Kernel-level support for the Direct Rendering Infrastructure (DRI)
+ introduced in XFree86 4.0. If you say Y here, you need to select
+ the module that's right for your graphics card from the list below.
+ These modules provide support for synchronization, security, and
+ DMA transfers. Please see <http://dri.sourceforge.net/> for more
+ details. You should also select and configure AGP
+ (/dev/agpgart) support.
+
+Build drivers for new (XFree 4.1) DRM
+CONFIG_DRM_NEW
+ If you set this option, the new DRM version needed by XFree86 4.1
+ will be used. Otherwise, the old DRM version will be used,
+ appropriate for XFree86 4.0.
+
+3dfx Banshee/Voodoo3+
+CONFIG_DRM_TDFX
+ Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
+ graphics card. If M is selected, the module will be called tdfx.o.
+
+3dlabs GMX 2000
+CONFIG_DRM_GAMMA
+ Choose this option if you have a 3dlabs GMX 2000 graphics card.
+ If M is selected, the module will be called gamma.o.
+
+ATI Rage 128
+CONFIG_DRM_R128
+ Choose this option if you have an ATI Rage 128 graphics card. If M
+ is selected, the module will be called r128.o. AGP support for
+ this card is strongly suggested (unless you have a PCI version).
+
+ATI Radeon
+CONFIG_DRM_RADEON
+ Choose this option if you have an ATI Radeon graphics card. There
+ are both PCI and AGP versions. You don't need to choose this to
+ run the Radeon in plain VGA mode. There is a product page at
+ <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
+ If M is selected, the module will be called radeon.o.
+
+Intel I810
+CONFIG_DRM_I810
+ Choose this option if you have an Intel I810 graphics card. If M is
+ selected, the module will be called i810.o. AGP support is required
+ for this driver to work.
+
+Matrox G200/G400/G450
+CONFIG_DRM_MGA
+ Choose this option if you have a Matrox G200, G400 or G450 graphics
+ card. If M is selected, the module will be called mga.o. AGP
+ support is required for this driver to work.
+
+3dfx Banshee/Voodoo3+
+CONFIG_DRM40_TDFX
+ Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
+ graphics card. If M is selected, the module will be called tdfx.o.
+
+3dlabs GMX 2000
+CONFIG_DRM40_GAMMA
+ Choose this option if you have a 3dlabs GMX 2000 graphics card.
+ If M is selected, the module will be called gamma.o.
+
+ATI Rage 128
+CONFIG_DRM40_R128
+ Choose this option if you have an ATI Rage 128 graphics card. If M
+ is selected, the module will be called r128.o. AGP support for
+ this card is strongly suggested (unless you have a PCI version).
+
+ATI Radeon
+CONFIG_DRM40_RADEON
+ Choose this option if you have an ATI Radeon graphics card. There
+ are both PCI and AGP versions. You don't need to choose this to
+ run the Radeon in plain VGA mode. There is a product page at
+ <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
+ If M is selected, the module will be called radeon.o.
+
+Intel I810
+CONFIG_DRM40_I810
+ Choose this option if you have an Intel I810 graphics card. If M is
+ selected, the module will be called i810.o. AGP support is required
+ for this driver to work.
+
+Matrox G200/G400/G450
+CONFIG_DRM40_MGA
+ Choose this option if you have a Matrox G200, G400 or G450 graphics
+ card. If M is selected, the module will be called mga.o. AGP
+ support is required for this driver to work.
+
+Creator/Creator3D/Elite3D
+CONFIG_DRM_FFB
+ Choose this option if you have one of Sun's Creator3D-based graphics
+ and frame buffer cards. Product page at
+ <http://www.sun.com/desktop/products/Graphics/creator3d.html>.
+
+MTRR (Memory Type Range Register) support
+CONFIG_MTRR
+ On Intel P6 family processors (Pentium Pro, Pentium II and later)
+ the Memory Type Range Registers (MTRRs) may be used to control
+ processor access to memory ranges. This is most useful if you have
+ a video (VGA) card on a PCI or AGP bus. Enabling write-combining
+ allows bus write transfers to be combined into a larger transfer
+ before bursting over the PCI/AGP bus. This can increase performance
+ of image write operations 2.5 times or more. Saying Y here creates a
+ /proc/mtrr file which may be used to manipulate your processor's
+ MTRRs. Typically the X server should use this.
+
+ This code has a reasonably generic interface so that similar
+ control registers on other processors can be easily supported
+ as well:
+
+ The Cyrix 6x86, 6x86MX and M II processors have Address Range
+ Registers (ARRs) which provide a similar functionality to MTRRs. For
+ these, the ARRs are used to emulate the MTRRs.
+ The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
+ MTRRs. The Centaur C6 (WinChip) has 8 MCRs, allowing
+ write-combining. All of these processors are supported by this code
+ and it makes sense to say Y here if you have one of them.
+
+ Saying Y here also fixes a problem with buggy SMP BIOSes which only
+ set the MTRRs for the boot CPU and not for the secondary CPUs. This
+ can lead to all sorts of problems, so it's good to say Y here.
+
+ You can safely say Y even if your machine doesn't have MTRRs, you'll
+ just add about 9 KB to your kernel.
+
+ See <file:Documentation/mtrr.txt> for more information.
+
+CPU clock frequency of your DEC Alpha
+CONFIG_FT_ALPHA_CLOCK
+ On some DEC Alpha machines the CPU clock frequency cannot be
+ determined automatically, so you need to specify it here ONLY if
+ running a DEC Alpha, otherwise this setting has no effect.
+
+Double Talk PC internal speech card support
+CONFIG_DTLK
+ This driver is for the DoubleTalk PC, a speech synthesizer
+ manufactured by RC Systems (<http://www.rcsys.com/>). It is also
+ called the `internal DoubleTalk'. If you want to compile this as a
+ module ( = code which can be inserted in and removed from the
+ running kernel whenever you want), say M here and read
+ <file:Documentation/modules.txt>. The module will be called dtlk.o.
+
+Siemens R3964 serial protocol support
+CONFIG_R3964
+ This driver allows synchronous communication with devices using the
+ Siemens R3964 packet protocol. Unless you are dealing with special
+ hardware like PLCs, you are unlikely to need this.
+
+ To compile this driver as a module ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read <file:Documentation/modules.txt>. The module will be called
+ n_r3964.o.
+
+ If unsure, say N.
+
+Applicom intelligent fieldbus card support
+CONFIG_APPLICOM
+ This driver provides the kernel-side support for the intelligent
+ fieldbus cards made by Applicom International. More information
+ about these cards can be found on the WWW at the address
+ <http://www.applicom-int.com/>, or by email from David Woodhouse
+ <dwmw2@infradead.org>.
+
+ To compile this driver as a module ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read <file:Documentation/modules.txt>. The module will be called
+ applicom.o.
+
+ If unsure, say N.
+
+Sony Vaio Programmable I/O Control Device support
+CONFIG_SONYPI
+ This driver enables access to the Sony Programmable I/O Control
+ Device which can be found in many (all ?) Sony Vaio laptops.
+
+ If you have one of those laptops, read
+ <file:Documentation/sonypi.txt>, and say Y or M here.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called sonypi.o.
+
+Intel Random Number Generator support
+CONFIG_INTEL_RNG
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Intel i8xx-based motherboards.
+
+ Both a character driver, used to read() entropy data, and a timer
+ function which automatically adds entropy directly into the
+ kernel pool, are exported by this driver.
+
+ To compile this driver as a module ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read <file:Documentation/modules.txt>. The module will be called
+ i810_rng.o.
+
+ If unsure, say N.
+
+Power Management support
+CONFIG_PM
+ "Power Management" means that parts of your computer are shut
+ off or put into a power conserving "sleep" mode if they are not
+ being used. There are two competing standards for doing this: APM
+ and ACPI. If you want to use either one, say Y here and then also
+ to the requisite support below.
+
+ Power Management is most important for battery powered laptop
+ computers; if you have a laptop, check out the Linux Laptop home
+ page on the WWW at
+ <http://www.cs.utexas.edu/users/kharker/linux-laptop/> and the
+ Battery Powered Linux mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that, even if you say N here, Linux on the x86 architecture
+ will issue the hlt instruction if nothing is to be done, thereby
+ sending the processor to sleep and saving power.
+
+ACPI support
+CONFIG_ACPI
+ ACPI/OSPM support for Linux is currently under development. As such,
+ this support is preliminary and EXPERIMENTAL. Configuring ACPI
+ support enables kernel interfaces that allow higher level software
+ (OSPM) to manipulate ACPI defined hardware and software interfaces,
+ including the evaluation of ACPI control methods. If unsure, choose
+ N here. Note, this option will enlarge your kernel by about 120K.
+
+ This support requires an ACPI compliant platform (hardware/firmware).
+ If both ACPI and Advanced Power Management (APM) support are
+ configured, whichever is loaded first shall be used.
+
+ This code DOES NOT currently provide a complete OSPM implementation
+ -- it has not yet reached APM's level of functionality. When fully
+ implemented, Linux ACPI/OSPM will provide a more robust functional
+ replacement for legacy configuration and power management
+ interfaces, including the Plug-and-Play BIOS specification (PnP
+ BIOS), the Multi-Processor Specification (MPS), and the Advanced
+ Power Management specification (APM).
+
+ Linux support for ACPI/OSPM is based on Intel Corporation's ACPI
+ Component Architecture (ACPI CA). The latest ACPI CA source code,
+ documentation, debug builds, and implementation status information
+ can be downloaded from:
+ <http://developer.intel.com/technology/iapc/acpi/downloads.htm>.
+
+ The ACPI Sourceforge project may also be of interest:
+ <http://sf.net/projects/acpi/>
+
+Enable ACPI 2.0 with errata 1.3
+CONFIG_ACPI20
+ Enable support for the 2.0 version of the ACPI interpreter. See the
+ help for ACPI for caveats and discussion.
+
+ACPI kernel configuration manager
+CONFIG_ACPI_KERNEL_CONFIG
+ If you say `Y' here, Linux's ACPI support will use the
+ hardware-level system descriptions found on IA64 machines.
+
+ACPI Debug Statements
+CONFIG_ACPI_DEBUG
+ The ACPI driver can optionally report errors with a great deal
+ of verbosity. Saying Y enables these statements. This will increase
+ your kernel size by around 50K.
+
+ACPI Bus Manager
+CONFIG_ACPI_BUSMGR
+ The ACPI Bus Manager enumerates devices in the ACPI namespace, and
+ handles PnP messages. All ACPI devices use its services, so using
+ them requires saying Y here.
+
+ACPI System Driver
+CONFIG_ACPI_SYS
+ This driver will enable your system to shut down using ACPI, and
+ dump your ACPI DSDT table using /proc/acpi/dsdt.
+
+ACPI Processor Driver
+CONFIG_ACPI_CPU
+ This driver installs ACPI as the idle handler for Linux, and uses
+ ACPI C2 and C3 processor states to save power, on systems that
+ support it.
+
+ACPI Button
+CONFIG_ACPI_BUTTON
+ This driver registers for events based on buttons, such as the
+ power, sleep, and lid switch. In the future, a daemon will read
+ /proc/acpi/event and perform user-defined actions such as shutting
+ down the system. Until then, you can cat it, and see output when
+ a button is pressed.
+
+ACPI AC Adapter
+CONFIG_ACPI_AC
+ This driver adds support for the AC Adapter object, which indicates
+ whether a system is on AC, or not. Typically, only laptops have
+ this object, since desktops are always on AC.
+
+ACPI Embedded Controller
+CONFIG_ACPI_EC
+ This driver is required on some systems for the proper operation of
+ the battery and thermal drivers. If you are compiling for a laptop,
+ say Y.
+
+ACPI Control Method Battery
+CONFIG_ACPI_CMBATT
+ This driver adds support for battery information through
+ /proc/acpi/battery. If you have a laptop with a battery, say Y.
+
+ACPI Thermal
+CONFIG_ACPI_THERMAL
+ This driver handles overheating conditions on laptops. It is HIGHLY
+ recommended, as your laptop CPU may be damaged without it.
+
+Advanced Power Management BIOS support
+CONFIG_APM
+ APM is a BIOS specification for saving power using several different
+ techniques. This is mostly useful for battery powered laptops with
+ APM compliant BIOSes. If you say Y here, the system time will be
+ reset after a RESUME operation, the /proc/apm device will provide
+ battery status information, and user-space programs will receive
+ notification of APM "events" (e.g. battery status change).
+
+ If you select "Y" here, you can disable actual use of the APM
+ BIOS by passing the "apm=off" option to the kernel at boot time.
+
+ Note that the APM support is almost completely disabled for
+ machines with more than one CPU.
+
+ In order to use APM, you will need supporting software. For location
+ and more information, read <file:Documentation/pm.txt> and the
+ Battery Powered Linux mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ This driver does not spin down disk drives (see the hdparm(8)
+ manpage ("man 8 hdparm") for that), and it doesn't turn off
+ VESA-compliant "green" monitors.
+
+ This driver does not support the TI 4000M TravelMate and the ACER
+ 486/DX4/75 because they don't have compliant BIOSes. Many "green"
+ desktop machines also don't have compliant BIOSes, and this driver
+ may cause those machines to panic during the boot phase.
+
+ Generally, if you don't have a battery in your machine, there isn't
+ much point in using this driver and you should say N. If you get
+ random kernel OOPSes or reboots that don't seem to be related to
+ anything, try disabling/enabling this option (or disabling/enabling
+ APM in your BIOS).
+
+ Some other things you should try when experiencing seemingly random,
+ "weird" problems:
+
+ 1) make sure that you have enough swap space and that it is
+ enabled.
+ 2) pass the "no-hlt" option to the kernel
+ 3) switch on floating point emulation in the kernel and pass
+ the "no387" option to the kernel
+ 4) pass the "floppy=nodma" option to the kernel
+ 5) pass the "mem=4M" option to the kernel (thereby disabling
+ all but the first 4 MB of RAM)
+ 6) make sure that the CPU is not over clocked.
+ 7) read the sig11 FAQ at <http://www.bitwizard.nl/sig11/>
+ 8) disable the cache from your BIOS settings
+ 9) install a fan for the video card or exchange video RAM
+ 10) install a better fan for the CPU
+ 11) exchange RAM chips
+ 12) exchange the motherboard.
+
+ To compile this driver as a module ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read <file:Documentation/modules.txt>. The module will be called
+ apm.o.
+
+Ignore USER SUSPEND
+CONFIG_APM_IGNORE_USER_SUSPEND
+ This option will ignore USER SUSPEND requests. On machines with a
+ compliant APM BIOS, you want to say N. However, on the NEC Versa M
+ series notebooks, it is necessary to say Y because of a BIOS bug.
+
+Enable APM at boot time
+CONFIG_APM_DO_ENABLE
+ Enable APM features at boot time. From page 36 of the APM BIOS
+ specification: "When disabled, the APM BIOS does not automatically
+ power manage devices, enter the Standby State, enter the Suspend
+ State, or take power saving steps in response to CPU Idle calls."
+ This driver will make CPU Idle calls when Linux is idle (unless this
+ feature is turned off -- see "Do CPU IDLE calls", below). This
+ should always save battery power, but more complicated APM features
+ will be dependent on your BIOS implementation. You may need to turn
+ this option off if your computer hangs at boot time when using APM
+ support, or if it beeps continuously instead of suspending. Turn
+ this off if you have a NEC UltraLite Versa 33/C or a Toshiba
+ T400CDT. This is off by default since most machines do fine without
+ this feature.
+
+Make CPU Idle calls when idle
+CONFIG_APM_CPU_IDLE
+ Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop.
+ On some machines, this can activate improved power savings, such as
+ a slowed CPU clock rate, when the machine is idle. These idle calls
+ are made after the idle loop has run for some length of time (e.g.,
+ 333 mS). On some machines, this will cause a hang at boot time or
+ whenever the CPU becomes idle. (On machines with more than one CPU,
+ this option does nothing.)
+
+Enable console blanking using APM
+CONFIG_APM_DISPLAY_BLANK
+ Enable console blanking using the APM. Some laptops can use this to
+ turn off the LCD backlight when the screen blanker of the Linux
+ virtual console blanks the screen. Note that this is only used by
+ the virtual console screen blanker, and won't turn off the backlight
+ when using the X Window system. This also doesn't have anything to
+ do with your VESA-compliant power-saving monitor. Further, this
+ option doesn't work for all laptops -- it might not turn off your
+ backlight at all, or it might print a lot of errors to the console,
+ especially if you are using gpm.
+
+RTC stores time in GMT
+CONFIG_APM_RTC_IS_GMT
+ Say Y here if your RTC (Real Time Clock a.k.a. hardware clock)
+ stores the time in GMT (Greenwich Mean Time). Say N if your RTC
+ stores localtime.
+
+ It is in fact recommended to store GMT in your RTC, because then you
+ don't have to worry about daylight savings time changes. The only
+ reason not to use GMT in your RTC is if you also run a broken OS
+ that doesn't understand GMT.
+
+Allow interrupts during APM BIOS calls
+CONFIG_APM_ALLOW_INTS
+ Normally we disable external interrupts while we are making calls to
+ the APM BIOS as a measure to lessen the effects of a badly behaving
+ BIOS implementation. The BIOS should reenable interrupts if it
+ needs to. Unfortunately, some BIOSes do not -- especially those in
+ many of the newer IBM Thinkpads. If you experience hangs when you
+ suspend, try setting this to Y. Otherwise, say N.
+
+Use real mode APM BIOS call to power off
+CONFIG_APM_REAL_MODE_POWER_OFF
+ Use real mode APM BIOS calls to switch off the computer. This is
+ a work-around for a number of buggy BIOSes. Switch this option on if
+ your computer crashes instead of powering off properly.
+
+Watchdog Timer Support
+CONFIG_WATCHDOG
+ If you say Y here (and to one of the following options) and create a
+ character special file /dev/watchdog with major number 10 and minor
+ number 130 using mknod ("man mknod"), you will get a watchdog, i.e.:
+ subsequently opening the file and then failing to write to it for
+ longer than 1 minute will result in rebooting the machine. This
+ could be useful for a networked machine that needs to come back
+ online as fast as possible after a lock-up. There's both a watchdog
+ implementation entirely in software (which can sometimes fail to
+ reboot the machine) and a driver for hardware watchdog boards, which
+ are more robust and can also keep track of the temperature inside
+ your computer. For details, read <file:Documentation/watchdog.txt>
+ in the kernel source.
+
+ The watchdog is usually used together with the watchdog daemon
+ which is available from
+ <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
+ also monitor NFS connections and can reboot the machine when the process
+ table is full.
+
+ If unsure, say N.
+
+Disable watchdog shutdown on close
+CONFIG_WATCHDOG_NOWAYOUT
+ The default watchdog behaviour (which you get if you say N here) is
+ to stop the timer if the process managing it closes the file
+ /dev/watchdog. It's always remotely possible that this process might
+ get killed. If you say Y here, the watchdog cannot be stopped once
+ it has been started.
+
+WDT Watchdog timer
+CONFIG_WDT
+ If you have a WDT500P or WDT501P watchdog board, say Y here,
+ otherwise N. It is not possible to probe for this board, which means
+ that you have to inform the kernel about the IO port and IRQ using
+ the "wdt=" kernel option (try "man bootparam" or see the
+ documentation of your boot loader (lilo or loadlin) about how to
+ pass options to the kernel at boot time).
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called wdt.o.
+
+WDT PCI Watchdog timer
+CONFIG_WDTPCI
+ If you have a PCI WDT500/501 watchdog board, say Y here, otherwise
+ N. It is not possible to probe for this board, which means that you
+ have to inform the kernel about the IO port and IRQ using the "wdt="
+ kernel option (try "man bootparam" or see the documentation of your
+ boot loader (lilo or loadlin) about how to pass options to the
+ kernel at boot time).
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called wdt_pci.o.
+
+WDT501 features
+CONFIG_WDT_501
+ Saying Y here and creating a character special file /dev/temperature
+ with major number 10 and minor number 131 ("man mknod") will give
+ you a thermometer inside your computer: reading from
+ /dev/temperature yields one byte, the temperature in degrees
+ Fahrenheit. This works only if you have a WDT501P watchdog board
+ installed.
+
+Fan Tachometer
+CONFIG_WDT_501_FAN
+ Enable the Fan Tachometer on the WDT501. Only do this if you have a
+ fan tachometer actually set up.
+
+Software Watchdog
+CONFIG_SOFT_WATCHDOG
+ A software monitoring watchdog. This will fail to reboot your system
+ from some situations that the hardware watchdog will recover
+ from. Equally it's a lot cheaper to install.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ softdog.o.
+
+Berkshire Products PC Watchdog
+CONFIG_PCWATCHDOG
+ This is the driver for the Berkshire Products PC Watchdog card.
+ This card simply watches your kernel to make sure it doesn't freeze,
+ and if it does, it reboots your computer after a certain amount of
+ time. This driver is like the WDT501 driver but for different
+ hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC
+ watchdog cards can be ordered from <http://www.berkprod.com/>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called pcwd.o. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ Most people will say N.
+
+Acquire SBC Watchdog Timer
+CONFIG_ACQUIRE_WDT
+ This is the driver for the hardware watchdog on the PSC-6x86 Single
+ Board Computer produced by Acquire Inc (and others). This watchdog
+ simply watches your kernel to make sure it doesn't freeze, and if
+ it does, it reboots your computer after a certain amount of time.
+
+ This driver is like the WDT501 driver but for different hardware.
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called pscwdt.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. Most
+ people will say N.
+
+Advantech SBC Watchdog Timer
+CONFIG_ADVANTECH_WDT
+ If you are configuring a Linux kernel for the Advantech single-board
+ computer, say `Y' here to support its built-in watchdog timer
+ feature. See the help for CONFIG_WATCHDOG for discussion.
+
+ALi M7101 Watchdog Timer
+CONFIG_ALIM7101_WDT
+ This is the driver for the hardware watchdog on the ALi M7101 PMU
+ as used in the x86 Cobalt servers.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called alim7101_wdt.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. Most
+ people will say N.
+
+IB700 SBC Watchdog Timer
+CONFIG_IB700_WDT
+ This is the driver for the hardware watchdog on the IB700 Single
+ Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog
+ simply watches your kernel to make sure it doesn't freeze, and if
+ it does, it reboots your computer after a certain amount of time.
+
+ This driver is like the WDT501 driver but for slightly different hardware.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called ib700wdt.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt. Most people
+ will say N.
+
+Mixcom Watchdog
+CONFIG_MIXCOMWD
+ This is a driver for the Mixcom hardware watchdog cards. This
+ watchdog simply watches your kernel to make sure it doesn't freeze,
+ and if it does, it reboots your computer after a certain amount of
+ time.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called mixcomwd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. Most
+ people will say N.
+
+ZF MachZ Watchdog
+CONFIG_MACHZ_WDT
+ If you are using a ZF Micro MachZ processor, say Y here, otherwise
+ N. This is the driver for the watchdog timer builtin on that
+ processor using ZF-Logic interface. This watchdog simply watches
+ your kernel to make sure it doesn't freeze, and if it does, it
+ reboots your computer after a certain amount of time.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called machzwd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_SC1200_WDT
+ This is a driver for National Semiconductor PC87307/PC97307 hardware
+ watchdog cards as found on the SC1200. This watchdog is mainly used
+ for power management purposes and can be used to power down the device
+ during inactivity periods (includes interrupt activity monitoring).
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called sc1200wdt.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>. Most
+ people will say N.
+
+SuperH Watchdog
+CONFIG_SH_WDT
+ This driver adds watchdog support for the integrated watchdog in the
+ SuperH 3, 4 and 5 processors. If you have one of these processors, say
+ Y, otherwise say N.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called shwdt.o. If you want to compile it as a module,
+ say M here and read Documentation/modules.txt.
+
+Wafer 5823 Watchdog
+CONFIG_WAFER_WDT
+ This is a driver for the hardware watchdog on the ICP Wafer 5823
+ Single Board Computer (and probably other similar models).
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ wafer5823wdt.o
+
+Machine Check Exception
+CONFIG_X86_MCE
+ Machine Check Exception support allows the processor to notify the
+ kernel if it detects a problem (e.g. overheating, component failure).
+ The action the kernel takes depends on the severity of the problem,
+ ranging from a warning message on the console, to halting the machine.
+ You can safely select this on machines that do not support this feature.
+
+ For pentium machines the mce support defaults to off as the mainboard
+ support is not always present. You must activate it as a boot option.
+
+Toshiba Laptop support
+CONFIG_TOSHIBA
+ This adds a driver to safely access the System Management Mode of
+ the CPU on Toshiba portables with a genuine Toshiba BIOS. It does
+ not work on models with a Phoenix BIOS. The System Management Mode
+ is used to set the BIOS and power saving options on Toshiba portables.
+
+ For information on utilities to make use of this driver see the
+ Toshiba Linux utilities web site at:
+ <http://www.buzzard.org.uk/toshiba/>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ toshiba.o
+
+ Say Y if you intend to run this kernel on a Toshiba portable.
+ Say N otherwise.
+
+Dell laptop support
+CONFIG_I8K
+ This adds a driver to safely access the System Management Mode
+ of the CPU on the Dell Inspiron and Latitude laptops. The System
+ Management Mode is used to read cpu temperature, cooling fan
+ status and Fn-keys status on Dell laptops. It can also be used
+ to switch the fans on and off.
+
+ The driver has been developed and tested on an Inspiron 8000
+ but it should work on any Dell Inspiron or Latitude laptop.
+ You can force loading on unsupported models by passing the
+ parameter `force=1' to the module. Use at your own risk.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ i8k.o
+
+ For more information on this driver and for utilities that make
+ use of the module see the I8K Linux Utilities web site at:
+ <http://www.debian.org/~dz/i8k/>.
+
+ Say Y if you intend to run this kernel on a Dell laptop.
+ Say N otherwise.
+
+/dev/cpu/microcode - Intel IA32 CPU microcode support
+CONFIG_MICROCODE
+ If you say Y here and also to "/dev file system support" in the
+ 'File systems' section, you will be able to update the microcode on
+ Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II,
+ Pentium III, Pentium 4, Xeon etc. You will obviously need the
+ actual microcode binary data itself which is not shipped with the
+ Linux kernel.
+
+ For latest news and information on obtaining all the required
+ ingredients for this driver, check:
+ <http://www.urbanmyth.org/microcode/>.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called microcode.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ you use modprobe or kmod you may also want to add the line
+ 'alias char-major-10-184 microcode' to your /etc/modules.conf file.
+
+/dev/cpu/*/msr - Model-specific register support
CONFIG_X86_MSR
This device gives privileged processes access to the x86
Model-Specific Registers (MSRs). It is a character device with
@@ -5380,8 +19295,8 @@ CONFIG_60XX_WDT
Eurotech CPU-1220/1410 Watchdog Timer
CONFIG_EUROTECH_WDT
- Enable support for the watchdog timer on the Eurotech CPU-1220 and
- CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product
+ Enable support for the watchdog timer on the Eurotech CPU-1220 and
+ CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product
information are at <http://www.eurotech.it/>.
W83877F Watchdog Timer
@@ -6509,7 +20424,7 @@ CONFIG_SOUND_CMPCI_SPDIFLOOP
A userspace utility to control even more internal registers of these
chips is available at
<http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
- This package will among other things help you enable SPDIF
+ This package will among other things help you enable SPDIF
out/in/loop/monitor.
Enable legacy FM
@@ -6725,7 +20640,7 @@ CONFIG_SOUND_GUSMAX
Intel ICH audio support
CONFIG_SOUND_ICH
Supports the following chipsets:
-
+
Intel ICH 82801AA
Intel ICH 82901AB
Intel 440 MX
@@ -6734,9 +20649,9 @@ CONFIG_SOUND_ICH
SiS 7012
NVidia nForce
AMD 768
-
+
These are audio drivers for integral audio in chipsets of motherboards.
-
+
Intel's I/O Controller Hub (ICH) is used on 810/815/820/840/845/845D/850 motherboards.
SiS 7012 is used on 645/735/745 motherboards.
@@ -6773,7 +20688,7 @@ CONFIG_SOUND_YMFPCI_LEGACY
RME Hammerfall (RME96XX) support
CONFIG_SOUND_RME96XX
- Say Y or M if you have a Hammerfall or Hammerfall light multichannel card
+ Say Y or M if you have a Hammerfall or Hammerfall light multichannel card
from RME. If you want to acess advanced features of the card, read
Documentation/sound/rme96xx.
@@ -6879,6 +20794,13 @@ CONFIG_LL_DEBUG
Currently used only by the time services code in the MIPS port.
Don't turn this on unless you know what you are doing.
+Enable run-time debugging
+CONFIG_DEBUG
+ If you say Y here, some debugging macros will do run-time checking.
+ If you say N here, those macros will mostly turn to no-ops. For
+ MIPS boards only. See include/asm-mips/debug.h for debuging macros.
+ If unsure, say N.
+
Remote GDB kernel debugging
CONFIG_REMOTE_DEBUG
If you say Y here, it will be possible to remotely debug the MIPS
@@ -7334,7 +21256,7 @@ CONFIG_HISAX_AMD7930
HiSax debugging
CONFIG_HISAX_DEBUG
This enables debugging code in the new-style HiSax drivers, i.e.
- the ST5481 USB driver currently.
+ the ST5481 USB driver currently.
If in doubt, say yes.
ELSA PCMCIA MicroLink cards
@@ -7778,8 +21700,8 @@ CONFIG_PARPORT_SUNBPP
SPARC power management support
CONFIG_SUN_PM
- Enable power management and CPU standby features on supported
- SPARC platforms.
+ Enable power management and CPU standby features on supported
+ SPARC platforms.
/proc/hardware support
CONFIG_PROC_HARDWARE
@@ -7835,7 +21757,7 @@ CONFIG_BLUEZ_BNEP
emulation layer on top of Bluetooth. BNEP is required for Bluetooth
PAN (Personal Area Network).
- To use BNEP, you will need user-space utilities provided in the
+ To use BNEP, you will need user-space utilities provided in the
BlueZ-PAN package.
For more information, see <http://bluez.sourceforge.net>.
@@ -7846,18 +21768,18 @@ HCI UART driver
CONFIG_BLUEZ_HCIUART
Bluetooth HCI UART driver.
This driver is required if you want to use Bluetooth devices with
- serial port interface. You will also need this driver if you have
- UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card
+ serial port interface. You will also need this driver if you have
+ UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card
adapter and BrainBoxes Bluetooth PC Card.
Say Y here to compile support for Bluetooth UART devices into the
kernel or say M to compile it as module (hci_uart.o).
-HCI UART (H4) protocol support
+HCI UART (H4) protocol support
CONFIG_BLUEZ_HCIUART_H4
- UART (H4) is serial protocol for communication between Bluetooth
- device and host. This protocol is required for most UART based
- Bluetooth device (including PCMCIA and CF).
+ UART (H4) is serial protocol for communication between Bluetooth
+ device and host. This protocol is required for most UART based
+ Bluetooth device (including PCMCIA and CF).
Say Y here to compile support for HCI UART (H4) protocol.
@@ -7873,8 +21795,8 @@ CONFIG_BLUEZ_HCIUSB
HCI USB zero packet support
CONFIG_BLUEZ_USB_ZERO_PACKET
Support for USB zero packets.
- This option is provided only as a work around for buggy Bluetooth USB
- devices. Do _not_ enable it unless you know for sure that your device
+ This option is provided only as a work around for buggy Bluetooth USB
+ devices. Do _not_ enable it unless you know for sure that your device
requires zero packets.
Most people should say N here.
@@ -7944,7 +21866,7 @@ CompactFlash Connection Area
CONFIG_CF_AREA5
If your board has "Directly Connected" CompactFlash, You should
select the area where your CF is connected to.
-
+
- "Area5" if CompactFlash is connected to Area 5 (0x14000000)
- "Area6" if it is connected to Area 6 (0x18000000)
@@ -8035,11 +21957,11 @@ CONFIG_BLK_DEV_Q40IDE
Sun 3 support
CONFIG_SUN3
This option enables support for the Sun 3 series of workstations.
- Note that if this option is enabled, support for all other m68k
- platforms above must be disabled in order to produce a working
+ Note that if this option is enabled, support for all other m68k
+ platforms above must be disabled in order to produce a working
kernel.
- Also, you will want to enable 68020 support below, and disable
+ Also, you will want to enable 68020 support below, and disable
all other CPU types. General Linux information on the Sun 3x series
(now discontinued) is at
<http://www.angelfire.com/ca2/tech68k/sun3.html>.
@@ -8050,7 +21972,7 @@ Sun 3X support
CONFIG_SUN3X
This option enables support for the Sun 3x series of workstations.
Currently, only the Sun 3/80 is supported within the Sun 3x family.
- You will also want to enable 68030 support below
+ You will also want to enable 68030 support below
General Linux information on the Sun 3x series (now discontinued)
is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
@@ -8862,10 +22784,10 @@ CONFIG_RPXLITE
Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
RPX-Classic:
- Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on
+ Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on
the MPC 860
- BSE-IP:
+ BSE-IP:
Bright Star Engineering ip-Engine.
TQM823L:
@@ -8907,7 +22829,7 @@ CONFIG_RPXLITE
URL: <http://www.speech-design.de/>
IVML24:
- MPC860 based board used in the "Integrated Voice Mail System",
+ MPC860 based board used in the "Integrated Voice Mail System",
Large Version (24 voice channels)
Manufacturer: Speech Design, <http://www.speech-design.de/>
Date of Release: March 2001 (?)
@@ -8929,7 +22851,7 @@ CONFIG_RPXLITE
End of life: -
URL: <http://www.multidata.de/english/products/hpro.htm>
- IP860:
+ IP860:
VMEBus IP (Industry Pack) carrier board with MPC860
Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
Date of Release: ?
@@ -9004,7 +22926,7 @@ CONFIG_FPS850
TQM860
CONFIG_TQM860
Say Y here to support the TQM860, one of an MPC8xx-based family of
- SBCs (credit-card size) from TQ Components first released in
+ SBCs (credit-card size) from TQ Components first released in
mid-1999 and discontinued mid-2000.
SM850
@@ -9564,7 +23486,7 @@ CONFIG_RADIO_GEMTEK_PCI
Choose Y here if you have this PCI FM radio card.
In order to control your radio card, you will need to use programs
- that are compatible with the Video for Linux API. Information on
+ that are compatible with the Video for Linux API. Information on
this API and pointers to "v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
@@ -9810,7 +23732,7 @@ CONFIG_IPL_TAPE
IPL from a virtual card reader emulated by VM/ESA
CONFIG_IPL_VM
- Select this option if you are running under VM/ESA and want
+ Select this option if you are running under VM/ESA and want
to IPL the image from the emulated card reader.
CONFIG_PFAULT
@@ -9834,7 +23756,7 @@ Support for IBM-style disk-labels (S/390)
CONFIG_S390_PARTITION
Enable this option to assure standard IBM labels on the DASDs.
You must enable it, if you are planning to access DASDs also
- attached to another IBM mainframe operation system (OS/390,
+ attached to another IBM mainframe operation system (OS/390,
VM/ESA, VSE/ESA).
Support for DASD hard disks
@@ -9845,13 +23767,13 @@ CONFIG_DASD
Support for ECKD hard disks
CONFIG_DASD_ECKD
- ECKD (Extended Count Key Data) devices are the most commonly used
- devices on S/390s. You should enable this option unless you are
+ ECKD (Extended Count Key Data) devices are the most commonly used
+ devices on S/390s. You should enable this option unless you are
very sure you have no ECKD device.
ECKD demand loading
CONFIG_DASD_AUTO_ECKD
- This option enables demand loading of the ECKD module.
+ This option enables demand loading of the ECKD module.
Support for FBA hard disks
CONFIG_DASD_FBA
@@ -9860,7 +23782,7 @@ CONFIG_DASD_FBA
FBA demand loading
CONFIG_DASD_AUTO_FBA
- This option enables demand loading of the FBA module.
+ This option enables demand loading of the FBA module.
Support for DIAG access to CMS reserved Disks
CONFIG_DASD_DIAG
@@ -9870,7 +23792,7 @@ CONFIG_DASD_DIAG
DIAG demand loading
CONFIG_DASD_AUTO_DIAG
- This option enables demand loading of the DIAG module.
+ This option enables demand loading of the DIAG module.
Merge some code into the kernel to make the image IPLable
CONFIG_IPLABLE
@@ -10000,8 +23922,8 @@ CONFIG_IUCV
Process warning machine checks
CONFIG_MACHCHK_WARNING
- Select this option if you want the machine check handler on IBM S/390 or
- zSeries to process warning machine checks (e.g. on power failures).
+ Select this option if you want the machine check handler on IBM S/390 or
+ zSeries to process warning machine checks (e.g. on power failures).
If unsure, say "Y".
Use chscs for Common I/O
@@ -10891,7 +24813,7 @@ CONFIG_USB_STORAGE_HP8200e
you use this driver. If in doubt, select N.
Lexar Jumpshot Compact Flash Reader
-CONFIG_USB_STORAGE_JUMPSHOT
+CONFIG_USB_STORAGE_JUMPSHOT
This option enables a sub-driver of the USB Mass Storage driver. These
sub-drivers are considered experimental, and should only be used by very
brave people. System crashes and other bad things are likely to occur if
@@ -10923,12 +24845,12 @@ CONFIG_NS83820
This is a driver for the National Semiconductor DP83820 series
of gigabit ethernet MACs. Cards using this chipset include:
- SMC 9452TX SMC SMC9462TX
+ SMC 9452TX SMC SMC9462TX
D-Link DGE-500T PureData PDP8023Z-TG
SOHO-GA2000T SOHO-GA2500T.
NetGear GA621
- This driver supports the use of zero copy on tx, checksum
+ This driver supports the use of zero copy on tx, checksum
validation on rx, and 64 bit addressing.
If you want to compile the driver as a module ( = code which can be
@@ -11073,7 +24995,7 @@ CONFIG_OLD_BELKIN_DONGLE
and read <file:Documentation/modules.txt>. The module will be
called old_belkin.o. Some information is contained in the comments
at the top of <file:drivers/net/irda/old_belkin.c>.
-
+
ACTiSYS IR-200L dongle (Experimental)
CONFIG_ACT200L_DONGLE
Say Y here if you want to build support for the ACTiSYS IR-200L
@@ -12425,7 +26347,7 @@ Physical memory start address
CONFIG_MEMORY_START
Computers built with Hitachi SuperH processors always
map the ROM starting at address zero. But the processor
- does not specify the range that RAM takes.
+ does not specify the range that RAM takes.
The physical memory (RAM) start address will be automatically
set to 08000000, unless you selected one of the following
@@ -12485,7 +26407,7 @@ CONFIG_HD64465_IOBASE
The default setting of the HD64465 IO base address is 0xb0000000.
Do not change this unless you know what you are doing.
-
+
Early printk support
CONFIG_SH_EARLY_PRINTK
Say Y here to redirect kernel printk messages to the serial port
@@ -12756,7 +26678,7 @@ CONFIG_SERIAL_SGI_L1_PROTOCOL
SGI SN (Scalable NUMA) platform for IA64. If you are compiling for
an SGI SN box then Y is the recommended value, otherwise say N.
-New bus configuration (EXPERIMENTAL)
+New bus configuration (EXPERIMENTAL)
CONFIG_TULIP_MWI
This configures your Tulip card specifically for the card and
system cache line size type you are using.
@@ -12765,6 +26687,26 @@ CONFIG_TULIP_MWI
If unsure, say N.
+CONFIG_IP_NF_MATCH_LAYER7
+ Say Y if you want to be able to classify connections (and their
+ packets) based on regular expression matching of their application
+ layer data. This is one way to classify applications such as
+ peer-to-peer filesharing systems that do not always use the same
+ port.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+CONFIG_IP_NF_MATCH_LAYER7_DEBUG
+ Say Y to get lots of debugging output.
+
+RTSP protocol support
+CONFIG_IP_NF_RTSP
+ Support the RTSP protocol. This allows UDP transports to be setup
+ properly, including RTP and RDT.
+
+ If you want to compile it as a module, say 'M' here and read
+ Documentation/modules.txt. If unsure, say 'Y'.
+
#
# A couple of things I keep forgetting:
# capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
diff --git a/release/src/linux/linux/Documentation/filesystems/00-INDEX b/release/src/linux/linux/Documentation/filesystems/00-INDEX
index 7ce02316..15abefcb 100644
--- a/release/src/linux/linux/Documentation/filesystems/00-INDEX
+++ b/release/src/linux/linux/Documentation/filesystems/00-INDEX
@@ -10,6 +10,8 @@ befs.txt
- info for the BeOS file system (BFS)
bfs.txt
- info for the SCO UnixWare Boot Filesystem (BFS).
+cifs.txt
+ - info on the Common Internet File System (CIFS)
coda.txt
- description of the CODA filesystem.
cramfs.txt
diff --git a/release/src/linux/linux/Documentation/filesystems/cifs.txt b/release/src/linux/linux/Documentation/filesystems/cifs.txt
new file mode 100644
index 00000000..49cc923a
--- /dev/null
+++ b/release/src/linux/linux/Documentation/filesystems/cifs.txt
@@ -0,0 +1,51 @@
+ This is the client VFS module for the Common Internet File System
+ (CIFS) protocol which is the successor to the Server Message Block
+ (SMB) protocol, the native file sharing mechanism for most early
+ PC operating systems. CIFS is fully supported by current network
+ file servers such as Windows 2000, Windows 2003 (including
+ Windows XP) as well by Samba (which provides excellent CIFS
+ server support for Linux and many other operating systems), so
+ this network filesystem client can mount to a wide variety of
+ servers. The smbfs module should be used instead of this cifs module
+ for mounting to older SMB servers such as OS/2. The smbfs and cifs
+ modules can coexist and do not conflict. The CIFS VFS filesystem
+ module is designed to work well with servers that implement the
+ newer versions (dialects) of the SMB/CIFS protocol such as Samba,
+ the program written by Andrew Tridgell that turns any Unix host
+ into a SMB/CIFS file server.
+
+ The intent of this module is to provide the most advanced network
+ file system function for CIFS compliant servers, including better
+ POSIX compliance, secure per-user session establishment, high
+ performance safe distributed caching (oplock), optional packet
+ signing, large files, Unicode support and other internationalization
+ improvements. Since both Samba server and this filesystem client support
+ the CIFS Unix extensions, the combination can provide a reasonable
+ alternative to NFSv4 for fileserving in some Linux to Linux environments,
+ not just in Linux to Windows environments.
+
+ This filesystem has an optional mount utility (mount.cifs) that can
+ be obtained from the project page and installed in the path in the same
+ directory with the other mount helpers (such as mount.smbfs).
+ Mounting using the cifs filesystem without installing the mount helper
+ requires specifying the server's ip address.
+
+ For Linux 2.4:
+ mount //anything/here /mnt_target -o
+ user=username,pass=password,unc=//ip_address_of_server/sharename
+
+ For Linux 2.5:
+ mount //ip_address_of_server/sharename /mnt_target -o user=username, pass=password
+
+
+ For more information on the module see the project page at
+
+ http://us1.samba.org/samba/Linux_CIFS_client.html
+
+ For more information on CIFS see:
+
+ http://www.snia.org/tech_activities/CIFS
+
+ or the Samba site:
+
+ http://www.samba.org
diff --git a/release/src/linux/linux/Makefile b/release/src/linux/linux/Makefile
index b378a3ff..beb7b184 100644
--- a/release/src/linux/linux/Makefile
+++ b/release/src/linux/linux/Makefile
@@ -236,7 +236,9 @@ CLEAN_FILES = \
drivers/tc/lk201-map.c \
net/khttpd/make_times_h \
net/khttpd/times.h \
- submenu*
+ submenu* \
+ drivers/net/hnd/shared_ksyms.c
+
# directories removed with 'make clean'
CLEAN_DIRS = \
modules
@@ -460,7 +462,7 @@ modules modules_install: dummy
endif
clean: archclean
- find . \( -name '*.[oas]' -o -name core -o -name '.*.flags' \) -type f -print \
+ find . \( -name '*.[oas]' -o -name core -o -name '.*.flags' \) -type f -not -name diag_led.o -not -name ctmisc.o -print \
| grep -v lxdialog/ | xargs rm -f
rm -f $(CLEAN_FILES)
rm -rf $(CLEAN_DIRS)
diff --git a/release/src/linux/linux/arch/mips/Makefile b/release/src/linux/linux/arch/mips/Makefile
index fb3caa33..34111451 100644
--- a/release/src/linux/linux/arch/mips/Makefile
+++ b/release/src/linux/linux/arch/mips/Makefile
@@ -636,10 +636,12 @@ archclean:
$(MAKE) -C arch/$(ARCH)/tools clean
$(MAKE) -C arch/mips/baget clean
$(MAKE) -C arch/mips/lasat clean
+ $(MAKE) -C arch/mips/brcm-boards/bcm947xx/compressed clean
archmrproper:
@$(MAKEBOOT) mrproper
$(MAKE) -C arch/$(ARCH)/tools mrproper
+ $(MAKE) -C arch/mips/brcm-boards/bcm947xx/compressed mrproper
archdep:
if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \
diff --git a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c
new file mode 100644
index 00000000..706dfbf1
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c
@@ -0,0 +1,41 @@
+/*
+ * Early initialization code for BCM94710 boards
+ *
+ * Copyright 2006, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id$
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/bootinfo.h>
+
+void __init
+prom_init(int argc, const char **argv)
+{
+ unsigned long mem;
+
+ mips_machgroup = MACH_GROUP_BRCM;
+ mips_machtype = MACH_BCM947XX;
+
+ /* Figure out memory size by finding aliases */
+ for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
+ if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
+ *(unsigned long *)(prom_init))
+ break;
+ }
+ add_memory_region(0, mem, BOOT_MEM_RAM);
+}
+
+void __init
+prom_free_prom_memory(void)
+{
+}
diff --git a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c
index 242dafb9..cb35926d 100644
--- a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c
+++ b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c
@@ -1,7 +1,7 @@
/*
* Early initialization code for BCM94710 boards
*
- * Copyright 2005, Broadcom Corporation
+ * Copyright 2006, Broadcom Corporation
* All Rights Reserved.
*
* THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
@@ -9,7 +9,7 @@
* SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
*
- * $Id: prom.c,v 1.1.1.7 2005/03/07 07:30:37 kanki Exp $
+ * $Id$
*/
#include <linux/config.h>
@@ -18,24 +18,39 @@
#include <linux/types.h>
#include <asm/bootinfo.h>
-void __init
-prom_init(int argc, const char **argv)
+void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
{
- unsigned long mem;
+ unsigned long mem, before, offset;
- mips_machgroup = MACH_GROUP_BRCM;
- mips_machtype = MACH_BCM947XX;
+ mips_machgroup = MACH_GROUP_BRCM;
+ mips_machtype = MACH_BCM947XX;
- /* Figure out memory size by finding aliases */
- for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
- if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
- *(unsigned long *)(prom_init))
+ /* Figure out memory size by finding aliases.
+ *
+ * We assume that there will be no more than 128 MB of memory,
+ * and that the memory size will be a multiple of 1 MB.
+ *
+ * We set 'before' to be the amount of memory (in MB) before this
+ * function, i.e. one MB less than the number of MB of memory that we
+ * *know* we have. And we set 'offset' to be the address of 'prominit'
+ * minus 'before', so that KSEG0 or KSEG1 base + offset < 1 MB.
+ * This prevents us from overrunning 128 MB and causing a bus error.
+ */
+ before = ((unsigned long) &prom_init) & (127 << 20);
+ offset = ((unsigned long) &prom_init) - before;
+ for (mem = before + (1 << 20); mem < (128 << 20); mem += (1 << 20))
+ if (*(unsigned long *)(offset + mem) ==
+ *(unsigned long *)(prom_init)) {
+ /*
+ * We may already be well past the end of memory at
+ * this point, so we'll have to compensate for it.
+ */
+ mem -= before;
break;
- }
+ }
add_memory_region(0, mem, BOOT_MEM_RAM);
}
-void __init
-prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
{
}
diff --git a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/setup.c b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/setup.c
index c4983dc2..dc55be85 100644
--- a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/setup.c
+++ b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/setup.c
@@ -3,7 +3,7 @@
*
* Copyright 2005, Broadcom Corporation
* All Rights Reserved.
- *
+ *
* THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
* KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
* SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
@@ -38,8 +38,6 @@
#include <sbutils.h>
#include <trxhdr.h>
-#include <cy_conf.h>
-
extern void bcm947xx_time_init(void);
extern void bcm947xx_timer_setup(struct irqaction *irq);
@@ -53,9 +51,6 @@ extern void breakpoint(void);
extern struct ide_ops std_ide_ops;
#endif
-#ifdef MULTILANG_SUPPORT
-#endif
-
/* Global SB handle */
void *bcm947xx_sbh = NULL;
spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED;
@@ -139,9 +134,9 @@ brcm_setup(void)
/* Initialize clocks and interrupts */
sb_mips_init(sbh);
- /*
- * Now that the sbh is inited set the proper PFC value
- */
+ /*
+ * Now that the sbh is inited set the proper PFC value
+ */
pfc_val = sb_mips_get_pfc(sbh);
printk("Setting the PFC value as 0x%x\n", pfc_val);
check_enable_mips_pfc(pfc_val);
@@ -184,197 +179,97 @@ bus_error_init(void)
#ifdef CONFIG_MTD_PARTITIONS
+
+/*
+ new layout -- zzz 04/2006
+
+ +--------------+
+ | boot |
+ +---+----------+ < search for HDR0
+ | | |
+ | | (kernel) |
+ | l | |
+ | i +----------+ < + trx->offset[1]
+ | n | |
+ | u | rootfs |
+ | x | |
+ + +----------+ < + trx->len
+ | | jffs2 |
+ +--------------+ < size - NVRAM_SPACE
+ | nvram |
+ +--------------+ < size
+*/
+
static struct mtd_partition bcm947xx_parts[] = {
- //{ name: "pmon", offset: 0, size: 0, /*mask_flags: MTD_WRITEABLE,*/ },
- { name: "boot", offset: 0, size: 0, /*mask_flags: MTD_WRITEABLE,*/ },
- { name: "linux", offset: 0, size: 0, },
- { name: "rootfs", offset: 0, size: 0, /*mask_flags: MTD_WRITEABLE,*/ },
-#ifdef MULTILANG_SUPPORT
- { name: "lang", offset: 0, size: 0, /*mask_flags: MTD_WRITEABLE,*/ }, /* for multilang*/
-#endif
- { name: "nvram", offset: 0, size: 0, },
+ { name: "pmon", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
+ { name: "linux", offset: 0, size: 0, },
+ { name: "rootfs", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
+ { name: "jffs2", offset: 0, size: 0, },
+ { name: "nvram", offset: 0, size: 0, },
{ name: NULL, },
};
+#define PART_BOOT 0
+#define PART_LINUX 1
+#define PART_ROOTFS 2
+#define PART_JFFS2 3
+#define PART_NVRAM 4
+
struct mtd_partition * __init
init_mtd_partitions(struct mtd_info *mtd, size_t size)
{
- struct minix_super_block *minixsb;
- struct ext2_super_block *ext2sb;
- struct romfs_super_block *romfsb;
- struct cramfs_super *cramfsb;
- struct squashfs_super_block *squashfsb;
struct trx_header *trx;
unsigned char buf[512];
- int off;
-#ifdef MULTILANG_SUPPORT
- struct lang_header *lang; /* for multilang */
- int off1;
-#endif
+ size_t off;
size_t len;
+ size_t trxsize;
- minixsb = (struct minix_super_block *) buf;
- ext2sb = (struct ext2_super_block *) buf;
- romfsb = (struct romfs_super_block *) buf;
- cramfsb = (struct cramfs_super *) buf;
- squashfsb = (struct squashfs_super_block *) buf;
- trx = (struct trx_header *) buf;
-#ifdef MULTILANG_SUPPORT
- lang = (struct lang_header *) buf; /* for multilang */
-#endif
-
- /* Look at every 64 KB boundary */
- for (off = 0; off < size; off += (64 * 1024)) {
- memset(buf, 0xe5, sizeof(buf));
+ bcm947xx_parts[PART_NVRAM].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
+ bcm947xx_parts[PART_NVRAM].size = size - bcm947xx_parts[PART_NVRAM].offset;
- /*
- * Read block 0 to test for romfs and cramfs superblock
- */
- if (MTD_READ(mtd, off, sizeof(buf), &len, buf) ||
- len != sizeof(buf))
- continue;
+ trxsize = 0;
+ trx = (struct trx_header *) buf;
+ for (off = 0; off < size; off += mtd->erasesize) {
+ if ((MTD_READ(mtd, off, sizeof(buf), &len, buf)) || (len != sizeof(buf))) continue;
- /* Try looking at TRX header for rootfs offset */
if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
- bcm947xx_parts[1].offset = off;
- if (le32_to_cpu(trx->offsets[1]) > off)
- off = le32_to_cpu(trx->offsets[1]);
- continue;
- }
-
- /* romfs is at block zero too */
- if (romfsb->word0 == ROMSB_WORD0 &&
- romfsb->word1 == ROMSB_WORD1) {
- printk(KERN_NOTICE
- "%s: romfs filesystem found at block %d\n",
- mtd->name, off / BLOCK_SIZE);
- goto done;
- }
-
- /* so is cramfs */
- if (cramfsb->magic == CRAMFS_MAGIC) {
- printk(KERN_NOTICE
- "%s: cramfs filesystem found at block %d\n",
- mtd->name, off / BLOCK_SIZE);
- goto done;
- }
-
- /* squashfs is at block zero too */
- if (squashfsb->s_magic == SQUASHFS_MAGIC) {
- printk(KERN_NOTICE
- "%s: squashfs filesystem found at block %d\n",
- mtd->name, off / BLOCK_SIZE);
- goto done;
- }
-
- /*
- * Read block 1 to test for minix and ext2 superblock
- */
- if (MTD_READ(mtd, off + BLOCK_SIZE, sizeof(buf), &len, buf) ||
- len != sizeof(buf))
- continue;
-
- /* Try minix */
- if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
- minixsb->s_magic == MINIX_SUPER_MAGIC2) {
- printk(KERN_NOTICE
- "%s: Minix filesystem found at block %d\n",
- mtd->name, off / BLOCK_SIZE);
- goto done;
- }
-
- /* Try ext2 */
- if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
- printk(KERN_NOTICE
- "%s: ext2 filesystem found at block %d\n",
- mtd->name, off / BLOCK_SIZE);
- goto done;
+ bcm947xx_parts[PART_BOOT].size = off;
+
+ bcm947xx_parts[PART_LINUX].offset = off;
+ bcm947xx_parts[PART_LINUX].size = bcm947xx_parts[PART_NVRAM].offset - off;
+
+ trxsize = ROUNDUP(le32_to_cpu(trx->len), mtd->erasesize); // kernel + rootfs
+
+ bcm947xx_parts[PART_ROOTFS].offset = trx->offsets[1] + off;
+ bcm947xx_parts[PART_ROOTFS].size = trxsize - trx->offsets[1];
+
+ bcm947xx_parts[PART_JFFS2].offset = off + trxsize;
+ bcm947xx_parts[PART_JFFS2].size = bcm947xx_parts[PART_NVRAM].offset - bcm947xx_parts[PART_JFFS2].offset;
+ break;
}
}
- printk(KERN_NOTICE
- "%s: Couldn't find valid ROM disk image\n",
- mtd->name);
-
- done:
-#if MULTILANG_SUPPORT
-/* below for multilang */
- /* Look at every 64 KB boundary */
- for (off1 = 0; off1 < size; off1 += (64 * 1024)) {
- memset(buf, 0xe5, sizeof(buf));
-
- /*
- * Read block 0 to test for romfs and cramfs superblock
- */
- if (MTD_READ(mtd, off1, sizeof(buf), &len, buf) ||
- len != sizeof(buf))
- continue;
-
- /* Try looking at TRX header for rootfs offset */
- if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
- printk("le32_to_cpu(trx->magic)=0x%lx trx->magic=0x%lx\n", le32_to_cpu(trx->magic), trx->magic);
- //bcm947xx_parts[1].offset = off1;
- printk("bcm947xx_parts[1].offset=0x%lx trx->offsets[1]=0x%lx off\n", bcm947xx_parts[2].offset);
- if (le32_to_cpu(trx->offsets[2]) > off1) {
- off1 = le32_to_cpu(trx->offsets[2]);
- printk("ok1 off1=0x%lx\n", off1);
- }
- continue;
- }
-
- /* so is cramfs */
- if (cramfsb->magic == CRAMFS_MAGIC) {
- printk(KERN_NOTICE
- "%s: lang cramfs filesystem found at block %d (0x%lx)\n",
- mtd->name, off1 / BLOCK_SIZE, off1);
- goto done1;
- }
-
- /* squashfs is at block zero too */
- if (squashfsb->s_magic == SQUASHFS_MAGIC) {
- printk(KERN_NOTICE
- "%s: lang squashfs filesystem found at block %d (0x%lx)\n",
- mtd->name, off1 / BLOCK_SIZE, off1);
- goto done1;
- }
-
+ if (trxsize == 0) {
+ // uh, now what...
+ printk(KERN_NOTICE "%s: Unable to find a valid linux partition\n", mtd->name);
}
-done1:
- printk("off=0x%lx off1=0x%lx size=0x%lx\n", off, off1, size);
- if(off1 == 0 || off1 == size )
- {
- off1 = size - 0x60000; // 0x3d0000 only lang.js
- printk("(Not Found Lang Block)off=0x%lx off1=0x%lx size=0x%lx\n", off, off1, size);
+
+#if 0
+ int i;
+ for (i = 0; bcm947xx_parts[i].name; ++i) {
+ printk(KERN_NOTICE "%8x %8x (%8x) %s\n",
+ bcm947xx_parts[i].offset,
+ (bcm947xx_parts[i].offset + bcm947xx_parts[i].size) - 1,
+ bcm947xx_parts[i].size,
+ bcm947xx_parts[i].name);
}
-/* for multilang -> */
- bcm947xx_parts[4].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
- bcm947xx_parts[4].size = size - bcm947xx_parts[4].offset;
- printk("nvram: offset=0x%lx size=0x%lx\n", bcm947xx_parts[4].offset, bcm947xx_parts[4].size);
-
- bcm947xx_parts[3].offset = off1;
- bcm947xx_parts[3].size = bcm947xx_parts[4].offset - bcm947xx_parts[3].offset;
-/* <- for multilang */
-#else
- /* Find and size nvram */
- bcm947xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
- bcm947xx_parts[3].size = size - bcm947xx_parts[3].offset;
#endif
- /* Find and size rootfs */
- if (off < size) {
- bcm947xx_parts[2].offset = off;
- bcm947xx_parts[2].size = bcm947xx_parts[3].offset - bcm947xx_parts[2].offset;
- }
-
- /* Size linux (kernel and rootfs) */
- bcm947xx_parts[1].size = bcm947xx_parts[3].offset - bcm947xx_parts[1].offset;
-
- /* Size pmon */
- bcm947xx_parts[0].size = bcm947xx_parts[1].offset - bcm947xx_parts[0].offset;
return bcm947xx_parts;
}
+
EXPORT_SYMBOL(init_mtd_partitions);
#endif
diff --git a/release/src/linux/linux/arch/mips/kernel/branch.c b/release/src/linux/linux/arch/mips/kernel/branch.c
index 8165789c..738ae74f 100644
--- a/release/src/linux/linux/arch/mips/kernel/branch.c
+++ b/release/src/linux/linux/arch/mips/kernel/branch.c
@@ -170,7 +170,7 @@ int __compute_return_epc(struct pt_regs *regs)
bit = (insn.i_format.rt >> 2);
bit += (bit != 0);
bit += 23;
- switch (insn.i_format.rt) {
+ switch (insn.i_format.rt & 3) {
case 0: /* bc1f */
case 2: /* bc1fl */
if (~fcr31 & (1 << bit))
diff --git a/release/src/linux/linux/arch/mips/kernel/mips_ksyms.c b/release/src/linux/linux/arch/mips/kernel/mips_ksyms.c
index a76613d1..3f07ed47 100644
--- a/release/src/linux/linux/arch/mips/kernel/mips_ksyms.c
+++ b/release/src/linux/linux/arch/mips/kernel/mips_ksyms.c
@@ -52,6 +52,7 @@ EXPORT_SYMBOL(EISA_bus);
*/
EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL_NOVERS(memchr);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memmove);
EXPORT_SYMBOL_NOVERS(strcat);
diff --git a/release/src/linux/linux/arch/mips/math-emu/cp1emu.c b/release/src/linux/linux/arch/mips/math-emu/cp1emu.c
index be1f732a..07f25d74 100644
--- a/release/src/linux/linux/arch/mips/math-emu/cp1emu.c
+++ b/release/src/linux/linux/arch/mips/math-emu/cp1emu.c
@@ -528,9 +528,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
if (MIPSInst_FUNC(ir) != movc_op)
return SIGILL;
cond = fpucondbit[MIPSInst_RT(ir) >> 2];
- if (((ctx->sr & cond) != 0) != ((MIPSInst_RT(ir) & 1) != 0))
- return 0;
- xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
+ if (((ctx->sr & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0))
+ xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
break;
#endif
diff --git a/release/src/linux/linux/drivers/char/serial.c b/release/src/linux/linux/drivers/char/serial.c
index 287eda33..dd3d7de4 100644
--- a/release/src/linux/linux/drivers/char/serial.c
+++ b/release/src/linux/linux/drivers/char/serial.c
@@ -2861,9 +2861,9 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->event = 0;
info->tty = 0;
if (info->blocked_open) {
- if (info->close_delay) {
+ if (state->close_delay) {
set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->close_delay);
+ schedule_timeout(state->close_delay);
}
wake_up_interruptible(&info->open_wait);
}
diff --git a/release/src/linux/linux/drivers/mtd/chips/gen_probe.c b/release/src/linux/linux/drivers/mtd/chips/gen_probe.c
index 4bed4f12..45ea742b 100644
--- a/release/src/linux/linux/drivers/mtd/chips/gen_probe.c
+++ b/release/src/linux/linux/drivers/mtd/chips/gen_probe.c
@@ -287,6 +287,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
#endif
#ifdef CONFIG_MTD_CFI_AMDSTD
case 0x0002:
+ case 0x0006: /* for Winbond W19L320SBT9C */
return cfi_cmdset_0002(map, primary);
#endif
#ifdef CONFIG_MTD_CFI_SSTSTD
diff --git a/release/src/linux/linux/drivers/net/Config.in b/release/src/linux/linux/drivers/net/Config.in
index 59de9c9e..9a79c778 100644
--- a/release/src/linux/linux/drivers/net/Config.in
+++ b/release/src/linux/linux/drivers/net/Config.in
@@ -8,6 +8,11 @@ source drivers/net/arcnet/Config.in
tristate 'Dummy net driver support' CONFIG_DUMMY
tristate 'Bonding driver support' CONFIG_BONDING
tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
+if [ "$CONFIG_NETFILTER" = "y" ]; then
+ tristate 'IMQ (intermediate queueing device) support' CONFIG_IMQ
+else
+ comment 'IMQ needs CONFIG_NETFILTER enabled'
+fi
tristate 'Universal TUN/TAP device driver support' CONFIG_TUN
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
diff --git a/release/src/linux/linux/drivers/net/Makefile b/release/src/linux/linux/drivers/net/Makefile
index acdea2cf..adec92ce 100644
--- a/release/src/linux/linux/drivers/net/Makefile
+++ b/release/src/linux/linux/drivers/net/Makefile
@@ -30,13 +30,13 @@ subdir-m += diag
#subdir-m += ext_io
#subdir-m += ctmisc
-ifeq ($(CONFIG_HW_QOS),y)
-subdir-m += port_based_qos
-else
- ifeq ($(CONFIG_PERFORMANCE),y)
- subdir-m += port_based_qos
- endif
-endif
+# ifeq ($(CONFIG_HW_QOS),y)
+# subdir-m += port_based_qos
+# else
+# ifeq ($(CONFIG_PERFORMANCE),y)
+# subdir-m += port_based_qos
+# endif
+# endif
ifeq ($(CONFIG_TULIP),y)
obj-y += tulip/tulip.o
@@ -174,6 +174,7 @@ endif
obj-$(CONFIG_STRIP) += strip.o
obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_IMQ) += imq.o
obj-$(CONFIG_BONDING) += bonding.o
obj-$(CONFIG_DE600) += de600.o
obj-$(CONFIG_DE620) += de620.o
diff --git a/release/src/linux/linux/drivers/net/hnd/shared_ksyms.sh b/release/src/linux/linux/drivers/net/hnd/shared_ksyms.sh
index 7814f7f0..a4454bea 100644..100755
--- a/release/src/linux/linux/drivers/net/hnd/shared_ksyms.sh
+++ b/release/src/linux/linux/drivers/net/hnd/shared_ksyms.sh
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright 2005, Broadcom Corporation
+# Copyright 2006, Broadcom Corporation
# All Rights Reserved.
#
# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
@@ -8,7 +8,7 @@
# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
#
-# $Id: shared_ksyms.sh,v 1.1.1.7 2005/03/07 07:30:48 kanki Exp $
+# $Id$
#
cat <<EOF
@@ -17,5 +17,5 @@ cat <<EOF
EOF
for file in $* ; do
- ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [DT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p'
+ ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [DRT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p'
done
diff --git a/release/src/linux/linux/drivers/net/imq.c b/release/src/linux/linux/drivers/net/imq.c
new file mode 100644
index 00000000..ac687dba
--- /dev/null
+++ b/release/src/linux/linux/drivers/net/imq.c
@@ -0,0 +1,321 @@
+/*
+ * Pseudo-driver for the intermediate queue device.
+ *
+ * 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.
+ *
+ * Authors: Patrick McHardy, <kaber@trash.net>
+ *
+ * The first version was written by Martin Devera, <devik@cdi.cz>
+ *
+ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
+ * - Update patch to 2.4.21
+ * Sebastian Strollo <sstrollo@nortelnetworks.com>
+ * - Fix "Dead-loop on netdevice imq"-issue
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#include <linux/netfilter_ipv6.h>
+#endif
+#include <linux/imq.h>
+#include <net/pkt_sched.h>
+
+static nf_hookfn imq_nf_hook;
+
+static struct nf_hook_ops imq_ingress_ipv4 = {
+ { NULL, NULL},
+ imq_nf_hook,
+ PF_INET,
+ NF_IP_PRE_ROUTING,
+ NF_IP_PRI_MANGLE + 1
+};
+
+static struct nf_hook_ops imq_egress_ipv4 = {
+ { NULL, NULL},
+ imq_nf_hook,
+ PF_INET,
+ NF_IP_POST_ROUTING,
+ NF_IP_PRI_LAST
+};
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static struct nf_hook_ops imq_ingress_ipv6 = {
+ { NULL, NULL},
+ imq_nf_hook,
+ PF_INET6,
+ NF_IP6_PRE_ROUTING,
+ NF_IP6_PRI_MANGLE + 1
+};
+
+static struct nf_hook_ops imq_egress_ipv6 = {
+ { NULL, NULL},
+ imq_nf_hook,
+ PF_INET6,
+ NF_IP6_POST_ROUTING,
+ NF_IP6_PRI_LAST
+};
+#endif
+
+static unsigned int numdevs = 2;
+
+MODULE_PARM(numdevs, "i");
+MODULE_PARM_DESC(numdevs, "number of imq devices");
+
+static struct net_device *imq_devs;
+
+
+static struct net_device_stats *imq_get_stats(struct net_device *dev)
+{
+ return (struct net_device_stats *)dev->priv;
+}
+
+/* called for packets kfree'd in qdiscs at places other than enqueue */
+static void imq_skb_destructor(struct sk_buff *skb)
+{
+ struct nf_info *info = skb->nf_info;
+
+ if (info) {
+ if (info->indev)
+ dev_put(info->indev);
+ if (info->outdev)
+ dev_put(info->outdev);
+ kfree(info);
+ }
+}
+
+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+
+ skb->imq_flags = 0;
+ skb->destructor = NULL;
+
+ dev->trans_start = jiffies;
+ nf_reinject(skb, skb->nf_info, NF_ACCEPT);
+ return 0;
+}
+
+static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info,
+ void *data)
+{
+ struct net_device *dev;
+ struct net_device_stats *stats;
+ struct sk_buff *skb2 = NULL;
+ struct Qdisc *q;
+ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
+ int ret = -1;
+
+ if (index > numdevs)
+ return -1;
+
+ dev = imq_devs + index;
+ if (!(dev->flags & IFF_UP)) {
+ skb->imq_flags = 0;
+ nf_reinject(skb, info, NF_ACCEPT);
+ return 0;
+ }
+ dev->last_rx = jiffies;
+
+ if (skb->destructor) {
+ skb2 = skb;
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (!skb)
+ return -1;
+ }
+ skb->nf_info = info;
+
+ stats = (struct net_device_stats *)dev->priv;
+ stats->rx_bytes+= skb->len;
+ stats->rx_packets++;
+
+ spin_lock_bh(&dev->queue_lock);
+ q = dev->qdisc;
+ if (q->enqueue) {
+ q->enqueue(skb_get(skb), q);
+ if (skb_shared(skb)) {
+ skb->destructor = imq_skb_destructor;
+ kfree_skb(skb);
+ ret = 0;
+ }
+ }
+ if (spin_is_locked(&dev->xmit_lock))
+ netif_schedule(dev);
+ else
+ qdisc_run(dev);
+ spin_unlock_bh(&dev->queue_lock);
+
+ if (skb2)
+ kfree_skb(ret ? skb : skb2);
+
+ return ret;
+}
+
+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff **pskb,
+ const struct net_device *indev,
+ const struct net_device *outdev,
+ int (*okfn)(struct sk_buff *))
+{
+ if ((*pskb)->imq_flags & IMQ_F_ENQUEUE)
+ return NF_QUEUE;
+
+ return NF_ACCEPT;
+}
+
+
+static int __init imq_init_hooks(void)
+{
+ int err;
+
+ if ((err = nf_register_queue_handler(PF_INET, imq_nf_queue, NULL)))
+ goto err1;
+ if ((err = nf_register_hook(&imq_ingress_ipv4)))
+ goto err2;
+ if ((err = nf_register_hook(&imq_egress_ipv4)))
+ goto err3;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ if ((err = nf_register_queue_handler(PF_INET6, imq_nf_queue, NULL)))
+ goto err4;
+ if ((err = nf_register_hook(&imq_ingress_ipv6)))
+ goto err5;
+ if ((err = nf_register_hook(&imq_egress_ipv6)))
+ goto err6;
+#endif
+
+ return 0;
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+err6:
+ nf_unregister_hook(&imq_ingress_ipv6);
+err5:
+ nf_unregister_queue_handler(PF_INET6);
+err4:
+ nf_unregister_hook(&imq_egress_ipv4);
+#endif
+err3:
+ nf_unregister_hook(&imq_ingress_ipv4);
+err2:
+ nf_unregister_queue_handler(PF_INET);
+err1:
+ return err;
+}
+
+static void __exit imq_unhook(void)
+{
+ nf_unregister_hook(&imq_ingress_ipv4);
+ nf_unregister_hook(&imq_egress_ipv4);
+ nf_unregister_queue_handler(PF_INET);
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ nf_unregister_hook(&imq_ingress_ipv6);
+ nf_unregister_hook(&imq_egress_ipv6);
+ nf_unregister_queue_handler(PF_INET6);
+#endif
+}
+
+static int __init imq_dev_init(struct net_device *dev)
+{
+ dev->hard_start_xmit = imq_dev_xmit;
+ dev->type = ARPHRD_VOID;
+ dev->mtu = 1500;
+ dev->tx_queue_len = 30;
+ dev->flags = IFF_NOARP;
+ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOMEM;
+ memset(dev->priv, 0, sizeof(struct net_device_stats));
+ dev->get_stats = imq_get_stats;
+
+ return 0;
+}
+
+static void imq_dev_uninit(struct net_device *dev)
+{
+ kfree(dev->priv);
+}
+
+static int __init imq_init_devs(void)
+{
+ struct net_device *dev;
+ int i;
+
+ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
+ printk(KERN_ERR "numdevs has to be betweed 1 and %u\n",
+ IMQ_MAX_DEVS);
+ return -EINVAL;
+ }
+
+ imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);
+ if (!imq_devs)
+ return -ENOMEM;
+ memset(imq_devs, 0, sizeof(struct net_device) * numdevs);
+
+ /* we start counting at zero */
+ numdevs--;
+
+ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {
+ SET_MODULE_OWNER(dev);
+ strcpy(dev->name, "imq%d");
+ dev->init = imq_dev_init;
+ dev->uninit = imq_dev_uninit;
+
+ if (register_netdev(dev) < 0)
+ goto err_register;
+ }
+ return 0;
+
+err_register:
+ for (; i; i--)
+ unregister_netdev(--dev);
+ kfree(imq_devs);
+ return -EIO;
+}
+
+static void imq_cleanup_devs(void)
+{
+ int i;
+ struct net_device *dev = imq_devs;
+
+ for (i = 0; i <= numdevs; i++)
+ unregister_netdev(dev++);
+
+ kfree(imq_devs);
+}
+
+static int __init imq_init_module(void)
+{
+ int err;
+
+ if ((err = imq_init_devs()))
+ return err;
+ if ((err = imq_init_hooks())) {
+ imq_cleanup_devs();
+ return err;
+ }
+
+ printk(KERN_INFO "imq driver loaded.\n");
+
+ return 0;
+}
+
+static void __exit imq_cleanup_module(void)
+{
+ imq_unhook();
+ imq_cleanup_devs();
+}
+
+module_init(imq_init_module);
+module_exit(imq_cleanup_module);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/drivers/net/ppp_generic.c b/release/src/linux/linux/drivers/net/ppp_generic.c
index 3a4e0fb8..ed4e243a 100644
--- a/release/src/linux/linux/drivers/net/ppp_generic.c
+++ b/release/src/linux/linux/drivers/net/ppp_generic.c
@@ -221,7 +221,7 @@ static atomic_t channel_count = ATOMIC_INIT(0);
#define DST_PORT(skb) (((skb)->data[24] << 8) + (skb)->data[25])
#define MARK_LAN2WAN 0x100
//#define myprintk(fmt, args...) printk(fmt, ## args)
-#define myprintk(fmt, args...)
+#define myprintk(fmt, args...)
/* We limit the length of ppp->file.rq to this (arbitrary) value */
@@ -301,7 +301,7 @@ static const int npindex_to_proto[NUM_NP] = {
PPP_IPX,
PPP_AT,
};
-
+
/* Translates an ethertype into an NP index */
static inline int ethertype_to_npindex(int ethertype)
{
@@ -987,6 +987,34 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
ppp->last_xmit = jiffies;
skb_pull(skb, 2);
#else
+
+#if 1 // zzz
+ switch (IP_PROTO(skb)) {
+ case 6: // TCP
+ switch (DST_PORT(skb)) {
+ case 139: // netbios-ssn
+ case 445: // microsoft-ds
+ break;
+ default:
+ ppp->last_xmit = jiffies;
+ break;
+ }
+ break;
+ case 17: // UDP
+ switch (DST_PORT(skb)) {
+ case 137: // netbios-ns
+ case 138: // netbios-dgm
+ break;
+ default:
+ ppp->last_xmit = jiffies;
+ break;
+ }
+ break;
+ default:
+ ppp->last_xmit = jiffies;
+ break;
+ }
+#else
/* for data packets, record the time */
myprintk(KERN_DEBUG "PPP: (%ld) send nfmark=[%lx] proto[%d] port[%d -> %d]\n",
jiffies,
@@ -1007,7 +1035,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
}
else
myprintk(KERN_DEBUG "PPP: No reset timer\n");
-
+#endif
+
#endif /* CONFIG_PPP_FILTER */
}
@@ -1543,7 +1572,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
//else if(UDP_PORT(skb) == 138){
// printk(KERN_DEBUG " Skip NETBIOS Datagram Service packet\n");
//}
- //else if(IP_PROTO(skb) == 2){
+ //else if(IP_PROTO(skb) == 2){
// printk(KERN_DEBUG " Skip IGMP packet\n");
//}
//else
@@ -2053,7 +2082,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
switch (CCP_CODE(dp)) {
case CCP_CONFREQ:
- /* A ConfReq starts negotiation of compression
+ /* A ConfReq starts negotiation of compression
* in one direction of transmission,
* and hence brings it down...but which way?
*
@@ -2063,16 +2092,16 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
if(inbound)
/* He is proposing what I should send */
ppp->xstate &= ~SC_COMP_RUN;
- else
+ else
/* I am proposing to what he should send */
ppp->rstate &= ~SC_DECOMP_RUN;
-
+
break;
-
+
case CCP_TERMREQ:
case CCP_TERMACK:
/*
- * CCP is going down, both directions of transmission
+ * CCP is going down, both directions of transmission
*/
ppp->rstate &= ~SC_DECOMP_RUN;
ppp->xstate &= ~SC_COMP_RUN;
diff --git a/release/src/linux/linux/fs/Config.in b/release/src/linux/linux/fs/Config.in
index 1c4628a6..f535df59 100644
--- a/release/src/linux/linux/fs/Config.in
+++ b/release/src/linux/linux/fs/Config.in
@@ -48,13 +48,20 @@ if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then
fi
tristate 'Compressed ROM file system support' CONFIG_CRAMFS
tristate 'Squashed file system support' CONFIG_SQUASHFS
+if [ "$CONFIG_SQUASHFS" = "y" -o "$CONFIG_SQUASHFS" = "m" ] ; then
+bool 'Additional options for memory constrained systems ' CONFIG_SQUASHFS_EMBEDDED
+fi
+if [ "$CONFIG_SQUASHFS_EMBEDDED" = "y" ] ; then
+int 'Number of fragments cached' CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE 3
+bool 'Use Vmalloc rather than Kmalloc' CONFIG_SQUASHFS_VMALLOC
+fi
bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
define_bool CONFIG_RAMFS y
-if [ "$CONFIG_CRAMFS" = "y" -o "$CONFIG_CRAMFS" = "m" ] ; then
+if [ "$CONFIG_CRAMFS" = "y" -o "$CONFIG_CRAMFS" = "m" -o "$CONFIG_SQUASHFS" = "y" -o "$CONFIG_SQUASHFS" = "m" ] ; then
choice 'Compression method' \
"ZLIB CONFIG_ZLIB_FS_INFLATE \
- LZMA CONFIG_LZMA_FS_INFLATE" ZLIB
+ LZMA CONFIG_LZMA_FS_INFLATE" LZMA
fi
tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS
@@ -131,6 +138,10 @@ if [ "$CONFIG_NET" = "y" ]; then
define_bool CONFIG_LOCKD_V4 y
fi
+ dep_tristate 'CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)' CONFIG_CIFS $CONFIG_INET
+ dep_mbool ' CIFS statistics' CONFIG_CIFS_STATS $CONFIG_CIFS
+ dep_mbool ' CIFS POSIX Protocol Extensions' CONFIG_CIFS_POSIX $CONFIG_CIFS
+
dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET
if [ "$CONFIG_SMB_FS" != "n" ]; then
bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT
diff --git a/release/src/linux/linux/fs/Makefile b/release/src/linux/linux/fs/Makefile
index 7d05f77f..951a6125 100644
--- a/release/src/linux/linux/fs/Makefile
+++ b/release/src/linux/linux/fs/Makefile
@@ -40,6 +40,7 @@ subdir-$(CONFIG_MSDOS_FS) += msdos
subdir-$(CONFIG_VFAT_FS) += vfat
subdir-$(CONFIG_BFS_FS) += bfs
subdir-$(CONFIG_ISO9660_FS) += isofs
+subdir-$(CONFIG_CIFS) += cifs
subdir-$(CONFIG_DEVFS_FS) += devfs
subdir-$(CONFIG_HFS_FS) += hfs
subdir-$(CONFIG_VXFS_FS) += freevxfs
@@ -67,8 +68,8 @@ subdir-$(CONFIG_REISERFS_FS) += reiserfs
subdir-$(CONFIG_DEVPTS_FS) += devpts
subdir-$(CONFIG_SUN_OPENPROMFS) += openpromfs
subdir-$(CONFIG_BEFS_FS) += befs
-subdir-$(CONFIG_JFS_FS) += jfs
subdir-$(CONFIG_SQUASHFS) += squashfs
+subdir-$(CONFIG_JFS_FS) += jfs
obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
diff --git a/release/src/linux/linux/fs/buffer.c b/release/src/linux/linux/fs/buffer.c
index 9ec1b055..3a691eeb 100644
--- a/release/src/linux/linux/fs/buffer.c
+++ b/release/src/linux/linux/fs/buffer.c
@@ -1824,7 +1824,7 @@ out:
* We may have to extend the file.
*/
-int cont_prepare_write(struct page *page, unsigned offset, unsigned to, get_block_t *get_block, unsigned long *bytes)
+int cont_prepare_write(struct page *page, unsigned offset, unsigned to, get_block_t *get_block, loff_t *bytes)
{
struct address_space *mapping = page->mapping;
struct inode *inode = mapping->host;
@@ -2808,6 +2808,8 @@ void wakeup_bdflush(void)
wake_up_interruptible(&bdflush_wait);
}
+EXPORT_SYMBOL(wakeup_bdflush);
+
/*
* Here we attempt to write back old buffers. We also try to flush inodes
* and supers as well, since this function is essentially "update", and
@@ -3009,4 +3011,3 @@ static int __init bdflush_init(void)
}
module_init(bdflush_init)
-
diff --git a/release/src/linux/linux/fs/cifs/AUTHORS b/release/src/linux/linux/fs/cifs/AUTHORS
new file mode 100644
index 00000000..43a7b653
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/AUTHORS
@@ -0,0 +1,37 @@
+Original Author
+===============
+Steve French (sfrench@samba.org)
+
+The author wishes to express his appreciation and thanks to:
+Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
+improvements. Thanks to IBM for allowing me the time and test resources to pursue
+this project. Jim McDonough from IBM (and the Samba Team) for his help.
+The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
+Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
+for proving years ago that a very good smb/cifs client could be done on a Unix like
+operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
+and others for their work on the Linux smbfs module over the years. Thanks to
+the other members of the Storage Network Industry Association CIFS Technical
+Workgroup for their work specifying this highly complex protocol and finally
+thanks to the Samba team for their technical advice and encouragement.
+
+Patch Contributors
+------------------
+Zwane Mwaikambo
+Andi Kleen
+Amrut Joshi
+Shobhit Dayal
+Sergey Vlasov
+Richard Hughes
+Yury Umanets
+
+Test case and Bug Report contributors
+-------------------------------------
+Thanks to those in the community who have submitted detailed bug reports
+and debug of problems they have found: Jochen Dolze, David Blaine,
+Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
+Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
+Olaf Kirch, Kieron Briggs, Nick Millington and others.
+
+And thanks to the IBM LTC and Power test teams and SuSE testers for
+finding multiple bugs during excellent stress test runs.
diff --git a/release/src/linux/linux/fs/cifs/CHANGES b/release/src/linux/linux/fs/cifs/CHANGES
new file mode 100644
index 00000000..3f166375
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/CHANGES
@@ -0,0 +1,572 @@
+Version 1.20
+------------
+Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
+info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir
+(in build_wildcard_path_from_dentry). Fix mknod to pass type field
+(block/char/fifo) properly. Remove spurious mount warning log entry when
+credentials passed as mount argument. Set major/minor device number in
+inode for block and char devices when unix extensions enabled.
+
+Version 1.19
+------------
+Fix /proc/fs/cifs/Stats and DebugData display to handle larger
+amounts of return data. Properly limit requests to MAX_REQ (50
+is the usual maximum active multiplex SMB/CIFS requests per server).
+Do not kill cifsd (and thus hurt the other SMB session) when more than one
+session to the same server (but with different userids) exists and one
+of the two user's smb sessions is being removed while leaving the other.
+Do not loop reconnecting in cifsd demultiplex thread when admin
+kills the thread without going through unmount.
+
+Version 1.18
+------------
+Do not rename hardlinked files (since that should be a noop). Flush
+cached write behind data when reopening a file after session abend,
+except when already in write. Grab per socket sem during reconnect
+to avoid oops in sendmsg if overlapping with reconnect. Do not
+reset cached inode file size on readdir for files open for write on
+client.
+
+
+Version 1.17
+------------
+Update number of blocks in file so du command is happier (in Linux a fake
+blocksize of 512 is required for calculating number of blocks in inode).
+Fix prepare write of partial pages to read in data from server if possible.
+Fix race on tcpStatus field between unmount and reconnection code, causing
+cifsd process sometimes to hang around forever. Improve out of memory
+checks in cifs_filldir
+
+Version 1.16
+------------
+Fix incorrect file size in file handle based setattr on big endian hardware.
+Fix oops in build_path_from_dentry when out of memory. Add checks for invalid
+and closing file structs in writepage/partialpagewrite. Add statistics
+for each mounted share (new menuconfig option). Fix endianness problem in
+volume information displayed in /proc/fs/cifs/DebugData (only affects
+affects big endian architectures). Prevent renames while constructing
+path names for open, mkdir and rmdir.
+
+Version 1.15
+------------
+Change to mempools for alloc smb request buffers and multiplex structs
+to better handle low memory problems (and potential deadlocks).
+
+Version 1.14
+------------
+Fix incomplete listings of large directories on Samba servers when Unix
+extensions enabled. Fix oops when smb_buffer can not be allocated. Fix
+rename deadlock when writing out dirty pages at same time.
+
+Version 1.13
+------------
+Fix open of files in which O_CREATE can cause the mode to change in
+some cases. Fix case in which retry of write overlaps file close.
+Fix PPC64 build error. Reduce excessive stack usage in smb password
+hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
+
+Version 1.12
+------------
+Fixes for large file copy, signal handling, socket retry, buffer
+allocation and low memory situations.
+
+Version 1.11
+------------
+Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
+also now allowing support for specifying client netbiosname. NT4 support added.
+
+Version 1.10
+------------
+Fix reconnection (and certain failed mounts) to properly wake up the
+blocked users thread so it does not seem hung (in some cases was blocked
+until the cifs receive timeout expired). Fix spurious error logging
+to kernel log when application with open network files killed.
+
+Version 1.09
+------------
+Fix /proc/fs module unload warning message (that could be logged
+to the kernel log). Fix intermittent failure in connectathon
+test7 (hardlink count not immediately refreshed in case in which
+inode metadata can be incorrectly kept cached when time near zero)
+
+Version 1.08
+------------
+Allow file_mode and dir_mode (specified at mount time) to be enforced
+locally (the server already enforced its own ACLs too) for servers
+that do not report the correct mode (do not support the
+CIFS Unix Extensions).
+
+Version 1.07
+------------
+Fix some small memory leaks in some unmount error paths. Fix major leak
+of cache pages in readpages causing multiple read oriented stress
+testcases (including fsx, and even large file copy) to fail over time.
+
+Version 1.06
+------------
+Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
+This allows files that differ only in case and improves performance of file
+creation and file open to such servers. Fix semaphore conflict which causes
+slow delete of open file to Samba (which unfortunately can cause an oplock
+break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
+
+Version 1.05
+------------
+fixes to cifs_readpages for fsx test case
+
+Version 1.04
+------------
+Fix caching data integrity bug when extending file size especially when no
+oplock on file. Fix spurious logging of valid already parsed mount options
+that are parsed outside of the cifs vfs such as nosuid.
+
+
+Version 1.03
+------------
+Connect to server when port number override not specified, and tcp port
+unitialized. Reset search to restart at correct file when kernel routine
+filldir returns error during large directory searches (readdir).
+
+Version 1.02
+------------
+Fix caching problem when files opened by multiple clients in which
+page cache could contain stale data, and write through did
+not occur often enough while file was still open when read ahead
+(read oplock) not allowed. Treat "sep=" when first mount option
+as an overrride of comma as the default separator between mount
+options.
+
+Version 1.01
+------------
+Allow passwords longer than 16 bytes. Allow null password string.
+
+Version 1.00
+------------
+Gracefully clean up failed mounts when attempting to mount to servers such as
+Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
+embedded commas in mount parsing of passwords.
+
+Version 0.99
+------------
+Invalidate local inode cached pages on oplock break and when last file
+instance is closed so that the client does not continue using stale local
+copy rather than later modified server copy of file. Do not reconnect
+when server drops the tcp session prematurely before negotiate
+protocol response. Fix oops in roepen_file when dentry freed. Allow
+the support for CIFS Unix Extensions to be disabled via proc interface.
+
+Version 0.98
+------------
+Fix hang in commit_write during reconnection of open files under heavy load.
+Fix unload_nls oops in a mount failure path. Serialize writes to same socket
+which also fixes any possible races when cifs signatures are enabled in SMBs
+being sent out of signature sequence number order.
+
+Version 0.97
+------------
+Fix byte range locking bug (endian problem) causing bad offset and
+length.
+
+Version 0.96
+------------
+Fix oops (in send_sig) caused by CIFS unmount code trying to
+wake up the demultiplex thread after it had exited. Do not log
+error on harmless oplock release of closed handle.
+
+Version 0.95
+------------
+Fix unsafe global variable usage and password hash failure on gcc 3.3.1
+Fix problem reconnecting secondary mounts to same server after session
+failure. Fix invalid dentry - race in mkdir when directory gets created
+by another client between the lookup and mkdir.
+
+Version 0.94
+------------
+Fix to list processing in reopen_files. Fix reconnection when server hung
+but tcpip session still alive. Set proper timeout on socket read.
+
+Version 0.93
+------------
+Add missing mount options including iocharset. SMP fixes in write and open.
+Fix errors in reconnecting after TCP session failure. Fix module unloading
+of default nls codepage
+
+Version 0.92
+------------
+Active smb transactions should never go negative (fix double FreeXid). Fix
+list processing in file routines. Check return code on kmalloc in open.
+Fix spinlock usage for SMP.
+
+Version 0.91
+------------
+Fix oops in reopen_files when invalid dentry. drop dentry on server rename
+and on revalidate errors. Fix cases where pid is now tgid. Fix return code
+on create hard link when server does not support them.
+
+Version 0.90
+------------
+Fix scheduling while atomic error in getting inode info on newly created file.
+Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
+
+Version 0.89
+------------
+Fix oops on write to dead tcp session. Remove error log write for case when file open
+O_CREAT but not O_EXCL
+
+Version 0.88
+------------
+Fix non-POSIX behavior on rename of open file and delete of open file by taking
+advantage of trans2 SetFileInfo rename facility if available on target server.
+Retry on ENOSPC and EAGAIN socket errors.
+
+Version 0.87
+------------
+Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
+allocation size miscalculation. After oplock token lost do not read through
+cache.
+
+Version 0.86
+------------
+Fix oops on empty file readahead. Fix for file size handling for locally cached files.
+
+Version 0.85
+------------
+Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
+during auto reconnection to server after server recovered from failure.
+
+Version 0.84
+------------
+Finish support for Linux 2.5 open/create changes, which removes the
+redundant NTCreate/QPathInfo/close that was sent during file create.
+Enable oplock by default. Enable packet signing by default (needed to
+access many recent Windows servers)
+
+Version 0.83
+------------
+Fix oops when mounting to long server names caused by inverted parms to kmalloc.
+Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
+we will choose a cifs user session (smb uid) that better matches the local
+uid if a) the mount uid does not match the current uid and b) we have another
+session to the same server (ip address) for a different mount which
+matches the current local uid.
+
+Version 0.82
+------------
+Add support for mknod of block or character devices. Fix oplock
+code (distributed caching) to properly send response to oplock
+break from server.
+
+Version 0.81
+------------
+Finish up CIFS packet digital signing for the default
+NTLM security case. This should help Windows 2003
+network interoperability since it is common for
+packet signing to be required now. Fix statfs (stat -f)
+which recently started returning errors due to
+invalid value (-1 instead of 0) being set in the
+struct kstatfs f_ffiles field.
+
+Version 0.80
+-----------
+Fix oops on stopping oplock thread when removing cifs when
+built as module.
+
+Version 0.79
+------------
+Fix mount options for ro (readonly), uid, gid and file and directory mode.
+
+Version 0.78
+------------
+Fix errors displayed on failed mounts to be more understandable.
+Fixed various incorrect or misleading smb to posix error code mappings.
+
+Version 0.77
+------------
+Fix display of NTFS DFS junctions to display as symlinks.
+They are the network equivalent. Fix oops in
+cifs_partialpagewrite caused by missing spinlock protection
+of openfile linked list. Allow writebehind caching errors to
+be returned to the application at file close.
+
+Version 0.76
+------------
+Clean up options displayed in /proc/mounts by show_options to
+be more consistent with other filesystems.
+
+Version 0.75
+------------
+Fix delete of readonly file to Windows servers. Reflect
+presence or absence of read only dos attribute in mode
+bits for servers that do not support CIFS Unix extensions.
+Fix shortened results on readdir of large directories to
+servers supporting CIFS Unix extensions (caused by
+incorrect resume key).
+
+Version 0.74
+------------
+Fix truncate bug (set file size) that could cause hangs e.g. running fsx
+
+Version 0.73
+------------
+unload nls if mount fails.
+
+Version 0.72
+------------
+Add resume key support to search (readdir) code to workaround
+Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
+allows disabling caching of attribute information for
+lookups.
+
+Version 0.71
+------------
+Add more oplock handling (distributed caching code). Remove
+dead code. Remove excessive stack space utilization from
+symlink routines.
+
+Version 0.70
+------------
+Fix oops in get dfs referral (triggered when null path sent in to
+mount). Add support for overriding rsize at mount time.
+
+Version 0.69
+------------
+Fix buffer overrun in readdir which caused intermittent kernel oopses.
+Fix writepage code to release kmap on write data. Allow "-ip=" new
+mount option to be passed in on parameter distinct from the first part
+(server name portion of) the UNC name. Allow override of the
+tcp port of the target server via new mount option "-port="
+
+Version 0.68
+------------
+Fix search handle leak on rewind. Fix setuid and gid so that they are
+reflected in the local inode immediately. Cleanup of whitespace
+to make 2.4 and 2.5 versions more consistent.
+
+
+Version 0.67
+------------
+Fix signal sending so that captive thread (cifsd) exits on umount
+(which was causing the warning in kmem_cache_free of the request buffers
+at rmmod time). This had broken as a sideeffect of the recent global
+kernel change to daemonize. Fix memory leak in readdir code which
+showed up in "ls -R" (and applications that did search rewinding).
+
+Version 0.66
+------------
+Reconnect tids and fids after session reconnection (still do not
+reconnect byte range locks though). Fix problem caching
+lookup information for directory inodes, improving performance,
+especially in deep directory trees. Fix various build warnings.
+
+Version 0.65
+------------
+Finish fixes to commit write for caching/readahead consistency. fsx
+now works to Samba servers. Fix oops caused when readahead
+was interrupted by a signal.
+
+Version 0.64
+------------
+Fix data corruption (in partial page after truncate) that caused fsx to
+fail to Windows servers. Cleaned up some extraneous error logging in
+common error paths. Add generic sendfile support.
+
+Version 0.63
+------------
+Fix memory leak in AllocMidQEntry.
+Finish reconnection logic, so connection with server can be dropped
+(or server rebooted) and the cifs client will reconnect.
+
+Version 0.62
+------------
+Fix temporary socket leak when bad userid or password specified
+(or other SMBSessSetup failure). Increase maximum buffer size to slightly
+over 16K to allow negotiation of up to Samba and Windows server default read
+sizes. Add support for readpages
+
+Version 0.61
+------------
+Fix oops when username not passed in on mount. Extensive fixes and improvements
+to error logging (strip redundant newlines, change debug macros to ensure newline
+passed in and to be more consistent). Fix writepage wrong file handle problem,
+a readonly file handle could be incorrectly used to attempt to write out
+file updates through the page cache to multiply open files. This could cause
+the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
+shares to the same Windows server when using different usernames
+(doing this to Samba servers worked but Windows was rejecting it) - now it is
+possible to use different userids when connecting to the same server from a
+Linux client. Fix oops when treeDisconnect called during unmount on
+previously freed socket.
+
+Version 0.60
+------------
+Fix oops in readpages caused by not setting address space operations in inode in
+rare code path.
+
+Version 0.59
+------------
+Includes support for deleting of open files and renaming over existing files (per POSIX
+requirement). Add readlink support for Windows junction points (directory symlinks).
+
+Version 0.58
+------------
+Changed read and write to go through pagecache. Added additional address space operations.
+Memory mapped operations now working.
+
+Version 0.57
+------------
+Added writepage code for additional memory mapping support. Fixed leak in xids causing
+the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on
+every stat call. Additional formatting cleanup.
+
+Version 0.56
+------------
+Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup.
+
+Version 0.55
+------------
+Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
+Also included a modified version of his fix to protect global list manipulation of
+the smb session and tree connection and mid related global variables.
+
+Version 0.54
+------------
+Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre
+changes to superblock layout. Remove wasteful allocation of smb buffers (now the send
+buffer is reused for responses). Add more oplock handling. Additional minor cleanup.
+
+Version 0.53
+------------
+More stylistic updates to better match kernel style. Add additional statistics
+for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2
+and CIFS Packet Signing enablement.
+
+Version 0.52
+------------
+Replace call to sleep_on with safer wait_on_event.
+Make stylistic changes to better match kernel style recommendations.
+Remove most typedef usage (except for the PDUs themselves).
+
+Version 0.51
+------------
+Update mount so the -unc mount option is no longer required (the ip address can be specified
+in a UNC style device name. Implementation of readpage/writepage started.
+
+Version 0.50
+------------
+Fix intermittent problem with incorrect smb header checking on badly
+fragmented tcp responses
+
+Version 0.49
+------------
+Fixes to setting of allocation size and file size.
+
+Version 0.48
+------------
+Various 2.5.38 fixes. Now works on 2.5.38
+
+Version 0.47
+------------
+Prepare for 2.5 kernel merge. Remove ifdefs.
+
+Version 0.46
+------------
+Socket buffer management fixes. Fix dual free.
+
+Version 0.45
+------------
+Various big endian fixes for hardlinks and symlinks and also for dfs.
+
+Version 0.44
+------------
+Various big endian fixes for servers with Unix extensions such as Samba
+
+Version 0.43
+------------
+Various FindNext fixes for incorrect filenames on large directory searches on big endian
+clients. basic posix file i/o tests now work on big endian machines, not just le
+
+Version 0.42
+------------
+SessionSetup and NegotiateProtocol now work from Big Endian machines.
+Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older
+versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
+
+Version 0.41
+------------
+Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
+files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
+
+Version 0.40
+------------
+Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
+session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
+Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
+(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
+
+Version 0.38
+------------
+Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
+it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
+
+Version 0.37
+------------
+Rewrote much of connection and mount/unmount logic to handle bugs with
+multiple uses to same share, multiple users to same server etc.
+
+Version 0.36
+------------
+Fixed major problem with dentry corruption (missing call to dput)
+
+Version 0.35
+------------
+Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
+Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs
+although corresponding function not fully implemented in the vfs yet
+
+Version 0.34
+------------
+Fixed dentry caching bug, misc. cleanup
+
+Version 0.33
+------------
+Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build
+on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
+Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added.
+
+Version 0.32
+------------
+Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
+and tested against Samba 2.2.5
+
+
+Version 0.31
+------------
+1) Fixed lockrange to be correct (it was one byte too short)
+
+2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly
+show range as locked when there is a conflict with an existing lock.
+
+3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
+in most cases. Eventually will offer optional ability to query server for the correct perms.
+
+3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded
+but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
+session)
+
+4) Fixed error logging of valid mount options
+
+5) Removed logging of password field.
+
+6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
+and cleaned them up and made them more consistent with other cifs functions.
+
+7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
+(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
+nor is the symlink support using the Unix extensions
+
+8) Started adding the readlink and follow_link code
+
+Version 0.3
+-----------
+Initial drop
+
diff --git a/release/src/linux/linux/fs/cifs/Makefile b/release/src/linux/linux/fs/cifs/Makefile
new file mode 100644
index 00000000..892af0ce
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for Linux CIFS VFS client
+#
+O_TARGET := cifs.o
+
+obj-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o cifsencrypt.o
+
+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff --git a/release/src/linux/linux/fs/cifs/README b/release/src/linux/linux/fs/cifs/README
new file mode 100644
index 00000000..59a00eea
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/README
@@ -0,0 +1,356 @@
+The CIFS VFS support for Linux supports many advanced network filesystem
+features such as heirarchical dfs like namespace, hardlinks, locking and more.
+It was designed to comply with the SNIA CIFS Technical Reference (which
+supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
+practical interoperability with Windows 2000, Windows XP, Samba and equivalent
+servers.
+
+For questions or bug reports please contact:
+ sfrench@samba.org (sfrench@us.ibm.com)
+
+Build instructions:
+==================
+For Linux 2.4:
+1) Get the kernel source (e.g.from http://www.kernel.org)
+and download the cifs vfs source (see the project page
+at http://us1.samba.org/samba/Linux_CIFS_client.html)
+and change directory into the top of the kernel directory
+then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
+to add the cifs vfs to your kernel configure options if
+it has not already been added (e.g. current SuSE and UL
+users do not need to apply the cifs_24.patch since the cifs vfs is
+already in the kernel configure menu) and then
+mkdir linux/fs/cifs and then copy the current cifs vfs files from
+the cifs download to your kernel build directory e.g.
+
+ cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
+
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make dep
+6) make modules (or "make" if CIFS VFS not to be built as a module)
+
+For Linux 2.5:
+1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
+at bk://linux.bkbits.net/linux-2.5) and change directory into the top
+of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make
+
+
+Installation instructions:
+=========================
+If you have built the CIFS vfs as module (successfully) simply
+type "make modules_install" (or if you prefer, manually copy the file to
+the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
+
+If you have built the CIFS vfs into the kernel itself, follow the instructions
+for your distribution on how to install a new kernel (usually you
+would simply type "make install").
+
+If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
+the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
+similar files reside (usually /sbin). Although the helper software is not
+required, mount.cifs is recommended. Eventually the Samba 3.0 utility program
+"net" may also be helpful since it may someday provide easier mount syntax for
+users who are used to Windows e.g. net use <mount point> <UNC name or cifs URL>
+Note that running the Winbind pam/nss module (logon service) on all of your
+Linux clients is useful in mapping Uids and Gids consistently across the
+domain to the proper network user. The mount.cifs mount helper can be
+trivially built from Samba 3.0 or later source e.g. by executing:
+
+ gcc samba/source/client/mount.cifs.c -o mount.cifs
+
+Note that when the mount.cifs utility is run suid (allowing user mounts),
+in order to reduce risks, the "nosuid" mount flag is passed in on mount to
+disallow execution of an suid program mounted on the remote target.
+When mount is executed as root, nosuid is not passed in by default,
+and execution of suid programs on the remote target would be enabled
+by default. This can be changed, as with nfs and other filesystems,
+by simply specifying "nosuid" among the mount options. For user mounts
+though to be able to pass the suid flag to mount requires rebuilding
+mount.cifs with the following flag:
+
+ gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
+
+There is a corresponding manual page for cifs mounting in the Samba 3.0 and
+later source tree in docs/manpages/mount.cifs.8
+
+Samba Considerations
+====================
+To get the maximum benefit from the CIFS VFS, we recommend using a server that
+supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
+Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
+Note that uid, gid and file permissions will display default values if you do
+not have a server that supports the Unix extensions for CIFS (such as Samba
+2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
+the line:
+
+ unix extensions = yes
+
+to your smb.conf file on the server. Note that the following smb.conf settings
+are also useful (on the Samba server) when the majority of clients are Unix or
+Linux:
+
+ case sensitive = yes
+ delete readonly = yes
+ ea support = yes
+
+Note that ea support is required for supporting Linux xattrs.
+Some administrators also change the "map archive" and the "create mask"
+parameters from their default values. Creating special devices (mknod)
+remotely may require specifying a mkdev function to Samba if you are not using
+Samba 3.0.5 or later. For more information on these see the manual pages
+("man smb.conf") on the Samba server system. Note that the cifs vfs,
+unlike the smbfs vfs, does not read the smb.conf on the client system
+(the few optional settings are passed in on mount via -o parameters instead).
+Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
+open files (required for strict POSIX compliance). Windows Servers already
+supported this feature. Samba server does not allow symlinks that refer to files
+outside of the share, so in Samba versions prior to 3.0.5, most symlinks to
+files with absolute paths (ie beginning with slash) such as:
+ ln -s /mnt/foo bar
+would be forbidden. Samba 3.0.5 server or later includes the ability to create
+such symlinks safely by converting unsafe symlinks (ie symlinks to server
+files that are outside of the share) to a samba specific format on the server
+that is ignored by local server applications and non-cifs clients and that will
+not be traversed by the Samba server). This is opaque to the Linux client
+application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
+later, but only for remote clients using the CIFS Unix extensions, and will
+be invisbile to Windows clients and typically will not affect local
+applications running on the same server as Samba.
+
+Use instructions:
+================
+Once the CIFS VFS support is built into the kernel or installed as a module
+(cifs.o), you can use mount syntax like the following to access Samba or Windows
+servers:
+
+ mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
+
+Before -o the option -v may be specified to make the mount.cifs
+mount helper display the mount steps more verbosely.
+After -o the following commonly used cifs vfs specific options
+are supported:
+
+ user=<username>
+ pass=<password>
+ domain=<domain name>
+
+Other cifs mount options are described below. Use of TCP names (in addition to
+ip addresses) is available if the mount helper (mount.cifs) is installed. If
+you do not trust the server to which are mounted, or if you do not have
+cifs signing enabled (and the physical network is insecure), consider use
+of the standard mount options "noexec" and "nosuid" to reduce the risk of
+running an altered binary on your local system (downloaded from a hostile server
+or altered by a hostile router).
+
+When using the mount helper mount.cifs, passwords may be specified via alternate
+mechanisms, instead of specifying it after -o using the normal "pass=" syntax
+on the command line:
+1) By including it in a credential file. Specify credentials=filename as one
+of the mount options. Credential files contain two lines
+ username=someuser
+ password=your_password
+2) By specifying the password in the PASSWD environment variable (similarly
+the user name can be taken from the USER environment variable).
+3) By specifying the password in a file by name via PASSWD_FILE
+4) By specifying the password in a file by file descriptor via PASSWD_FD
+
+If no password is provided, mount.cifs will prompt for password entry
+
+Restrictions
+============
+Servers must support the NTLM SMB dialect (which is the most recent, supported
+by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
+Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
+1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
+problem as most servers support this. IPv6 support is planned for the future.
+
+CIFS VFS Mount Options
+======================
+A partial list of the supported mount options follows:
+ user The user name to use when trying to establish
+ the CIFS session.
+ password The user password. If the mount helper is
+ installed, the user will be prompted for password
+ if it is not supplied.
+ ip The ip address of the target server
+ unc The target server Universal Network Name (export) to
+ mount.
+ domain Set the SMB/CIFS workgroup name prepended to the
+ username during CIFS session establishment
+ uid If CIFS Unix extensions are not supported by the server
+ this overrides the default uid for inodes. For mounts to
+ servers which do support the CIFS Unix extensions, such
+ as a properly configured Samba server, the server provides
+ the uid, gid and mode. For servers which do not support
+ the Unix extensions, the default uid (and gid) returned on
+ lookup of existing files is the uid (gid) of the person
+ who executed the mount (root, except when mount.cifs
+ is configured setuid for user mounts) unless the "uid="
+ (gid) mount option is specified. For the uid (gid) of newly
+ created files and directories, ie files created since
+ the last mount of the server share, the expected uid
+ (gid) is cached as as long as the inode remains in
+ memory on the client. Also note that permission
+ checks (authorization checks) on accesses to a file occur
+ at the server, but there are cases in which an administrator
+ may want to restrict at the client as well. For those
+ servers which do not report a uid/gid owner
+ (such as Windows), permissions can also be checked at the
+ client, and a crude form of client side permission checking
+ can be enabled by specifying file_mode and dir_mode on
+ the client
+ gid If CIFS Unix extensions are not supported by the server
+ this overrides the default gid for inodes.
+ file_mode If CIFS Unix extensions are not supported by the server
+ this overrides the default mode for file inodes.
+ dir_mode If CIFS Unix extensions are not supported by the server
+ this overrides the default mode for directory inodes.
+ port attempt to contact the server on this tcp port, before
+ trying the usual ports (port 445, then 139).
+ iocharset Codepage used to convert local path names to and from
+ Unicode. Unicode is used by default for network path
+ names if the server supports it. If iocharset is
+ not specified then the nls_default specified
+ during the local client kernel build will be used.
+ If server does not support Unicode, this parameter is
+ unused.
+ rsize default read size
+ wsize default write size
+ rw mount the network share read-write (note that the
+ server may still consider the share read-only)
+ ro mount network share read-only
+ version used to distinguish different versions of the
+ mount helper utility (not typically needed)
+ sep if first mount option (after the -o), overrides
+ the comma as the separator between the mount
+ parms. e.g.
+ -o user=myname,password=mypassword,domain=mydom
+ could be passed instead with period as the separator by
+ -o sep=.user=myname.password=mypassword.domain=mydom
+ this might be useful when comma is contained within username
+ or password or domain. This option is less important
+ when the cifs mount helper cifs.mount (version 1.1 or later)
+ is used.
+ nosuid Do not allow remote executables with the suid bit
+ program to be executed. This is only meaningful for mounts
+ to servers such as Samba which support the CIFS Unix Extensions.
+ If you do not trust the servers in your network (your mount
+ targets) it is recommended that you specify this option for
+ greater security.
+ suid Allow remote files on this mountpoint with suid enabled to
+ be executed (default for mounts when executed as root,
+ nosuid is default for user mounts).
+ credentials Although ignored by the cifs kernel component, it is used by
+ the mount helper, mount.cifs. When mount.cifs is installed it
+ opens and reads the credential file specified in order
+ to obtain the userid and password arguments which are passed to
+ the cifs vfs.
+ guest Although ignored by the kernel component, the mount.cifs
+ mount helper will not prompt the user for a password
+ if guest is specified on the mount options. If no
+ password is specified a null password will be used.
+
+The mount.cifs mount helper also accepts a few mount options before -o
+including:
+
+ -S take password from stdin (equivalent to setting the environment
+ variable "PASSWD_FD=0"
+ -V print mount.cifs version
+ -? display simple usage information
+
+With recent 2.6 kernel versions of modutils, the version of the cifs kernel
+module can be displayed via modinfo.
+
+Misc /proc/fs/cifs Flags and Debug Info
+=======================================
+Informational pseudo-files:
+DebugData Displays information about active CIFS sessions
+ and shares.
+Stats Lists summary resource usage information as well as per
+ share statistics, if CONFIG_CIFS_STATS in enabled
+ in the kernel configuration.
+
+Configuration pseudo-files:
+MultiuserMount If set to one, more than one CIFS session to
+ the same server ip address can be established
+ if more than one uid accesses the same mount
+ point and if the uids user/password mapping
+ information is available. (default is 0)
+PacketSigningEnabled If set to one, cifs packet signing is enabled
+ and will be used if the server requires
+ it. If set to two, cifs packet signing is
+ required even if the server considers packet
+ signing optional. (default 1)
+cifsFYI If set to one, additional debug information is
+ logged to the system error log. (default 0)
+ExtendedSecurity If set to one, SPNEGO session establishment
+ is allowed which enables more advanced
+ secure CIFS session establishment (default 0)
+NTLMV2Enabled If set to one, more secure password hashes
+ are used when the server supports them and
+ when kerberos is not negotiated (default 0)
+traceSMB If set to one, debug information is logged to the
+ system error log with the start of smb requests
+ and responses (default 0)
+LookupCacheEnable If set to one, inode information is kept cached
+ for one second improving performance of lookups
+ (default 1)
+OplockEnabled If set to one, safe distributed caching enabled.
+ (default 1)
+LinuxExtensionsEnabled If set to one then the client will attempt to
+ use the CIFS "UNIX" extensions which are optional
+ protocol enhancements that allow CIFS servers
+ to return accurate UID/GID information as well
+ as support symbolic links. If you use servers
+ such as Samba that support the CIFS Unix
+ extensions but do not want to use symbolic link
+ support and want to map the uid and gid fields
+ to values supplied at mount (rather than the
+ actual values, then set this to zero. (default 1)
+
+These experimental features and tracing can be enabled by changing flags in
+/proc/fs/cifs (after the cifs module has been installed or built into the
+kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
+tracing to the kernel message log type:
+
+ echo 1 > /proc/fs/cifs/cifsFYI
+
+and for more extensive tracing including the start of smb requests and responses
+
+ echo 1 > /proc/fs/cifs/traceSMB
+
+Three other experimental features are under development and to test
+require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
+
+ CONFIG_CIFS_QUOTA
+
+ CONFIG_CIFS_XATTR
+
+ CONFIG_CIFS_FCNTL (fcntl needed for support of directory change
+ notification and perhaps later for file leases)
+
+Per share (per client mount) statistics are available in /proc/fs/cifs/DebugData
+if the kernel was configured with cifs statistics enabled. The statistics
+represent the number of successful (ie non-zero return code from the server)
+SMB responses to some of the more common commands (open, delete, mkdir etc.).
+Also recorded is the total bytes read and bytes written to the server for
+that share. Note that due to client caching effects this can be less than the
+number of bytes read and written by the application running on the client.
+The statistics for the number of total SMBs and oplock breaks are different in
+that they represent all for that share, not just those for which the server
+returned success.
+
+Also note that "cat /proc/fs/cifs/DebugData" will display information about
+the active sessions and the shares that are mounted. Note: NTLMv2 enablement
+will not work since they its implementation is not quite complete yet.
+Do not alter these configuration values unless you are doing specific testing.
+Enabling extended security works to Windows 2000 Workstations and XP but not to
+Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
+(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
+complete in the CIFS VFS yet).
diff --git a/release/src/linux/linux/fs/cifs/TODO b/release/src/linux/linux/fs/cifs/TODO
new file mode 100644
index 00000000..51b230e0
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/TODO
@@ -0,0 +1,106 @@
+version 1.16 May 27, 2004
+
+A Partial List of Missing Features
+==================================
+
+Contributions are welcome. There are plenty of opportunities
+for visible, important contributions to this module. Here
+is a partial list of the known problems and missing features:
+
+a) Support for SecurityDescriptors for chmod/chgrp/chown so
+these can be supported for Windows servers
+
+b) Better pam/winbind integration
+
+c) multi-user mounts - multiplexed sessionsetups over single vc
+(ie tcp session) - prettying up needed
+
+d) Kerberos/SPNEGO session setup support - (started)
+
+e) NTLMv2 authentication (mostly implemented)
+
+f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
+used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
+and raw NTLMSSP already. This is important when enabling
+extended security and mounting to Windows 2003 Servers
+
+f) Directory entry caching relies on a 1 second timer, rather than
+using FindNotify or equivalent. - (started)
+
+g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
+style byte range lock differences
+
+h) quota support
+
+i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
+which will allow us to expose dos attributes as well as real
+ACLs. This support has been started in the current code, but is
+ifdeffed out.
+
+k) finish writepages support (multi-page write behind for improved
+performance) and syncpage
+
+l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
+extra copy in/out of the socket buffers in some cases.
+
+m) finish support for IPv6. This is mostly complete but
+needs a simple inet_pton like function to convert ipv6
+addresses in string representation.
+
+o) Better optimize open (and pathbased setfilesize) to reduce the
+oplock breaks coming from windows srv. Piggyback identical file
+opens on top of each other by incrementing reference count rather
+than resending (helps reduce server resource utilization and avoid
+spurious oplock breaks).
+
+p) Improve performance of readpages by sending more than one read
+at a time when 8 pages or more are requested. Evaluate whether
+reads larger than 16K would be helpful.
+
+q) For support of Windows9x/98 we need to retry failed mounts
+to *SMBSERVER (default server name) with the uppercase hostname
+in the RFC1001 session_init request.
+
+r) Add Extended Attributed support (for storing UID/GID info
+to Windows servers)
+
+s) Finish fcntl D_NOTIFY support so kde and gnome file list windows
+will autorefresh
+
+t) Add GUI tool to configure /proc/fs/cifs settings and for display of
+the CIFS statistics
+
+KNOWN BUGS (updated May 27, 2004)
+====================================
+1) existing symbolic links (Windows reparse points) are recognized but
+can not be created remotely. They are implemented for Samba and those that
+support the CIFS Unix extensions but Samba has a bug currently handling
+symlink text beginning with slash
+2) follow_link and readdir code does not follow dfs junctions
+but recognizes them
+3) create of new files to FAT partitions on Windows servers can
+succeed but still return access denied (appears to be Windows
+server not cifs client problem) and has not been reproduced recently.
+NTFS partitions do not have this problem.
+4) debug connectathon lock test case 10 which fails against
+Samba (may be unmappable due to POSIX to Windows lock model
+differences but worth investigating). Also debug Samba to
+see why lock test case 7 takes longer to complete to Samba
+than to Windows.
+
+Misc testing to do
+==================
+1) check out max path names and max path name components against various server
+types. Try nested symlinks. Return max path name in stat -f information
+
+2) Modify file portion of ltp so it can run against a mounted network
+share and run it against cifs vfs.
+
+3) Additional performance testing and optimization using iozone and similar -
+there are some easy changes that can be done to parallelize sequential writes,
+and when signing is disabled to request larger read sizes (larger than
+negotiated size) and send larger write sizes to modern servers.
+
+4) More exhaustively test the recently added NT4 support against various
+NT4 service pack levels.
+
diff --git a/release/src/linux/linux/fs/cifs/asn1.c b/release/src/linux/linux/fs/cifs/asn1.c
new file mode 100644
index 00000000..cf3c0276
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/asn1.c
@@ -0,0 +1,614 @@
+/*
+ * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
+ * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
+ *
+ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+
+/*****************************************************************************
+ *
+ * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
+ *
+ *****************************************************************************/
+
+/* Class */
+#define ASN1_UNI 0 /* Universal */
+#define ASN1_APL 1 /* Application */
+#define ASN1_CTX 2 /* Context */
+#define ASN1_PRV 3 /* Private */
+
+/* Tag */
+#define ASN1_EOC 0 /* End Of Contents or N/A */
+#define ASN1_BOL 1 /* Boolean */
+#define ASN1_INT 2 /* Integer */
+#define ASN1_BTS 3 /* Bit String */
+#define ASN1_OTS 4 /* Octet String */
+#define ASN1_NUL 5 /* Null */
+#define ASN1_OJI 6 /* Object Identifier */
+#define ASN1_OJD 7 /* Object Description */
+#define ASN1_EXT 8 /* External */
+#define ASN1_SEQ 16 /* Sequence */
+#define ASN1_SET 17 /* Set */
+#define ASN1_NUMSTR 18 /* Numerical String */
+#define ASN1_PRNSTR 19 /* Printable String */
+#define ASN1_TEXSTR 20 /* Teletext String */
+#define ASN1_VIDSTR 21 /* Video String */
+#define ASN1_IA5STR 22 /* IA5 String */
+#define ASN1_UNITIM 23 /* Universal Time */
+#define ASN1_GENTIM 24 /* General Time */
+#define ASN1_GRASTR 25 /* Graphical String */
+#define ASN1_VISSTR 26 /* Visible String */
+#define ASN1_GENSTR 27 /* General String */
+
+/* Primitive / Constructed methods*/
+#define ASN1_PRI 0 /* Primitive */
+#define ASN1_CON 1 /* Constructed */
+
+/*
+ * Error codes.
+ */
+#define ASN1_ERR_NOERROR 0
+#define ASN1_ERR_DEC_EMPTY 2
+#define ASN1_ERR_DEC_EOC_MISMATCH 3
+#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
+#define ASN1_ERR_DEC_BADVALUE 5
+
+#define SPNEGO_OID_LEN 7
+#define NTLMSSP_OID_LEN 10
+unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
+unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
+
+/*
+ * ASN.1 context.
+ */
+struct asn1_ctx {
+ int error; /* Error condition */
+ unsigned char *pointer; /* Octet just to be decoded */
+ unsigned char *begin; /* First octet */
+ unsigned char *end; /* Octet after last octet */
+};
+
+/*
+ * Octet string (not null terminated)
+ */
+struct asn1_octstr {
+ unsigned char *data;
+ unsigned int len;
+};
+
+static void
+asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
+{
+ ctx->begin = buf;
+ ctx->end = buf + len;
+ ctx->pointer = buf;
+ ctx->error = ASN1_ERR_NOERROR;
+}
+
+static unsigned char
+asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
+{
+ if (ctx->pointer >= ctx->end) {
+ ctx->error = ASN1_ERR_DEC_EMPTY;
+ return 0;
+ }
+ *ch = *(ctx->pointer)++;
+ return 1;
+}
+
+static unsigned char
+asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
+{
+ unsigned char ch;
+
+ *tag = 0;
+
+ do {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+ *tag <<= 7;
+ *tag |= ch & 0x7F;
+ } while ((ch & 0x80) == 0x80);
+ return 1;
+}
+
+static unsigned char
+asn1_id_decode(struct asn1_ctx *ctx,
+ unsigned int *cls, unsigned int *con, unsigned int *tag)
+{
+ unsigned char ch;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *cls = (ch & 0xC0) >> 6;
+ *con = (ch & 0x20) >> 5;
+ *tag = (ch & 0x1F);
+
+ if (*tag == 0x1F) {
+ if (!asn1_tag_decode(ctx, tag))
+ return 0;
+ }
+ return 1;
+}
+
+static unsigned char
+asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
+{
+ unsigned char ch, cnt;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ if (ch == 0x80)
+ *def = 0;
+ else {
+ *def = 1;
+
+ if (ch < 0x80)
+ *len = ch;
+ else {
+ cnt = (unsigned char) (ch & 0x7F);
+ *len = 0;
+
+ while (cnt > 0) {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+ *len <<= 8;
+ *len |= ch;
+ cnt--;
+ }
+ }
+ }
+ return 1;
+}
+
+static unsigned char
+asn1_header_decode(struct asn1_ctx *ctx,
+ unsigned char **eoc,
+ unsigned int *cls, unsigned int *con, unsigned int *tag)
+{
+ unsigned int def, len;
+
+ if (!asn1_id_decode(ctx, cls, con, tag))
+ return 0;
+
+ if (!asn1_length_decode(ctx, &def, &len))
+ return 0;
+
+ if (def)
+ *eoc = ctx->pointer + len;
+ else
+ *eoc = NULL;
+ return 1;
+}
+
+static unsigned char
+asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
+{
+ unsigned char ch;
+
+ if (eoc == 0) {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ if (ch != 0x00) {
+ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ if (ch != 0x00) {
+ ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
+ return 0;
+ }
+ return 1;
+ } else {
+ if (ctx->pointer != eoc) {
+ ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
+ return 0;
+ }
+ return 1;
+ }
+}
+
+/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc)
+{
+ ctx->pointer = eoc;
+ return 1;
+}
+
+static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc, long *integer)
+{
+ unsigned char ch;
+ unsigned int len;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer = (signed char) ch;
+ len = 1;
+
+ while (ctx->pointer < eoc) {
+ if (++len > sizeof(long)) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer <<= 8;
+ *integer |= ch;
+ }
+ return 1;
+}
+
+static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ unsigned int *integer)
+{
+ unsigned char ch;
+ unsigned int len;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer = ch;
+ if (ch == 0)
+ len = 0;
+ else
+ len = 1;
+
+ while (ctx->pointer < eoc) {
+ if (++len > sizeof(unsigned int)) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer <<= 8;
+ *integer |= ch;
+ }
+ return 1;
+}
+
+static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ unsigned long *integer)
+{
+ unsigned char ch;
+ unsigned int len;
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer = ch;
+ if (ch == 0)
+ len = 0;
+ else
+ len = 1;
+
+ while (ctx->pointer < eoc) {
+ if (++len > sizeof(unsigned long)) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ return 0;
+ }
+
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *integer <<= 8;
+ *integer |= ch;
+ }
+ return 1;
+}
+
+static unsigned char
+asn1_octets_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc,
+ unsigned char **octets, unsigned int *len)
+{
+ unsigned char *ptr;
+
+ *len = 0;
+
+ *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
+ if (*octets == NULL) {
+ return 0;
+ }
+
+ ptr = *octets;
+ while (ctx->pointer < eoc) {
+ if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
+ kfree(*octets);
+ *octets = NULL;
+ return 0;
+ }
+ (*len)++;
+ }
+ return 1;
+} */
+
+static unsigned char
+asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
+{
+ unsigned char ch;
+
+ *subid = 0;
+
+ do {
+ if (!asn1_octet_decode(ctx, &ch))
+ return 0;
+
+ *subid <<= 7;
+ *subid |= ch & 0x7F;
+ } while ((ch & 0x80) == 0x80);
+ return 1;
+}
+
+static unsigned char
+asn1_oid_decode(struct asn1_ctx *ctx,
+ unsigned char *eoc, unsigned long **oid, unsigned int *len)
+{
+ unsigned long subid;
+ unsigned int size;
+ unsigned long *optr;
+
+ size = eoc - ctx->pointer + 1;
+ *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
+ if (*oid == NULL) {
+ return 0;
+ }
+
+ optr = *oid;
+
+ if (!asn1_subid_decode(ctx, &subid)) {
+ kfree(*oid);
+ *oid = NULL;
+ return 0;
+ }
+
+ if (subid < 40) {
+ optr[0] = 0;
+ optr[1] = subid;
+ } else if (subid < 80) {
+ optr[0] = 1;
+ optr[1] = subid - 40;
+ } else {
+ optr[0] = 2;
+ optr[1] = subid - 80;
+ }
+
+ *len = 2;
+ optr += 2;
+
+ while (ctx->pointer < eoc) {
+ if (++(*len) > size) {
+ ctx->error = ASN1_ERR_DEC_BADVALUE;
+ kfree(*oid);
+ *oid = NULL;
+ return 0;
+ }
+
+ if (!asn1_subid_decode(ctx, optr++)) {
+ kfree(*oid);
+ *oid = NULL;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+compare_oid(unsigned long *oid1, unsigned int oid1len,
+ unsigned long *oid2, unsigned int oid2len)
+{
+ unsigned int i;
+
+ if (oid1len != oid2len)
+ return 0;
+ else {
+ for (i = 0; i < oid1len; i++) {
+ if (oid1[i] != oid2[i])
+ return 0;
+ }
+ return 1;
+ }
+}
+
+ /* BB check for endian conversion issues here */
+
+int
+decode_negTokenInit(unsigned char *security_blob, int length,
+ enum securityEnum *secType)
+{
+ struct asn1_ctx ctx;
+ unsigned char *end;
+ unsigned char *sequence_end;
+ unsigned long *oid;
+ unsigned int cls, con, tag, oidlen, rc;
+ int use_ntlmssp = FALSE;
+
+ *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
+
+ /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
+
+ asn1_open(&ctx, security_blob, length);
+
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1, ("Error decoding negTokenInit header "));
+ return 0;
+ } else if ((cls != ASN1_APL) || (con != ASN1_CON)
+ || (tag != ASN1_EOC)) {
+ cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
+ return 0;
+ } else {
+ /* remember to free obj->oid */
+ rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
+ if (rc) {
+ if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
+ rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
+ if (rc) {
+ rc = compare_oid(oid, oidlen,
+ SPNEGO_OID,
+ SPNEGO_OID_LEN);
+ kfree(oid);
+ }
+ } else
+ rc = 0;
+ }
+
+ if (!rc) {
+ cFYI(1, ("Error decoding negTokenInit header"));
+ return 0;
+ }
+
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1, ("Error decoding negTokenInit "));
+ return 0;
+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
+ || (tag != ASN1_EOC)) {
+ cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
+ cls, con, tag, end, *end));
+ return 0;
+ }
+
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1, ("Error decoding negTokenInit "));
+ return 0;
+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
+ || (tag != ASN1_SEQ)) {
+ cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
+ cls, con, tag, end, *end));
+ return 0;
+ }
+
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1, ("Error decoding 2nd part of negTokenInit "));
+ return 0;
+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
+ || (tag != ASN1_EOC)) {
+ cFYI(1,
+ ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
+ cls, con, tag, end, *end));
+ return 0;
+ }
+
+ if (asn1_header_decode
+ (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
+ cFYI(1, ("Error decoding 2nd part of negTokenInit "));
+ return 0;
+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
+ || (tag != ASN1_SEQ)) {
+ cFYI(1,
+ ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
+ cls, con, tag, end, *end));
+ return 0;
+ }
+
+ while (!asn1_eoc_decode(&ctx, sequence_end)) {
+ rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
+ if (!rc) {
+ cFYI(1,
+ ("Error 1 decoding negTokenInit header exit 2"));
+ return 0;
+ }
+ if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
+ asn1_oid_decode(&ctx, end, &oid, &oidlen);
+ cFYI(1,
+ ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
+ oidlen, *oid, *(oid + 1), *(oid + 2),
+ *(oid + 3)));
+ rc = compare_oid(oid, oidlen, NTLMSSP_OID,
+ NTLMSSP_OID_LEN);
+ kfree(oid);
+ if (rc)
+ use_ntlmssp = TRUE;
+ } else {
+ cFYI(1,("This should be an oid what is going on? "));
+ }
+ }
+
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1,
+ ("Error decoding last part of negTokenInit exit 3"));
+ return 0;
+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
+ cFYI(1,
+ ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end));
+ return 0;
+ }
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1,
+ ("Error decoding last part of negTokenInit exit 5"));
+ return 0;
+ } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
+ || (tag != ASN1_SEQ)) {
+ cFYI(1,
+ ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end));
+ }
+
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1,
+ ("Error decoding last part of negTokenInit exit 7"));
+ return 0;
+ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
+ cFYI(1,
+ ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end));
+ return 0;
+ }
+ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+ cFYI(1,
+ ("Error decoding last part of negTokenInit exit 9"));
+ return 0;
+ } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
+ || (tag != ASN1_GENSTR)) {
+ cFYI(1,
+ ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end));
+ return 0;
+ }
+ cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
+ }
+
+ /* if (use_kerberos)
+ *secType = Kerberos
+ else */
+ if (use_ntlmssp) {
+ *secType = NTLMSSP;
+ }
+
+ return 1;
+}
diff --git a/release/src/linux/linux/fs/cifs/cifs_debug.c b/release/src/linux/linux/fs/cifs/cifs_debug.c
new file mode 100644
index 00000000..bdcca609
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifs_debug.c
@@ -0,0 +1,797 @@
+/*
+ * fs/cifs_debug.c
+ *
+ * Copyright (C) International Business Machines Corp., 2000,2003
+ *
+ * Modified by Steve French (sfrench@us.ibm.com)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+void
+cifs_dump_mem(char *label, void *data, int length)
+{
+ int i, j;
+ int *intptr = data;
+ char *charptr = data;
+ char buf[10], line[80];
+
+ printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
+ label, length, data);
+ for (i = 0; i < length; i += 16) {
+ line[0] = 0;
+ for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
+ sprintf(buf, " %08x", intptr[i / 4 + j]);
+ strcat(line, buf);
+ }
+ buf[0] = ' ';
+ buf[2] = 0;
+ for (j = 0; (j < 16) && (i + j < length); j++) {
+ buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
+ strcat(line, buf);
+ }
+ printk(KERN_DEBUG "%s\n", line);
+ }
+}
+
+#ifdef CONFIG_PROC_FS
+int
+cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
+ int count, int *eof, void *data)
+{
+ struct list_head *tmp;
+ struct list_head *tmp1;
+ struct mid_q_entry * mid_entry;
+ struct cifsSesInfo *ses;
+ struct cifsTconInfo *tcon;
+ int i;
+ int length = 0;
+ char * original_buf = buf;
+
+ *beginBuffer = buf + offset;
+
+
+ length =
+ sprintf(buf,
+ "Display Internal CIFS Data Structures for Debugging\n"
+ "---------------------------------------------------\n");
+ buf += length;
+
+ length = sprintf(buf, "Servers:\n");
+ buf += length;
+
+ i = 0;
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &GlobalSMBSessionList) {
+ i++;
+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
+ length =
+ sprintf(buf,
+ "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d",
+ i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
+ ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
+ buf += length;
+ if(ses->server) {
+ buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
+ atomic_read(&ses->server->socketUseCount),
+ ses->server->secMode,
+ atomic_read(&ses->server->inFlight));
+
+ length = sprintf(buf, "\nMIDs: \n");
+ buf += length;
+
+ spin_lock(&GlobalMid_Lock);
+ list_for_each(tmp1, &ses->server->pending_mid_q) {
+ mid_entry = list_entry(tmp1, struct
+ mid_q_entry,
+ qhead);
+ if(mid_entry) {
+ length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid);
+ buf += length;
+ }
+ }
+ spin_unlock(&GlobalMid_Lock);
+ }
+
+ }
+ read_unlock(&GlobalSMBSeslock);
+ sprintf(buf, "\n");
+ buf++;
+
+ length = sprintf(buf, "\nShares:\n");
+ buf += length;
+
+ i = 0;
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &GlobalTreeConnectionList) {
+ i++;
+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+ length =
+ sprintf(buf,
+ "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
+ i, tcon->treeName,
+ atomic_read(&tcon->useCount),
+ tcon->nativeFileSystem,
+ tcon->fsDevInfo.DeviceCharacteristics,
+ tcon->fsAttrInfo.Attributes,
+ tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
+ buf += length;
+ if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
+ length = sprintf(buf, " type: DISK ");
+ else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
+ length = sprintf(buf, " type: CDROM ");
+ else
+ length =
+ sprintf(buf, " type: %d ",
+ tcon->fsDevInfo.DeviceType);
+ buf += length;
+ if(tcon->tidStatus == CifsNeedReconnect) {
+ buf += sprintf(buf, "\tDISCONNECTED ");
+ length += 14;
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+
+ length = sprintf(buf, "\n");
+ buf += length;
+
+ /* BB add code to dump additional info such as TCP session info now */
+ /* Now calculate total size of returned data */
+ length = buf - original_buf;
+
+ if(offset + count >= length)
+ *eof = 1;
+ if(length < offset) {
+ *eof = 1;
+ return 0;
+ } else {
+ length = length - offset;
+ }
+ if (length > count)
+ length = count;
+
+ return length;
+}
+
+#ifdef CONFIG_CIFS_STATS
+int
+cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
+ int count, int *eof, void *data)
+{
+ int item_length,i,length;
+ struct list_head *tmp;
+ struct cifsTconInfo *tcon;
+
+ *beginBuffer = buf + offset;
+
+ length = sprintf(buf,
+ "Resources in use\nCIFS Session: %d\n",
+ sesInfoAllocCount.counter);
+ buf += length;
+ item_length =
+ sprintf(buf,"Share (unique mount targets): %d\n",
+ tconInfoAllocCount.counter);
+ length += item_length;
+ buf += item_length;
+ item_length =
+ sprintf(buf,"SMB Request/Response Buffer: %d\n",
+ bufAllocCount.counter);
+ length += item_length;
+ buf += item_length;
+ item_length =
+ sprintf(buf,"Operations (MIDs): %d\n",
+ midCount.counter);
+ length += item_length;
+ buf += item_length;
+ item_length = sprintf(buf,
+ "\n%d session %d share reconnects\n",
+ tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
+ length += item_length;
+ buf += item_length;
+
+ item_length = sprintf(buf,
+ "Total vfs operations: %d maximum at one time: %d\n",
+ GlobalCurrentXid,GlobalMaxActiveXid);
+ length += item_length;
+ buf += item_length;
+
+ i = 0;
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &GlobalTreeConnectionList) {
+ i++;
+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+ item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
+ buf += item_length;
+ length += item_length;
+ if(tcon->tidStatus == CifsNeedReconnect) {
+ buf += sprintf(buf, "\tDISCONNECTED ");
+ length += 14;
+ }
+ item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
+ atomic_read(&tcon->num_smbs_sent),
+ atomic_read(&tcon->num_oplock_brks));
+ buf += item_length;
+ length += item_length;
+ item_length = sprintf(buf,"\nReads: %d Bytes %lld",
+ atomic_read(&tcon->num_reads),
+ (long long)(tcon->bytes_read));
+ buf += item_length;
+ length += item_length;
+ item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
+ atomic_read(&tcon->num_writes),
+ (long long)(tcon->bytes_written));
+ buf += item_length;
+ length += item_length;
+ item_length = sprintf(buf,
+ "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
+ atomic_read(&tcon->num_opens),
+ atomic_read(&tcon->num_deletes),
+ atomic_read(&tcon->num_mkdirs),
+ atomic_read(&tcon->num_rmdirs));
+ buf += item_length;
+ length += item_length;
+ item_length = sprintf(buf,
+ "\nRenames: %d T2 Renames %d",
+ atomic_read(&tcon->num_renames),
+ atomic_read(&tcon->num_t2renames));
+ buf += item_length;
+ length += item_length;
+ }
+ read_unlock(&GlobalSMBSeslock);
+
+ buf += sprintf(buf,"\n");
+ length++;
+
+ if(offset + count >= length)
+ *eof = 1;
+ if(length < offset) {
+ *eof = 1;
+ return 0;
+ } else {
+ length = length - offset;
+ }
+ if (length > count)
+ length = count;
+
+ return length;
+}
+#endif
+
+struct proc_dir_entry *proc_fs_cifs;
+read_proc_t cifs_txanchor_read;
+static read_proc_t cifsFYI_read;
+static write_proc_t cifsFYI_write;
+static read_proc_t oplockEnabled_read;
+static write_proc_t oplockEnabled_write;
+static read_proc_t lookupFlag_read;
+static write_proc_t lookupFlag_write;
+static read_proc_t traceSMB_read;
+static write_proc_t traceSMB_write;
+static read_proc_t multiuser_mount_read;
+static write_proc_t multiuser_mount_write;
+static read_proc_t extended_security_read;
+static write_proc_t extended_security_write;
+static read_proc_t ntlmv2_enabled_read;
+static write_proc_t ntlmv2_enabled_write;
+static read_proc_t packet_signing_enabled_read;
+static write_proc_t packet_signing_enabled_write;
+static read_proc_t quotaEnabled_read;
+static write_proc_t quotaEnabled_write;
+static read_proc_t linuxExtensionsEnabled_read;
+static write_proc_t linuxExtensionsEnabled_write;
+
+void
+cifs_proc_init(void)
+{
+ struct proc_dir_entry *pde;
+
+ proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
+ if (proc_fs_cifs == NULL)
+ return;
+
+ proc_fs_cifs->owner = THIS_MODULE;
+ create_proc_read_entry("DebugData", 0, proc_fs_cifs,
+ cifs_debug_data_read, NULL);
+
+#ifdef CONFIG_CIFS_STATS
+ create_proc_read_entry("Stats", 0, proc_fs_cifs,
+ cifs_stats_read, NULL);
+#endif
+ pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
+ cifsFYI_read, NULL);
+ if (pde)
+ pde->write_proc = cifsFYI_write;
+
+ pde =
+ create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
+ traceSMB_read, NULL);
+ if (pde)
+ pde->write_proc = traceSMB_write;
+
+ pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
+ oplockEnabled_read, NULL);
+ if (pde)
+ pde->write_proc = oplockEnabled_write;
+
+ pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
+ quotaEnabled_read, NULL);
+ if (pde)
+ pde->write_proc = quotaEnabled_write;
+
+ pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
+ linuxExtensionsEnabled_read, NULL);
+ if (pde)
+ pde->write_proc = linuxExtensionsEnabled_write;
+
+ pde =
+ create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
+ multiuser_mount_read, NULL);
+ if (pde)
+ pde->write_proc = multiuser_mount_write;
+
+ pde =
+ create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
+ extended_security_read, NULL);
+ if (pde)
+ pde->write_proc = extended_security_write;
+
+ pde =
+ create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
+ lookupFlag_read, NULL);
+ if (pde)
+ pde->write_proc = lookupFlag_write;
+
+ pde =
+ create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
+ ntlmv2_enabled_read, NULL);
+ if (pde)
+ pde->write_proc = ntlmv2_enabled_write;
+
+ pde =
+ create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
+ packet_signing_enabled_read, NULL);
+ if (pde)
+ pde->write_proc = packet_signing_enabled_write;
+}
+
+void
+cifs_proc_clean(void)
+{
+ if (proc_fs_cifs == NULL)
+ return;
+
+ remove_proc_entry("DebugData", proc_fs_cifs);
+ remove_proc_entry("cifsFYI", proc_fs_cifs);
+ remove_proc_entry("traceSMB", proc_fs_cifs);
+#ifdef CONFIG_CIFS_STATS
+ remove_proc_entry("Stats", proc_fs_cifs);
+#endif
+ remove_proc_entry("MultiuserMount", proc_fs_cifs);
+ remove_proc_entry("OplockEnabled", proc_fs_cifs);
+ remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
+ remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
+ remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
+ remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
+ remove_proc_entry("QuotaEnabled",proc_fs_cifs);
+ remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
+ remove_proc_entry("cifs", proc_root_fs);
+}
+
+static int
+cifsFYI_read(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", cifsFYI);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+cifsFYI_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ cifsFYI = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ cifsFYI = 1;
+
+ return count;
+}
+
+static int
+oplockEnabled_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", oplockEnabled);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+oplockEnabled_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ oplockEnabled = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ oplockEnabled = 1;
+
+ return count;
+}
+
+static int
+quotaEnabled_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", quotaEnabled);
+/* could also check if quotas are enabled in kernel
+ as a whole first */
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+quotaEnabled_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ quotaEnabled = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ quotaEnabled = 1;
+
+ return count;
+}
+
+static int
+linuxExtensionsEnabled_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", linuxExtEnabled);
+/* could also check if quotas are enabled in kernel
+ as a whole first */
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+linuxExtensionsEnabled_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ linuxExtEnabled = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ linuxExtEnabled = 1;
+
+ return count;
+}
+
+
+static int
+lookupFlag_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", lookupCacheEnabled);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+lookupFlag_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ lookupCacheEnabled = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ lookupCacheEnabled = 1;
+
+ return count;
+}
+static int
+traceSMB_read(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", traceSMB);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+traceSMB_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ traceSMB = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ traceSMB = 1;
+
+ return count;
+}
+
+static int
+multiuser_mount_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", multiuser_mount);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+multiuser_mount_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ multiuser_mount = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ multiuser_mount = 1;
+
+ return count;
+}
+
+static int
+extended_security_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", extended_security);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+extended_security_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ extended_security = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ extended_security = 1;
+
+ return count;
+}
+
+static int
+ntlmv2_enabled_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", ntlmv2_support);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+ntlmv2_enabled_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ ntlmv2_support = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ ntlmv2_support = 1;
+
+ return count;
+}
+
+static int
+packet_signing_enabled_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(page, "%d\n", sign_CIFS_PDUs);
+
+ len -= off;
+ *start = page + off;
+
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+static int
+packet_signing_enabled_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ sign_CIFS_PDUs = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ sign_CIFS_PDUs = 1;
+ else if (c == '2')
+ sign_CIFS_PDUs = 2;
+
+ return count;
+}
+
+
+#endif
diff --git a/release/src/linux/linux/fs/cifs/cifs_debug.h b/release/src/linux/linux/fs/cifs/cifs_debug.h
new file mode 100644
index 00000000..bf24d282
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifs_debug.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2002
+ * Modified by Steve French (sfrench@us.ibm.com)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+#define CIFS_DEBUG /* BB temporary */
+
+#ifndef _H_CIFS_DEBUG
+#define _H_CIFS_DEBUG
+
+void cifs_dump_mem(char *label, void *data, int length);
+extern int traceSMB; /* flag which enables the function below */
+void dump_smb(struct smb_hdr *, int);
+
+/*
+ * debug ON
+ * --------
+ */
+#ifdef CIFS_DEBUG
+
+
+/* information message: e.g., configuration, major event */
+extern int cifsFYI;
+#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
+
+#define cFYI(button,prspec) if (button) cifsfyi prspec
+
+#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
+
+/* debug event message: */
+extern int cifsERROR;
+
+#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
+
+/* error event message: e.g., i/o error */
+#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
+
+#define cERROR(button, prspec) if (button) cifserror prspec
+
+/*
+ * debug OFF
+ * ---------
+ */
+#else /* _CIFS_DEBUG */
+#define cERROR(button,prspec)
+#define cEVENT(format,arg...)
+#define cFYI(button, prspec)
+#define cifserror(format,arg...)
+#endif /* _CIFS_DEBUG */
+
+#endif /* _H_CIFS_DEBUG */
diff --git a/release/src/linux/linux/fs/cifs/cifs_fs_sb.h b/release/src/linux/linux/fs/cifs/cifs_fs_sb.h
new file mode 100644
index 00000000..8007c2e9
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifs_fs_sb.h
@@ -0,0 +1,32 @@
+/*
+ * fs/cifs/cifs_fs_sb.h
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ */
+#ifndef _CIFS_FS_SB_H
+#define _CIFS_FS_SB_H
+
+struct cifs_sb_info {
+ struct cifsTconInfo *tcon; /* primary mount */
+ struct list_head nested_tcon_q;
+ struct nls_table *local_nls;
+ unsigned int rsize;
+ unsigned int wsize;
+ uid_t mnt_uid;
+ gid_t mnt_gid;
+ mode_t mnt_file_mode;
+ mode_t mnt_dir_mode;
+};
+#endif /* _CIFS_FS_SB_H */
diff --git a/release/src/linux/linux/fs/cifs/cifs_unicode.c b/release/src/linux/linux/fs/cifs/cifs_unicode.c
new file mode 100644
index 00000000..a17adf4c
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifs_unicode.c
@@ -0,0 +1,87 @@
+/*
+ * fs/cifs/cifs_unicode.c
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2002
+ * Modified by Steve French (sfrench@us.ibm.com)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include "cifs_unicode.h"
+#include "cifs_uniupr.h"
+#include "cifspdu.h"
+#include "cifs_debug.h"
+
+/*
+ * NAME: cifs_strfromUCS()
+ *
+ * FUNCTION: Convert little-endian unicode string to character string
+ *
+ */
+int
+cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
+ int len, const struct nls_table *codepage)
+{
+ int i;
+ int outlen = 0;
+
+ for (i = 0; (i < len) && from[i]; i++) {
+ int charlen;
+ /* 2.4.0 kernel or greater */
+ charlen =
+ codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
+ NLS_MAX_CHARSET_SIZE);
+ if (charlen > 0) {
+ outlen += charlen;
+ } else {
+ to[outlen++] = '?';
+ }
+ }
+ to[outlen] = 0;
+ return outlen;
+}
+
+/*
+ * NAME: cifs_strtoUCS()
+ *
+ * FUNCTION: Convert character string to unicode string
+ *
+ */
+int
+cifs_strtoUCS(wchar_t * to, const char *from, int len,
+ const struct nls_table *codepage)
+{
+ int charlen;
+ int i;
+
+ for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
+
+ /* works for 2.4.0 kernel or later */
+ charlen = codepage->char2uni(from, len, &to[i]);
+ if (charlen < 1) {
+ cERROR(1,
+ ("cifs_strtoUCS: char2uni returned %d",
+ charlen));
+ to[i] = cpu_to_le16(0x003f); /* a question mark */
+ charlen = 1;
+ }
+ to[i] = cpu_to_le16(to[i]);
+
+ }
+
+ to[i] = 0;
+ return i;
+}
+
diff --git a/release/src/linux/linux/fs/cifs/cifs_unicode.h b/release/src/linux/linux/fs/cifs/cifs_unicode.h
new file mode 100644
index 00000000..da8dde96
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifs_unicode.h
@@ -0,0 +1,353 @@
+/*
+ * cifs_unicode: Unicode kernel case support
+ *
+ * Function:
+ * Convert a unicode character to upper or lower case using
+ * compressed tables.
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2002
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * Notes:
+ * These APIs are based on the C library functions. The semantics
+ * should match the C functions but with expanded size operands.
+ *
+ * The upper/lower functions are based on a table created by mkupr.
+ * This is a compressed table of upper and lower case conversion.
+ *
+ */
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/nls.h>
+
+#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
+
+/* Just define what we want from uniupr.h. We don't want to define the tables
+ * in each source file.
+ */
+#ifndef UNICASERANGE_DEFINED
+struct UniCaseRange {
+ wchar_t start;
+ wchar_t end;
+ signed char *table;
+};
+#endif /* UNICASERANGE_DEFINED */
+
+#ifndef UNIUPR_NOUPPER
+extern signed char CifsUniUpperTable[512];
+extern const struct UniCaseRange CifsUniUpperRange[];
+#endif /* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+extern signed char UniLowerTable[512];
+extern struct UniCaseRange UniLowerRange[];
+#endif /* UNIUPR_NOLOWER */
+
+#ifdef __KERNEL__
+int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
+int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
+#endif
+
+/*
+ * UniStrcat: Concatenate the second string to the first
+ *
+ * Returns:
+ * Address of the first string
+ */
+static inline wchar_t *
+UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
+{
+ wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
+
+ while (*ucs1++) ; /* To end of first string */
+ ucs1--; /* Return to the null */
+ while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
+ return anchor;
+}
+
+/*
+ * UniStrchr: Find a character in a string
+ *
+ * Returns:
+ * Address of first occurrence of character in string
+ * or NULL if the character is not in the string
+ */
+static inline wchar_t *
+UniStrchr(const wchar_t * ucs, wchar_t uc)
+{
+ while ((*ucs != uc) && *ucs)
+ ucs++;
+
+ if (*ucs == uc)
+ return (wchar_t *) ucs;
+ return NULL;
+}
+
+/*
+ * UniStrcmp: Compare two strings
+ *
+ * Returns:
+ * < 0: First string is less than second
+ * = 0: Strings are equal
+ * > 0: First string is greater than second
+ */
+static inline int
+UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
+{
+ while ((*ucs1 == *ucs2) && *ucs1) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int) *ucs1 - (int) *ucs2;
+}
+
+/*
+ * UniStrcpy: Copy a string
+ */
+static inline wchar_t *
+UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
+{
+ wchar_t *anchor = ucs1; /* save the start of result string */
+
+ while ((*ucs1++ = *ucs2++)) ;
+ return anchor;
+}
+
+/*
+ * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
+ */
+static inline size_t
+UniStrlen(const wchar_t * ucs1)
+{
+ int i = 0;
+
+ while (*ucs1++)
+ i++;
+ return i;
+}
+
+/*
+ * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
+ */
+static inline size_t
+UniStrnlen(const wchar_t * ucs1, int maxlen)
+{
+ int i = 0;
+
+ while (*ucs1++) {
+ i++;
+ if (i >= maxlen)
+ break;
+ }
+ return i;
+}
+
+/*
+ * UniStrncat: Concatenate length limited string
+ */
+static inline wchar_t *
+UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1; /* save pointer to string 1 */
+
+ while (*ucs1++) ;
+ ucs1--; /* point to null terminator of s1 */
+ while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
+ ucs1++;
+ ucs2++;
+ }
+ *ucs1 = 0; /* Null terminate the result */
+ return (anchor);
+}
+
+/*
+ * UniStrncmp: Compare length limited string
+ */
+static inline int
+UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+ if (!n)
+ return 0; /* Null strings are equal */
+ while ((*ucs1 == *ucs2) && *ucs1 && --n) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int) *ucs1 - (int) *ucs2;
+}
+
+/*
+ * UniStrncmp_le: Compare length limited string - native to little-endian
+ */
+static inline int
+UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+ if (!n)
+ return 0; /* Null strings are equal */
+ while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
+}
+
+/*
+ * UniStrncpy: Copy length limited string with pad
+ */
+static inline wchar_t *
+UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1;
+
+ while (n-- && *ucs2) /* Copy the strings */
+ *ucs1++ = *ucs2++;
+
+ n++;
+ while (n--) /* Pad with nulls */
+ *ucs1++ = 0;
+ return anchor;
+}
+
+/*
+ * UniStrncpy_le: Copy length limited string with pad to little-endian
+ */
+static inline wchar_t *
+UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1;
+
+ while (n-- && *ucs2) /* Copy the strings */
+ *ucs1++ = __le16_to_cpu(*ucs2++);
+
+ n++;
+ while (n--) /* Pad with nulls */
+ *ucs1++ = 0;
+ return anchor;
+}
+
+/*
+ * UniStrstr: Find a string in a string
+ *
+ * Returns:
+ * Address of first match found
+ * NULL if no matching string is found
+ */
+static inline wchar_t *
+UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
+{
+ const wchar_t *anchor1 = ucs1;
+ const wchar_t *anchor2 = ucs2;
+
+ while (*ucs1) {
+ if (*ucs1 == *ucs2) { /* Partial match found */
+ ucs1++;
+ ucs2++;
+ } else {
+ if (!*ucs2) /* Match found */
+ return (wchar_t *) anchor1;
+ ucs1 = ++anchor1; /* No match */
+ ucs2 = anchor2;
+ }
+ }
+
+ if (!*ucs2) /* Both end together */
+ return (wchar_t *) anchor1; /* Match found */
+ return NULL; /* No match */
+}
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * UniToupper: Convert a unicode character to upper case
+ */
+static inline wchar_t
+UniToupper(register wchar_t uc)
+{
+ register const struct UniCaseRange *rp;
+
+ if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */
+ return uc + CifsUniUpperTable[uc]; /* Use base tables */
+ } else {
+ rp = CifsUniUpperRange; /* Use range tables */
+ while (rp->start) {
+ if (uc < rp->start) /* Before start of range */
+ return uc; /* Uppercase = input */
+ if (uc <= rp->end) /* In range */
+ return uc + rp->table[uc - rp->start];
+ rp++; /* Try next range */
+ }
+ }
+ return uc; /* Past last range */
+}
+
+/*
+ * UniStrupr: Upper case a unicode string
+ */
+static inline wchar_t *
+UniStrupr(register wchar_t * upin)
+{
+ register wchar_t *up;
+
+ up = upin;
+ while (*up) { /* For all characters */
+ *up = UniToupper(*up);
+ up++;
+ }
+ return upin; /* Return input pointer */
+}
+#endif /* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * UniTolower: Convert a unicode character to lower case
+ */
+static inline wchar_t
+UniTolower(wchar_t uc)
+{
+ register struct UniCaseRange *rp;
+
+ if (uc < sizeof (UniLowerTable)) { /* Latin characters */
+ return uc + UniLowerTable[uc]; /* Use base tables */
+ } else {
+ rp = UniLowerRange; /* Use range tables */
+ while (rp->start) {
+ if (uc < rp->start) /* Before start of range */
+ return uc; /* Uppercase = input */
+ if (uc <= rp->end) /* In range */
+ return uc + rp->table[uc - rp->start];
+ rp++; /* Try next range */
+ }
+ }
+ return uc; /* Past last range */
+}
+
+/*
+ * UniStrlwr: Lower case a unicode string
+ */
+static inline wchar_t *
+UniStrlwr(register wchar_t * upin)
+{
+ register wchar_t *up;
+
+ up = upin;
+ while (*up) { /* For all characters */
+ *up = UniTolower(*up);
+ up++;
+ }
+ return upin; /* Return input pointer */
+}
+
+#endif
diff --git a/release/src/linux/linux/fs/cifs/cifs_uniupr.h b/release/src/linux/linux/fs/cifs/cifs_uniupr.h
new file mode 100644
index 00000000..272d72df
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifs_uniupr.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2000,2002
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * uniupr.h - Unicode compressed case ranges
+ *
+*/
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * Latin upper case
+ */
+signed char CifsUniUpperTable[512] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
+ -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
+ 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
+ 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
+ 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
+ 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
+ -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
+ 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
+ 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
+};
+
+/* Upper case range - Greek */
+static signed char UniCaseRangeU03a0[47] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
+ -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
+ -63, -63,
+};
+
+/* Upper case range - Cyrillic */
+static signed char UniCaseRangeU0430[48] = {
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
+ 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
+};
+
+/* Upper case range - Extended cyrillic */
+static signed char UniCaseRangeU0490[61] = {
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
+ 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
+};
+
+/* Upper case range - Extended latin and greek */
+static signed char UniCaseRangeU1e00[509] = {
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
+ 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
+ 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
+ 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
+ 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
+ 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
+ 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Upper case range - Wide latin */
+static signed char UniCaseRangeUff40[27] = {
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+};
+
+/*
+ * Upper Case Range
+ */
+const struct UniCaseRange CifsUniUpperRange[] = {
+ {0x03a0, 0x03ce, UniCaseRangeU03a0},
+ {0x0430, 0x045f, UniCaseRangeU0430},
+ {0x0490, 0x04cc, UniCaseRangeU0490},
+ {0x1e00, 0x1ffc, UniCaseRangeU1e00},
+ {0xff40, 0xff5a, UniCaseRangeUff40},
+ {0, 0, NULL}
+};
+#endif
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * Latin lower case
+ */
+static signed char CifsUniLowerTable[512] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
+ 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
+ 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
+ 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
+ 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
+ 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
+ 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
+ 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
+ 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
+ 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
+};
+
+/* Lower case range - Greek */
+static signed char UniCaseRangeL0380[44] = {
+ 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
+ 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/* Lower case range - Cyrillic */
+static signed char UniCaseRangeL0400[48] = {
+ 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
+};
+
+/* Lower case range - Extended cyrillic */
+static signed char UniCaseRangeL0490[60] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
+ 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
+};
+
+/* Lower case range - Extended latin and greek */
+static signed char UniCaseRangeL1e00[504] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
+ 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Lower case range - Wide latin */
+static signed char UniCaseRangeLff20[27] = {
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/*
+ * Lower Case Range
+ */
+const static struct UniCaseRange CifsUniLowerRange[] = {
+ 0x0380, 0x03ab, UniCaseRangeL0380,
+ 0x0400, 0x042f, UniCaseRangeL0400,
+ 0x0490, 0x04cb, UniCaseRangeL0490,
+ 0x1e00, 0x1ff7, UniCaseRangeL1e00,
+ 0xff20, 0xff3a, UniCaseRangeLff20,
+ 0, 0, 0
+};
+#endif
diff --git a/release/src/linux/linux/fs/cifs/cifsencrypt.c b/release/src/linux/linux/fs/cifs/cifsencrypt.c
new file mode 100644
index 00000000..8fdf3d79
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifsencrypt.c
@@ -0,0 +1,204 @@
+/*
+ * fs/cifs/cifsencrypt.c
+ *
+ * Copyright (C) International Business Machines Corp., 2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "md5.h"
+#include "cifs_unicode.h"
+
+/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
+/* the 16 byte signature must be allocated by the caller */
+/* Note we only use the 1st eight bytes */
+/* Note that the smb header signature field on input contains the
+ sequence number before this function is called */
+
+extern void mdfour(unsigned char *out, unsigned char *in, int n);
+extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+
+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
+{
+ struct MD5Context context;
+
+ if((cifs_pdu == NULL) || (signature == NULL))
+ return -EINVAL;
+
+ MD5Init(&context);
+ MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+ MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
+ MD5Final(signature,&context);
+ return 0;
+}
+
+int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
+ __u32 * pexpected_response_sequence_number)
+{
+ int rc = 0;
+ char smb_signature[20];
+
+ /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
+ /* BB remember to add code to save expected sequence number in midQ entry BB */
+
+ if((cifs_pdu == NULL) || (ses == NULL))
+ return -EINVAL;
+
+ if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
+ return rc;
+
+ spin_lock(&GlobalMid_Lock);
+ cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
+ cifs_pdu->Signature.Sequence.Reserved = 0;
+
+ *pexpected_response_sequence_number = ses->sequence_number++;
+ ses->sequence_number++;
+ spin_unlock(&GlobalMid_Lock);
+
+ rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
+ if(rc)
+ memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+ else
+ memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+ return rc;
+}
+
+int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
+ __u32 expected_sequence_number)
+{
+ unsigned int rc;
+ char server_response_sig[8];
+ char what_we_think_sig_should_be[20];
+
+ if((cifs_pdu == NULL) || (mac_key == NULL))
+ return -EINVAL;
+
+ if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
+ return 0;
+
+ if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
+ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
+ if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
+ return 0;
+ }
+
+ /* BB what if signatures are supposed to be on for session but server does not
+ send one? BB */
+
+ /* Do not need to verify session setups with signature "BSRSPYL " */
+ if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
+ cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
+
+ expected_sequence_number = cpu_to_le32(expected_sequence_number);
+
+ /* save off the origiginal signature so we can modify the smb and check
+ its signature against what the server sent */
+ memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
+
+ cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
+ cifs_pdu->Signature.Sequence.Reserved = 0;
+
+ rc = cifs_calculate_signature(cifs_pdu, mac_key,
+ what_we_think_sig_should_be);
+
+ if(rc)
+ return rc;
+
+
+/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
+
+ if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
+ return -EACCES;
+ else
+ return 0;
+
+}
+
+/* We fill in key by putting in 40 byte array which was allocated by caller */
+int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
+{
+ char temp_key[16];
+ if ((key == NULL) || (rn == NULL))
+ return -EINVAL;
+
+ E_md4hash(password, temp_key);
+ mdfour(key,temp_key,16);
+ memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
+ return 0;
+}
+
+int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
+{
+ char temp_hash[16];
+ struct HMACMD5Context ctx;
+ char * ucase_buf;
+ wchar_t * unicode_buf;
+ unsigned int i,user_name_len,dom_name_len;
+
+ if(ses)
+ return -EINVAL;
+
+ E_md4hash(ses->password, temp_hash);
+
+ hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
+ user_name_len = strlen(ses->userName);
+ if(user_name_len > MAX_USERNAME_SIZE)
+ return -EINVAL;
+ dom_name_len = strlen(ses->domainName);
+ if(dom_name_len > MAX_USERNAME_SIZE)
+ return -EINVAL;
+
+ ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
+ unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
+
+ for(i=0;i<user_name_len;i++)
+ ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
+ ucase_buf[i] = 0;
+ user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
+ unicode_buf[user_name_len] = 0;
+ user_name_len++;
+
+ for(i=0;i<dom_name_len;i++)
+ ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
+ ucase_buf[i] = 0;
+ dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
+
+ unicode_buf[user_name_len + dom_name_len] = 0;
+ hmac_md5_update((const unsigned char *) unicode_buf,
+ (user_name_len+dom_name_len)*2,&ctx);
+
+ hmac_md5_final(ses->mac_signing_key,&ctx);
+ kfree(ucase_buf);
+ kfree(unicode_buf);
+ return 0;
+}
+void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
+{
+ struct HMACMD5Context context;
+ memcpy(v2_session_response + 8, ses->server->cryptKey,8);
+ /* gen_blob(v2_session_response + 16); */
+ hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
+
+ hmac_md5_update(ses->server->cryptKey,8,&context);
+/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
+
+ hmac_md5_final(v2_session_response,&context);
+}
diff --git a/release/src/linux/linux/fs/cifs/cifserr.c b/release/src/linux/linux/fs/cifs/cifserr.c
new file mode 100644
index 00000000..4c8eb7a0
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifserr.c
@@ -0,0 +1,70 @@
+/*
+ * fs/cifserr.c
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/smbno.h>
+#include "cifsfs.h"
+
+int map_cifs_error(int error_class, int error_code,
+ int status_codes_negotiated)
+{
+
+
+ if (status_codes_negotiated) {
+ switch (error_code) {
+ default:
+ return EIO;
+ }
+ } else
+ switch (error_class) {
+ case SUCCESS:
+ return 0;
+
+ case ERRDOS:
+ switch (error_code) {
+ case ERRbadfunc:
+ return EINVAL;
+ default:
+ return EIO;
+ }
+
+ case ERRSRV:
+ switch (error_code) {
+ default:
+ return EIO;
+ }
+
+ case ERRHRD:
+ switch (error_code) {
+ default:
+ return EIO;
+ }
+ default:
+ return EIO;
+ }
+ return 0;
+}
+
+int map_smb_error(int error_class, int error_code)
+{
+ return map_cifs_error(error_class, error_code, FALSE);
+}
diff --git a/release/src/linux/linux/fs/cifs/cifsfs.c b/release/src/linux/linux/fs/cifs/cifsfs.c
new file mode 100644
index 00000000..9e96b3b3
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifsfs.c
@@ -0,0 +1,769 @@
+/*
+ * fs/cifs/cifsfs.c
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2004
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Common Internet FileSystem (CIFS) client
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Note that BB means BUGBUG (ie something to fix eventually) */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
+#include <linux/seq_file.h>
+#endif
+#include <linux/vfs.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#define DECLARE_GLOBALS_HERE
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include <linux/mm.h>
+#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
+/* BB when mempool_resize is added back in, we will resize pool on new mount */
+#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
+
+#ifdef CONFIG_CIFS_QUOTA
+static struct quotactl_ops cifs_quotactl_ops;
+#endif
+
+extern struct file_system_type cifs_fs_type;
+
+int cifsFYI = 0;
+int cifsERROR = 1;
+int traceSMB = 0;
+unsigned int oplockEnabled = 1;
+unsigned int quotaEnabled = 0;
+unsigned int linuxExtEnabled = 1;
+unsigned int lookupCacheEnabled = 1;
+unsigned int multiuser_mount = 0;
+unsigned int extended_security = 0;
+unsigned int ntlmv2_support = 0;
+unsigned int sign_CIFS_PDUs = 1;
+unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
+struct task_struct * oplockThread = NULL;
+
+extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
+ const char *);
+extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
+void cifs_proc_init(void);
+void cifs_proc_clean(void);
+
+static DECLARE_COMPLETION(cifs_oplock_exited);
+
+
+struct super_block *
+cifs_read_super(struct super_block *sb, void *data, int silent)
+{
+ struct inode *inode;
+ struct cifs_sb_info *cifs_sb;
+ int rc = 0;
+
+ sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
+ cifs_sb = CIFS_SB(sb);
+ if(cifs_sb == NULL)
+ return 0;
+ else
+ memset(cifs_sb,0,sizeof(struct cifs_sb_info));
+
+
+ rc = cifs_mount(sb, cifs_sb, data, NULL);
+
+ if (rc) {
+ if (!silent)
+ cERROR(1,
+ ("cifs_mount failed w/return code = %d", rc));
+ goto out_mount_failed;
+ }
+
+ sb->s_magic = CIFS_MAGIC_NUMBER;
+ sb->s_op = &cifs_super_ops;
+/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
+ sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
+#ifdef CONFIG_CIFS_QUOTA
+ sb->s_qcop = &cifs_quotactl_ops;
+#endif
+ sb->s_blocksize = CIFS_MAX_MSGSIZE;
+ sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
+ inode = iget(sb, ROOT_I);
+
+ if (!inode) {
+ goto out_no_root;
+ }
+
+ sb->s_root = d_alloc_root(inode);
+
+ if (!sb->s_root) {
+ goto out_no_root;
+ }
+
+ return sb;
+
+out_no_root:
+ cERROR(1, ("cifs_read_super: get root inode failed"));
+ if (inode)
+ iput(inode);
+
+out_mount_failed:
+ if(cifs_sb->local_nls)
+ unload_nls(cifs_sb->local_nls);
+ sb->s_dev = 0;
+ return 0;
+}
+
+static void
+cifs_put_super(struct super_block *sb)
+{
+ int rc = 0;
+ struct cifs_sb_info *cifs_sb;
+
+ cFYI(1, ("In cifs_put_super"));
+ cifs_sb = CIFS_SB(sb);
+ if(cifs_sb == NULL) {
+ cFYI(1,("Empty cifs superblock info passed to unmount"));
+ return;
+ }
+ rc = cifs_umount(sb, cifs_sb);
+ if (rc) {
+ cERROR(1, ("cifs_umount failed with return code %d", rc));
+ }
+ unload_nls(cifs_sb->local_nls);
+ return;
+}
+
+static int
+cifs_statfs(struct super_block *sb, struct statfs *buf)
+{
+ int xid, rc;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(sb);
+ pTcon = cifs_sb->tcon;
+
+ buf->f_type = CIFS_MAGIC_NUMBER;
+
+ /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
+ buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably
+ be length of total path, note that some servers may be
+ able to support more than this, but best to be safe
+ since Win2k and others can not handle very long filenames */
+ buf->f_files = 0; /* undefined */
+ buf->f_ffree = 0; /* unlimited */
+
+ rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
+
+ /*
+ int f_type;
+ __fsid_t f_fsid;
+ int f_namelen; */
+ /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
+ FreeXid(xid);
+ return 0; /* always return success? what if volume is no longer available? */
+}
+
+static int cifs_permission(struct inode * inode, int mask)
+{
+ /* the server does permission checks, we do not need to do it here */
+ return 0;
+}
+
+kmem_cache_t *cifs_req_cachep;
+kmem_cache_t *cifs_mid_cachep;
+kmem_cache_t *cifs_oplock_cachep;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static struct inode *
+cifs_alloc_inode(struct super_block *sb)
+{
+ struct cifsInodeInfo *cifs_inode;
+ cifs_inode =
+ (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
+ SLAB_KERNEL);
+ if (!cifs_inode)
+ return NULL;
+ cifs_inode->cifsAttrs = 0x20; /* default */
+ atomic_set(&cifs_inode->inUse, 0);
+ cifs_inode->time = 0;
+ /* Until the file is open and we have gotten oplock
+ info back from the server, can not assume caching of
+ file data or metadata */
+ cifs_inode->clientCanCacheRead = FALSE;
+ cifs_inode->clientCanCacheAll = FALSE;
+ INIT_LIST_HEAD(&cifs_inode->openFileList);
+ return &cifs_inode->vfs_inode;
+}
+
+static void
+cifs_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
+}
+#endif
+
+/*
+ * cifs_show_options() is for displaying mount options in /proc/mounts.
+ * Not all settable options are displayed but most of the important
+ * ones are.
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
+static int
+cifs_show_options(struct seq_file *s, struct vfsmount *m)
+{
+ struct cifs_sb_info *cifs_sb;
+
+ cifs_sb = CIFS_SB(m->mnt_sb);
+
+ if (cifs_sb) {
+ if (cifs_sb->tcon) {
+ seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
+ if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
+ seq_printf(s, ",username=%s",
+ cifs_sb->tcon->ses->userName);
+ if(cifs_sb->tcon->ses->domainName)
+ seq_printf(s, ",domain=%s",
+ cifs_sb->tcon->ses->domainName);
+ }
+ seq_printf(s, ",rsize=%d",cifs_sb->rsize);
+ seq_printf(s, ",wsize=%d",cifs_sb->wsize);
+ }
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_CIFS_QUOTA
+int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
+ struct fs_disk_quota * pdquota)
+{
+ int xid;
+ int rc = 0;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *pTcon;
+
+ if(cifs_sb)
+ pTcon = cifs_sb->tcon;
+ else
+ return -EIO;
+
+
+ xid = GetXid();
+ if(pTcon) {
+ cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
+ } else {
+ return -EIO;
+ }
+
+ FreeXid(xid);
+ return rc;
+}
+
+int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
+ struct fs_disk_quota * pdquota)
+{
+ int xid;
+ int rc = 0;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *pTcon;
+
+ if(cifs_sb)
+ pTcon = cifs_sb->tcon;
+ else
+ return -EIO;
+
+ xid = GetXid();
+ if(pTcon) {
+ cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
+ } else {
+ rc = -EIO;
+ }
+
+ FreeXid(xid);
+ return rc;
+}
+
+int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
+{
+ int xid;
+ int rc = 0;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *pTcon;
+
+ if(cifs_sb)
+ pTcon = cifs_sb->tcon;
+ else
+ return -EIO;
+
+ xid = GetXid();
+ if(pTcon) {
+ cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
+ } else {
+ rc = -EIO;
+ }
+
+ FreeXid(xid);
+ return rc;
+}
+
+int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
+{
+ int xid;
+ int rc = 0;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *pTcon;
+
+ if(cifs_sb) {
+ pTcon = cifs_sb->tcon;
+ } else {
+ return -EIO;
+ }
+ xid = GetXid();
+ if(pTcon) {
+ cFYI(1,("pqstats %p",qstats));
+ } else {
+ rc = -EIO;
+ }
+
+ FreeXid(xid);
+ return rc;
+}
+
+static struct quotactl_ops cifs_quotactl_ops = {
+ .set_xquota = cifs_xquota_set,
+ .get_xquota = cifs_xquota_set,
+ .set_xstate = cifs_xstate_set,
+ .get_xstate = cifs_xstate_get,
+};
+#endif
+
+static int cifs_remount(struct super_block *sb, int *flags, char *data)
+{
+ *flags |= MS_NODIRATIME;
+ return 0;
+}
+
+struct super_operations cifs_super_ops = {
+ .read_inode = cifs_read_inode,
+ .put_super = cifs_put_super,
+ .statfs = cifs_statfs,
+/* .alloc_inode = cifs_alloc_inode,
+ .destroy_inode = cifs_destroy_inode, */
+/* .drop_inode = generic_delete_inode,
+ .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
+ unless later we add lazy close of inodes or unless the kernel forgets to call
+ us with the same number of releases (closes) as opens */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
+ .show_options = cifs_show_options,
+#endif
+/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
+};
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static struct super_block *
+cifs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data)
+{
+ int rc;
+ struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
+
+ cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
+
+ if (IS_ERR(sb))
+ return sb;
+
+ sb->s_flags = flags;
+
+ rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
+ if (rc) {
+ up_write(&sb->s_umount);
+ deactivate_super(sb);
+ return ERR_PTR(rc);
+ }
+ sb->s_flags |= MS_ACTIVE;
+ return sb;
+}
+#endif
+
+static ssize_t
+cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
+ loff_t * poffset)
+{
+ if(file == NULL)
+ return -EIO;
+ else if(file->f_dentry == NULL)
+ return -EIO;
+ else if(file->f_dentry->d_inode == NULL)
+ return -EIO;
+
+ if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
+ return generic_file_read(file,read_data,read_size,poffset);
+ } else {
+ /* BB do we need to lock inode from here until after invalidate? */
+/* if(file->f_dentry->d_inode->i_mapping) {
+ filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
+ filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
+ }*/
+/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
+
+ /* BB we should make timer configurable - perhaps
+ by simply calling cifs_revalidate here */
+ /* invalidate_remote_inode(file->f_dentry->d_inode);*/
+ return generic_file_read(file,read_data,read_size,poffset);
+ }
+}
+
+static ssize_t
+cifs_write_wrapper(struct file * file, const char *write_data,
+ size_t write_size, loff_t * poffset)
+{
+ ssize_t written;
+
+ if(file == NULL)
+ return -EIO;
+ else if(file->f_dentry == NULL)
+ return -EIO;
+ else if(file->f_dentry->d_inode == NULL)
+ return -EIO;
+
+ /* check whether we can cache writes locally */
+ written = generic_file_write(file,write_data,write_size,poffset);
+ if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
+ if(file->f_dentry->d_inode->i_mapping) {
+ filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
+ }
+ }
+ return written;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static struct file_system_type cifs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "cifs",
+ .get_sb = cifs_get_sb,
+ .kill_sb = kill_anon_super,
+ /* .fs_flags */
+};
+#endif
+
+static DECLARE_FSTYPE(cifs_fs_type, "cifs", cifs_read_super,0);
+
+
+struct inode_operations cifs_dir_inode_ops = {
+ .create = cifs_create,
+ .lookup = cifs_lookup,
+ .unlink = cifs_unlink,
+ .link = cifs_hardlink,
+ .mkdir = cifs_mkdir,
+ .rmdir = cifs_rmdir,
+ .rename = cifs_rename,
+ .permission = cifs_permission,
+ .revalidate = cifs_revalidate,
+ .setattr = cifs_setattr,
+ .symlink = cifs_symlink,
+ .mknod = cifs_mknod,
+};
+
+struct inode_operations cifs_file_inode_ops = {
+ .revalidate = cifs_revalidate,
+ .setattr = cifs_setattr,
+/* .getattr = cifs_getattr,*/
+ .rename = cifs_rename,
+ .permission = cifs_permission,
+#ifdef CONFIG_CIFS_XATTR
+ .setxattr = cifs_setxattr,
+ .getxattr = cifs_getxattr,
+ .listxattr = cifs_listxattr,
+ .removexattr = cifs_removexattr,
+#endif
+};
+
+struct inode_operations cifs_symlink_inode_ops = {
+ .readlink = cifs_readlink,
+ .follow_link = cifs_follow_link,
+ .permission = cifs_permission,
+ /* BB add the following two eventually */
+ /* revalidate: cifs_revalidate,
+ setattr: cifs_notify_change, *//* BB do we need notify change */
+#ifdef CONFIG_CIFS_XATTR
+ .setxattr = cifs_setxattr,
+ .getxattr = cifs_getxattr,
+ .listxattr = cifs_listxattr,
+ .removexattr = cifs_removexattr,
+#endif
+};
+
+struct file_operations cifs_file_ops = {
+ .read = cifs_read_wrapper,
+ .write = cifs_write_wrapper,
+ .open = cifs_open,
+ .release = cifs_close,
+ .lock = cifs_lock,
+ .fsync = cifs_fsync,
+ .flush = cifs_flush,
+ .mmap = cifs_file_mmap,
+/* .sendfile = generic_file_sendfile,*/
+#ifdef CONFIG_CIFS_FCNTL
+ .fcntl = cifs_fcntl,
+#endif
+};
+
+struct file_operations cifs_dir_ops = {
+ .readdir = cifs_readdir,
+ .release = cifs_closedir,
+ .read = generic_read_dir,
+#ifdef CONFIG_CIFS_FCNTL
+ .fcntl = cifs_fcntl,
+#endif
+};
+/*
+static void
+cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
+
+ if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR) {
+ inode_init_once(&cifsi->vfs_inode);
+ INIT_LIST_HEAD(&cifsi->lockList);
+ }
+}
+
+static int
+cifs_init_inodecache(void)
+{
+ cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
+ sizeof (struct cifsInodeInfo),
+ 0, SLAB_HWCACHE_ALIGN,
+ cifs_init_once, NULL);
+ if (cifs_inode_cachep == NULL)
+ return -ENOMEM;
+
+
+ return 0;
+}
+
+static void
+cifs_destroy_inodecache(void)
+{
+ if (kmem_cache_destroy(cifs_inode_cachep))
+ printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
+} */
+
+static int
+cifs_init_request_bufs(void)
+{
+ cifs_req_cachep = kmem_cache_create("cifs_request",
+ CIFS_MAX_MSGSIZE +
+ MAX_CIFS_HDR_SIZE, 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (cifs_req_cachep == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void
+cifs_destroy_request_bufs(void)
+{
+ if (kmem_cache_destroy(cifs_req_cachep))
+ printk(KERN_WARNING
+ "cifs_destroy_request_cache: error not all structures were freed\n");
+}
+
+static int
+cifs_init_mids(void)
+{
+ cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
+ sizeof (struct mid_q_entry), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (cifs_mid_cachep == NULL)
+ return -ENOMEM;
+ cifs_oplock_cachep = kmem_cache_create("cifs_oplock_struct",
+ sizeof (struct oplock_q_entry), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (cifs_oplock_cachep == NULL) {
+ kmem_cache_destroy(cifs_mid_cachep);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void
+cifs_destroy_mids(void)
+{
+ if (kmem_cache_destroy(cifs_mid_cachep))
+ printk(KERN_WARNING
+ "cifs_destroy_mids: error not all structures were freed\n");
+ if (kmem_cache_destroy(cifs_oplock_cachep))
+ printk(KERN_WARNING
+ "error not all oplock structures were freed\n");
+}
+
+static int cifs_oplock_thread(void * dummyarg)
+{
+ struct oplock_q_entry * oplock_item;
+ struct cifsTconInfo *pTcon;
+ struct inode * inode;
+ __u16 netfid;
+ int rc = 0;
+
+ daemonize();
+ sprintf(current->comm,"cifsoplockd");
+
+ oplockThread = current;
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ schedule_timeout(1*HZ);
+ spin_lock(&GlobalMid_Lock);
+ if(list_empty(&GlobalOplock_Q)) {
+ spin_unlock(&GlobalMid_Lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(39*HZ);
+ } else {
+ oplock_item = list_entry(GlobalOplock_Q.next,
+ struct oplock_q_entry, qhead);
+ if(oplock_item) {
+ cFYI(1,("found oplock item to write out"));
+ pTcon = oplock_item->tcon;
+ inode = oplock_item->pinode;
+ netfid = oplock_item->netfid;
+ spin_unlock(&GlobalMid_Lock);
+ DeleteOplockQEntry(oplock_item);
+ /* can not grab inode sem here since it would
+ deadlock when oplock received on delete
+ since vfs_unlink holds the i_sem across
+ the call */
+ /* down(&inode->i_sem);*/
+ if (S_ISREG(inode->i_mode)) {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
+ rc = filemap_fdatasync(inode->i_mapping);
+ if(rc)
+ CIFS_I(inode)->write_behind_rc = rc;
+#else
+ filemap_fdatasync(inode->i_mapping);
+#endif
+ if(CIFS_I(inode)->clientCanCacheRead == 0)
+ invalidate_inode_pages(inode);
+ } else
+ rc = 0;
+ /* releasing a stale oplock after recent reconnection
+ of smb session using a now incorrect file
+ handle is not a data integrity issue but do
+ not bother sending an oplock release if session
+ to server still is disconnected since oplock
+ already released by the server in that case */
+ if(pTcon->tidStatus != CifsNeedReconnect) {
+ rc = CIFSSMBLock(0, pTcon,
+ netfid,
+ 0 /* len */ , 0 /* offset */, 0,
+ 0, LOCKING_ANDX_OPLOCK_RELEASE,
+ 0 /* wait flag */);
+ cFYI(1,("Oplock release rc = %d ",rc));
+ }
+ } else
+ spin_unlock(&GlobalMid_Lock);
+ }
+ } while(!signal_pending(current));
+ complete_and_exit (&cifs_oplock_exited, 0);
+}
+
+static int __init
+init_cifs(void)
+{
+ int rc = 0;
+#if CONFIG_PROC_FS
+ cifs_proc_init();
+#endif
+ INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
+ INIT_LIST_HEAD(&GlobalSMBSessionList);
+ INIT_LIST_HEAD(&GlobalTreeConnectionList);
+ INIT_LIST_HEAD(&GlobalOplock_Q);
+/*
+ * Initialize Global counters
+ */
+ atomic_set(&sesInfoAllocCount, 0);
+ atomic_set(&tconInfoAllocCount, 0);
+ atomic_set(&tcpSesReconnectCount, 0);
+ atomic_set(&tconInfoReconnectCount, 0);
+
+ atomic_set(&bufAllocCount, 0);
+ atomic_set(&midCount, 0);
+ GlobalCurrentXid = 0;
+ GlobalTotalActiveXid = 0;
+ GlobalMaxActiveXid = 0;
+ GlobalSMBSeslock = RW_LOCK_UNLOCKED;
+ GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
+
+/* rc = cifs_init_inodecache();*/
+ if (!rc) {
+ rc = cifs_init_mids();
+ if (!rc) {
+ rc = cifs_init_request_bufs();
+ if (!rc) {
+ rc = register_filesystem(&cifs_fs_type);
+ if (!rc) {
+ kernel_thread(cifs_oplock_thread, NULL,
+ CLONE_FS | CLONE_FILES | CLONE_VM);
+ return rc; /* Success */
+ } else
+ cifs_destroy_request_bufs();
+ }
+ cifs_destroy_mids();
+ }
+/* cifs_destroy_inodecache(); */
+ }
+#if CONFIG_PROC_FS
+ cifs_proc_clean();
+#endif
+ return rc;
+}
+
+static void __exit
+exit_cifs(void)
+{
+ cFYI(0, ("In unregister ie exit_cifs"));
+#if CONFIG_PROC_FS
+ cifs_proc_clean();
+#endif
+ unregister_filesystem(&cifs_fs_type);
+/* cifs_destroy_inodecache();*/
+ cifs_destroy_mids();
+ cifs_destroy_request_bufs();
+ if(oplockThread) {
+ send_sig(SIGTERM, oplockThread, 1);
+ wait_for_completion(&cifs_oplock_exited);
+ }
+}
+
+MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
+MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
+MODULE_DESCRIPTION
+ ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
+module_init(init_cifs)
+module_exit(exit_cifs)
diff --git a/release/src/linux/linux/fs/cifs/cifsfs.h b/release/src/linux/linux/fs/cifs/cifsfs.h
new file mode 100644
index 00000000..4f2da1e7
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifsfs.h
@@ -0,0 +1,97 @@
+/*
+ * fs/cifs/cifsfs.h
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _CIFSFS_H
+#define _CIFSFS_H
+
+#define ROOT_I 2
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+extern int map_cifs_error(int error_class, int error_code,
+ int status_codes_negotiated);
+
+extern struct address_space_operations cifs_addr_ops;
+
+/* Functions related to super block operations */
+extern struct super_operations cifs_super_ops;
+extern void cifs_put_inode(struct inode *);
+extern void cifs_read_inode(struct inode *);
+extern void cifs_delete_inode(struct inode *);
+/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
+
+/* Functions related to inodes */
+extern struct inode_operations cifs_dir_inode_ops;
+extern int cifs_create(struct inode *, struct dentry *, int);
+extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
+extern int cifs_unlink(struct inode *, struct dentry *);
+extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
+extern int cifs_mknod(struct inode *, struct dentry *, int, int);
+extern int cifs_mkdir(struct inode *, struct dentry *, int);
+extern int cifs_rmdir(struct inode *, struct dentry *);
+extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
+ struct dentry *);
+extern int cifs_revalidate(struct dentry *);
+extern int cifs_setattr(struct dentry *, struct iattr *);
+
+extern struct inode_operations cifs_file_inode_ops;
+extern void cifs_truncate_file(struct inode *);
+extern struct inode_operations cifs_symlink_inode_ops;
+
+/* Functions related to files and directories */
+extern struct file_operations cifs_file_ops;
+extern int cifs_open(struct inode *inode, struct file *file);
+extern int cifs_close(struct inode *inode, struct file *file);
+extern int cifs_closedir(struct inode *inode, struct file *file);
+extern ssize_t cifs_read(struct file *file, char *read_data,
+ size_t read_size, loff_t * poffset);
+extern ssize_t cifs_write(struct file *file, const char *write_data,
+ size_t write_size, loff_t * poffset);
+extern int cifs_lock(struct file *, int, struct file_lock *);
+extern int cifs_fsync(struct file *, struct dentry *, int);
+extern int cifs_flush(struct file *);
+extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
+extern struct file_operations cifs_dir_ops;
+extern int cifs_dir_open(struct inode *inode, struct file *file);
+extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
+extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *);
+
+/* Functions related to dir entries */
+extern struct dentry_operations cifs_dentry_ops;
+
+/* Functions related to symlinks */
+extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
+extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
+extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
+ const char *symname);
+extern int cifs_removexattr(struct dentry *, const char *);
+extern int cifs_setxattr(struct dentry *, const char *, const void *,
+ size_t, int);
+extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
+#define CIFS_VERSION "1.20"
+#endif /* _CIFSFS_H */
diff --git a/release/src/linux/linux/fs/cifs/cifsglob.h b/release/src/linux/linux/fs/cifs/cifsglob.h
new file mode 100644
index 00000000..e8991b79
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifsglob.h
@@ -0,0 +1,413 @@
+/*
+ * fs/cifs/cifsglob.h
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ */
+#include <linux/in.h>
+#include <linux/in6.h>
+#include "cifs_fs_sb.h"
+/*
+ * The sizes of various internal tables and strings
+ */
+#define MAX_UID_INFO 16
+#define MAX_SES_INFO 2
+#define MAX_TCON_INFO 4
+
+#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
+#define MAX_SERVER_SIZE 15
+#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
+#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
+ termination then *2 for unicode versions */
+#define MAX_PASSWORD_SIZE 16
+
+/*
+ * MAX_REQ is the maximum number of requests that WE will send
+ * on one socket concurently. It also matches the most common
+ * value of max multiplex returned by servers. We may
+ * eventually want to use the negotiated value (in case
+ * future servers can handle more) when we are more confident that
+ * we will not have problems oveloading the socket with pending
+ * write data.
+ */
+#define CIFS_MAX_REQ 50
+
+#define SERVER_NAME_LENGTH 15
+#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
+
+/* used to define string lengths for reversing unicode strings */
+/* (256+1)*2 = 514 */
+/* (max path length + 1 for null) * 2 for unicode */
+#define MAX_NAME 514
+
+#include "cifspdu.h"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef XATTR_DOS_ATTRIB
+#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
+#endif
+
+/*
+ * This information is kept on every Server we know about.
+ *
+ * Some things to note:
+ *
+ */
+#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
+
+/*
+ * CIFS vfs client Status information (based on what we know.)
+ */
+
+ /* associated with each tcp and smb session */
+enum statusEnum {
+ CifsNew = 0,
+ CifsGood,
+ CifsExiting,
+ CifsNeedReconnect
+};
+
+enum securityEnum {
+ NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
+ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
+ RawNTLMSSP, /* NTLMSSP without SPNEGO */
+ NTLMSSP, /* NTLMSSP via SPNEGO */
+ Kerberos /* Kerberos via SPNEGO */
+};
+
+enum protocolEnum {
+ IPV4 = 0,
+ IPV6,
+ SCTP
+ /* Netbios frames protocol not supported at this time */
+};
+
+/*
+ *****************************************************************
+ * Except the CIFS PDUs themselves all the
+ * globally interesting structs should go here
+ *****************************************************************
+ */
+
+struct TCP_Server_Info {
+ char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
+ char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
+ struct socket *ssocket;
+ union {
+ struct sockaddr_in sockAddr;
+ struct sockaddr_in6 sockAddr6;
+ } addr;
+ wait_queue_head_t response_q;
+ wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
+ struct list_head pending_mid_q;
+ void *Server_NlsInfo; /* BB - placeholder for future NLS info */
+ unsigned short server_codepage; /* codepage for the server */
+ unsigned long ip_address; /* IP addr for the server if known */
+ enum protocolEnum protocolType;
+ char versionMajor;
+ char versionMinor;
+ int svlocal:1; /* local server or remote */
+ atomic_t socketUseCount; /* number of open cifs sessions on socket */
+ atomic_t inFlight; /* number of requests on the wire to server */
+ enum statusEnum tcpStatus; /* what we think the status is */
+ struct semaphore tcpSem;
+ struct task_struct *tsk;
+ char server_GUID[16];
+ char secMode;
+ enum securityEnum secType;
+ unsigned int maxReq; /* Clients should submit no more */
+ /* than maxReq distinct unanswered SMBs to the server when using */
+ /* multiplexed reads or writes */
+ unsigned int maxBuf; /* maxBuf specifies the maximum */
+ /* message size the server can send or receive for non-raw SMBs */
+ unsigned int maxRw; /* maxRw specifies the maximum */
+ /* message size the server can send or receive for */
+ /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
+ char sessid[4]; /* unique token id for this session */
+ /* (returned on Negotiate */
+ int capabilities; /* allow selective disabling of caps by smb sess */
+ __u16 timeZone;
+ char cryptKey[CIFS_CRYPTO_KEY_SIZE];
+ char workstation_RFC1001_name[16]; /* 16th byte is always zero */
+};
+
+/*
+ * The following is our shortcut to user information. We surface the uid,
+ * and name. We always get the password on the fly in case it
+ * has changed. We also hang a list of sessions owned by this user off here.
+ */
+struct cifsUidInfo {
+ struct list_head userList;
+ struct list_head sessionList; /* SMB sessions for this user */
+ uid_t linux_uid;
+ char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
+ /* BB may need ptr or callback for PAM or WinBind info */
+};
+
+/*
+ * Session structure. One of these for each uid session with a particular host
+ */
+struct cifsSesInfo {
+ struct list_head cifsSessionList;
+ struct semaphore sesSem;
+ struct cifsUidInfo *uidInfo; /* pointer to user info */
+ struct TCP_Server_Info *server; /* pointer to server info */
+ atomic_t inUse; /* # of mounts (tree connections) on this ses */
+ enum statusEnum status;
+ __u32 sequence_number; /* needed for CIFS PDU signature */
+ __u16 ipc_tid; /* special tid for connection to IPC share */
+ char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
+ char *serverOS; /* name of operating system underlying the server */
+ char *serverNOS; /* name of network operating system that the server is running */
+ char *serverDomain; /* security realm of server */
+ int Suid; /* remote smb uid */
+ uid_t linux_uid; /* local Linux uid */
+ int capabilities;
+ char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
+ char userName[MAX_USERNAME_SIZE + 1];
+ char domainName[MAX_USERNAME_SIZE + 1];
+ char * password;
+};
+
+/*
+ * there is one of these for each connection to a resource on a particular
+ * session
+ */
+struct cifsTconInfo {
+ struct list_head cifsConnectionList;
+ struct list_head openFileList;
+ struct semaphore tconSem;
+ struct cifsSesInfo *ses; /* pointer to session associated with */
+ char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
+ char *nativeFileSystem;
+ __u16 tid; /* The 2 byte tree id */
+ __u16 Flags; /* optional support bits */
+ enum statusEnum tidStatus;
+ atomic_t useCount; /* how many mounts (explicit or implicit) to this share */
+#ifdef CONFIG_CIFS_STATS
+ atomic_t num_smbs_sent;
+ atomic_t num_writes;
+ atomic_t num_reads;
+ atomic_t num_oplock_brks;
+ atomic_t num_opens;
+ atomic_t num_deletes;
+ atomic_t num_mkdirs;
+ atomic_t num_rmdirs;
+ atomic_t num_renames;
+ atomic_t num_t2renames;
+ __u64 bytes_read;
+ __u64 bytes_written;
+ spinlock_t stat_lock;
+#endif
+ FILE_SYSTEM_DEVICE_INFO fsDevInfo;
+ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
+ FILE_SYSTEM_UNIX_INFO fsUnixInfo;
+ int retry:1;
+ /* BB add field for back pointer to sb struct? */
+};
+
+/*
+ * This info hangs off the cifsFileInfo structure. This is used to track
+ * byte stream locks on the file
+ */
+struct cifsLockInfo {
+ struct cifsLockInfo *next;
+ int start;
+ int length;
+ int type;
+};
+
+/*
+ * One of these for each open instance of a file
+ */
+struct cifsFileInfo {
+ struct list_head tlist; /* pointer to next fid owned by tcon */
+ struct list_head flist; /* next fid (file instance) for this inode */
+ unsigned int uid; /* allows finding which FileInfo structure */
+ __u32 pid; /* process id who opened file */
+ __u16 netfid; /* file id from remote */
+ /* BB add lock scope info here if needed */ ;
+ /* lock scope id (0 if none) */
+ struct file * pfile; /* needed for writepage */
+ struct inode * pInode; /* needed for oplock break */
+ int endOfSearch:1; /* we have reached end of search */
+ int closePend:1; /* file is marked to close */
+ int emptyDir:1;
+ int invalidHandle:1; /* file closed via session abend */
+ struct semaphore fh_sem; /* prevents reopen race after dead ses*/
+ char * search_resume_name;
+ unsigned int resume_name_length;
+ __u32 resume_key;
+};
+
+/*
+ * One of these for each file inode
+ */
+
+struct cifsInodeInfo {
+ struct list_head lockList;
+ /* BB add in lists for dirty pages - i.e. write caching info for oplock */
+ struct list_head openFileList;
+ int write_behind_rc;
+ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
+ atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
+ unsigned long time; /* jiffies of last update/check of inode */
+ int clientCanCacheRead:1; /* read oplock */
+ int clientCanCacheAll:1; /* read and writebehind oplock */
+ int oplockPending:1;
+ struct inode vfs_inode;
+};
+
+static inline struct cifsInodeInfo * CIFS_I(struct inode *inode)
+{
+ return (struct cifsInodeInfo *)&(inode->u);
+}
+
+static inline struct cifs_sb_info * CIFS_SB(struct super_block *sb)
+{
+ return (struct cifs_sb_info *) &(sb->u);
+}
+
+
+/* one of these for every pending CIFS request to the server */
+struct mid_q_entry {
+ struct list_head qhead; /* mids waiting on reply from this server */
+ __u16 mid; /* multiplex id */
+ __u16 pid; /* process id */
+ __u32 sequence_number; /* for CIFS signing */
+ __u16 command; /* smb command code */
+ struct timeval when_sent; /* time when smb sent */
+ struct cifsSesInfo *ses; /* smb was sent to this server */
+ struct task_struct *tsk; /* task waiting for response */
+ struct smb_hdr *resp_buf; /* response buffer */
+ int midState; /* wish this were enum but can not pass to wait_event */
+};
+
+struct oplock_q_entry {
+ struct list_head qhead;
+ struct inode * pinode;
+ struct cifsTconInfo * tcon;
+ __u16 netfid;
+};
+
+#define MID_FREE 0
+#define MID_REQUEST_ALLOCATED 1
+#define MID_REQUEST_SUBMITTED 2
+#define MID_RESPONSE_RECEIVED 4
+#define MID_RETRY_NEEDED 8 /* session closed while this request out */
+
+/*
+ *****************************************************************
+ * All constants go here
+ *****************************************************************
+ */
+
+#define UID_HASH (16)
+
+/*
+ * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
+ * following to be declared.
+ */
+
+/****************************************************************************
+ * Locking notes. All updates to global variables and lists should be
+ * protected by spinlocks or semaphores.
+ *
+ * Spinlocks
+ * ---------
+ * GlobalMid_Lock protects:
+ * list operations on pending_mid_q and oplockQ
+ * updates to XID counters, multiplex id and SMB sequence numbers
+ * GlobalSMBSesLock protects:
+ * list operations on tcp and SMB session lists and tCon lists
+ * f_owner.lock protects certain per file struct operations
+ * mapping->page_lock protects certain per page operations
+ *
+ * Semaphores
+ * ----------
+ * sesSem operations on smb session
+ * tconSem operations on tree connection
+ * fh_sem file handle reconnection operations
+ *
+ ****************************************************************************/
+
+#ifdef DECLARE_GLOBALS_HERE
+#define GLOBAL_EXTERN
+#else
+#define GLOBAL_EXTERN extern
+#endif
+
+/*
+ * The list of servers that did not respond with NT LM 0.12.
+ * This list helps improve performance and eliminate the messages indicating
+ * that we had a communications error talking to the server in this list.
+ */
+GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
+
+/*
+ * The following is a hash table of all the users we know about.
+ */
+GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
+
+GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
+GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
+GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
+GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
+
+GLOBAL_EXTERN struct list_head GlobalOplock_Q;
+
+/*
+ * Global transaction id (XID) information
+ */
+GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
+GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
+GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
+GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
+ /* on midQ entries */
+GLOBAL_EXTERN char Local_System_Name[15];
+
+/*
+ * Global counters, updated atomically
+ */
+GLOBAL_EXTERN atomic_t sesInfoAllocCount;
+GLOBAL_EXTERN atomic_t tconInfoAllocCount;
+
+GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
+GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
+
+/* Various Debug counters to remove someday (BB) */
+GLOBAL_EXTERN atomic_t bufAllocCount;
+GLOBAL_EXTERN atomic_t midCount;
+
+/* Misc globals */
+GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
+ to be established on existing mount if we
+ have the uid/password or Kerberos credential
+ or equivalent for current user */
+GLOBAL_EXTERN unsigned int oplockEnabled;
+GLOBAL_EXTERN unsigned int quotaEnabled;
+GLOBAL_EXTERN unsigned int lookupCacheEnabled;
+GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
+ with more secure ntlmssp2 challenge/resp */
+GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
+GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
+GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */
+
diff --git a/release/src/linux/linux/fs/cifs/cifspdu.h b/release/src/linux/linux/fs/cifs/cifspdu.h
new file mode 100644
index 00000000..067eb4e3
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifspdu.h
@@ -0,0 +1,1793 @@
+/*
+ * fs/cifs/cifspdu.h
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _CIFSPDU_H
+#define _CIFSPDU_H
+
+#include <net/sock.h>
+
+#define CIFS_PROT 0
+#define BAD_PROT CIFS_PROT+1
+
+/* SMB command codes */
+#define SMB_COM_CREATE_DIRECTORY 0x00
+#define SMB_COM_DELETE_DIRECTORY 0x01
+#define SMB_COM_CLOSE 0x04
+#define SMB_COM_DELETE 0x06
+#define SMB_COM_RENAME 0x07
+#define SMB_COM_LOCKING_ANDX 0x24
+#define SMB_COM_COPY 0x29
+#define SMB_COM_READ_ANDX 0x2E
+#define SMB_COM_WRITE_ANDX 0x2F
+#define SMB_COM_TRANSACTION2 0x32
+#define SMB_COM_TRANSACTION2_SECONDARY 0x33
+#define SMB_COM_FIND_CLOSE2 0x34
+#define SMB_COM_TREE_DISCONNECT 0x71
+#define SMB_COM_NEGOTIATE 0x72
+#define SMB_COM_SESSION_SETUP_ANDX 0x73
+#define SMB_COM_LOGOFF_ANDX 0x74
+#define SMB_COM_TREE_CONNECT_ANDX 0x75
+#define SMB_COM_NT_TRANSACT 0xA0
+#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
+#define SMB_COM_NT_CREATE_ANDX 0xA2
+#define SMB_COM_NT_RENAME 0xA5
+
+/* Transact2 subcommand codes */
+#define TRANS2_OPEN 0x00
+#define TRANS2_FIND_FIRST 0x01
+#define TRANS2_FIND_NEXT 0x02
+#define TRANS2_QUERY_FS_INFORMATION 0x03
+#define TRANS2_QUERY_PATH_INFORMATION 0x05
+#define TRANS2_SET_PATH_INFORMATION 0x06
+#define TRANS2_QUERY_FILE_INFORMATION 0x07
+#define TRANS2_SET_FILE_INFORMATION 0x08
+#define TRANS2_GET_DFS_REFERRAL 0x10
+#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
+
+/* NT Transact subcommand codes */
+#define NT_TRANSACT_CREATE 0x01
+#define NT_TRANSACT_IOCTL 0x02
+#define NT_TRANSACT_SET_SECURITY_DESC 0x03
+#define NT_TRANSACT_NOTIFY_CHANGE 0x04
+#define NT_TRANSACT_RENAME 0x05
+#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
+#define NT_TRANSACT_GET_USER_QUOTA 0x07
+#define NT_TRANSACT_SET_USER_QUOTA 0x08
+
+#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
+
+/* internal cifs vfs structures */
+/*****************************************************************
+ * All constants go here
+ *****************************************************************
+ */
+
+/*
+ * Starting value for maximum SMB size negotiation
+ */
+#define CIFS_MAX_MSGSIZE (4*4096)
+
+/*
+ * Size of encrypted user password in bytes
+ */
+#define CIFS_ENCPWD_SIZE (16)
+
+/*
+ * Size of the crypto key returned on the negotiate SMB in bytes
+ */
+#define CIFS_CRYPTO_KEY_SIZE (8)
+
+/*
+ * Size of the session key (crypto key encrypted with the password
+ */
+#define CIFS_SESSION_KEY_SIZE (24)
+
+/*
+ * Maximum user name length
+ */
+#define CIFS_UNLEN (20)
+
+/*
+ * Flags on SMB open
+ */
+#define SMBOPEN_WRITE_THROUGH 0x4000
+#define SMBOPEN_DENY_ALL 0x0010
+#define SMBOPEN_DENY_WRITE 0x0020
+#define SMBOPEN_DENY_READ 0x0030
+#define SMBOPEN_DENY_NONE 0x0040
+#define SMBOPEN_READ 0x0000
+#define SMBOPEN_WRITE 0x0001
+#define SMBOPEN_READWRITE 0x0002
+#define SMBOPEN_EXECUTE 0x0003
+
+#define SMBOPEN_OCREATE 0x0010
+#define SMBOPEN_OTRUNC 0x0002
+#define SMBOPEN_OAPPEND 0x0001
+
+/*
+ * SMB flag definitions
+ */
+#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
+#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
+#define SMBFLG_RSVD 0x04
+#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
+#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
+#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
+#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
+#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
+
+/*
+ * SMB flag2 definitions
+ */
+#define SMBFLG2_KNOWS_LONG_NAMES 0x0001 /* can send long (non-8.3) path names in response */
+#define SMBFLG2_KNOWS_EAS 0x0002
+#define SMBFLG2_SECURITY_SIGNATURE 0x0004
+#define SMBFLG2_IS_LONG_NAME 0x0040
+#define SMBFLG2_EXT_SEC 0x0800
+#define SMBFLG2_DFS 0x1000
+#define SMBFLG2_PAGING_IO 0x2000
+#define SMBFLG2_ERR_STATUS 0x4000
+#define SMBFLG2_UNICODE 0x8000
+
+/*
+ * These are the file access permission bits defined in CIFS for the
+ * NTCreateAndX as well as the level 0x107
+ * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
+ * responds with the AccessFlags.
+ * The AccessFlags specifies the access permissions a caller has to the
+ * file and can have any suitable combination of the following values:
+ */
+
+#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
+#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
+#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
+#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
+ /* with the file can be read */
+#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
+ /* with the file can be written */
+#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
+ /* the file using system paging I/O */
+#define FILE_DELETE_CHILD 0x00000040
+#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
+ /* file can be read */
+#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
+ /* file can be written */
+#define DELETE 0x00010000 /* The file can be deleted */
+#define READ_CONTROL 0x00020000 /* The access control list and */
+ /* ownership associated with the */
+ /* file can be read */
+#define WRITE_DAC 0x00040000 /* The access control list and */
+ /* ownership associated with the */
+ /* file can be written. */
+#define WRITE_OWNER 0x00080000 /* Ownership information associated */
+ /* with the file can be written */
+#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
+ /* synchronize with the completion */
+ /* of an input/output request */
+#define GENERIC_ALL 0x10000000
+#define GENERIC_EXECUTE 0x20000000
+#define GENERIC_WRITE 0x40000000
+#define GENERIC_READ 0x80000000
+ /* In summary - Relevant file */
+ /* access flags from CIFS are */
+ /* file_read_data, file_write_data */
+ /* file_execute, file_read_attributes */
+ /* write_dac, and delete. */
+
+/*
+ * Invalid readdir handle
+ */
+#define CIFS_NO_HANDLE 0xFFFF
+
+/* IPC$ in ASCII */
+#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
+
+/* IPC$ in Unicode */
+#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
+
+/* Unicode Null terminate 2 bytes of 0 */
+#define UNICODE_NULL "\x00\x00"
+#define ASCII_NULL 0x00
+
+/*
+ * Server type values (returned on EnumServer API
+ */
+#define CIFS_SV_TYPE_DC 0x00000008
+#define CIFS_SV_TYPE_BACKDC 0x00000010
+
+/*
+ * Alias type flags (From EnumAlias API call
+ */
+#define CIFS_ALIAS_TYPE_FILE 0x0001
+#define CIFS_SHARE_TYPE_FILE 0x0000
+
+/*
+ * File Attribute flags
+ */
+#define ATTR_READONLY 0x0001
+#define ATTR_HIDDEN 0x0002
+#define ATTR_SYSTEM 0x0004
+#define ATTR_VOLUME 0x0008
+#define ATTR_DIRECTORY 0x0010
+#define ATTR_ARCHIVE 0x0020
+#define ATTR_DEVICE 0x0040
+#define ATTR_NORMAL 0x0080
+#define ATTR_TEMPORARY 0x0100
+#define ATTR_SPARSE 0x0200
+#define ATTR_REPARSE 0x0400
+#define ATTR_COMPRESSED 0x0800
+#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
+#define ATTR_NOT_CONTENT_INDEXED 0x2000
+#define ATTR_ENCRYPTED 0x4000
+#define ATTR_POSIX_SEMANTICS 0x01000000
+#define ATTR_BACKUP_SEMANTICS 0x02000000
+#define ATTR_DELETE_ON_CLOSE 0x04000000
+#define ATTR_SEQUENTIAL_SCAN 0x08000000
+#define ATTR_RANDOM_ACCESS 0x10000000
+#define ATTR_NO_BUFFERING 0x20000000
+#define ATTR_WRITE_THROUGH 0x80000000
+
+/* ShareAccess flags */
+#define FILE_NO_SHARE 0x00000000
+#define FILE_SHARE_READ 0x00000001
+#define FILE_SHARE_WRITE 0x00000002
+#define FILE_SHARE_DELETE 0x00000004
+#define FILE_SHARE_ALL 0x00000007
+
+/* CreateDisposition flags */
+#define FILE_SUPERSEDE 0x00000000
+#define FILE_OPEN 0x00000001
+#define FILE_CREATE 0x00000002
+#define FILE_OPEN_IF 0x00000003
+#define FILE_OVERWRITE 0x00000004
+#define FILE_OVERWRITE_IF 0x00000005
+
+/* CreateOptions */
+#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
+#define CREATE_WRITE_THROUGH 0x00000002
+#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
+#define CREATE_RANDOM_ACCESS 0x00000800
+#define CREATE_DELETE_ON_CLOSE 0x00001000
+#define OPEN_REPARSE_POINT 0x00200000
+
+/* ImpersonationLevel flags */
+#define SECURITY_ANONYMOUS 0
+#define SECURITY_IDENTIFICATION 1
+#define SECURITY_IMPERSONATION 2
+#define SECURITY_DELEGATION 3
+
+/* SecurityFlags */
+#define SECURITY_CONTEXT_TRACKING 0x01
+#define SECURITY_EFFECTIVE_ONLY 0x02
+
+/*
+ * Default PID value, used in all SMBs where the PID is not important
+ */
+#define CIFS_DFT_PID 0x1234
+
+/*
+ * We use the same routine for Copy and Move SMBs. This flag is used to
+ * distinguish
+ */
+#define CIFS_COPY_OP 1
+#define CIFS_RENAME_OP 2
+
+#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
+#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
+
+#pragma pack(1)
+
+struct smb_hdr {
+ __u32 smb_buf_length; /* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */
+ __u8 Protocol[4];
+ __u8 Command;
+ union {
+ struct {
+ __u8 ErrorClass;
+ __u8 Reserved;
+ __u16 Error; /* note: treated as little endian (le) on wire */
+ } DosError;
+ __u32 CifsError; /* note: le */
+ } Status;
+ __u8 Flags;
+ __u16 Flags2; /* note: le */
+ __u16 PidHigh; /* note: le */
+ union {
+ struct {
+ __u32 SequenceNumber; /* le */
+ __u32 Reserved; /* zero */
+ } Sequence;
+ __u8 SecuritySignature[8]; /* le */
+ } Signature;
+ __u8 pad[2];
+ __u16 Tid;
+ __u16 Pid; /* note: le */
+ __u16 Uid;
+ __u16 Mid;
+ __u8 WordCount;
+};
+/* given a pointer to an smb_hdr retrieve the value of byte count */
+#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
+
+/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
+#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
+
+/*
+ * Computer Name Length
+ */
+#define CNLEN 15
+
+/*
+ * Share Name Length @S8A
+ * Note: This length is limited by the SMB used to get @S8A
+ * the Share info. NetShareEnum only returns 13 @S8A
+ * chars, including the null termination. @S8A
+ */
+#define SNLEN 12 /*@S8A */
+
+/*
+ * Comment Length
+ */
+#define MAXCOMMENTLEN 40
+
+/*
+ * The OS/2 maximum path name
+ */
+#define MAX_PATHCONF 256
+
+/*
+ * SMB frame definitions (following must be packed structs)
+ * See the SNIA CIFS Specification for details.
+ *
+ * The Naming convention is the lower case version of the
+ * smb command code name for the struct and this is typedef to the
+ * uppercase version of the same name with the prefix SMB_ removed
+ * for brevity. Although typedefs are not commonly used for
+ * structure definitions in the Linux kernel, their use in the
+ * CIFS standards document, which this code is based on, may
+ * make this one of the cases where typedefs for structures make
+ * sense to improve readability for readers of the standards doc.
+ * Typedefs can always be removed later if they are too distracting
+ * and they are only used for the CIFSs PDUs themselves, not
+ * internal cifs vfs structures
+ *
+ */
+
+typedef struct negotiate_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount;
+ unsigned char DialectsArray[1];
+} NEGOTIATE_REQ;
+
+typedef struct negotiate_rsp {
+ struct smb_hdr hdr; /* wct = 17 */
+ __u16 DialectIndex;
+ __u8 SecurityMode;
+ __u16 MaxMpxCount;
+ __u16 MaxNumberVcs;
+ __u32 MaxBufferSize;
+ __u32 MaxRawSize;
+ __u32 SessionKey;
+ __u32 Capabilities; /* see below */
+ __u32 SystemTimeLow;
+ __u32 SystemTimeHigh;
+ __u16 ServerTimeZone;
+ __u8 EncryptionKeyLength;
+ __u16 ByteCount;
+ union {
+ unsigned char EncryptionKey[1]; /* if cap extended security is off */
+ /* followed by Domain name - if extended security is off */
+ /* followed by 16 bytes of server GUID */
+ /* followed by security blob if cap_extended_security negotiated */
+ struct {
+ unsigned char GUID[16];
+ unsigned char SecurityBlob[1];
+ } extended_response;
+ } u;
+} NEGOTIATE_RSP;
+
+/* SecurityMode bits */
+#define SECMODE_USER 0x01 /* off indicates share level security */
+#define SECMODE_PW_ENCRYPT 0x02
+#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
+#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
+
+/* Negotiate response Capabilities */
+#define CAP_RAW_MODE 0x00000001
+#define CAP_MPX_MODE 0x00000002
+#define CAP_UNICODE 0x00000004
+#define CAP_LARGE_FILES 0x00000008
+#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
+#define CAP_RPC_REMOTE_APIS 0x00000020
+#define CAP_STATUS32 0x00000040
+#define CAP_LEVEL_II_OPLOCKS 0x00000080
+#define CAP_LOCK_AND_READ 0x00000100
+#define CAP_NT_FIND 0x00000200
+#define CAP_DFS 0x00001000
+#define CAP_INFOLEVEL_PASSTHRU 0x00002000
+#define CAP_LARGE_READ_X 0x00004000
+#define CAP_LARGE_WRITE_X 0x00008000
+#define CAP_UNIX 0x00800000
+#define CAP_RESERVED 0x02000000
+#define CAP_BULK_TRANSFER 0x20000000
+#define CAP_COMPRESSED_DATA 0x40000000
+#define CAP_EXTENDED_SECURITY 0x80000000
+
+typedef union smb_com_session_setup_andx {
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 12 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 MaxBufferSize;
+ __u16 MaxMpxCount;
+ __u16 VcNumber;
+ __u32 SessionKey;
+ __u16 SecurityBlobLength;
+ __u32 Reserved;
+ __u32 Capabilities; /* see below */
+ __u16 ByteCount;
+ unsigned char SecurityBlob[1]; /* followed by */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+ } req; /* NTLM request format (with extended security */
+
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 13 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 MaxBufferSize;
+ __u16 MaxMpxCount;
+ __u16 VcNumber;
+ __u32 SessionKey;
+ __u16 CaseInsensitivePasswordLength; /* ASCII password length */
+ __u16 CaseSensitivePasswordLength; /* Unicode password length */
+ __u32 Reserved; /* see below */
+ __u32 Capabilities;
+ __u16 ByteCount;
+ unsigned char CaseInsensitivePassword[1]; /* followed by: */
+ /* unsigned char * CaseSensitivePassword; */
+ /* STRING AccountName */
+ /* STRING PrimaryDomain */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+ } req_no_secext; /* NTLM request format (without extended security */
+
+ struct { /* default (NTLM) response format */
+ struct smb_hdr hdr; /* wct = 4 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Action; /* see below */
+ __u16 SecurityBlobLength;
+ __u16 ByteCount;
+ unsigned char SecurityBlob[1]; /* followed by */
+/* unsigned char * NativeOS; */
+/* unsigned char * NativeLanMan; */
+/* unsigned char * PrimaryDomain; */
+ } resp; /* NTLM response format (with or without extended security */
+
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 10 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 MaxBufferSize;
+ __u16 MaxMpxCount;
+ __u16 VcNumber;
+ __u32 SessionKey;
+ __u16 PassswordLength;
+ __u32 Reserved;
+ __u16 ByteCount;
+ unsigned char AccountPassword[1]; /* followed by */
+ /* STRING AccountName */
+ /* STRING PrimaryDomain */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+ } old_req; /* pre-NTLM (LANMAN2.1) request format */
+
+ struct { /* default (NTLM) response format */
+ struct smb_hdr hdr; /* wct = 3 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Action; /* see below */
+ __u16 ByteCount;
+ unsigned char NativeOS[1]; /* followed by */
+/* unsigned char * NativeLanMan; */
+/* unsigned char * PrimaryDomain; */
+ } old_resp; /* pre-NTLM (LANMAN2.1) response format */
+} SESSION_SETUP_ANDX;
+
+#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
+
+/* Capabilities bits (for NTLM SessSetup request) */
+#define CAP_UNICODE 0x00000004
+#define CAP_LARGE_FILES 0x00000008
+#define CAP_NT_SMBS 0x00000010
+#define CAP_STATUS32 0x00000040
+#define CAP_LEVEL_II_OPLOCKS 0x00000080
+#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
+#define CAP_BULK_TRANSFER 0x20000000
+#define CAP_EXTENDED_SECURITY 0x80000000
+
+/* Action bits */
+#define GUEST_LOGIN 1
+
+typedef struct smb_com_tconx_req {
+ struct smb_hdr hdr; /* wct = 4 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Flags; /* see below */
+ __u16 PasswordLength;
+ __u16 ByteCount;
+ unsigned char Password[1]; /* followed by */
+/* STRING Path *//* \\server\share name */
+ /* STRING Service */
+} TCONX_REQ;
+
+typedef struct smb_com_tconx_rsp {
+ struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 OptionalSupport; /* see below */
+ __u16 ByteCount;
+ unsigned char Service[1]; /* always ASCII, not Unicode */
+ /* STRING NativeFileSystem */
+} TCONX_RSP;
+
+/* tree connect Flags */
+#define DISCONNECT_TID 0x0001
+#define TCON_EXTENDED_SECINFO 0x0008
+/* OptionalSupport bits */
+#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
+#define SMB_SHARE_IS_IN_DFS 0x0002
+
+typedef struct smb_com_logoff_andx_req {
+
+ struct smb_hdr hdr; /* wct = 2 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 ByteCount;
+} LOGOFF_ANDX_REQ;
+
+typedef struct smb_com_logoff_andx_rsp {
+ struct smb_hdr hdr; /* wct = 2 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 ByteCount;
+} LOGOFF_ANDX_RSP;
+
+typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
+ struct {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bcc = 0 */
+ } req;
+ struct {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bcc = 0 */
+ } resp;
+} TREE_DISCONNECT;
+
+typedef struct smb_com_close_req {
+ struct smb_hdr hdr; /* wct = 3 */
+ __u16 FileID;
+ __u32 LastWriteTime; /* should be zero */
+ __u16 ByteCount; /* 0 */
+} CLOSE_REQ;
+
+typedef struct smb_com_close_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} CLOSE_RSP;
+
+typedef struct smb_com_findclose_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __u16 FileID;
+ __u16 ByteCount; /* 0 */
+} FINDCLOSE_REQ;
+
+/* OpenFlags */
+#define REQ_OPLOCK 0x00000002
+#define REQ_BATCHOPLOCK 0x00000004
+#define REQ_OPENDIRONLY 0x00000008
+
+typedef struct smb_com_open_req { /* also handles create */
+ struct smb_hdr hdr; /* wct = 24 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u8 Reserved; /* Must Be Zero */
+ __u16 NameLength;
+ __u32 OpenFlags;
+ __u32 RootDirectoryFid;
+ __u32 DesiredAccess;
+ __u64 AllocationSize;
+ __u32 FileAttributes;
+ __u32 ShareAccess;
+ __u32 CreateDisposition;
+ __u32 CreateOptions;
+ __u32 ImpersonationLevel;
+ __u8 SecurityFlags;
+ __u16 ByteCount;
+ char fileName[1];
+} OPEN_REQ;
+
+/* open response: oplock levels */
+#define OPLOCK_NONE 0
+#define OPLOCK_EXCLUSIVE 1
+#define OPLOCK_BATCH 2
+#define OPLOCK_READ 3 /* level 2 oplock */
+
+/* open response for CreateAction shifted left */
+#define CIFS_CREATE_ACTION 0x20000 /* file created */
+
+typedef struct smb_com_open_rsp {
+ struct smb_hdr hdr; /* wct = 34 BB */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u8 OplockLevel;
+ __u16 Fid;
+ __u32 CreateAction;
+ __u64 CreationTime;
+ __u64 LastAccessTime;
+ __u64 LastWriteTime;
+ __u64 ChangeTime;
+ __u32 FileAttributes;
+ __u64 AllocationSize;
+ __u64 EndOfFile;
+ __u16 FileType;
+ __u16 DeviceState;
+ __u8 DirectoryFlag;
+ __u16 ByteCount; /* bct = 0 */
+} OPEN_RSP;
+
+typedef struct smb_com_write_req {
+ struct smb_hdr hdr; /* wct = 14 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Fid;
+ __u32 OffsetLow;
+ __u32 Reserved;
+ __u16 WriteMode;
+ __u16 Remaining;
+ __u16 DataLengthHigh;
+ __u16 DataLengthLow;
+ __u16 DataOffset;
+ __u32 OffsetHigh;
+ __u16 ByteCount;
+ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
+ char Data[1];
+} WRITE_REQ;
+
+typedef struct smb_com_write_rsp {
+ struct smb_hdr hdr; /* wct = 6 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Count;
+ __u16 Remaining;
+ __u32 Reserved;
+ __u16 ByteCount;
+} WRITE_RSP;
+
+typedef struct smb_com_read_req {
+ struct smb_hdr hdr; /* wct = 12 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Fid;
+ __u32 OffsetLow;
+ __u16 MaxCount;
+ __u16 MinCount; /* obsolete */
+ __u32 MaxCountHigh;
+ __u16 Remaining;
+ __u32 OffsetHigh;
+ __u16 ByteCount;
+} READ_REQ;
+
+typedef struct smb_com_read_rsp {
+ struct smb_hdr hdr; /* wct = 12 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Remaining;
+ __u16 DataCompactionMode;
+ __u16 Reserved;
+ __u16 DataLength;
+ __u16 DataOffset;
+ __u16 DataLengthHigh;
+ __u64 Reserved2;
+ __u16 ByteCount;
+ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
+ char Data[1];
+} READ_RSP;
+
+typedef struct locking_andx_range {
+ __u16 Pid;
+ __u16 Pad;
+ __u32 OffsetHigh;
+ __u32 OffsetLow;
+ __u32 LengthHigh;
+ __u32 LengthLow;
+} LOCKING_ANDX_RANGE;
+
+#define LOCKING_ANDX_SHARED_LOCK 0x01
+#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
+#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
+#define LOCKING_ANDX_CANCEL_LOCK 0x08
+#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
+
+typedef struct smb_com_lock_req {
+ struct smb_hdr hdr; /* wct = 8 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 Fid;
+ __u8 LockType;
+ __u8 OplockLevel;
+ __u32 Timeout;
+ __u16 NumberOfUnlocks;
+ __u16 NumberOfLocks;
+ __u16 ByteCount;
+ LOCKING_ANDX_RANGE Locks[1];
+} LOCK_REQ;
+
+typedef struct smb_com_lock_rsp {
+ struct smb_hdr hdr; /* wct = 2 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 ByteCount;
+} LOCK_RSP;
+
+typedef struct smb_com_rename_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __u16 SearchAttributes; /* target file attributes */
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName */
+} RENAME_REQ;
+
+ /* copy request flags */
+#define COPY_MUST_BE_FILE 0x0001
+#define COPY_MUST_BE_DIR 0x0002
+#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
+#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
+#define COPY_VERIFY_WRITES 0x0010
+#define COPY_TREE 0x0020
+
+typedef struct smb_com_copy_req {
+ struct smb_hdr hdr; /* wct = 3 */
+ __u16 Tid2;
+ __u16 OpenFunction;
+ __u16 Flags;
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName string */
+} COPY_REQ;
+
+typedef struct smb_com_copy_rsp {
+ struct smb_hdr hdr; /* wct = 1 */
+ __u16 CopyCount; /* number of files copied */
+ __u16 ByteCount; /* may be zero */
+ __u8 BufferFormat; /* 0x04 - only present if errored file follows */
+ unsigned char ErrorFileName[1]; /* only present if error in copy */
+} COPY_RSP;
+
+#define CREATE_HARD_LINK 0x103
+#define MOVEFILE_COPY_ALLOWED 0x0002
+#define MOVEFILE_REPLACE_EXISTING 0x0001
+
+typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
+ struct smb_hdr hdr; /* wct = 4 */
+ __u16 SearchAttributes; /* target file attributes */
+ __u16 Flags; /* spec says Information Level */
+ __u32 ClusterCount;
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName */
+} NT_RENAME_REQ;
+
+typedef struct smb_com_rename_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} RENAME_RSP;
+
+typedef struct smb_com_delete_file_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __u16 SearchAttributes;
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+} DELETE_FILE_REQ;
+
+typedef struct smb_com_delete_file_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} DELETE_FILE_RSP;
+
+typedef struct smb_com_delete_directory_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char DirName[1];
+} DELETE_DIRECTORY_REQ;
+
+typedef struct smb_com_delete_directory_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} DELETE_DIRECTORY_RSP;
+
+typedef struct smb_com_create_directory_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char DirName[1];
+} CREATE_DIRECTORY_REQ;
+
+typedef struct smb_com_create_directory_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} CREATE_DIRECTORY_RSP;
+
+/***************************************************/
+/* NT Transact structure defintions follow */
+/* Currently only ioctl and notify are implemented */
+/***************************************************/
+typedef struct smb_com_transaction_ioctl_req {
+ struct smb_hdr hdr; /* wct = 23 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __u32 TotalParameterCount;
+ __u32 TotalDataCount;
+ __u32 MaxParameterCount;
+ __u32 MaxDataCount;
+ __u32 ParameterCount;
+ __u32 ParameterOffset;
+ __u32 DataCount;
+ __u32 DataOffset;
+ __u8 SetupCount; /* four setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __u16 SubCommand;/* 2 = IOCTL/FSCTL */
+ __u32 FunctionCode;
+ __u16 Fid;
+ __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
+ __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
+ __u16 ByteCount;
+ __u8 Pad[3];
+ __u8 Data[1];
+} TRANSACT_IOCTL_REQ;
+
+typedef struct smb_com_transaction_ioctl_rsp {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 Reserved[3];
+ __u32 TotalParameterCount;
+ __u32 TotalDataCount;
+ __u32 ParameterCount;
+ __u32 ParameterOffset;
+ __u32 ParameterDisplacement;
+ __u32 DataCount;
+ __u32 DataOffset;
+ __u32 DataDisplacement;
+ __u8 SetupCount; /* 1 */
+ __u16 ReturnedDataLen;
+ __u16 ByteCount;
+ __u8 Pad[3];
+} TRANSACT_IOCTL_RSP;
+
+typedef struct smb_com_transaction_change_notify_req {
+ struct smb_hdr hdr; /* wct = 23 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __u32 TotalParameterCount;
+ __u32 TotalDataCount;
+ __u32 MaxParameterCount;
+ __u32 MaxDataCount;
+ __u32 ParameterCount;
+ __u32 ParameterOffset;
+ __u32 DataCount;
+ __u32 DataOffset;
+ __u8 SetupCount; /* four setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __u16 SubCommand;/* 4 = Change Notify */
+ __u32 CompletionFilter; /* operation to monitor */
+ __u16 Fid;
+ __u8 WatchTree; /* 1 = Monitor subdirectories */
+ __u8 Reserved2;
+ __u16 ByteCount;
+/* __u8 Pad[3];*/
+/* __u8 Data[1];*/
+} TRANSACT_CHANGE_NOTIFY_REQ;
+
+typedef struct smb_com_transaction_change_notify_rsp {
+ struct smb_hdr hdr; /* wct = 18 */
+ __u8 Reserved[3];
+ __u32 TotalParameterCount;
+ __u32 TotalDataCount;
+ __u32 ParameterCount;
+ __u32 ParameterOffset;
+ __u32 ParameterDisplacement;
+ __u32 DataCount;
+ __u32 DataOffset;
+ __u32 DataDisplacement;
+ __u8 SetupCount; /* 0 */
+ __u16 ByteCount;
+ /* __u8 Pad[3]; */
+} TRANSACT_CHANGE_NOTIFY_RSP;
+/* Completion Filter flags for Notify */
+#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
+#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
+#define FILE_NOTIFY_CHANGE_NAME 0x00000003
+#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
+#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
+#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
+#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
+#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
+#define FILE_NOTIFY_CHANGE_EA 0x00000080
+#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
+#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
+#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
+#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
+
+#define FILE_ACTION_ADDED 0x00000001
+#define FILE_ACTION_REMOVED 0x00000002
+#define FILE_ACTION_MODIFIED 0x00000003
+#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
+#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
+#define FILE_ACTION_ADDED_STREAM 0x00000006
+#define FILE_ACTION_REMOVED_STREAM 0x00000007
+#define FILE_ACTION_MODIFIED_STREAM 0x00000008
+
+/* response contains array of the following structures */
+struct file_notify_information {
+ __u32 NextEntryOffset;
+ __u32 Action;
+ __u32 FileNameLength;
+ __u8 FileName[1];
+};
+
+struct reparse_data {
+ __u32 ReparseTag;
+ __u16 ReparseDataLength;
+ __u16 Reserved;
+ __u16 AltNameOffset;
+ __u16 AltNameLen;
+ __u16 TargetNameOffset;
+ __u16 TargetNameLen;
+ char LinkNamesBuf[1];
+};
+
+struct cifs_quota_data {
+ __u32 rsrvd1; /* 0 */
+ __u32 sid_size;
+ __u64 rsrvd2; /* 0 */
+ __u64 space_used;
+ __u64 soft_limit;
+ __u64 hard_limit;
+ char sid[1]; /* variable size? */
+};
+
+/* quota sub commands */
+#define QUOTA_LIST_CONTINUE 0
+#define QUOTA_LIST_START 0x100
+#define QUOTA_FOR_SID 0x101
+
+typedef union smb_com_transaction2 {
+ struct {
+ struct smb_hdr hdr; /* wct = 14+ */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */
+ __u16 ByteCount; /* careful - setupcount is not always one */
+ } req;
+ struct {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParamterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* should be zero setup words following */
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
+ /* data area follows */
+ } resp;
+} TRANSACTION2;
+
+/* PathInfo/FileInfo infolevels */
+#define SMB_INFO_STANDARD 1
+#define SMB_INFO_QUERY_EAS_FROM_LIST 3
+#define SMB_INFO_QUERY_ALL_EAS 4
+#define SMB_INFO_IS_NAME_VALID 6
+#define SMB_QUERY_FILE_BASIC_INFO 0x101
+#define SMB_QUERY_FILE_STANDARD_INFO 0x102
+#define SMB_QUERY_FILE_EA_INFO 0x103
+#define SMB_QUERY_FILE_NAME_INFO 0x104
+#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
+#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
+#define SMB_QUERY_FILE_ALL_INFO 0x107
+#define SMB_QUERY_ALT_NAME_INFO 0x108
+#define SMB_QUERY_FILE_STREAM_INFO 0x109
+#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
+#define SMB_QUERY_FILE_UNIX_BASIC 0x200
+#define SMB_QUERY_FILE_UNIX_LINK 0x201
+
+#define SMB_SET_FILE_BASIC_INFO 0x101
+#define SMB_SET_FILE_DISPOSITION_INFO 0x102
+#define SMB_SET_FILE_ALLOCATION_INFO 0x103
+#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
+#define SMB_SET_FILE_UNIX_BASIC 0x200
+#define SMB_SET_FILE_UNIX_LINK 0x201
+#define SMB_SET_FILE_UNIX_HLINK 0x203
+#define SMB_SET_FILE_BASIC_INFO2 0x3ec
+#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
+#define SMB_FILE_ALL_INFO2 0x3fa
+#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
+#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
+#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
+#define SMB_FILE_QUOTA_INFO 0x408
+#define SMB_FILE_REPARSEPOINT_INFO 0x409
+#define SMB_FILE_MAXIMUM_INFO 0x40d
+
+/* Find File infolevels */
+#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
+#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
+#define SMB_FIND_FILE_NAMES_INFO 0x103
+#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
+#define SMB_FIND_FILE_UNIX 0x202
+
+typedef struct smb_com_transaction2_qpi_req {
+ struct smb_hdr hdr; /* wct = 14+ */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __u16 SubCommand; /* one setup word */
+ __u16 ByteCount;
+ __u8 Pad;
+ __u16 InformationLevel;
+ __u32 Reserved4;
+ char FileName[1];
+} TRANSACTION2_QPI_REQ;
+
+typedef struct smb_com_transaction2_qpi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* should be zero setup words following */
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
+} TRANSACTION2_QPI_RSP;
+
+typedef struct smb_com_transaction2_spi_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __u16 SubCommand; /* one setup word */
+ __u16 ByteCount;
+ __u8 Pad;
+ __u16 Pad1;
+ __u16 InformationLevel;
+ __u32 Reserved4;
+ char FileName[1];
+} TRANSACTION2_SPI_REQ;
+
+typedef struct smb_com_transaction2_spi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* should be zero setup words following */
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
+} TRANSACTION2_SPI_RSP;
+
+struct set_file_rename {
+ __u32 overwrite; /* 1 = overwrite dest */
+ __u32 root_fid; /* zero */
+ __u32 target_name_len;
+ char target_name[0]; /* Must be unicode */
+};
+
+struct smb_com_transaction2_sfi_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __u16 SubCommand; /* one setup word */
+ __u16 ByteCount;
+ __u8 Pad;
+ __u16 Pad1;
+ __u16 Fid;
+ __u16 InformationLevel;
+ __u16 Reserved4;
+};
+
+struct smb_com_transaction2_sfi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* should be zero setup words following */
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
+};
+
+
+/*
+ * Flags on T2 FINDFIRST and FINDNEXT
+ */
+#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
+#define CIFS_SEARCH_CLOSE_AT_END 0x0002
+#define CIFS_SEARCH_RETURN_RESUME 0x0004
+#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
+#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
+
+/*
+ * Size of the resume key on FINDFIRST and FINDNEXT calls
+ */
+#define CIFS_SMB_RESUME_KEY_SIZE 4
+
+typedef struct smb_com_transaction2_ffirst_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount; /* one */
+ __u8 Reserved3;
+ __u16 SubCommand; /* TRANS2_FIND_FIRST */
+ __u16 ByteCount;
+ __u8 Pad;
+ __u16 SearchAttributes;
+ __u16 SearchCount;
+ __u16 SearchFlags;
+ __u16 InformationLevel;
+ __u32 SearchStorageType;
+ char FileName[1];
+} TRANSACTION2_FFIRST_REQ;
+
+typedef struct smb_com_transaction2_ffirst_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* should be zero setup words following */
+ __u16 ByteCount;
+} TRANSACTION2_FFIRST_RSP;
+
+typedef struct smb_com_transaction2_ffirst_rsp_parms {
+ __u16 SearchHandle;
+ __u16 SearchCount;
+ __u16 EndofSearch;
+ __u16 EAErrorOffset;
+ __u16 LastNameOffset;
+} T2_FFIRST_RSP_PARMS;
+
+typedef struct smb_com_transaction2_fnext_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount; /* one */
+ __u8 Reserved3;
+ __u16 SubCommand; /* TRANS2_FIND_NEXT */
+ __u16 ByteCount;
+ __u8 Pad;
+ __u16 SearchHandle;
+ __u16 SearchCount;
+ __u16 InformationLevel;
+ __u32 ResumeKey;
+ __u16 SearchFlags;
+ char ResumeFileName[1];
+} TRANSACTION2_FNEXT_REQ;
+
+typedef struct smb_com_transaction2_fnext_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* should be zero setup words following */
+ __u16 ByteCount;
+} TRANSACTION2_FNEXT_RSP;
+
+typedef struct smb_com_transaction2_fnext_rsp_parms {
+ __u16 SearchCount;
+ __u16 EndofSearch;
+ __u16 EAErrorOffset;
+ __u16 LastNameOffset;
+} T2_FNEXT_RSP_PARMS;
+
+/* QFSInfo Levels */
+#define SMB_INFO_ALLOCATION 1
+#define SMB_INFO_VOLUME 2
+#define SMB_QUERY_FS_VOLUME_INFO 0x102
+#define SMB_QUERY_FS_SIZE_INFO 0x103
+#define SMB_QUERY_FS_DEVICE_INFO 0x104
+#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
+#define SMB_QUERY_CIFS_UNIX_INFO 0x200
+#define SMB_QUERY_LABEL_INFO 0x3ea
+#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
+
+typedef struct smb_com_transaction2_qfsi_req {
+ struct smb_hdr hdr; /* wct = 14+ */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __u16 SubCommand; /* one setup word */
+ __u16 ByteCount;
+ __u8 Pad;
+ __u16 InformationLevel;
+} TRANSACTION2_QFSI_REQ;
+
+typedef struct smb_com_transaction_qfsi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* should be zero setup words following */
+ __u16 ByteCount;
+ __u8 Pad; /* may be three bytes *//* followed by data area */
+} TRANSACTION2_QFSI_RSP;
+
+typedef struct smb_com_transaction2_get_dfs_refer_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 MaxParameterCount;
+ __u16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __u16 Flags;
+ __u32 Timeout;
+ __u16 Reserved2;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __u16 SubCommand; /* one setup word */
+ __u16 ByteCount;
+ __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
+ __u16 MaxReferralLevel;
+ char RequestFileName[1];
+} TRANSACTION2_GET_DFS_REFER_REQ;
+
+typedef struct dfs_referral_level_3 {
+ __u16 VersionNumber;
+ __u16 ReferralSize;
+ __u16 ServerType; /* 0x0001 = CIFS server */
+ __u16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
+ __u16 TimeToLive;
+ __u16 Proximity;
+ __u16 DfsPathOffset;
+ __u16 DfsAlternatePathOffset;
+ __u16 NetworkAddressOffset;
+} REFERRAL3;
+
+typedef struct smb_com_transaction_get_dfs_refer_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ __u16 TotalParameterCount;
+ __u16 TotalDataCount;
+ __u16 Reserved;
+ __u16 ParameterCount;
+ __u16 ParameterOffset;
+ __u16 ParameterDisplacement;
+ __u16 DataCount;
+ __u16 DataOffset;
+ __u16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1; /* zero setup words following */
+ __u16 ByteCount;
+ __u8 Pad;
+ __u16 PathConsumed;
+ __u16 NumberOfReferrals;
+ __u16 DFSFlags;
+ __u16 Pad2;
+ REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
+ /* followed by the strings pointed to by the referral structures */
+} TRANSACTION2_GET_DFS_REFER_RSP;
+
+/* DFS Flags */
+#define DFSREF_REFERRAL_SERVER 0x0001
+#define DFSREF_STORAGE_SERVER 0x0002
+
+/* IOCTL information */
+/* List of ioctl function codes that look to be of interest to remote clients like this. */
+/* Need to do some experimentation to make sure they all work remotely. */
+/* Some of the following such as the encryption/compression ones would be */
+/* invoked from tools via a specialized hook into the VFS rather than via the */
+/* standard vfs entry points */
+#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
+#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
+#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
+#define FSCTL_LOCK_VOLUME 0x00090018
+#define FSCTL_UNLOCK_VOLUME 0x0009001C
+#define FSCTL_GET_COMPRESSION 0x0009003C
+#define FSCTL_SET_COMPRESSION 0x0009C040
+#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
+#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
+#define FSCTL_SET_REPARSE_POINT 0x000900A4
+#define FSCTL_GET_REPARSE_POINT 0x000900A8
+#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
+#define FSCTL_SET_SPARSE 0x000900C4
+#define FSCTL_SET_ZERO_DATA 0x000900C8
+#define FSCTL_SET_ENCRYPTION 0x000900D7
+#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
+#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
+#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
+#define FSCTL_SIS_COPYFILE 0x00090100
+#define FSCTL_SIS_LINK_FILES 0x0009C104
+
+#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
+#define IO_REPARSE_TAG_HSM 0xC0000004
+#define IO_REPARSE_TAG_SIS 0x80000007
+
+/*
+ ************************************************************************
+ * All structs for everything above the SMB PDUs themselves
+ * (such as the T2 level specific data) go here
+ ************************************************************************
+ */
+
+/*
+ * Information on a server
+ */
+
+struct serverInfo {
+ char name[16];
+ unsigned char versionMajor;
+ unsigned char versionMinor;
+ unsigned long type;
+ unsigned int commentOffset;
+};
+
+/*
+ * The following structure is the format of the data returned on a NetShareEnum
+ * with level "90" (x5A)
+ */
+
+struct shareInfo {
+ char shareName[13];
+ char pad;
+ unsigned short type;
+ unsigned int commentOffset;
+};
+
+struct aliasInfo {
+ char aliasName[9];
+ char pad;
+ unsigned int commentOffset;
+ unsigned char type[2];
+};
+
+struct aliasInfo92 {
+ int aliasNameOffset;
+ int serverNameOffset;
+ int shareNameOffset;
+};
+
+typedef struct {
+ __u64 TotalAllocationUnits;
+ __u64 FreeAllocationUnits;
+ __u32 SectorsPerAllocationUnit;
+ __u32 BytesPerSector;
+} FILE_SYSTEM_INFO; /* size info, level 0x103 */
+
+typedef struct {
+ __u16 MajorVersionNumber;
+ __u16 MinorVersionNumber;
+ __u64 Capability;
+} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
+/* Linux/Unix extensions capability flags */
+#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
+#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
+
+/* DeviceType Flags */
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+
+typedef struct {
+ __u32 DeviceType;
+ __u32 DeviceCharacteristics;
+} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
+
+typedef struct {
+ __u32 Attributes;
+ __u32 MaxPathNameComponentLength;
+ __u32 FileSystemNameLen;
+ char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
+} FILE_SYSTEM_ATTRIBUTE_INFO;
+
+typedef struct { /* data block encoding of response to level 263 QPathInfo */
+ __u64 CreationTime;
+ __u64 LastAccessTime;
+ __u64 LastWriteTime;
+ __u64 ChangeTime;
+ __u32 Attributes;
+ __u32 Pad1;
+ __u64 AllocationSize;
+ __u64 EndOfFile; /* size ie offset to first free byte in file */
+ __u32 NumberOfLinks; /* hard links */
+ __u8 DeletePending;
+ __u8 Directory;
+ __u16 Pad2;
+ __u64 IndexNumber;
+ __u32 EASize;
+ __u32 AccessFlags;
+ __u64 IndexNumber1;
+ __u64 CurrentByteOffset;
+ __u32 Mode;
+ __u32 AlignmentRequirement;
+ __u32 FileNameLength;
+ char FileName[1];
+} FILE_ALL_INFO; /* level 263 QPathInfo */
+
+typedef struct {
+ __u64 EndOfFile;
+ __u64 NumOfBytes;
+ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
+ __u64 LastAccessTime;
+ __u64 LastModificationTime;
+ __u64 Uid;
+ __u64 Gid;
+ __u32 Type;
+ __u64 DevMajor;
+ __u64 DevMinor;
+ __u64 UniqueId;
+ __u64 Permissions;
+ __u64 Nlinks;
+} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */
+
+typedef struct {
+ char LinkDest[1];
+} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */
+
+/* defines for enumerating possible values of the Unix type field below */
+#define UNIX_FILE 0
+#define UNIX_DIR 1
+#define UNIX_SYMLINK 2
+#define UNIX_CHARDEV 3
+#define UNIX_BLOCKDEV 4
+#define UNIX_FIFO 5
+#define UNIX_SOCKET 6
+
+typedef struct {
+ __u32 NextEntryOffset;
+ __u32 ResumeKey;
+ __u64 EndOfFile;
+ __u64 NumOfBytes;
+ __u64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */
+ __u64 LastAccessTime;
+ __u64 LastModificationTime;
+ __u64 Uid;
+ __u64 Gid;
+ __u32 Type;
+ __u64 DevMajor;
+ __u64 DevMinor;
+ __u64 UniqueId;
+ __u64 Permissions;
+ __u64 Nlinks;
+ char FileName[1];
+} FILE_UNIX_INFO;
+
+typedef struct {
+ __u64 CreationTime;
+ __u64 LastAccessTime;
+ __u64 LastWriteTime;
+ __u64 ChangeTime;
+ __u32 Attributes;
+ __u32 Pad;
+} FILE_BASIC_INFO; /* size info, level 0x101 */
+
+struct file_allocation_info {
+ __u64 AllocationSize;
+}; /* size info, level 0x103 */
+
+struct file_end_of_file_info {
+ __u64 FileSize; /* offset to end of file */
+}; /* size info, level 0x104 */
+
+typedef struct {
+ __u32 NextEntryOffset;
+ __u32 FileIndex;
+ __u64 CreationTime;
+ __u64 LastAccessTime;
+ __u64 LastWriteTime;
+ __u64 ChangeTime;
+ __u64 EndOfFile;
+ __u64 AllocationSize;
+ __u32 ExtFileAttributes;
+ __u32 FileNameLength;
+ char FileName[1];
+} FILE_DIRECTORY_INFO; /* level 257 FF response data area */
+
+struct gea {
+ unsigned char cbName;
+ char szName[1];
+};
+
+struct gealist {
+ unsigned long cbList;
+ struct gea list[1];
+};
+
+struct fea {
+ unsigned char EA_flags;
+ __u8 name_len;
+ __u16 value_len;
+ char szName[1];
+ /* optionally followed by value */
+};
+/* flags for _FEA.fEA */
+#define FEA_NEEDEA 0x80 /* need EA bit */
+
+struct fealist {
+ __u32 list_len;
+ struct fea list[1];
+};
+
+/* used to hold an arbitrary blob of data */
+struct data_blob {
+ __u8 *data;
+ size_t length;
+ void (*free) (struct data_blob * data_blob);
+};
+
+#ifdef CONFIG_CIFS_POSIX
+/*
+ For better POSIX semantics from Linux client, (even better
+ than the existing CIFS Unix Extensions) we need updated PDUs for:
+
+ 1) PosixCreateX - to set and return the mode, inode#, device info and
+ perhaps add a CreateDevice - to create Pipes and other special .inodes
+ Also note POSIX open flags
+ 2) Close - to return the last write time to do cache across close more safely
+ 3) PosixQFSInfo - to return statfs info
+ 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
+ 5) Mkdir - set mode
+
+ And under consideration:
+ 6) FindClose2 (return nanosecond timestamp ??)
+ 7) Use nanosecond timestamps throughout all time fields if
+ corresponding attribute flag is set
+ 8) sendfile - handle based copy
+ 9) Direct i/o
+ 10) "POSIX ACL" support
+ 11) Misc fcntls?
+
+ what about fixing 64 bit alignment
+
+ There are also various legacy SMB/CIFS requests used as is
+
+ From existing Lanman and NTLM dialects:
+ --------------------------------------
+ NEGOTIATE
+ SESSION_SETUP_ANDX (BB which?)
+ TREE_CONNECT_ANDX (BB which wct?)
+ TREE_DISCONNECT (BB add volume timestamp on response)
+ LOGOFF_ANDX
+ DELETE (note delete open file behavior)
+ DELETE_DIRECTORY
+ READ_AND_X
+ WRITE_AND_X
+ LOCKING_AND_X (note posix lock semantics)
+ RENAME (note rename across dirs and open file rename posix behaviors)
+ NT_RENAME (for hardlinks) Is this good enough for all features?
+ FIND_CLOSE2
+ TRANSACTION2 (18 cases)
+ SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
+ (BB verify that never need to set allocation size)
+ SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
+
+ COPY (note support for copy across directories) - FUTURE, OPTIONAL
+ setting/getting OS/2 EAs - FUTURE (BB can this handle
+ setting Linux xattrs perfectly) - OPTIONAL
+ dnotify - FUTURE, OPTIONAL
+ quota - FUTURE, OPTIONAL
+
+ Note that various requests implemented for NT interop such as
+ NT_TRANSACT (IOCTL) QueryReparseInfo
+ are unneeded to servers compliant with the CIFS POSIX extensions
+
+ From CIFS Unix Extensions:
+ -------------------------
+ T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
+ T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
+ Actually need QUERY_FILE_UNIX_INFO since has inode num
+ BB what about a) blksize/blkbits/blocks
+ b) i_version
+ c) i_rdev
+ d) notify mask?
+ e) generation
+ f) size_seqcount
+ T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
+ TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
+ T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
+
+
+ */
+#endif
+
+#pragma pack() /* resume default structure packing */
+
+#endif /* _CIFSPDU_H */
diff --git a/release/src/linux/linux/fs/cifs/cifsproto.h b/release/src/linux/linux/fs/cifs/cifsproto.h
new file mode 100644
index 00000000..530c554e
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifsproto.h
@@ -0,0 +1,254 @@
+/*
+ * fs/cifs/cifsproto.h
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _CIFSPROTO_H
+#define _CIFSPROTO_H
+#include <linux/nls.h>
+
+struct statfs;
+
+/*
+ *****************************************************************
+ * All Prototypes
+ *****************************************************************
+ */
+
+extern struct smb_hdr *cifs_buf_get(void);
+extern void cifs_buf_release(void *);
+extern int smb_send(struct socket *, struct smb_hdr *,
+ unsigned int /* length */ , struct sockaddr *);
+extern unsigned int _GetXid(void);
+extern void _FreeXid(unsigned int);
+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
+#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
+extern char *build_path_from_dentry(struct dentry *);
+extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
+extern void renew_parental_timestamps(struct dentry *direntry);
+extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
+ struct smb_hdr * /* input */ ,
+ struct smb_hdr * /* out */ ,
+ int * /* bytes returned */ , const int long_op);
+extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
+extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
+extern int is_valid_oplock_break(struct smb_hdr *smb);
+extern unsigned int smbCalcSize(struct smb_hdr *ptr);
+extern int decode_negTokenInit(unsigned char *security_blob, int length,
+ enum securityEnum *secType);
+extern int map_smb_to_linux_error(struct smb_hdr *smb);
+extern void header_assemble(struct smb_hdr *, char /* command */ ,
+ const struct cifsTconInfo *, int
+ /* length of fixed section (word count) in two byte units */
+ );
+struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
+void DeleteOplockQEntry(struct oplock_q_entry *);
+extern time_t cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
+extern u64 cifs_UnixTimeToNT(time_t);
+extern int cifs_get_inode_info(struct inode **pinode,
+ const unsigned char *search_path,
+ FILE_ALL_INFO * pfile_info,
+ struct super_block *sb, int xid);
+extern int cifs_get_inode_info_unix(struct inode **pinode,
+ const unsigned char *search_path,
+ struct super_block *sb,int xid);
+
+extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
+ struct nls_table * nls_info);
+extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
+
+extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
+ const char *tree, struct cifsTconInfo *tcon,
+ const struct nls_table *);
+
+extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
+ const char *searchName,
+ FILE_DIRECTORY_INFO * findData,
+ T2_FFIRST_RSP_PARMS * findParms,
+ const struct nls_table *nls_codepage,
+ int *pUnicodeFlag,
+ int *pUnixFlag /* if Unix extensions used */ );
+extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
+ FILE_DIRECTORY_INFO * findData,
+ T2_FNEXT_RSP_PARMS * findParms,
+ const __u16 searchHandle, char * resume_name,
+ int name_length, __u32 resume_key,
+ int *UnicodeFlag, int *pUnixFlag);
+
+extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
+ const __u16 search_handle);
+
+extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ FILE_ALL_INFO * findData,
+ const struct nls_table *nls_codepage);
+
+extern int CIFSSMBUnixQPathInfo(const int xid,
+ struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ FILE_UNIX_BASIC_INFO * pFindData,
+ const struct nls_table *nls_codepage);
+
+extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
+ const unsigned char *searchName,
+ unsigned char **targetUNCs,
+ unsigned int *number_of_UNC_in_array,
+ const struct nls_table *nls_codepage);
+
+extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+ const char *old_path,
+ const struct nls_table *nls_codepage);
+extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+ const char *old_path, const struct nls_table *nls_codepage,
+ unsigned int *pnum_referrals, unsigned char ** preferrals);
+extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
+ struct statfs *FSData,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSAttributeInfo(const int xid,
+ struct cifsTconInfo *tcon,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
+ const struct nls_table *nls_codepage);
+
+extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
+ char *fileName, FILE_BASIC_INFO * data,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
+ char *fileName, __u64 size,int setAllocationSizeFlag,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
+ __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
+extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
+ char *full_path, __u64 mode, __u64 uid,
+ __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
+
+extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
+ const char *newName,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
+ const char *name, const struct nls_table *nls_codepage);
+
+extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
+ const char *name,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
+ int netfid, char * target_name, const struct nls_table *nls_codepage);
+extern int CIFSCreateHardLink(const int xid,
+ struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage);
+extern int CIFSUnixCreateHardLink(const int xid,
+ struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage);
+extern int CIFSUnixCreateSymLink(const int xid,
+ struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBUnixQuerySymLink(const int xid,
+ struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ char *syminfo, const int buflen,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBQueryReparseLinkInfo(const int xid,
+ struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ char *symlinkinfo, const int buflen, __u16 fid,
+ const struct nls_table *nls_codepage);
+
+extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
+ const char *fileName, const int disposition,
+ const int access_flags, const int omode,
+ __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
+ const int smb_file_id);
+
+extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
+ const int netfid, unsigned int count,
+ const __u64 lseek, unsigned int *nbytes, char **buf);
+extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
+ const int netfid, const unsigned int count,
+ const __u64 lseek, unsigned int *nbytes,
+ const char *buf, const int long_op);
+extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
+ const __u16 netfid, const __u64 len,
+ const __u64 offset, const __u32 numUnlock,
+ const __u32 numLock, const __u8 lockType,
+ const int waitFlag);
+
+extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
+extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
+
+extern struct cifsSesInfo *sesInfoAlloc(void);
+extern void sesInfoFree(struct cifsSesInfo *);
+extern struct cifsTconInfo *tconInfoAlloc(void);
+extern void tconInfoFree(struct cifsTconInfo *);
+
+extern int cifs_reconnect(struct TCP_Server_Info *server);
+
+extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
+extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
+ __u32 expected_sequence_number);
+extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
+extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
+extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
+
+extern int CIFSBuildServerList(int xid, char *serverBufferList,
+ int recordlength, int *entries,
+ int *totalEntries, int *topoChangedFlag);
+extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
+ struct shareInfo *shareList, int bufferLen,
+ int *entries, int *totalEntries);
+extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
+ struct aliasInfo *aliasList, int bufferLen,
+ int *entries, int *totalEntries);
+extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
+ char *aliasName, char *serverName,
+ char *shareName, char *comment);
+extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
+ char *share, char *comment);
+extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
+ char *userName, char *searchName, int *perms);
+extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
+
+extern int CIFSSMBSeek(int xid,
+ struct cifsTconInfo *tcon,
+ int netfid,
+ int pid,
+ int whence, unsigned long offset, long long *newoffset);
+
+extern int CIFSSMBCopy(int xid,
+ struct cifsTconInfo *source_tcon,
+ const char *fromName,
+ const __u16 target_tid,
+ const char *toName, const int flags,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
+ const int notify_subdirs,const __u16 netfid,__u32 filter,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ char * EAData, size_t size,
+ const struct nls_table *nls_codepage);
+#endif /* _CIFSPROTO_H */
diff --git a/release/src/linux/linux/fs/cifs/cifssmb.c b/release/src/linux/linux/fs/cifs/cifssmb.c
new file mode 100644
index 00000000..ca4dedf7
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/cifssmb.c
@@ -0,0 +1,3016 @@
+/*
+ * fs/cifs/cifssmb.c
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Contains the routines for constructing the SMB PDUs themselves
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
+ /* These are mostly routines that operate on a pathname, or on a tree id */
+ /* (mounted volume), but there are eight handle based routines which must be */
+ /* treated slightly different for reconnection purposes since we never want */
+ /* to reuse a stale file handle and the caller knows the file handle */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/vfs.h>
+#include <asm/uaccess.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+
+#ifdef CONFIG_CIFS_POSIX
+static struct {
+ int index;
+ char *name;
+} protocols[] = {
+ {CIFS_PROT, "\2NT LM 0.12"},
+ {CIFS_PROT, "\2POSIX 2"},
+ {BAD_PROT, "\2"}
+};
+#else
+static struct {
+ int index;
+ char *name;
+} protocols[] = {
+ {CIFS_PROT, "\2NT LM 0.12"},
+ {BAD_PROT, "\2"}
+};
+#endif
+
+
+/* Mark as invalid, all open files on tree connections since they
+ were closed when session to server was lost */
+static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
+{
+ struct cifsFileInfo *open_file = NULL;
+ struct list_head * tmp;
+ struct list_head * tmp1;
+
+/* list all files open on tree connection and mark them invalid */
+ write_lock(&GlobalSMBSeslock);
+ list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
+ open_file = list_entry(tmp,struct cifsFileInfo, tlist);
+ if(open_file) {
+ open_file->invalidHandle = TRUE;
+ }
+ }
+ write_unlock(&GlobalSMBSeslock);
+ /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
+}
+
+static int
+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+ void **request_buf /* returned */ ,
+ void **response_buf /* returned */ )
+{
+ int rc = 0;
+ int timeout = 10 * HZ;
+
+ /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
+ check for tcp and smb session status done differently
+ for those three - in the calling routine */
+ if(tcon) {
+ if((tcon->ses) && (tcon->ses->server)){
+ struct nls_table *nls_codepage;
+ /* Give Demultiplex thread up to 10 seconds to
+ reconnect, should be greater than cifs socket
+ timeout which is 7 seconds */
+ while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+ while ((tcon->ses->server->tcpStatus != CifsGood) && (timeout > 0)){
+ timeout = interruptible_sleep_on_timeout(&tcon->ses->server->response_q,timeout);
+ }
+ if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+ /* on "soft" mounts we wait once */
+ if((tcon->retry == FALSE) ||
+ (tcon->ses->status == CifsExiting)) {
+ cFYI(1,("gave up waiting on reconnect in smb_init"));
+ return -EHOSTDOWN;
+ } /* else "hard" mount - keep retrying until
+ process is killed or server comes back up */
+ } else /* TCP session is reestablished now */
+ break;
+
+ }
+
+ nls_codepage = load_nls_default();
+ /* need to prevent multiple threads trying to
+ simultaneously reconnect the same SMB session */
+ down(&tcon->ses->sesSem);
+ if(tcon->ses->status == CifsNeedReconnect)
+ rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+ if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+ mark_open_files_invalid(tcon);
+ rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
+ nls_codepage);
+ up(&tcon->ses->sesSem);
+ if(rc == 0)
+ atomic_inc(&tconInfoReconnectCount);
+
+ cFYI(1, ("reconnect tcon rc = %d", rc));
+ /* Removed call to reopen open files here -
+ it is safer (and faster) to reopen files
+ one at a time as needed in read and write */
+
+ /* Check if handle based operation so we
+ know whether we can continue or not without
+ returning to caller to reset file handle */
+ switch(smb_command) {
+ case SMB_COM_READ_ANDX:
+ case SMB_COM_WRITE_ANDX:
+ case SMB_COM_CLOSE:
+ case SMB_COM_FIND_CLOSE2:
+ case SMB_COM_LOCKING_ANDX: {
+ unload_nls(nls_codepage);
+ return -EAGAIN;
+ }
+ }
+ } else {
+ up(&tcon->ses->sesSem);
+ }
+ unload_nls(nls_codepage);
+
+ } else {
+ return -EIO;
+ }
+ }
+ if(rc)
+ return rc;
+
+ *request_buf = cifs_buf_get();
+ if (*request_buf == 0) {
+ /* BB should we add a retry in here if not a writepage? */
+ return -ENOMEM;
+ }
+ /* Although the original thought was we needed the response buf for */
+ /* potential retries of smb operations it turns out we can determine */
+ /* from the mid flags when the request buffer can be resent without */
+ /* having to use a second distinct buffer for the response */
+ *response_buf = *request_buf;
+
+ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
+ wct /*wct */ );
+
+#ifdef CONFIG_CIFS_STATS
+ if(tcon != NULL) {
+ atomic_inc(&tcon->num_smbs_sent);
+ }
+#endif
+ return rc;
+}
+
+int
+CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
+{
+ NEGOTIATE_REQ *pSMB;
+ NEGOTIATE_RSP *pSMBr;
+ int rc = 0;
+ int bytes_returned;
+ struct TCP_Server_Info * server;
+
+ if(ses->server)
+ server = ses->server;
+ else {
+ rc = -EIO;
+ return rc;
+ }
+ rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
+ (void **) &pSMB, (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
+ if (extended_security)
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+
+ pSMB->ByteCount = strlen(protocols[0].name) + 1;
+ strncpy(pSMB->DialectsArray, protocols[0].name, 30);
+ /* null guaranteed to be at end of source and target buffers anyway */
+
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc == 0) {
+ server->secMode = pSMBr->SecurityMode;
+ server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
+ /* one byte - no need to convert this or EncryptionKeyLen from le,*/
+ server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+ /* probably no need to store and check maxvcs */
+ server->maxBuf =
+ min(le32_to_cpu(pSMBr->MaxBufferSize),
+ (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
+ server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
+ cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
+ GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
+ server->capabilities = le32_to_cpu(pSMBr->Capabilities);
+ server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
+ /* BB with UTC do we ever need to be using srvr timezone? */
+ if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+ memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
+ CIFS_CRYPTO_KEY_SIZE);
+ } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
+ && (pSMBr->EncryptionKeyLength == 0)) {
+ /* decode security blob */
+ } else
+ rc = -EIO;
+
+ /* BB might be helpful to save off the domain of server here */
+
+ if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
+ if (pSMBr->ByteCount < 16)
+ rc = -EIO;
+ else if (pSMBr->ByteCount == 16) {
+ server->secType = RawNTLMSSP;
+ if (server->socketUseCount.counter > 1) {
+ if (memcmp
+ (server->server_GUID,
+ pSMBr->u.extended_response.
+ GUID, 16) != 0) {
+ cFYI(1,
+ ("UID of server does not match previous connection to same ip address"));
+ memcpy(server->
+ server_GUID,
+ pSMBr->u.
+ extended_response.
+ GUID, 16);
+ }
+ } else
+ memcpy(server->server_GUID,
+ pSMBr->u.extended_response.
+ GUID, 16);
+ } else {
+ rc = decode_negTokenInit(pSMBr->u.
+ extended_response.
+ SecurityBlob,
+ pSMBr->ByteCount -
+ 16, &server->secType);
+ }
+ } else
+ server->capabilities &= ~CAP_EXTENDED_SECURITY;
+ if(sign_CIFS_PDUs == FALSE) {
+ if(server->secMode & SECMODE_SIGN_REQUIRED)
+ cERROR(1,
+ ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
+ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+ } else if(sign_CIFS_PDUs == 1) {
+ if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
+ server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+ }
+
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ return rc;
+}
+
+int
+CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
+{
+ struct smb_hdr *smb_buffer;
+ struct smb_hdr *smb_buffer_response;
+ int rc = 0;
+ int length;
+
+ cFYI(1, ("In tree disconnect"));
+ /*
+ * If last user of the connection and
+ * connection alive - disconnect it
+ * If this is the last connection on the server session disconnect it
+ * (and inside session disconnect we should check if tcp socket needs
+ * to be freed and kernel thread woken up).
+ */
+ if (tcon)
+ down(&tcon->tconSem);
+ else
+ return -EIO;
+
+ atomic_dec(&tcon->useCount);
+ if (atomic_read(&tcon->useCount) > 0) {
+ up(&tcon->tconSem);
+ return -EBUSY;
+ }
+
+ /* No need to return error on this operation if tid invalidated and
+ closed on server already e.g. due to tcp session crashing */
+ if(tcon->tidStatus == CifsNeedReconnect) {
+ up(&tcon->tconSem);
+ return 0;
+ }
+
+ if((tcon->ses == 0) || (tcon->ses->server == 0)) {
+ up(&tcon->tconSem);
+ return -EIO;
+ }
+
+ rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
+ (void **) &smb_buffer, (void **) &smb_buffer_response);
+ if (rc) {
+ up(&tcon->tconSem);
+ return rc;
+ }
+ rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
+ &length, 0);
+ if (rc)
+ cFYI(1, (" Tree disconnect failed %d", rc));
+
+ if (smb_buffer)
+ cifs_buf_release(smb_buffer);
+ up(&tcon->tconSem);
+
+ /* No need to return error on this operation if tid invalidated and
+ closed on server already e.g. due to tcp session crashing */
+ if (rc == -EAGAIN)
+ rc = 0;
+
+ return rc;
+}
+
+int
+CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
+{
+ struct smb_hdr *smb_buffer_response;
+ LOGOFF_ANDX_REQ *pSMB;
+ int rc = 0;
+ int length;
+
+ cFYI(1, ("In SMBLogoff for session disconnect"));
+ if (ses)
+ down(&ses->sesSem);
+ else
+ return -EIO;
+
+ atomic_dec(&ses->inUse);
+ if (atomic_read(&ses->inUse) > 0) {
+ up(&ses->sesSem);
+ return -EBUSY;
+ }
+
+ rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
+ (void **) &pSMB, (void **) &smb_buffer_response);
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ if (rc) {
+ up(&ses->sesSem);
+ return rc;
+ }
+
+ pSMB->hdr.Uid = ses->Suid;
+
+ pSMB->AndXCommand = 0xFF;
+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+ smb_buffer_response, &length, 0);
+ if (ses->server) {
+ atomic_dec(&ses->server->socketUseCount);
+ if (atomic_read(&ses->server->socketUseCount) == 0) {
+ spin_lock(&GlobalMid_Lock);
+ ses->server->tcpStatus = CifsExiting;
+ spin_unlock(&GlobalMid_Lock);
+ rc = -ESHUTDOWN;
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ up(&ses->sesSem);
+
+ /* if session dead then we do not need to do ulogoff,
+ since server closed smb session, no sense reporting
+ error */
+ if (rc == -EAGAIN)
+ rc = 0;
+ return rc;
+}
+
+int
+CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
+ const char *fileName, const struct nls_table *nls_codepage)
+{
+ DELETE_FILE_REQ *pSMB = NULL;
+ DELETE_FILE_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+DelFileRetry:
+ rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->fileName, fileName, name_len);
+ }
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
+ pSMB->ByteCount = name_len + 1;
+ pSMB->BufferFormat = 0x04;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Error in RMFile = %d", rc));
+ }
+#ifdef CONFIG_CIFS_STATS
+ else {
+ atomic_inc(&tcon->num_deletes);
+ }
+#endif
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto DelFileRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
+ const char *dirName, const struct nls_table *nls_codepage)
+{
+ DELETE_DIRECTORY_REQ *pSMB = NULL;
+ DELETE_DIRECTORY_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In CIFSSMBRmDir"));
+RmDirRetry:
+ rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(dirName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->DirName, dirName, name_len);
+ }
+
+ pSMB->ByteCount = name_len + 1;
+ pSMB->BufferFormat = 0x04;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Error in RMDir = %d", rc));
+ }
+#ifdef CONFIG_CIFS_STATS
+ else {
+ atomic_inc(&tcon->num_rmdirs);
+ }
+#endif
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto RmDirRetry;
+ return rc;
+}
+
+int
+CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
+ const char *name, const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ CREATE_DIRECTORY_REQ *pSMB = NULL;
+ CREATE_DIRECTORY_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In CIFSSMBMkDir"));
+MkDirRetry:
+ rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(name, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->DirName, name, name_len);
+ }
+
+ pSMB->ByteCount = name_len + 1 /* for buf format */ ;
+ pSMB->BufferFormat = 0x04;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Error in Mkdir = %d", rc));
+ }
+#ifdef CONFIG_CIFS_STATS
+ else {
+ atomic_inc(&tcon->num_mkdirs);
+ }
+#endif
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto MkDirRetry;
+ return rc;
+}
+
+int
+CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
+ const char *fileName, const int openDisposition,
+ const int access_flags, const int create_options, __u16 * netfid,
+ int *pOplock, FILE_ALL_INFO * pfile_info,
+ const struct nls_table *nls_codepage)
+{
+ int rc = -EACCES;
+ OPEN_REQ *pSMB = NULL;
+ OPEN_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len;
+
+openRetry:
+ rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
+ name_len =
+ cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
+ fileName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->NameLength = cpu_to_le16(name_len);
+ } else { /* BB improve the check for buffer overruns BB */
+ pSMB->ByteCount = 0; /* no pad */
+ name_len = strnlen(fileName, 530);
+ name_len++; /* trailing null */
+ pSMB->NameLength = cpu_to_le16(name_len);
+ strncpy(pSMB->fileName, fileName, name_len);
+ }
+ if (*pOplock & REQ_OPLOCK)
+ pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
+ else if (*pOplock & REQ_BATCHOPLOCK) {
+ pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
+ }
+ pSMB->DesiredAccess = cpu_to_le32(access_flags);
+ pSMB->AllocationSize = 0;
+ pSMB->FileAttributes = ATTR_NORMAL;
+ /* XP does not handle ATTR_POSIX_SEMANTICS */
+ /* but it helps speed up case sensitive checks for other
+ servers such as Samba */
+ if (tcon->ses->capabilities & CAP_UNIX)
+ pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
+
+ /* if ((omode & S_IWUGO) == 0)
+ pSMB->FileAttributes |= ATTR_READONLY;*/
+ /* Above line causes problems due to vfs splitting create into two
+ pieces - need to set mode after file created not while it is
+ being created */
+ pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
+ pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
+ pSMB->CreateDisposition = cpu_to_le32(openDisposition);
+ pSMB->CreateOptions = cpu_to_le32(create_options);
+ pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
+ pSMB->SecurityFlags =
+ cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
+
+ pSMB->ByteCount += name_len;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ /* long_op set to 1 to allow for oplock break timeouts */
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 1);
+ if (rc) {
+ cFYI(1, ("Error in Open = %d", rc));
+ } else {
+ *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
+ *netfid = pSMBr->Fid; /* cifs fid stays in le */
+ /* Let caller know file was created so we can set the mode. */
+ /* Do we care about the CreateAction in any other cases? */
+ if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
+ *pOplock |= CIFS_CREATE_ACTION;
+ if(pfile_info) {
+ memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
+ 36 /* CreationTime to Attributes */);
+ /* the file_info buf is endian converted by caller */
+ pfile_info->AllocationSize = pSMBr->AllocationSize;
+ pfile_info->EndOfFile = pSMBr->EndOfFile;
+ pfile_info->NumberOfLinks = cpu_to_le32(1);
+ }
+
+#ifdef CONFIG_CIFS_STATS
+ atomic_inc(&tcon->num_opens);
+#endif
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto openRetry;
+ return rc;
+}
+
+/* If no buffer passed in, then caller wants to do the copy
+ as in the case of readpages so the SMB buffer must be
+ freed by the caller */
+
+int
+CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
+ const int netfid, const unsigned int count,
+ const __u64 lseek, unsigned int *nbytes, char **buf)
+{
+ int rc = -EACCES;
+ READ_REQ *pSMB = NULL;
+ READ_RSP *pSMBr = NULL;
+ char *pReadData = NULL;
+ int bytes_returned;
+
+ *nbytes = 0;
+ rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ /* tcon and ses pointer are checked in smb_init */
+ if (tcon->ses->server == NULL)
+ return -ECONNABORTED;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
+ pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
+ pSMB->Remaining = 0;
+ pSMB->MaxCount = cpu_to_le16(count);
+ pSMB->MaxCountHigh = 0;
+ pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cERROR(1, ("Send error in read = %d", rc));
+ } else {
+ pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
+ *nbytes = pSMBr->DataLength;
+ /*check that DataLength would not go beyond end of SMB */
+ if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
+ || (pSMBr->DataLength > count)) {
+ cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
+ rc = -EIO;
+ *nbytes = 0;
+ } else {
+ pReadData =
+ (char *) (&pSMBr->hdr.Protocol) +
+ le16_to_cpu(pSMBr->DataOffset);
+/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
+ cERROR(1,("Faulting on read rc = %d",rc));
+ rc = -EFAULT;
+ }*/ /* can not use copy_to_user when using page cache*/
+ if(*buf)
+ memcpy(*buf,pReadData,pSMBr->DataLength);
+ }
+ }
+ if (pSMB) {
+ if(*buf)
+ cifs_buf_release(pSMB);
+ else
+ *buf = (char *)pSMB;
+ }
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+ return rc;
+}
+
+int
+CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
+ const int netfid, const unsigned int count,
+ const __u64 offset, unsigned int *nbytes, const char *buf,
+ const int long_op)
+{
+ int rc = -EACCES;
+ WRITE_REQ *pSMB = NULL;
+ WRITE_RSP *pSMBr = NULL;
+ int bytes_returned;
+
+ rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+ /* tcon and ses pointer are checked in smb_init */
+ if (tcon->ses->server == NULL)
+ return -ECONNABORTED;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+ pSMB->Remaining = 0;
+ if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
+ pSMB->DataLengthLow =
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
+ else
+ pSMB->DataLengthLow = count;
+ pSMB->DataLengthHigh = 0;
+ pSMB->DataOffset =
+ cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+
+ memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
+
+ pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
+ pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
+ if (rc) {
+ cFYI(1, ("Send error in write = %d", rc));
+ *nbytes = 0;
+ } else
+ *nbytes = le16_to_cpu(pSMBr->Count);
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
+ const __u16 smb_file_id, const __u64 len,
+ const __u64 offset, const __u32 numUnlock,
+ const __u32 numLock, const __u8 lockType, const int waitFlag)
+{
+ int rc = 0;
+ LOCK_REQ *pSMB = NULL;
+ LOCK_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int timeout = 0;
+ __u64 temp;
+
+ cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
+ rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
+ timeout = -1; /* no response expected */
+ pSMB->Timeout = 0;
+ } else if (waitFlag == TRUE) {
+ timeout = 3; /* blocking operation, no timeout */
+ pSMB->Timeout = -1; /* blocking - do not time out */
+ } else {
+ pSMB->Timeout = 0;
+ }
+
+ pSMB->NumberOfLocks = cpu_to_le32(numLock);
+ pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
+ pSMB->LockType = lockType;
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = smb_file_id; /* netfid stays le */
+
+ if(numLock != 0) {
+ pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
+ /* BB where to store pid high? */
+ temp = cpu_to_le64(len);
+ pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
+ pSMB->Locks[0].LengthHigh = (__u32)(temp>>32);
+ temp = cpu_to_le64(offset);
+ pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
+ pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
+ pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
+ } else {
+ /* oplock break */
+ pSMB->ByteCount = 0;
+ }
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+
+ if (rc) {
+ cFYI(1, ("Send error in Lock = %d", rc));
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+ return rc;
+}
+
+int
+CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
+{
+ int rc = 0;
+ CLOSE_REQ *pSMB = NULL;
+ CLOSE_RSP *pSMBr = NULL;
+ int bytes_returned;
+ cFYI(1, ("In CIFSSMBClose"));
+
+/* do not retry on dead session on close */
+ rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if(rc == -EAGAIN)
+ return 0;
+ if (rc)
+ return rc;
+
+ pSMB->FileID = (__u16) smb_file_id;
+ pSMB->LastWriteTime = 0;
+ pSMB->ByteCount = 0;
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ if(rc!=-EINTR) {
+ /* EINTR is expected when user ctl-c to kill app */
+ cERROR(1, ("Send error in Close = %d", rc));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Since session is dead, file will be closed on server already */
+ if(rc == -EAGAIN)
+ rc = 0;
+
+ return rc;
+}
+
+int
+CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ RENAME_REQ *pSMB = NULL;
+ RENAME_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len, name_len2;
+
+ cFYI(1, ("In CIFSSMBRename"));
+renameRetry:
+ rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->BufferFormat = 0x04;
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->OldFileName[name_len] = 0x04; /* pad */
+ /* protocol requires ASCII signature byte on Unicode string */
+ pSMB->OldFileName[name_len + 1] = 0x00;
+ name_len2 =
+ cifs_strtoUCS((wchar_t *) & pSMB->
+ OldFileName[name_len + 2], toName, 530,
+ nls_codepage);
+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
+ name_len2 *= 2; /* convert to bytes */
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fromName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->OldFileName, fromName, name_len);
+ name_len2 = strnlen(toName, 530);
+ name_len2++; /* trailing null */
+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
+ name_len2++; /* trailing null */
+ name_len2++; /* signature byte */
+ }
+
+ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in rename = %d", rc));
+ }
+
+#ifdef CONFIG_CIFS_STATS
+ else {
+ atomic_inc(&tcon->num_renames);
+ }
+#endif
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto renameRetry;
+
+ return rc;
+}
+
+int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
+ int netfid, char * target_name, const struct nls_table * nls_codepage)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+ struct set_file_rename * rename_info;
+ char *data_offset;
+ char dummy_string[30];
+ int rc = 0;
+ int bytes_returned = 0;
+ int len_of_str;
+
+ cFYI(1, ("Rename to File by handle"));
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->ParameterCount = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
+ Fid) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+
+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ rename_info = (struct set_file_rename *) data_offset;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ /* construct random name ".cifs_tmp<inodenum><mid>" */
+ rename_info->overwrite = cpu_to_le32(1);
+ rename_info->root_fid = 0;
+ /* unicode only call */
+ if(target_name == NULL) {
+ sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
+ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
+ } else {
+ len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
+ }
+ rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
+ pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
+ pSMB->ByteCount += pSMB->DataCount;
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->Fid = netfid;
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1,("Send error in Rename (by file handle) = %d", rc));
+ }
+#ifdef CONFIG_CIFS_STATS
+ else {
+ atomic_inc(&pTcon->num_t2renames);
+ }
+#endif
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
+ const __u16 target_tid, const char *toName, const int flags,
+ const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ COPY_REQ *pSMB = NULL;
+ COPY_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len, name_len2;
+
+ cFYI(1, ("In CIFSSMBCopy"));
+copyRetry:
+ rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->BufferFormat = 0x04;
+ pSMB->Tid2 = target_tid;
+
+ if(flags & COPY_TREE)
+ pSMB->Flags |= COPY_TREE;
+ pSMB->Flags = cpu_to_le16(pSMB->Flags);
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
+ fromName,
+ 530 /* find define for this maxpathcomponent */,
+ nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->OldFileName[name_len] = 0x04; /* pad */
+ /* protocol requires ASCII signature byte on Unicode string */
+ pSMB->OldFileName[name_len + 1] = 0x00;
+ name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
+ OldFileName[name_len + 2], toName, 530,
+ nls_codepage);
+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
+ name_len2 *= 2; /* convert to bytes */
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fromName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->OldFileName, fromName, name_len);
+ name_len2 = strnlen(toName, 530);
+ name_len2++; /* trailing null */
+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
+ name_len2++; /* trailing null */
+ name_len2++; /* signature byte */
+ }
+
+ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in copy = %d with %d files copied",
+ rc, pSMBr->CopyCount));
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto copyRetry;
+
+ return rc;
+}
+
+int
+CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ char *data_offset;
+ int name_len;
+ int name_len_target;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In Symlink Unix style"));
+createSymLinkRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fromName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fromName, name_len);
+ }
+ pSMB->ParameterCount = 6 + name_len;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+
+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len_target =
+ cifs_strtoUCS((wchar_t *) data_offset, toName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len_target++; /* trailing null */
+ name_len_target *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len_target = strnlen(toName, 530);
+ name_len_target++; /* trailing null */
+ strncpy(data_offset, toName, name_len_target);
+ }
+
+ pSMB->DataCount = name_len_target;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max on data count below from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1,
+ ("Send error in SetPathInfo (create symlink) = %d",
+ rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto createSymLinkRetry;
+
+ return rc;
+}
+
+int
+CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ char *data_offset;
+ int name_len;
+ int name_len_target;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In Create Hard link Unix style"));
+createHardLinkRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(toName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, toName, name_len);
+ }
+ pSMB->ParameterCount = 6 + name_len;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+
+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len_target =
+ cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len_target++; /* trailing null */
+ name_len_target *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len_target = strnlen(fromName, 530);
+ name_len_target++; /* trailing null */
+ strncpy(data_offset, fromName, name_len_target);
+ }
+
+ pSMB->DataCount = name_len_target;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max on data count below from sess*/
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto createHardLinkRetry;
+
+ return rc;
+}
+
+int
+CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ NT_RENAME_REQ *pSMB = NULL;
+ RENAME_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len, name_len2;
+
+ cFYI(1, ("In CIFSCreateHardLink"));
+winCreateHardLinkRetry:
+
+ rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+ pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
+ pSMB->ClusterCount = 0;
+
+ pSMB->BufferFormat = 0x04;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->OldFileName[name_len] = 0; /* pad */
+ pSMB->OldFileName[name_len + 1] = 0x04;
+ name_len2 =
+ cifs_strtoUCS((wchar_t *) & pSMB->
+ OldFileName[name_len + 2], toName, 530,
+ nls_codepage);
+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
+ name_len2 *= 2; /* convert to bytes */
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fromName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->OldFileName, fromName, name_len);
+ name_len2 = strnlen(toName, 530);
+ name_len2++; /* trailing null */
+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
+ strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
+ name_len2++; /* trailing null */
+ name_len2++; /* signature byte */
+ }
+
+ pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto winCreateHardLinkRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ char *symlinkinfo, const int buflen,
+ const struct nls_table *nls_codepage)
+{
+/* SMB_QUERY_FILE_UNIX_LINK */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
+
+querySymLinkRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ pSMB->TotalParameterCount =
+ 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
+ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+ /* BB also check enough total bytes returned */
+ rc = -EIO; /* bad smb */
+ else {
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = UniStrnlen((wchar_t *) ((char *)
+ &pSMBr->hdr.Protocol +pSMBr->DataOffset),
+ min_t(const int, buflen,pSMBr->DataCount) / 2);
+ cifs_strfromUCS_le(symlinkinfo,
+ (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
+ pSMBr->DataOffset),
+ name_len, nls_codepage);
+ } else {
+ strncpy(symlinkinfo,
+ (char *) &pSMBr->hdr.Protocol +
+ pSMBr->DataOffset,
+ min_t(const int, buflen, pSMBr->DataCount));
+ }
+ symlinkinfo[buflen] = 0;
+ /* just in case so calling code does not go off the end of buffer */
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto querySymLinkRetry;
+ return rc;
+}
+
+
+
+int
+CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ char *symlinkinfo, const int buflen,__u16 fid,
+ const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ struct smb_com_transaction_ioctl_req * pSMB;
+ struct smb_com_transaction_ioctl_rsp * pSMBr;
+
+ cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->TotalParameterCount = 0 ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le32(2);
+ /* BB find exact data count max from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le32(4000);
+ pSMB->MaxSetupCount = 4;
+ pSMB->Reserved = 0;
+ pSMB->ParameterOffset = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 4;
+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
+ pSMB->IsFsctl = 1; /* FSCTL */
+ pSMB->IsRootFlag = 0;
+ pSMB->Fid = fid; /* file handle always le */
+ pSMB->ByteCount = 0;
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
+ if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+ /* BB also check enough total bytes returned */
+ rc = -EIO; /* bad smb */
+ else {
+ if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
+ /* could also validate reparse tag && better check name length */
+ struct reparse_data * reparse_buf = (struct reparse_data *)
+ ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = UniStrnlen((wchar_t *)
+ (reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset),
+ min(buflen/2, reparse_buf->TargetNameLen / 2));
+ cifs_strfromUCS_le(symlinkinfo,
+ (wchar_t *) (reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset),
+ name_len, nls_codepage);
+ } else { /* ASCII names */
+ strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset,
+ min_t(const int, buflen, reparse_buf->TargetNameLen));
+ }
+ } else {
+ rc = -EIO;
+ cFYI(1,("Invalid return data count on get reparse info ioctl"));
+ }
+ symlinkinfo[buflen] = 0; /* just in case so the caller
+ does not go off the end of the buffer */
+ cFYI(1,("readlink result - %s ",symlinkinfo));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ FILE_ALL_INFO * pFindData,
+ const struct nls_table *nls_codepage)
+{
+/* level 263 SMB_QUERY_FILE_ALL_INFO */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In QPathInfo path %s", searchName));
+QPathInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
+ name_len /* includes null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in QPathInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ /* BB also check enough total bytes returned */
+ /* BB we need to improve the validity checking
+ of these trans2 responses */
+ if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
+ rc = -EIO; /* bad smb */
+ else if (pFindData){
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
+ } else
+ rc = -ENOMEM;
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QPathInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ FILE_UNIX_BASIC_INFO * pFindData,
+ const struct nls_table *nls_codepage)
+{
+/* SMB_QUERY_FILE_UNIX_BASIC */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned = 0;
+ int name_len;
+
+ cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
+UnixQPathInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
+ name_len /* includes null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in QPathInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ /* BB also check if enough total bytes returned */
+ if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
+ (pSMBr->DataOffset > 512) ||
+ (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
+ cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
+ (int)pSMBr->DataOffset,bytes_returned));
+ rc = -EIO; /* bad smb */
+ } else {
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ pSMBr->DataOffset,
+ sizeof (FILE_UNIX_BASIC_INFO));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto UnixQPathInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
+ const char *searchName, FILE_ALL_INFO * findData,
+ const struct nls_table *nls_codepage)
+{
+/* level 257 SMB_ */
+ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In FindUnique"));
+findUniqueRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+ pSMB->TotalDataCount = 0; /* no EAs */
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(
+ offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1; /* one byte, no need to le convert */
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+ pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
+ pSMB->SearchFlags = cpu_to_le16(1);
+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
+ pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+ if (rc) {
+ cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
+ } else { /* decode response */
+
+ /* BB fill in */
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto findUniqueRetry;
+
+ return rc;
+}
+
+int
+CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
+ const char *searchName, FILE_DIRECTORY_INFO * findData,
+ T2_FFIRST_RSP_PARMS * findParms,
+ const struct nls_table *nls_codepage, int *pUnicodeFlag,
+ int *pUnixFlag)
+{
+/* level 257 SMB_ */
+ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
+ char *response_data;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In FindFirst"));
+findFirstRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+ pSMB->TotalDataCount = 0; /* no EAs */
+ pSMB->MaxParameterCount = cpu_to_le16(10);
+ pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
+ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
+ smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+ pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
+ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
+
+ /* test for Unix extensions */
+ if (tcon->ses->capabilities & CAP_UNIX) {
+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
+ *pUnixFlag = TRUE;
+ } else {
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
+ *pUnixFlag = FALSE;
+ }
+ pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+ if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
+ cFYI(1, ("Error in FindFirst = %d", rc));
+ } else { /* decode response */
+ /* BB add safety checks for these memcpys */
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ *pUnicodeFlag = TRUE;
+ else
+ *pUnicodeFlag = FALSE;
+ memcpy(findParms,
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->ParameterOffset),
+ sizeof (T2_FFIRST_RSP_PARMS));
+ /* search handle can stay LE and EAoffset not needed so not converted */
+ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
+ findParms->LastNameOffset =
+ le16_to_cpu(findParms->LastNameOffset);
+ findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
+ response_data =
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->DataOffset);
+ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto findFirstRetry;
+
+ return rc;
+}
+
+int
+CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
+ FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
+ const __u16 searchHandle, char * resume_file_name, int name_len,
+ __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
+{
+/* level 257 SMB_ */
+ TRANSACTION2_FNEXT_REQ *pSMB = NULL;
+ TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
+ char *response_data;
+ int rc = 0;
+ int bytes_returned;
+
+ cFYI(1, ("In FindNext"));
+
+ if(resume_file_name == NULL) {
+ return -EIO;
+ }
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
+ pSMB->TotalDataCount = 0; /* no EAs */
+ pSMB->MaxParameterCount = cpu_to_le16(8);
+ pSMB->MaxDataCount =
+ cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
+ pSMB->SearchHandle = searchHandle; /* always kept as le */
+ findParms->SearchCount = 0; /* set to zero in case of error */
+ pSMB->SearchCount =
+ cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
+ /* test for Unix extensions */
+ if (tcon->ses->capabilities & CAP_UNIX) {
+ pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
+ *pUnixFlag = TRUE;
+ } else {
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
+ *pUnixFlag = FALSE;
+ }
+ pSMB->ResumeKey = resume_key;
+ pSMB->SearchFlags =
+ cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
+ /* BB add check to make sure we do not cross end of smb */
+ if(name_len < CIFS_MAX_MSGSIZE) {
+ memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
+ pSMB->ByteCount += name_len;
+ }
+ pSMB->TotalParameterCount += name_len;
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ /* BB improve error handling here */
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+ if (rc) {
+ if (rc == -EBADF)
+ rc = 0; /* search probably was closed at end of search above */
+ else
+ cFYI(1, ("FindNext returned = %d", rc));
+ } else { /* decode response */
+ /* BB add safety checks for these memcpys */
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ *pUnicodeFlag = TRUE;
+ else
+ *pUnicodeFlag = FALSE;
+ memcpy(findParms,
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->ParameterOffset),
+ sizeof (T2_FNEXT_RSP_PARMS));
+ findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
+ findParms->LastNameOffset =
+ le16_to_cpu(findParms->LastNameOffset);
+ findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
+ response_data =
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->DataOffset);
+ memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
+{
+ int rc = 0;
+ FINDCLOSE_REQ *pSMB = NULL;
+ CLOSE_RSP *pSMBr = NULL;
+ int bytes_returned;
+
+ cFYI(1, ("In CIFSSMBFindClose"));
+ rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ /* no sense returning error if session restarted
+ file handle has been closed */
+ if(rc == -EAGAIN)
+ return 0;
+ if (rc)
+ return rc;
+
+ pSMB->FileID = searchHandle;
+ pSMB->ByteCount = 0;
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cERROR(1, ("Send error in FindClose = %d", rc));
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Since session is dead, search handle closed on server already */
+ if (rc == -EAGAIN)
+ rc = 0;
+
+ return rc;
+}
+
+int
+CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
+ const unsigned char *searchName,
+ unsigned char **targetUNCs,
+ unsigned int *number_of_UNC_in_array,
+ const struct nls_table *nls_codepage)
+{
+/* TRANS2_GET_DFS_REFERRAL */
+ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
+ TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
+ struct dfs_referral_level_3 * referrals = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ unsigned int i;
+ char * temp;
+ *number_of_UNC_in_array = 0;
+ *targetUNCs = NULL;
+
+ cFYI(1, ("In GetDFSRefer the path %s", searchName));
+ if (ses == NULL)
+ return -ENODEV;
+getDFSRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Tid = ses->ipc_tid;
+ pSMB->hdr.Uid = ses->Suid;
+ if (ses->capabilities & CAP_STATUS32) {
+ pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ pSMB->hdr.Flags2 |= SMBFLG2_DFS;
+ }
+
+ if (ses->capabilities & CAP_UNICODE) {
+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
+ searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->RequestFileName, searchName, name_len);
+ }
+
+ pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->MaxParameterCount = 0;
+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
+ pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->MaxReferralLevel = cpu_to_le16(3);
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in GetDFSRefer = %d", rc));
+ } else { /* decode response */
+/* BB Add logic to parse referrals here */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
+ cFYI(1,
+ ("Decoding GetDFSRefer response. BCC: %d Offset %d",
+ pSMBr->ByteCount, pSMBr->DataOffset));
+ if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
+ rc = -EIO; /* bad smb */
+ else {
+ referrals =
+ (struct dfs_referral_level_3 *)
+ (8 /* sizeof start of data block */ +
+ pSMBr->DataOffset +
+ (char *) &pSMBr->hdr.Protocol);
+ cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
+ /* BB This field is actually two bytes in from start of
+ data block so we could do safety check that DataBlock
+ begins at address of pSMBr->NumberOfReferrals */
+ *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
+
+ /* BB Fix below so can return more than one referral */
+ if(*number_of_UNC_in_array > 1)
+ *number_of_UNC_in_array = 1;
+
+ /* get the length of the strings describing refs */
+ name_len = 0;
+ for(i=0;i<*number_of_UNC_in_array;i++) {
+ /* make sure that DfsPathOffset not past end */
+ referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
+ if(referrals->DfsPathOffset > pSMBr->DataCount) {
+ /* if invalid referral, stop here and do
+ not try to copy any more */
+ *number_of_UNC_in_array = i;
+ break;
+ }
+ temp = ((char *)referrals) + referrals->DfsPathOffset;
+
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
+ } else {
+ name_len += strnlen(temp,pSMBr->DataCount);
+ }
+ referrals++;
+ /* BB add check that referral pointer does not fall off end PDU */
+
+ }
+ /* BB add check for name_len bigger than bcc */
+ *targetUNCs =
+ kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
+ /* copy the ref strings */
+ referrals =
+ (struct dfs_referral_level_3 *)
+ (8 /* sizeof data hdr */ +
+ pSMBr->DataOffset +
+ (char *) &pSMBr->hdr.Protocol);
+
+ for(i=0;i<*number_of_UNC_in_array;i++) {
+ temp = ((char *)referrals) + referrals->DfsPathOffset;
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+ cifs_strfromUCS_le(*targetUNCs,
+ (wchar_t *) temp, name_len, nls_codepage);
+ } else {
+ strncpy(*targetUNCs,temp,name_len);
+ }
+ /* BB update target_uncs pointers */
+ referrals++;
+ }
+ temp = *targetUNCs;
+ temp[name_len] = 0;
+ }
+
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto getDFSRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
+ struct statfs *FSData, const struct nls_table *nls_codepage)
+{
+/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In QFSInfo"));
+QFSInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->TotalParameterCount = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cERROR(1, ("Send error in QFSInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ cFYI(1,
+ ("Decoding qfsinfo response. BCC: %d Offset %d",
+ pSMBr->ByteCount, pSMBr->DataOffset));
+ if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
+ rc = -EIO; /* bad smb */
+ else {
+ response_data =
+ (FILE_SYSTEM_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ pSMBr->DataOffset);
+ FSData->f_bsize =
+ le32_to_cpu(response_data->BytesPerSector) *
+ le32_to_cpu(response_data->
+ SectorsPerAllocationUnit);
+ FSData->f_blocks =
+ le64_to_cpu(response_data->TotalAllocationUnits);
+ FSData->f_bfree = FSData->f_bavail =
+ le64_to_cpu(response_data->FreeAllocationUnits);
+ cFYI(1,
+ ("Blocks: %lld Free: %lld Block size %ld",
+ (unsigned long long)FSData->f_blocks,
+ (unsigned long long)FSData->f_bfree,
+ FSData->f_bsize));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
+ const struct nls_table *nls_codepage)
+{
+/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In QFSAttributeInfo"));
+QFSAttributeRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->TotalParameterCount = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
+ rc = -EIO; /* bad smb */
+ } else {
+ response_data =
+ (FILE_SYSTEM_ATTRIBUTE_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ pSMBr->DataOffset);
+ response_data->Attributes = le32_to_cpu(response_data->Attributes);
+ response_data->MaxPathNameComponentLength =
+ le32_to_cpu(response_data->MaxPathNameComponentLength);
+ response_data->FileSystemNameLen =
+ le32_to_cpu(response_data->FileSystemNameLen);
+ memcpy(&tcon->fsAttrInfo, response_data,
+ sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSAttributeRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
+ const struct nls_table *nls_codepage)
+{
+/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_DEVICE_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In QFSDeviceInfo"));
+QFSDeviceRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->TotalParameterCount = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
+ || (pSMBr->DataOffset > 512))
+ rc = -EIO; /* bad smb */
+ else {
+ response_data =
+ (FILE_SYSTEM_DEVICE_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ pSMBr->DataOffset);
+ response_data->DeviceType =
+ le32_to_cpu(response_data->DeviceType);
+ response_data->DeviceCharacteristics =
+ le32_to_cpu(response_data->DeviceCharacteristics);
+ memcpy(&tcon->fsDevInfo, response_data,
+ sizeof (FILE_SYSTEM_DEVICE_INFO));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSDeviceRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
+ const struct nls_table *nls_codepage)
+{
+/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_UNIX_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In QFSUnixInfo"));
+QFSUnixRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->ParameterCount = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
+ smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
+ if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
+ rc = -EIO; /* bad smb */
+ } else {
+ response_data =
+ (FILE_SYSTEM_UNIX_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ pSMBr->DataOffset);
+ response_data->MajorVersionNumber =
+ le16_to_cpu(response_data->MajorVersionNumber);
+ response_data->MinorVersionNumber =
+ le16_to_cpu(response_data->MinorVersionNumber);
+ response_data->Capability =
+ le64_to_cpu(response_data->Capability);
+ memcpy(&tcon->fsUnixInfo, response_data,
+ sizeof (FILE_SYSTEM_UNIX_INFO));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSUnixRetry;
+
+
+ return rc;
+}
+
+/* We can not use write of zero bytes trick to
+ set file size due to need for large file support. Also note that
+ this SetPathInfo is preferred to SetFileInfo based method in next
+ routine which is only needed to work around a sharing violation bug
+ in Samba which this routine can run into */
+
+int
+CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
+ __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
+{
+ struct smb_com_transaction2_spi_req *pSMB = NULL;
+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+ struct file_end_of_file_info *parm_data;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+
+ cFYI(1, ("In SetEOF"));
+SetEOFRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+ pSMB->ParameterCount = 6 + name_len;
+ pSMB->DataCount = sizeof (struct file_end_of_file_info);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ if(SetAllocation) {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
+ } else /* Set File Size */ {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
+ }
+
+ parm_data =
+ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
+ pSMB->DataOffset);
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ parm_data->FileSize = cpu_to_le64(size);
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("SetPathInfo (file size) returned %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetEOFRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
+ __u16 fid, __u32 pid_of_opener, int SetAllocation)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+ char *data_offset;
+ struct file_end_of_file_info *parm_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u32 tmp;
+
+ cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
+ (long long)size));
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
+ so network fid will be valid */
+ pSMB->hdr.Pid = tmp & 0xFFFF;
+ tmp >>= 16;
+ pSMB->hdr.PidHigh = tmp & 0xFFFF;
+
+ pSMB->ParameterCount = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
+ Fid) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+
+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+
+ pSMB->DataCount = sizeof(struct file_end_of_file_info);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ parm_data =
+ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
+ pSMB->DataOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
+ parm_data->FileSize = cpu_to_le64(size);
+ pSMB->Fid = fid;
+ if(SetAllocation) {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
+ } else /* Set File Size */ {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
+ }
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1,
+ ("Send error in SetFileInfo (SetFileSize) = %d",
+ rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
+ FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ char *data_offset;
+
+ cFYI(1, ("In SetTimes"));
+
+SetTimesRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+
+ pSMB->ParameterCount = 6 + name_len;
+ pSMB->DataCount = sizeof (FILE_BASIC_INFO);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+ else
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("SetPathInfo (times) returned %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetTimesRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
+ char *fileName, __u64 mode, __u64 uid, __u64 gid,
+ dev_t device, const struct nls_table *nls_codepage)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ FILE_UNIX_BASIC_INFO *data_offset;
+
+ cFYI(1, ("In SetUID/GID/Mode"));
+setPermsRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+ }
+
+ pSMB->ParameterCount = 6 + name_len;
+ pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+ data_offset =
+ (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
+ pSMB->DataOffset);
+ pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+ pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+ pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ data_offset->Uid = cpu_to_le64(uid);
+ data_offset->Gid = cpu_to_le64(gid);
+ /* better to leave device as zero when it is */
+ data_offset->DevMajor = cpu_to_le64(MAJOR(device));
+ data_offset->DevMinor = cpu_to_le64(MINOR(device));
+ data_offset->Permissions = cpu_to_le64(mode);
+
+ if(S_ISREG(mode))
+ data_offset->Type = cpu_to_le32(UNIX_FILE);
+ else if(S_ISDIR(mode))
+ data_offset->Type = cpu_to_le32(UNIX_DIR);
+ else if(S_ISLNK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
+ else if(S_ISCHR(mode))
+ data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
+ else if(S_ISBLK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
+ else if(S_ISFIFO(mode))
+ data_offset->Type = cpu_to_le32(UNIX_FIFO);
+ else if(S_ISSOCK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_SOCKET);
+
+
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("SetPathInfo (perms) returned %d", rc));
+ }
+
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto setPermsRetry;
+ return rc;
+}
+
+int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
+ const int notify_subdirs, const __u16 netfid,
+ __u32 filter, const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ struct smb_com_transaction_change_notify_req * pSMB = NULL;
+ struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
+ int bytes_returned;
+
+ cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->TotalParameterCount = 0 ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le32(2);
+ /* BB find exact data count max from sess structure BB */
+ pSMB->MaxDataCount = 0; /* same in little endian or be */
+ pSMB->MaxSetupCount = 4;
+ pSMB->Reserved = 0;
+ pSMB->ParameterOffset = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 4; /* single byte does not need le conversion */
+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ if(notify_subdirs)
+ pSMB->WatchTree = 1; /* one byte - no le conversion needed */
+ pSMB->Reserved2 = 0;
+ pSMB->CompletionFilter = cpu_to_le32(filter);
+ pSMB->Fid = netfid; /* file handle always le */
+ pSMB->ByteCount = 0;
+
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Error in Notify = %d", rc));
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+/* if (rc == -EAGAIN)
+ goto NotifyRetry; */
+ return rc;
+}
+#ifdef CONFIG_CIFS_XATTR
+int
+CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+ char * EAData, size_t size,
+ const struct nls_table *nls_codepage)
+{
+ /* BB assumes one setup word */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In Query All EAs path %s", searchName));
+QAllEAsRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+ /* find define for this maxpathcomponent */
+ , nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, 530);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
+ name_len /* includes null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+ pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in QueryAllEAs = %d", rc));
+ } else { /* decode response */
+ pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+ /* BB also check enough total bytes returned */
+ /* BB we need to improve the validity checking
+ of these trans2 responses */
+ if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
+ rc = -EIO; /* bad smb */
+ /* else if (pFindData){
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ pSMBr->DataOffset, kl);
+ }*/ else {
+ /* check that length of list is not more than bcc */
+ /* check that each entry does not go beyond length
+ of list */
+ /* check that each element of each entry does not
+ go beyond end of list */
+ struct fealist * ea_response_data;
+ rc = 0;
+ /* validate_trans2_offsets() */
+ /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+ ea_response_data = (struct fealist *)
+ (((char *) &pSMBr->hdr.Protocol) +
+ pSMBr->DataOffset);
+ cFYI(1,("ea length %d",ea_response_data->list_len));
+ }
+ }
+ if (pSMB)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QAllEAsRetry;
+
+ return rc;
+}
+#endif
diff --git a/release/src/linux/linux/fs/cifs/connect.c b/release/src/linux/linux/fs/cifs/connect.c
new file mode 100644
index 00000000..76e4a04f
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/connect.c
@@ -0,0 +1,2925 @@
+/*
+ * fs/cifs/connect.c
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2004
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/version.h>
+#include <linux/ipv6.h>
+#include <linux/pagemap.h>
+#include <linux/ctype.h>
+#include <linux/utsname.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+#include "rfc1002pdu.h"
+
+#define CIFS_PORT 445
+#define RFC1001_PORT 139
+
+extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
+ unsigned char *p24);
+extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
+ unsigned char *p24);
+extern int cifs_inet_pton(int, const char *, void *dst);
+
+struct smb_vol {
+ char *username;
+ char *password;
+ char *domainname;
+ char *UNC;
+ char *UNCip;
+ char *iocharset; /* local code page for mapping to and from Unicode */
+ char source_rfc1001_name[16]; /* netbios name of client */
+ uid_t linux_uid;
+ gid_t linux_gid;
+ mode_t file_mode;
+ mode_t dir_mode;
+ int rw:1;
+ int retry:1;
+ int intr:1;
+ unsigned int rsize;
+ unsigned int wsize;
+ unsigned int sockopt;
+ unsigned short int port;
+};
+
+static int ipv4_connect(struct sockaddr_in *psin_server,
+ struct socket **csocket,
+ char * netb_name);
+static int ipv6_connect(struct sockaddr_in6 *psin_server,
+ struct socket **csocket);
+
+
+ /*
+ * cifs tcp session reconnection
+ *
+ * mark tcp session as reconnecting so temporarily locked
+ * mark all smb sessions as reconnecting for tcp session
+ * reconnect tcp session
+ * wake up waiters on reconnection? - (not needed currently)
+ */
+
+int
+cifs_reconnect(struct TCP_Server_Info *server)
+{
+ int rc = 0;
+ struct list_head *tmp;
+ struct cifsSesInfo *ses;
+ struct cifsTconInfo *tcon;
+ struct mid_q_entry * mid_entry;
+
+ spin_lock(&GlobalMid_Lock);
+ if(server->tcpStatus == CifsExiting) {
+ /* the demux thread will exit normally
+ next time through the loop */
+ spin_unlock(&GlobalMid_Lock);
+ return rc;
+ } else
+ server->tcpStatus = CifsNeedReconnect;
+ spin_unlock(&GlobalMid_Lock);
+ server->maxBuf = 0;
+
+ cFYI(1, ("Reconnecting tcp session "));
+
+ /* before reconnecting the tcp session, mark the smb session (uid)
+ and the tid bad so they are not used until reconnected */
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &GlobalSMBSessionList) {
+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
+ if (ses->server) {
+ if (ses->server == server) {
+ ses->status = CifsNeedReconnect;
+ ses->ipc_tid = 0;
+ }
+ }
+ /* else tcp and smb sessions need reconnection */
+ }
+ list_for_each(tmp, &GlobalTreeConnectionList) {
+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+ if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
+ tcon->tidStatus = CifsNeedReconnect;
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ /* do not want to be sending data on a socket we are freeing */
+ down(&server->tcpSem);
+ if(server->ssocket) {
+ cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
+ server->ssocket->flags));
+ server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
+ cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
+ server->ssocket->flags));
+ sock_release(server->ssocket);
+ server->ssocket = NULL;
+ }
+
+ spin_lock(&GlobalMid_Lock);
+ list_for_each(tmp, &server->pending_mid_q) {
+ mid_entry = list_entry(tmp, struct
+ mid_q_entry,
+ qhead);
+ if(mid_entry) {
+ if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
+ /* Mark other intransit requests as needing retry so
+ we do not immediately mark the session bad again
+ (ie after we reconnect below) as they timeout too */
+ mid_entry->midState = MID_RETRY_NEEDED;
+ }
+ }
+ }
+ spin_unlock(&GlobalMid_Lock);
+ up(&server->tcpSem);
+
+ while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
+ {
+ if(server->protocolType == IPV6) {
+ rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
+ } else {
+ rc = ipv4_connect(&server->addr.sockAddr,
+ &server->ssocket,
+ server->workstation_RFC1001_name);
+ }
+ if(rc) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(3 * HZ);
+ } else {
+ atomic_inc(&tcpSesReconnectCount);
+ spin_lock(&GlobalMid_Lock);
+ if(server->tcpStatus != CifsExiting)
+ server->tcpStatus = CifsGood;
+ spin_unlock(&GlobalMid_Lock);
+ /* atomic_set(&server->inFlight,0);*/
+ wake_up(&server->response_q);
+ }
+ }
+ return rc;
+}
+
+static int
+cifs_demultiplex_thread(struct TCP_Server_Info *server)
+{
+ int length;
+ unsigned int pdu_length, total_read;
+ struct smb_hdr *smb_buffer = NULL;
+ struct msghdr smb_msg;
+ mm_segment_t temp_fs;
+ struct iovec iov;
+ struct socket *csocket = server->ssocket;
+ struct list_head *tmp;
+ struct cifsSesInfo *ses;
+ struct task_struct *task_to_wake = NULL;
+ struct mid_q_entry *mid_entry;
+ char *temp;
+
+ daemonize();
+ sprintf(current->comm,"cifsd");
+ /* allow_signal(SIGKILL);*/
+ current->flags |= PF_MEMALLOC;
+ server->tsk = current; /* save process info to wake at shutdown */
+ cFYI(1, ("Demultiplex PID: %d", current->pid));
+
+ temp_fs = get_fs(); /* we must turn off socket api parm checking */
+ set_fs(get_ds());
+
+ while (server->tcpStatus != CifsExiting) {
+ if (smb_buffer == NULL)
+ smb_buffer = cifs_buf_get();
+ else
+ memset(smb_buffer, 0, sizeof (struct smb_hdr));
+
+ if (smb_buffer == NULL) {
+ cERROR(1,("Can not get memory for SMB response"));
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ * 3); /* give system time to free memory */
+ continue;
+ }
+ iov.iov_base = smb_buffer;
+ iov.iov_len = sizeof (struct smb_hdr) - 1;
+ /* 1 byte less above since wct is not always returned in error cases */
+ smb_msg.msg_iov = &iov;
+ smb_msg.msg_iovlen = 1;
+ smb_msg.msg_control = NULL;
+ smb_msg.msg_controllen = 0;
+
+ length =
+ sock_recvmsg(csocket, &smb_msg,
+ sizeof (struct smb_hdr) -
+ 1 /* RFC1001 header and SMB header */ ,
+ MSG_PEEK /* flags see socket.h */ );
+
+ if(server->tcpStatus == CifsExiting) {
+ break;
+ } else if (server->tcpStatus == CifsNeedReconnect) {
+ cFYI(1,("Reconnecting after server stopped responding"));
+ cifs_reconnect(server);
+ cFYI(1,("call to reconnect done"));
+ csocket = server->ssocket;
+ continue;
+ } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1); /* minimum sleep to prevent looping
+ allowing socket to clear and app threads to set
+ tcpStatus CifsNeedReconnect if server hung */
+ continue;
+ } else if (length <= 0) {
+ if(server->tcpStatus == CifsNew) {
+ cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
+ /* some servers kill tcp session rather than returning
+ smb negprot error in which case reconnecting here is
+ not going to help - return error to mount */
+ break;
+ }
+ if(length == -EINTR) {
+ cFYI(1,("cifsd thread killed"));
+ break;
+ }
+ cFYI(1,("Reconnecting after unexpected peek error %d",length));
+ cifs_reconnect(server);
+ csocket = server->ssocket;
+ wake_up(&server->response_q);
+ continue;
+ }
+
+ pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
+ /* Ony read pdu_length after below checks for too short (due
+ to e.g. int overflow) and too long ie beyond end of buf */
+ cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
+
+ temp = (char *) smb_buffer;
+ if (length > 3) {
+ if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
+ iov.iov_base = smb_buffer;
+ iov.iov_len = 4;
+ length = sock_recvmsg(csocket, &smb_msg, 4, 0);
+ cFYI(0,("Received 4 byte keep alive packet"));
+ } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
+ iov.iov_base = smb_buffer;
+ iov.iov_len = 4;
+ length = sock_recvmsg(csocket, &smb_msg, 4, 0);
+ cFYI(1,("Good RFC 1002 session rsp"));
+ } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
+ && (length == 5)) {
+ /* we get this from Windows 98 instead of error on SMB negprot response */
+ cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
+ if(server->tcpStatus == CifsNew) {
+ /* if nack on negprot (rather than
+ ret of smb negprot error) reconnecting
+ not going to help, ret error to mount */
+ break;
+ } else {
+ /* give server a second to
+ clean up before reconnect attempt */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ /* always try 445 first on reconnect
+ since we get NACK on some if we ever
+ connected to port 139 (the NACK is
+ since we do not begin with RFC1001
+ session initialize frame) */
+ server->addr.sockAddr.sin_port = CIFS_PORT;
+ cifs_reconnect(server);
+ csocket = server->ssocket;
+ wake_up(&server->response_q);
+ continue;
+ }
+ } else if (temp[0] != (char) 0) {
+ cERROR(1,("Unknown RFC 1002 frame"));
+ cifs_dump_mem(" Received Data: ", temp, length);
+ cifs_reconnect(server);
+ csocket = server->ssocket;
+ continue;
+ } else {
+ if ((length != sizeof (struct smb_hdr) - 1)
+ || (pdu_length >
+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
+ || (pdu_length <
+ sizeof (struct smb_hdr) - 1)
+ ||
+ (checkSMBhdr
+ (smb_buffer, smb_buffer->Mid))) {
+ cERROR(1,
+ ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
+ length, pdu_length));
+ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+ /* could we fix this network corruption by finding next
+ smb header (instead of killing the session) and
+ restart reading from next valid SMB found? */
+ cifs_reconnect(server);
+ csocket = server->ssocket;
+ continue;
+ } else { /* length ok */
+
+ length = 0;
+ iov.iov_base = smb_buffer;
+ iov.iov_len = pdu_length;
+ for (total_read = 0;
+ total_read < pdu_length;
+ total_read += length) {
+ length = sock_recvmsg(csocket, &smb_msg,
+ pdu_length - total_read, 0);
+ if (length == 0) {
+ cERROR(1,
+ ("Zero length receive when expecting %d ",
+ pdu_length - total_read));
+ cifs_reconnect(server);
+ csocket = server->ssocket;
+ continue;
+ }
+ }
+ }
+
+ dump_smb(smb_buffer, length);
+ if (checkSMB
+ (smb_buffer, smb_buffer->Mid, total_read)) {
+ cERROR(1, ("Bad SMB Received "));
+ continue;
+ }
+
+ task_to_wake = NULL;
+ spin_lock(&GlobalMid_Lock);
+ list_for_each(tmp, &server->pending_mid_q) {
+ mid_entry = list_entry(tmp, struct
+ mid_q_entry,
+ qhead);
+
+ if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
+ cFYI(1,
+ (" Mid 0x%x matched - waking up ",mid_entry->mid));
+ task_to_wake = mid_entry->tsk;
+ mid_entry->resp_buf =
+ smb_buffer;
+ mid_entry->midState =
+ MID_RESPONSE_RECEIVED;
+ }
+ }
+ spin_unlock(&GlobalMid_Lock);
+ if (task_to_wake) {
+ smb_buffer = NULL; /* will be freed by users thread after he is done */
+ wake_up_process(task_to_wake);
+ } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
+ cERROR(1, ("No task to wake, unknown frame rcvd!"));
+ cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+ }
+ }
+ } else {
+ cFYI(0,
+ ("Frame less than four bytes received %d bytes long.",
+ length));
+ if (length > 0) {
+ length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
+ cFYI(1,
+ (" with junk 0x%x in it ",
+ *(__u32 *) smb_buffer));
+ }
+ }
+ }
+ spin_lock(&GlobalMid_Lock);
+ server->tcpStatus = CifsExiting;
+ server->tsk = NULL;
+ atomic_set(&server->inFlight, 0);
+ spin_unlock(&GlobalMid_Lock);
+ /* Although there should not be any requests blocked on
+ this queue it can not hurt to be paranoid and try to wake up requests
+ that may haven been blocked when more than 50 at time were on the wire
+ to the same server - they now will see the session is in exit state
+ and get out of SendReceive. */
+ wake_up_all(&server->request_q);
+ /* give those requests time to exit */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/8);
+
+ if(server->ssocket) {
+ sock_release(csocket);
+ server->ssocket = NULL;
+ }
+ set_fs(temp_fs);
+ if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
+ cifs_buf_release(smb_buffer);
+
+ read_lock(&GlobalSMBSeslock);
+ if (list_empty(&server->pending_mid_q)) {
+ /* loop through server session structures attached to this and mark them dead */
+ list_for_each(tmp, &GlobalSMBSessionList) {
+ ses =
+ list_entry(tmp, struct cifsSesInfo,
+ cifsSessionList);
+ if (ses->server == server) {
+ ses->status = CifsExiting;
+ ses->server = NULL;
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ } else {
+ spin_lock(&GlobalMid_Lock);
+ list_for_each(tmp, &server->pending_mid_q) {
+ mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+ if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
+ cFYI(1,
+ (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
+ task_to_wake = mid_entry->tsk;
+ if(task_to_wake) {
+ wake_up_process(task_to_wake);
+ }
+ }
+ }
+ spin_unlock(&GlobalMid_Lock);
+ read_unlock(&GlobalSMBSeslock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ /* 1/8th of sec is more than enough time for them to exit */
+ schedule_timeout(HZ/8);
+ }
+
+ if (list_empty(&server->pending_mid_q)) {
+ /* mpx threads have not exited yet give them
+ at least the smb send timeout time for long ops */
+ cFYI(1, ("Wait for exit from demultiplex thread"));
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(46 * HZ);
+ /* if threads still have not exited they are probably never
+ coming home not much else we can do but free the memory */
+ }
+ kfree(server);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+ return 0;
+}
+
+static void *
+cifs_kcalloc(size_t size, int type)
+{
+ void *addr;
+ addr = kmalloc(size, type);
+ if (addr)
+ memset(addr, 0, size);
+ return addr;
+}
+
+static int
+cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
+{
+ char *value;
+ char *data;
+ unsigned int temp_len, i, j;
+ char separator[2];
+
+ separator[0] = ',';
+ separator[1] = 0;
+
+ memset(vol->source_rfc1001_name,0x20,15);
+ for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
+ /* does not have to be a perfect mapping since the field is
+ informational, only used for servers that do not support
+ port 445 and it can be overridden at mount time */
+ vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
+ }
+ vol->source_rfc1001_name[15] = 0;
+
+ vol->linux_uid = current->uid; /* current->euid instead? */
+ vol->linux_gid = current->gid;
+ vol->dir_mode = S_IRWXUGO;
+ /* 2767 perms indicate mandatory locking support */
+ vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
+
+ /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
+ vol->rw = TRUE;
+
+ if (!options)
+ return 1;
+
+ if(strncmp(options,"sep=",4) == 0) {
+ if(options[4] != 0) {
+ separator[0] = options[4];
+ options += 5;
+ } else {
+ cFYI(1,("Null separator not allowed"));
+ }
+ }
+
+ while ((data = strsep(&options, separator)) != NULL) {
+ if (!*data)
+ continue;
+ if ((value = strchr(data, '=')) != NULL)
+ *value++ = '\0';
+ if (strnicmp(data, "user", 4) == 0) {
+ if (!value || !*value) {
+ printk(KERN_WARNING
+ "CIFS: invalid or missing username\n");
+ return 1; /* needs_arg; */
+ }
+ if (strnlen(value, 200) < 200) {
+ vol->username = value;
+ } else {
+ printk(KERN_WARNING "CIFS: username too long\n");
+ return 1;
+ }
+ } else if (strnicmp(data, "pass", 4) == 0) {
+ if (!value || !*value) {
+ vol->password = NULL;
+ continue;
+ }
+ temp_len = strlen(value);
+ /* removed password length check, NTLM passwords
+ can be arbitrarily long */
+
+ /* if comma in password, the string will be
+ prematurely null terminated. Commas in password are
+ specified across the cifs mount interface by a double
+ comma ie ,, and a comma used as in other cases ie ','
+ as a parameter delimiter/separator is single and due
+ to the strsep above is temporarily zeroed. */
+
+ /* NB: password legally can have multiple commas and
+ the only illegal character in a password is null */
+
+ if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
+ /* reinsert comma */
+ value[temp_len] = separator[0];
+ temp_len+=2; /* move after the second comma */
+ while(value[temp_len] != 0) {
+ if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
+ /* single comma indicating start of next parm */
+ break;
+ }
+ temp_len++;
+ }
+ if(value[temp_len] == 0) {
+ options = NULL;
+ } else {
+ value[temp_len] = 0;
+ /* move options to point to start of next parm */
+ options = value + temp_len + 1;
+ }
+ /* go from value to (value + temp_len) condensing double commas to singles */
+ vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
+ for(i=0,j=0;i<temp_len;i++,j++) {
+ vol->password[j] = value[i];
+ if(value[i] == separator[0] && value[i+1] == separator[0]) {
+ /* skip second comma */
+ i++;
+ }
+ }
+ /* value[temp_len] is zeroed above so
+ vol->password[temp_len] guaranteed to be null */
+ } else {
+ vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
+ strcpy(vol->password, value);
+ }
+ } else if (strnicmp(data, "ip", 2) == 0) {
+ if (!value || !*value) {
+ vol->UNCip = NULL;
+ } else if (strnlen(value, 35) < 35) {
+ vol->UNCip = value;
+ } else {
+ printk(KERN_WARNING "CIFS: ip address too long\n");
+ return 1;
+ }
+ } else if ((strnicmp(data, "unc", 3) == 0)
+ || (strnicmp(data, "target", 6) == 0)
+ || (strnicmp(data, "path", 4) == 0)) {
+ if (!value || !*value) {
+ printk(KERN_WARNING
+ "CIFS: invalid path to network resource\n");
+ return 1; /* needs_arg; */
+ }
+ if ((temp_len = strnlen(value, 300)) < 300) {
+ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
+ if(vol->UNC == NULL)
+ return 1;
+ strcpy(vol->UNC,value);
+ if (strncmp(vol->UNC, "//", 2) == 0) {
+ vol->UNC[0] = '\\';
+ vol->UNC[1] = '\\';
+ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
+ printk(KERN_WARNING
+ "CIFS: UNC Path does not begin with // or \\\\ \n");
+ return 1;
+ }
+ } else {
+ printk(KERN_WARNING "CIFS: UNC name too long\n");
+ return 1;
+ }
+ } else if ((strnicmp(data, "domain", 3) == 0)
+ || (strnicmp(data, "workgroup", 5) == 0)) {
+ if (!value || !*value) {
+ printk(KERN_WARNING "CIFS: invalid domain name\n");
+ return 1; /* needs_arg; */
+ }
+ /* BB are there cases in which a comma can be valid in
+ a domain name and need special handling? */
+ if (strnlen(value, 65) < 65) {
+ vol->domainname = value;
+ cFYI(1, ("Domain name set"));
+ } else {
+ printk(KERN_WARNING "CIFS: domain name too long\n");
+ return 1;
+ }
+ } else if (strnicmp(data, "iocharset", 9) == 0) {
+ if (!value || !*value) {
+ printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
+ return 1; /* needs_arg; */
+ }
+ if (strnlen(value, 65) < 65) {
+ if(strnicmp(value,"default",7))
+ vol->iocharset = value;
+ /* if iocharset not set load_nls_default used by caller */
+ cFYI(1, ("iocharset set to %s",value));
+ } else {
+ printk(KERN_WARNING "CIFS: iocharset name too long.\n");
+ return 1;
+ }
+ } else if (strnicmp(data, "uid", 3) == 0) {
+ if (value && *value) {
+ vol->linux_uid =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "gid", 3) == 0) {
+ if (value && *value) {
+ vol->linux_gid =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "file_mode", 4) == 0) {
+ if (value && *value) {
+ vol->file_mode =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "dir_mode", 3) == 0) {
+ if (value && *value) {
+ vol->dir_mode =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "port", 4) == 0) {
+ if (value && *value) {
+ vol->port =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "rsize", 5) == 0) {
+ if (value && *value) {
+ vol->rsize =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "wsize", 5) == 0) {
+ if (value && *value) {
+ vol->wsize =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "sockopt", 5) == 0) {
+ if (value && *value) {
+ vol->sockopt =
+ simple_strtoul(value, &value, 0);
+ }
+ } else if (strnicmp(data, "netbiosname", 4) == 0) {
+ if (!value || !*value || (*value == ' ')) {
+ cFYI(1,("invalid (empty) netbiosname specified"));
+ } else {
+ memset(vol->source_rfc1001_name,0x20,15);
+ for(i=0;i<15;i++) {
+ /* BB are there cases in which a comma can be
+ valid in this workstation netbios name (and need
+ special handling)? */
+
+ /* We do not uppercase netbiosname for user */
+ if (value[i]==0)
+ break;
+ else
+ vol->source_rfc1001_name[i] = value[i];
+ }
+ /* The string has 16th byte zero still from
+ set at top of the function */
+ if((i==15) && (value[i] != 0))
+ printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
+ }
+ } else if (strnicmp(data, "credentials", 4) == 0) {
+ /* ignore */
+ } else if (strnicmp(data, "version", 3) == 0) {
+ /* ignore */
+ } else if (strnicmp(data, "rw", 2) == 0) {
+ vol->rw = TRUE;
+ } else if ((strnicmp(data, "suid", 4) == 0) ||
+ (strnicmp(data, "nosuid", 6) == 0) ||
+ (strnicmp(data, "exec", 4) == 0) ||
+ (strnicmp(data, "noexec", 6) == 0) ||
+ (strnicmp(data, "nodev", 5) == 0) ||
+ (strnicmp(data, "noauto", 6) == 0) ||
+ (strnicmp(data, "dev", 3) == 0)) {
+ /* The mount tool or mount.cifs helper (if present)
+ uses these opts to set flags, and the flags are read
+ by the kernel vfs layer before we get here (ie
+ before read super) so there is no point trying to
+ parse these options again and set anything and it
+ is ok to just ignore them */
+ continue;
+ } else if (strnicmp(data, "ro", 2) == 0) {
+ vol->rw = FALSE;
+ } else if (strnicmp(data, "hard", 4) == 0) {
+ vol->retry = 1;
+ } else if (strnicmp(data, "soft", 4) == 0) {
+ vol->retry = 0;
+ } else if (strnicmp(data, "nohard", 6) == 0) {
+ vol->retry = 0;
+ } else if (strnicmp(data, "nosoft", 6) == 0) {
+ vol->retry = 1;
+ } else if (strnicmp(data, "nointr", 6) == 0) {
+ vol->intr = 0;
+ } else if (strnicmp(data, "intr", 4) == 0) {
+ vol->intr = 1;
+ } else if (strnicmp(data, "noac", 4) == 0) {
+ printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
+ } else
+ printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
+ }
+ if (vol->UNC == NULL) {
+ if(devname == NULL) {
+ printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
+ return 1;
+ }
+ if ((temp_len = strnlen(devname, 300)) < 300) {
+ vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
+ if(vol->UNC == NULL)
+ return 1;
+ strcpy(vol->UNC,devname);
+ if (strncmp(vol->UNC, "//", 2) == 0) {
+ vol->UNC[0] = '\\';
+ vol->UNC[1] = '\\';
+ } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
+ printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
+ return 1;
+ }
+ } else {
+ printk(KERN_WARNING "CIFS: UNC name too long\n");
+ return 1;
+ }
+ }
+ if(vol->UNCip == 0)
+ vol->UNCip = &vol->UNC[2];
+
+ return 0;
+}
+
+static struct cifsSesInfo *
+cifs_find_tcp_session(__u32 new_target_ip_addr,
+ char *userName, struct TCP_Server_Info **psrvTcp)
+{
+ struct list_head *tmp;
+ struct cifsSesInfo *ses;
+
+ *psrvTcp = NULL;
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &GlobalSMBSessionList) {
+ ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
+ if (ses->server) {
+ if (ses->server->addr.sockAddr.sin_addr.s_addr ==
+ new_target_ip_addr) {
+ /* BB lock server and tcp session and increment use count here?? */
+ *psrvTcp = ses->server; /* found a match on the TCP session */
+ /* BB check if reconnection needed */
+ if (strncmp
+ (ses->userName, userName,
+ MAX_USERNAME_SIZE) == 0){
+ read_unlock(&GlobalSMBSeslock);
+ return ses; /* found exact match on both tcp and SMB sessions */
+ }
+ }
+ }
+ /* else tcp and smb sessions need reconnection */
+ }
+ read_unlock(&GlobalSMBSeslock);
+ return NULL;
+}
+
+static struct cifsTconInfo *
+find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
+{
+ struct list_head *tmp;
+ struct cifsTconInfo *tcon;
+
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &GlobalTreeConnectionList) {
+ cFYI(1, ("Next tcon - "));
+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+ if (tcon->ses) {
+ if (tcon->ses->server) {
+ cFYI(1,
+ (" old ip addr: %x == new ip %x ?",
+ tcon->ses->server->addr.sockAddr.sin_addr.
+ s_addr, new_target_ip_addr));
+ if (tcon->ses->server->addr.sockAddr.sin_addr.
+ s_addr == new_target_ip_addr) {
+ /* BB lock tcon and server and tcp session and increment use count here? */
+ /* found a match on the TCP session */
+ /* BB check if reconnection needed */
+ cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
+ tcon->treeName, uncName));
+ if (strncmp
+ (tcon->treeName, uncName,
+ MAX_TREE_SIZE) == 0) {
+ cFYI(1,
+ ("Matched UNC, old user: %s == new: %s ?",
+ tcon->treeName, uncName));
+ if (strncmp
+ (tcon->ses->userName,
+ userName,
+ MAX_USERNAME_SIZE) == 0) {
+ read_unlock(&GlobalSMBSeslock);
+ return tcon;/* also matched user (smb session)*/
+ }
+ }
+ }
+ }
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ return NULL;
+}
+
+int
+connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+ const char *old_path, const struct nls_table *nls_codepage)
+{
+ unsigned char *referrals = NULL;
+ unsigned int num_referrals;
+ int rc = 0;
+
+ rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
+ &num_referrals, &referrals);
+
+ /* BB Add in code to: if valid refrl, if not ip address contact
+ the helper that resolves tcp names, mount to it, try to
+ tcon to it unmount it if fail */
+
+ if(referrals)
+ kfree(referrals);
+
+ return rc;
+}
+
+int
+get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+ const char *old_path, const struct nls_table *nls_codepage,
+ unsigned int *pnum_referrals, unsigned char ** preferrals)
+{
+ char *temp_unc;
+ int rc = 0;
+
+ *pnum_referrals = 0;
+
+ if (pSesInfo->ipc_tid == 0) {
+ temp_unc = kmalloc(2 /* for slashes */ +
+ strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
+ + 1 + 4 /* slash IPC$ */ + 2,
+ GFP_KERNEL);
+ if (temp_unc == NULL)
+ return -ENOMEM;
+ temp_unc[0] = '\\';
+ temp_unc[1] = '\\';
+ strcpy(temp_unc + 2, pSesInfo->serverName);
+ strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
+ rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
+ cFYI(1,
+ ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
+ kfree(temp_unc);
+ }
+ if (rc == 0)
+ rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
+ pnum_referrals, nls_codepage);
+
+ return rc;
+}
+
+/* See RFC1001 section 14 on representation of Netbios names */
+static void rfc1002mangle(char * target,char * source, unsigned int length)
+{
+ unsigned int i,j;
+
+ for(i=0,j=0;i<(length);i++) {
+ /* mask a nibble at a time and encode */
+ target[j] = 'A' + (0x0F & (source[i] >> 4));
+ target[j+1] = 'A' + (0x0F & source[i]);
+ j+=2;
+ }
+
+}
+
+
+static int
+ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
+ char * netbios_name)
+{
+ int rc = 0;
+ int connected = 0;
+ unsigned short int orig_port = 0;
+
+ if(*csocket == NULL) {
+ rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
+ if (rc < 0) {
+ cERROR(1, ("Error %d creating socket",rc));
+ *csocket = NULL;
+ return rc;
+ } else {
+ /* BB other socket options to set KEEPALIVE, NODELAY? */
+ cFYI(1,("Socket created"));
+ (*csocket)->sk->allocation = GFP_NOFS;
+ (*csocket)->sk->keepopen = 1; // test jz
+ }
+ }
+
+ psin_server->sin_family = AF_INET;
+ if(psin_server->sin_port) { /* user overrode default port */
+ rc = (*csocket)->ops->connect(*csocket,
+ (struct sockaddr *) psin_server,
+ sizeof (struct sockaddr_in),0);
+ if (rc >= 0)
+ connected = 1;
+ }
+
+ if(!connected) {
+ /* save original port so we can retry user specified port
+ later if fall back ports fail this time */
+ orig_port = psin_server->sin_port;
+
+ /* do not retry on the same port we just failed on */
+ if(psin_server->sin_port != htons(CIFS_PORT)) {
+ psin_server->sin_port = htons(CIFS_PORT);
+
+ rc = (*csocket)->ops->connect(*csocket,
+ (struct sockaddr *) psin_server,
+ sizeof (struct sockaddr_in),0);
+ if (rc >= 0)
+ connected = 1;
+ }
+ }
+ if (!connected) {
+ psin_server->sin_port = htons(RFC1001_PORT);
+ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
+ psin_server, sizeof (struct sockaddr_in),0);
+ if (rc >= 0)
+ connected = 1;
+ }
+
+ /* give up here - unless we want to retry on different
+ protocol families some day */
+ if (!connected) {
+ if(orig_port)
+ psin_server->sin_port = orig_port;
+ cFYI(1,("Error %d connecting to server via ipv4",rc));
+ sock_release(*csocket);
+ *csocket = NULL;
+ return rc;
+ }
+ /* Eventually check for other socket options to change from
+ the default. sock_setsockopt not used because it expects
+ user space buffer */
+ (*csocket)->sk->rcvtimeo = 7 * HZ;
+
+ /* send RFC1001 sessinit */
+
+ if(psin_server->sin_port == htons(139)) {
+ /* some servers require RFC1001 sessinit before sending
+ negprot - BB check reconnection in case where second
+ sessinit is sent but no second negprot */
+ struct rfc1002_session_packet * ses_init_buf;
+ struct smb_hdr * smb_buf;
+ ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
+ if(ses_init_buf) {
+ ses_init_buf->trailer.session_req.called_len = 32;
+ rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
+ DEFAULT_CIFS_CALLED_NAME,16);
+ ses_init_buf->trailer.session_req.calling_len = 32;
+ /* calling name ends in null (byte 16) from old smb
+ convention. */
+ if(netbios_name && (netbios_name[0] !=0)) {
+ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
+ netbios_name,16);
+ } else {
+ rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
+ "LINUX_CIFS_CLNT",16);
+ }
+ ses_init_buf->trailer.session_req.scope1 = 0;
+ ses_init_buf->trailer.session_req.scope2 = 0;
+ smb_buf = (struct smb_hdr *)ses_init_buf;
+ /* sizeof RFC1002_SESSION_REQUEST with no scope */
+ smb_buf->smb_buf_length = 0x81000044;
+ rc = smb_send(*csocket, smb_buf, 0x44,
+ (struct sockaddr *)psin_server);
+ kfree(ses_init_buf);
+ }
+ /* else the negprot may still work without this
+ even though malloc failed */
+
+ }
+
+ return rc;
+}
+
+static int
+ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
+{
+ int rc = 0;
+ int connected = 0;
+
+ if(*csocket == NULL) {
+ rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
+ if (rc < 0) {
+ cERROR(1, ("Error %d creating ipv6 socket",rc));
+ *csocket = NULL;
+ return rc;
+ } else {
+ /* BB other socket options to set KEEPALIVE, NODELAY? */
+ cFYI(1,("ipv6 Socket created"));
+ (*csocket)->sk->allocation = GFP_NOFS;
+ }
+ }
+
+ psin_server->sin6_family = AF_INET6;
+
+ if(psin_server->sin6_port) { /* user overrode default port */
+ rc = (*csocket)->ops->connect(*csocket,
+ (struct sockaddr *) psin_server,
+ sizeof (struct sockaddr_in6),0);
+ if (rc >= 0)
+ connected = 1;
+ }
+
+ if(!connected) {
+ /* do not retry on the same port we just failed on */
+ if(psin_server->sin6_port != htons(CIFS_PORT)) {
+ psin_server->sin6_port = htons(CIFS_PORT);
+
+ rc = (*csocket)->ops->connect(*csocket,
+ (struct sockaddr *) psin_server,
+ sizeof (struct sockaddr_in6),0);
+ if (rc >= 0)
+ connected = 1;
+ }
+ }
+ if (!connected) {
+ psin_server->sin6_port = htons(RFC1001_PORT);
+ rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
+ psin_server, sizeof (struct sockaddr_in6),0);
+ if (rc >= 0)
+ connected = 1;
+ }
+
+ /* give up here - unless we want to retry on different
+ protocol families some day */
+ if (!connected) {
+ cFYI(1,("Error %d connecting to server via ipv6",rc));
+ sock_release(*csocket);
+ *csocket = NULL;
+ return rc;
+ }
+ /* Eventually check for other socket options to change from
+ the default. sock_setsockopt not used because it expects
+ user space buffer */
+ (*csocket)->sk->rcvtimeo = 7 * HZ;
+
+ return rc;
+}
+
+int
+cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
+ char *mount_data, const char *devname)
+{
+ int rc = 0;
+ int xid;
+ struct socket *csocket = NULL;
+ struct sockaddr_in sin_server;
+ struct sockaddr_in6 sin_server6;
+ struct smb_vol volume_info;
+ struct cifsSesInfo *pSesInfo = NULL;
+ struct cifsSesInfo *existingCifsSes = NULL;
+ struct cifsTconInfo *tcon = NULL;
+ struct TCP_Server_Info *srvTcp = NULL;
+
+ xid = GetXid();
+
+ cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); /* BB removeme BB fixme */
+
+ memset(&volume_info,0,sizeof(struct smb_vol));
+ if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return -EINVAL;
+ }
+
+ if (volume_info.username) {
+ cFYI(1, ("Username: %s ", volume_info.username));
+
+ } else {
+ cifserror("No username specified ");
+ /* In userspace mount helper we can get user name from alternate
+ locations such as env variables and files on disk */
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return -EINVAL;
+ }
+
+ if (volume_info.UNCip && volume_info.UNC) {
+ rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
+
+ if(rc == 0) {
+ /* not ipv4 address, try ipv6 */
+ rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
+ }
+
+ if(rc != 1) {
+ /* we failed translating address */
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return -EINVAL;
+ }
+
+ cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
+ /* success */
+ rc = 0;
+ } else if (volume_info.UNCip){
+ /* BB using ip addr as server name connect to the DFS root below */
+ cERROR(1,("Connecting to DFS root not implemented yet"));
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return -EINVAL;
+ } else /* which servers DFS root would we conect to */ {
+ cERROR(1,
+ ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return -EINVAL;
+ }
+
+ /* this is needed for ASCII cp to Unicode converts */
+ if(volume_info.iocharset == NULL) {
+ cifs_sb->local_nls = load_nls_default();
+ /* load_nls_default can not return null */
+ } else {
+ cifs_sb->local_nls = load_nls(volume_info.iocharset);
+ if(cifs_sb->local_nls == NULL) {
+ cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return -ELIBACC;
+ }
+ }
+
+ existingCifsSes =
+ cifs_find_tcp_session(sin_server.sin_addr.s_addr,
+ volume_info.username, &srvTcp);
+ if (srvTcp) {
+ cFYI(1, ("Existing tcp session with server found "));
+ } else { /* create socket */
+ if(volume_info.port)
+ sin_server.sin_port = htons(volume_info.port);
+ else
+ sin_server.sin_port = 0;
+ rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
+ if (rc < 0) {
+ cERROR(1,
+ ("Error connecting to IPv4 socket. Aborting operation"));
+ if(csocket != NULL)
+ sock_release(csocket);
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return rc;
+ }
+
+ srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
+ if (srvTcp == NULL) {
+ rc = -ENOMEM;
+ sock_release(csocket);
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ if(volume_info.password)
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return rc;
+ } else {
+ memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
+ memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
+ atomic_set(&srvTcp->inFlight,0);
+ /* BB Add code for ipv6 case too */
+ srvTcp->ssocket = csocket;
+ srvTcp->protocolType = IPV4;
+ init_waitqueue_head(&srvTcp->response_q);
+ init_waitqueue_head(&srvTcp->request_q);
+ INIT_LIST_HEAD(&srvTcp->pending_mid_q);
+ /* at this point we are the only ones with the pointer
+ to the struct since the kernel thread not created yet
+ so no need to spinlock this init of tcpStatus */
+ srvTcp->tcpStatus = CifsNew;
+ init_MUTEX(&srvTcp->tcpSem);
+ kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
+ CLONE_FS | CLONE_FILES | CLONE_VM);
+ memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
+ }
+ }
+
+ if (existingCifsSes) {
+ pSesInfo = existingCifsSes;
+ cFYI(1, ("Existing smb sess found "));
+ if(volume_info.password)
+ kfree(volume_info.password);
+ /* volume_info.UNC freed at end of function */
+ } else if (!rc) {
+ cFYI(1, ("Existing smb sess not found "));
+ pSesInfo = sesInfoAlloc();
+ if (pSesInfo == NULL)
+ rc = -ENOMEM;
+ else {
+ pSesInfo->server = srvTcp;
+ sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
+ NIPQUAD(sin_server.sin_addr.s_addr));
+ }
+
+ if (!rc){
+ /* volume_info.password freed at unmount */
+ if (volume_info.password)
+ pSesInfo->password = volume_info.password;
+ if (volume_info.username)
+ strncpy(pSesInfo->userName,
+ volume_info.username,MAX_USERNAME_SIZE);
+ if (volume_info.domainname)
+ strncpy(pSesInfo->domainName,
+ volume_info.domainname,MAX_USERNAME_SIZE);
+ pSesInfo->linux_uid = volume_info.linux_uid;
+ down(&pSesInfo->sesSem);
+ rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
+ up(&pSesInfo->sesSem);
+ if(!rc)
+ atomic_inc(&srvTcp->socketUseCount);
+ } else
+ if(volume_info.password)
+ kfree(volume_info.password);
+ }
+
+ /* search for existing tcon to this server share */
+ if (!rc) {
+ if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+ cifs_sb->rsize = volume_info.rsize;
+ else
+ cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+ if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+ cifs_sb->wsize = volume_info.wsize;
+ else
+ cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+ if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
+ cifs_sb->rsize = PAGE_CACHE_SIZE;
+ cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
+ }
+ cifs_sb->mnt_uid = volume_info.linux_uid;
+ cifs_sb->mnt_gid = volume_info.linux_gid;
+ cifs_sb->mnt_file_mode = volume_info.file_mode;
+ cifs_sb->mnt_dir_mode = volume_info.dir_mode;
+ cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+ tcon =
+ find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
+ volume_info.username);
+ if (tcon) {
+ cFYI(1, ("Found match on UNC path "));
+ /* we can have only one retry value for a connection
+ to a share so for resources mounted more than once
+ to the same server share the last value passed in
+ for the retry flag is used */
+ tcon->retry = volume_info.retry;
+ } else {
+ tcon = tconInfoAlloc();
+ if (tcon == NULL)
+ rc = -ENOMEM;
+ else {
+ /* check for null share name ie connect to dfs root */
+
+ /* BB check if this works for exactly length three strings */
+ if ((strchr(volume_info.UNC + 3, '\\') == NULL)
+ && (strchr(volume_info.UNC + 3, '/') ==
+ NULL)) {
+ rc = connect_to_dfs_path(xid,
+ pSesInfo,
+ "",
+ cifs_sb->
+ local_nls);
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ FreeXid(xid);
+ return -ENODEV;
+ } else {
+ rc = CIFSTCon(xid, pSesInfo,
+ volume_info.UNC,
+ tcon, cifs_sb->local_nls);
+ cFYI(1, ("CIFS Tcon rc = %d", rc));
+ }
+ if (!rc) {
+ atomic_inc(&pSesInfo->inUse);
+ tcon->retry = volume_info.retry;
+ }
+ }
+ }
+ }
+ if(pSesInfo) {
+ if (pSesInfo->capabilities & CAP_LARGE_FILES) {
+ sb->s_maxbytes = (u64) 1 << 63;
+ } else
+ sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
+ }
+
+/* on error free sesinfo and tcon struct if needed */
+ if (rc) {
+ /* if session setup failed, use count is zero but
+ we still need to free cifsd thread */
+ if(atomic_read(&srvTcp->socketUseCount) == 0) {
+ spin_lock(&GlobalMid_Lock);
+ srvTcp->tcpStatus = CifsExiting;
+ spin_unlock(&GlobalMid_Lock);
+ if(srvTcp->tsk)
+ send_sig(SIGKILL,srvTcp->tsk,1);
+ }
+ /* If find_unc succeeded then rc == 0 so we can not end */
+ if (tcon) /* up accidently freeing someone elses tcon struct */
+ tconInfoFree(tcon);
+ if (existingCifsSes == 0) {
+ if (pSesInfo) {
+ if ((pSesInfo->server) &&
+ (pSesInfo->status == CifsGood)) {
+ int temp_rc;
+ temp_rc = CIFSSMBLogoff(xid, pSesInfo);
+ /* if the socketUseCount is now zero */
+ if((temp_rc == -ESHUTDOWN) &&
+ (pSesInfo->server->tsk))
+ send_sig(SIGKILL,pSesInfo->server->tsk,1);
+ } else
+ cFYI(1, ("No session or bad tcon"));
+ sesInfoFree(pSesInfo);
+ /* pSesInfo = NULL; */
+ }
+ }
+ } else {
+ atomic_inc(&tcon->useCount);
+ cifs_sb->tcon = tcon;
+ tcon->ses = pSesInfo;
+
+ /* do not care if following two calls succeed - informational only */
+ CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
+ CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
+ if (tcon->ses->capabilities & CAP_UNIX)
+ CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
+ }
+
+ /* volume_info.password is freed above when existing session found
+ (in which case it is not needed anymore) but when new sesion is created
+ the password ptr is put in the new session structure (in which case the
+ password will be freed at unmount time) */
+ if(volume_info.UNC)
+ kfree(volume_info.UNC);
+ FreeXid(xid);
+ return rc;
+}
+
+static int
+CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
+ char session_key[CIFS_SESSION_KEY_SIZE],
+ const struct nls_table *nls_codepage)
+{
+ struct smb_hdr *smb_buffer;
+ struct smb_hdr *smb_buffer_response;
+ SESSION_SETUP_ANDX *pSMB;
+ SESSION_SETUP_ANDX *pSMBr;
+ char *bcc_ptr;
+ char *user = ses->userName;
+ char *domain = ses->domainName;
+ int rc = 0;
+ int remaining_words = 0;
+ int bytes_returned = 0;
+ int len;
+
+ cFYI(1, ("In sesssetup "));
+
+ smb_buffer = cifs_buf_get();
+ if (smb_buffer == 0) {
+ return -ENOMEM;
+ }
+ smb_buffer_response = smb_buffer;
+ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+
+ /* send SMBsessionSetup here */
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 13 /* wct */ );
+
+ pSMB->req_no_secext.AndXCommand = 0xFF;
+ pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+ pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ pSMB->req_no_secext.Capabilities =
+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
+ if (ses->capabilities & CAP_UNICODE) {
+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+ pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
+ }
+ if (ses->capabilities & CAP_STATUS32) {
+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ smb_buffer->Flags2 |= SMBFLG2_DFS;
+ pSMB->req_no_secext.Capabilities |= CAP_DFS;
+ }
+ pSMB->req_no_secext.Capabilities =
+ cpu_to_le32(pSMB->req_no_secext.Capabilities);
+ /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
+ CIFS_SESSION_KEY_SIZE; */
+ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+ pSMB->req_no_secext.CaseSensitivePasswordLength =
+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+ bcc_ptr = pByteArea(smb_buffer);
+ /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
+ bcc_ptr += CIFS_SESSION_KEY_SIZE; */
+ memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
+ bcc_ptr += CIFS_SESSION_KEY_SIZE;
+
+ if (ses->capabilities & CAP_UNICODE) {
+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ if(user == NULL)
+ bytes_returned = 0; /* skill null user */
+ else
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
+ nls_codepage);
+ bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
+ bcc_ptr += 2; /* trailing null */
+ if (domain == NULL)
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr,
+ "CIFS_LINUX_DOM", 32, nls_codepage);
+ else
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+ nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ 32, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+ nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ 64, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2;
+ } else {
+ if(user != NULL) {
+ strncpy(bcc_ptr, user, 200);
+ bcc_ptr += strnlen(user, 200);
+ }
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ if (domain == NULL) {
+ strcpy(bcc_ptr, "CIFS_LINUX_DOM");
+ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
+ } else {
+ strncpy(bcc_ptr, domain, 64);
+ bcc_ptr += strnlen(domain, 64);
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ strcpy(bcc_ptr, "Linux version ");
+ bcc_ptr += strlen("Linux version ");
+ strcpy(bcc_ptr, UTS_RELEASE);
+ bcc_ptr += strlen(UTS_RELEASE) + 1;
+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+ }
+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+ smb_buffer->smb_buf_length += BCC(smb_buffer);
+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+
+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+ &bytes_returned, 1);
+ if (rc) {
+/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
+ } else if ((smb_buffer_response->WordCount == 3)
+ || (smb_buffer_response->WordCount == 4)) {
+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
+ if (pSMBr->resp.Action & GUEST_LOGIN)
+ cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
+ if (ses) {
+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
+ cFYI(1, ("UID = %d ", ses->Suid));
+ /* response can have either 3 or 4 word count - Samba sends 3 */
+ bcc_ptr = pByteArea(smb_buffer_response);
+ if ((pSMBr->resp.hdr.WordCount == 3)
+ || ((pSMBr->resp.hdr.WordCount == 4)
+ && (pSMBr->resp.SecurityBlobLength <
+ pSMBr->resp.ByteCount))) {
+ if (pSMBr->resp.hdr.WordCount == 4)
+ bcc_ptr +=
+ pSMBr->resp.SecurityBlobLength;
+
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+ if ((long) (bcc_ptr) % 2) {
+ remaining_words =
+ (BCC(smb_buffer_response)
+ - 1) / 2;
+ bcc_ptr++; /* Unicode strings must be word aligned */
+ } else {
+ remaining_words =
+ BCC
+ (smb_buffer_response) / 2;
+ }
+ len =
+ UniStrnlen((wchar_t *) bcc_ptr,
+ remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+ the end since (at least) WIN2K and Windows XP have a major bug in not null
+ terminating last Unicode string in response */
+ ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverOS,
+ (wchar_t *)bcc_ptr, len,nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ remaining_words -= len + 1;
+ ses->serverOS[2 * len] = 0;
+ ses->serverOS[1 + (2 * len)] = 0;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *)bcc_ptr,
+ remaining_words
+ - 1);
+ ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverNOS,
+ (wchar_t *)bcc_ptr,len,nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ ses->serverNOS[2 * len] = 0;
+ ses->serverNOS[1 + (2 * len)] = 0;
+ remaining_words -= len + 1;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+ ses->serverDomain =
+ cifs_kcalloc(2*(len+1),GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverDomain,
+ (wchar_t *)bcc_ptr,len,nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ ses->serverDomain[2*len] = 0;
+ ses->serverDomain[1+(2*len)] = 0;
+ } /* else no more room so create dummy domain string */
+ else
+ ses->serverDomain =
+ cifs_kcalloc(2,
+ GFP_KERNEL);
+ } else { /* no room so create dummy domain and NOS string */
+ ses->serverDomain =
+ cifs_kcalloc(2, GFP_KERNEL);
+ ses->serverNOS =
+ cifs_kcalloc(2, GFP_KERNEL);
+ }
+ } else { /* ASCII */
+ len = strnlen(bcc_ptr, 1024);
+ if (((long) bcc_ptr + len) - (long)
+ pByteArea(smb_buffer_response)
+ <= BCC(smb_buffer_response)) {
+ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+ strncpy(ses->serverOS,bcc_ptr, len);
+
+ bcc_ptr += len;
+ bcc_ptr[0] = 0; /* null terminate the string */
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+ strncpy(ses->serverNOS, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
+ strncpy(ses->serverDomain, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+ } else
+ cFYI(1,
+ ("Variable field of length %d extends beyond end of smb ",
+ len));
+ }
+ } else {
+ cERROR(1,
+ (" Security Blob Length extends beyond end of SMB"));
+ }
+ } else {
+ cERROR(1, ("No session structure passed in."));
+ }
+ } else {
+ cERROR(1,
+ (" Invalid Word count %d: ",
+ smb_buffer_response->WordCount));
+ rc = -EIO;
+ }
+
+ if (smb_buffer)
+ cifs_buf_release(smb_buffer);
+
+ return rc;
+}
+
+static int
+CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
+ char *SecurityBlob,int SecurityBlobLength,
+ const struct nls_table *nls_codepage)
+{
+ struct smb_hdr *smb_buffer;
+ struct smb_hdr *smb_buffer_response;
+ SESSION_SETUP_ANDX *pSMB;
+ SESSION_SETUP_ANDX *pSMBr;
+ char *bcc_ptr;
+ char *user = ses->userName;
+ char *domain = ses->domainName;
+ int rc = 0;
+ int remaining_words = 0;
+ int bytes_returned = 0;
+ int len;
+
+ cFYI(1, ("In spnego sesssetup "));
+
+ smb_buffer = cifs_buf_get();
+ if (smb_buffer == 0) {
+ return -ENOMEM;
+ }
+ smb_buffer_response = smb_buffer;
+ pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+
+ /* send SMBsessionSetup here */
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 12 /* wct */ );
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ pSMB->req.AndXCommand = 0xFF;
+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ pSMB->req.Capabilities =
+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+ CAP_EXTENDED_SECURITY;
+ if (ses->capabilities & CAP_UNICODE) {
+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+ pSMB->req.Capabilities |= CAP_UNICODE;
+ }
+ if (ses->capabilities & CAP_STATUS32) {
+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ pSMB->req.Capabilities |= CAP_STATUS32;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ smb_buffer->Flags2 |= SMBFLG2_DFS;
+ pSMB->req.Capabilities |= CAP_DFS;
+ }
+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+
+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
+ bcc_ptr = pByteArea(smb_buffer);
+ memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
+ bcc_ptr += SecurityBlobLength;
+
+ if (ses->capabilities & CAP_UNICODE) {
+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
+ bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
+ bcc_ptr += 2; /* trailing null */
+ if (domain == NULL)
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr,
+ "CIFS_LINUX_DOM", 32, nls_codepage);
+ else
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+ nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ 32, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+ nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ 64, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2;
+ } else {
+ strncpy(bcc_ptr, user, 200);
+ bcc_ptr += strnlen(user, 200);
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ if (domain == NULL) {
+ strcpy(bcc_ptr, "CIFS_LINUX_DOM");
+ bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
+ } else {
+ strncpy(bcc_ptr, domain, 64);
+ bcc_ptr += strnlen(domain, 64);
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ strcpy(bcc_ptr, "Linux version ");
+ bcc_ptr += strlen("Linux version ");
+ strcpy(bcc_ptr, UTS_RELEASE);
+ bcc_ptr += strlen(UTS_RELEASE) + 1;
+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+ }
+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+ smb_buffer->smb_buf_length += BCC(smb_buffer);
+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+
+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+ &bytes_returned, 1);
+ if (rc) {
+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
+ } else if ((smb_buffer_response->WordCount == 3)
+ || (smb_buffer_response->WordCount == 4)) {
+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
+ pSMBr->resp.SecurityBlobLength =
+ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+ if (pSMBr->resp.Action & GUEST_LOGIN)
+ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
+ if (ses) {
+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
+ cFYI(1, ("UID = %d ", ses->Suid));
+ bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
+
+ /* BB Fix below to make endian neutral !! */
+
+ if ((pSMBr->resp.hdr.WordCount == 3)
+ || ((pSMBr->resp.hdr.WordCount == 4)
+ && (pSMBr->resp.SecurityBlobLength <
+ pSMBr->resp.ByteCount))) {
+ if (pSMBr->resp.hdr.WordCount == 4) {
+ bcc_ptr +=
+ pSMBr->resp.SecurityBlobLength;
+ cFYI(1,
+ ("Security Blob Length %d ",
+ pSMBr->resp.SecurityBlobLength));
+ }
+
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+ if ((long) (bcc_ptr) % 2) {
+ remaining_words =
+ (BCC(smb_buffer_response)
+ - 1) / 2;
+ bcc_ptr++; /* Unicode strings must be word aligned */
+ } else {
+ remaining_words =
+ BCC
+ (smb_buffer_response) / 2;
+ }
+ len =
+ UniStrnlen((wchar_t *) bcc_ptr,
+ remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+ the end since (at least) WIN2K and Windows XP have a major bug in not null
+ terminating last Unicode string in response */
+ ses->serverOS =
+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverOS,
+ (wchar_t *)
+ bcc_ptr, len,
+ nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ remaining_words -= len + 1;
+ ses->serverOS[2 * len] = 0;
+ ses->serverOS[1 + (2 * len)] = 0;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *)bcc_ptr,
+ remaining_words
+ - 1);
+ ses->serverNOS =
+ cifs_kcalloc(2 * (len + 1),
+ GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverNOS,
+ (wchar_t *)bcc_ptr,
+ len,
+ nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ ses->serverNOS[2 * len] = 0;
+ ses->serverNOS[1 + (2 * len)] = 0;
+ remaining_words -= len + 1;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+ ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverDomain,
+ (wchar_t *)bcc_ptr,
+ len,
+ nls_codepage);
+ bcc_ptr += 2*(len+1);
+ ses->serverDomain[2*len] = 0;
+ ses->serverDomain[1+(2*len)] = 0;
+ } /* else no more room so create dummy domain string */
+ else
+ ses->serverDomain =
+ cifs_kcalloc(2,GFP_KERNEL);
+ } else { /* no room so create dummy domain and NOS string */
+ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
+ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
+ }
+ } else { /* ASCII */
+
+ len = strnlen(bcc_ptr, 1024);
+ if (((long) bcc_ptr + len) - (long)
+ pByteArea(smb_buffer_response)
+ <= BCC(smb_buffer_response)) {
+ ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
+ strncpy(ses->serverOS, bcc_ptr, len);
+
+ bcc_ptr += len;
+ bcc_ptr[0] = 0; /* null terminate the string */
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+ strncpy(ses->serverNOS, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
+ strncpy(ses->serverDomain, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+ } else
+ cFYI(1,
+ ("Variable field of length %d extends beyond end of smb ",
+ len));
+ }
+ } else {
+ cERROR(1,
+ (" Security Blob Length extends beyond end of SMB"));
+ }
+ } else {
+ cERROR(1, ("No session structure passed in."));
+ }
+ } else {
+ cERROR(1,
+ (" Invalid Word count %d: ",
+ smb_buffer_response->WordCount));
+ rc = -EIO;
+ }
+
+ if (smb_buffer)
+ cifs_buf_release(smb_buffer);
+
+ return rc;
+}
+
+static int
+CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
+ struct cifsSesInfo *ses, int * pNTLMv2_flag,
+ const struct nls_table *nls_codepage)
+{
+ struct smb_hdr *smb_buffer;
+ struct smb_hdr *smb_buffer_response;
+ SESSION_SETUP_ANDX *pSMB;
+ SESSION_SETUP_ANDX *pSMBr;
+ char *bcc_ptr;
+ char *domain = ses->domainName;
+ int rc = 0;
+ int remaining_words = 0;
+ int bytes_returned = 0;
+ int len;
+ int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
+ PNEGOTIATE_MESSAGE SecurityBlob;
+ PCHALLENGE_MESSAGE SecurityBlob2;
+
+ cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+ *pNTLMv2_flag = FALSE;
+ smb_buffer = cifs_buf_get();
+ if (smb_buffer == 0) {
+ return -ENOMEM;
+ }
+ smb_buffer_response = smb_buffer;
+ pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
+
+ /* send SMBsessionSetup here */
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 12 /* wct */ );
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
+
+ pSMB->req.AndXCommand = 0xFF;
+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ pSMB->req.Capabilities =
+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+ CAP_EXTENDED_SECURITY;
+ if (ses->capabilities & CAP_UNICODE) {
+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+ pSMB->req.Capabilities |= CAP_UNICODE;
+ }
+ if (ses->capabilities & CAP_STATUS32) {
+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ pSMB->req.Capabilities |= CAP_STATUS32;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ smb_buffer->Flags2 |= SMBFLG2_DFS;
+ pSMB->req.Capabilities |= CAP_DFS;
+ }
+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+
+ bcc_ptr = (char *) &pSMB->req.SecurityBlob;
+ SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
+ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
+ SecurityBlob->MessageType = NtLmNegotiate;
+ SecurityBlob->NegotiateFlags =
+ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
+ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
+ /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
+ if(sign_CIFS_PDUs)
+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
+ if(ntlmv2_support)
+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+ /* setup pointers to domain name and workstation name */
+ bcc_ptr += SecurityBlobLength;
+
+ SecurityBlob->WorkstationName.Buffer = 0;
+ SecurityBlob->WorkstationName.Length = 0;
+ SecurityBlob->WorkstationName.MaximumLength = 0;
+
+ if (domain == NULL) {
+ SecurityBlob->DomainName.Buffer = 0;
+ SecurityBlob->DomainName.Length = 0;
+ SecurityBlob->DomainName.MaximumLength = 0;
+ } else {
+ SecurityBlob->NegotiateFlags |=
+ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+ strncpy(bcc_ptr, domain, 63);
+ SecurityBlob->DomainName.Length = strnlen(domain, 64);
+ SecurityBlob->DomainName.MaximumLength =
+ cpu_to_le16(SecurityBlob->DomainName.Length);
+ SecurityBlob->DomainName.Buffer =
+ cpu_to_le32((long) &SecurityBlob->
+ DomainString -
+ (long) &SecurityBlob->Signature);
+ bcc_ptr += SecurityBlob->DomainName.Length;
+ SecurityBlobLength += SecurityBlob->DomainName.Length;
+ SecurityBlob->DomainName.Length =
+ cpu_to_le16(SecurityBlob->DomainName.Length);
+ }
+ if (ses->capabilities & CAP_UNICODE) {
+ if ((long) bcc_ptr % 2) {
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ 32, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+ nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2; /* null terminate Linux version */
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ 64, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ *(bcc_ptr + 1) = 0;
+ *(bcc_ptr + 2) = 0;
+ bcc_ptr += 2; /* null terminate network opsys string */
+ *(bcc_ptr + 1) = 0;
+ *(bcc_ptr + 2) = 0;
+ bcc_ptr += 2; /* null domain */
+ } else { /* ASCII */
+ strcpy(bcc_ptr, "Linux version ");
+ bcc_ptr += strlen("Linux version ");
+ strcpy(bcc_ptr, UTS_RELEASE);
+ bcc_ptr += strlen(UTS_RELEASE) + 1;
+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+ bcc_ptr++; /* empty domain field */
+ *bcc_ptr = 0;
+ }
+ SecurityBlob->NegotiateFlags =
+ cpu_to_le32(SecurityBlob->NegotiateFlags);
+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+ smb_buffer->smb_buf_length += BCC(smb_buffer);
+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+
+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+ &bytes_returned, 1);
+
+ if (smb_buffer_response->Status.CifsError ==
+ (NT_STATUS_MORE_PROCESSING_REQUIRED))
+ rc = 0;
+
+ if (rc) {
+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
+ } else if ((smb_buffer_response->WordCount == 3)
+ || (smb_buffer_response->WordCount == 4)) {
+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
+ pSMBr->resp.SecurityBlobLength =
+ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+ if (pSMBr->resp.Action & GUEST_LOGIN)
+ cFYI(1, (" Guest login"));
+ /* Do we want to set anything in SesInfo struct when guest login? */
+
+ bcc_ptr = pByteArea(smb_buffer_response);
+ /* response can have either 3 or 4 word count - Samba sends 3 */
+
+ SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
+ if (SecurityBlob2->MessageType != NtLmChallenge) {
+ cFYI(1,
+ ("Unexpected NTLMSSP message type received %d",
+ SecurityBlob2->MessageType));
+ } else if (ses) {
+ ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
+ cFYI(1, ("UID = %d ", ses->Suid));
+ if ((pSMBr->resp.hdr.WordCount == 3)
+ || ((pSMBr->resp.hdr.WordCount == 4)
+ && (pSMBr->resp.SecurityBlobLength <
+ pSMBr->resp.ByteCount))) {
+ if (pSMBr->resp.hdr.WordCount == 4) {
+ bcc_ptr +=
+ pSMBr->resp.SecurityBlobLength;
+ cFYI(1,
+ ("Security Blob Length %d ",
+ pSMBr->resp.SecurityBlobLength));
+ }
+
+ cFYI(1, ("NTLMSSP Challenge rcvd "));
+
+ memcpy(ses->server->cryptKey,
+ SecurityBlob2->Challenge,
+ CIFS_CRYPTO_KEY_SIZE);
+ if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
+ *pNTLMv2_flag = TRUE;
+
+ if((SecurityBlob2->NegotiateFlags &
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
+ || (sign_CIFS_PDUs > 1))
+ ses->server->secMode |=
+ SECMODE_SIGN_REQUIRED;
+ if ((SecurityBlob2->NegotiateFlags &
+ NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
+ ses->server->secMode |=
+ SECMODE_SIGN_ENABLED;
+
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+ if ((long) (bcc_ptr) % 2) {
+ remaining_words =
+ (BCC(smb_buffer_response)
+ - 1) / 2;
+ bcc_ptr++; /* Unicode strings must be word aligned */
+ } else {
+ remaining_words =
+ BCC
+ (smb_buffer_response) / 2;
+ }
+ len =
+ UniStrnlen((wchar_t *) bcc_ptr,
+ remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+ the end since (at least) WIN2K and Windows XP have a major bug in not null
+ terminating last Unicode string in response */
+ ses->serverOS =
+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverOS,
+ (wchar_t *)
+ bcc_ptr, len,
+ nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ remaining_words -= len + 1;
+ ses->serverOS[2 * len] = 0;
+ ses->serverOS[1 + (2 * len)] = 0;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *)
+ bcc_ptr,
+ remaining_words
+ - 1);
+ ses->serverNOS =
+ cifs_kcalloc(2 * (len + 1),
+ GFP_KERNEL);
+ cifs_strfromUCS_le(ses->
+ serverNOS,
+ (wchar_t *)
+ bcc_ptr,
+ len,
+ nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ ses->serverNOS[2 * len] = 0;
+ ses->serverNOS[1 +
+ (2 * len)] = 0;
+ remaining_words -= len + 1;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
+ /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+ ses->serverDomain =
+ cifs_kcalloc(2 *
+ (len +
+ 1),
+ GFP_KERNEL);
+ cifs_strfromUCS_le
+ (ses->
+ serverDomain,
+ (wchar_t *)
+ bcc_ptr, len,
+ nls_codepage);
+ bcc_ptr +=
+ 2 * (len + 1);
+ ses->
+ serverDomain[2
+ * len]
+ = 0;
+ ses->
+ serverDomain[1
+ +
+ (2
+ *
+ len)]
+ = 0;
+ } /* else no more room so create dummy domain string */
+ else
+ ses->serverDomain =
+ cifs_kcalloc(2,
+ GFP_KERNEL);
+ } else { /* no room so create dummy domain and NOS string */
+ ses->serverDomain =
+ cifs_kcalloc(2, GFP_KERNEL);
+ ses->serverNOS =
+ cifs_kcalloc(2, GFP_KERNEL);
+ }
+ } else { /* ASCII */
+ len = strnlen(bcc_ptr, 1024);
+ if (((long) bcc_ptr + len) - (long)
+ pByteArea(smb_buffer_response)
+ <= BCC(smb_buffer_response)) {
+ ses->serverOS =
+ cifs_kcalloc(len + 1,
+ GFP_KERNEL);
+ strncpy(ses->serverOS,
+ bcc_ptr, len);
+
+ bcc_ptr += len;
+ bcc_ptr[0] = 0; /* null terminate string */
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverNOS =
+ cifs_kcalloc(len + 1,
+ GFP_KERNEL);
+ strncpy(ses->serverNOS, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverDomain =
+ cifs_kcalloc(len + 1,
+ GFP_KERNEL);
+ strncpy(ses->serverDomain, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+ } else
+ cFYI(1,
+ ("Variable field of length %d extends beyond end of smb ",
+ len));
+ }
+ } else {
+ cERROR(1,
+ (" Security Blob Length extends beyond end of SMB"));
+ }
+ } else {
+ cERROR(1, ("No session structure passed in."));
+ }
+ } else {
+ cERROR(1,
+ (" Invalid Word count %d: ",
+ smb_buffer_response->WordCount));
+ rc = -EIO;
+ }
+
+ if (smb_buffer)
+ cifs_buf_release(smb_buffer);
+
+ return rc;
+}
+
+static int
+CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
+ char *ntlm_session_key, int ntlmv2_flag,
+ const struct nls_table *nls_codepage)
+{
+ struct smb_hdr *smb_buffer;
+ struct smb_hdr *smb_buffer_response;
+ SESSION_SETUP_ANDX *pSMB;
+ SESSION_SETUP_ANDX *pSMBr;
+ char *bcc_ptr;
+ char *user = ses->userName;
+ char *domain = ses->domainName;
+ int rc = 0;
+ int remaining_words = 0;
+ int bytes_returned = 0;
+ int len;
+ int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
+ PAUTHENTICATE_MESSAGE SecurityBlob;
+
+ cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
+
+ smb_buffer = cifs_buf_get();
+ if (smb_buffer == 0) {
+ return -ENOMEM;
+ }
+ smb_buffer_response = smb_buffer;
+ pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+ pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
+
+ /* send SMBsessionSetup here */
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 12 /* wct */ );
+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ pSMB->req.AndXCommand = 0xFF;
+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+ pSMB->req.hdr.Uid = ses->Suid;
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ pSMB->req.Capabilities =
+ CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+ CAP_EXTENDED_SECURITY;
+ if (ses->capabilities & CAP_UNICODE) {
+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+ pSMB->req.Capabilities |= CAP_UNICODE;
+ }
+ if (ses->capabilities & CAP_STATUS32) {
+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ pSMB->req.Capabilities |= CAP_STATUS32;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ smb_buffer->Flags2 |= SMBFLG2_DFS;
+ pSMB->req.Capabilities |= CAP_DFS;
+ }
+ pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+
+ bcc_ptr = (char *) &pSMB->req.SecurityBlob;
+ SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
+ strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
+ SecurityBlob->MessageType = NtLmAuthenticate;
+ bcc_ptr += SecurityBlobLength;
+ SecurityBlob->NegotiateFlags =
+ NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
+ 0x80000000 | NTLMSSP_NEGOTIATE_128;
+ if(sign_CIFS_PDUs)
+ SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
+ if(ntlmv2_flag)
+ SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+
+/* setup pointers to domain name and workstation name */
+
+ SecurityBlob->WorkstationName.Buffer = 0;
+ SecurityBlob->WorkstationName.Length = 0;
+ SecurityBlob->WorkstationName.MaximumLength = 0;
+ SecurityBlob->SessionKey.Length = 0;
+ SecurityBlob->SessionKey.MaximumLength = 0;
+ SecurityBlob->SessionKey.Buffer = 0;
+
+ SecurityBlob->LmChallengeResponse.Length = 0;
+ SecurityBlob->LmChallengeResponse.MaximumLength = 0;
+ SecurityBlob->LmChallengeResponse.Buffer = 0;
+
+ SecurityBlob->NtChallengeResponse.Length =
+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+ SecurityBlob->NtChallengeResponse.MaximumLength =
+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+ memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
+ SecurityBlob->NtChallengeResponse.Buffer =
+ cpu_to_le32(SecurityBlobLength);
+ SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
+ bcc_ptr += CIFS_SESSION_KEY_SIZE;
+
+ if (ses->capabilities & CAP_UNICODE) {
+ if (domain == NULL) {
+ SecurityBlob->DomainName.Buffer = 0;
+ SecurityBlob->DomainName.Length = 0;
+ SecurityBlob->DomainName.MaximumLength = 0;
+ } else {
+ SecurityBlob->DomainName.Length =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+ nls_codepage);
+ SecurityBlob->DomainName.Length *= 2;
+ SecurityBlob->DomainName.MaximumLength =
+ cpu_to_le16(SecurityBlob->DomainName.Length);
+ SecurityBlob->DomainName.Buffer =
+ cpu_to_le32(SecurityBlobLength);
+ bcc_ptr += SecurityBlob->DomainName.Length;
+ SecurityBlobLength += SecurityBlob->DomainName.Length;
+ SecurityBlob->DomainName.Length =
+ cpu_to_le16(SecurityBlob->DomainName.Length);
+ }
+ if (user == NULL) {
+ SecurityBlob->UserName.Buffer = 0;
+ SecurityBlob->UserName.Length = 0;
+ SecurityBlob->UserName.MaximumLength = 0;
+ } else {
+ SecurityBlob->UserName.Length =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
+ nls_codepage);
+ SecurityBlob->UserName.Length *= 2;
+ SecurityBlob->UserName.MaximumLength =
+ cpu_to_le16(SecurityBlob->UserName.Length);
+ SecurityBlob->UserName.Buffer =
+ cpu_to_le32(SecurityBlobLength);
+ bcc_ptr += SecurityBlob->UserName.Length;
+ SecurityBlobLength += SecurityBlob->UserName.Length;
+ SecurityBlob->UserName.Length =
+ cpu_to_le16(SecurityBlob->UserName.Length);
+ }
+
+ /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
+ SecurityBlob->WorkstationName.Length *= 2;
+ SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
+ SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
+ bcc_ptr += SecurityBlob->WorkstationName.Length;
+ SecurityBlobLength += SecurityBlob->WorkstationName.Length;
+ SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
+
+ if ((long) bcc_ptr % 2) {
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+ 32, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
+ nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ bcc_ptr += 2; /* null term version string */
+ bytes_returned =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ 64, nls_codepage);
+ bcc_ptr += 2 * bytes_returned;
+ *(bcc_ptr + 1) = 0;
+ *(bcc_ptr + 2) = 0;
+ bcc_ptr += 2; /* null terminate network opsys string */
+ *(bcc_ptr + 1) = 0;
+ *(bcc_ptr + 2) = 0;
+ bcc_ptr += 2; /* null domain */
+ } else { /* ASCII */
+ if (domain == NULL) {
+ SecurityBlob->DomainName.Buffer = 0;
+ SecurityBlob->DomainName.Length = 0;
+ SecurityBlob->DomainName.MaximumLength = 0;
+ } else {
+ SecurityBlob->NegotiateFlags |=
+ NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+ strncpy(bcc_ptr, domain, 63);
+ SecurityBlob->DomainName.Length = strnlen(domain, 64);
+ SecurityBlob->DomainName.MaximumLength =
+ cpu_to_le16(SecurityBlob->DomainName.Length);
+ SecurityBlob->DomainName.Buffer =
+ cpu_to_le32(SecurityBlobLength);
+ bcc_ptr += SecurityBlob->DomainName.Length;
+ SecurityBlobLength += SecurityBlob->DomainName.Length;
+ SecurityBlob->DomainName.Length =
+ cpu_to_le16(SecurityBlob->DomainName.Length);
+ }
+ if (user == NULL) {
+ SecurityBlob->UserName.Buffer = 0;
+ SecurityBlob->UserName.Length = 0;
+ SecurityBlob->UserName.MaximumLength = 0;
+ } else {
+ strncpy(bcc_ptr, user, 63);
+ SecurityBlob->UserName.Length = strnlen(user, 64);
+ SecurityBlob->UserName.MaximumLength =
+ cpu_to_le16(SecurityBlob->UserName.Length);
+ SecurityBlob->UserName.Buffer =
+ cpu_to_le32(SecurityBlobLength);
+ bcc_ptr += SecurityBlob->UserName.Length;
+ SecurityBlobLength += SecurityBlob->UserName.Length;
+ SecurityBlob->UserName.Length =
+ cpu_to_le16(SecurityBlob->UserName.Length);
+ }
+ /* BB fill in our workstation name if known BB */
+
+ strcpy(bcc_ptr, "Linux version ");
+ bcc_ptr += strlen("Linux version ");
+ strcpy(bcc_ptr, UTS_RELEASE);
+ bcc_ptr += strlen(UTS_RELEASE) + 1;
+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+ bcc_ptr++; /* null domain */
+ *bcc_ptr = 0;
+ }
+ SecurityBlob->NegotiateFlags =
+ cpu_to_le32(SecurityBlob->NegotiateFlags);
+ pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+ smb_buffer->smb_buf_length += BCC(smb_buffer);
+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+
+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+ &bytes_returned, 1);
+ if (rc) {
+/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
+ } else if ((smb_buffer_response->WordCount == 3)
+ || (smb_buffer_response->WordCount == 4)) {
+ pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
+ pSMBr->resp.SecurityBlobLength =
+ le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+ if (pSMBr->resp.Action & GUEST_LOGIN)
+ cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
+/* if(SecurityBlob2->MessageType != NtLm??){
+ cFYI("Unexpected message type on auth response is %d "));
+ } */
+ if (ses) {
+ cFYI(1,
+ ("Does UID on challenge %d match auth response UID %d ",
+ ses->Suid, smb_buffer_response->Uid));
+ ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
+ bcc_ptr = pByteArea(smb_buffer_response);
+ /* response can have either 3 or 4 word count - Samba sends 3 */
+ if ((pSMBr->resp.hdr.WordCount == 3)
+ || ((pSMBr->resp.hdr.WordCount == 4)
+ && (pSMBr->resp.SecurityBlobLength <
+ pSMBr->resp.ByteCount))) {
+ if (pSMBr->resp.hdr.WordCount == 4) {
+ bcc_ptr +=
+ pSMBr->resp.SecurityBlobLength;
+ cFYI(1,
+ ("Security Blob Length %d ",
+ pSMBr->resp.SecurityBlobLength));
+ }
+
+ cFYI(1,
+ ("NTLMSSP response to Authenticate "));
+
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+ if ((long) (bcc_ptr) % 2) {
+ remaining_words =
+ (BCC(smb_buffer_response)
+ - 1) / 2;
+ bcc_ptr++; /* Unicode strings must be word aligned */
+ } else {
+ remaining_words = BCC(smb_buffer_response) / 2;
+ }
+ len =
+ UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+ the end since (at least) WIN2K and Windows XP have a major bug in not null
+ terminating last Unicode string in response */
+ ses->serverOS =
+ cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+ cifs_strfromUCS_le(ses->serverOS,
+ (wchar_t *)
+ bcc_ptr, len,
+ nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ remaining_words -= len + 1;
+ ses->serverOS[2 * len] = 0;
+ ses->serverOS[1 + (2 * len)] = 0;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *)
+ bcc_ptr,
+ remaining_words
+ - 1);
+ ses->serverNOS =
+ cifs_kcalloc(2 * (len + 1),
+ GFP_KERNEL);
+ cifs_strfromUCS_le(ses->
+ serverNOS,
+ (wchar_t *)
+ bcc_ptr,
+ len,
+ nls_codepage);
+ bcc_ptr += 2 * (len + 1);
+ ses->serverNOS[2 * len] = 0;
+ ses->serverNOS[1+(2*len)] = 0;
+ remaining_words -= len + 1;
+ if (remaining_words > 0) {
+ len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
+ /* last string not always null terminated (e.g. for Windows XP & 2000) */
+ ses->serverDomain =
+ cifs_kcalloc(2 *
+ (len +
+ 1),
+ GFP_KERNEL);
+ cifs_strfromUCS_le
+ (ses->
+ serverDomain,
+ (wchar_t *)
+ bcc_ptr, len,
+ nls_codepage);
+ bcc_ptr +=
+ 2 * (len + 1);
+ ses->
+ serverDomain[2
+ * len]
+ = 0;
+ ses->
+ serverDomain[1
+ +
+ (2
+ *
+ len)]
+ = 0;
+ } /* else no more room so create dummy domain string */
+ else
+ ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
+ } else { /* no room so create dummy domain and NOS string */
+ ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
+ ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
+ }
+ } else { /* ASCII */
+ len = strnlen(bcc_ptr, 1024);
+ if (((long) bcc_ptr + len) -
+ (long) pByteArea(smb_buffer_response)
+ <= BCC(smb_buffer_response)) {
+ ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+ strncpy(ses->serverOS,bcc_ptr, len);
+
+ bcc_ptr += len;
+ bcc_ptr[0] = 0; /* null terminate the string */
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
+ strncpy(ses->serverNOS, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+
+ len = strnlen(bcc_ptr, 1024);
+ ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
+ strncpy(ses->serverDomain, bcc_ptr, len);
+ bcc_ptr += len;
+ bcc_ptr[0] = 0;
+ bcc_ptr++;
+ } else
+ cFYI(1,
+ ("Variable field of length %d extends beyond end of smb ",
+ len));
+ }
+ } else {
+ cERROR(1,
+ (" Security Blob Length extends beyond end of SMB"));
+ }
+ } else {
+ cERROR(1, ("No session structure passed in."));
+ }
+ } else {
+ cERROR(1,
+ (" Invalid Word count %d: ",
+ smb_buffer_response->WordCount));
+ rc = -EIO;
+ }
+
+ if (smb_buffer)
+ cifs_buf_release(smb_buffer);
+
+ return rc;
+}
+
+int
+CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
+ const char *tree, struct cifsTconInfo *tcon,
+ const struct nls_table *nls_codepage)
+{
+ struct smb_hdr *smb_buffer;
+ struct smb_hdr *smb_buffer_response;
+ TCONX_REQ *pSMB;
+ TCONX_RSP *pSMBr;
+ char *bcc_ptr;
+ int rc = 0;
+ int length;
+
+ if (ses == NULL)
+ return -EIO;
+
+ smb_buffer = cifs_buf_get();
+ if (smb_buffer == 0) {
+ return -ENOMEM;
+ }
+ smb_buffer_response = smb_buffer;
+
+ header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
+ NULL /*no tid */ , 4 /*wct */ );
+ smb_buffer->Uid = ses->Suid;
+ pSMB = (TCONX_REQ *) smb_buffer;
+ pSMBr = (TCONX_RSP *) smb_buffer_response;
+
+ pSMB->AndXCommand = 0xFF;
+ pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
+ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
+ bcc_ptr = &(pSMB->Password[0]);
+ bcc_ptr++; /* skip password */
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ if (ses->capabilities & CAP_STATUS32) {
+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ smb_buffer->Flags2 |= SMBFLG2_DFS;
+ }
+ if (ses->capabilities & CAP_UNICODE) {
+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+ length =
+ cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
+ bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
+ bcc_ptr += 2; /* skip trailing null */
+ } else { /* ASCII */
+
+ strcpy(bcc_ptr, tree);
+ bcc_ptr += strlen(tree) + 1;
+ }
+ strcpy(bcc_ptr, "?????");
+ bcc_ptr += strlen("?????");
+ bcc_ptr += 1;
+ BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+ smb_buffer->smb_buf_length += BCC(smb_buffer);
+ BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+
+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
+
+ /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
+ /* above now done in SendReceive */
+ if ((rc == 0) && (tcon != NULL)) {
+ tcon->tidStatus = CifsGood;
+ tcon->tid = smb_buffer_response->Tid;
+ bcc_ptr = pByteArea(smb_buffer_response);
+ length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
+ /* skip service field (NB: this field is always ASCII) */
+ bcc_ptr += length + 1;
+ strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+ length = UniStrnlen((wchar_t *) bcc_ptr, 512);
+ if (((long) bcc_ptr + (2 * length)) -
+ (long) pByteArea(smb_buffer_response) <=
+ BCC(smb_buffer_response)) {
+ if(tcon->nativeFileSystem)
+ kfree(tcon->nativeFileSystem);
+ tcon->nativeFileSystem =
+ cifs_kcalloc(length + 2, GFP_KERNEL);
+ cifs_strfromUCS_le(tcon->nativeFileSystem,
+ (wchar_t *) bcc_ptr,
+ length, nls_codepage);
+ bcc_ptr += 2 * length;
+ bcc_ptr[0] = 0; /* null terminate the string */
+ bcc_ptr[1] = 0;
+ bcc_ptr += 2;
+ }
+ /* else do not bother copying these informational fields */
+ } else {
+ length = strnlen(bcc_ptr, 1024);
+ if (((long) bcc_ptr + length) -
+ (long) pByteArea(smb_buffer_response) <=
+ BCC(smb_buffer_response)) {
+ if(tcon->nativeFileSystem)
+ kfree(tcon->nativeFileSystem);
+ tcon->nativeFileSystem =
+ cifs_kcalloc(length + 1, GFP_KERNEL);
+ strncpy(tcon->nativeFileSystem, bcc_ptr,
+ length);
+ }
+ /* else do not bother copying these informational fields */
+ }
+ tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
+ cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
+ } else if ((rc == 0) && tcon == NULL) {
+ /* all we need to save for IPC$ connection */
+ ses->ipc_tid = smb_buffer_response->Tid;
+ }
+
+ if (smb_buffer)
+ cifs_buf_release(smb_buffer);
+ return rc;
+}
+
+int
+cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
+{
+ int rc = 0;
+ int xid;
+ struct cifsSesInfo *ses = NULL;
+ struct task_struct *cifsd_task;
+
+ xid = GetXid();
+
+ if (cifs_sb->tcon) {
+ ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
+ rc = CIFSSMBTDis(xid, cifs_sb->tcon);
+ if (rc == -EBUSY) {
+ FreeXid(xid);
+ return 0;
+ }
+ tconInfoFree(cifs_sb->tcon);
+ if ((ses) && (ses->server)) {
+ /* save off task so we do not refer to ses later */
+ cifsd_task = ses->server->tsk;
+ cFYI(1, ("About to do SMBLogoff "));
+ rc = CIFSSMBLogoff(xid, ses);
+ if (rc == -EBUSY) {
+ FreeXid(xid);
+ return 0;
+ } else if (rc == -ESHUTDOWN) {
+ cFYI(1,("Waking up socket by sending it signal"));
+ send_sig(SIGKILL,cifsd_task,1);
+ rc = 0;
+ } /* else - we have an smb session
+ left on this socket do not kill cifsd */
+ } else
+ cFYI(1, ("No session or bad tcon"));
+ }
+
+ cifs_sb->tcon = NULL;
+ if (ses) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ / 2);
+ }
+ if (ses)
+ sesInfoFree(ses);
+
+ FreeXid(xid);
+ return rc; /* BB check if we should always return zero here */
+}
+
+int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
+ struct nls_table * nls_info)
+{
+ int rc = 0;
+ char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
+ int ntlmv2_flag = FALSE;
+
+ /* what if server changes its buffer size after dropping the session? */
+ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
+ rc = CIFSSMBNegotiate(xid, pSesInfo);
+ if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
+ rc = CIFSSMBNegotiate(xid, pSesInfo);
+ if(rc == -EAGAIN)
+ rc = -EHOSTDOWN;
+ }
+ if(rc == 0) {
+ spin_lock(&GlobalMid_Lock);
+ if(pSesInfo->server->tcpStatus != CifsExiting)
+ pSesInfo->server->tcpStatus = CifsGood;
+ else
+ rc = -EHOSTDOWN;
+ spin_unlock(&GlobalMid_Lock);
+
+ }
+ }
+ if (!rc) {
+ pSesInfo->capabilities = pSesInfo->server->capabilities;
+ if(linuxExtEnabled == 0)
+ pSesInfo->capabilities &= (~CAP_UNIX);
+ pSesInfo->sequence_number = 0;
+ cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
+ pSesInfo->server->secMode,
+ pSesInfo->server->capabilities,
+ pSesInfo->server->timeZone));
+ if (extended_security
+ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
+ && (pSesInfo->server->secType == NTLMSSP)) {
+ cFYI(1, ("New style sesssetup "));
+ rc = CIFSSpnegoSessSetup(xid, pSesInfo,
+ NULL /* security blob */,
+ 0 /* blob length */,
+ nls_info);
+ } else if (extended_security
+ && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
+ && (pSesInfo->server->secType == RawNTLMSSP)) {
+ cFYI(1, ("NTLMSSP sesssetup "));
+ rc = CIFSNTLMSSPNegotiateSessSetup(xid,
+ pSesInfo,
+ &ntlmv2_flag,
+ nls_info);
+ if (!rc) {
+ if(ntlmv2_flag) {
+ char * v2_response;
+ cFYI(1,("Can use more secure NTLM version 2 password hash"));
+ CalcNTLMv2_partial_mac_key(pSesInfo,
+ nls_info);
+ v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
+ if(v2_response) {
+ CalcNTLMv2_response(pSesInfo,v2_response);
+/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
+ kfree(v2_response);
+ /* BB Put dummy sig in SessSetup PDU? */
+ } else
+ rc = -ENOMEM;
+
+ } else {
+ SMBNTencrypt(pSesInfo->password,
+ pSesInfo->server->cryptKey,
+ ntlm_session_key);
+
+ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
+ ntlm_session_key,
+ pSesInfo->password);
+ }
+ /* for better security the weaker lanman hash not sent
+ in AuthSessSetup so we no longer calculate it */
+
+ rc = CIFSNTLMSSPAuthSessSetup(xid,
+ pSesInfo,
+ ntlm_session_key,
+ ntlmv2_flag,
+ nls_info);
+ }
+ } else { /* old style NTLM 0.12 session setup */
+ SMBNTencrypt(pSesInfo->password,
+ pSesInfo->server->cryptKey,
+ ntlm_session_key);
+
+ cifs_calculate_mac_key(pSesInfo->mac_signing_key,
+ ntlm_session_key, pSesInfo->password);
+ rc = CIFSSessSetup(xid, pSesInfo,
+ ntlm_session_key, nls_info);
+ }
+ if (rc) {
+ cERROR(1,("Send error in SessSetup = %d",rc));
+ } else {
+ cFYI(1,("CIFS Session Established successfully"));
+ pSesInfo->status = CifsGood;
+ }
+ }
+ return rc;
+}
+
diff --git a/release/src/linux/linux/fs/cifs/dir.c b/release/src/linux/linux/fs/cifs/dir.c
new file mode 100644
index 00000000..123b0a6d
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/dir.c
@@ -0,0 +1,425 @@
+/*
+ * fs/cifs/dir.c
+ *
+ * vfs operations that deal with dentries
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+void
+renew_parental_timestamps(struct dentry *direntry)
+{
+ /* BB check if there is a way to get the kernel to do this or if we really need this */
+ do {
+ direntry->d_time = jiffies;
+ direntry = direntry->d_parent;
+ } while (!IS_ROOT(direntry));
+}
+
+/* Note: caller must free return buffer */
+char *
+build_path_from_dentry(struct dentry *direntry)
+{
+ struct dentry *temp;
+ int namelen = 0;
+ char *full_path;
+
+ if(direntry == NULL)
+ return NULL; /* not much we can do if dentry is freed and
+ we need to reopen the file after it was closed implicitly
+ when the server crashed */
+
+cifs_bp_rename_retry:
+ for (temp = direntry; !IS_ROOT(temp);) {
+ namelen += (1 + temp->d_name.len);
+ temp = temp->d_parent;
+ if(temp == NULL) {
+ cERROR(1,("corrupt dentry"));
+ return NULL;
+ }
+ }
+
+ full_path = kmalloc(namelen+1, GFP_KERNEL);
+ if(full_path == NULL)
+ return full_path;
+ full_path[namelen] = 0; /* trailing null */
+
+ for (temp = direntry; !IS_ROOT(temp);) {
+ namelen -= 1 + temp->d_name.len;
+ if (namelen < 0) {
+ break;
+ } else {
+ full_path[namelen] = '\\';
+ strncpy(full_path + namelen + 1, temp->d_name.name,
+ temp->d_name.len);
+ cFYI(0, (" name: %s ", full_path + namelen));
+ }
+ temp = temp->d_parent;
+ if(temp == NULL) {
+ cERROR(1,("corrupt dentry"));
+ kfree(full_path);
+ return NULL;
+ }
+ }
+ if (namelen != 0) {
+ cERROR(1,
+ ("We did not end path lookup where we expected namelen is %d",
+ namelen));
+ /* presumably this is only possible if we were racing with a rename
+ of one of the parent directories (we can not lock the dentries
+ above us to prevent this, but retrying should be harmless) */
+ kfree(full_path);
+ namelen = 0;
+ goto cifs_bp_rename_retry;
+ }
+
+ return full_path;
+}
+
+/* Note: caller must free return buffer */
+char *
+build_wildcard_path_from_dentry(struct dentry *direntry)
+{
+ struct dentry *temp;
+ int namelen = 0;
+ char *full_path;
+
+ if(direntry == NULL)
+ return NULL; /* not much we can do if dentry is freed and
+ we need to reopen the file after it was closed implicitly
+ when the server crashed */
+
+cifs_bwp_rename_retry:
+ for (temp = direntry; !IS_ROOT(temp);) {
+ namelen += (1 + temp->d_name.len);
+ temp = temp->d_parent;
+ if(temp == NULL) {
+ cERROR(1,("corrupt dentry"));
+ return NULL;
+ }
+ }
+
+ full_path = kmalloc(namelen+3, GFP_KERNEL);
+ if(full_path == NULL)
+ return full_path;
+
+ full_path[namelen] = '\\';
+ full_path[namelen+1] = '*';
+ full_path[namelen+2] = 0; /* trailing null */
+
+ for (temp = direntry; !IS_ROOT(temp);) {
+ namelen -= 1 + temp->d_name.len;
+ if (namelen < 0) {
+ break;
+ } else {
+ full_path[namelen] = '\\';
+ strncpy(full_path + namelen + 1, temp->d_name.name,
+ temp->d_name.len);
+ cFYI(0, (" name: %s ", full_path + namelen));
+ }
+ temp = temp->d_parent;
+ if(temp == NULL) {
+ cERROR(1,("corrupt dentry"));
+ kfree(full_path);
+ return NULL;
+ }
+ }
+ if (namelen != 0) {
+ cERROR(1,
+ ("We did not end path lookup where we expected namelen is %d",
+ namelen));
+ /* presumably this is only possible if we were racing with a rename
+ of one of the parent directories (we can not lock the dentries
+ above us to prevent this, but retrying should be harmless) */
+ kfree(full_path);
+ namelen = 0;
+ goto cifs_bwp_rename_retry;
+ }
+
+ return full_path;
+}
+
+/* Inode operations in similar order to how they appear in the Linux file fs.h */
+
+int
+cifs_create(struct inode *inode, struct dentry *direntry, int mode)
+{
+ int rc = -ENOENT;
+ int xid;
+ int oplock = 0; /* no sense requested oplock if we are just going to
+ immediately close the file */
+ __u16 fileHandle;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ FILE_ALL_INFO * buf = NULL;
+ struct inode *newinode = NULL;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&direntry->d_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&direntry->d_sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+
+ /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
+
+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OVERWRITE_IF,
+ GENERIC_WRITE, CREATE_NOT_DIR,
+ &fileHandle, &oplock, buf, cifs_sb->local_nls);
+ if (rc) {
+ cFYI(1, ("cifs_create returned 0x%x ", rc));
+ } else {
+ /* BB for case of overwriting existing file can we use the inode that was
+ passed in rather than creating new one?? */
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb,xid);
+ else
+ rc = cifs_get_inode_info(&newinode, full_path,
+ buf, inode->i_sb,xid);
+
+ if (rc != 0) {
+ cFYI(1,("Create worked but get_inode_info failed with rc = %d",
+ rc));
+ } else {
+ direntry->d_op = &cifs_dentry_ops;
+ d_instantiate(direntry, newinode);
+ }
+ CIFSSMBClose(xid, pTcon, fileHandle);
+
+ if(newinode) {
+ newinode->i_mode = mode;
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
+ (__u64)-1,
+ (__u64)-1,
+ 0 /* dev */,
+ cifs_sb->local_nls);
+ else { /* BB implement via Windows security descriptors */
+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
+ /* in the meantime could set r/o dos attribute when perms are eg:
+ mode & 0222 == 0 */
+ }
+ }
+ }
+
+ if (buf)
+ kfree(buf);
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+
+ return rc;
+}
+
+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number)
+{
+ int rc = -EPERM;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ struct inode * newinode = NULL;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&direntry->d_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&direntry->d_sb->s_vfs_rename_sem);
+ if(full_path == NULL)
+ rc = -ENOMEM;
+
+ if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
+ rc = CIFSSMBUnixSetPerms(xid, pTcon,
+ full_path, mode, current->euid, current->egid,
+ device_number, cifs_sb->local_nls);
+ if(!rc) {
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb,xid);
+ direntry->d_op = &cifs_dentry_ops;
+ if(rc == 0)
+ d_instantiate(direntry, newinode);
+ }
+ }
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+
+ return rc;
+}
+
+
+struct dentry *
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
+{
+ int xid;
+ int rc = 0; /* to get around spurious gcc warning, set to zero here */
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct inode *newInode = NULL;
+ char *full_path = NULL;
+
+ xid = GetXid();
+
+ cFYI(1,
+ (" parent inode = 0x%p name is: %s and dentry = 0x%p",
+ parent_dir_inode, direntry->d_name.name, direntry));
+
+ /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
+
+ /* check whether path exists */
+
+ cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ /* can not grab the rename sem here since it would
+ deadlock in the cases (beginning of sys_rename itself)
+ in which we already have the sb rename sem */
+ full_path = build_path_from_dentry(direntry);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (direntry->d_inode != NULL) {
+ cFYI(1, (" non-NULL inode in lookup"));
+ } else {
+ cFYI(1, (" NULL inode in lookup"));
+ }
+ cFYI(1,
+ (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
+
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&newInode, full_path,
+ parent_dir_inode->i_sb,xid);
+ else
+ rc = cifs_get_inode_info(&newInode, full_path, NULL,
+ parent_dir_inode->i_sb,xid);
+
+ if ((rc == 0) && (newInode != NULL)) {
+ direntry->d_op = &cifs_dentry_ops;
+ d_add(direntry, newInode);
+
+ /* since paths are not looked up by component - the parent directories are presumed to be good here */
+ renew_parental_timestamps(direntry);
+
+ } else if (rc == -ENOENT) {
+ rc = 0;
+ d_add(direntry, NULL);
+ } else {
+ cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
+ /* BB special case check for Access Denied - watch security
+ exposure of returning dir info implicitly via different rc
+ if file exists or not but no access BB */
+ }
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return ERR_PTR(rc);
+}
+
+int
+cifs_dir_open(struct inode *inode, struct file *file)
+{ /* NB: currently unused since searches are opened in readdir */
+ int rc = 0;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ if(file->f_dentry) {
+ down(&file->f_dentry->d_sb->s_vfs_rename_sem);
+ full_path = build_wildcard_path_from_dentry(file->f_dentry);
+ up(&file->f_dentry->d_sb->s_vfs_rename_sem);
+ } else {
+ FreeXid(xid);
+ return -EIO;
+ }
+
+ cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+static int
+cifs_d_revalidate(struct dentry *direntry, int flags)
+{
+ int isValid = 1;
+
+/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
+
+ if (direntry->d_inode) {
+ if (cifs_revalidate(direntry)) {
+ /* unlock_kernel(); */
+ return 0;
+ }
+ } else {
+ cFYI(1,
+ ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
+ direntry->d_name.name, direntry));
+ }
+
+/* unlock_kernel(); */
+
+ return isValid;
+}
+
+/* static int cifs_d_delete(struct dentry *direntry)
+{
+ int rc = 0;
+
+ cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
+
+ return rc;
+} */
+
+struct dentry_operations cifs_dentry_ops = {
+ .d_revalidate = cifs_d_revalidate,
+/* d_delete: cifs_d_delete, *//* not needed except for debugging */
+ /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
+};
diff --git a/release/src/linux/linux/fs/cifs/file.c b/release/src/linux/linux/fs/cifs/file.c
new file mode 100644
index 00000000..d7f3bac6
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/file.c
@@ -0,0 +1,2185 @@
+/*
+ * fs/cifs/file.c
+ *
+ * vfs operations that deal with files
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/version.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
+#include <linux/list.h>
+#include <asm/div64.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+int
+cifs_open(struct inode *inode, struct file *file)
+{
+ int rc = -EACCES;
+ int xid, oplock;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct cifsFileInfo *pCifsFile;
+ struct cifsInodeInfo *pCifsInode;
+ char *full_path = NULL;
+ int desiredAccess = 0x20197;
+ int disposition;
+ __u16 netfid;
+ FILE_ALL_INFO * buf = NULL;
+ time_t temp;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&inode->i_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(file->f_dentry);
+ up(&inode->i_sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+
+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+ desiredAccess = GENERIC_READ;
+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+ desiredAccess = GENERIC_WRITE;
+ else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+ /* GENERIC_ALL is too much permission to request */
+ /* can cause unnecessary access denied on create */
+ /* desiredAccess = GENERIC_ALL; */
+ desiredAccess = GENERIC_READ | GENERIC_WRITE;
+ }
+
+/*********************************************************************
+ * open flag mapping table:
+ *
+ * POSIX Flag CIFS Disposition
+ * ---------- ----------------
+ * O_CREAT FILE_OPEN_IF
+ * O_CREAT | O_EXCL FILE_CREATE
+ * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
+ * O_TRUNC FILE_OVERWRITE
+ * none of the above FILE_OPEN
+ *
+ * Note that there is not a direct match between disposition
+ * FILE_SUPERSEDE (ie create whether or not file exists although
+ * O_CREAT | O_TRUNC is similar but truncates the existing
+ * file rather than creating a new file as FILE_SUPERSEDE does
+ * (which uses the attributes / metadata passed in on open call)
+ *?
+ *? O_SYNC is a reasonable match to CIFS writethrough flag
+ *? and the read write flags match reasonably. O_LARGEFILE
+ *? is irrelevant because largefile support is always used
+ *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
+ * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
+ *********************************************************************/
+
+ /* For 2.4 case, file was already checked for existence
+ before create by vfs lookup and created in create
+ entry point, we are now just opening the newly
+ created file with the right desiredAccess flags */
+
+ if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ disposition = FILE_OPEN_IF;
+ else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ disposition = FILE_OVERWRITE_IF;
+ else if((file->f_flags & O_CREAT) == O_CREAT)
+ disposition = FILE_OPEN_IF;
+ else
+ disposition = FILE_OPEN;
+
+ if (oplockEnabled)
+ oplock = REQ_OPLOCK;
+ else
+ oplock = FALSE;
+
+ /* BB pass O_SYNC flag through on file attributes .. BB */
+
+ /* Also refresh inode by passing in file_info buf returned by SMBOpen
+ and calling get_inode_info with returned buf (at least
+ helps non-Unix server case */
+
+ /* BB we can not do this if this is the second open of a file
+ and the first handle has writebehind data, we might be
+ able to simply do a filemap_fdatawrite/filemap_fdatawait first */
+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+ if(buf==0) {
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
+ CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
+ if (rc) {
+ cFYI(1, ("cifs_open returned 0x%x ", rc));
+ cFYI(1, ("oplock: %d ", oplock));
+ } else {
+ file->private_data =
+ kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
+ if (file->private_data) {
+ memset(file->private_data, 0, sizeof(struct cifsFileInfo));
+ pCifsFile = (struct cifsFileInfo *) file->private_data;
+ pCifsFile->netfid = netfid;
+ pCifsFile->pid = current->pid;
+ init_MUTEX(&pCifsFile->fh_sem);
+ pCifsFile->pfile = file; /* needed for writepage */
+ pCifsFile->pInode = inode;
+ pCifsFile->invalidHandle = FALSE;
+ pCifsFile->closePend = FALSE;
+ write_lock(&GlobalSMBSeslock);
+ spin_lock(&files_lock);
+ list_add(&pCifsFile->tlist,&pTcon->openFileList);
+ pCifsInode = CIFS_I(file->f_dentry->d_inode);
+ if(pCifsInode) {
+ /* want handles we can use to read with first */
+ /* in the list so we do not have to walk the */
+ /* list to search for one in prepare_write */
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+ list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
+ } else {
+ list_add(&pCifsFile->flist,&pCifsInode->openFileList);
+ }
+ spin_unlock(&files_lock);
+ write_unlock(&GlobalSMBSeslock);
+ if(pCifsInode->clientCanCacheRead) {
+ /* we have the inode open somewhere else
+ no need to discard cache data */
+ } else {
+ if(buf) {
+ /* BB need same check in cifs_create too? */
+
+ /* if not oplocked, invalidate inode pages if mtime
+ or file size changed */
+ temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
+ if((file->f_dentry->d_inode->i_mtime == temp) &&
+ (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
+ cFYI(1,("inode unchanged on server"));
+ } else {
+ if(file->f_dentry->d_inode->i_mapping) {
+ /* BB no need to lock inode until after invalidate*/
+ /* since namei code should already have it locked?*/
+ filemap_fdatasync(file->f_dentry->d_inode->i_mapping);
+ }
+ cFYI(1,("invalidating remote inode since open detected it changed"));
+ invalidate_inode_pages(file->f_dentry->d_inode);
+ }
+ }
+ }
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
+ full_path, inode->i_sb,xid);
+ else
+ rc = cifs_get_inode_info(&file->f_dentry->d_inode,
+ full_path, buf, inode->i_sb,xid);
+
+ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = TRUE;
+ pCifsInode->clientCanCacheRead = TRUE;
+ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
+ } else if((oplock & 0xF) == OPLOCK_READ)
+ pCifsInode->clientCanCacheRead = TRUE;
+ } else {
+ spin_unlock(&files_lock);
+ write_unlock(&GlobalSMBSeslock);
+ }
+ if(oplock & CIFS_CREATE_ACTION) {
+ /* time to set mode which we can not set earlier due
+ to problems creating new read-only files */
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
+ (__u64)-1,
+ (__u64)-1,
+ 0 /* dev */,
+ cifs_sb->local_nls);
+ else {/* BB implement via Windows security descriptors */
+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
+ /* in the meantime could set r/o dos attribute when perms are eg:
+ mode & 0222 == 0 */
+ }
+ }
+ }
+ }
+
+ if (buf)
+ kfree(buf);
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+/* Try to reaquire byte range locks that were released when session */
+/* to server was lost */
+static int cifs_relock_file(struct cifsFileInfo * cifsFile)
+{
+ int rc = 0;
+
+/* BB list all locks open on this file and relock */
+
+ return rc;
+}
+
+static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
+{
+ int rc = -EACCES;
+ int xid, oplock;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct cifsFileInfo *pCifsFile;
+ struct cifsInodeInfo *pCifsInode;
+ char *full_path = NULL;
+ int desiredAccess = 0x20197;
+ int disposition = FILE_OPEN;
+ __u16 netfid;
+
+ if(inode == NULL)
+ return -EBADF;
+ if (file->private_data) {
+ pCifsFile = (struct cifsFileInfo *) file->private_data;
+ } else
+ return -EBADF;
+
+ xid = GetXid();
+ down(&pCifsFile->fh_sem);
+ if(pCifsFile->invalidHandle == FALSE) {
+ up(&pCifsFile->fh_sem);
+ FreeXid(xid);
+ return 0;
+ }
+
+ if(file->f_dentry == NULL) {
+ up(&pCifsFile->fh_sem);
+ cFYI(1,("failed file reopen, no valid name if dentry freed"));
+ FreeXid(xid);
+ return -EBADF;
+ }
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+/* can not grab rename sem here because various ops, including
+those that already have the rename sem can end up causing writepage
+to get called and if the server was down that means we end up here,
+and we can never tell if the caller already has the rename_sem */
+ full_path = build_path_from_dentry(file->f_dentry);
+ if(full_path == NULL) {
+ up(&pCifsFile->fh_sem);
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+
+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+ desiredAccess = GENERIC_READ;
+ else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+ desiredAccess = GENERIC_WRITE;
+ else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+ /* GENERIC_ALL is too much permission to request */
+ /* can cause unnecessary access denied on create */
+ /* desiredAccess = GENERIC_ALL; */
+ desiredAccess = GENERIC_READ | GENERIC_WRITE;
+ }
+
+ if (oplockEnabled)
+ oplock = REQ_OPLOCK;
+ else
+ oplock = FALSE;
+
+
+ /* Can not refresh inode by passing in file_info buf to be returned
+ by SMBOpen and then calling get_inode_info with returned buf
+ since file might have write behind data that needs to be flushed
+ and server version of file size can be stale. If we
+ knew for sure that inode was not dirty locally we could do this */
+
+/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+ if(buf==0) {
+ up(&pCifsFile->fh_sem);
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return -ENOMEM;
+ }*/
+ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
+ CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
+ if (rc) {
+ up(&pCifsFile->fh_sem);
+ cFYI(1, ("cifs_open returned 0x%x ", rc));
+ cFYI(1, ("oplock: %d ", oplock));
+ } else {
+ pCifsFile->netfid = netfid;
+ pCifsFile->invalidHandle = FALSE;
+ up(&pCifsFile->fh_sem);
+ pCifsInode = CIFS_I(inode);
+ if(pCifsInode) {
+ if(can_flush) {
+ filemap_fdatasync(inode->i_mapping);
+ filemap_fdatawait(inode->i_mapping);
+ /* temporarily disable caching while we
+ go to server to get inode info */
+ pCifsInode->clientCanCacheAll = FALSE;
+ pCifsInode->clientCanCacheRead = FALSE;
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&inode,
+ full_path, inode->i_sb,xid);
+ else
+ rc = cifs_get_inode_info(&inode,
+ full_path, NULL, inode->i_sb,xid);
+ } /* else we are writing out data to server already
+ and could deadlock if we tried to flush data, and
+ since we do not know if we have data that would
+ invalidate the current end of file on the server
+ we can not go to the server to get the new
+ inod info */
+ if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = TRUE;
+ pCifsInode->clientCanCacheRead = TRUE;
+ cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
+ } else if((oplock & 0xF) == OPLOCK_READ) {
+ pCifsInode->clientCanCacheRead = TRUE;
+ pCifsInode->clientCanCacheAll = FALSE;
+ } else {
+ pCifsInode->clientCanCacheRead = FALSE;
+ pCifsInode->clientCanCacheAll = FALSE;
+ }
+ cifs_relock_file(pCifsFile);
+ }
+ }
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_close(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct cifsFileInfo *pSMBFile =
+ (struct cifsFileInfo *) file->private_data;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+ if (pSMBFile) {
+ pSMBFile->closePend = TRUE;
+ spin_lock(&files_lock);
+ if(pTcon) {
+ /* no sense reconnecting to close a file that is
+ already closed */
+ if (pTcon->tidStatus != CifsNeedReconnect) {
+ spin_unlock(&files_lock);
+ rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
+ spin_lock(&files_lock);
+ }
+ }
+ list_del(&pSMBFile->flist);
+ list_del(&pSMBFile->tlist);
+ spin_unlock(&files_lock);
+ if(pSMBFile->search_resume_name)
+ kfree(pSMBFile->search_resume_name);
+ kfree(file->private_data);
+ file->private_data = NULL;
+ } else
+ rc = -EBADF;
+
+ if(list_empty(&(CIFS_I(inode)->openFileList))) {
+ cFYI(1,("closing last open instance for inode %p",inode));
+ /* if the file is not open we do not know if we can cache
+ info on this inode, much less write behind and read ahead */
+ CIFS_I(inode)->clientCanCacheRead = FALSE;
+ CIFS_I(inode)->clientCanCacheAll = FALSE;
+ }
+ if((rc ==0) && CIFS_I(inode)->write_behind_rc)
+ rc = CIFS_I(inode)->write_behind_rc;
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_closedir(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ int xid;
+ struct cifsFileInfo *pSMBFileStruct =
+ (struct cifsFileInfo *) file->private_data;
+
+ cFYI(1, ("Closedir inode = 0x%p with ", inode));
+
+ xid = GetXid();
+
+ if (pSMBFileStruct) {
+ cFYI(1, ("Freeing private data in close dir"));
+ kfree(file->private_data);
+ file->private_data = NULL;
+ }
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
+{
+ int rc, xid;
+ __u32 lockType = LOCKING_ANDX_LARGE_FILES;
+ __u32 numLock = 0;
+ __u32 numUnlock = 0;
+ __u64 length;
+ int wait_flag = FALSE;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ length = 1 + pfLock->fl_end - pfLock->fl_start;
+
+ rc = -EACCES;
+
+ xid = GetXid();
+
+ cFYI(1,
+ ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
+ cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
+ pfLock->fl_end));
+
+ if (pfLock->fl_flags & FL_POSIX)
+ cFYI(1, ("Posix "));
+ if (pfLock->fl_flags & FL_FLOCK)
+ cFYI(1, ("Flock "));
+/* if (pfLock->fl_flags & FL_SLEEP) {
+ cFYI(1, ("Blocking lock "));
+ wait_flag = TRUE;
+ } */
+ if (pfLock->fl_flags & FL_ACCESS)
+ cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
+ if (pfLock->fl_flags & FL_LEASE)
+ cFYI(1, ("Lease on file - not implemented yet"));
+ if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_ACCESS | FL_LEASE)))
+ cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
+
+ if (pfLock->fl_type == F_WRLCK) {
+ cFYI(1, ("F_WRLCK "));
+ numLock = 1;
+ } else if (pfLock->fl_type == F_UNLCK) {
+ cFYI(1, ("F_UNLCK "));
+ numUnlock = 1;
+ } else if (pfLock->fl_type == F_RDLCK) {
+ cFYI(1, ("F_RDLCK "));
+ lockType |= LOCKING_ANDX_SHARED_LOCK;
+ numLock = 1;
+ } else if (pfLock->fl_type == F_EXLCK) {
+ cFYI(1, ("F_EXLCK "));
+ numLock = 1;
+ } else if (pfLock->fl_type == F_SHLCK) {
+ cFYI(1, ("F_SHLCK "));
+ lockType |= LOCKING_ANDX_SHARED_LOCK;
+ numLock = 1;
+ } else
+ cFYI(1, ("Unknown type of lock "));
+
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+
+ if (file->private_data == NULL) {
+ FreeXid(xid);
+ return -EBADF;
+ }
+
+ if (IS_GETLK(cmd)) {
+ rc = CIFSSMBLock(xid, pTcon,
+ ((struct cifsFileInfo *) file->
+ private_data)->netfid,
+ length,
+ pfLock->fl_start, 0, 1, lockType,
+ 0 /* wait flag */ );
+ if (rc == 0) {
+ rc = CIFSSMBLock(xid, pTcon,
+ ((struct cifsFileInfo *) file->
+ private_data)->netfid,
+ length,
+ pfLock->fl_start, 1 /* numUnlock */ ,
+ 0 /* numLock */ , lockType,
+ 0 /* wait flag */ );
+ pfLock->fl_type = F_UNLCK;
+ if (rc != 0)
+ cERROR(1,
+ ("Error unlocking previously locked range %d during test of lock ",
+ rc));
+ rc = 0;
+
+ } else {
+ /* if rc == ERR_SHARING_VIOLATION ? */
+ rc = 0; /* do not change lock type to unlock since range in use */
+ }
+
+ FreeXid(xid);
+ return rc;
+ }
+
+ rc = CIFSSMBLock(xid, pTcon,
+ ((struct cifsFileInfo *) file->private_data)->
+ netfid, length,
+ pfLock->fl_start, numUnlock, numLock, lockType,
+ wait_flag);
+ FreeXid(xid);
+ return rc;
+}
+
+ssize_t
+cifs_write(struct file * file, const char *write_data,
+ size_t write_size, loff_t * poffset)
+{
+ int rc = 0;
+ unsigned int bytes_written = 0;
+ unsigned int total_written;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ int xid, long_op;
+ struct cifsFileInfo * open_file;
+
+ if(file->f_dentry == NULL)
+ return -EBADF;
+
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ if(cifs_sb == NULL) {
+ return -EBADF;
+ }
+ pTcon = cifs_sb->tcon;
+
+ /*cFYI(1,
+ (" write %d bytes to offset %lld of %s", write_size,
+ *poffset, file->f_dentry->d_name.name)); */
+
+ if (file->private_data == NULL) {
+ return -EBADF;
+ } else {
+ open_file = (struct cifsFileInfo *) file->private_data;
+ }
+
+ xid = GetXid();
+ if(file->f_dentry->d_inode == NULL) {
+ FreeXid(xid);
+ return -EBADF;
+ }
+
+ if (*poffset > file->f_dentry->d_inode->i_size)
+ long_op = 2; /* writes past end of file can take a long time */
+ else
+ long_op = 1;
+
+ for (total_written = 0; write_size > total_written;
+ total_written += bytes_written) {
+ rc = -EAGAIN;
+ while(rc == -EAGAIN) {
+ if(file->private_data == NULL) {
+ /* file has been closed on us */
+ FreeXid(xid);
+ /* if we have gotten here we have written some data
+ and blocked, and the file has been freed on us
+ while we blocked so return what we managed to write */
+ return total_written;
+ }
+ if(open_file->closePend) {
+ FreeXid(xid);
+ if(total_written)
+ return total_written;
+ else
+ return -EBADF;
+ }
+ if (open_file->invalidHandle) {
+ if((file->f_dentry == NULL) ||
+ (file->f_dentry->d_inode == NULL)) {
+ FreeXid(xid);
+ return total_written;
+ }
+ /* we could deadlock if we called
+ filemap_fdatawait from here so tell
+ reopen_file not to flush data to server now */
+ rc = cifs_reopen_file(file->f_dentry->d_inode,
+ file,FALSE);
+ if(rc != 0)
+ break;
+ }
+
+ rc = CIFSSMBWrite(xid, pTcon,
+ open_file->netfid,
+ write_size - total_written, *poffset,
+ &bytes_written,
+ write_data + total_written, long_op);
+ }
+ if (rc || (bytes_written == 0)) {
+ if (total_written)
+ break;
+ else {
+ FreeXid(xid);
+ return rc;
+ }
+ } else
+ *poffset += bytes_written;
+ long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
+ }
+
+#ifdef CONFIG_CIFS_STATS
+ if(total_written > 0) {
+ atomic_inc(&pTcon->num_writes);
+ spin_lock(&pTcon->stat_lock);
+ pTcon->bytes_written += total_written;
+ spin_unlock(&pTcon->stat_lock);
+ }
+#endif
+
+ /* since the write may have blocked check these pointers again */
+ if(file->f_dentry) {
+ if(file->f_dentry->d_inode) {
+ file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
+ CURRENT_TIME;
+ if (total_written > 0) {
+ if (*poffset > file->f_dentry->d_inode->i_size)
+ file->f_dentry->d_inode->i_size = *poffset;
+ }
+ mark_inode_dirty_sync(file->f_dentry->d_inode);
+ }
+ }
+ FreeXid(xid);
+ return total_written;
+}
+
+static int
+cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
+{
+ struct address_space *mapping = page->mapping;
+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ char * write_data;
+ int rc = -EFAULT;
+ int bytes_written = 0;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct inode *inode;
+ struct cifsInodeInfo *cifsInode;
+ struct cifsFileInfo *open_file = NULL;
+ struct list_head *tmp;
+ struct list_head *tmp1;
+
+ if (!mapping) {
+ return -EFAULT;
+ } else if(!mapping->host) {
+ return -EFAULT;
+ }
+
+ inode = page->mapping->host;
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ offset += (loff_t)from;
+ write_data = kmap(page);
+ write_data += from;
+
+ if((to > PAGE_CACHE_SIZE) || (from > to)) {
+ kunmap(page);
+ return -EIO;
+ }
+
+ /* racing with truncate? */
+ if(offset > mapping->host->i_size) {
+ kunmap(page);
+ return 0; /* don't care */
+ }
+
+ /* check to make sure that we are not extending the file */
+ if(mapping->host->i_size - offset < (loff_t)to)
+ to = (unsigned)(mapping->host->i_size - offset);
+
+
+ cifsInode = CIFS_I(mapping->host);
+ read_lock(&GlobalSMBSeslock);
+ /* BB we should start at the end */
+ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
+ if(open_file->closePend)
+ continue;
+ /* We check if file is open for writing first */
+ if((open_file->pfile) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ read_unlock(&GlobalSMBSeslock);
+ bytes_written = cifs_write(open_file->pfile, write_data,
+ to-from, &offset);
+ read_lock(&GlobalSMBSeslock);
+ /* Does mm or vfs already set times? */
+ inode->i_atime = inode->i_mtime = CURRENT_TIME;
+ if ((bytes_written > 0) && (offset)) {
+ rc = 0;
+ } else if(bytes_written < 0) {
+ if(rc == -EBADF) {
+ /* have seen a case in which
+ kernel seemed to have closed/freed a file
+ even with writes active so we might as well
+ see if there are other file structs to try
+ for the same inode before giving up */
+ continue;
+ } else
+ rc = bytes_written;
+ }
+ break; /* now that we found a valid file handle
+ and tried to write to it we are done, no
+ sense continuing to loop looking for another */
+ }
+ if(tmp->next == NULL) {
+ cFYI(1,("File instance %p removed",tmp));
+ break;
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ if(open_file == NULL) {
+ cFYI(1,("No writeable filehandles for inode"));
+ rc = -EIO;
+ }
+
+ kunmap(page);
+ return rc;
+}
+
+#if 0
+static int
+cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
+{
+ int rc = -EFAULT;
+ int xid;
+
+ xid = GetXid();
+/* call 16K write then Setpageuptodate */
+ FreeXid(xid);
+ return rc;
+}
+#endif
+
+static int
+cifs_writepage(struct page* page)
+{
+ int rc = -EFAULT;
+ int xid;
+
+ xid = GetXid();
+/* BB add check for wbc flags */
+ page_cache_get(page);
+ if (!Page_Uptodate(page)) {
+ cFYI(1,("ppw - page not up to date"));
+ }
+
+ rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
+ SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+ unlock_page(page);
+#else
+ UnlockPage(page);
+#endif
+ page_cache_release(page);
+ FreeXid(xid);
+ return rc;
+}
+
+static int
+cifs_commit_write(struct file *file, struct page *page, unsigned offset,
+ unsigned to)
+{
+ int xid;
+ int rc = 0;
+ struct inode *inode = page->mapping->host;
+ loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ char * page_data;
+
+ xid = GetXid();
+ cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
+ if (position > inode->i_size){
+ inode->i_size = position;
+ /*if (file->private_data == NULL) {
+ rc = -EBADF;
+ } else {
+ open_file = (struct cifsFileInfo *)file->private_data;
+ cifs_sb = CIFS_SB(inode->i_sb);
+ rc = -EAGAIN;
+ while(rc == -EAGAIN) {
+ if((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
+ rc = cifs_reopen_file(file->f_dentry->d_inode,file);
+ if(rc != 0)
+ break;
+ }
+ if(!open_file->closePend) {
+ rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
+ position, open_file->netfid,
+ open_file->pid,FALSE);
+ } else {
+ rc = -EBADF;
+ break;
+ }
+ }
+ cFYI(1,(" SetEOF (commit write) rc = %d",rc));
+ }*/
+ }
+ if (!Page_Uptodate(page)) {
+ position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
+ /* can not rely on (or let) writepage write this data */
+ if(to < offset) {
+ cFYI(1,("Illegal offsets, can not copy from %d to %d",
+ offset,to));
+ FreeXid(xid);
+ return rc;
+ }
+ /* this is probably better than directly calling
+ partialpage_write since in this function
+ the file handle is known which we might as well
+ leverage */
+ /* BB check if anything else missing out of ppw */
+ /* such as updating last write time */
+ page_data = kmap(page);
+ rc = cifs_write(file, page_data+offset,to-offset,
+ &position);
+ if(rc > 0)
+ rc = 0;
+ /* else if rc < 0 should we set writebehind rc? */
+ kunmap(page);
+ } else {
+ set_page_dirty(page);
+ }
+
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+ int xid;
+ int rc = 0;
+ struct inode * inode = file->f_dentry->d_inode;
+
+ xid = GetXid();
+
+ cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
+ dentry->d_name.name, datasync));
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
+ rc = filemap_fdatasync(inode->i_mapping);
+#else
+ filemap_fdatasync(inode->i_mapping);
+#endif
+ if(rc == 0)
+ CIFS_I(inode)->write_behind_rc = 0;
+ FreeXid(xid);
+ return rc;
+}
+
+static int
+cifs_sync_page(struct page *page)
+{
+ struct address_space *mapping;
+ struct inode *inode;
+ unsigned long index = page->index;
+ unsigned int rpages = 0;
+ int rc = 0;
+
+ cFYI(1,("sync page %p",page));
+ mapping = page->mapping;
+ if (!mapping)
+ return 0;
+ inode = mapping->host;
+ if (!inode)
+ return 0;
+
+/* fill in rpages then
+ result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
+
+ cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
+
+ if (rc < 0)
+ return rc;
+ return 0;
+}
+
+/*
+ * As file closes, flush all cached write data for this inode checking
+ * for write behind errors.
+ *
+ */
+int cifs_flush(struct file *file)
+{
+ struct inode * inode = file->f_dentry->d_inode;
+ int rc = 0;
+
+ /* Rather than do the steps manually: */
+ /* lock the inode for writing */
+ /* loop through pages looking for write behind data (dirty pages) */
+ /* coalesce into contiguous 16K (or smaller) chunks to write to server */
+ /* send to server (prefer in parallel) */
+ /* deal with writebehind errors */
+ /* unlock inode for writing */
+ /* filemapfdatawrite appears easier for the time being */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
+ rc = filemap_fdatasync(inode->i_mapping);
+#else
+ filemap_fdatasync(inode->i_mapping);
+#endif
+ if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
+ CIFS_I(inode)->write_behind_rc = 0;
+
+ cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
+
+ return rc;
+}
+
+
+ssize_t
+cifs_read(struct file * file, char *read_data, size_t read_size,
+ loff_t * poffset)
+{
+ int rc = -EACCES;
+ unsigned int bytes_read = 0;
+ unsigned int total_read;
+ unsigned int current_read_size;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ int xid;
+ char * current_offset;
+ struct cifsFileInfo * open_file;
+
+ xid = GetXid();
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+
+ if (file->private_data == NULL) {
+ FreeXid(xid);
+ return -EBADF;
+ }
+ open_file = (struct cifsFileInfo *)file->private_data;
+
+ if((file->f_flags & O_ACCMODE) == O_WRONLY) {
+ cFYI(1,("attempting read on write only file instance"));
+ }
+
+ for (total_read = 0,current_offset=read_data; read_size > total_read;
+ total_read += bytes_read,current_offset+=bytes_read) {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
+ current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
+#else
+ current_read_size = min(read_size - total_read,cifs_sb->rsize);
+#endif
+ rc = -EAGAIN;
+ while(rc == -EAGAIN) {
+ if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ rc = cifs_reopen_file(file->f_dentry->d_inode,
+ file,TRUE);
+ if(rc != 0)
+ break;
+ }
+
+ rc = CIFSSMBRead(xid, pTcon,
+ open_file->netfid,
+ current_read_size, *poffset,
+ &bytes_read, &current_offset);
+ }
+ if (rc || (bytes_read == 0)) {
+ if (total_read) {
+ break;
+ } else {
+ FreeXid(xid);
+ return rc;
+ }
+ } else {
+#ifdef CONFIG_CIFS_STATS
+ atomic_inc(&pTcon->num_reads);
+ spin_lock(&pTcon->stat_lock);
+ pTcon->bytes_read += total_read;
+ spin_unlock(&pTcon->stat_lock);
+#endif
+ *poffset += bytes_read;
+ }
+ }
+ FreeXid(xid);
+ return total_read;
+}
+
+int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
+{
+ struct dentry * dentry = file->f_dentry;
+ int rc, xid;
+
+ xid = GetXid();
+ rc = cifs_revalidate(dentry);
+ if (rc) {
+ cFYI(1,("Validation prior to mmap failed, error=%d", rc));
+ FreeXid(xid);
+ return rc;
+ }
+ rc = generic_file_mmap(file, vma);
+ FreeXid(xid);
+ return rc;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static void cifs_copy_cache_pages(struct address_space *mapping,
+ struct list_head *pages, int bytes_read,
+ char *data,struct pagevec * plru_pvec)
+{
+ struct page *page;
+ char * target;
+
+ while (bytes_read > 0) {
+ if(list_empty(pages))
+ break;
+
+ page = list_entry(pages->prev, struct page, lru);
+ list_del(&page->lru);
+
+ if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
+ page_cache_release(page);
+ cFYI(1,("Add page cache failed"));
+ continue;
+ }
+
+ target = kmap_atomic(page,KM_USER0);
+
+ if(PAGE_CACHE_SIZE > bytes_read) {
+ memcpy(target,data,bytes_read);
+ /* zero the tail end of this partial page */
+ memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
+ bytes_read = 0;
+ } else {
+ memcpy(target,data,PAGE_CACHE_SIZE);
+ bytes_read -= PAGE_CACHE_SIZE;
+ }
+ kunmap_atomic(target,KM_USER0);
+
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ unlock_page(page);
+ if (!pagevec_add(plru_pvec, page))
+ __pagevec_lru_add(plru_pvec);
+ data += PAGE_CACHE_SIZE;
+ }
+ return;
+}
+
+
+static int
+cifs_readpages(struct file *file, struct address_space *mapping,
+ struct list_head *page_list, unsigned num_pages)
+{
+ int rc = -EACCES;
+ int xid;
+ loff_t offset;
+ struct page * page;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ int bytes_read = 0;
+ unsigned int read_size,i;
+ char * smb_read_data = NULL;
+ struct smb_com_read_rsp * pSMBr;
+ struct pagevec lru_pvec;
+ struct cifsFileInfo * open_file;
+
+ xid = GetXid();
+ if (file->private_data == NULL) {
+ FreeXid(xid);
+ return -EBADF;
+ }
+ open_file = (struct cifsFileInfo *)file->private_data;
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+
+ pagevec_init(&lru_pvec, 0);
+
+ for(i = 0;i<num_pages;) {
+ unsigned contig_pages;
+ struct page * tmp_page;
+ unsigned long expected_index;
+
+ if(list_empty(page_list)) {
+ break;
+ }
+ page = list_entry(page_list->prev, struct page, lru);
+ offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+
+ /* count adjacent pages that we will read into */
+ contig_pages = 0;
+ expected_index = list_entry(page_list->prev,struct page,lru)->index;
+ list_for_each_entry_reverse(tmp_page,page_list,lru) {
+ if(tmp_page->index == expected_index) {
+ contig_pages++;
+ expected_index++;
+ } else {
+ break;
+ }
+ }
+ if(contig_pages + i > num_pages) {
+ contig_pages = num_pages - i;
+ }
+
+ /* for reads over a certain size could initiate async read ahead */
+
+ read_size = contig_pages * PAGE_CACHE_SIZE;
+ /* Read size needs to be in multiples of one page */
+ read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
+
+ rc = -EAGAIN;
+ while(rc == -EAGAIN) {
+ if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ rc = cifs_reopen_file(file->f_dentry->d_inode,
+ file, TRUE);
+ if(rc != 0)
+ break;
+ }
+
+ rc = CIFSSMBRead(xid, pTcon,
+ open_file->netfid,
+ read_size, offset,
+ &bytes_read, &smb_read_data);
+ /* BB need to check return code here */
+ if(rc== -EAGAIN) {
+ if(smb_read_data) {
+ cifs_buf_release(smb_read_data);
+ smb_read_data = NULL;
+ }
+ }
+ }
+ if ((rc < 0) || (smb_read_data == NULL)) {
+ cFYI(1,("Read error in readpages: %d",rc));
+ /* clean up remaing pages off list */
+ while (!list_empty(page_list) && (i < num_pages)) {
+ page = list_entry(page_list->prev, struct page, lru);
+ list_del(&page->lru);
+ page_cache_release(page);
+ }
+ break;
+ } else if (bytes_read > 0) {
+ pSMBr = (struct smb_com_read_rsp *)smb_read_data;
+ cifs_copy_cache_pages(mapping, page_list, bytes_read,
+ smb_read_data + 4 /* RFC1001 hdr */ +
+ le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
+
+ i += bytes_read >> PAGE_CACHE_SHIFT;
+#ifdef CONFIG_CIFS_STATS
+ atomic_inc(&pTcon->num_reads);
+ spin_lock(&pTcon->stat_lock);
+ pTcon->bytes_read += bytes_read;
+ spin_unlock(&pTcon->stat_lock);
+#endif
+ if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
+ cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
+
+ i++; /* account for partial page */
+
+ /* server copy of file can have smaller size than client */
+ /* BB do we need to verify this common case ? this case is ok -
+ if we are at server EOF we will hit it on next read */
+
+ /* while(!list_empty(page_list) && (i < num_pages)) {
+ page = list_entry(page_list->prev,struct page, list);
+ list_del(&page->list);
+ page_cache_release(page);
+ }
+ break; */
+ }
+ } else {
+ cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
+ /* BB turn off caching and do new lookup on file size at server? */
+ while (!list_empty(page_list) && (i < num_pages)) {
+ page = list_entry(page_list->prev, struct page, lru);
+ list_del(&page->lru);
+ page_cache_release(page); /* BB removeme - replace with zero of page? */
+ }
+ break;
+ }
+ if(smb_read_data) {
+ cifs_buf_release(smb_read_data);
+ smb_read_data = NULL;
+ }
+ bytes_read = 0;
+ }
+
+ pagevec_lru_add(&lru_pvec);
+
+/* need to free smb_read_data buf before exit */
+ if(smb_read_data) {
+ cifs_buf_release(smb_read_data);
+ smb_read_data = NULL;
+ }
+
+ FreeXid(xid);
+ return rc;
+}
+#endif
+
+static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
+{
+ char * read_data;
+ int rc;
+
+ page_cache_get(page);
+ read_data = kmap(page);
+ /* for reads over a certain size could initiate async read ahead */
+
+ rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
+
+ if (rc < 0)
+ goto io_error;
+ else {
+ cFYI(1,("Bytes read %d ",rc));
+ }
+
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+
+ if(PAGE_CACHE_SIZE > rc) {
+ memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
+ }
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ rc = 0;
+
+io_error:
+ kunmap(page);
+ page_cache_release(page);
+ return rc;
+}
+
+static int
+cifs_readpage(struct file *file, struct page *page)
+{
+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ int rc = -EACCES;
+ int xid;
+
+ xid = GetXid();
+
+ if (file->private_data == NULL) {
+ FreeXid(xid);
+ return -EBADF;
+ }
+
+ cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
+
+ rc = cifs_readpage_worker(file,page,&offset);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20))
+ unlock_page(page);
+#else
+ UnlockPage(page);
+#endif
+
+ FreeXid(xid);
+ return rc;
+}
+
+/* We do not want to update the file size from server for inodes
+ open for write - to avoid races with writepage extending
+ the file - in the future we could consider allowing
+ refreshing the inode only on increases in the file size
+ but this is tricky to do without racing with writebehind
+ page caching in the current Linux kernel design */
+
+int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
+{
+ struct list_head *tmp;
+ struct list_head *tmp1;
+ struct cifsFileInfo *open_file = NULL;
+ int rc = TRUE;
+
+ if(cifsInode == NULL)
+ return rc;
+
+ read_lock(&GlobalSMBSeslock);
+ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
+ if(open_file == NULL)
+ break;
+ if(open_file->closePend)
+ continue;
+ /* We check if file is open for writing,
+ BB we could supplement this with a check to see if file size
+ changes have been flushed to server - ie inode metadata dirty */
+ if((open_file->pfile) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ rc = FALSE;
+ break;
+ }
+ if(tmp->next == NULL) {
+ cFYI(1,("File instance %p removed",tmp));
+ break;
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ return rc;
+}
+
+
+void
+fill_in_inode(struct inode *tmp_inode,
+ FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
+{
+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+
+ pfindData->ExtFileAttributes =
+ le32_to_cpu(pfindData->ExtFileAttributes);
+ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
+ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
+ cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
+ cifsInfo->time = jiffies;
+
+ /* Linux can not store file creation time unfortunately so ignore it */
+ tmp_inode->i_atime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+ tmp_inode->i_mtime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
+ tmp_inode->i_ctime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+ /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
+ /* 2767 perms - indicate mandatory locking */
+ /* BB fill in uid and gid here? with help from winbind?
+ or retrieve from NTFS stream extended attribute */
+ if(atomic_read(&cifsInfo->inUse) == 0) {
+ tmp_inode->i_uid = cifs_sb->mnt_uid;
+ tmp_inode->i_gid = cifs_sb->mnt_gid;
+ /* set default mode. will override for dirs below */
+ tmp_inode->i_mode = cifs_sb->mnt_file_mode;
+ }
+
+ cFYI(0,
+ ("CIFS FFIRST: Attributes came in as 0x%x",
+ pfindData->ExtFileAttributes));
+ if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
+ *pobject_type = DT_LNK;
+ /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
+ tmp_inode->i_mode |= S_IFLNK;
+ } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
+ *pobject_type = DT_DIR;
+ /* override default perms since we do not lock dirs */
+ if(atomic_read(&cifsInfo->inUse) == 0) {
+ tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
+ }
+ tmp_inode->i_mode |= S_IFDIR;
+ } else {
+ *pobject_type = DT_REG;
+ tmp_inode->i_mode |= S_IFREG;
+ if(pfindData->ExtFileAttributes & ATTR_READONLY)
+ tmp_inode->i_mode &= ~(S_IWUGO);
+
+ }/* could add code here - to validate if device or weird share type? */
+
+ /* can not fill in nlink here as in qpathinfo version and Unx search */
+ if(atomic_read(&cifsInfo->inUse) == 0) {
+ atomic_set(&cifsInfo->inUse,1);
+ }
+ if(is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
+ tmp_inode->i_size = pfindData->EndOfFile;
+
+ /* 512 bytes (2**9) is the fake blocksize that must be used */
+ /* for this calculation, even though the reported blocksize is larger */
+ tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
+ }
+
+ if (pfindData->AllocationSize < pfindData->EndOfFile)
+ cFYI(1, ("Possible sparse file: allocation size less than end of file "));
+ cFYI(1,
+ ("File Size %ld and blocks %ld and blocksize %ld",
+ (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
+ tmp_inode->i_blksize));
+ if (S_ISREG(tmp_inode->i_mode)) {
+ cFYI(1, (" File inode "));
+ tmp_inode->i_op = &cifs_file_inode_ops;
+ tmp_inode->i_fop = &cifs_file_ops;
+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
+ } else if (S_ISDIR(tmp_inode->i_mode)) {
+ cFYI(1, (" Directory inode"));
+ tmp_inode->i_op = &cifs_dir_inode_ops;
+ tmp_inode->i_fop = &cifs_dir_ops;
+ } else if (S_ISLNK(tmp_inode->i_mode)) {
+ cFYI(1, (" Symbolic Link inode "));
+ tmp_inode->i_op = &cifs_symlink_inode_ops;
+ } else {
+ cFYI(1, (" Init special inode "));
+ init_special_inode(tmp_inode, tmp_inode->i_mode,
+ kdev_t_to_nr(tmp_inode->i_rdev));
+ }
+}
+
+void
+unix_fill_in_inode(struct inode *tmp_inode,
+ FILE_UNIX_INFO * pfindData, int *pobject_type)
+{
+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+ cifsInfo->time = jiffies;
+ atomic_inc(&cifsInfo->inUse);
+
+ tmp_inode->i_atime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+ tmp_inode->i_mtime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
+ tmp_inode->i_ctime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
+
+ tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
+ pfindData->Type = le32_to_cpu(pfindData->Type);
+ if (pfindData->Type == UNIX_FILE) {
+ *pobject_type = DT_REG;
+ tmp_inode->i_mode |= S_IFREG;
+ } else if (pfindData->Type == UNIX_SYMLINK) {
+ *pobject_type = DT_LNK;
+ tmp_inode->i_mode |= S_IFLNK;
+ } else if (pfindData->Type == UNIX_DIR) {
+ *pobject_type = DT_DIR;
+ tmp_inode->i_mode |= S_IFDIR;
+ } else if (pfindData->Type == UNIX_CHARDEV) {
+ *pobject_type = DT_CHR;
+ tmp_inode->i_mode |= S_IFCHR;
+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
+ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
+ } else if (pfindData->Type == UNIX_BLOCKDEV) {
+ *pobject_type = DT_BLK;
+ tmp_inode->i_mode |= S_IFBLK;
+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
+ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
+ } else if (pfindData->Type == UNIX_FIFO) {
+ *pobject_type = DT_FIFO;
+ tmp_inode->i_mode |= S_IFIFO;
+ } else if (pfindData->Type == UNIX_SOCKET) {
+ *pobject_type = DT_SOCK;
+ tmp_inode->i_mode |= S_IFSOCK;
+ }
+
+ tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
+ tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
+ tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
+
+ pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
+ if(is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
+ pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
+ tmp_inode->i_size = pfindData->EndOfFile;
+
+ /* 512 bytes (2**9) is the fake blocksize that must be used */
+ /* for this calculation, not the real blocksize */
+ tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
+ }
+
+ if (S_ISREG(tmp_inode->i_mode)) {
+ cFYI(1, ("File inode"));
+ tmp_inode->i_op = &cifs_file_inode_ops;
+ tmp_inode->i_fop = &cifs_file_ops;
+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
+ } else if (S_ISDIR(tmp_inode->i_mode)) {
+ cFYI(1, ("Directory inode"));
+ tmp_inode->i_op = &cifs_dir_inode_ops;
+ tmp_inode->i_fop = &cifs_dir_ops;
+ } else if (S_ISLNK(tmp_inode->i_mode)) {
+ cFYI(1, ("Symbolic Link inode"));
+ tmp_inode->i_op = &cifs_symlink_inode_ops;
+/* tmp_inode->i_fop = *//* do not need to set to anything */
+ } else {
+ cFYI(1, ("Special inode"));
+ init_special_inode(tmp_inode, tmp_inode->i_mode,
+ kdev_t_to_nr(tmp_inode->i_rdev));
+ }
+}
+
+static void
+construct_dentry(struct qstr *qstring, struct file *file,
+ struct inode **ptmp_inode, struct dentry **pnew_dentry)
+{
+ struct dentry *tmp_dentry;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct cifsInodeInfo *pCifsI;
+
+ cFYI(1, ("For %s ", qstring->name));
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+
+ qstring->hash = full_name_hash(qstring->name, qstring->len);
+ tmp_dentry = d_lookup(file->f_dentry, qstring);
+ if (tmp_dentry) {
+ cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
+ *ptmp_inode = tmp_dentry->d_inode;
+ /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
+ if(*ptmp_inode == NULL) {
+ *ptmp_inode = new_inode(file->f_dentry->d_sb);
+ if(*ptmp_inode == NULL)
+ return;
+ d_instantiate(tmp_dentry, *ptmp_inode);
+ insert_inode_hash(*ptmp_inode);
+ pCifsI = CIFS_I(*ptmp_inode);
+ INIT_LIST_HEAD(&pCifsI->openFileList);
+ /* can not enable caching for this inode
+ until a file instance is open and we
+ can check the oplock flag on the open
+ response */
+ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
+ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
+#endif
+ pCifsI->clientCanCacheRead = FALSE;
+ pCifsI->clientCanCacheAll = FALSE;
+ pCifsI->time = 0;
+ /* do not need to set cifs Attrs since
+ they are about to be overwritten
+ in fill_in_inode */
+ atomic_set(&pCifsI->inUse, 0);
+ }
+ } else {
+ tmp_dentry = d_alloc(file->f_dentry, qstring);
+ if(tmp_dentry == NULL) {
+ cERROR(1,("Failed allocating dentry"));
+ return;
+ }
+
+ if(ptmp_inode) {
+ *ptmp_inode = new_inode(file->f_dentry->d_sb);
+ if(*ptmp_inode == NULL)
+ return;
+ pCifsI = CIFS_I(*ptmp_inode);
+ insert_inode_hash(*ptmp_inode);
+ INIT_LIST_HEAD(&pCifsI->openFileList);
+ /* can not enable caching for this inode
+ until a file instance is open and we
+ can check the oplock flag on the open
+ response */
+ (*ptmp_inode)->i_blksize = CIFS_MAX_MSGSIZE;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
+ (*ptmp_inode)->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
+#endif
+ pCifsI->clientCanCacheRead = FALSE;
+ pCifsI->clientCanCacheAll = FALSE;
+ pCifsI->time = 0;
+ /* do not need to set cifs Attrs since
+ they are about to be overwritten
+ in fill_in_inode */
+ atomic_set(&pCifsI->inUse, 0);
+ }
+ tmp_dentry->d_op = &cifs_dentry_ops;
+ d_instantiate(tmp_dentry, *ptmp_inode);
+ d_rehash(tmp_dentry);
+ }
+
+ tmp_dentry->d_time = jiffies;
+ *pnew_dentry = tmp_dentry;
+}
+
+static void reset_resume_key(struct file * dir_file,
+ unsigned char * filename,
+ unsigned int len,int Unicode,struct nls_table * nls_tab) {
+ struct cifsFileInfo *cifsFile;
+
+ cifsFile = (struct cifsFileInfo *)dir_file->private_data;
+ if(cifsFile == NULL)
+ return;
+ if(cifsFile->search_resume_name) {
+ kfree(cifsFile->search_resume_name);
+ }
+
+ if(Unicode)
+ len *= 2;
+ cifsFile->resume_name_length = len;
+
+ cifsFile->search_resume_name =
+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
+
+ if(cifsFile->search_resume_name == NULL) {
+ cERROR(1,("failed new resume key allocate, length %d",
+ cifsFile->resume_name_length));
+ return;
+ }
+ if(Unicode)
+ cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
+ filename, len, nls_tab);
+ else
+ memcpy(cifsFile->search_resume_name, filename,
+ cifsFile->resume_name_length);
+ cFYI(1,("Reset resume key to: %s with len %d",filename,len));
+ return;
+}
+
+
+
+static int
+cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
+ struct file *file, filldir_t filldir, void *direntry)
+{
+ struct inode *tmp_inode;
+ struct dentry *tmp_dentry;
+ int object_type,rc;
+
+ pqstring->name = pfindData->FileName;
+ pqstring->len = pfindData->FileNameLength;
+
+ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
+ if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
+ return -ENOMEM;
+ }
+ fill_in_inode(tmp_inode, pfindData, &object_type);
+ rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
+ tmp_inode->i_ino, object_type);
+ if(rc) {
+ /* due to readdir error we need to recalculate resume
+ key so next readdir will restart on right entry */
+ cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
+ }
+ dput(tmp_dentry);
+ return rc;
+}
+
+static int
+cifs_filldir_unix(struct qstr *pqstring,
+ FILE_UNIX_INFO * pUnixFindData, struct file *file,
+ filldir_t filldir, void *direntry)
+{
+ struct inode *tmp_inode;
+ struct dentry *tmp_dentry;
+ int object_type, rc;
+
+ pqstring->name = pUnixFindData->FileName;
+ pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
+
+ construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
+ if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
+ return -ENOMEM;
+ }
+
+ unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
+ rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
+ file->f_pos, tmp_inode->i_ino, object_type);
+ if(rc) {
+ /* due to readdir error we need to recalculate resume
+ key so next readdir will restart on right entry */
+ cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
+ }
+ dput(tmp_dentry);
+ return rc;
+}
+
+int
+cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
+{
+ int rc = 0;
+ int xid;
+ int Unicode = FALSE;
+ int UnixSearch = FALSE;
+ unsigned int bufsize, i;
+ __u16 searchHandle;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct cifsFileInfo *cifsFile = NULL;
+ char *full_path = NULL;
+ char *data;
+ struct qstr qstring;
+ T2_FFIRST_RSP_PARMS findParms;
+ T2_FNEXT_RSP_PARMS findNextParms;
+ FILE_DIRECTORY_INFO *pfindData;
+ FILE_DIRECTORY_INFO *lastFindData;
+ FILE_UNIX_INFO *pfindDataUnix;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+ bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
+ if(bufsize > CIFS_MAX_MSGSIZE) {
+ FreeXid(xid);
+ return -EIO;
+ }
+ data = kmalloc(bufsize, GFP_KERNEL);
+ pfindData = (FILE_DIRECTORY_INFO *) data;
+
+ if(file->f_dentry == NULL) {
+ FreeXid(xid);
+ return -EIO;
+ }
+ down(&file->f_dentry->d_sb->s_vfs_rename_sem);
+ full_path = build_wildcard_path_from_dentry(file->f_dentry);
+ up(&file->f_dentry->d_sb->s_vfs_rename_sem);
+
+
+ cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
+
+ switch ((int) file->f_pos) {
+ case 0:
+ if (filldir(direntry, ".", 1, file->f_pos,
+ file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
+ cERROR(1, ("Filldir for current dir failed "));
+ break;
+ }
+ file->f_pos++;
+ /* fallthrough */
+ case 1:
+ if (filldir(direntry, "..", 2, file->f_pos,
+ file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+ cERROR(1, ("Filldir for parent dir failed "));
+ break;
+ }
+ file->f_pos++;
+ /* fallthrough */
+ case 2:
+ if (file->private_data != NULL) {
+ cifsFile =
+ (struct cifsFileInfo *) file->private_data;
+ if (cifsFile->endOfSearch) {
+ if(cifsFile->emptyDir) {
+ cFYI(1, ("End of search, empty dir"));
+ rc = 0;
+ break;
+ }
+ } else {
+ cifsFile->invalidHandle = TRUE;
+ CIFSFindClose(xid, pTcon, cifsFile->netfid);
+ }
+ if(cifsFile->search_resume_name) {
+ kfree(cifsFile->search_resume_name);
+ cifsFile->search_resume_name = NULL;
+ }
+ }
+ rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
+ &findParms, cifs_sb->local_nls,
+ &Unicode, &UnixSearch);
+ cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
+ findParms.EndofSearch));
+
+ if (rc == 0) {
+ searchHandle = findParms.SearchHandle;
+ if(file->private_data == NULL)
+ file->private_data =
+ kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
+ if (file->private_data) {
+ memset(file->private_data, 0,
+ sizeof (struct cifsFileInfo));
+ cifsFile =
+ (struct cifsFileInfo *) file->private_data;
+ cifsFile->netfid = searchHandle;
+ cifsFile->invalidHandle = FALSE;
+ init_MUTEX(&cifsFile->fh_sem);
+ } else {
+ rc = -ENOMEM;
+ break;
+ }
+
+ renew_parental_timestamps(file->f_dentry);
+ lastFindData =
+ (FILE_DIRECTORY_INFO *) ((char *) pfindData +
+ findParms.LastNameOffset);
+ if((char *)lastFindData > (char *)pfindData + bufsize) {
+ cFYI(1,("last search entry past end of packet"));
+ rc = -EIO;
+ break;
+ }
+ /* Offset of resume key same for levels 257 and 514 */
+ cifsFile->resume_key = lastFindData->FileIndex;
+ if(UnixSearch == FALSE) {
+ cifsFile->resume_name_length =
+ le32_to_cpu(lastFindData->FileNameLength);
+ if(cifsFile->resume_name_length > bufsize - 64) {
+ cFYI(1,("Illegal resume file name length %d",
+ cifsFile->resume_name_length));
+ rc = -ENOMEM;
+ break;
+ }
+ cifsFile->search_resume_name =
+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
+ cFYI(1,("Last file: %s with name %d bytes long",
+ lastFindData->FileName,
+ cifsFile->resume_name_length));
+ memcpy(cifsFile->search_resume_name,
+ lastFindData->FileName,
+ cifsFile->resume_name_length);
+ } else {
+ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
+ if (Unicode == TRUE) {
+ for(i=0;(pfindDataUnix->FileName[i]
+ | pfindDataUnix->FileName[i+1]);
+ i+=2) {
+ if(i > bufsize-64)
+ break;
+ }
+ cifsFile->resume_name_length = i + 2;
+ } else {
+ cifsFile->resume_name_length =
+ strnlen(pfindDataUnix->FileName,
+ bufsize-63);
+ }
+ if(cifsFile->resume_name_length > bufsize - 64) {
+ cFYI(1,("Illegal resume file name length %d",
+ cifsFile->resume_name_length));
+ rc = -ENOMEM;
+ break;
+ }
+ cifsFile->search_resume_name =
+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
+ cFYI(1,("Last file: %s with name %d bytes long",
+ pfindDataUnix->FileName,
+ cifsFile->resume_name_length));
+ memcpy(cifsFile->search_resume_name,
+ pfindDataUnix->FileName,
+ cifsFile->resume_name_length);
+ }
+ for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
+ if (UnixSearch == FALSE) {
+ pfindData->FileNameLength =
+ le32_to_cpu(pfindData->FileNameLength);
+ if (Unicode == TRUE)
+ pfindData->FileNameLength =
+ cifs_strfromUCS_le
+ (pfindData->FileName,
+ (wchar_t *)
+ pfindData->FileName,
+ (pfindData->
+ FileNameLength) / 2,
+ cifs_sb->local_nls);
+ qstring.len = pfindData->FileNameLength;
+ if (((qstring.len != 1)
+ || (pfindData->FileName[0] != '.'))
+ && ((qstring.len != 2)
+ || (pfindData->
+ FileName[0] != '.')
+ || (pfindData->
+ FileName[1] != '.'))) {
+ if(cifs_filldir(&qstring,
+ pfindData,
+ file, filldir,
+ direntry)) {
+ /* do not end search if
+ kernel not ready to take
+ remaining entries yet */
+ reset_resume_key(file, pfindData->FileName,qstring.len,
+ Unicode, cifs_sb->local_nls);
+ findParms.EndofSearch = 0;
+ break;
+ }
+ file->f_pos++;
+ }
+ } else { /* UnixSearch */
+ pfindDataUnix =
+ (FILE_UNIX_INFO *) pfindData;
+ if (Unicode == TRUE)
+ qstring.len =
+ cifs_strfromUCS_le
+ (pfindDataUnix->FileName,
+ (wchar_t *)
+ pfindDataUnix->FileName,
+ MAX_PATHCONF,
+ cifs_sb->local_nls);
+ else
+ qstring.len =
+ strnlen(pfindDataUnix->
+ FileName,
+ MAX_PATHCONF);
+ if (((qstring.len != 1)
+ || (pfindDataUnix->
+ FileName[0] != '.'))
+ && ((qstring.len != 2)
+ || (pfindDataUnix->
+ FileName[0] != '.')
+ || (pfindDataUnix->
+ FileName[1] != '.'))) {
+ if(cifs_filldir_unix(&qstring,
+ pfindDataUnix,
+ file,
+ filldir,
+ direntry)) {
+ /* do not end search if
+ kernel not ready to take
+ remaining entries yet */
+ findParms.EndofSearch = 0;
+ reset_resume_key(file, pfindDataUnix->FileName,
+ qstring.len,Unicode,cifs_sb->local_nls);
+ break;
+ }
+ file->f_pos++;
+ }
+ }
+ /* works also for Unix ff struct since first field of both */
+ pfindData =
+ (FILE_DIRECTORY_INFO *) ((char *) pfindData
+ + le32_to_cpu(pfindData->NextEntryOffset));
+ /* BB also should check to make sure that pointer is not beyond the end of the SMB */
+ /* if(pfindData > lastFindData) rc = -EIO; break; */
+ } /* end for loop */
+ if ((findParms.EndofSearch != 0) && cifsFile) {
+ cifsFile->endOfSearch = TRUE;
+ if(findParms.SearchCount == 2)
+ cifsFile->emptyDir = TRUE;
+ }
+ } else {
+ if (cifsFile)
+ cifsFile->endOfSearch = TRUE;
+ /* unless parent directory gone do not return error */
+ rc = 0;
+ }
+ break;
+ default:
+ if (file->private_data == NULL) {
+ rc = -EBADF;
+ cFYI(1,
+ ("Readdir on closed srch, pos = %lld",
+ file->f_pos));
+ } else {
+ cifsFile = (struct cifsFileInfo *) file->private_data;
+ if (cifsFile->endOfSearch) {
+ rc = 0;
+ cFYI(1, ("End of search "));
+ break;
+ }
+ searchHandle = cifsFile->netfid;
+ rc = CIFSFindNext(xid, pTcon, pfindData,
+ &findNextParms, searchHandle,
+ cifsFile->search_resume_name,
+ cifsFile->resume_name_length,
+ cifsFile->resume_key,
+ &Unicode, &UnixSearch);
+ cFYI(1,("Count: %d End: %d ",
+ findNextParms.SearchCount,
+ findNextParms.EndofSearch));
+ if ((rc == 0) && (findNextParms.SearchCount != 0)) {
+ /* BB save off resume key, key name and name length */
+ lastFindData =
+ (FILE_DIRECTORY_INFO *) ((char *) pfindData
+ + findNextParms.LastNameOffset);
+ if((char *)lastFindData > (char *)pfindData + bufsize) {
+ cFYI(1,("last search entry past end of packet"));
+ rc = -EIO;
+ break;
+ }
+ /* Offset of resume key same for levels 257 and 514 */
+ cifsFile->resume_key = lastFindData->FileIndex;
+
+ if(UnixSearch == FALSE) {
+ cifsFile->resume_name_length =
+ le32_to_cpu(lastFindData->FileNameLength);
+ if(cifsFile->resume_name_length > bufsize - 64) {
+ cFYI(1,("Illegal resume file name length %d",
+ cifsFile->resume_name_length));
+ rc = -ENOMEM;
+ break;
+ }
+ /* Free the memory allocated by previous findfirst
+ or findnext call - we can not reuse the memory since
+ the resume name may not be same string length */
+ if(cifsFile->search_resume_name)
+ kfree(cifsFile->search_resume_name);
+ cifsFile->search_resume_name =
+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
+ cFYI(1,("Last file: %s with name %d bytes long",
+ lastFindData->FileName,
+ cifsFile->resume_name_length));
+ memcpy(cifsFile->search_resume_name,
+ lastFindData->FileName,
+ cifsFile->resume_name_length);
+ } else {
+ pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
+ if (Unicode == TRUE) {
+ for(i=0;(pfindDataUnix->FileName[i]
+ | pfindDataUnix->FileName[i+1]);
+ i+=2) {
+ if(i > bufsize-64)
+ break;
+ }
+ cifsFile->resume_name_length = i + 2;
+ } else {
+ cifsFile->resume_name_length =
+ strnlen(pfindDataUnix->
+ FileName,
+ MAX_PATHCONF);
+ }
+ if(cifsFile->resume_name_length > bufsize - 64) {
+ cFYI(1,("Illegal resume file name length %d",
+ cifsFile->resume_name_length));
+ rc = -ENOMEM;
+ break;
+ }
+ /* Free the memory allocated by previous findfirst
+ or findnext call - we can not reuse the memory since
+ the resume name may not be same string length */
+ if(cifsFile->search_resume_name)
+ kfree(cifsFile->search_resume_name);
+ cifsFile->search_resume_name =
+ kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
+ cFYI(1,("fnext last file: %s with name %d bytes long",
+ pfindDataUnix->FileName,
+ cifsFile->resume_name_length));
+ memcpy(cifsFile->search_resume_name,
+ pfindDataUnix->FileName,
+ cifsFile->resume_name_length);
+ }
+
+ for (i = 0; i < findNextParms.SearchCount; i++) {
+ pfindData->FileNameLength =
+ le32_to_cpu(pfindData->
+ FileNameLength);
+ if (UnixSearch == FALSE) {
+ if (Unicode == TRUE)
+ pfindData->FileNameLength =
+ cifs_strfromUCS_le
+ (pfindData->FileName,
+ (wchar_t *)
+ pfindData->FileName,
+ (pfindData->FileNameLength)/ 2,
+ cifs_sb->local_nls);
+ qstring.len =
+ pfindData->FileNameLength;
+ if (((qstring.len != 1)
+ || (pfindData->FileName[0] != '.'))
+ && ((qstring.len != 2)
+ || (pfindData->FileName[0] != '.')
+ || (pfindData->FileName[1] !=
+ '.'))) {
+ if(cifs_filldir
+ (&qstring,
+ pfindData,
+ file, filldir,
+ direntry)) {
+ /* do not end search if
+ kernel not ready to take
+ remaining entries yet */
+ findNextParms.EndofSearch = 0;
+ reset_resume_key(file, pfindData->FileName,qstring.len,
+ Unicode,cifs_sb->local_nls);
+ break;
+ }
+ file->f_pos++;
+ }
+ } else { /* UnixSearch */
+ pfindDataUnix =
+ (FILE_UNIX_INFO *)
+ pfindData;
+ if (Unicode == TRUE)
+ qstring.len =
+ cifs_strfromUCS_le
+ (pfindDataUnix->FileName,
+ (wchar_t *)
+ pfindDataUnix->FileName,
+ MAX_PATHCONF,
+ cifs_sb->local_nls);
+ else
+ qstring.len =
+ strnlen
+ (pfindDataUnix->
+ FileName,
+ MAX_PATHCONF);
+ if (((qstring.len != 1)
+ || (pfindDataUnix->
+ FileName[0] != '.'))
+ && ((qstring.len != 2)
+ || (pfindDataUnix->
+ FileName[0] != '.')
+ || (pfindDataUnix->
+ FileName[1] !=
+ '.'))) {
+ if(cifs_filldir_unix
+ (&qstring,
+ pfindDataUnix,
+ file, filldir,
+ direntry)) {
+ /* do not end search if
+ kernel not ready to take
+ remaining entries yet */
+ findNextParms.EndofSearch = 0;
+ reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
+ Unicode,cifs_sb->local_nls);
+ break;
+ }
+ file->f_pos++;
+ }
+ }
+ pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* works also for Unix find struct since this is the first field of both */
+ /* BB also should check to make sure that pointer is not beyond the end of the SMB */
+ } /* end for loop */
+ if (findNextParms.EndofSearch != 0) {
+ cifsFile->endOfSearch = TRUE;
+ }
+ } else {
+ cifsFile->endOfSearch = TRUE;
+ rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */
+ }
+ }
+ } /* end switch */
+ if (data)
+ kfree(data);
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+
+ return rc;
+}
+int cifs_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+{
+ int rc = 0;
+ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
+ if (!Page_Uptodate(page)) {
+ /* if (to - from != PAGE_CACHE_SIZE) {
+ void *kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr, 0, from);
+ memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+ } */
+ /* If we are writing a full page it will be up to date,
+ no need to read from the server */
+ if((to==PAGE_CACHE_SIZE) && (from == 0))
+ SetPageUptodate(page);
+
+ /* might as well read a page, it is fast enough */
+ if((file->f_flags & O_ACCMODE) != O_WRONLY) {
+ rc = cifs_readpage_worker(file,page,&offset);
+ } else {
+ /* should we try using another
+ file handle if there is one - how would we lock it
+ to prevent close of that handle racing with this read? */
+ /* In any case this will be written out by commit_write */
+ }
+ }
+
+ /* BB should we pass any errors back? e.g. if we do not have read access to the file */
+ return 0;
+}
+
+
+struct address_space_operations cifs_addr_ops = {
+ .readpage = cifs_readpage,
+/* .readpages = cifs_readpages, */
+ .writepage = cifs_writepage,
+ .prepare_write = cifs_prepare_write,
+ .commit_write = cifs_commit_write,
+ .sync_page = cifs_sync_page,
+ /*.direct_IO = */
+};
diff --git a/release/src/linux/linux/fs/cifs/inode.c b/release/src/linux/linux/fs/cifs/inode.c
new file mode 100644
index 00000000..dce55552
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/inode.c
@@ -0,0 +1,1079 @@
+/*
+ * fs/cifs/inode.c
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/pagemap.h>
+#include <linux/version.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+extern int is_size_safe_to_change(struct cifsInodeInfo *);
+
+struct inode * get_cifs_inode(struct super_block * sb)
+{
+ struct inode * newinode;
+ newinode = new_inode(sb);
+ cFYI(1,("got new inode %p",newinode));
+ if(newinode) {
+ struct cifsInodeInfo * cifsInfo = CIFS_I(newinode);
+ cifsInfo->clientCanCacheRead = FALSE;
+ cifsInfo->clientCanCacheAll = FALSE;
+ INIT_LIST_HEAD(&cifsInfo->openFileList);
+ cifsInfo->cifsAttrs = 0x20; /* default */
+ newinode->i_blksize = CIFS_MAX_MSGSIZE;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,15))
+ newinode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
+#endif
+ atomic_set(&cifsInfo->inUse, 0);
+ cifsInfo->time = 0;
+ insert_inode_hash(newinode);
+ }
+ return newinode;
+
+}
+
+int
+cifs_get_inode_info_unix(struct inode **pinode,
+ const unsigned char *search_path,
+ struct super_block *sb,int xid)
+{
+ int rc = 0;
+ FILE_UNIX_BASIC_INFO findData;
+ struct cifsTconInfo *pTcon;
+ struct inode *inode;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ char *tmp_path;
+
+ pTcon = cifs_sb->tcon;
+ cFYI(1, (" Getting info on %s ", search_path));
+ /* we could have done a find first instead but this returns more info */
+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
+ cifs_sb->local_nls);
+ /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
+ if (rc) {
+ if (rc == -EREMOTE) {
+ tmp_path =
+ kmalloc(strnlen
+ (pTcon->treeName,
+ MAX_TREE_SIZE + 1) +
+ strnlen(search_path, MAX_PATHCONF) + 1,
+ GFP_KERNEL);
+ if (tmp_path == NULL) {
+ return -ENOMEM;
+ }
+ /* have to skip first of the double backslash of UNC name */
+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+ strncat(tmp_path, search_path, MAX_PATHCONF);
+ rc = connect_to_dfs_path(xid, pTcon->ses,
+ /* treename + */ tmp_path,
+ cifs_sb->local_nls);
+ kfree(tmp_path);
+
+ /* BB fix up inode etc. */
+ } else if (rc) {
+ return rc;
+ }
+
+ } else {
+ struct cifsInodeInfo *cifsInfo;
+
+ /* get new inode */
+ if (*pinode == NULL) {
+ *pinode = get_cifs_inode(sb);
+ }
+ if(*pinode == NULL) {
+ return -ENOMEM;
+ }
+
+ inode = *pinode;
+ cifsInfo = CIFS_I(inode);
+
+ cFYI(1, (" Old time %ld ", cifsInfo->time));
+ cifsInfo->time = jiffies;
+ cFYI(1, (" New time %ld ", cifsInfo->time));
+ atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
+
+ inode->i_atime =
+ cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
+ inode->i_mtime =
+ cifs_NTtimeToUnix(le64_to_cpu
+ (findData.LastModificationTime));
+ inode->i_ctime =
+ cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
+ inode->i_mode = le64_to_cpu(findData.Permissions);
+ findData.Type = le32_to_cpu(findData.Type);
+ if (findData.Type == UNIX_FILE) {
+ inode->i_mode |= S_IFREG;
+ } else if (findData.Type == UNIX_SYMLINK) {
+ inode->i_mode |= S_IFLNK;
+ } else if (findData.Type == UNIX_DIR) {
+ inode->i_mode |= S_IFDIR;
+ } else if (findData.Type == UNIX_CHARDEV) {
+ inode->i_mode |= S_IFCHR;
+ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
+ le64_to_cpu(findData.DevMinor) & MINORMASK);
+ } else if (findData.Type == UNIX_BLOCKDEV) {
+ inode->i_mode |= S_IFBLK;
+ inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
+ le64_to_cpu(findData.DevMinor) & MINORMASK);
+ } else if (findData.Type == UNIX_FIFO) {
+ inode->i_mode |= S_IFIFO;
+ } else if (findData.Type == UNIX_SOCKET) {
+ inode->i_mode |= S_IFSOCK;
+ }
+ inode->i_uid = le64_to_cpu(findData.Uid);
+ inode->i_gid = le64_to_cpu(findData.Gid);
+ inode->i_nlink = le64_to_cpu(findData.Nlinks);
+ findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
+ findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
+
+ if(is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
+ inode->i_size = findData.EndOfFile;
+/* blksize needs to be multiple of two. So safer to default to blksize
+ and blkbits set in superblock so 2**blkbits and blksize will match */
+/* inode->i_blksize =
+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
+
+ /* This seems incredibly stupid but it turns out that
+ i_blocks is not related to (i_size / i_blksize), instead a
+ size of 512 is required to be used for calculating num blocks */
+
+
+/* inode->i_blocks =
+ (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
+
+ /* 512 bytes (2**9) is the fake blocksize that must be used */
+ /* for this calculation */
+ inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
+ }
+
+ if (findData.NumOfBytes < findData.EndOfFile)
+ cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
+ cFYI(1,
+ ("Size %ld and blocks %ld ",
+ (unsigned long) inode->i_size, inode->i_blocks));
+ if (S_ISREG(inode->i_mode)) {
+ cFYI(1, (" File inode "));
+ inode->i_op = &cifs_file_inode_ops;
+ inode->i_fop = &cifs_file_ops;
+ inode->i_data.a_ops = &cifs_addr_ops;
+ } else if (S_ISDIR(inode->i_mode)) {
+ cFYI(1, (" Directory inode"));
+ inode->i_op = &cifs_dir_inode_ops;
+ inode->i_fop = &cifs_dir_ops;
+ } else if (S_ISLNK(inode->i_mode)) {
+ cFYI(1, (" Symbolic Link inode "));
+ inode->i_op = &cifs_symlink_inode_ops;
+/* tmp_inode->i_fop = *//* do not need to set to anything */
+ } else {
+ cFYI(1, (" Init special inode "));
+ init_special_inode(inode, inode->i_mode,
+ kdev_t_to_nr(inode->i_rdev));
+ }
+ }
+ return rc;
+}
+
+int
+cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
+ FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
+{
+ int rc = 0;
+ struct cifsTconInfo *pTcon;
+ struct inode *inode;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ char *tmp_path;
+ char *buf = NULL;
+
+ pTcon = cifs_sb->tcon;
+ cFYI(1,("Getting info on %s ", search_path));
+
+ if((pfindData == NULL) && (*pinode != NULL)) {
+ if(CIFS_I(*pinode)->clientCanCacheRead) {
+ cFYI(1,("No need to revalidate inode sizes on cached file "));
+ return rc;
+ }
+ }
+
+ /* if file info not passed in then get it from server */
+ if(pfindData == NULL) {
+ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+ pfindData = (FILE_ALL_INFO *)buf;
+ /* could do find first instead but this returns more info */
+ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
+ cifs_sb->local_nls);
+ }
+ /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
+ if (rc) {
+ if (rc == -EREMOTE) {
+ tmp_path =
+ kmalloc(strnlen
+ (pTcon->treeName,
+ MAX_TREE_SIZE + 1) +
+ strnlen(search_path, MAX_PATHCONF) + 1,
+ GFP_KERNEL);
+ if (tmp_path == NULL) {
+ if(buf)
+ kfree(buf);
+ return -ENOMEM;
+ }
+
+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+ strncat(tmp_path, search_path, MAX_PATHCONF);
+ rc = connect_to_dfs_path(xid, pTcon->ses,
+ /* treename + */ tmp_path,
+ cifs_sb->local_nls);
+ kfree(tmp_path);
+ /* BB fix up inode etc. */
+ } else if (rc) {
+ if(buf)
+ kfree(buf);
+ return rc;
+ }
+ } else {
+ struct cifsInodeInfo *cifsInfo;
+
+ /* get new inode */
+ if (*pinode == NULL) {
+ *pinode = get_cifs_inode(sb);
+ }
+ if(*pinode == NULL)
+ return -ENOMEM;
+ inode = *pinode;
+ cifsInfo = CIFS_I(inode);
+ pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
+ cifsInfo->cifsAttrs = pfindData->Attributes;
+ cFYI(1, (" Old time %ld ", cifsInfo->time));
+ cifsInfo->time = jiffies;
+ cFYI(1, (" New time %ld ", cifsInfo->time));
+
+/* blksize needs to be multiple of two. So safer to default to blksize
+ and blkbits set in superblock so 2**blkbits and blksize will match */
+/* inode->i_blksize =
+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
+
+ /* Linux can not store file creation time unfortunately so we ignore it */
+ inode->i_atime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+ inode->i_mtime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
+ inode->i_ctime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+ cFYI(0,
+ (" Attributes came in as 0x%x ", pfindData->Attributes));
+
+ /* set default mode. will override for dirs below */
+ if(atomic_read(&cifsInfo->inUse) == 0)
+ /* new inode, can safely set these fields */
+ inode->i_mode = cifs_sb->mnt_file_mode;
+
+ if (pfindData->Attributes & ATTR_REPARSE) {
+ /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
+ inode->i_mode |= S_IFLNK;
+ } else if (pfindData->Attributes & ATTR_DIRECTORY) {
+ /* override default perms since we do not do byte range locking on dirs */
+ inode->i_mode = cifs_sb->mnt_dir_mode;
+ inode->i_mode |= S_IFDIR;
+ } else {
+ inode->i_mode |= S_IFREG;
+ /* treat the dos attribute of read-only as read-only mode e.g. 555 */
+ if(cifsInfo->cifsAttrs & ATTR_READONLY)
+ inode->i_mode &= ~(S_IWUGO);
+ /* BB add code here - validate if device or weird share or device type? */
+ }
+ if(is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
+ inode->i_size = le64_to_cpu(pfindData->EndOfFile);
+
+ /* 512 bytes (2**9) is the fake blocksize that must be used */
+ /* for this calculation */
+ inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
+ >> 9;
+ }
+ pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
+
+ cFYI(1,
+ (" Size %ld and blocks %ld ",
+ (unsigned long) inode->i_size, inode->i_blocks));
+ inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
+
+ /* BB fill in uid and gid here? with help from winbind?
+ or retrieve from NTFS stream extended attribute */
+ if(atomic_read(&cifsInfo->inUse) == 0) {
+ inode->i_uid = cifs_sb->mnt_uid;
+ inode->i_gid = cifs_sb->mnt_gid;
+ /* set so we do not keep refreshing these fields with
+ bad data after user has changed them in memory */
+ atomic_set(&cifsInfo->inUse,1);
+ }
+
+ if (S_ISREG(inode->i_mode)) {
+ cFYI(1, (" File inode "));
+ inode->i_op = &cifs_file_inode_ops;
+ inode->i_fop = &cifs_file_ops;
+ inode->i_data.a_ops = &cifs_addr_ops;
+ } else if (S_ISDIR(inode->i_mode)) {
+ cFYI(1, (" Directory inode "));
+ inode->i_op = &cifs_dir_inode_ops;
+ inode->i_fop = &cifs_dir_ops;
+ } else if (S_ISLNK(inode->i_mode)) {
+ cFYI(1, (" Symbolic Link inode "));
+ inode->i_op = &cifs_symlink_inode_ops;
+ } else {
+ init_special_inode(inode, inode->i_mode,
+ kdev_t_to_nr(inode->i_rdev));
+ }
+ }
+ if(buf)
+ kfree(buf);
+ return rc;
+}
+
+void
+cifs_read_inode(struct inode *inode)
+{ /* gets root inode */
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsInodeInfo *cifs_inode;
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ xid = GetXid();
+
+ cifs_inode = CIFS_I(inode);
+ cifs_inode->cifsAttrs = ATTR_DIRECTORY;
+ atomic_set(&cifs_inode->inUse, 0);
+ cifs_inode->time = 0;
+ inode->i_blksize = CIFS_MAX_MSGSIZE;
+ inode->i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
+
+ INIT_LIST_HEAD(&cifs_inode->openFileList);
+
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
+ else
+ cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
+ /* can not call macro FreeXid here since in a void func */
+ _FreeXid(xid);
+}
+
+int
+cifs_unlink(struct inode *inode, struct dentry *direntry)
+{
+ int rc = 0;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ struct cifsInodeInfo *cifsInode;
+ FILE_BASIC_INFO * pinfo_buf;
+
+ cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+/* Unlink can be called from rename so we can not grab
+ the sem here since we deadlock otherwise */
+/* down(&direntry->d_sb->s_vfs_rename_sem);*/
+ full_path = build_path_from_dentry(direntry);
+/* up(&direntry->d_sb->s_vfs_rename_sem);*/
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
+
+ if (!rc) {
+ direntry->d_inode->i_nlink--;
+ } else if (rc == -ENOENT) {
+ d_drop(direntry);
+ } else if (rc == -ETXTBSY) {
+ int oplock = FALSE;
+ __u16 netfid;
+
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
+ &netfid, &oplock, NULL, cifs_sb->local_nls);
+ if(rc==0) {
+ CIFSSMBRenameOpenFile(xid,pTcon,netfid,
+ NULL, cifs_sb->local_nls);
+ CIFSSMBClose(xid, pTcon, netfid);
+ direntry->d_inode->i_nlink--;
+ }
+ } else if (rc == -EACCES) {
+ /* try only if r/o attribute set in local lookup data? */
+ pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
+ if(pinfo_buf) {
+ memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
+ /* ATTRS set to normal clears r/o bit */
+ pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
+ cifs_sb->local_nls);
+ kfree(pinfo_buf);
+ }
+ if(rc==0) {
+ rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
+ if (!rc) {
+ direntry->d_inode->i_nlink--;
+ } else if (rc == -ETXTBSY) {
+ int oplock = FALSE;
+ __u16 netfid;
+
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
+ &netfid, &oplock, NULL, cifs_sb->local_nls);
+ if(rc==0) {
+ CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
+ CIFSSMBClose(xid, pTcon, netfid);
+ direntry->d_inode->i_nlink--;
+ }
+ /* BB if rc = -ETXTBUSY goto the rename logic BB */
+ }
+ }
+ }
+ cifsInode = CIFS_I(direntry->d_inode);
+ cifsInode->time = 0; /* will force revalidate to get info when needed */
+ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
+ CURRENT_TIME;
+ cifsInode = CIFS_I(inode);
+ cifsInode->time = 0; /* force revalidate of dir as well */
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
+{
+ int rc = 0;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ struct inode *newinode = NULL;
+
+ cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&inode->i_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&inode->i_sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ /* BB add setting the equivalent of mode via CreateX w/ACLs */
+ rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
+ if (rc) {
+ cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
+ d_drop(direntry);
+ } else {
+ inode->i_nlink++;
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb,xid);
+ else
+ rc = cifs_get_inode_info(&newinode, full_path,NULL,
+ inode->i_sb,xid);
+
+ direntry->d_op = &cifs_dentry_ops;
+ d_instantiate(direntry, newinode);
+ if(direntry->d_inode)
+ direntry->d_inode->i_nlink = 2;
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+ (__u64)-1,
+ (__u64)-1,
+ 0 /* dev_t */,
+ cifs_sb->local_nls);
+ else { /* BB to be implemented via Windows secrty descriptors*/
+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
+ }
+ }
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+
+ return rc;
+}
+
+int
+cifs_rmdir(struct inode *inode, struct dentry *direntry)
+{
+ int rc = 0;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ struct cifsInodeInfo *cifsInode;
+
+ cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&inode->i_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&inode->i_sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+
+ rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
+
+ if (!rc) {
+ inode->i_nlink--;
+ direntry->d_inode->i_size = 0;
+ direntry->d_inode->i_nlink = 0;
+ }
+
+ cifsInode = CIFS_I(direntry->d_inode);
+ cifsInode->time = 0; /* force revalidate to go get info when needed */
+ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
+ CURRENT_TIME;
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
+ struct inode *target_inode, struct dentry *target_direntry)
+{
+ char *fromName;
+ char *toName;
+ struct cifs_sb_info *cifs_sb_source;
+ struct cifs_sb_info *cifs_sb_target;
+ struct cifsTconInfo *pTcon;
+ int xid;
+ int rc = 0;
+
+ xid = GetXid();
+
+ cifs_sb_target = CIFS_SB(target_inode->i_sb);
+ cifs_sb_source = CIFS_SB(source_inode->i_sb);
+ pTcon = cifs_sb_source->tcon;
+
+ if (pTcon != cifs_sb_target->tcon) {
+ FreeXid(xid);
+ return -EXDEV; /* BB actually could be allowed if same server, but
+ different share. Might eventually add support for this */
+ }
+
+ /* we already have the rename sem so we do not need
+ to grab it again here to protect the path integrity */
+ fromName = build_path_from_dentry(source_direntry);
+ toName = build_path_from_dentry(target_direntry);
+ if((fromName == NULL) || (toName == NULL)) {
+ rc = -ENOMEM;
+ goto cifs_rename_exit;
+ }
+
+ rc = CIFSSMBRename(xid, pTcon, fromName, toName,
+ cifs_sb_source->local_nls);
+ if(rc == -EEXIST) {
+ /* check if they are the same file
+ because rename of hardlinked files is a noop */
+ FILE_UNIX_BASIC_INFO * info_buf_source;
+ FILE_UNIX_BASIC_INFO * info_buf_target;
+
+ info_buf_source =
+ kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
+ if(info_buf_source != NULL) {
+ info_buf_target = info_buf_source+1;
+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
+ info_buf_source, cifs_sb_source->local_nls);
+ if(rc == 0) {
+ rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
+ info_buf_target,
+ cifs_sb_target->local_nls);
+ }
+ if((rc == 0) &&
+ (info_buf_source->UniqueId ==
+ info_buf_target->UniqueId)) {
+ /* do not rename since the files are hardlinked
+ which is a noop */
+ } else {
+ /* we either can not tell the files are hardlinked
+ (as with Windows servers) or files are not hardlinked
+ so delete the target manually before renaming to
+ follow POSIX rather than Windows semantics */
+ cifs_unlink(target_inode, target_direntry);
+ rc = CIFSSMBRename(xid, pTcon, fromName, toName,
+ cifs_sb_source->local_nls);
+ }
+ kfree(info_buf_source);
+ } /* if we can not get memory just leave rc as EEXIST */
+ }
+
+ if((rc == -EIO)||(rc == -EEXIST)) {
+ int oplock = FALSE;
+ __u16 netfid;
+
+ rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
+ CREATE_NOT_DIR,
+ &netfid, &oplock, NULL, cifs_sb_source->local_nls);
+ if(rc==0) {
+ CIFSSMBRenameOpenFile(xid,pTcon,netfid,
+ toName, cifs_sb_source->local_nls);
+ CIFSSMBClose(xid, pTcon, netfid);
+ }
+ }
+
+cifs_rename_exit:
+ if (fromName)
+ kfree(fromName);
+ if (toName)
+ kfree(toName);
+
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_revalidate(struct dentry *direntry)
+{
+ int xid;
+ int rc = 0;
+ char *full_path;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsInodeInfo *cifsInode;
+ loff_t local_size;
+ time_t local_mtime;
+ int invalidate_inode = FALSE;
+
+ if(direntry->d_inode == NULL)
+ return -ENOENT;
+
+ cifsInode = CIFS_I(direntry->d_inode);
+
+ if(cifsInode == NULL)
+ return -ENOENT;
+
+ /* no sense revalidating inode info on file that no one can write */
+ if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
+ return rc;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(direntry->d_sb);
+
+ /* can not safely grab the rename sem here if
+ rename calls revalidate since that would deadlock */
+ full_path = build_path_from_dentry(direntry);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ cFYI(1,
+ ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
+ full_path, direntry->d_inode,
+ direntry->d_inode->i_count.counter, direntry,
+ direntry->d_time, jiffies));
+
+ if (cifsInode->time == 0){
+ /* was set to zero previously to force revalidate */
+ } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
+ if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
+ (direntry->d_inode->i_nlink == 1)) {
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+ } else {
+ cFYI(1,("Have to revalidate file due to hardlinks"));
+ }
+ }
+
+ /* save mtime and size */
+ local_mtime = direntry->d_inode->i_mtime;
+ local_size = direntry->d_inode->i_size;
+
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+ rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
+ direntry->d_sb,xid);
+ if(rc) {
+ cFYI(1,("error on getting revalidate info %d",rc));
+/* if(rc != -ENOENT)
+ rc = 0; */ /* BB should we cache info on certain errors? */
+ }
+ } else {
+ rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
+ direntry->d_sb,xid);
+ if(rc) {
+ cFYI(1,("error on getting revalidate info %d",rc));
+/* if(rc != -ENOENT)
+ rc = 0; */ /* BB should we cache info on certain errors? */
+ }
+ }
+ /* should we remap certain errors, access denied?, to zero */
+
+ /* if not oplocked, we invalidate inode pages if mtime
+ or file size had changed on server */
+
+ if((local_mtime == direntry->d_inode->i_mtime) &&
+ (local_size == direntry->d_inode->i_size)) {
+ cFYI(1,("cifs_revalidate - inode unchanged"));
+ } else {
+ /* file may have changed on server */
+ if(cifsInode->clientCanCacheRead) {
+ /* no need to invalidate inode pages since we were
+ the only ones who could have modified the file and
+ the server copy is staler than ours */
+ } else {
+ invalidate_inode = TRUE;
+ }
+ }
+
+ /* can not grab this sem since kernel filesys locking
+ documentation indicates i_sem may be taken by the kernel
+ on lookup and rename which could deadlock if we grab
+ the i_sem here as well */
+/* down(&direntry->d_inode->i_sem);*/
+ /* need to write out dirty pages here */
+ if(direntry->d_inode->i_mapping) {
+ /* do we need to lock inode until after invalidate completes below? */
+ filemap_fdatasync(direntry->d_inode->i_mapping);
+ }
+ if(invalidate_inode) {
+ filemap_fdatawait(direntry->d_inode->i_mapping);
+ /* may eventually have to do this for open files too */
+ if(list_empty(&(cifsInode->openFileList))) {
+ /* Has changed on server - flush read ahead pages */
+ cFYI(1,("Invalidating read ahead data on closed file"));
+ invalidate_inode_pages(direntry->d_inode);
+ }
+ }
+/* up(&direntry->d_inode->i_sem);*/
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+
+ return rc;
+}
+
+/* int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+ int err = cifs_revalidate(dentry);
+ if (!err)
+ generic_fillattr(dentry->d_inode, stat);
+ return err;
+} */
+
+void
+cifs_truncate_file(struct inode *inode)
+{ /* BB remove - may not need this function after all BB */
+ int xid;
+ int rc = -EIO;
+ int found = FALSE;
+ struct cifsFileInfo *open_file = NULL;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct cifsInodeInfo *cifsInode;
+ struct dentry *dirent;
+ struct list_head * tmp;
+ char *full_path = NULL;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ /* To avoid spurious oplock breaks from server, in the case
+ of inodes that we already have open, avoid doing path
+ based setting of file size if we can do it by handle.
+ This keeps our caching token (oplock) and avoids
+ timeouts when the local oplock break takes longer to flush
+ writebehind data than the SMB timeout for the SetPathInfo
+ request would allow */
+ read_lock(&GlobalSMBSeslock);
+ cifsInode = CIFS_I(inode);
+ list_for_each(tmp, &cifsInode->openFileList) {
+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
+ /* We check if file is open for writing first */
+ if((open_file->pfile) && (!open_file->invalidHandle) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ read_unlock(&GlobalSMBSeslock);
+ found = TRUE;
+ rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
+ open_file->netfid,open_file->pid,FALSE);
+ if(rc == 0) {
+ FreeXid(xid);
+ return;
+ }
+ /* Do not need reopen and retry on EAGAIN since we will
+ retry by pathname below */
+ if(rc == -EAGAIN)
+ rc = -EHOSTDOWN;
+
+ break; /* now that we found one valid file handle no
+ sense continuing to loop trying others */
+ }
+ }
+ if(found == FALSE)
+ read_unlock(&GlobalSMBSeslock);
+
+ if (list_empty(&inode->i_dentry)) {
+ cERROR(1,
+ ("Can not get pathname from empty dentry in inode 0x%p ",
+ inode));
+ FreeXid(xid);
+ return;
+ }
+
+ dirent = list_entry(inode->i_dentry.next, struct dentry, d_alias);
+ if (dirent) {
+ full_path = build_path_from_dentry(dirent);
+ rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
+ cifs_sb->local_nls);
+ cFYI(1,(" SetEOF (truncate) rc = %d",rc));
+ if (!rc)
+ CIFSSMBSetEOF(xid,pTcon,full_path,inode->i_size,TRUE,cifs_sb->local_nls);
+ /* allocation size setting seems optional so ignore return code */
+ }
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return;
+}
+
+static int cifs_truncate_page(struct address_space *mapping, loff_t from)
+{
+ unsigned long index = from >> PAGE_CACHE_SHIFT;
+ unsigned offset = from & (PAGE_CACHE_SIZE-1);
+ struct page *page;
+ char *kaddr;
+ int rc = 0;
+
+ page = grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+
+ kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+ unlock_page(page);
+ page_cache_release(page);
+ return rc;
+}
+
+int
+cifs_setattr(struct dentry *direntry, struct iattr *attrs)
+{
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ int rc = -EACCES;
+ int found = FALSE;
+ struct cifsFileInfo *open_file = NULL;
+ FILE_BASIC_INFO time_buf;
+ int set_time = FALSE;
+ __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
+ __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
+ __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
+ struct cifsInodeInfo *cifsInode;
+ struct list_head * tmp;
+
+ xid = GetXid();
+
+ cFYI(1,
+ (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
+ direntry->d_name.name, attrs->ia_valid));
+ cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&direntry->d_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&direntry->d_sb->s_vfs_rename_sem);
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ cifsInode = CIFS_I(direntry->d_inode);
+
+ /* BB check if we need to refresh inode from server now ? BB */
+
+ /* need to flush data before changing file size on server */
+ filemap_fdatasync(direntry->d_inode->i_mapping);
+
+ if (attrs->ia_valid & ATTR_SIZE) {
+ read_lock(&GlobalSMBSeslock);
+ /* To avoid spurious oplock breaks from server, in the case
+ of inodes that we already have open, avoid doing path
+ based setting of file size if we can do it by handle.
+ This keeps our caching token (oplock) and avoids
+ timeouts when the local oplock break takes longer to flush
+ writebehind data than the SMB timeout for the SetPathInfo
+ request would allow */
+ list_for_each(tmp, &cifsInode->openFileList) {
+ open_file = list_entry(tmp,struct cifsFileInfo, flist);
+ /* We check if file is open for writing first */
+ if((open_file->pfile) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ if(open_file->invalidHandle == FALSE) {
+ /* we found a valid, writeable network file
+ handle to use to try to set the file size */
+ __u16 nfid = open_file->netfid;
+ __u32 npid = open_file->pid;
+ read_unlock(&GlobalSMBSeslock);
+ found = TRUE;
+ rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
+ nfid,npid,FALSE);
+ cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
+ /* Do not need reopen and retry on EAGAIN since we will
+ retry by pathname below */
+
+ break; /* now that we found one valid file handle no
+ sense continuing to loop trying others */
+ }
+ }
+ }
+ if(found == FALSE) {
+ read_unlock(&GlobalSMBSeslock);
+ }
+
+
+ if(rc != 0) {
+ /* Set file size by pathname rather than by handle either
+ because no valid, writeable file handle for it was found or
+ because there was an error setting it by handle */
+ rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
+ cifs_sb->local_nls);
+ cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
+ }
+
+ /* Server is ok setting allocation size implicitly - no need to call: */
+ /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
+
+ if (rc == 0) {
+ rc = vmtruncate(direntry->d_inode, attrs->ia_size);
+ cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
+ }
+ }
+ if (attrs->ia_valid & ATTR_UID) {
+ cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
+ uid = attrs->ia_uid;
+ /* entry->uid = cpu_to_le16(attr->ia_uid); */
+ }
+ if (attrs->ia_valid & ATTR_GID) {
+ cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
+ gid = attrs->ia_gid;
+ /* entry->gid = cpu_to_le16(attr->ia_gid); */
+ }
+
+ time_buf.Attributes = 0;
+ if (attrs->ia_valid & ATTR_MODE) {
+ cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
+ mode = attrs->ia_mode;
+ /* entry->mode = cpu_to_le16(attr->ia_mode); */
+ }
+
+ if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
+ rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
+ 0 /* dev_t */, cifs_sb->local_nls);
+ else if (attrs->ia_valid & ATTR_MODE) {
+ if((mode & S_IWUGO) == 0) /* not writeable */ {
+ if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
+ time_buf.Attributes =
+ cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
+ } else if((mode & S_IWUGO) == S_IWUGO) {
+ if(cifsInode->cifsAttrs & ATTR_READONLY)
+ time_buf.Attributes =
+ cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
+ }
+ /* BB to be implemented - via Windows security descriptors or streams */
+ /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
+ }
+
+ if (attrs->ia_valid & ATTR_ATIME) {
+ set_time = TRUE;
+ time_buf.LastAccessTime =
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
+ } else
+ time_buf.LastAccessTime = 0;
+
+ if (attrs->ia_valid & ATTR_MTIME) {
+ set_time = TRUE;
+ time_buf.LastWriteTime =
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
+ } else
+ time_buf.LastWriteTime = 0;
+
+ if (attrs->ia_valid & ATTR_CTIME) {
+ set_time = TRUE;
+ time_buf.ChangeTime =
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
+ } else
+ time_buf.ChangeTime = 0;
+
+ if (set_time | time_buf.Attributes) {
+ /* BB what if setting one attribute fails
+ (such as size) but time setting works */
+ time_buf.CreationTime = 0; /* do not change */
+ /* In the future we should experiment - try setting timestamps
+ via Handle (SetFileInfo) instead of by path */
+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
+ cifs_sb->local_nls);
+ }
+
+ /* do not need local check to inode_check_ok since the server does that */
+ if (!rc)
+ rc = inode_setattr(direntry->d_inode, attrs);
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+void
+cifs_delete_inode(struct inode *inode)
+{
+ cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
+ /* may have to add back in if and when safe distributed caching of
+ directories added e.g. via FindNotify */
+}
diff --git a/release/src/linux/linux/fs/cifs/link.c b/release/src/linux/linux/fs/cifs/link.c
new file mode 100644
index 00000000..d4e93724
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/link.c
@@ -0,0 +1,328 @@
+/*
+ * fs/cifs/link.c
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+int
+cifs_hardlink(struct dentry *old_file, struct inode *inode,
+ struct dentry *direntry)
+{
+ int rc = -EACCES;
+ int xid;
+ char *fromName = NULL;
+ char *toName = NULL;
+ struct cifs_sb_info *cifs_sb_target;
+ struct cifsTconInfo *pTcon;
+ struct cifsInodeInfo *cifsInode;
+
+ xid = GetXid();
+
+ cifs_sb_target = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb_target->tcon;
+
+/* No need to check for cross device links since server will do that
+ BB note DFS case in future though (when we may have to check) */
+
+ down(&inode->i_sb->s_vfs_rename_sem);
+ fromName = build_path_from_dentry(old_file);
+ toName = build_path_from_dentry(direntry);
+ up(&inode->i_sb->s_vfs_rename_sem);
+ if((fromName == NULL) || (toName == NULL)) {
+ rc = -ENOMEM;
+ goto cifs_hl_exit;
+ }
+
+ if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
+ rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
+ cifs_sb_target->local_nls);
+ else {
+ rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
+ cifs_sb_target->local_nls);
+ if(rc == -EIO)
+ rc = -EOPNOTSUPP;
+ }
+
+/* if (!rc) */
+ {
+ /* renew_parental_timestamps(old_file);
+ inode->i_nlink++;
+ mark_inode_dirty(inode);
+ d_instantiate(direntry, inode); */
+ /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
+ }
+ d_drop(direntry); /* force new lookup from server */
+ cifsInode = CIFS_I(old_file->d_inode);
+ cifsInode->time = 0; /* will force revalidate to go get info when needed */
+
+cifs_hl_exit:
+ if (fromName)
+ kfree(fromName);
+ if (toName)
+ kfree(toName);
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
+{
+ struct inode *inode = direntry->d_inode;
+ int rc = -EACCES;
+ int xid;
+ char *full_path = NULL;
+ char * target_path;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+
+ xid = GetXid();
+
+ down(&direntry->d_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&direntry->d_sb->s_vfs_rename_sem);
+
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+ target_path = kmalloc(PATH_MAX, GFP_KERNEL);
+ if(target_path == NULL) {
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+ /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
+ /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
+
+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
+ target_path,
+ PATH_MAX-1,
+ cifs_sb->local_nls);
+ else {
+ /* rc = CIFSSMBQueryReparseLinkInfo */
+ /* BB Add code to Query ReparsePoint info */
+ }
+ /* BB Anything else to do to handle recursive links? */
+ /* BB Should we be using page symlink ops here? */
+
+ if (rc == 0) {
+
+/* BB Add special case check for Samba DFS symlinks */
+
+ target_path[PATH_MAX-1] = 0;
+ rc = vfs_follow_link(nd, target_path);
+ }
+ /* else EACCESS */
+
+ if (target_path)
+ kfree(target_path);
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
+{
+ int rc = -EOPNOTSUPP;
+ int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ struct inode *newinode = NULL;
+
+ xid = GetXid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+ down(&inode->i_sb->s_vfs_rename_sem);
+ full_path = build_path_from_dentry(direntry);
+ up(&inode->i_sb->s_vfs_rename_sem);
+
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+
+ cFYI(1, ("Full path: %s ", full_path));
+ cFYI(1, ("symname is %s", symname));
+
+ /* BB what if DFS and this volume is on different share? BB */
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
+ cifs_sb->local_nls);
+ /* else
+ rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
+
+ if (rc == 0) {
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb,xid);
+ else
+ rc = cifs_get_inode_info(&newinode, full_path, NULL,
+ inode->i_sb,xid);
+
+ if (rc != 0) {
+ cFYI(1,
+ ("Create symlink worked but get_inode_info failed with rc = %d ",
+ rc));
+ } else {
+ direntry->d_op = &cifs_dentry_ops;
+ d_instantiate(direntry, newinode);
+ }
+ }
+
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+}
+
+int
+cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
+{
+ struct inode *inode = direntry->d_inode;
+ int rc = -EACCES;
+ int xid;
+ int oplock = FALSE;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ char *tmp_path = NULL;
+ char * tmpbuffer;
+ unsigned char * referrals = NULL;
+ int num_referrals = 0;
+ int len;
+ __u16 fid;
+
+ xid = GetXid();
+ cifs_sb = CIFS_SB(inode->i_sb);
+ pTcon = cifs_sb->tcon;
+
+/* BB would it be safe against deadlock to grab this sem
+ even though rename itself grabs the sem and calls lookup? */
+/* down(&inode->i_sb->s_vfs_rename_sem);*/
+ full_path = build_path_from_dentry(direntry);
+/* up(&inode->i_sb->s_vfs_rename_sem);*/
+
+ if(full_path == NULL) {
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+
+ cFYI(1,
+ ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
+ full_path, inode, pBuffer, buflen));
+ if(buflen > PATH_MAX)
+ len = PATH_MAX;
+ else
+ len = buflen;
+ tmpbuffer = kmalloc(len,GFP_KERNEL);
+ if(tmpbuffer == NULL) {
+ if (full_path)
+ kfree(full_path);
+ FreeXid(xid);
+ return -ENOMEM;
+ }
+
+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
+ tmpbuffer,
+ len - 1,
+ cifs_sb->local_nls);
+ else {
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
+ OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
+ if(!rc) {
+ rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
+ tmpbuffer,
+ len - 1,
+ fid,
+ cifs_sb->local_nls);
+ if(CIFSSMBClose(xid, pTcon, fid)) {
+ cFYI(1,("Error closing junction point (open for ioctl)"));
+ }
+ if(rc == -EIO) {
+ /* Query if DFS Junction */
+ tmp_path =
+ kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
+ GFP_KERNEL);
+ if (tmp_path) {
+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+ strncat(tmp_path, full_path, MAX_PATHCONF);
+ rc = get_dfs_path(xid, pTcon->ses, tmp_path,
+ cifs_sb->local_nls, &num_referrals, &referrals);
+ cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
+ if((num_referrals == 0) && (rc == 0))
+ rc = -EACCES;
+ else {
+ cFYI(1,("num referral: %d",num_referrals));
+ if(referrals) {
+ cFYI(1,("referral string: %s ",referrals));
+ strncpy(tmpbuffer, referrals, len-1);
+ }
+ }
+ if(referrals)
+ kfree(referrals);
+ kfree(tmp_path);
+ if(referrals) {
+ kfree(referrals);
+ }
+ }
+ /* BB add code like else decode referrals then memcpy to
+ tmpbuffer and free referrals string array BB */
+ }
+ }
+ }
+ /* BB Anything else to do to handle recursive links? */
+ /* BB Should we be using page ops here? */
+
+ /* BB null terminate returned string in pBuffer? BB */
+ if (rc == 0) {
+ rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
+ cFYI(1,
+ ("vfs_readlink called from cifs_readlink returned %d",
+ rc));
+ }
+
+ if (tmpbuffer) {
+ kfree(tmpbuffer);
+ }
+ if (full_path) {
+ kfree(full_path);
+ }
+ FreeXid(xid);
+ return rc;
+}
diff --git a/release/src/linux/linux/fs/cifs/md4.c b/release/src/linux/linux/fs/cifs/md4.c
new file mode 100644
index 00000000..1edbe22c
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/md4.c
@@ -0,0 +1,203 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ a implementation of MD4 designed for use in the SMB authentication protocol
+ Copyright (C) Andrew Tridgell 1997-1998.
+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include <linux/module.h>
+#include <linux/fs.h>
+/* NOTE: This code makes no attempt to be fast! */
+
+static __u32
+F(__u32 X, __u32 Y, __u32 Z)
+{
+ return (X & Y) | ((~X) & Z);
+}
+
+static __u32
+G(__u32 X, __u32 Y, __u32 Z)
+{
+ return (X & Y) | (X & Z) | (Y & Z);
+}
+
+static __u32
+H(__u32 X, __u32 Y, __u32 Z)
+{
+ return X ^ Y ^ Z;
+}
+
+static __u32
+lshift(__u32 x, int s)
+{
+ x &= 0xFFFFFFFF;
+ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
+}
+
+#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
+#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
+#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
+
+/* this applies md4 to 64 byte chunks */
+static void
+mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
+{
+ int j;
+ __u32 AA, BB, CC, DD;
+ __u32 X[16];
+
+
+ for (j = 0; j < 16; j++)
+ X[j] = M[j];
+
+ AA = *A;
+ BB = *B;
+ CC = *C;
+ DD = *D;
+
+ ROUND1(A, B, C, D, 0, 3);
+ ROUND1(D, A, B, C, 1, 7);
+ ROUND1(C, D, A, B, 2, 11);
+ ROUND1(B, C, D, A, 3, 19);
+ ROUND1(A, B, C, D, 4, 3);
+ ROUND1(D, A, B, C, 5, 7);
+ ROUND1(C, D, A, B, 6, 11);
+ ROUND1(B, C, D, A, 7, 19);
+ ROUND1(A, B, C, D, 8, 3);
+ ROUND1(D, A, B, C, 9, 7);
+ ROUND1(C, D, A, B, 10, 11);
+ ROUND1(B, C, D, A, 11, 19);
+ ROUND1(A, B, C, D, 12, 3);
+ ROUND1(D, A, B, C, 13, 7);
+ ROUND1(C, D, A, B, 14, 11);
+ ROUND1(B, C, D, A, 15, 19);
+
+ ROUND2(A, B, C, D, 0, 3);
+ ROUND2(D, A, B, C, 4, 5);
+ ROUND2(C, D, A, B, 8, 9);
+ ROUND2(B, C, D, A, 12, 13);
+ ROUND2(A, B, C, D, 1, 3);
+ ROUND2(D, A, B, C, 5, 5);
+ ROUND2(C, D, A, B, 9, 9);
+ ROUND2(B, C, D, A, 13, 13);
+ ROUND2(A, B, C, D, 2, 3);
+ ROUND2(D, A, B, C, 6, 5);
+ ROUND2(C, D, A, B, 10, 9);
+ ROUND2(B, C, D, A, 14, 13);
+ ROUND2(A, B, C, D, 3, 3);
+ ROUND2(D, A, B, C, 7, 5);
+ ROUND2(C, D, A, B, 11, 9);
+ ROUND2(B, C, D, A, 15, 13);
+
+ ROUND3(A, B, C, D, 0, 3);
+ ROUND3(D, A, B, C, 8, 9);
+ ROUND3(C, D, A, B, 4, 11);
+ ROUND3(B, C, D, A, 12, 15);
+ ROUND3(A, B, C, D, 2, 3);
+ ROUND3(D, A, B, C, 10, 9);
+ ROUND3(C, D, A, B, 6, 11);
+ ROUND3(B, C, D, A, 14, 15);
+ ROUND3(A, B, C, D, 1, 3);
+ ROUND3(D, A, B, C, 9, 9);
+ ROUND3(C, D, A, B, 5, 11);
+ ROUND3(B, C, D, A, 13, 15);
+ ROUND3(A, B, C, D, 3, 3);
+ ROUND3(D, A, B, C, 11, 9);
+ ROUND3(C, D, A, B, 7, 11);
+ ROUND3(B, C, D, A, 15, 15);
+
+ *A += AA;
+ *B += BB;
+ *C += CC;
+ *D += DD;
+
+ *A &= 0xFFFFFFFF;
+ *B &= 0xFFFFFFFF;
+ *C &= 0xFFFFFFFF;
+ *D &= 0xFFFFFFFF;
+
+ for (j = 0; j < 16; j++)
+ X[j] = 0;
+}
+
+static void
+copy64(__u32 * M, unsigned char *in)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
+ (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
+}
+
+static void
+copy4(unsigned char *out, __u32 x)
+{
+ out[0] = x & 0xFF;
+ out[1] = (x >> 8) & 0xFF;
+ out[2] = (x >> 16) & 0xFF;
+ out[3] = (x >> 24) & 0xFF;
+}
+
+/* produce a md4 message digest from data of length n bytes */
+void
+mdfour(unsigned char *out, unsigned char *in, int n)
+{
+ unsigned char buf[128];
+ __u32 M[16];
+ __u32 b = n * 8;
+ int i;
+ __u32 A = 0x67452301;
+ __u32 B = 0xefcdab89;
+ __u32 C = 0x98badcfe;
+ __u32 D = 0x10325476;
+
+ while (n > 64) {
+ copy64(M, in);
+ mdfour64(M,&A,&B, &C, &D);
+ in += 64;
+ n -= 64;
+ }
+
+ for (i = 0; i < 128; i++)
+ buf[i] = 0;
+ memcpy(buf, in, n);
+ buf[n] = 0x80;
+
+ if (n <= 55) {
+ copy4(buf + 56, b);
+ copy64(M, buf);
+ mdfour64(M, &A, &B, &C, &D);
+ } else {
+ copy4(buf + 120, b);
+ copy64(M, buf);
+ mdfour64(M, &A, &B, &C, &D);
+ copy64(M, buf + 64);
+ mdfour64(M, &A, &B, &C, &D);
+ }
+
+ for (i = 0; i < 128; i++)
+ buf[i] = 0;
+ copy64(M, buf);
+
+ copy4(out, A);
+ copy4(out + 4, B);
+ copy4(out + 8, C);
+ copy4(out + 12, D);
+
+ A = B = C = D = 0;
+}
diff --git a/release/src/linux/linux/fs/cifs/md5.c b/release/src/linux/linux/fs/cifs/md5.c
new file mode 100644
index 00000000..7aa23490
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/md5.c
@@ -0,0 +1,363 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code slightly modified to fit into Samba by
+ abartlet@samba.org Jun 2001
+ and to fit the cifs vfs by
+ Steve French sfrench@us.ibm.com */
+
+#include <linux/string.h>
+#include "md5.h"
+
+static void MD5Transform(__u32 buf[4], __u32 const in[16]);
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void
+byteReverse(unsigned char *buf, unsigned longs)
+{
+ __u32 t;
+ do {
+ t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(__u32 *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+ register __u32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memmove(p, buf, len);
+ return;
+ }
+ memmove(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memmove(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memmove(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned int count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((__u32 *) ctx->in)[14] = ctx->bits[0];
+ ((__u32 *) ctx->in)[15] = ctx->bits[1];
+
+ MD5Transform(ctx->buf, (__u32 *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memmove(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+MD5Transform(__u32 buf[4], __u32 const in[16])
+{
+ register __u32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/***********************************************************************
+ the rfc 2104 version of hmac_md5 initialisation.
+***********************************************************************/
+void
+hmac_md5_init_rfc2104(unsigned char *key, int key_len,
+ struct HMACMD5Context *ctx)
+{
+ int i;
+
+ /* if key is longer than 64 bytes reset it to key=MD5(key) */
+ if (key_len > 64) {
+ unsigned char tk[16];
+ struct MD5Context tctx;
+
+ MD5Init(&tctx);
+ MD5Update(&tctx, key, key_len);
+ MD5Final(tk, &tctx);
+
+ key = tk;
+ key_len = 16;
+ }
+
+ /* start out by storing key in pads */
+ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
+ memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+ memcpy(ctx->k_ipad, key, key_len);
+ memcpy(ctx->k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < 64; i++) {
+ ctx->k_ipad[i] ^= 0x36;
+ ctx->k_opad[i] ^= 0x5c;
+ }
+
+ MD5Init(&ctx->ctx);
+ MD5Update(&ctx->ctx, ctx->k_ipad, 64);
+}
+
+/***********************************************************************
+ the microsoft version of hmac_md5 initialisation.
+***********************************************************************/
+void
+hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
+ struct HMACMD5Context *ctx)
+{
+ int i;
+
+ /* if key is longer than 64 bytes truncate it */
+ if (key_len > 64) {
+ key_len = 64;
+ }
+
+ /* start out by storing key in pads */
+ memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
+ memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+ memcpy(ctx->k_ipad, key, key_len);
+ memcpy(ctx->k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < 64; i++) {
+ ctx->k_ipad[i] ^= 0x36;
+ ctx->k_opad[i] ^= 0x5c;
+ }
+
+ MD5Init(&ctx->ctx);
+ MD5Update(&ctx->ctx, ctx->k_ipad, 64);
+}
+
+/***********************************************************************
+ update hmac_md5 "inner" buffer
+***********************************************************************/
+void
+hmac_md5_update(const unsigned char *text, int text_len,
+ struct HMACMD5Context *ctx)
+{
+ MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
+}
+
+/***********************************************************************
+ finish off hmac_md5 "inner" buffer and generate outer one.
+***********************************************************************/
+void
+hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
+{
+ struct MD5Context ctx_o;
+
+ MD5Final(digest, &ctx->ctx);
+
+ MD5Init(&ctx_o);
+ MD5Update(&ctx_o, ctx->k_opad, 64);
+ MD5Update(&ctx_o, digest, 16);
+ MD5Final(digest, &ctx_o);
+}
+
+/***********************************************************
+ single function to calculate an HMAC MD5 digest from data.
+ use the microsoft hmacmd5 init method because the key is 16 bytes.
+************************************************************/
+void
+hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
+ unsigned char *digest)
+{
+ struct HMACMD5Context ctx;
+ hmac_md5_init_limK_to_64(key, 16, &ctx);
+ if (data_len != 0) {
+ hmac_md5_update(data, data_len, &ctx);
+ }
+ hmac_md5_final(digest, &ctx);
+}
diff --git a/release/src/linux/linux/fs/cifs/md5.h b/release/src/linux/linux/fs/cifs/md5.h
new file mode 100644
index 00000000..00e1c539
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/md5.h
@@ -0,0 +1,38 @@
+#ifndef MD5_H
+#define MD5_H
+#ifndef HEADER_MD5_H
+/* Try to avoid clashes with OpenSSL */
+#define HEADER_MD5_H
+#endif
+
+struct MD5Context {
+ __u32 buf[4];
+ __u32 bits[2];
+ unsigned char in[64];
+};
+#endif /* !MD5_H */
+
+#ifndef _HMAC_MD5_H
+struct HMACMD5Context {
+ struct MD5Context ctx;
+ unsigned char k_ipad[65];
+ unsigned char k_opad[65];
+};
+#endif /* _HMAC_MD5_H */
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+ unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+
+/* The following definitions come from lib/hmacmd5.c */
+
+void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
+ struct HMACMD5Context *ctx);
+void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
+ struct HMACMD5Context *ctx);
+void hmac_md5_update(const unsigned char *text, int text_len,
+ struct HMACMD5Context *ctx);
+void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
+void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
+ unsigned char *digest);
diff --git a/release/src/linux/linux/fs/cifs/misc.c b/release/src/linux/linux/fs/cifs/misc.c
new file mode 100644
index 00000000..2241c45e
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/misc.c
@@ -0,0 +1,463 @@
+/*
+ * fs/cifs/misc.c
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "smberr.h"
+#include "nterr.h"
+
+extern kmem_cache_t *cifs_req_cachep;
+extern struct task_struct * oplockThread;
+
+__u16 GlobalMid; /* multiplex id - rotating counter */
+
+/* The xid serves as a useful identifier for each incoming vfs request,
+ in a similar way to the mid which is useful to track each sent smb,
+ and CurrentXid can also provide a running counter (although it
+ will eventually wrap past zero) of the total vfs operations handled
+ since the cifs fs was mounted */
+
+unsigned int
+_GetXid(void)
+{
+ unsigned int xid;
+
+ spin_lock(&GlobalMid_Lock);
+ GlobalTotalActiveXid++;
+ if (GlobalTotalActiveXid > GlobalMaxActiveXid)
+ GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
+ xid = GlobalCurrentXid++;
+ spin_unlock(&GlobalMid_Lock);
+ return xid;
+}
+
+void
+_FreeXid(unsigned int xid)
+{
+ spin_lock(&GlobalMid_Lock);
+ /* if(GlobalTotalActiveXid == 0)
+ BUG(); */
+ GlobalTotalActiveXid--;
+ spin_unlock(&GlobalMid_Lock);
+}
+
+struct cifsSesInfo *
+sesInfoAlloc(void)
+{
+ struct cifsSesInfo *ret_buf;
+
+ ret_buf =
+ (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
+ GFP_KERNEL);
+ if (ret_buf) {
+ memset(ret_buf, 0, sizeof (struct cifsSesInfo));
+ write_lock(&GlobalSMBSeslock);
+ atomic_inc(&sesInfoAllocCount);
+ ret_buf->status = CifsNew;
+ list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
+ init_MUTEX(&ret_buf->sesSem);
+ write_unlock(&GlobalSMBSeslock);
+ }
+ return ret_buf;
+}
+
+void
+sesInfoFree(struct cifsSesInfo *buf_to_free)
+{
+ if (buf_to_free == NULL) {
+ cFYI(1, ("Null buffer passed to sesInfoFree"));
+ return;
+ }
+
+ write_lock(&GlobalSMBSeslock);
+ atomic_dec(&sesInfoAllocCount);
+ list_del(&buf_to_free->cifsSessionList);
+ write_unlock(&GlobalSMBSeslock);
+ if (buf_to_free->serverOS)
+ kfree(buf_to_free->serverOS);
+ if (buf_to_free->serverDomain)
+ kfree(buf_to_free->serverDomain);
+ if (buf_to_free->serverNOS)
+ kfree(buf_to_free->serverNOS);
+ if (buf_to_free->password)
+ kfree(buf_to_free->password);
+ kfree(buf_to_free);
+}
+
+struct cifsTconInfo *
+tconInfoAlloc(void)
+{
+ struct cifsTconInfo *ret_buf;
+ ret_buf =
+ (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
+ GFP_KERNEL);
+ if (ret_buf) {
+ memset(ret_buf, 0, sizeof (struct cifsTconInfo));
+ write_lock(&GlobalSMBSeslock);
+ atomic_inc(&tconInfoAllocCount);
+ list_add(&ret_buf->cifsConnectionList,
+ &GlobalTreeConnectionList);
+ ret_buf->tidStatus = CifsNew;
+ INIT_LIST_HEAD(&ret_buf->openFileList);
+ init_MUTEX(&ret_buf->tconSem);
+#ifdef CONFIG_CIFS_STATS
+ ret_buf->stat_lock = SPIN_LOCK_UNLOCKED;
+#endif
+ write_unlock(&GlobalSMBSeslock);
+ }
+ return ret_buf;
+}
+
+void
+tconInfoFree(struct cifsTconInfo *buf_to_free)
+{
+ if (buf_to_free == NULL) {
+ cFYI(1, ("Null buffer passed to tconInfoFree"));
+ return;
+ }
+ write_lock(&GlobalSMBSeslock);
+ atomic_dec(&tconInfoAllocCount);
+ list_del(&buf_to_free->cifsConnectionList);
+ write_unlock(&GlobalSMBSeslock);
+ if (buf_to_free->nativeFileSystem)
+ kfree(buf_to_free->nativeFileSystem);
+ kfree(buf_to_free);
+}
+
+struct smb_hdr *
+cifs_buf_get(void)
+{
+ struct smb_hdr *ret_buf = NULL;
+
+/* We could use negotiated size instead of max_msgsize -
+ but it may be more efficient to always alloc same size
+ albeit slightly larger than necessary and maxbuffersize
+ defaults to this and can not be bigger */
+ ret_buf =
+ (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
+
+ /* clear the first few header bytes */
+ if (ret_buf) {
+ memset(ret_buf, 0, sizeof (struct smb_hdr));
+ atomic_inc(&bufAllocCount);
+ }
+
+ return ret_buf;
+}
+
+void
+cifs_buf_release(void *buf_to_free)
+{
+
+ if (buf_to_free == NULL) {
+ cFYI(1, ("Null buffer passed to cifs_buf_release"));
+ return;
+ }
+ kmem_cache_free(cifs_req_cachep, buf_to_free);
+
+ atomic_dec(&bufAllocCount);
+ return;
+}
+
+void
+header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
+ const struct cifsTconInfo *treeCon, int word_count
+ /* length of fixed section (word count) in two byte units */
+ )
+{
+ int i;
+ __u32 tmp;
+ struct list_head* temp_item;
+ struct cifsSesInfo * ses;
+ char *temp = (char *) buffer;
+
+ for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) {
+ temp[i] = 0; /* BB is this needed ?? */
+ }
+
+ buffer->smb_buf_length =
+ (2 * word_count) + sizeof (struct smb_hdr) -
+ 4 /* RFC 1001 length field does not count */ +
+ 2 /* for bcc field itself */ ;
+ /* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */
+
+ buffer->Protocol[0] = 0xFF;
+ buffer->Protocol[1] = 'S';
+ buffer->Protocol[2] = 'M';
+ buffer->Protocol[3] = 'B';
+ buffer->Command = smb_command;
+ buffer->Flags = 0x00; /* case sensitive */
+ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
+ tmp = cpu_to_le32(current->pid);
+ buffer->Pid = tmp & 0xFFFF;
+ tmp >>= 16;
+ buffer->PidHigh = tmp & 0xFFFF;
+ spin_lock(&GlobalMid_Lock);
+ GlobalMid++;
+ buffer->Mid = GlobalMid;
+ spin_unlock(&GlobalMid_Lock);
+ if (treeCon) {
+ buffer->Tid = treeCon->tid;
+ if (treeCon->ses) {
+ if (treeCon->ses->capabilities & CAP_UNICODE)
+ buffer->Flags2 |= SMBFLG2_UNICODE;
+ if (treeCon->ses->capabilities & CAP_STATUS32) {
+ buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ }
+
+ buffer->Uid = treeCon->ses->Suid; /* always in LE format */
+ if(multiuser_mount != 0) {
+ /* For the multiuser case, there are few obvious technically */
+ /* possible mechanisms to match the local linux user (uid) */
+ /* to a valid remote smb user (smb_uid): */
+ /* 1) Query Winbind (or other local pam/nss daemon */
+ /* for userid/password/logon_domain or credential */
+ /* 2) Query Winbind for uid to sid to username mapping */
+ /* and see if we have a matching password for existing*/
+ /* session for that user perhas getting password by */
+ /* adding a new pam_cifs module that stores passwords */
+ /* so that the cifs vfs can get at that for all logged*/
+ /* on users */
+ /* 3) (Which is the mechanism we have chosen) */
+ /* Search through sessions to the same server for a */
+ /* a match on the uid that was passed in on mount */
+ /* with the current processes uid (or euid?) and use */
+ /* that smb uid. If no existing smb session for */
+ /* that uid found, use the default smb session ie */
+ /* the smb session for the volume mounted which is */
+ /* the same as would be used if the multiuser mount */
+ /* flag were disabled. */
+
+ /* BB Add support for establishing new tCon and SMB Session */
+ /* with userid/password pairs found on the smb session */
+ /* for other target tcp/ip addresses BB */
+ if(current->uid != treeCon->ses->linux_uid) {
+ cFYI(1,("Multiuser mode and UID did not match tcon uid "));
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(temp_item, &GlobalSMBSessionList) {
+ ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
+ if(ses->linux_uid == current->uid) {
+ if(ses->server == treeCon->ses->server) {
+ cFYI(1,("found matching uid substitute right smb_uid"));
+ buffer->Uid = ses->Suid;
+ break;
+ } else {
+ /* BB eventually call cifs_setup_session here */
+ cFYI(1,("local UID found but smb sess with this server does not exist"));
+ }
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ }
+ }
+ }
+ if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
+ buffer->Flags2 |= SMBFLG2_DFS;
+ if(treeCon->ses->server)
+ if(treeCon->ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+ }
+
+/* endian conversion of flags is now done just before sending */
+ buffer->WordCount = (char) word_count;
+ return;
+}
+
+int
+checkSMBhdr(struct smb_hdr *smb, __u16 mid)
+{
+ /* Make sure that this really is an SMB, that it is a response,
+ and that the message ids match */
+ if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
+ (mid == smb->Mid)) {
+ if(smb->Flags & SMBFLG_RESPONSE)
+ return 0;
+ else {
+ /* only one valid case where server sends us request */
+ if(smb->Command == SMB_COM_LOCKING_ANDX)
+ return 0;
+ else
+ cERROR(1, ("Rcvd Request not response "));
+ }
+ } else { /* bad signature or mid */
+ if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
+ cERROR(1,
+ ("Bad protocol string signature header %x ",
+ *(unsigned int *) smb->Protocol));
+ if (mid != smb->Mid)
+ cERROR(1, ("Mids do not match"));
+ }
+ cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
+ return 1;
+}
+
+int
+checkSMB(struct smb_hdr *smb, __u16 mid, int length)
+{
+ cFYI(0,
+ ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
+ length, ntohl(smb->smb_buf_length)));
+ if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
+ || (ntohl(smb->smb_buf_length) >
+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
+ if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
+ cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
+ if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
+ && (smb->Status.CifsError != 0))
+ return 0; /* some error cases do not return wct and bcc */
+
+ }
+ if (ntohl(smb->smb_buf_length) >
+ CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
+ cERROR(1,
+ ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
+ cERROR(1,
+ ("bad smb detected. Illegal length. The mid=%d",
+ smb->Mid));
+ return 1;
+ }
+
+ if (checkSMBhdr(smb, mid))
+ return 1;
+
+ if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
+ || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
+ return 0;
+ } else {
+ cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
+ cERROR(1,
+ ("bad smb size detected. The Mid=%d", smb->Mid));
+ return 1;
+ }
+}
+int
+is_valid_oplock_break(struct smb_hdr *buf)
+{
+ struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
+ struct list_head *tmp;
+ struct list_head *tmp1;
+ struct cifsTconInfo *tcon;
+ struct cifsFileInfo *netfile;
+
+ /* could add check for smb response flag 0x80 */
+ cFYI(1,("Checking for oplock break"));
+ if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
+ return FALSE;
+ if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
+ /* no sense logging error on invalid handle on oplock
+ break - harmless race between close request and oplock
+ break response is expected from time to time writing out
+ large dirty files cached on the client */
+ if ((NT_STATUS_INVALID_HANDLE) ==
+ le32_to_cpu(pSMB->hdr.Status.CifsError)) {
+ cFYI(1,("invalid handle on oplock break"));
+ return TRUE;
+ } else if (ERRbadfid ==
+ le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
+ return TRUE;
+ } else {
+ return FALSE; /* on valid oplock brk we get "request" */
+ }
+ }
+ if(pSMB->hdr.WordCount != 8)
+ return FALSE;
+
+ cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
+ if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
+ return FALSE;
+
+ /* look up tcon based on tid & uid */
+ read_lock(&GlobalSMBSeslock);
+ list_for_each(tmp, &GlobalTreeConnectionList) {
+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+ if (tcon->tid == buf->Tid) {
+#ifdef CONFIG_CIFS_STATS
+ atomic_inc(&tcon->num_oplock_brks);
+#endif
+ list_for_each(tmp1,&tcon->openFileList){
+ netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
+ if(pSMB->Fid == netfile->netfid) {
+ struct cifsInodeInfo *pCifsInode;
+ read_unlock(&GlobalSMBSeslock);
+ cFYI(1,("Matching file id, processing oplock break"));
+ pCifsInode =
+ CIFS_I(netfile->pInode);
+ pCifsInode->clientCanCacheAll = FALSE;
+ if(pSMB->OplockLevel == 0)
+ pCifsInode->clientCanCacheRead = FALSE;
+ pCifsInode->oplockPending = TRUE;
+ AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
+ cFYI(1,("about to wake up oplock thd"));
+ wake_up_process(oplockThread);
+ return TRUE;
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ cFYI(1,("No matching file for oplock break on connection"));
+ return TRUE;
+ }
+ }
+ read_unlock(&GlobalSMBSeslock);
+ cFYI(1,("Can not process oplock break for non-existent connection"));
+ return TRUE;
+}
+
+void
+dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
+{
+ int i, j;
+ char debug_line[17];
+ unsigned char *buffer;
+
+ if (traceSMB == 0)
+ return;
+
+ buffer = (unsigned char *) smb_buf;
+ for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
+ if (i % 8 == 0) { /* we have reached the beginning of line */
+ printk(KERN_DEBUG "| ");
+ j = 0;
+ }
+ printk("%0#4x ", buffer[i]);
+ debug_line[2 * j] = ' ';
+ if (isprint(buffer[i]))
+ debug_line[1 + (2 * j)] = buffer[i];
+ else
+ debug_line[1 + (2 * j)] = '_';
+
+ if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
+ debug_line[16] = 0;
+ printk(" | %s\n", debug_line);
+ }
+ }
+ for (; j < 8; j++) {
+ printk(" ");
+ debug_line[2 * j] = ' ';
+ debug_line[1 + (2 * j)] = ' ';
+ }
+ printk( " | %s\n", debug_line);
+ return;
+}
diff --git a/release/src/linux/linux/fs/cifs/netmisc.c b/release/src/linux/linux/fs/cifs/netmisc.c
new file mode 100644
index 00000000..0a06be9d
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/netmisc.c
@@ -0,0 +1,905 @@
+/*
+ * fs/cifs/netmisc.c
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Error mapping routines from Samba libsmb/errormap.c
+ * Copyright (C) Andrew Tridgell 2001
+ *
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <asm/div64.h>
+#include <asm/byteorder.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smberr.h"
+#include "cifs_debug.h"
+#include "nterr.h"
+
+struct smb_to_posix_error {
+ __u16 smb_err;
+ int posix_code;
+};
+
+const struct smb_to_posix_error mapping_table_ERRDOS[] = {
+ {ERRbadfunc, -EINVAL},
+ {ERRbadfile, -ENOENT},
+ {ERRbadpath, -ENOTDIR},
+ {ERRnofids, -EMFILE},
+ {ERRnoaccess, -EACCES},
+ {ERRbadfid, -EBADF},
+ {ERRbadmcb, -EIO},
+ {ERRnomem, -ENOMEM},
+ {ERRbadmem, -EFAULT},
+ {ERRbadenv, -EFAULT},
+ {ERRbadformat, -EINVAL},
+ {ERRbadaccess, -EACCES},
+ {ERRbaddata, -EIO},
+ {ERRbaddrive, -ENXIO},
+ {ERRremcd, -EACCES},
+ {ERRdiffdevice, -EXDEV},
+ {ERRnofiles, -ENOENT},
+ {ERRbadshare, -ETXTBSY},
+ {ERRlock, -EACCES},
+ {ERRunsup, -EINVAL},
+ {ERRnosuchshare,-ENXIO},
+ {ERRfilexists, -EEXIST},
+ {ERRinvparm, -EINVAL},
+ {ERRdiskfull, -ENOSPC},
+ {ERRinvname, -ENOENT},
+ {ERRdirnotempty, -ENOTEMPTY},
+ {ERRnotlocked, -ENOLCK},
+ {ERRalreadyexists, -EEXIST},
+ {ERRmoredata, -EOVERFLOW},
+ {ErrQuota, -EDQUOT},
+ {ErrNotALink, -ENOLINK},
+ {ERRnetlogonNotStarted,-ENOPROTOOPT},
+ {0, 0}
+};
+
+const struct smb_to_posix_error mapping_table_ERRSRV[] = {
+ {ERRerror, -EIO},
+ {ERRbadpw, -EPERM},
+ {ERRbadtype, -EREMOTE},
+ {ERRaccess, -EACCES},
+ {ERRinvtid, -ENXIO},
+ {ERRinvnetname, -ENODEV},
+ {ERRinvdevice, -ENXIO},
+ {ERRqfull, -ENOSPC},
+ {ERRqtoobig, -ENOSPC},
+ {ERRqeof, -EIO},
+ {ERRinvpfid, -EBADF},
+ {ERRsmbcmd, -EBADRQC},
+ {ERRsrverror, -EIO},
+ {ERRbadBID, -EIO},
+ {ERRfilespecs, -EINVAL},
+ {ERRbadLink, -EIO},
+ {ERRbadpermits, -EINVAL},
+ {ERRbadPID, -ESRCH},
+ {ERRsetattrmode, -EINVAL},
+ {ERRpaused, -EHOSTDOWN},
+ {ERRmsgoff, -EHOSTDOWN},
+ {ERRnoroom, -ENOSPC},
+ {ERRrmuns, -EUSERS},
+ {ERRtimeout, -ETIME},
+ {ERRnoresource, -ENOBUFS},
+ {ERRtoomanyuids, -EUSERS},
+ {ERRbaduid, -EACCES},
+ {ERRusempx, -EIO},
+ {ERRusestd, -EIO},
+ {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
+ {ERRaccountexpired, -EACCES},
+ {ERRbadclient, -EACCES},
+ {ERRbadLogonTime, -EACCES},
+ {ERRpasswordExpired, -EACCES},
+ {ERRnosupport, -EINVAL},
+ {0, 0}
+};
+
+const struct smb_to_posix_error mapping_table_ERRHRD[] = {
+ {0, 0}
+};
+
+/* Convert string containing dotted ip address to binary form */
+/* returns 0 if invalid address */
+
+/* BB add address family, change rc to status flag and return union or for ipv6 */
+/* will need parent to call something like inet_pton to convert ipv6 address BB */
+int
+cifs_inet_pton(int address_family, char *cp,void *dst)
+{
+ struct in_addr address;
+ int value;
+ int digit;
+ int i;
+ char temp;
+ char bytes[4];
+ char *end = bytes;
+ static const int addr_class_max[4] =
+ { 0xffffffff, 0xffffff, 0xffff, 0xff };
+
+ if(address_family != AF_INET)
+ return -EAFNOSUPPORT;
+
+ for (i = 0; i < 4; i++) {
+ bytes[i] = 0;
+ }
+
+ temp = *cp;
+
+ while (TRUE) {
+ if (!isdigit(temp))
+ return 0;
+
+ value = 0;
+ digit = 0;
+ for (;;) {
+ if (isascii(temp) && isdigit(temp)) {
+ value = (value * 10) + temp - '0';
+ temp = *++cp;
+ digit = 1;
+ } else
+ break;
+ }
+
+ if (temp == '.') {
+ if ((end > bytes + 2) || (value > 255))
+ return 0;
+ *end++ = value;
+ temp = *++cp;
+ } else if (temp == ':') {
+ cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
+ return -1;
+ } else
+ break;
+ }
+
+ /* check for last characters */
+ if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
+ if (temp != '\\') {
+ if (temp != '/')
+ return 0;
+ else
+ (*cp = '\\'); /* switch the slash the expected way */
+ }
+ if (value > addr_class_max[end - bytes])
+ return 0;
+
+ address.s_addr = *((int *) bytes) | htonl(value);
+ *((int *)dst) = address.s_addr;
+ return 1; /* success */
+}
+
+/*****************************************************************************
+convert a NT status code to a dos class/code
+ *****************************************************************************/
+/* NT status -> dos error map */
+static const struct {
+ __u8 dos_class;
+ __u16 dos_code;
+ __u32 ntstatus;
+} ntstatus_to_dos_map[] = {
+ {
+ ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
+ ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
+ ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
+ ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
+ ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
+ ERRDOS, 87, NT_STATUS_INVALID_CID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
+ ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
+ ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
+ ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
+ ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
+ ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
+ during the session setup } */
+ {
+ ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
+ ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
+ ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
+ ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
+ ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
+ ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
+ during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
+ ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
+ ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
+ ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
+ ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
+ ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */
+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
+ ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
+ ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
+ ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
+ ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
+ ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
+ ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
+ ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
+ ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
+ ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
+ ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
+ ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
+ ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
+ ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
+ ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
+ ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
+ ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED}, {
+ ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
+ ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
+ ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
+ ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
+ ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
+ ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
+ ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
+ during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
+ during the session setup } */
+ {
+ ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
+ ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
+ ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
+ ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
+ ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
+ ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
+ ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
+ ERRDOS, 112, NT_STATUS_DISK_FULL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
+ ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
+ ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
+ ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
+ ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
+ ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
+ ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
+ during the session setup } */
+ {
+ ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
+ ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
+ ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
+ ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
+ ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
+ ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
+ ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
+ ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
+ ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
+ ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
+ ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
+ ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
+ ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
+ ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
+ ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
+ ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
+ ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
+ ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
+ ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
+ ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
+ ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
+ ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
+ ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
+ ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
+ ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
+ ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
+ ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
+ ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
+ ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
+ ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
+ ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
+ ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
+ ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
+ ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
+ ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
+ ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
+ ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
+ ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
+ ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
+ ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
+ ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
+ ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
+ ERRDOS, 203, 0xc0000100}, {
+ ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
+ ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
+ ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
+ ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
+ ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
+ ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
+ ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
+ ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
+ ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
+ ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
+ ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
+ ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
+ ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
+ ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
+ ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
+ ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
+ ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
+ ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
+ ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
+ ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
+ ERRHRD, ERRgeneral, 0xc000016e}, {
+ ERRHRD, ERRgeneral, 0xc000016f}, {
+ ERRHRD, ERRgeneral, 0xc0000170}, {
+ ERRHRD, ERRgeneral, 0xc0000171}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
+ ERRHRD, ERRgeneral, 0xc0000179}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
+ ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
+ ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
+ ERRDOS, 19, NT_STATUS_TOO_LATE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
+ during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
+ ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
+ ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
+ during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
+ ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
+ ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
+ ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
+ ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
+ ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
+ ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
+ ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
+ ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
+ ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
+ ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
+ ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
+ ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
+ ERRHRD, ERRgeneral, 0xc000024a}, {
+ ERRHRD, ERRgeneral, 0xc000024b}, {
+ ERRHRD, ERRgeneral, 0xc000024c}, {
+ ERRHRD, ERRgeneral, 0xc000024d}, {
+ ERRHRD, ERRgeneral, 0xc000024e}, {
+ ERRHRD, ERRgeneral, 0xc000024f}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
+ ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
+ ERRHRD, ERRgeneral, 0xc000025d}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
+ ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
+ ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
+ ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
+ ERRDOS, 21, 0xc000026e}, {
+ ERRDOS, 161, 0xc0000281}, {
+ ERRDOS, ERRnoaccess, 0xc000028a}, {
+ ERRDOS, ERRnoaccess, 0xc000028b}, {
+ ERRHRD, ERRgeneral, 0xc000028c}, {
+ ERRDOS, ERRnoaccess, 0xc000028d}, {
+ ERRDOS, ERRnoaccess, 0xc000028e}, {
+ ERRDOS, ERRnoaccess, 0xc000028f}, {
+ ERRDOS, ERRnoaccess, 0xc0000290}, {
+ERRDOS, ERRbadfunc, 0xc000029c},};
+
+/*****************************************************************************
+ Print an error message from the status code
+ *****************************************************************************/
+static void
+cifs_print_status(__u32 status_code)
+{
+ int idx = 0;
+
+ while (nt_errs[idx].nt_errstr != NULL) {
+ if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
+ (status_code & 0xFFFFFF)) {
+ printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
+ status_code,nt_errs[idx].nt_errstr);
+ }
+ idx++;
+ }
+ return;
+}
+
+
+static void
+ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
+{
+ int i;
+ if (ntstatus == 0) {
+ *eclass = 0;
+ *ecode = 0;
+ return;
+ }
+ for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
+ if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
+ *eclass = ntstatus_to_dos_map[i].dos_class;
+ *ecode = ntstatus_to_dos_map[i].dos_code;
+ return;
+ }
+ }
+ *eclass = ERRHRD;
+ *ecode = ERRgeneral;
+}
+
+int
+map_smb_to_linux_error(struct smb_hdr *smb)
+{
+ unsigned int i;
+ int rc = -EIO; /* if transport error smb error may not be set */
+ __u8 smberrclass;
+ __u16 smberrcode;
+
+ /* BB if NT Status codes - map NT BB */
+
+ /* old style smb error codes */
+ if (smb->Status.CifsError == 0)
+ return 0;
+
+ if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
+ /* translate the newer STATUS codes to old style errors and then to POSIX errors */
+ smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
+ if(cifsFYI)
+ cifs_print_status(smb->Status.CifsError);
+ ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
+ &smberrcode);
+ } else {
+ smberrclass = smb->Status.DosError.ErrorClass;
+ smb->Status.DosError.Error =
+ le16_to_cpu(smb->Status.DosError.Error);
+ smberrcode = smb->Status.DosError.Error;
+ }
+
+ /* old style errors */
+
+ /* DOS class smb error codes - map DOS */
+ if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
+ for (i = 0;
+ i <
+ sizeof (mapping_table_ERRDOS) /
+ sizeof (struct smb_to_posix_error); i++) {
+ if (mapping_table_ERRDOS[i].smb_err == 0)
+ break;
+ else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
+ rc = mapping_table_ERRDOS[i].posix_code;
+ break;
+ }
+ /* else try the next error mapping one to see if it will match */
+ }
+ } else if (smberrclass == ERRSRV) { /* server class of error codes */
+ for (i = 0;
+ i <
+ sizeof (mapping_table_ERRSRV) /
+ sizeof (struct smb_to_posix_error); i++) {
+ if (mapping_table_ERRSRV[i].smb_err == 0)
+ break;
+ else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
+ rc = mapping_table_ERRSRV[i].posix_code;
+ break;
+ }
+ /* else try the next error mapping one to see if it will match */
+ }
+ }
+ /* else ERRHRD class errors or junk - return EIO */
+
+ cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
+
+ /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
+
+ return rc;
+}
+
+/*
+ * calculate the size of the SMB message based on the fixed header
+ * portion, the number of word parameters and the data portion of the message
+ */
+unsigned int
+smbCalcSize(struct smb_hdr *ptr)
+{
+ return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+ BCC(ptr));
+}
+
+/* The following are taken from fs/ntfs/util.c */
+
+#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
+
+ /*
+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
+ * into Unix UTC (based 1970-01-01, in seconds).
+ */
+time_t
+cifs_NTtimeToUnix(__u64 ntutc)
+{
+ /* BB what about the timezone? BB */
+
+ /* Subtract the NTFS time offset, then convert to 1s intervals. */
+ u64 t;
+
+ t = ntutc - NTFS_TIME_OFFSET;
+ do_div(t, 10000000);
+ return (time_t)t;
+}
+
+/* Convert the Unix UTC into NT UTC. */
+__u64
+cifs_UnixTimeToNT(time_t t)
+{
+ __u64 dce_time;
+ /* Convert to 100ns intervals and then add the NTFS time offset. */
+ dce_time = (__u64) t * 10000000;
+ dce_time += NTFS_TIME_OFFSET;
+ return dce_time;
+}
diff --git a/release/src/linux/linux/fs/cifs/nterr.c b/release/src/linux/linux/fs/cifs/nterr.c
new file mode 100644
index 00000000..4da50cd3
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/nterr.c
@@ -0,0 +1,687 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * RPC Pipe client / server routines
+ * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* NT error codes - see nterr.h */
+#include <linux/types.h>
+#include <linux/fs.h>
+#include "nterr.h"
+
+const struct nt_err_code_struct nt_errs[] = {
+ {"NT_STATUS_OK", NT_STATUS_OK},
+ {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
+ {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
+ {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
+ {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
+ {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
+ {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
+ {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
+ {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
+ {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
+ {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
+ {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
+ {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
+ {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
+ {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
+ {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
+ {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
+ {"NT_STATUS_INVALID_DEVICE_REQUEST",
+ NT_STATUS_INVALID_DEVICE_REQUEST},
+ {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
+ {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
+ {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
+ {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
+ {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
+ {"NT_STATUS_MORE_PROCESSING_REQUIRED",
+ NT_STATUS_MORE_PROCESSING_REQUIRED},
+ {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
+ {"NT_STATUS_CONFLICTING_ADDRESSES",
+ NT_STATUS_CONFLICTING_ADDRESSES},
+ {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
+ {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
+ {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
+ NT_STATUS_UNABLE_TO_DELETE_SECTION},
+ {"NT_STATUS_INVALID_SYSTEM_SERVICE",
+ NT_STATUS_INVALID_SYSTEM_SERVICE},
+ {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
+ {"NT_STATUS_INVALID_LOCK_SEQUENCE",
+ NT_STATUS_INVALID_LOCK_SEQUENCE},
+ {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
+ {"NT_STATUS_INVALID_FILE_FOR_SECTION",
+ NT_STATUS_INVALID_FILE_FOR_SECTION},
+ {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
+ {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
+ {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
+ {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
+ {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
+ NT_STATUS_NONCONTINUABLE_EXCEPTION},
+ {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
+ {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
+ {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
+ {"NT_STATUS_INVALID_UNWIND_TARGET",
+ NT_STATUS_INVALID_UNWIND_TARGET},
+ {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
+ {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
+ {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
+ NT_STATUS_UNABLE_TO_DECOMMIT_VM},
+ {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
+ {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
+ NT_STATUS_INVALID_PORT_ATTRIBUTES},
+ {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
+ NT_STATUS_PORT_MESSAGE_TOO_LONG},
+ {"NT_STATUS_INVALID_PARAMETER_MIX",
+ NT_STATUS_INVALID_PARAMETER_MIX},
+ {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
+ {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
+ {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
+ {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
+ NT_STATUS_OBJECT_NAME_NOT_FOUND},
+ {"NT_STATUS_OBJECT_NAME_COLLISION",
+ NT_STATUS_OBJECT_NAME_COLLISION},
+ {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
+ {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
+ {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
+ NT_STATUS_DEVICE_ALREADY_ATTACHED},
+ {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
+ {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
+ NT_STATUS_OBJECT_PATH_NOT_FOUND},
+ {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
+ NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
+ {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
+ {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
+ {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
+ {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
+ {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
+ {"NT_STATUS_PORT_CONNECTION_REFUSED",
+ NT_STATUS_PORT_CONNECTION_REFUSED},
+ {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
+ {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
+ {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
+ {"NT_STATUS_INVALID_PAGE_PROTECTION",
+ NT_STATUS_INVALID_PAGE_PROTECTION},
+ {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
+ {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
+ NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
+ {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
+ {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
+ {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
+ NT_STATUS_SUSPEND_COUNT_EXCEEDED},
+ {"NT_STATUS_THREAD_IS_TERMINATING",
+ NT_STATUS_THREAD_IS_TERMINATING},
+ {"NT_STATUS_BAD_WORKING_SET_LIMIT",
+ NT_STATUS_BAD_WORKING_SET_LIMIT},
+ {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
+ NT_STATUS_INCOMPATIBLE_FILE_MAP},
+ {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
+ {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
+ {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
+ {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
+ {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
+ {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
+ {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
+ {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
+ {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
+ {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
+ NT_STATUS_CTL_FILE_NOT_SUPPORTED},
+ {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
+ {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
+ {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
+ {"NT_STATUS_INVALID_PRIMARY_GROUP",
+ NT_STATUS_INVALID_PRIMARY_GROUP},
+ {"NT_STATUS_NO_IMPERSONATION_TOKEN",
+ NT_STATUS_NO_IMPERSONATION_TOKEN},
+ {"NT_STATUS_CANT_DISABLE_MANDATORY",
+ NT_STATUS_CANT_DISABLE_MANDATORY},
+ {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
+ {"NT_STATUS_NO_SUCH_LOGON_SESSION",
+ NT_STATUS_NO_SUCH_LOGON_SESSION},
+ {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
+ {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
+ {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
+ {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
+ {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
+ {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
+ {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
+ {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
+ {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
+ {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
+ {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
+ {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
+ {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
+ {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
+ {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
+ {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
+ {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
+ {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
+ {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
+ {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
+ {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
+ NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
+ {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
+ {"NT_STATUS_INVALID_SUB_AUTHORITY",
+ NT_STATUS_INVALID_SUB_AUTHORITY},
+ {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
+ {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
+ {"NT_STATUS_INVALID_SECURITY_DESCR",
+ NT_STATUS_INVALID_SECURITY_DESCR},
+ {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
+ {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
+ {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
+ {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
+ {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
+ {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
+ {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
+ {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
+ {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
+ NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
+ {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
+ {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
+ {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
+ {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
+ {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
+ {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
+ {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
+ NT_STATUS_RESOURCE_DATA_NOT_FOUND},
+ {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
+ NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
+ {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
+ NT_STATUS_RESOURCE_NAME_NOT_FOUND},
+ {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
+ NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
+ {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
+ NT_STATUS_FLOAT_DENORMAL_OPERAND},
+ {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
+ {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
+ {"NT_STATUS_FLOAT_INVALID_OPERATION",
+ NT_STATUS_FLOAT_INVALID_OPERATION},
+ {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
+ {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
+ {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
+ {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
+ NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
+ {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
+ {"NT_STATUS_PRIVILEGED_INSTRUCTION",
+ NT_STATUS_PRIVILEGED_INSTRUCTION},
+ {"NT_STATUS_TOO_MANY_PAGING_FILES",
+ NT_STATUS_TOO_MANY_PAGING_FILES},
+ {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
+ {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
+ NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
+ {"NT_STATUS_INSUFFICIENT_RESOURCES",
+ NT_STATUS_INSUFFICIENT_RESOURCES},
+ {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
+ {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
+ {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
+ {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
+ {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
+ {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
+ {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
+ {"NT_STATUS_MEDIA_WRITE_PROTECTED",
+ NT_STATUS_MEDIA_WRITE_PROTECTED},
+ {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
+ {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
+ NT_STATUS_INVALID_GROUP_ATTRIBUTES},
+ {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
+ NT_STATUS_BAD_IMPERSONATION_LEVEL},
+ {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
+ {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
+ {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
+ {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
+ NT_STATUS_BAD_MASTER_BOOT_RECORD},
+ {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
+ NT_STATUS_INSTRUCTION_MISALIGNMENT},
+ {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
+ NT_STATUS_INSTANCE_NOT_AVAILABLE},
+ {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
+ {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
+ {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
+ {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
+ {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
+ {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
+ {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
+ {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
+ {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
+ {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
+ {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
+ {"NT_STATUS_PROFILING_NOT_STARTED",
+ NT_STATUS_PROFILING_NOT_STARTED},
+ {"NT_STATUS_PROFILING_NOT_STOPPED",
+ NT_STATUS_PROFILING_NOT_STOPPED},
+ {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
+ {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
+ {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
+ {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
+ {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
+ {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
+ {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
+ {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
+ NT_STATUS_DEVICE_DOES_NOT_EXIST},
+ {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
+ {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
+ NT_STATUS_ADAPTER_HARDWARE_ERROR},
+ {"NT_STATUS_INVALID_NETWORK_RESPONSE",
+ NT_STATUS_INVALID_NETWORK_RESPONSE},
+ {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
+ NT_STATUS_UNEXPECTED_NETWORK_ERROR},
+ {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
+ {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
+ {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
+ {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
+ {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
+ {"NT_STATUS_NETWORK_ACCESS_DENIED",
+ NT_STATUS_NETWORK_ACCESS_DENIED},
+ {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
+ {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
+ {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
+ {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
+ {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
+ {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
+ {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
+ {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
+ {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
+ {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
+ {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
+ {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
+ NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
+ {"NT_STATUS_NO_SECURITY_ON_OBJECT",
+ NT_STATUS_NO_SECURITY_ON_OBJECT},
+ {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
+ {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
+ {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
+ NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
+ {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
+ {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
+ {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
+ {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
+ {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
+ {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
+ {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
+ NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
+ {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
+ {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
+ NT_STATUS_INVALID_OPLOCK_PROTOCOL},
+ {"NT_STATUS_INTERNAL_DB_CORRUPTION",
+ NT_STATUS_INTERNAL_DB_CORRUPTION},
+ {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
+ {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
+ {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
+ NT_STATUS_BAD_DESCRIPTOR_FORMAT},
+ {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
+ {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
+ {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
+ NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
+ {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
+ NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
+ {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
+ NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
+ {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
+ {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
+ {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
+ {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
+ {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
+ {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
+ {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
+ {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
+ {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
+ {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
+ {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
+ {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
+ {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
+ {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
+ {"NT_STATUS_REDIRECTOR_NOT_STARTED",
+ NT_STATUS_REDIRECTOR_NOT_STARTED},
+ {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
+ {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
+ {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
+ {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
+ {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
+ {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
+ {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
+ {"NT_STATUS_BAD_LOGON_SESSION_STATE",
+ NT_STATUS_BAD_LOGON_SESSION_STATE},
+ {"NT_STATUS_LOGON_SESSION_COLLISION",
+ NT_STATUS_LOGON_SESSION_COLLISION},
+ {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
+ {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
+ {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
+ {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
+ {"NT_STATUS_PROCESS_IS_TERMINATING",
+ NT_STATUS_PROCESS_IS_TERMINATING},
+ {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
+ {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
+ {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
+ {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
+ {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
+ {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
+ {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
+ NT_STATUS_ABIOS_LID_ALREADY_OWNED},
+ {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
+ {"NT_STATUS_ABIOS_INVALID_COMMAND",
+ NT_STATUS_ABIOS_INVALID_COMMAND},
+ {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
+ {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
+ NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
+ {"NT_STATUS_ABIOS_INVALID_SELECTOR",
+ NT_STATUS_ABIOS_INVALID_SELECTOR},
+ {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
+ {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
+ {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
+ {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
+ NT_STATUS_INVALID_LDT_DESCRIPTOR},
+ {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
+ NT_STATUS_INVALID_IMAGE_NE_FORMAT},
+ {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
+ {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
+ {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
+ NT_STATUS_MAPPED_FILE_SIZE_ZERO},
+ {"NT_STATUS_TOO_MANY_OPENED_FILES",
+ NT_STATUS_TOO_MANY_OPENED_FILES},
+ {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
+ {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
+ {"NT_STATUS_INVALID_COMPUTER_NAME",
+ NT_STATUS_INVALID_COMPUTER_NAME},
+ {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
+ {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
+ {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
+ {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
+ {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
+ NT_STATUS_MEMBERS_PRIMARY_GROUP},
+ {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
+ {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
+ {"NT_STATUS_THREAD_NOT_IN_PROCESS",
+ NT_STATUS_THREAD_NOT_IN_PROCESS},
+ {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
+ {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
+ NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
+ {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
+ {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
+ NT_STATUS_INVALID_IMAGE_LE_FORMAT},
+ {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
+ {"NT_STATUS_INVALID_IMAGE_PROTECT",
+ NT_STATUS_INVALID_IMAGE_PROTECT},
+ {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
+ {"NT_STATUS_LOGON_SERVER_CONFLICT",
+ NT_STATUS_LOGON_SERVER_CONFLICT},
+ {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
+ NT_STATUS_TIME_DIFFERENCE_AT_DC},
+ {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
+ NT_STATUS_SYNCHRONIZATION_REQUIRED},
+ {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
+ {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
+ {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
+ {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
+ {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
+ {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
+ {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
+ {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
+ {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
+ {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
+ {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
+ {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
+ {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
+ {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
+ {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
+ {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
+ {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
+ {"NT_STATUS_PAGEFILE_CREATE_FAILED",
+ NT_STATUS_PAGEFILE_CREATE_FAILED},
+ {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
+ {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
+ {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
+ {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
+ NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
+ {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
+ {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
+ {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
+ {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
+ {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
+ {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
+ NT_STATUS_SERIAL_NO_DEVICE_INITED},
+ {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
+ {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
+ {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
+ {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
+ {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
+ {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
+ {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
+ {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
+ {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
+ {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
+ {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
+ NT_STATUS_LOGON_TYPE_NOT_GRANTED},
+ {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
+ {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
+ NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
+ {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
+ NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
+ {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
+ {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
+ NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
+ {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
+ {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
+ {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
+ {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
+ {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
+ NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
+ {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
+ NT_STATUS_FLOPPY_WRONG_CYLINDER},
+ {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
+ {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
+ {"NT_STATUS_DISK_RECALIBRATE_FAILED",
+ NT_STATUS_DISK_RECALIBRATE_FAILED},
+ {"NT_STATUS_DISK_OPERATION_FAILED",
+ NT_STATUS_DISK_OPERATION_FAILED},
+ {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
+ {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
+ {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
+ {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
+ {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
+ {"NT_STATUS_DEVICE_NOT_PARTITIONED",
+ NT_STATUS_DEVICE_NOT_PARTITIONED},
+ {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
+ {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
+ NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
+ {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
+ {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
+ {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
+ {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
+ {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
+ {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
+ {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
+ {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
+ NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
+ {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
+ {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
+ NT_STATUS_CHILD_MUST_BE_VOLATILE},
+ {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
+ NT_STATUS_DEVICE_CONFIGURATION_ERROR},
+ {"NT_STATUS_DRIVER_INTERNAL_ERROR",
+ NT_STATUS_DRIVER_INTERNAL_ERROR},
+ {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
+ {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
+ {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
+ NT_STATUS_DEVICE_PROTOCOL_ERROR},
+ {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
+ {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
+ {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
+ {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
+ {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
+ {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
+ NT_STATUS_TRUSTED_DOMAIN_FAILURE},
+ {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
+ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
+ {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
+ NT_STATUS_EVENTLOG_FILE_CORRUPT},
+ {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
+ {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
+ {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
+ NT_STATUS_MUTANT_LIMIT_EXCEEDED},
+ {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
+ {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
+ {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
+ {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
+ NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
+ {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
+ {"NT_STATUS_EVENTLOG_FILE_CHANGED",
+ NT_STATUS_EVENTLOG_FILE_CHANGED},
+ {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
+ NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
+ {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
+ NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
+ {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
+ NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
+ {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
+ NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
+ {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
+ {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
+ {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
+ {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
+ NT_STATUS_RESOURCE_LANG_NOT_FOUND},
+ {"NT_STATUS_INSUFF_SERVER_RESOURCES",
+ NT_STATUS_INSUFF_SERVER_RESOURCES},
+ {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
+ {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
+ NT_STATUS_INVALID_ADDRESS_COMPONENT},
+ {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
+ NT_STATUS_INVALID_ADDRESS_WILDCARD},
+ {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
+ {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
+ NT_STATUS_ADDRESS_ALREADY_EXISTS},
+ {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
+ {"NT_STATUS_CONNECTION_DISCONNECTED",
+ NT_STATUS_CONNECTION_DISCONNECTED},
+ {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
+ {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
+ {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
+ {"NT_STATUS_TRANSACTION_TIMED_OUT",
+ NT_STATUS_TRANSACTION_TIMED_OUT},
+ {"NT_STATUS_TRANSACTION_NO_RELEASE",
+ NT_STATUS_TRANSACTION_NO_RELEASE},
+ {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
+ {"NT_STATUS_TRANSACTION_RESPONDED",
+ NT_STATUS_TRANSACTION_RESPONDED},
+ {"NT_STATUS_TRANSACTION_INVALID_ID",
+ NT_STATUS_TRANSACTION_INVALID_ID},
+ {"NT_STATUS_TRANSACTION_INVALID_TYPE",
+ NT_STATUS_TRANSACTION_INVALID_TYPE},
+ {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
+ {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
+ {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
+ NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
+ {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
+ {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
+ NT_STATUS_SYSTEM_PROCESS_TERMINATED},
+ {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
+ {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
+ NT_STATUS_NO_BROWSER_SERVERS_FOUND},
+ {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
+ {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
+ NT_STATUS_DRIVER_CANCEL_TIMEOUT},
+ {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
+ NT_STATUS_REPLY_MESSAGE_MISMATCH},
+ {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
+ {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
+ NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
+ {"NT_STATUS_LOST_WRITEBEHIND_DATA",
+ NT_STATUS_LOST_WRITEBEHIND_DATA},
+ {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
+ NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
+ {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
+ {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
+ {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
+ {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
+ {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
+ {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
+ {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
+ {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
+ {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
+ {"NT_STATUS_RETRY", NT_STATUS_RETRY},
+ {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
+ {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
+ {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
+ {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
+ {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
+ {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
+ NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
+ {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
+ {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
+ {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
+ {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
+ {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
+ NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
+ {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
+ NT_STATUS_ADDRESS_NOT_ASSOCIATED},
+ {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
+ {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
+ {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
+ {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
+ {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
+ {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
+ {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
+ {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
+ {"NT_STATUS_BAD_COMPRESSION_BUFFER",
+ NT_STATUS_BAD_COMPRESSION_BUFFER},
+ {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
+ {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
+ {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
+ NT_STATUS_TIMER_RESOLUTION_NOT_SET},
+ {"NT_STATUS_CONNECTION_COUNT_LIMIT",
+ NT_STATUS_CONNECTION_COUNT_LIMIT},
+ {"NT_STATUS_LOGIN_TIME_RESTRICTION",
+ NT_STATUS_LOGIN_TIME_RESTRICTION},
+ {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
+ NT_STATUS_LOGIN_WKSTA_RESTRICTION},
+ {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
+ {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
+ NT_STATUS_INSUFFICIENT_LOGON_INFO},
+ {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
+ {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
+ NT_STATUS_BAD_SERVICE_ENTRYPOINT},
+ {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
+ {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
+ {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
+ {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
+ {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
+ {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
+ {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
+ NT_STATUS_LICENSE_QUOTA_EXCEEDED},
+ {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
+ {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
+ {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
+ {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
+ {"NT_STATUS_UNSUPPORTED_COMPRESSION",
+ NT_STATUS_UNSUPPORTED_COMPRESSION},
+ {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
+ {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
+ NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
+ {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
+ NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
+ {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
+ NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
+ {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
+ {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
+ {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
+ NT_STATUS_QUOTA_LIST_INCONSISTENT},
+ {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
+ {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
+ {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
+ {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
+ {NULL, 0}
+};
diff --git a/release/src/linux/linux/fs/cifs/nterr.h b/release/src/linux/linux/fs/cifs/nterr.h
new file mode 100644
index 00000000..d2fb06c9
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/nterr.h
@@ -0,0 +1,556 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NT error code constants
+ Copyright (C) Andrew Tridgell 1992-2000
+ Copyright (C) John H Terpstra 1996-2000
+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+ Copyright (C) Paul Ashton 1998-2000
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+
+#ifndef _NTERR_H
+#define _NTERR_H
+
+struct nt_err_code_struct {
+ char *nt_errstr;
+ __u32 nt_errcode;
+};
+
+extern const struct nt_err_code_struct nt_errs[];
+
+/* Win32 Status codes. */
+
+#define STATUS_BUFFER_OVERFLOW 0x80000005
+#define STATUS_MORE_ENTRIES 0x0105
+#define ERROR_INVALID_PARAMETER 0x0057
+#define ERROR_INSUFFICIENT_BUFFER 0x007a
+#define STATUS_1804 0x070c
+#define STATUS_NOTIFY_ENUM_DIR 0x010c
+
+/* Win32 Error codes extracted using a loop in smbclient then printing a
+ netmon sniff to a file. */
+
+#define NT_STATUS_OK 0x0000
+#define STATUS_SOME_UNMAPPED 0x0107
+#define STATUS_BUFFER_OVERFLOW 0x80000005
+#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
+#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
+#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
+#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
+#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
+#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
+#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
+#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
+#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
+#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
+#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
+#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
+#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
+#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
+#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
+#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
+#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
+#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
+#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
+#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
+#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
+#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
+#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
+#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
+#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
+#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
+#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
+#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
+#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
+#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
+#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
+#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
+#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
+#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
+#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
+#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
+#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
+#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
+#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
+#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
+#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
+#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
+#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
+#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
+#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
+#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
+#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
+#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
+#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
+#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
+#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
+#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
+#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
+#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
+#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
+#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
+#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
+#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
+#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
+#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
+#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
+#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
+#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
+#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
+#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
+#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
+#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
+#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
+#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
+#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
+#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
+#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
+#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
+#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
+#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
+#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
+#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
+#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
+#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
+#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
+#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
+#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
+#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
+#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
+#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
+#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
+#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
+#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
+#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
+#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
+#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
+#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
+#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
+#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
+#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
+#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
+#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
+#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
+#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
+#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
+#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
+#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
+#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
+#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
+#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
+#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
+#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
+#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
+#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
+#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
+#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
+#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
+#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
+#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
+#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
+#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
+#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
+#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
+#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
+#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
+#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
+#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
+#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
+#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
+#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
+#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
+#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
+#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
+#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
+#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
+#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
+#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
+#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
+#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
+#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
+#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
+#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
+#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
+#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
+#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
+#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
+#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
+#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
+#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
+#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
+#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
+#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
+#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
+#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
+#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
+#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
+#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
+#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
+#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
+#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
+#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
+#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
+#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
+#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
+#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
+#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
+#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
+#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
+#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
+#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
+#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
+#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
+#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
+#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
+#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
+#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
+#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
+#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
+#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
+#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
+#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
+#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
+#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
+#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
+#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
+#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
+#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
+#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
+#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
+#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
+#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
+#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
+#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
+#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
+#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
+#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
+#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
+#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
+#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
+#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
+#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
+#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
+#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
+#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
+#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
+#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
+#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
+#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
+#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
+#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
+#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
+#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
+#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
+#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
+#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
+#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
+#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
+#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
+#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
+#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
+#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
+#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
+#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
+#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
+#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
+#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
+#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
+#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
+#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
+#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
+#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
+#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
+#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
+#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
+#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
+#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
+#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
+#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
+#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
+#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
+#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
+#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
+#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
+#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
+#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
+#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
+#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
+#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
+#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
+#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
+#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
+#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
+#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
+#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
+#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
+#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
+#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
+#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
+#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
+#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
+#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
+#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
+#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
+#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
+#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
+#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
+#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
+#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
+#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
+#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
+#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
+#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
+#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
+#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
+#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
+#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
+#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
+#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
+#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
+#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
+#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
+#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
+#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
+#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
+#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
+#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
+#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
+#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
+#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
+#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
+#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
+#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
+#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
+#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
+#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
+#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
+#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
+#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
+#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
+#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
+#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
+#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
+#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
+#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
+#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
+#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
+#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
+#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
+#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
+#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
+#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
+#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
+#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
+#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
+#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
+#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
+#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
+#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
+#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
+#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
+#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
+#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
+#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
+#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
+#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
+#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
+#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
+#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
+#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
+#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
+#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
+#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
+#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
+#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
+#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
+#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
+#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
+#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
+#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
+#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
+#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
+#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
+#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
+#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
+#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
+#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
+#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
+#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
+#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
+#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
+#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
+#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
+#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
+#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
+#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
+#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
+#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
+#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
+#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
+#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
+#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
+#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
+#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
+#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
+#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
+#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
+#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
+#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
+#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
+#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
+#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
+#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
+#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
+#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
+#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
+#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
+#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
+#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
+#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
+#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
+#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
+#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
+#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
+#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
+#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
+#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
+#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
+#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
+#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
+#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
+#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
+#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
+#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
+#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
+#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
+#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
+#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
+#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
+#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
+#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
+#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
+#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
+#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
+#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
+#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
+#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
+#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
+#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
+#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
+#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
+#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
+#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
+#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
+#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
+#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
+#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
+#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
+#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
+#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
+#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
+#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
+#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
+#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
+#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
+#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
+#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
+#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
+#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
+#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
+#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
+#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
+#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
+#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
+#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
+#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
+#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
+#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
+#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
+#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
+#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
+#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
+#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
+#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
+#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
+#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
+#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
+#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
+#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
+#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
+#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
+#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
+#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
+#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
+#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
+#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
+#define NT_STATUS_RETRY 0xC0000000 | 0x022d
+#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
+#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
+#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
+#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
+#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
+#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
+#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
+#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
+#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
+#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
+#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
+#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
+#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
+#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
+#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
+#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
+#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
+#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
+#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
+#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
+#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
+#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
+#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
+#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
+#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
+#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
+#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
+#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
+#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
+#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
+#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
+#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
+#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
+#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
+#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
+#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
+#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
+#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
+#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
+#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
+#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
+#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
+#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
+#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
+#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
+#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
+#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
+#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
+#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
+#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
+#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
+#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
+
+#endif /* _NTERR_H */
diff --git a/release/src/linux/linux/fs/cifs/ntlmssp.h b/release/src/linux/linux/fs/cifs/ntlmssp.h
new file mode 100644
index 00000000..f06edcbe
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/ntlmssp.h
@@ -0,0 +1,101 @@
+/*
+ * fs/cifs/ntlmssp.h
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#pragma pack(1)
+
+#define NTLMSSP_SIGNATURE "NTLMSSP"
+/* Message Types */
+#define NtLmNegotiate 1
+#define NtLmChallenge 2
+#define NtLmAuthenticate 3
+#define UnknownMessage 8
+
+/* Negotiate Flags */
+#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
+#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
+#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
+#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
+#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
+#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
+#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
+#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
+#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
+#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
+#define NTLMSSP_REQUEST_INIT_RESP 0x100000
+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
+#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
+#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
+#define NTLMSSP_NEGOTIATE_128 0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
+#define NTLMSSP_NEGOTIATE_56 0x80000000
+
+/* Although typedefs are not commonly used for structure definitions */
+/* in the Linux kernel, in this particular case they are useful */
+/* to more closely match the standards document for NTLMSSP from */
+/* OpenGroup and to make the code more closely match the standard in */
+/* appearance */
+
+typedef struct _SECURITY_BUFFER {
+ __u16 Length;
+ __u16 MaximumLength;
+ __u32 Buffer; /* offset to buffer */
+} SECURITY_BUFFER;
+
+typedef struct _NEGOTIATE_MESSAGE {
+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+ __u32 MessageType; /* 1 */
+ __u32 NegotiateFlags;
+ SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
+ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
+ char DomainString[0];
+ /* followed by WorkstationString */
+} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
+
+typedef struct _CHALLENGE_MESSAGE {
+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+ __u32 MessageType; /* 2 */
+ SECURITY_BUFFER TargetName;
+ __u32 NegotiateFlags;
+ __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
+ __u8 Reserved[8];
+ SECURITY_BUFFER TargetInfoArray;
+} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
+
+typedef struct _AUTHENTICATE_MESSAGE {
+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+ __u32 MessageType; /* 3 */
+ SECURITY_BUFFER LmChallengeResponse;
+ SECURITY_BUFFER NtChallengeResponse;
+ SECURITY_BUFFER DomainName;
+ SECURITY_BUFFER UserName;
+ SECURITY_BUFFER WorkstationName;
+ SECURITY_BUFFER SessionKey;
+ __u32 NegotiateFlags;
+ char UserString[0];
+} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+
+#pragma pack() /* resume default structure packing */
diff --git a/release/src/linux/linux/fs/cifs/rfc1002pdu.h b/release/src/linux/linux/fs/cifs/rfc1002pdu.h
new file mode 100644
index 00000000..806c0ed0
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/rfc1002pdu.h
@@ -0,0 +1,79 @@
+/*
+ * fs/cifs/rfc1002pdu.h
+ *
+ * Protocol Data Unit definitions for RFC 1001/1002 support
+ *
+ * Copyright (c) International Business Machines Corp., 2004
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#pragma pack(1)
+
+/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
+
+ /* RFC 1002 session packet types */
+#define RFC1002_SESSION_MESASAGE 0x00
+#define RFC1002_SESSION_REQUEST 0x81
+#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
+#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
+#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
+#define RFC1002_SESSION_KEEP_ALIVE 0x85
+
+ /* RFC 1002 flags (only one defined */
+#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
+
+struct rfc1002_session_packet {
+ __u8 type;
+ __u8 flags;
+ __u16 length;
+ union {
+ struct {
+ __u8 called_len;
+ __u8 called_name[32];
+ __u8 scope1; /* null */
+ __u8 calling_len;
+ __u8 calling_name[32];
+ __u8 scope2; /* null */
+ } session_req;
+ struct {
+ __u32 retarget_ip_addr;
+ __u16 port;
+ } retarget_resp;
+ __u8 neg_ses_resp_error_code;
+ /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
+ SESSION_KEEP_ALIVE packet also does not include a trailer.
+ Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
+ } trailer;
+};
+
+/* Negative Session Response error codes */
+#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
+#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
+#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
+#define RFC1002_INSUFFICIENT_RESOURCE 0x83
+#define RFC1002_UNSPECIFIED_ERROR 0x8F
+
+/* RFC 1002 Datagram service packets are not defined here as they
+are not needed for the network filesystem client unless we plan on
+implementing broadcast resolution of the server ip address (from
+server netbios name). Currently server names are resolved only via DNS
+(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
+
+#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
+
+#pragma pack() /* resume default structure packing */
+
diff --git a/release/src/linux/linux/fs/cifs/smbdes.c b/release/src/linux/linux/fs/cifs/smbdes.c
new file mode 100644
index 00000000..4d765f73
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/smbdes.c
@@ -0,0 +1,408 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+
+ a partial implementation of DES designed for use in the
+ SMB authentication protocol
+
+ Copyright (C) Andrew Tridgell 1998
+ Modified by Steve French (sfrench@us.ibm.com) 2002,2004
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* NOTES:
+
+ This code makes no attempt to be fast! In fact, it is a very
+ slow implementation
+
+ This code is NOT a complete DES implementation. It implements only
+ the minimum necessary for SMB authentication, as used by all SMB
+ products (including every copy of Microsoft Windows95 ever sold)
+
+ In particular, it can only do a unchained forward DES pass. This
+ means it is not possible to use this code for encryption/decryption
+ of data, instead it is only useful as a "hash" algorithm.
+
+ There is no entry point into this code that allows normal DES operation.
+
+ I believe this means that this code does not come under ITAR
+ regulations but this is NOT a legal opinion. If you are concerned
+ about the applicability of ITAR regulations to this code then you
+ should confirm it for yourself (and maybe let me know if you come
+ up with a different answer to the one above)
+*/
+#include <linux/slab.h>
+#define uchar unsigned char
+
+static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+};
+
+static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7
+};
+
+static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1
+};
+
+static uchar perm5[32] = { 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25
+};
+
+static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25
+};
+
+static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
+
+static uchar sbox[8][4][16] = {
+ {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
+
+ {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
+
+ {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
+
+ {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
+
+ {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
+
+ {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
+
+ {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
+
+ {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
+};
+
+static void
+permute(char *out, char *in, uchar * p, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ out[i] = in[p[i] - 1];
+}
+
+static void
+lshift(char *d, int count, int n)
+{
+ char out[64];
+ int i;
+ for (i = 0; i < n; i++)
+ out[i] = d[(i + count) % n];
+ for (i = 0; i < n; i++)
+ d[i] = out[i];
+}
+
+static void
+concat(char *out, char *in1, char *in2, int l1, int l2)
+{
+ while (l1--)
+ *out++ = *in1++;
+ while (l2--)
+ *out++ = *in2++;
+}
+
+static void
+xor(char *out, char *in1, char *in2, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ out[i] = in1[i] ^ in2[i];
+}
+
+static void
+dohash(char *out, char *in, char *key, int forw)
+{
+ int i, j, k;
+ char *pk1;
+ char c[28];
+ char d[28];
+ char *cd;
+ char ki[16][48];
+ char *pd1;
+ char l[32], r[32];
+ char *rl;
+
+ /* Have to reduce stack usage */
+ pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
+ if(pk1 == NULL)
+ return;
+
+ cd = pk1 + 56;
+ pd1= cd + 56;
+ rl = pd1 + 64;
+
+ permute(pk1, key, perm1, 56);
+
+ for (i = 0; i < 28; i++)
+ c[i] = pk1[i];
+ for (i = 0; i < 28; i++)
+ d[i] = pk1[i + 28];
+
+ for (i = 0; i < 16; i++) {
+ lshift(c, sc[i], 28);
+ lshift(d, sc[i], 28);
+
+ concat(cd, c, d, 28, 28);
+ permute(ki[i], cd, perm2, 48);
+ }
+
+ permute(pd1, in, perm3, 64);
+
+ for (j = 0; j < 32; j++) {
+ l[j] = pd1[j];
+ r[j] = pd1[j + 32];
+ }
+
+ for (i = 0; i < 16; i++) {
+ char *er; /* er[48] */
+ char *erk; /* erk[48] */
+ char b[8][6];
+ char *cb; /* cb[32] */
+ char *pcb; /* pcb[32] */
+ char *r2; /* r2[32] */
+
+ er = kmalloc(48+48+32+32+32, GFP_KERNEL);
+ if(er == NULL) {
+ kfree(pk1);
+ return;
+ }
+ erk = er+48;
+ cb = erk+48;
+ pcb = cb+32;
+ r2 = pcb+32;
+
+ permute(er, r, perm4, 48);
+
+ xor(erk, er, ki[forw ? i : 15 - i], 48);
+
+ for (j = 0; j < 8; j++)
+ for (k = 0; k < 6; k++)
+ b[j][k] = erk[j * 6 + k];
+
+ for (j = 0; j < 8; j++) {
+ int m, n;
+ m = (b[j][0] << 1) | b[j][5];
+
+ n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
+ 1) | b[j][4];
+
+ for (k = 0; k < 4; k++)
+ b[j][k] =
+ (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
+ }
+
+ for (j = 0; j < 8; j++)
+ for (k = 0; k < 4; k++)
+ cb[j * 4 + k] = b[j][k];
+ permute(pcb, cb, perm5, 32);
+
+ xor(r2, l, pcb, 32);
+
+ for (j = 0; j < 32; j++)
+ l[j] = r[j];
+
+ for (j = 0; j < 32; j++)
+ r[j] = r2[j];
+
+ kfree(er);
+ }
+
+ concat(rl, r, l, 32, 32);
+
+ permute(out, rl, perm6, 64);
+ kfree(pk1);
+}
+
+static void
+str_to_key(unsigned char *str, unsigned char *key)
+{
+ int i;
+
+ key[0] = str[0] >> 1;
+ key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
+ key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
+ key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
+ key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
+ key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
+ key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
+ key[7] = str[6] & 0x7F;
+ for (i = 0; i < 8; i++) {
+ key[i] = (key[i] << 1);
+ }
+}
+
+static void
+smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
+{
+ int i;
+ char *outb; /* outb[64] */
+ char *inb; /* inb[64] */
+ char *keyb; /* keyb[64] */
+ unsigned char key2[8];
+
+ outb = kmalloc(64 * 3,GFP_KERNEL);
+ if(outb == NULL)
+ return;
+
+ inb = outb + 64;
+ keyb = inb + 64;
+
+ str_to_key(key, key2);
+
+ for (i = 0; i < 64; i++) {
+ inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
+ keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
+ outb[i] = 0;
+ }
+
+ dohash(outb, inb, keyb, forw);
+
+ for (i = 0; i < 8; i++) {
+ out[i] = 0;
+ }
+
+ for (i = 0; i < 64; i++) {
+ if (outb[i])
+ out[i / 8] |= (1 << (7 - (i % 8)));
+ }
+ kfree(outb);
+}
+
+void
+E_P16(unsigned char *p14, unsigned char *p16)
+{
+ unsigned char sp8[8] =
+ { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
+ smbhash(p16, sp8, p14, 1);
+ smbhash(p16 + 8, sp8, p14 + 7, 1);
+}
+
+void
+E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
+{
+ smbhash(p24, c8, p21, 1);
+ smbhash(p24 + 8, c8, p21 + 7, 1);
+ smbhash(p24 + 16, c8, p21 + 14, 1);
+}
+
+void
+D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
+{
+ smbhash(out, in, p14, 0);
+ smbhash(out + 8, in + 8, p14 + 7, 0);
+}
+
+void
+E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
+{
+ smbhash(out, in, p14, 1);
+ smbhash(out + 8, in + 8, p14 + 7, 1);
+}
+
+void
+cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+ unsigned char buf[8];
+
+ smbhash(buf, in, key, 1);
+ smbhash(out, buf, key + 9, 1);
+}
+
+void
+cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+ unsigned char buf[8];
+ static unsigned char key2[8];
+
+ smbhash(buf, in, key, 1);
+ key2[0] = key[7];
+ smbhash(out, buf, key2, 1);
+}
+
+void
+cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
+{
+ static unsigned char key2[8];
+
+ smbhash(out, in, key, forw);
+ key2[0] = key[7];
+ smbhash(out + 8, in + 8, key2, forw);
+}
diff --git a/release/src/linux/linux/fs/cifs/smbencrypt.c b/release/src/linux/linux/fs/cifs/smbencrypt.c
new file mode 100644
index 00000000..18329601
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/smbencrypt.c
@@ -0,0 +1,295 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ SMB parameters and setup
+ Copyright (C) Andrew Tridgell 1992-2000
+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+ Modified by Jeremy Allison 1995.
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include "cifs_unicode.h"
+#include "cifspdu.h"
+#include "md5.h"
+#include "cifs_debug.h"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/* following came from the other byteorder.h to avoid include conflicts */
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
+
+/*The following definitions come from lib/md4.c */
+
+void mdfour(unsigned char *out, unsigned char *in, int n);
+
+/*The following definitions come from libsmb/smbdes.c */
+
+void E_P16(unsigned char *p14, unsigned char *p16);
+void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
+void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
+void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
+void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
+void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
+void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
+ int forw);
+
+/*The following definitions come from libsmb/smbencrypt.c */
+
+void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
+void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
+void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
+ unsigned char p24[24]);
+void NTLMSSPOWFencrypt(unsigned char passwd[8],
+ unsigned char *ntlmchalresp, unsigned char p24[24]);
+void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
+int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
+ int new_pwrd_size, __u32 * new_pw_len);
+
+/*
+ This implements the X/Open SMB password encryption
+ It takes a password, a 8 byte "crypt key" and puts 24 bytes of
+ encrypted password into p24 */
+/* Note that password must be uppercased and null terminated */
+void
+SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
+{
+ unsigned char p14[15], p21[21];
+
+ memset(p21, '\0', 21);
+ memset(p14, '\0', 14);
+ strncpy((char *) p14, (char *) passwd, 14);
+
+/* strupper((char *)p14); *//* BB at least uppercase the easy range */
+ E_P16(p14, p21);
+
+ SMBOWFencrypt(p21, c8, p24);
+
+ memset(p14,0,15);
+ memset(p21,0,21);
+}
+
+/* Routines for Windows NT MD4 Hash functions. */
+static int
+_my_wcslen(__u16 * str)
+{
+ int len = 0;
+ while (*str++ != 0)
+ len++;
+ return len;
+}
+
+/*
+ * Convert a string into an NT UNICODE string.
+ * Note that regardless of processor type
+ * this must be in intel (little-endian)
+ * format.
+ */
+
+static int
+_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
+{ /* not a very good conversion routine - change/fix */
+ int i;
+ __u16 val;
+
+ for (i = 0; i < len; i++) {
+ val = *src;
+ SSVAL(dst, 0, val);
+ dst++;
+ src++;
+ if (val == 0)
+ break;
+ }
+ return i;
+}
+
+/*
+ * Creates the MD4 Hash of the users password in NT UNICODE.
+ */
+
+void
+E_md4hash(const unsigned char *passwd, unsigned char *p16)
+{
+ int len;
+ __u16 wpwd[129];
+
+ /* Password cannot be longer than 128 characters */
+ if(passwd) {
+ len = strlen((char *) passwd);
+ if (len > 128) {
+ len = 128;
+ }
+ /* Password must be converted to NT unicode */
+ _my_mbstowcs(wpwd, passwd, len);
+ } else
+ len = 0;
+
+ wpwd[len] = 0; /* Ensure string is null terminated */
+ /* Calculate length in bytes */
+ len = _my_wcslen(wpwd) * sizeof (__u16);
+
+ mdfour(p16, (unsigned char *) wpwd, len);
+ memset(wpwd,0,129 * 2);
+}
+
+/* Does both the NT and LM owfs of a user's password */
+void
+nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
+{
+ char passwd[514];
+
+ memset(passwd, '\0', 514);
+ if (strlen(pwd) < 513)
+ strcpy(passwd, pwd);
+ else
+ memcpy(passwd, pwd, 512);
+ /* Calculate the MD4 hash (NT compatible) of the password */
+ memset(nt_p16, '\0', 16);
+ E_md4hash(passwd, nt_p16);
+
+ /* Mangle the passwords into Lanman format */
+ passwd[14] = '\0';
+/* strupper(passwd); */
+
+ /* Calculate the SMB (lanman) hash functions of the password */
+
+ memset(p16, '\0', 16);
+ E_P16((unsigned char *) passwd, (unsigned char *) p16);
+
+ /* clear out local copy of user's password (just being paranoid). */
+ memset(passwd, '\0', sizeof (passwd));
+}
+
+/* Does the NTLMv2 owfs of a user's password */
+void
+ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
+ const char *domain_n, unsigned char kr_buf[16],
+ const struct nls_table *nls_codepage)
+{
+ wchar_t * user_u;
+ wchar_t * dom_u;
+ int user_l, domain_l;
+ struct HMACMD5Context ctx;
+
+ /* might as well do one alloc to hold both (user_u and dom_u) */
+ user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
+ if(user_u == NULL)
+ return;
+ dom_u = user_u + 1024;
+
+ /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+ push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
+
+ /* BB user and domain may need to be uppercased */
+ user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
+ domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
+
+ user_l++; /* trailing null */
+ domain_l++;
+
+ hmac_md5_init_limK_to_64(owf, 16, &ctx);
+ hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
+ hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
+ hmac_md5_final(kr_buf, &ctx);
+
+ kfree(user_u);
+}
+
+/* Does the des encryption from the NT or LM MD4 hash. */
+void
+SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
+ unsigned char p24[24])
+{
+ unsigned char p21[21];
+
+ memset(p21, '\0', 21);
+
+ memcpy(p21, passwd, 16);
+ E_P24(p21, c8, p24);
+}
+
+/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
+void
+NTLMSSPOWFencrypt(unsigned char passwd[8],
+ unsigned char *ntlmchalresp, unsigned char p24[24])
+{
+ unsigned char p21[21];
+
+ memset(p21, '\0', 21);
+ memcpy(p21, passwd, 8);
+ memset(p21 + 8, 0xbd, 8);
+
+ E_P24(p21, ntlmchalresp, p24);
+}
+
+/* Does the NT MD4 hash then des encryption. */
+
+void
+SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
+{
+ unsigned char p21[21];
+
+ memset(p21, '\0', 21);
+
+ E_md4hash(passwd, p21);
+ SMBOWFencrypt(p21, c8, p24);
+}
+
+/* Does the md5 encryption from the NT hash for NTLMv2. */
+void
+SMBOWFencrypt_ntv2(const unsigned char kr[16],
+ const struct data_blob * srv_chal,
+ const struct data_blob * cli_chal, unsigned char resp_buf[16])
+{
+ struct HMACMD5Context ctx;
+
+ hmac_md5_init_limK_to_64(kr, 16, &ctx);
+ hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
+ hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
+ hmac_md5_final(resp_buf, &ctx);
+}
+
+void
+SMBsesskeygen_ntv2(const unsigned char kr[16],
+ const unsigned char *nt_resp, __u8 sess_key[16])
+{
+ struct HMACMD5Context ctx;
+
+ hmac_md5_init_limK_to_64(kr, 16, &ctx);
+ hmac_md5_update(nt_resp, 16, &ctx);
+ hmac_md5_final((unsigned char *) sess_key, &ctx);
+}
+
+void
+SMBsesskeygen_ntv1(const unsigned char kr[16],
+ const unsigned char *nt_resp, __u8 sess_key[16])
+{
+ mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
+}
diff --git a/release/src/linux/linux/fs/cifs/smberr.c b/release/src/linux/linux/fs/cifs/smberr.c
new file mode 100644
index 00000000..f408b42b
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/smberr.c
@@ -0,0 +1,240 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Copyright (C) Andrew Tridgell 1998
+ Copyright (C) Steve French (sfrench@us.ibm.com) 2002
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+include "smberr.h"
+#define NO_SYSLOG
+/* error code stuff - put together by Merik Karman
+ merik@blackadder.dsh.oz.au */
+ typedef const struct {
+ char *name;
+ int code;
+ char *message;
+ int posix_code;
+} err_code_struct;
+
+/* Dos Error Messages */
+err_code_struct dos_msgs[] = {
+ {"ERRbadfunc", ERRbadfunc, "Invalid function.", -EINVAL},
+ {"ERRbadfile", ERRbadfile, "File not found.", -ENOENT},
+ {"ERRbadpath", ERRbadpath, "Directory invalid.", -ENOENT},
+ {"ERRnofids", ERRnofids, "No file descriptors available", -EMFILE},
+ {"ERRnoaccess", ERRnoaccess, "Access denied.", -EACCES},
+ {"ERRbadfid", ERRbadfid, "Invalid file handle.", -EBADF},
+ {"ERRbadmcb", 7, "Memory control blocks destroyed.", -EIO},
+ {"ERRnomem", ERRnomem,
+ "Insufficient server memory to perform the requested function.",
+ -ENOMEM},
+ {"ERRbadmem", ERRbadmem, "Invalid memory block address.", -EFAULT},
+ {"ERRbadenv", ERRbadenv, "Invalid environment.", -EFAULT},
+ {"ERRbadformat", 11, "Invalid format.", -EINVAL},
+ {"ERRbadaccess", ERRbadaccess, "Invalid open mode." - EACCES},
+ {"ERRbaddata", ERRbaddata, "Invalid data.", -EIO},
+ {"ERR", ERRres, "reserved.", -EIO},
+ {"ERRbaddrive", ERRbaddrive, "Invalid drive specified.", -ENXIO},
+ {"ERRremcd", ERRremcd,
+ "A Delete Directory request attempted to remove the server's current directory.",
+ -EIO},
+ {"ERRdiffdevice", ERRdiffdevice, "Not same device.", -EXDEV},
+ {"ERRnofiles", ERRnofiles, "A File Search command can find no more files matching the specified criteria.", -ENOENT}, /* Note: must map to zero manually in some places such as readdir */
+ {"ERRbadshare", ERRbadshare,
+ "The sharing mode specified for an Open conflicts with existing FIDs on the file.",
+ -EXTBSY},
+ {"ERRlock", ERRlock,
+ "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process.",
+ -EACCES},
+ {"ERRunsup", ERRunsup, "The operation is unsupported", -EINVAL},
+ {"ERRnosuchshare", ERRnosuchshare,
+ "You specified an invalid share name", -ENXIO},
+ {"ERRfilexists", ERRfilexists,
+ "The file named in a Create Directory, Make New File or Link request already exists.",
+ -EEXIST},
+ {"ERRinvalidname", ERRinvalidname, "Invalid name", -ENOENT},
+ {"ERRdiskfull", ERRdiskfull, "Disk full", -ENOSPC}
+
+ {"ERRmoredata", ERRmoredata,
+ "There is more data to be returned.",},
+ {"ERRinvgroup", 2455, "Invalid workgroup (try the -W option)"},
+ {NULL, -1, NULL, -EIO}
+};
+
+/* Server Error Messages */
+err_code_struct server_msgs[] = {
+ {"ERRerror", 1, "Non-specific error code."},
+ {"ERRbadpw", 2,
+ "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
+ {"ERRbadtype", 3, "reserved."},
+ {"ERRaccess", 4,
+ "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
+ {"ERRinvnid", 5,
+ "The tree ID (TID) specified in a command was invalid."},
+ {"ERRinvnetname", 6, "Invalid network name in tree connect."},
+ {"ERRinvdevice", 7,
+ "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
+ {"ERRqfull", 49,
+ "Print queue full (files) -- returned by open print file."},
+ {"ERRqtoobig", 50, "Print queue full -- no space."},
+ {"ERRqeof", 51, "EOF on print queue dump."},
+ {"ERRinvpfid", 52, "Invalid print file FID."},
+ {"ERRsmbcmd", 64,
+ "The server did not recognize the command received."},
+ {"ERRsrverror", 65,
+ "The server encountered an internal error, e.g., system file unavailable."},
+ {"ERRfilespecs", 67,
+ "The file handle (FID) and pathname parameters contained an invalid combination of values."},
+ {"ERRreserved", 68, "reserved."},
+ {"ERRbadpermits", 69,
+ "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
+ {"ERRreserved", 70, "reserved."},
+ {"ERRsetattrmode", 71,
+ "The attribute mode in the Set File Attribute request is invalid."},
+ {"ERRpaused", 81, "Server is paused."},
+ {"ERRmsgoff", 82, "Not receiving messages."},
+ {"ERRnoroom", 83, "No room to buffer message."},
+ {"ERRrmuns", 87, "Too many remote user names."},
+ {"ERRtimeout", 88, "Operation timed out."},
+ {"ERRnoresource", 89,
+ "No resources currently available for request."},
+ {"ERRtoomanyuids", 90, "Too many UIDs active on this session."},
+ {"ERRbaduid", 91,
+ "The UID is not known as a valid ID on this session."},
+ {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode."},
+ {"ERRusestd", 251,
+ "Temp unable to support Raw, use standard read/write."},
+ {"ERRcontmpx", 252, "Continue in MPX mode."},
+ {"ERRreserved", 253, "reserved."},
+ {"ERRreserved", 254, "reserved."},
+ {"ERRnosupport", 0xFFFF, "Function not supported."},
+ {NULL, -1, NULL}
+};
+
+/* Hard Error Messages */
+err_code_struct hard_msgs[] = {
+ {"ERRnowrite", 19,
+ "Attempt to write on write-protected diskette."},
+ {"ERRbadunit", 20, "Unknown unit."},
+ {"ERRnotready", 21, "Drive not ready."},
+ {"ERRbadcmd", 22, "Unknown command."},
+ {"ERRdata", 23, "Data error (CRC)."},
+ {"ERRbadreq", 24, "Bad request structure length."},
+ {"ERRseek", 25, "Seek error."},
+ {"ERRbadmedia", 26, "Unknown media type."},
+ {"ERRbadsector", 27, "Sector not found."},
+ {"ERRnopaper", 28, "Printer out of paper."},
+ {"ERRwrite", 29, "Write fault."},
+ {"ERRread", 30, "Read fault."},
+ {"ERRgeneral", 31, "General failure."},
+ {"ERRbadshare", 32, "An open conflicts with an existing open."},
+ {"ERRlock", 33,
+ "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRwrongdisk", 34, "The wrong disk was found in a drive."},
+ {"ERRFCBUnavail", 35, "No FCBs are available to process request."},
+ {"ERRsharebufexc", 36, "A sharing buffer has been exceeded."},
+ {NULL, -1, NULL}
+};
+
+
+const struct {
+ int code;
+ char *class;
+ err_code_struct *err_msgs;
+} err_classes[] = {
+ {
+ 0, "SUCCESS", NULL}, {
+ 0x01, "ERRDOS", dos_msgs}, {
+ 0x02, "ERRSRV", server_msgs}, {
+ 0x03, "ERRHRD", hard_msgs}, {
+ 0x04, "ERRXOS", NULL}, {
+ 0xE1, "ERRRMX1", NULL}, {
+ 0xE2, "ERRRMX2", NULL}, {
+ 0xE3, "ERRRMX3", NULL}, {
+ 0xFF, "ERRCMD", NULL}, {
+-1, NULL, NULL}};
+
+
+/****************************************************************************
+return a SMB error string from a SMB buffer
+****************************************************************************/
+char *smb_dos_errstr(char *inbuf)
+{
+ static pstring ret;
+ int class = CVAL(inbuf, smb_rcls);
+ int num = SVAL(inbuf, smb_err);
+ int i, j;
+
+ for (i = 0; err_classes[i].class; i++)
+ if (err_classes[i].code == class) {
+ if (err_classes[i].err_msgs) {
+ err_code_struct *err =
+ err_classes[i].err_msgs;
+ for (j = 0; err[j].name; j++)
+ if (num == err[j].code) {
+ if (DEBUGLEVEL > 0)
+ slprintf(ret,
+ sizeof
+ (ret) - 1,
+ "%s - %s (%s)",
+ err_classes
+ [i].class,
+ err[j].
+ name,
+ err[j].
+ message);
+ else
+ slprintf(ret,
+ sizeof
+ (ret) - 1,
+ "%s - %s",
+ err_classes
+ [i].class,
+ err[j].
+ name);
+ return ret;
+ }
+ }
+
+ slprintf(ret, sizeof(ret) - 1, "%s - %d",
+ err_classes[i].class, num);
+ return ret;
+ }
+
+ slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",
+ class, num);
+ return (ret);
+}
+
+
+/*****************************************************************************
+ returns an WERROR error message.
+ *****************************************************************************/
+char *werror_str(WERROR status)
+{
+ static fstring msg;
+ slprintf(msg, sizeof(msg), "WIN32 code 0x%08x", W_ERROR_V(status));
+ return msg;
+}
+
+
+/*****************************************************************************
+map a unix errno to a win32 error
+ *****************************************************************************/
+WERROR map_werror_from_unix(int error)
+{
+ NTSTATUS status = map_nt_error_from_unix(error);
+ return ntstatus_to_werror(status);
+}
diff --git a/release/src/linux/linux/fs/cifs/smberr.h b/release/src/linux/linux/fs/cifs/smberr.h
new file mode 100644
index 00000000..25a39bf3
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/smberr.h
@@ -0,0 +1,113 @@
+/*
+ * fs/cifs/smberr.h
+ *
+ * Copyright (c) International Business Machines Corp., 2002
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * See Error Codes section of the SNIA CIFS Specification
+ * for more information
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define SUCCESS 0 /* The request was successful. */
+#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
+#define ERRSRV 0x02 /* Error is generated by the file server daemon */
+#define ERRHRD 0x03 /* Error is a hardware error. */
+#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
+
+/* The following error codes may be generated with the SUCCESS error class.*/
+
+#define SUCCESS 0 /* The request was successful. */
+
+/* The following error codes may be generated with the ERRDOS error class.*/
+
+#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */
+#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */
+#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */
+#define ERRnofids 4 /* Too many open files. The server has no file handles available. */
+#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */
+#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */
+#define ERRbadmcb 7 /* Memory control blocks destroyed. */
+#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */
+#define ERRbadmem 9 /* Invalid memory block address. */
+#define ERRbadenv 10 /* Invalid environment. */
+#define ERRbadformat 11 /* Invalid format. */
+#define ERRbadaccess 12 /* Invalid open mode. */
+#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */
+#define ERRbaddrive 15 /* Invalid drive specified. */
+#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */
+#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */
+#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */
+#define ERRgeneral 31
+#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
+#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */
+#define ERRunsup 50
+#define ERRnosuchshare 67
+#define ERRfilexists 80 /* The file named in the request already exists. */
+#define ERRinvparm 87
+#define ERRdiskfull 112
+#define ERRinvname 123
+#define ERRdirnotempty 145
+#define ERRnotlocked 158
+#define ERRalreadyexists 183
+#define ERRbadpipe 230
+#define ERRpipebusy 231
+#define ERRpipeclosing 232
+#define ERRnotconnected 233
+#define ERRmoredata 234
+#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
+#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
+ was not a link. */
+
+/* Following error codes may be generated with the ERRSRV error
+class.*/
+
+#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */
+#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
+#define ERRbadtype 3 /* used for indicating DFS referral needed */
+#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */
+#define ERRinvtid 5 /* The Tid specified in a command was invalid. */
+#define ERRinvnetname 6 /* Invalid network name in tree connect. */
+#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
+#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */
+#define ERRqtoobig 50 /* Print queue full -- no space. */
+#define ERRqeof 51 /* EOF on print queue dump */
+#define ERRinvpfid 52 /* Invalid print file FID. */
+#define ERRsmbcmd 64 /* The server did not recognize the command received. */
+#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */
+#define ERRbadBID 66 /* (obsolete) */
+#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */
+#define ERRbadLink 68 /* (obsolete) */
+#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */
+#define ERRbadPID 70
+#define ERRsetattrmode 71 /* attribute (mode) is invalid */
+#define ERRpaused 81 /* Server is paused */
+#define ERRmsgoff 82 /* reserved - messaging off */
+#define ERRnoroom 83 /* reserved - no room for message */
+#define ERRrmuns 87 /* reserved - too many remote names */
+#define ERRtimeout 88 /* operation timed out */
+#define ERRnoresource 89 /* No resources available for request */
+#define ERRtoomanyuids 90 /* Too many UIDs active on this session */
+#define ERRbaduid 91 /* The UID is not known as a valid user */
+#define ERRusempx 250 /* temporarily unable to use raw */
+#define ERRusestd 251 /* temporarily unable to use either raw or mpx */
+#define ERR_NOTIFY_ENUM_DIR 1024
+#define ERRaccountexpired 2239
+#define ERRbadclient 2240
+#define ERRbadLogonTime 2241
+#define ERRpasswordExpired 2242
+#define ERRnetlogonNotStarted 2455
+#define ERRnosupport 0xFFFF
diff --git a/release/src/linux/linux/fs/cifs/transport.c b/release/src/linux/linux/fs/cifs/transport.c
new file mode 100644
index 00000000..4092aea7
--- /dev/null
+++ b/release/src/linux/linux/fs/cifs/transport.c
@@ -0,0 +1,434 @@
+/*
+ * fs/cifs/transport.c
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2004
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/net.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+extern kmem_cache_t *cifs_mid_cachep;
+extern kmem_cache_t *cifs_oplock_cachep;
+
+struct mid_q_entry *
+AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
+{
+ struct mid_q_entry *temp;
+
+ if (ses == NULL) {
+ cERROR(1, ("Null session passed in to AllocMidQEntry "));
+ return NULL;
+ }
+ if (ses->server == NULL) {
+ cERROR(1, ("Null TCP session in AllocMidQEntry"));
+ return NULL;
+ }
+
+ temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
+ SLAB_KERNEL);
+ if (temp == NULL)
+ return temp;
+ else {
+ memset(temp, 0, sizeof (struct mid_q_entry));
+ temp->mid = smb_buffer->Mid; /* always LE */
+ temp->pid = current->pid;
+ temp->command = smb_buffer->Command;
+ cFYI(1, ("For smb_command %d", temp->command));
+ do_gettimeofday(&temp->when_sent);
+ temp->ses = ses;
+ temp->tsk = current;
+ }
+
+ spin_lock(&GlobalMid_Lock);
+ list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
+ atomic_inc(&midCount);
+ temp->midState = MID_REQUEST_ALLOCATED;
+ spin_unlock(&GlobalMid_Lock);
+ return temp;
+}
+
+void
+DeleteMidQEntry(struct mid_q_entry *midEntry)
+{
+ spin_lock(&GlobalMid_Lock);
+ midEntry->midState = MID_FREE;
+ list_del(&midEntry->qhead);
+ atomic_dec(&midCount);
+ spin_unlock(&GlobalMid_Lock);
+ cifs_buf_release(midEntry->resp_buf);
+ kmem_cache_free(cifs_mid_cachep, midEntry);
+}
+
+struct oplock_q_entry *
+AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
+{
+ struct oplock_q_entry *temp;
+ if ((pinode== NULL) || (tcon == NULL)) {
+ cERROR(1, ("Null parms passed to AllocOplockQEntry"));
+ return NULL;
+ }
+ temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
+ SLAB_KERNEL);
+ if (temp == NULL)
+ return temp;
+ else {
+ temp->pinode = pinode;
+ temp->tcon = tcon;
+ temp->netfid = fid;
+ spin_lock(&GlobalMid_Lock);
+ list_add_tail(&temp->qhead, &GlobalOplock_Q);
+ spin_unlock(&GlobalMid_Lock);
+ }
+ return temp;
+
+}
+
+void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
+{
+ spin_lock(&GlobalMid_Lock);
+ /* should we check if list empty first? */
+ list_del(&oplockEntry->qhead);
+ spin_unlock(&GlobalMid_Lock);
+ kmem_cache_free(cifs_oplock_cachep, oplockEntry);
+}
+
+int
+smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
+ unsigned int smb_buf_length, struct sockaddr *sin)
+{
+ int rc = 0;
+ int i = 0;
+ struct msghdr smb_msg;
+ struct iovec iov;
+ mm_segment_t temp_fs;
+
+ if(ssocket == NULL)
+ return -ENOTSOCK; /* BB eventually add reconnect code here */
+ iov.iov_base = smb_buffer;
+ iov.iov_len = smb_buf_length + 4;
+
+ smb_msg.msg_name = sin;
+ smb_msg.msg_namelen = sizeof (struct sockaddr);
+ smb_msg.msg_iov = &iov;
+ smb_msg.msg_iovlen = 1;
+ smb_msg.msg_control = NULL;
+ smb_msg.msg_controllen = 0;
+ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+
+ /* smb header is converted in header_assemble. bcc and rest of SMB word
+ area, and byte area if necessary, is converted to littleendian in
+ cifssmb.c and RFC1001 len is converted to bigendian in smb_send
+ Flags2 is converted in SendReceive */
+
+ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+ cFYI(1, ("Sending smb of length %d ", smb_buf_length));
+ dump_smb(smb_buffer, smb_buf_length + 4);
+
+ temp_fs = get_fs(); /* we must turn off socket api parm checking */
+ set_fs(get_ds());
+ while(iov.iov_len > 0) {
+ rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
+ if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+ i++;
+ if(i > 60) {
+ cERROR(1,
+ ("sends on sock %p stuck for 30 seconds",
+ ssocket));
+ rc = -EAGAIN;
+ break;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/2);
+ continue;
+ }
+ if (rc < 0)
+ break;
+ iov.iov_base += rc;
+ iov.iov_len -= rc;
+ }
+ set_fs(temp_fs);
+
+ if (rc < 0) {
+ cERROR(1,("Error %d sending data on socket to server.", rc));
+ } else {
+ rc = 0;
+ }
+
+ return rc;
+}
+
+int
+SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
+ struct smb_hdr *in_buf, struct smb_hdr *out_buf,
+ int *pbytes_returned, const int long_op)
+{
+ int rc = 0;
+ unsigned int receive_len;
+ long timeout;
+ struct mid_q_entry *midQ;
+
+ if (ses == NULL) {
+ cERROR(1,("Null smb session"));
+ return -EIO;
+ }
+ if(ses->server == NULL) {
+ cERROR(1,("Null tcp session"));
+ return -EIO;
+ }
+
+ /* Ensure that we do not send more than 50 overlapping requests
+ to the same server. We may make this configurable later or
+ use ses->maxReq */
+ if(long_op == -1) {
+ /* oplock breaks must not be held up */
+ atomic_inc(&ses->server->inFlight);
+ } else {
+ spin_lock(&GlobalMid_Lock);
+ while(1) {
+ if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){
+ spin_unlock(&GlobalMid_Lock);
+ wait_event(ses->server->request_q,
+ atomic_read(&ses->server->inFlight)
+ < CIFS_MAX_REQ);
+ spin_lock(&GlobalMid_Lock);
+ } else {
+ if(ses->server->tcpStatus == CifsExiting) {
+ spin_unlock(&GlobalMid_Lock);
+ return -ENOENT;
+ }
+
+ /* can not count locking commands against total since
+ they are allowed to block on server */
+
+ if(long_op < 3) {
+ /* update # of requests on the wire to server */
+ atomic_inc(&ses->server->inFlight);
+ }
+ spin_unlock(&GlobalMid_Lock);
+ break;
+ }
+ }
+ }
+ /* make sure that we sign in the same order that we send on this socket
+ and avoid races inside tcp sendmsg code that could cause corruption
+ of smb data */
+
+ down(&ses->server->tcpSem);
+
+ if (ses->server->tcpStatus == CifsExiting) {
+ rc = -ENOENT;
+ goto out_unlock;
+ } else if (ses->server->tcpStatus == CifsNeedReconnect) {
+ cFYI(1,("tcp session dead - return to caller to retry"));
+ rc = -EAGAIN;
+ goto out_unlock;
+ } else if (ses->status != CifsGood) {
+ /* check if SMB session is bad because we are setting it up */
+ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
+ (in_buf->Command != SMB_COM_NEGOTIATE)) {
+ rc = -EAGAIN;
+ goto out_unlock;
+ } /* else ok - we are setting up session */
+ }
+ midQ = AllocMidQEntry(in_buf, ses);
+ if (midQ == NULL) {
+ up(&ses->server->tcpSem);
+ /* If not lock req, update # of requests on wire to server */
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+ return -ENOMEM;
+ }
+
+ if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
+ up(&ses->server->tcpSem);
+ cERROR(1,
+ ("Illegal length, greater than maximum frame, %d ",
+ in_buf->smb_buf_length));
+ DeleteMidQEntry(midQ);
+ /* If not lock req, update # of requests on wire to server */
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+ return -EIO;
+ }
+
+ if (in_buf->smb_buf_length > 12)
+ in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
+
+ rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
+
+ midQ->midState = MID_REQUEST_SUBMITTED;
+ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+ (struct sockaddr *) &(ses->server->addr.sockAddr));
+ if(rc < 0) {
+ DeleteMidQEntry(midQ);
+ up(&ses->server->tcpSem);
+ /* If not lock req, update # of requests on wire to server */
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+ return rc;
+ } else
+ up(&ses->server->tcpSem);
+ if (long_op == -1)
+ goto cifs_no_response_exit;
+ else if (long_op == 2) /* writes past end of file can take looooong time */
+ timeout = 300 * HZ;
+ else if (long_op == 1)
+ timeout = 45 * HZ; /* should be greater than
+ servers oplock break timeout (about 43 seconds) */
+ else if (long_op > 2) {
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ } else
+ timeout = 15 * HZ;
+ /* wait for 15 seconds or until woken up due to response arriving or
+ due to last connection to this server being unmounted */
+ if (signal_pending(current)) {
+ /* if signal pending do not hold up user for full smb timeout
+ but we still give response a change to complete */
+ if(midQ->midState & MID_REQUEST_SUBMITTED) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
+ }
+ } else { /* using normal timeout */
+ /* timeout = wait_event_interruptible_timeout(ses->server->response_q,
+ (midQ->midState & MID_RESPONSE_RECEIVED) ||
+ ((ses->server->tcpStatus != CifsGood) &&
+ (ses->server->tcpStatus != CifsNew)),
+ timeout); */
+ /* Can not allow user interrupts- wreaks havoc with performance */
+ if(midQ->midState & MID_REQUEST_SUBMITTED) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ timeout = sleep_on_timeout(&ses->server->response_q,timeout);
+ }
+ }
+
+ spin_lock(&GlobalMid_Lock);
+ if (midQ->resp_buf) {
+ spin_unlock(&GlobalMid_Lock);
+ receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
+ } else {
+ cERROR(1,("No response buffer"));
+ if(midQ->midState == MID_REQUEST_SUBMITTED) {
+ if(ses->server->tcpStatus == CifsExiting)
+ rc = -EHOSTDOWN;
+ else {
+ ses->server->tcpStatus = CifsNeedReconnect;
+ midQ->midState = MID_RETRY_NEEDED;
+ }
+ }
+
+ if (rc != -EHOSTDOWN) {
+ if(midQ->midState == MID_RETRY_NEEDED) {
+ rc = -EAGAIN;
+ cFYI(1,("marking request for retry"));
+ } else {
+ rc = -EIO;
+ }
+ }
+ spin_unlock(&GlobalMid_Lock);
+ DeleteMidQEntry(midQ);
+ /* If not lock req, update # of requests on wire to server */
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+ return rc;
+ }
+
+ if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
+ cERROR(1,
+ ("Frame too large received. Length: %d Xid: %d",
+ receive_len, xid));
+ rc = -EIO;
+ } else { /* rcvd frame is ok */
+
+ if (midQ->resp_buf && out_buf
+ && (midQ->midState == MID_RESPONSE_RECEIVED)) {
+ memcpy(out_buf, midQ->resp_buf,
+ receive_len +
+ 4 /* include 4 byte RFC1001 header */ );
+
+ dump_smb(out_buf, 92);
+ /* convert the length into a more usable form */
+ out_buf->smb_buf_length =
+ be32_to_cpu(out_buf->smb_buf_length);
+ if((out_buf->smb_buf_length > 24) &&
+ (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
+ rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
+ if(rc)
+ cFYI(1,("Unexpected signature received from server"));
+ }
+
+ if (out_buf->smb_buf_length > 12)
+ out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
+ if (out_buf->smb_buf_length > 28)
+ out_buf->Pid = le16_to_cpu(out_buf->Pid);
+ if (out_buf->smb_buf_length > 28)
+ out_buf->PidHigh =
+ le16_to_cpu(out_buf->PidHigh);
+
+ *pbytes_returned = out_buf->smb_buf_length;
+
+ /* BB special case reconnect tid and reconnect uid here? */
+ rc = map_smb_to_linux_error(out_buf);
+
+ /* convert ByteCount if necessary */
+ if (receive_len >=
+ sizeof (struct smb_hdr) -
+ 4 /* do not count RFC1001 header */ +
+ (2 * out_buf->WordCount) + 2 /* bcc */ )
+ BCC(out_buf) = le16_to_cpu(BCC(out_buf));
+ } else {
+ rc = -EIO;
+ cFYI(1,("Bad MID state? "));
+ }
+ }
+cifs_no_response_exit:
+ DeleteMidQEntry(midQ);
+
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+
+ return rc;
+
+out_unlock:
+ up(&ses->server->tcpSem);
+ /* If not lock req, update # of requests on wire to server */
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+
+ return rc;
+}
diff --git a/release/src/linux/linux/fs/nls/Config.in b/release/src/linux/linux/fs/nls/Config.in
index 0ac7ab5d..aff381db 100644
--- a/release/src/linux/linux/fs/nls/Config.in
+++ b/release/src/linux/linux/fs/nls/Config.in
@@ -11,6 +11,7 @@ fi
# msdos and Joliet want NLS
if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
+ -o "$CONFIG_CIFS" != "n" \
-o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
-o "$CONFIG_SMB_NLS" = "y" -o "$CONFIG_JFS_FS" != "n" \
-o "$CONFIG_BEFS_FS" != "n" ]; then
diff --git a/release/src/linux/linux/fs/squashfs/LzmaDecode.c b/release/src/linux/linux/fs/squashfs/LzmaDecode.c
new file mode 100644
index 00000000..951700bd
--- /dev/null
+++ b/release/src/linux/linux/fs/squashfs/LzmaDecode.c
@@ -0,0 +1,663 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ UInt32 size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ Byte *stream, UInt32 bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->InCallback = inCallback;
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i > 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i > 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#ifdef _LZMA_OUT_READ
+
+typedef struct _LzmaVarState
+{
+ CRangeDecoder RangeDecoder;
+ Byte *Dictionary;
+ UInt32 DictionarySize;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 Reps[4];
+ int lc;
+ int lp;
+ int pb;
+ int State;
+ int PreviousIsMatch;
+ int RemainLen;
+} LzmaVarState;
+
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+ )
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ UInt32 i;
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ vs->Dictionary = dictionary;
+ vs->DictionarySize = dictionarySize;
+ vs->DictionaryPos = 0;
+ vs->GlobalPos = 0;
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
+ vs->lc = lc;
+ vs->lp = lp;
+ vs->pb = pb;
+ vs->State = 0;
+ vs->PreviousIsMatch = 0;
+ vs->RemainLen = 0;
+ dictionary[dictionarySize - 1] = 0;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&vs->RangeDecoder,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+ return LZMA_RESULT_OK;
+}
+
+int LzmaDecode(unsigned char *buffer,
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ CRangeDecoder rd = vs->RangeDecoder;
+ int state = vs->State;
+ int previousIsMatch = vs->PreviousIsMatch;
+ Byte previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
+ int lc = vs->lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ if (len == -1)
+ {
+ *outSizeProcessed = 0;
+ return LZMA_RESULT_OK;
+ }
+
+ while(len > 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+#else
+
+int LzmaDecode(
+ Byte *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ CProb *p = (CProb *)buffer;
+ CRangeDecoder rd;
+ UInt32 i;
+ int state = 0;
+ int previousIsMatch = 0;
+ Byte previousByte = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << pb) - 1;
+ UInt32 literalPosMask = (1 << lp) - 1;
+ int len = 0;
+ if (bufferSize < numProbs * sizeof(CProb))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&rd,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+#endif
+
+ *outSizeProcessed = 0;
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ if (previousIsMatch)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ previousIsMatch = 0;
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ }
+ else
+ {
+ previousIsMatch = 1;
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ if (
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ rep0++;
+ }
+ if (rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = -1;
+ break;
+ }
+ if (rep0 > nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ {
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len += kMatchMinLen;
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ len--;
+ }
+ while(len > 0 && nowPos < outSize);
+ }
+ }
+
+ #ifdef _LZMA_OUT_READ
+ vs->RangeDecoder = rd;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + nowPos;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->PreviousIsMatch = previousIsMatch;
+ vs->RemainLen = len;
+ #endif
+
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/release/src/linux/linux/fs/squashfs/LzmaDecode.h b/release/src/linux/linux/fs/squashfs/LzmaDecode.h
new file mode 100644
index 00000000..f58944e3
--- /dev/null
+++ b/release/src/linux/linux/fs/squashfs/LzmaDecode.h
@@ -0,0 +1,100 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+/*
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
+bufferSize += 100 in case of _LZMA_OUT_READ
+by default CProb is unsigned short,
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
+*/
+
+#ifdef _LZMA_OUT_READ
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+);
+#endif
+
+int LzmaDecode(
+ unsigned char *buffer,
+ #ifndef _LZMA_OUT_READ
+ UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed);
+
+#endif
diff --git a/release/src/linux/linux/fs/squashfs/Makefile b/release/src/linux/linux/fs/squashfs/Makefile
index 0dcd8d17..367dbfc2 100644
--- a/release/src/linux/linux/fs/squashfs/Makefile
+++ b/release/src/linux/linux/fs/squashfs/Makefile
@@ -4,7 +4,11 @@
O_TARGET := squashfs.o
-obj-y := inode.o
+obj-y := inode.o squashfs2_0.o
+
+ifdef CONFIG_LZMA_FS_INFLATE
+obj-y += LzmaDecode.o
+endif
obj-m := $(O_TARGET)
diff --git a/release/src/linux/linux/fs/squashfs/inode.c b/release/src/linux/linux/fs/squashfs/inode.c
index 08193482..5c17f070 100644
--- a/release/src/linux/linux/fs/squashfs/inode.c
+++ b/release/src/linux/linux/fs/squashfs/inode.c
@@ -1,7 +1,11 @@
/*
* Squashfs - a compressed read only filesystem for Linux
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * LZMA decompressor support added by Oleg I. Vdovikin
+ * Copyright (c) 2005 Oleg I.Vdovikin <oleg@cs.msu.su>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -16,39 +20,47 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Squashfs - a compressed read only filesystem for Linux
*
* inode.c
*/
-#define SQUASHFS_1_0_COMPATIBILITY
-
#include <linux/types.h>
#include <linux/squashfs_fs.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/fs.h>
+#include <linux/smp_lock.h>
#include <linux/locks.h>
#include <linux/init.h>
#include <linux/dcache.h>
-#include <asm/uaccess.h>
#include <linux/wait.h>
-#include <asm/semaphore.h>
#include <linux/zlib.h>
#include <linux/blkdev.h>
#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <linux/autoconf.h>
-#ifdef SQUASHFS_TRACE
-#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
-#else
-#define TRACE(s, args...) {}
+#include "squashfs.h"
+
+#ifdef CONFIG_LZMA_FS_INFLATE
+ #define SQUASHFS_LZMA
#endif
-#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
+#ifdef SQUASHFS_LZMA
+#include "LzmaDecode.h"
+
+/* default LZMA settings, should be in sync with mksquashfs */
+#define LZMA_LC 3
+#define LZMA_LP 0
+#define LZMA_PB 2
+
+#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \
+ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb))
+
+#endif
-#define SERROR(s, args...) if(!silent) printk(KERN_ERR "SQUASHFS error: "s, ## args)
-#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
static struct super_block *squashfs_read_super(struct super_block *, void *, int);
static void squashfs_put_super(struct super_block *);
@@ -58,26 +70,16 @@ static int squashfs_readpage(struct file *file, struct page *page);
static int squashfs_readpage4K(struct file *file, struct page *page);
static int squashfs_readdir(struct file *, void *, filldir_t);
static struct dentry *squashfs_lookup(struct inode *, struct dentry *);
-static unsigned int read_data(struct super_block *s, char *buffer,
- unsigned int index, unsigned int length, int, unsigned int *next_index);
-static int squashfs_get_cached_block(struct super_block *s, char *buffer,
- unsigned int block, unsigned int offset, int length,
- unsigned int *next_block, unsigned int *next_offset);
-static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode);
-static unsigned int read_blocklist(struct inode *inode, int index, int readahead_blks,
- char *block_list, char **block_p, unsigned int *bsize);
-static void squashfs_put_super(struct super_block *s);
-
-#ifdef SQUASHFS_1_0_COMPATIBILITY
-static int squashfs_readpage_lessthan4K(struct file *file, struct page *page);
-static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode inode);
-static unsigned int read_blocklist_1(struct inode *inode, int index, int readahead_blks,
- char *block_list, char **block_p, unsigned int *bsize);
-#endif
-
-DECLARE_MUTEX(read_data_mutex);
+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
+static long long read_blocklist(struct inode *inode, int index,
+ int readahead_blks, char *block_list,
+ unsigned short **block_p, unsigned int *bsize);
+#ifdef SQUASHFS_LZMA
+static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE];
+#else
static z_stream stream;
+#endif
static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super);
@@ -86,140 +88,161 @@ static unsigned char squashfs_filetype_table[] = {
};
static struct super_operations squashfs_ops = {
- statfs: squashfs_statfs,
- put_super: squashfs_put_super,
+ .statfs = squashfs_statfs,
+ .put_super = squashfs_put_super,
};
-static struct address_space_operations squashfs_symlink_aops = {
- readpage: squashfs_symlink_readpage
+SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
+ .readpage = squashfs_symlink_readpage
};
-static struct address_space_operations squashfs_aops = {
- readpage: squashfs_readpage
+SQSH_EXTERN struct address_space_operations squashfs_aops = {
+ .readpage = squashfs_readpage
};
-static struct address_space_operations squashfs_aops_4K = {
- readpage: squashfs_readpage4K
+SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
+ .readpage = squashfs_readpage4K
};
-#ifdef SQUASHFS_1_0_COMPATIBILITY
-static struct address_space_operations squashfs_aops_lessthan4K = {
- readpage: squashfs_readpage_lessthan4K
-};
-#endif
-
static struct file_operations squashfs_dir_ops = {
- read: generic_read_dir,
- readdir: squashfs_readdir
+ .read = generic_read_dir,
+ .readdir = squashfs_readdir
};
static struct inode_operations squashfs_dir_inode_ops = {
- lookup: squashfs_lookup
+ .lookup = squashfs_lookup
};
+static struct buffer_head *get_block_length(struct super_block *s,
+ int *cur_index, int *offset, int *c_byte)
+{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ unsigned short temp;
+ struct buffer_head *bh;
+
+ if (!(bh = sb_bread(s, *cur_index)))
+ goto out;
+
+ if (msblk->devblksize - *offset == 1) {
+ if (msblk->swap)
+ ((unsigned char *) &temp)[1] = *((unsigned char *)
+ (bh->b_data + *offset));
+ else
+ ((unsigned char *) &temp)[0] = *((unsigned char *)
+ (bh->b_data + *offset));
+ brelse(bh);
+ if (!(bh = sb_bread(s, ++(*cur_index))))
+ goto out;
+ if (msblk->swap)
+ ((unsigned char *) &temp)[0] = *((unsigned char *)
+ bh->b_data);
+ else
+ ((unsigned char *) &temp)[1] = *((unsigned char *)
+ bh->b_data);
+ *c_byte = temp;
+ *offset = 1;
+ } else {
+ if (msblk->swap) {
+ ((unsigned char *) &temp)[1] = *((unsigned char *)
+ (bh->b_data + *offset));
+ ((unsigned char *) &temp)[0] = *((unsigned char *)
+ (bh->b_data + *offset + 1));
+ } else {
+ ((unsigned char *) &temp)[0] = *((unsigned char *)
+ (bh->b_data + *offset));
+ ((unsigned char *) &temp)[1] = *((unsigned char *)
+ (bh->b_data + *offset + 1));
+ }
+ *c_byte = temp;
+ *offset += 2;
+ }
+
+ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
+ if (*offset == msblk->devblksize) {
+ brelse(bh);
+ if (!(bh = sb_bread(s, ++(*cur_index))))
+ goto out;
+ *offset = 0;
+ }
+ if (*((unsigned char *) (bh->b_data + *offset)) !=
+ SQUASHFS_MARKER_BYTE) {
+ ERROR("Metadata block marker corrupt @ %x\n",
+ *cur_index);
+ brelse(bh);
+ goto out;
+ }
+ (*offset)++;
+ }
+ return bh;
+
+out:
+ return NULL;
+}
+
-static unsigned int read_data(struct super_block *s, char *buffer,
- unsigned int index, unsigned int length, int datablock, unsigned int *next_index)
+SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+ long long index, unsigned int length,
+ long long *next_index)
{
- squashfs_sb_info *msBlk = &s->u.squashfs_sb;
- struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> msBlk->devblksize_log2) + 2];
- unsigned int offset = index & ((1 << msBlk->devblksize_log2) - 1);
- unsigned int cur_index = index >> msBlk->devblksize_log2;
- int bytes, avail_bytes, b, k;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
+ msblk->devblksize_log2) + 2];
+ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
+ unsigned int cur_index = index >> msblk->devblksize_log2;
+ int bytes, avail_bytes, b = 0, k;
char *c_buffer;
unsigned int compressed;
unsigned int c_byte = length;
- if(c_byte) {
- bytes = msBlk->devblksize - offset;
- if(datablock) {
- c_buffer = (compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte)) ? msBlk->read_data : buffer;
- c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
- } else {
- c_buffer = (compressed = SQUASHFS_COMPRESSED(c_byte)) ? msBlk->read_data : buffer;
- c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
- }
+ if (c_byte) {
+ bytes = msblk->devblksize - offset;
+ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
+ c_buffer = compressed ? msblk->read_data : buffer;
+ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
- TRACE("Block @ 0x%x, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte);
+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
+ ? "" : "un", (unsigned int) c_byte);
- if(!(bh[0] = sb_getblk(s, cur_index)))
+ if (!(bh[0] = sb_getblk(s, cur_index)))
goto block_release;
- for(b = 1; bytes < c_byte; b++) {
- if(!(bh[b] = sb_getblk(s, ++cur_index)))
+
+ for (b = 1; bytes < c_byte; b++) {
+ if (!(bh[b] = sb_getblk(s, ++cur_index)))
goto block_release;
- bytes += msBlk->devblksize;
+ bytes += msblk->devblksize;
}
ll_rw_block(READ, b, bh);
} else {
- unsigned short temp;
- if(!(bh[0] = sb_bread(s, cur_index)))
+ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
+ &c_byte)))
goto read_failure;
- if(msBlk->devblksize - offset == 1) {
- if(msBlk->swap)
- ((unsigned char *) &temp)[1] = *((unsigned char *) (bh[0]->b_data + offset));
- else
- ((unsigned char *) &temp)[0] = *((unsigned char *) (bh[0]->b_data + offset));
- brelse(bh[0]);
- if(!(bh[0] = sb_bread(s, ++cur_index)))
- goto read_failure;
- if(msBlk->swap)
- ((unsigned char *) &temp)[0] = *((unsigned char *) bh[0]->b_data);
- else
- ((unsigned char *) &temp)[1] = *((unsigned char *) bh[0]->b_data);
- c_byte = temp;
- offset = 1;
- }
- else {
- if(msBlk->swap) {
- unsigned short temp;
- ((unsigned char *) &temp)[1] = *((unsigned char *) (bh[0]->b_data + offset));
- ((unsigned char *) &temp)[0] = *((unsigned char *) (bh[0]->b_data + offset + 1));
- c_byte = temp;
- } else
- c_byte = *((unsigned short *) (bh[0]->b_data + offset));
- offset += 2;
- }
- if(SQUASHFS_CHECK_DATA(msBlk->sBlk.flags)) {
- if(offset == msBlk->devblksize) {
- brelse(bh[0]);
- if(!(bh[0] = sb_bread(s, ++cur_index)))
- goto read_failure;
- offset = 0;
- }
- if(*((unsigned char *) (bh[0]->b_data + offset)) != SQUASHFS_MARKER_BYTE) {
- ERROR("Metadata block marker corrupt @ %x\n", index);
- brelse(bh[0]);
- return 0;
- }
- offset ++;
- }
-
- bytes = msBlk->devblksize - offset;
- if(datablock) {
- c_buffer = (compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte)) ? msBlk->read_data : buffer;
- c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
- } else {
- c_buffer = (compressed = SQUASHFS_COMPRESSED(c_byte)) ? msBlk->read_data : buffer;
- c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
- }
+ bytes = msblk->devblksize - offset;
+ compressed = SQUASHFS_COMPRESSED(c_byte);
+ c_buffer = compressed ? msblk->read_data : buffer;
+ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
- TRACE("Block @ 0x%x, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte);
+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
+ ? "" : "un", (unsigned int) c_byte);
- for(b = 1; bytes < c_byte; b++) {
- if(!(bh[b] = sb_getblk(s, ++cur_index)))
+ for (b = 1; bytes < c_byte; b++) {
+ if (!(bh[b] = sb_getblk(s, ++cur_index)))
goto block_release;
- bytes += msBlk->devblksize;
+ bytes += msblk->devblksize;
}
ll_rw_block(READ, b - 1, bh + 1);
}
- if(compressed)
- down(&read_data_mutex);
+ if (compressed)
+ down(&msblk->read_data_mutex);
- for(bytes = 0, k = 0; k < b; k++) {
- avail_bytes = (c_byte - bytes) > (msBlk->devblksize - offset) ? msBlk->devblksize - offset : c_byte - bytes;
+ for (bytes = 0, k = 0; k < b; k++) {
+ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
+ msblk->devblksize - offset :
+ c_byte - bytes;
wait_on_buffer(bh[k]);
+ if (!buffer_uptodate(bh[k]))
+ goto block_release;
memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
bytes += avail_bytes;
offset = 0;
@@ -229,30 +252,46 @@ static unsigned int read_data(struct super_block *s, char *buffer,
/*
* uncompress block
*/
- if(compressed) {
+ if (compressed) {
int zlib_err;
+#ifdef SQUASHFS_LZMA
+ if ((zlib_err = LzmaDecode(lzma_workspace,
+ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB,
+ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK)
+ {
+ ERROR("lzma returned unexpected result 0x%x\n", zlib_err);
+ bytes = 0;
+ }
+#else
stream.next_in = c_buffer;
stream.avail_in = c_byte;
stream.next_out = buffer;
- stream.avail_out = msBlk->read_size;
- if(((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
- ((zlib_err = zlib_inflate(&stream, Z_FINISH)) != Z_STREAM_END) ||
- ((zlib_err = zlib_inflateEnd(&stream)) != Z_OK)) {
- ERROR("zlib_fs returned unexpected result 0x%x\n", zlib_err);
+ stream.avail_out = msblk->read_size;
+
+ if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
+ ((zlib_err = zlib_inflate(&stream, Z_FINISH))
+ != Z_STREAM_END) || ((zlib_err =
+ zlib_inflateEnd(&stream)) != Z_OK)) {
+ ERROR("zlib_fs returned unexpected result 0x%x\n",
+ zlib_err);
bytes = 0;
} else
bytes = stream.total_out;
- up(&read_data_mutex);
+#endif
+
+ up(&msblk->read_data_mutex);
}
- if(next_index)
- *next_index = index + c_byte + (length ? 0 : (SQUASHFS_CHECK_DATA(msBlk->sBlk.flags) ? 3 : 2));
-
+ if (next_index)
+ *next_index = index + c_byte + (length ? 0 :
+ (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
+ ? 3 : 2));
return bytes;
block_release:
- while(--b >= 0) brelse(bh[b]);
+ while (--b >= 0)
+ brelse(bh[b]);
read_failure:
ERROR("sb_bread failed reading block 0x%x\n", cur_index);
@@ -260,543 +299,668 @@ read_failure:
}
-static int squashfs_get_cached_block(struct super_block *s, char *buffer,
- unsigned int block, unsigned int offset, int length,
- unsigned int *next_block, unsigned int *next_offset)
+SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
+ long long block, unsigned int offset,
+ int length, long long *next_block,
+ unsigned int *next_offset)
{
- squashfs_sb_info *msBlk = &s->u.squashfs_sb;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
int n, i, bytes, return_length = length;
- unsigned int next_index;
+ long long next_index;
- TRACE("Entered squashfs_get_cached_block [%x:%x]\n", block, offset);
+ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
- for(;;) {
- for(i = 0; i < SQUASHFS_CACHED_BLKS; i++)
- if(msBlk->block_cache[i].block == block)
+ while ( 1 ) {
+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
+ if (msblk->block_cache[i].block == block)
break;
- down(&msBlk->block_cache_mutex);
- if(i == SQUASHFS_CACHED_BLKS) {
+ down(&msblk->block_cache_mutex);
+
+ if (i == SQUASHFS_CACHED_BLKS) {
/* read inode header block */
- for(i = msBlk->next_cache, n = SQUASHFS_CACHED_BLKS; n ; n --, i = (i + 1) % SQUASHFS_CACHED_BLKS)
- if(msBlk->block_cache[i].block != SQUASHFS_USED_BLK)
+ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
+ n ; n --, i = (i + 1) %
+ SQUASHFS_CACHED_BLKS)
+ if (msblk->block_cache[i].block !=
+ SQUASHFS_USED_BLK)
break;
- if(n == 0) {
- up(&msBlk->block_cache_mutex);
- sleep_on(&msBlk->waitq);
+
+ if (n == 0) {
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&msblk->waitq, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ up(&msblk->block_cache_mutex);
+ schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&msblk->waitq, &wait);
continue;
}
- msBlk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
-
- if(msBlk->block_cache[i].block == SQUASHFS_INVALID_BLK) {
- if(!(msBlk->block_cache[i].data = (unsigned char *)
- kmalloc(SQUASHFS_METADATA_SIZE, GFP_KERNEL))) {
- ERROR("Failed to allocate cache block\n");
- up(&msBlk->block_cache_mutex);
- return 0;
+ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
+
+ if (msblk->block_cache[i].block ==
+ SQUASHFS_INVALID_BLK) {
+ if (!(msblk->block_cache[i].data =
+ kmalloc(SQUASHFS_METADATA_SIZE,
+ GFP_KERNEL))) {
+ ERROR("Failed to allocate cache"
+ "block\n");
+ up(&msblk->block_cache_mutex);
+ goto out;
}
}
- msBlk->block_cache[i].block = SQUASHFS_USED_BLK;
- up(&msBlk->block_cache_mutex);
- if(!(msBlk->block_cache[i].length = read_data(s, msBlk->block_cache[i].data, block, 0, 0,
- &next_index))) {
- ERROR("Unable to read cache block [%x:%x]\n", block, offset);
- return 0;
+ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
+ up(&msblk->block_cache_mutex);
+
+ if (!(msblk->block_cache[i].length =
+ squashfs_read_data(s,
+ msblk->block_cache[i].data,
+ block, 0, &next_index))) {
+ ERROR("Unable to read cache block [%llx:%x]\n",
+ block, offset);
+ goto out;
}
- down(&msBlk->block_cache_mutex);
- wake_up(&msBlk->waitq);
- msBlk->block_cache[i].block = block;
- msBlk->block_cache[i].next_index = next_index;
- TRACE("Read cache block [%x:%x]\n", block, offset);
+
+ down(&msblk->block_cache_mutex);
+ wake_up(&msblk->waitq);
+ msblk->block_cache[i].block = block;
+ msblk->block_cache[i].next_index = next_index;
+ TRACE("Read cache block [%llx:%x]\n", block, offset);
}
- if(msBlk->block_cache[i].block != block) {
- up(&msBlk->block_cache_mutex);
+ if (msblk->block_cache[i].block != block) {
+ up(&msblk->block_cache_mutex);
continue;
}
- if((bytes = msBlk->block_cache[i].length - offset) >= length) {
- if(buffer)
- memcpy(buffer, msBlk->block_cache[i].data + offset, length);
- if(msBlk->block_cache[i].length - offset == length) {
- *next_block = msBlk->block_cache[i].next_index;
+ if ((bytes = msblk->block_cache[i].length - offset) >= length) {
+ if (buffer)
+ memcpy(buffer, msblk->block_cache[i].data +
+ offset, length);
+ if (msblk->block_cache[i].length - offset == length) {
+ *next_block = msblk->block_cache[i].next_index;
*next_offset = 0;
} else {
*next_block = block;
*next_offset = offset + length;
}
-
- up(&msBlk->block_cache_mutex);
- return return_length;
+ up(&msblk->block_cache_mutex);
+ goto finish;
} else {
- if(buffer) {
- memcpy(buffer, msBlk->block_cache[i].data + offset, bytes);
+ if (buffer) {
+ memcpy(buffer, msblk->block_cache[i].data +
+ offset, bytes);
buffer += bytes;
}
- block = msBlk->block_cache[i].next_index;
- up(&msBlk->block_cache_mutex);
+ block = msblk->block_cache[i].next_index;
+ up(&msblk->block_cache_mutex);
length -= bytes;
offset = 0;
}
}
+
+finish:
+ return return_length;
+out:
+ return 0;
}
-static int get_fragment_location(struct super_block *s, unsigned int fragment, unsigned int *fragment_start_block, unsigned int *fragment_size)
+static int get_fragment_location(struct super_block *s, unsigned int fragment,
+ long long *fragment_start_block,
+ unsigned int *fragment_size)
{
- squashfs_sb_info *msBlk = &s->u.squashfs_sb;
- unsigned int start_block = msBlk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ long long start_block =
+ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
- squashfs_fragment_entry fragment_entry;
+ struct squashfs_fragment_entry fragment_entry;
- if(msBlk->swap) {
- squashfs_fragment_entry sfragment_entry;
+ if (msblk->swap) {
+ struct squashfs_fragment_entry sfragment_entry;
- if(!squashfs_get_cached_block(s, (char *) &sfragment_entry, start_block, offset,
- sizeof(sfragment_entry), &start_block, &offset))
- return 0;
+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
+ start_block, offset,
+ sizeof(sfragment_entry), &start_block,
+ &offset))
+ goto out;
SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
} else
- if(!squashfs_get_cached_block(s, (char *) &fragment_entry, start_block, offset,
- sizeof(fragment_entry), &start_block, &offset))
- return 0;
+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
+ start_block, offset,
+ sizeof(fragment_entry), &start_block,
+ &offset))
+ goto out;
*fragment_start_block = fragment_entry.start_block;
*fragment_size = fragment_entry.size;
return 1;
+
+out:
+ return 0;
}
-void release_cached_fragment(squashfs_sb_info *msBlk, struct squashfs_fragment_cache *fragment)
+SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
+ squashfs_fragment_cache *fragment)
{
- down(&msBlk->fragment_mutex);
+ down(&msblk->fragment_mutex);
fragment->locked --;
- wake_up(&msBlk->fragment_wait_queue);
- up(&msBlk->fragment_mutex);
+ wake_up(&msblk->fragment_wait_queue);
+ up(&msblk->fragment_mutex);
}
-struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, unsigned int start_block, int length)
+SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
+ *s, long long start_block,
+ int length)
{
int i, n;
- squashfs_sb_info *msBlk = &s->u.squashfs_sb;
-
- for(;;) {
- down(&msBlk->fragment_mutex);
- for(i = 0; i < SQUASHFS_CACHED_FRAGMENTS && msBlk->fragment[i].block != start_block; i++);
- if(i == SQUASHFS_CACHED_FRAGMENTS) {
- for(i = msBlk->next_fragment, n = SQUASHFS_CACHED_FRAGMENTS;
- n && msBlk->fragment[i].locked; n--, i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS);
-
- if(n == 0) {
- up(&msBlk->fragment_mutex);
- sleep_on(&msBlk->fragment_wait_queue);
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+
+ while ( 1 ) {
+ down(&msblk->fragment_mutex);
+
+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
+ msblk->fragment[i].block != start_block; i++);
+
+ if (i == SQUASHFS_CACHED_FRAGMENTS) {
+ for (i = msblk->next_fragment, n =
+ SQUASHFS_CACHED_FRAGMENTS; n &&
+ msblk->fragment[i].locked; n--, i = (i + 1) %
+ SQUASHFS_CACHED_FRAGMENTS);
+
+ if (n == 0) {
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&msblk->fragment_wait_queue,
+ &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ up(&msblk->fragment_mutex);
+ schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&msblk->fragment_wait_queue,
+ &wait);
continue;
}
- msBlk->next_fragment = (msBlk->next_fragment + 1) % SQUASHFS_CACHED_FRAGMENTS;
+ msblk->next_fragment = (msblk->next_fragment + 1) %
+ SQUASHFS_CACHED_FRAGMENTS;
- if(msBlk->fragment[i].data == NULL)
- if(!(msBlk->fragment[i].data = (unsigned char *)
- kmalloc(SQUASHFS_FILE_MAX_SIZE, GFP_KERNEL))) {
- ERROR("Failed to allocate fragment cache block\n");
- up(&msBlk->fragment_mutex);
- return NULL;
+ if (msblk->fragment[i].data == NULL)
+ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
+ (SQUASHFS_FILE_MAX_SIZE))) {
+ ERROR("Failed to allocate fragment "
+ "cache block\n");
+ up(&msblk->fragment_mutex);
+ goto out;
}
- msBlk->fragment[i].block = SQUASHFS_INVALID_BLK;
- msBlk->fragment[i].locked = 1;
- up(&msBlk->fragment_mutex);
- if(!(msBlk->fragment[i].length = read_data(s, msBlk->fragment[i].data, start_block, length,
- 1, NULL))) {
- ERROR("Unable to read fragment cache block [%x]\n", start_block);
- msBlk->fragment[i].locked = 0;
- return NULL;
+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
+ msblk->fragment[i].locked = 1;
+ up(&msblk->fragment_mutex);
+
+ if (!(msblk->fragment[i].length = squashfs_read_data(s,
+ msblk->fragment[i].data,
+ start_block, length, NULL))) {
+ ERROR("Unable to read fragment cache block "
+ "[%llx]\n", start_block);
+ msblk->fragment[i].locked = 0;
+ goto out;
}
- msBlk->fragment[i].block = start_block;
- TRACE("New fragment %d, start block %d, locked %d\n", i, msBlk->fragment[i].block, msBlk->fragment[i].locked);
- return &msBlk->fragment[i];
+
+ msblk->fragment[i].block = start_block;
+ TRACE("New fragment %d, start block %lld, locked %d\n",
+ i, msblk->fragment[i].block,
+ msblk->fragment[i].locked);
+ break;
}
- msBlk->fragment[i].locked ++;
- up(&msBlk->fragment_mutex);
-
- TRACE("Got fragment %d, start block %d, locked %d\n", i, msBlk->fragment[i].block, msBlk->fragment[i].locked);
- return &msBlk->fragment[i];
+ msblk->fragment[i].locked++;
+ up(&msblk->fragment_mutex);
+ TRACE("Got fragment %d, start block %lld, locked %d\n", i,
+ msblk->fragment[i].block,
+ msblk->fragment[i].locked);
+ break;
}
+
+ return &msblk->fragment[i];
+
+out:
+ return NULL;
}
-#ifdef SQUASHFS_1_0_COMPATIBILITY
-static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode inode)
+static struct inode *squashfs_new_inode(struct super_block *s,
+ struct squashfs_base_inode_header *inodeb)
{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
struct inode *i = new_inode(s);
- squashfs_sb_info *msBlk = &s->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
- unsigned int block = SQUASHFS_INODE_BLK(inode) + sBlk->inode_table_start;
- unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
- unsigned int next_block, next_offset;
- squashfs_base_inode_header_1 inodeb;
-
- TRACE("Entered squashfs_iget_1\n");
- if(msBlk->swap) {
- squashfs_base_inode_header_1 sinodeb;
+ if (i) {
+ i->i_ino = inodeb->inode_number;
+ i->i_mtime = inodeb->mtime;
+ i->i_atime = inodeb->mtime;
+ i->i_ctime = inodeb->mtime;
+ i->i_uid = msblk->uid[inodeb->uid];
+ i->i_mode = inodeb->mode;
+ i->i_size = 0;
+ if (inodeb->guid == SQUASHFS_GUIDS)
+ i->i_gid = i->i_uid;
+ else
+ i->i_gid = msblk->guid[inodeb->guid];
+ }
- if(!squashfs_get_cached_block(s, (char *) &sinodeb, block, offset,
- sizeof(sinodeb), &next_block, &next_offset))
- goto failed_read;
- SQUASHFS_SWAP_BASE_INODE_HEADER_1(&inodeb, &sinodeb, sizeof(sinodeb));
- } else
- if(!squashfs_get_cached_block(s, (char *) &inodeb, block, offset,
- sizeof(inodeb), &next_block, &next_offset))
- goto failed_read;
+ return i;
+}
- i->i_nlink = 1;
- i->i_mtime = sBlk->mkfs_time;
- i->i_atime = sBlk->mkfs_time;
- i->i_ctime = sBlk->mkfs_time;
+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
+{
+ struct inode *i;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ long long block = SQUASHFS_INODE_BLK(inode) +
+ sblk->inode_table_start;
+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+ long long next_block;
+ unsigned int next_offset;
+ union squashfs_inode_header id, sid;
+ struct squashfs_base_inode_header *inodeb = &id.base,
+ *sinodeb = &sid.base;
- if(inodeb.inode_type != SQUASHFS_IPC_TYPE)
- i->i_uid = msBlk->uid[((inodeb.inode_type - 1) / SQUASHFS_TYPES) * 16 + inodeb.uid];
- i->i_ino = SQUASHFS_MK_VFS_INODE(block - sBlk->inode_table_start, offset);
+ TRACE("Entered squashfs_iget\n");
- i->i_mode = inodeb.mode;
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
+ offset, sizeof(*sinodeb), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
+ sizeof(*sinodeb));
+ } else
+ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
+ offset, sizeof(*inodeb), &next_block,
+ &next_offset))
+ goto failed_read;
- switch(inodeb.inode_type == SQUASHFS_IPC_TYPE ? SQUASHFS_IPC_TYPE : (inodeb.inode_type - 1) % SQUASHFS_TYPES + 1) {
+ switch(inodeb->inode_type) {
case SQUASHFS_FILE_TYPE: {
- squashfs_reg_inode_header_1 inodep;
-
- if(msBlk->swap) {
- squashfs_reg_inode_header_1 sinodep;
-
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
+ unsigned int frag_size;
+ long long frag_blk;
+ struct squashfs_reg_inode_header *inodep = &id.reg;
+ struct squashfs_reg_inode_header *sinodep = &sid.reg;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
goto failed_read;
- SQUASHFS_SWAP_REG_INODE_HEADER_1(&inodep, &sinodep);
+ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
} else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
goto failed_read;
- i->i_size = inodep.file_size;
+ frag_blk = SQUASHFS_INVALID_BLK;
+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
+ !get_fragment_location(s,
+ inodep->fragment, &frag_blk, &frag_size))
+ goto failed_read;
+
+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
+ goto failed_read1;
+
+ i->i_nlink = 1;
+ i->i_size = inodep->file_size;
i->i_fop = &generic_ro_fops;
- if(sBlk->block_size > 4096)
+ i->i_mode |= S_IFREG;
+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+ i->i_blksize = PAGE_CACHE_SIZE;
+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
+ SQUASHFS_I(i)->start_block = inodep->start_block;
+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
+ SQUASHFS_I(i)->offset = next_offset;
+ if (sblk->block_size > 4096)
i->i_data.a_ops = &squashfs_aops;
- else if(sBlk->block_size == 4096)
- i->i_data.a_ops = &squashfs_aops_4K;
else
- i->i_data.a_ops = &squashfs_aops_lessthan4K;
+ i->i_data.a_ops = &squashfs_aops_4K;
+
+ TRACE("File inode %x:%x, start_block %llx, "
+ "block_list_start %llx, offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep->start_block, next_block,
+ next_offset);
+ break;
+ }
+ case SQUASHFS_LREG_TYPE: {
+ unsigned int frag_size;
+ long long frag_blk;
+ struct squashfs_lreg_inode_header *inodep = &id.lreg;
+ struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ frag_blk = SQUASHFS_INVALID_BLK;
+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
+ !get_fragment_location(s,
+ inodep->fragment, &frag_blk, &frag_size))
+ goto failed_read;
+
+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
+ goto failed_read1;
+
+ i->i_nlink = inodep->nlink;
+ i->i_size = inodep->file_size;
+ i->i_fop = &generic_ro_fops;
i->i_mode |= S_IFREG;
- i->i_mtime = inodep.mtime;
- i->i_atime = inodep.mtime;
- i->i_ctime = inodep.mtime;
i->i_blocks = ((i->i_size - 1) >> 9) + 1;
i->i_blksize = PAGE_CACHE_SIZE;
- i->u.squashfs_i.fragment_start_block = SQUASHFS_INVALID_BLK;
- i->u.squashfs_i.fragment_offset = 0;
- i->u.squashfs_i.start_block = inodep.start_block;
- i->u.squashfs_i.block_list_start = next_block;
- i->u.squashfs_i.offset = next_offset;
- TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n",
- SQUASHFS_INODE_BLK(inode), offset, inodep.start_block, next_block, next_offset);
+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
+ SQUASHFS_I(i)->start_block = inodep->start_block;
+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
+ SQUASHFS_I(i)->offset = next_offset;
+ if (sblk->block_size > 4096)
+ i->i_data.a_ops = &squashfs_aops;
+ else
+ i->i_data.a_ops = &squashfs_aops_4K;
+
+ TRACE("File inode %x:%x, start_block %llx, "
+ "block_list_start %llx, offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep->start_block, next_block,
+ next_offset);
break;
}
case SQUASHFS_DIR_TYPE: {
- squashfs_dir_inode_header_1 inodep;
+ struct squashfs_dir_inode_header *inodep = &id.dir;
+ struct squashfs_dir_inode_header *sinodep = &sid.dir;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
+ goto failed_read;
- if(msBlk->swap) {
- squashfs_dir_inode_header_1 sinodep;
+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
+ goto failed_read1;
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
+ i->i_nlink = inodep->nlink;
+ i->i_size = inodep->file_size;
+ i->i_op = &squashfs_dir_inode_ops;
+ i->i_fop = &squashfs_dir_ops;
+ i->i_mode |= S_IFDIR;
+ SQUASHFS_I(i)->start_block = inodep->start_block;
+ SQUASHFS_I(i)->offset = inodep->offset;
+ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
+
+ TRACE("Directory inode %x:%x, start_block %x, offset "
+ "%x\n", SQUASHFS_INODE_BLK(inode),
+ offset, inodep->start_block,
+ inodep->offset);
+ break;
+ }
+ case SQUASHFS_LDIR_TYPE: {
+ struct squashfs_ldir_inode_header *inodep = &id.ldir;
+ struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
goto failed_read;
- SQUASHFS_SWAP_DIR_INODE_HEADER_1(&inodep, &sinodep);
+ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
+ sinodep);
} else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
goto failed_read;
- i->i_size = inodep.file_size;
+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
+ goto failed_read1;
+
+ i->i_nlink = inodep->nlink;
+ i->i_size = inodep->file_size;
i->i_op = &squashfs_dir_inode_ops;
i->i_fop = &squashfs_dir_ops;
i->i_mode |= S_IFDIR;
- i->i_mtime = inodep.mtime;
- i->i_atime = inodep.mtime;
- i->i_ctime = inodep.mtime;
- i->u.squashfs_i.start_block = inodep.start_block;
- i->u.squashfs_i.offset = inodep.offset;
- TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset,
- inodep.start_block, inodep.offset);
+ SQUASHFS_I(i)->start_block = inodep->start_block;
+ SQUASHFS_I(i)->offset = inodep->offset;
+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
+ SQUASHFS_I(i)->u.s2.directory_index_offset =
+ next_offset;
+ SQUASHFS_I(i)->u.s2.directory_index_count =
+ inodep->i_count;
+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
+
+ TRACE("Long directory inode %x:%x, start_block %x, "
+ "offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep->start_block, inodep->offset);
break;
}
case SQUASHFS_SYMLINK_TYPE: {
- squashfs_symlink_inode_header_1 inodep;
+ struct squashfs_symlink_inode_header *inodep =
+ &id.symlink;
+ struct squashfs_symlink_inode_header *sinodep =
+ &sid.symlink;
- if(msBlk->swap) {
- squashfs_symlink_inode_header_1 sinodep;
-
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
goto failed_read;
- SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(&inodep, &sinodep);
+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
+ sinodep);
} else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
goto failed_read;
- i->i_size = inodep.symlink_size;
+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
+ goto failed_read1;
+
+ i->i_nlink = inodep->nlink;
+ i->i_size = inodep->symlink_size;
i->i_op = &page_symlink_inode_operations;
i->i_data.a_ops = &squashfs_symlink_aops;
i->i_mode |= S_IFLNK;
- i->u.squashfs_i.start_block = next_block;
- i->u.squashfs_i.offset = next_offset;
- TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n",
- SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset);
+ SQUASHFS_I(i)->start_block = next_block;
+ SQUASHFS_I(i)->offset = next_offset;
+
+ TRACE("Symbolic link inode %x:%x, start_block %llx, "
+ "offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ next_block, next_offset);
break;
}
case SQUASHFS_BLKDEV_TYPE:
case SQUASHFS_CHRDEV_TYPE: {
- squashfs_dev_inode_header_1 inodep;
-
- if(msBlk->swap) {
- squashfs_dev_inode_header_1 sinodep;
-
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
+ struct squashfs_dev_inode_header *inodep = &id.dev;
+ struct squashfs_dev_inode_header *sinodep = &sid.dev;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
goto failed_read;
- SQUASHFS_SWAP_DEV_INODE_HEADER_1(&inodep, &sinodep);
+ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
} else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
goto failed_read;
- i->i_size = 0;
- i->i_mode |= (inodeb.inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK;
- init_special_inode(i, i->i_mode, inodep.rdev);
- TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep.rdev);
- break;
- }
- case SQUASHFS_IPC_TYPE: {
- squashfs_ipc_inode_header_1 inodep;
+ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
+ goto failed_read1;
- if(msBlk->swap) {
- squashfs_ipc_inode_header_1 sinodep;
+ i->i_nlink = inodep->nlink;
+ i->i_mode |= (inodeb->inode_type ==
+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
+ S_IFBLK;
+ init_special_inode(i, i->i_mode, inodep->rdev);
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
+ TRACE("Device inode %x:%x, rdev %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep->rdev);
+ break;
+ }
+ case SQUASHFS_FIFO_TYPE:
+ case SQUASHFS_SOCKET_TYPE: {
+ struct squashfs_ipc_inode_header *inodep = &id.ipc;
+ struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
goto failed_read;
- SQUASHFS_SWAP_IPC_INODE_HEADER_1(&inodep, &sinodep);
+ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
} else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
goto failed_read;
- i->i_size = 0;
- i->i_mode |= (inodep.type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK;
- i->i_uid = msBlk->uid[inodep.offset * 16 + inodeb.uid];
+ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
+ goto failed_read1;
+
+ i->i_nlink = inodep->nlink;
+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
+ ? S_IFIFO : S_IFSOCK;
init_special_inode(i, i->i_mode, 0);
break;
}
default:
- ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb.inode_type);
- goto failed_read1;
+ ERROR("Unknown inode type %d in squashfs_iget!\n",
+ inodeb->inode_type);
+ goto failed_read1;
}
- if(inodeb.guid == 15)
- i->i_gid = i->i_uid;
- else
- i->i_gid = msBlk->guid[inodeb.guid];
-
+ insert_inode_hash(i);
return i;
failed_read:
- ERROR("Unable to read inode [%x:%x]\n", block, offset);
+ ERROR("Unable to read inode [%llx:%x]\n", block, offset);
failed_read1:
return NULL;
}
-#endif
-static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode)
+int read_fragment_index_table(struct super_block *s)
{
- struct inode *i = new_inode(s);
- squashfs_sb_info *msBlk = &s->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
- unsigned int block = SQUASHFS_INODE_BLK(inode) + sBlk->inode_table_start;
- unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
- unsigned int next_block, next_offset;
- squashfs_base_inode_header inodeb;
-
- TRACE("Entered squashfs_iget\n");
-
- if(msBlk->swap) {
- squashfs_base_inode_header sinodeb;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
- if(!squashfs_get_cached_block(s, (char *) &sinodeb, block, offset,
- sizeof(sinodeb), &next_block, &next_offset))
- goto failed_read;
- SQUASHFS_SWAP_BASE_INODE_HEADER(&inodeb, &sinodeb, sizeof(sinodeb));
- } else
- if(!squashfs_get_cached_block(s, (char *) &inodeb, block, offset,
- sizeof(inodeb), &next_block, &next_offset))
- goto failed_read;
-
- i->i_nlink = 1;
-
- i->i_mtime = sBlk->mkfs_time;
- i->i_atime = sBlk->mkfs_time;
- i->i_ctime = sBlk->mkfs_time;
-
- if(inodeb.inode_type != SQUASHFS_IPC_TYPE)
- i->i_uid = msBlk->uid[((inodeb.inode_type - 1) / SQUASHFS_TYPES) * 16 + inodeb.uid];
- i->i_ino = SQUASHFS_MK_VFS_INODE(block - sBlk->inode_table_start, offset);
-
- i->i_mode = inodeb.mode;
-
- switch(inodeb.inode_type) {
- case SQUASHFS_FILE_TYPE: {
- squashfs_reg_inode_header inodep;
-
- if(msBlk->swap) {
- squashfs_reg_inode_header sinodep;
-
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
- goto failed_read;
- SQUASHFS_SWAP_REG_INODE_HEADER(&inodep, &sinodep);
- } else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
- goto failed_read;
+ if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
+ (sblk->fragments), GFP_KERNEL))) {
+ ERROR("Failed to allocate uid/gid table\n");
+ return 0;
+ }
+
+ if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
+ !squashfs_read_data(s, (char *)
+ msblk->fragment_index,
+ sblk->fragment_table_start,
+ SQUASHFS_FRAGMENT_INDEX_BYTES
+ (sblk->fragments) |
+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+ ERROR("unable to read fragment index table\n");
+ return 0;
+ }
- i->u.squashfs_i.fragment_start_block = SQUASHFS_INVALID_BLK;
- if(inodep.fragment != SQUASHFS_INVALID_BLK && !get_fragment_location(s, inodep.fragment,
- &i->u.squashfs_i.fragment_start_block, &i->u.squashfs_i.fragment_size))
- goto failed_read;
+ if (msblk->swap) {
+ int i;
+ long long fragment;
- i->u.squashfs_i.fragment_offset = inodep.offset;
- i->i_size = inodep.file_size;
- i->i_fop = &generic_ro_fops;
- if(sBlk->block_size > 4096)
- i->i_data.a_ops = &squashfs_aops;
- else
- i->i_data.a_ops = &squashfs_aops_4K;
- i->i_mode |= S_IFREG;
- i->i_mtime = inodep.mtime;
- i->i_atime = inodep.mtime;
- i->i_ctime = inodep.mtime;
- i->i_blocks = ((i->i_size - 1) >> 9) + 1;
- i->i_blksize = PAGE_CACHE_SIZE;
- i->u.squashfs_i.start_block = inodep.start_block;
- i->u.squashfs_i.block_list_start = next_block;
- i->u.squashfs_i.offset = next_offset;
- TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x fragment_index %x fragment_offset %x\n",
- SQUASHFS_INODE_BLK(inode), offset, inodep.start_block, next_block, next_offset, inodep.fragment, inodep.offset);
- break;
+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
+ i++) {
+ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
+ &msblk->fragment_index[i], 1);
+ msblk->fragment_index[i] = fragment;
}
- case SQUASHFS_DIR_TYPE: {
- squashfs_dir_inode_header inodep;
+ }
- if(msBlk->swap) {
- squashfs_dir_inode_header sinodep;
+ return 1;
+}
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
- goto failed_read;
- SQUASHFS_SWAP_DIR_INODE_HEADER(&inodep, &sinodep);
- } else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
- goto failed_read;
- i->i_size = inodep.file_size;
- i->i_op = &squashfs_dir_inode_ops;
- i->i_fop = &squashfs_dir_ops;
- i->i_mode |= S_IFDIR;
- i->i_mtime = inodep.mtime;
- i->i_atime = inodep.mtime;
- i->i_ctime = inodep.mtime;
- i->u.squashfs_i.start_block = inodep.start_block;
- i->u.squashfs_i.offset = inodep.offset;
- TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset,
- inodep.start_block, inodep.offset);
- break;
+static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
+{
+ struct squashfs_super_block *sblk = &msblk->sblk;
+
+ msblk->iget = squashfs_iget;
+ msblk->read_blocklist = read_blocklist;
+ msblk->read_fragment_index_table = read_fragment_index_table;
+
+ if (sblk->s_major == 1) {
+ if (!squashfs_1_0_supported(msblk)) {
+ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
+ "are unsupported\n");
+ SERROR("Please recompile with "
+ "Squashfs 1.0 support enabled\n");
+ return 0;
}
- case SQUASHFS_SYMLINK_TYPE: {
- squashfs_symlink_inode_header inodep;
-
- if(msBlk->swap) {
- squashfs_symlink_inode_header sinodep;
-
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
- goto failed_read;
- SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep);
- } else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
- goto failed_read;
-
- i->i_size = inodep.symlink_size;
- i->i_op = &page_symlink_inode_operations;
- i->i_data.a_ops = &squashfs_symlink_aops;
- i->i_mode |= S_IFLNK;
- i->u.squashfs_i.start_block = next_block;
- i->u.squashfs_i.offset = next_offset;
- TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n",
- SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset);
- break;
- }
- case SQUASHFS_BLKDEV_TYPE:
- case SQUASHFS_CHRDEV_TYPE: {
- squashfs_dev_inode_header inodep;
-
- if(msBlk->swap) {
- squashfs_dev_inode_header sinodep;
-
- if(!squashfs_get_cached_block(s, (char *) &sinodep, block, offset, sizeof(sinodep),
- &next_block, &next_offset))
- goto failed_read;
- SQUASHFS_SWAP_DEV_INODE_HEADER(&inodep, &sinodep);
- } else
- if(!squashfs_get_cached_block(s, (char *) &inodep, block, offset, sizeof(inodep),
- &next_block, &next_offset))
- goto failed_read;
-
- i->i_size = 0;
- i->i_mode |= (inodeb.inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK;
- init_special_inode(i, i->i_mode, inodep.rdev);
- TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep.rdev);
- break;
- }
- case SQUASHFS_FIFO_TYPE:
- case SQUASHFS_SOCKET_TYPE: {
- i->i_size = 0;
- i->i_mode |= (inodeb.inode_type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK;
- init_special_inode(i, i->i_mode, 0);
- break;
- }
- default:
- ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb.inode_type);
- goto failed_read1;
+ } else if (sblk->s_major == 2) {
+ if (!squashfs_2_0_supported(msblk)) {
+ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
+ "are unsupported\n");
+ SERROR("Please recompile with "
+ "Squashfs 2.0 support enabled\n");
+ return 0;
+ }
+ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
+ SQUASHFS_MINOR) {
+ SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
+ "filesystem\n", sblk->s_major, sblk->s_minor);
+ SERROR("Please update your kernel\n");
+ return 0;
}
-
- if(inodeb.guid == SQUASHFS_GUIDS)
- i->i_gid = i->i_uid;
- else
- i->i_gid = msBlk->guid[inodeb.guid];
-
- return i;
-failed_read:
- ERROR("Unable to read inode [%x:%x]\n", block, offset);
-
-failed_read1:
- return NULL;
+ return 1;
}
@@ -804,221 +968,204 @@ static struct super_block *squashfs_read_super(struct super_block *s,
void *data, int silent)
{
kdev_t dev = s->s_dev;
- squashfs_sb_info *msBlk = &s->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
int i;
-
- TRACE("Entered squashfs_read_superblock\n");
-
- msBlk->devblksize = get_hardsect_size(dev);
- if(msBlk->devblksize < BLOCK_SIZE)
- msBlk->devblksize = BLOCK_SIZE;
- msBlk->devblksize_log2 = ffz(~msBlk->devblksize);
- set_blocksize(dev, msBlk->devblksize);
- s->s_blocksize = msBlk->devblksize;
- s->s_blocksize_bits = msBlk->devblksize_log2;
-
- init_MUTEX(&msBlk->read_page_mutex);
- init_MUTEX(&msBlk->block_cache_mutex);
- init_MUTEX(&msBlk->fragment_mutex);
+ struct inode *root;
+
+ msblk->devblksize = get_hardsect_size(dev);
+ if(msblk->devblksize < BLOCK_SIZE)
+ msblk->devblksize = BLOCK_SIZE;
+ msblk->devblksize_log2 = ffz(~msblk->devblksize);
+ set_blocksize(dev, msblk->devblksize);
+ s->s_blocksize = msblk->devblksize;
+ s->s_blocksize_bits = msblk->devblksize_log2;
+
+ init_MUTEX(&msblk->read_data_mutex);
+ init_MUTEX(&msblk->read_page_mutex);
+ init_MUTEX(&msblk->block_cache_mutex);
+ init_MUTEX(&msblk->fragment_mutex);
- init_waitqueue_head(&msBlk->waitq);
- init_waitqueue_head(&msBlk->fragment_wait_queue);
+ init_waitqueue_head(&msblk->waitq);
+ init_waitqueue_head(&msblk->fragment_wait_queue);
- if(!read_data(s, (char *) sBlk, SQUASHFS_START, sizeof(squashfs_super_block) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
+ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
+ sizeof(struct squashfs_super_block) |
+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
SERROR("unable to read superblock\n");
goto failed_mount;
}
/* Check it is a SQUASHFS superblock */
- msBlk->swap = 0;
- if((s->s_magic = sBlk->s_magic) != SQUASHFS_MAGIC) {
- if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) {
- squashfs_super_block sblk;
- WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", bdevname(dev));
- SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk);
- memcpy(sBlk, &sblk, sizeof(squashfs_super_block));
- msBlk->swap = 1;
+ msblk->swap = 0;
+ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
+ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
+ struct squashfs_super_block ssblk;
+
+ WARNING("Mounting a different endian SQUASHFS "
+ "filesystem on %s\n", bdevname(dev));
+
+ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
+ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
+ msblk->swap = 1;
} else {
- SERROR("Can't find a SQUASHFS superblock on %s\n", bdevname(dev));
+ SERROR("Can't find a SQUASHFS superblock on %s\n",
+ bdevname(dev));
goto failed_mount;
}
}
/* Check the MAJOR & MINOR versions */
-#ifdef SQUASHFS_1_0_COMPATIBILITY
- if((sBlk->s_major != 1) && (sBlk->s_major != 2 || sBlk->s_minor > SQUASHFS_MINOR)) {
- SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (1 : x) or (2 : <= %d)\n",
- sBlk->s_major, sBlk->s_minor, SQUASHFS_MINOR);
+ if(!supported_squashfs_filesystem(msblk, silent))
goto failed_mount;
- }
- if(sBlk->s_major == 1)
- sBlk->block_size = sBlk->block_size_1;
-#else
- if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
- SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (%d: <= %d)\n",
- sBlk->s_major, sBlk->s_minor, SQUASHFS_MAJOR, SQUASHFS_MINOR);
- goto failed_mount;
- }
-#endif
TRACE("Found valid superblock on %s\n", bdevname(dev));
- TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
- TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : "");
- TRACE("Check data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not");
- TRACE("Filesystem size %d bytes\n", sBlk->bytes_used);
- TRACE("Block size %d\n", sBlk->block_size);
- TRACE("Number of inodes %d\n", sBlk->inodes);
- if(sBlk->s_major > 1)
- TRACE("Number of fragments %d\n", sBlk->fragments);
- TRACE("Number of uids %d\n", sBlk->no_uids);
- TRACE("Number of gids %d\n", sBlk->no_guids);
- TRACE("sBlk->inode_table_start %x\n", sBlk->inode_table_start);
- TRACE("sBlk->directory_table_start %x\n", sBlk->directory_table_start);
- if(sBlk->s_major > 1)
- TRACE("sBlk->fragment_table_start %x\n", sBlk->fragment_table_start);
- TRACE("sBlk->uid_start %x\n", sBlk->uid_start);
+ TRACE("Inodes are %scompressed\n",
+ SQUASHFS_UNCOMPRESSED_INODES
+ (sblk->flags) ? "un" : "");
+ TRACE("Data is %scompressed\n",
+ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
+ ? "un" : "");
+ TRACE("Check data is %s present in the filesystem\n",
+ SQUASHFS_CHECK_DATA(sblk->flags) ?
+ "" : "not");
+ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
+ TRACE("Block size %d\n", sblk->block_size);
+ TRACE("Number of inodes %d\n", sblk->inodes);
+ if (sblk->s_major > 1)
+ TRACE("Number of fragments %d\n", sblk->fragments);
+ TRACE("Number of uids %d\n", sblk->no_uids);
+ TRACE("Number of gids %d\n", sblk->no_guids);
+ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
+ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
+ if (sblk->s_major > 1)
+ TRACE("sblk->fragment_table_start %llx\n",
+ sblk->fragment_table_start);
+ TRACE("sblk->uid_start %llx\n", sblk->uid_start);
s->s_flags |= MS_RDONLY;
s->s_op = &squashfs_ops;
/* Init inode_table block pointer array */
- if(!(msBlk->block_cache = (squashfs_cache *) kmalloc(sizeof(squashfs_cache) * SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
+ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
+ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
ERROR("Failed to allocate block cache\n");
goto failed_mount;
}
- for(i = 0; i < SQUASHFS_CACHED_BLKS; i++)
- msBlk->block_cache[i].block = SQUASHFS_INVALID_BLK;
+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
+ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
- msBlk->next_cache = 0;
+ msblk->next_cache = 0;
/* Allocate read_data block */
- msBlk->read_size = (sBlk->block_size < SQUASHFS_METADATA_SIZE) ? SQUASHFS_METADATA_SIZE : sBlk->block_size;
- if(!(msBlk->read_data = (char *) kmalloc(msBlk->read_size, GFP_KERNEL))) {
+ msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
+ SQUASHFS_METADATA_SIZE :
+ sblk->block_size;
+
+ if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
ERROR("Failed to allocate read_data block\n");
- goto failed_mount1;
+ goto failed_mount;
}
/* Allocate read_page block */
- if(sBlk->block_size > PAGE_CACHE_SIZE &&
- !(msBlk->read_page = (char *) kmalloc(sBlk->block_size, GFP_KERNEL))) {
+ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
ERROR("Failed to allocate read_page block\n");
- goto failed_mount2;
+ goto failed_mount;
}
/* Allocate uid and gid tables */
- if(!(msBlk->uid = (squashfs_uid *) kmalloc((sBlk->no_uids +
- sBlk->no_guids) * sizeof(squashfs_uid), GFP_KERNEL))) {
+ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
+ sizeof(unsigned int), GFP_KERNEL))) {
ERROR("Failed to allocate uid/gid table\n");
- goto failed_mount3;
+ goto failed_mount;
}
- msBlk->guid = msBlk->uid + sBlk->no_uids;
+ msblk->guid = msblk->uid + sblk->no_uids;
- if(msBlk->swap) {
- squashfs_uid suid[sBlk->no_uids + sBlk->no_guids];
-
- if(!read_data(s, (char *) &suid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) *
- sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
- SERROR("unable to read uid/gid table\n");
- goto failed_mount4;
+ if (msblk->swap) {
+ unsigned int suid[sblk->no_uids + sblk->no_guids];
+
+ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
+ ((sblk->no_uids + sblk->no_guids) *
+ sizeof(unsigned int)) |
+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+ ERROR("unable to read uid/gid table\n");
+ goto failed_mount;
}
- SQUASHFS_SWAP_DATA(msBlk->uid, suid, (sBlk->no_uids + sBlk->no_guids), (sizeof(squashfs_uid) * 8));
+
+ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
+ sblk->no_guids), (sizeof(unsigned int) * 8));
} else
- if(!read_data(s, (char *) msBlk->uid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) *
- sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
- SERROR("unable to read uid/gid table\n");
- goto failed_mount4;
+ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
+ ((sblk->no_uids + sblk->no_guids) *
+ sizeof(unsigned int)) |
+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+ ERROR("unable to read uid/gid table\n");
+ goto failed_mount;
}
-#ifdef SQUASHFS_1_0_COMPATIBILITY
- if(sBlk->s_major == 1) {
- msBlk->iget = squashfs_iget_1;
- msBlk->read_blocklist = read_blocklist_1;
- msBlk->fragment = (struct squashfs_fragment_cache *) msBlk->fragment_index = NULL;
+ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
goto allocate_root;
- }
-#endif
- msBlk->iget = squashfs_iget;
- msBlk->read_blocklist = read_blocklist;
- if(!(msBlk->fragment = (struct squashfs_fragment_cache *) kmalloc(sizeof(struct squashfs_fragment_cache) * SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
+ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
+ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
ERROR("Failed to allocate fragment block cache\n");
- goto failed_mount4;
+ goto failed_mount;
}
- for(i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
- msBlk->fragment[i].locked = 0;
- msBlk->fragment[i].block = SQUASHFS_INVALID_BLK;
- msBlk->fragment[i].data = NULL;
+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
+ msblk->fragment[i].locked = 0;
+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
+ msblk->fragment[i].data = NULL;
}
- msBlk->next_fragment = 0;
+ msblk->next_fragment = 0;
/* Allocate fragment index table */
- if(!(msBlk->fragment_index = (squashfs_fragment_index *) kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), GFP_KERNEL))) {
- ERROR("Failed to allocate uid/gid table\n");
- goto failed_mount5;
- }
-
- if(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments) &&
- !read_data(s, (char *) msBlk->fragment_index, sBlk->fragment_table_start,
- SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
- SERROR("unable to read fragment index table\n");
- goto failed_mount6;
- }
-
- if(msBlk->swap) {
- int i;
- squashfs_fragment_index fragment;
-
- for(i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); i++) {
- SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), &msBlk->fragment_index[i], 1);
- msBlk->fragment_index[i] = fragment;
- }
- }
+ if(msblk->read_fragment_index_table(s) == 0)
+ goto failed_mount;
-#ifdef SQUASHFS_1_0_COMPATIBILITY
allocate_root:
-#endif
- if(!(s->s_root = d_alloc_root((msBlk->iget)(s, sBlk->root_inode)))) {
+ if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
+ goto failed_mount;
+
+ if ((s->s_root = d_alloc_root(root)) == NULL) {
ERROR("Root inode create failed\n");
- goto failed_mount5;
+ iput(root);
+ goto failed_mount;
}
TRACE("Leaving squashfs_read_super\n");
return s;
-failed_mount6:
- kfree(msBlk->fragment_index);
-failed_mount5:
- kfree(msBlk->fragment);
-failed_mount4:
- kfree(msBlk->uid);
-failed_mount3:
- kfree(msBlk->read_page);
-failed_mount2:
- kfree(msBlk->read_data);
-failed_mount1:
- kfree(msBlk->block_cache);
failed_mount:
+ kfree(msblk->fragment_index);
+ kfree(msblk->fragment);
+ kfree(msblk->uid);
+ kfree(msblk->read_page);
+ kfree(msblk->read_data);
+ kfree(msblk->block_cache);
+ kfree(msblk->fragment_index_2);
return NULL;
}
static int squashfs_statfs(struct super_block *s, struct statfs *buf)
{
- squashfs_super_block *sBlk = &s->u.squashfs_sb.sBlk;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
TRACE("Entered squashfs_statfs\n");
+
buf->f_type = SQUASHFS_MAGIC;
- buf->f_bsize = sBlk->block_size;
- buf->f_blocks = ((sBlk->bytes_used - 1) >> sBlk->block_log) + 1;
+ buf->f_bsize = sblk->block_size;
+ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
buf->f_bfree = buf->f_bavail = 0;
- buf->f_files = sBlk->inodes;
+ buf->f_files = sblk->inodes;
buf->f_ffree = 0;
buf->f_namelen = SQUASHFS_NAME_LEN;
+
return 0;
}
@@ -1027,35 +1174,41 @@ static int squashfs_symlink_readpage(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
- int block = inode->u.squashfs_i.start_block;
- int offset = inode->u.squashfs_i.offset;
- void *pageaddr = kmap(page);
-
- TRACE("Entered squashfs_symlink_readpage, page index %x, start block %x, offset %x\n",
- (unsigned int) page->index, inode->u.squashfs_i.start_block, inode->u.squashfs_i.offset);
-
- for(length = 0; length < index; length += bytes) {
- if(!(bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, offset,
- PAGE_CACHE_SIZE, &block, &offset))) {
- ERROR("Unable to read symbolic link [%x:%x]\n", block, offset);
+ long long block = SQUASHFS_I(inode)->start_block;
+ int offset = SQUASHFS_I(inode)->offset;
+ void *pageaddr = kmap(page);
+
+ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
+ "%llx, offset %x\n", page->index,
+ SQUASHFS_I(inode)->start_block,
+ SQUASHFS_I(inode)->offset);
+
+ for (length = 0; length < index; length += bytes) {
+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
+ block, offset, PAGE_CACHE_SIZE, &block,
+ &offset))) {
+ ERROR("Unable to read symbolic link [%llx:%x]\n", block,
+ offset);
goto skip_read;
}
}
- if(length != index) {
+ if (length != index) {
ERROR("(squashfs_symlink_readpage) length != index\n");
bytes = 0;
goto skip_read;
}
- bytes = (inode->i_size - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : inode->i_size - length;
- if(!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, bytes, &block, &offset)))
- ERROR("Unable to read symbolic link [%x:%x]\n", block, offset);
+ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
+ i_size_read(inode) - length;
+
+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
+ offset, bytes, &block, &offset)))
+ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
skip_read:
memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
kunmap(page);
- flush_dcache_page(page);
SetPageUptodate(page);
UnlockPage(page);
@@ -1063,155 +1216,358 @@ skip_read:
}
-#define SIZE 256
+struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
+{
+ struct meta_index *meta = NULL;
+ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
+ int i;
+
+ down(&msblk->meta_index_mutex);
+
+ TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
+
+ if(msblk->meta_index == NULL)
+ goto not_allocated;
+
+ for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
+ if (msblk->meta_index[i].inode_number == inode->i_ino &&
+ msblk->meta_index[i].offset >= offset &&
+ msblk->meta_index[i].offset <= index &&
+ msblk->meta_index[i].locked == 0) {
+ TRACE("locate_meta_index: entry %d, offset %d\n", i,
+ msblk->meta_index[i].offset);
+ meta = &msblk->meta_index[i];
+ offset = meta->offset;
+ }
-#ifdef SQUASHFS_1_0_COMPATIBILITY
-static unsigned int read_blocklist_1(struct inode *inode, int index, int readahead_blks,
- char *block_list, char **block_p, unsigned int *bsize)
+ if (meta)
+ meta->locked = 1;
+
+not_allocated:
+ up(&msblk->meta_index_mutex);
+
+ return meta;
+}
+
+
+struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
{
- squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;
- unsigned short *block_listp;
- int i = 0;
- int block_ptr = inode->u.squashfs_i.block_list_start;
- int offset = inode->u.squashfs_i.offset;
- int block = inode->u.squashfs_i.start_block;
-
- for(;;) {
- int blocks = (index + readahead_blks - i);
- if(blocks > (SIZE >> 1)) {
- if((index - i) <= (SIZE >> 1))
- blocks = index - i;
- else
- blocks = SIZE >> 1;
+ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
+ struct meta_index *meta = NULL;
+ int i;
+
+ down(&msblk->meta_index_mutex);
+
+ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
+
+ if(msblk->meta_index == NULL) {
+ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
+ SQUASHFS_META_NUMBER, GFP_KERNEL))) {
+ ERROR("Failed to allocate meta_index\n");
+ goto failed;
}
+ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
+ msblk->meta_index[i].inode_number = 0;
+ msblk->meta_index[i].locked = 0;
+ }
+ msblk->next_meta_index = 0;
+ }
- if(msBlk->swap) {
- unsigned char sblock_list[SIZE];
- if(!squashfs_get_cached_block(inode->i_sb, (char *) sblock_list, block_ptr, offset, blocks << 1, &block_ptr, &offset)) {
- ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
- return 0;
- }
- SQUASHFS_SWAP_SHORTS(((unsigned short *)block_list), ((unsigned short *)sblock_list), blocks);
- } else
- if(!squashfs_get_cached_block(inode->i_sb, (char *) block_list, block_ptr, offset, blocks << 1, &block_ptr, &offset)) {
- ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
- return 0;
- }
- for(block_listp = (unsigned short *) block_list; i < index && blocks; i ++, block_listp ++, blocks --)
- block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
- if(blocks >= readahead_blks)
- break;
+ for(i = SQUASHFS_META_NUMBER; i &&
+ msblk->meta_index[msblk->next_meta_index].locked; i --)
+ msblk->next_meta_index = (msblk->next_meta_index + 1) %
+ SQUASHFS_META_NUMBER;
+
+ if(i == 0) {
+ TRACE("empty_meta_index: failed!\n");
+ goto failed;
}
- if(bsize)
- *bsize = SQUASHFS_COMPRESSED_SIZE(*block_listp) | (!SQUASHFS_COMPRESSED(*block_listp) ? SQUASHFS_COMPRESSED_BIT_BLOCK : 0);
- else
- (unsigned short *) *block_p = block_listp;
- return block;
+ TRACE("empty_meta_index: returned meta entry %d, %p\n",
+ msblk->next_meta_index,
+ &msblk->meta_index[msblk->next_meta_index]);
+
+ meta = &msblk->meta_index[msblk->next_meta_index];
+ msblk->next_meta_index = (msblk->next_meta_index + 1) %
+ SQUASHFS_META_NUMBER;
+
+ meta->inode_number = inode->i_ino;
+ meta->offset = offset;
+ meta->skip = skip;
+ meta->entries = 0;
+ meta->locked = 1;
+
+failed:
+ up(&msblk->meta_index_mutex);
+ return meta;
}
-#endif
+void release_meta_index(struct inode *inode, struct meta_index *meta)
+{
+ meta->locked = 0;
+}
+
-static unsigned int read_blocklist(struct inode *inode, int index, int readahead_blks,
- char *block_list, char **block_p, unsigned int *bsize)
+static int read_block_index(struct super_block *s, int blocks, char *block_list,
+ long long *start_block, int *offset)
{
- squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
unsigned int *block_listp;
- int i = 0;
- int block_ptr = inode->u.squashfs_i.block_list_start;
- int offset = inode->u.squashfs_i.offset;
- int block = inode->u.squashfs_i.start_block;
-
- for(;;) {
- int blocks = (index + readahead_blks - i);
- if(blocks > (SIZE >> 2)) {
- if((index - i) <= (SIZE >> 2))
- blocks = index - i;
- else
- blocks = SIZE >> 2;
+ int block = 0;
+
+ if (msblk->swap) {
+ char sblock_list[blocks << 2];
+
+ if (!squashfs_get_cached_block(s, sblock_list, *start_block,
+ *offset, blocks << 2, start_block, offset)) {
+ ERROR("Unable to read block list [%llx:%x]\n",
+ *start_block, *offset);
+ goto failure;
+ }
+ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
+ ((unsigned int *)sblock_list), blocks);
+ } else
+ if (!squashfs_get_cached_block(s, block_list, *start_block,
+ *offset, blocks << 2, start_block, offset)) {
+ ERROR("Unable to read block list [%llx:%x]\n",
+ *start_block, *offset);
+ goto failure;
}
- if(msBlk->swap) {
- unsigned char sblock_list[SIZE];
- if(!squashfs_get_cached_block(inode->i_sb, (char *) sblock_list, block_ptr, offset, blocks << 2, &block_ptr, &offset)) {
- ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
- return 0;
- }
- SQUASHFS_SWAP_INTS(((unsigned int *)block_list), ((unsigned int *)sblock_list), blocks);
- } else
- if(!squashfs_get_cached_block(inode->i_sb, (char *) block_list, block_ptr, offset, blocks << 2, &block_ptr, &offset)) {
- ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
- return 0;
+ for (block_listp = (unsigned int *) block_list; blocks;
+ block_listp++, blocks --)
+ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
+
+ return block;
+
+failure:
+ return -1;
+}
+
+
+#define SIZE 256
+
+static inline int calculate_skip(int blocks) {
+ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
+ return skip >= 7 ? 7 : skip + 1;
+}
+
+
+static int get_meta_index(struct inode *inode, int index,
+ long long *index_block, int *index_offset,
+ long long *data_block, char *block_list)
+{
+ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
+ int offset = 0;
+ struct meta_index *meta;
+ struct meta_entry *meta_entry;
+ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
+ int cur_offset = SQUASHFS_I(inode)->offset;
+ long long cur_data_block = SQUASHFS_I(inode)->start_block;
+ int i;
+
+ index /= SQUASHFS_META_INDEXES * skip;
+
+ while ( offset < index ) {
+ meta = locate_meta_index(inode, index, offset + 1);
+
+ if (meta == NULL) {
+ if ((meta = empty_meta_index(inode, offset + 1,
+ skip)) == NULL)
+ goto all_done;
+ } else {
+ offset = index < meta->offset + meta->entries ? index :
+ meta->offset + meta->entries - 1;
+ meta_entry = &meta->meta_entry[offset - meta->offset];
+ cur_index_block = meta_entry->index_block + sblk->inode_table_start;
+ cur_offset = meta_entry->offset;
+ cur_data_block = meta_entry->data_block;
+ TRACE("get_meta_index: offset %d, meta->offset %d, "
+ "meta->entries %d\n", offset, meta->offset,
+ meta->entries);
+ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
+ " data_block 0x%llx\n", cur_index_block,
+ cur_offset, cur_data_block);
+ }
+
+ for (i = meta->offset + meta->entries; i <= index &&
+ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
+ int blocks = skip * SQUASHFS_META_INDEXES;
+
+ while (blocks) {
+ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
+ blocks;
+ int res = read_block_index(inode->i_sb, block,
+ block_list, &cur_index_block,
+ &cur_offset);
+
+ if (res == -1)
+ goto failed;
+
+ cur_data_block += res;
+ blocks -= block;
}
- for(block_listp = (unsigned int *) block_list; i < index && blocks; i ++, block_listp ++, blocks --)
- block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
- if(blocks >= readahead_blks)
- break;
+
+ meta_entry = &meta->meta_entry[i - meta->offset];
+ meta_entry->index_block = cur_index_block - sblk->inode_table_start;
+ meta_entry->offset = cur_offset;
+ meta_entry->data_block = cur_data_block;
+ meta->entries ++;
+ offset ++;
+ }
+
+ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
+ meta->offset, meta->entries);
+
+ release_meta_index(inode, meta);
}
- *bsize = *block_listp;
+all_done:
+ *index_block = cur_index_block;
+ *index_offset = cur_offset;
+ *data_block = cur_data_block;
+
+ return offset * SQUASHFS_META_INDEXES * skip;
+
+failed:
+ release_meta_index(inode, meta);
+ return -1;
+}
+
+
+static long long read_blocklist(struct inode *inode, int index,
+ int readahead_blks, char *block_list,
+ unsigned short **block_p, unsigned int *bsize)
+{
+ long long block_ptr;
+ int offset;
+ long long block;
+ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
+ block_list);
+
+ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
+ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
+ block);
+
+ if(res == -1)
+ goto failure;
+
+ index -= res;
+
+ while ( index ) {
+ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
+ int res = read_block_index(inode->i_sb, blocks, block_list,
+ &block_ptr, &offset);
+ if (res == -1)
+ goto failure;
+ block += res;
+ index -= blocks;
+ }
+
+ if (read_block_index(inode->i_sb, 1, block_list,
+ &block_ptr, &offset) == -1)
+ goto failure;
+ *bsize = *((unsigned int *) block_list);
+
return block;
+
+failure:
+ return 0;
}
static int squashfs_readpage(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
- squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
+ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
unsigned char block_list[SIZE];
- unsigned int bsize, block, i = 0, bytes = 0, byte_offset = 0;
- int index = page->index >> (sBlk->block_log - PAGE_CACHE_SHIFT);
- void *pageaddr = kmap(page);
- struct squashfs_fragment_cache *fragment;
- char *data_ptr = msBlk->read_page;
+ long long block;
+ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
+ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
+ void *pageaddr;
+ struct squashfs_fragment_cache *fragment = NULL;
+ char *data_ptr = msblk->read_page;
- int mask = (1 << (sBlk->block_log - PAGE_CACHE_SHIFT)) - 1;
+ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
int start_index = page->index & ~mask;
int end_index = start_index | mask;
- TRACE("Entered squashfs_readpage, page index %x, start block %x\n", (unsigned int) page->index,
- inode->u.squashfs_i.start_block);
+ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
+ page->index,
+ SQUASHFS_I(inode)->start_block);
- if(inode->u.squashfs_i.fragment_start_block == SQUASHFS_INVALID_BLK || index < (inode->i_size >> sBlk->block_log)) {
- if((block = (msBlk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize)) == 0)
+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+ PAGE_CACHE_SHIFT))
+ goto skip_read;
+
+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
+ || index < (i_size_read(inode) >>
+ sblk->block_log)) {
+ if ((block = (msblk->read_blocklist)(inode, index, 1,
+ block_list, NULL, &bsize)) == 0)
goto skip_read;
- down(&msBlk->read_page_mutex);
- if(!(bytes = read_data(inode->i_sb, msBlk->read_page, block, bsize, 1, NULL))) {
- ERROR("Unable to read page, block %x, size %x\n", block, bsize);
- up(&msBlk->read_page_mutex);
+ down(&msblk->read_page_mutex);
+
+ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
+ block, bsize, NULL))) {
+ ERROR("Unable to read page, block %llx, size %x\n", block,
+ bsize);
+ up(&msblk->read_page_mutex);
goto skip_read;
}
} else {
- if((fragment = get_cached_fragment(inode->i_sb, inode->u.squashfs_i.fragment_start_block, inode->u.squashfs_i.fragment_size)) == NULL) {
- ERROR("Unable to read page, block %x, size %x\n", inode->u.squashfs_i.fragment_start_block, (int) inode->u.squashfs_i.fragment_size);
+ if ((fragment = get_cached_fragment(inode->i_sb,
+ SQUASHFS_I(inode)->
+ u.s1.fragment_start_block,
+ SQUASHFS_I(inode)->u.s1.fragment_size))
+ == NULL) {
+ ERROR("Unable to read page, block %llx, size %x\n",
+ SQUASHFS_I(inode)->
+ u.s1.fragment_start_block,
+ (int) SQUASHFS_I(inode)->
+ u.s1.fragment_size);
goto skip_read;
}
- bytes = inode->u.squashfs_i.fragment_offset + (inode->i_size & (sBlk->block_size - 1));
- byte_offset = inode->u.squashfs_i.fragment_offset;
+ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
+ (i_size_read(inode) & (sblk->block_size
+ - 1));
+ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
data_ptr = fragment->data;
}
- for(i = start_index; i <= end_index && byte_offset < bytes; i++, byte_offset += PAGE_CACHE_SIZE) {
+ for (i = start_index; i <= end_index && byte_offset < bytes;
+ i++, byte_offset += PAGE_CACHE_SIZE) {
struct page *push_page;
- int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : bytes - byte_offset;
-
- TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", bytes, i, byte_offset, available_bytes);
-
- if(i == page->index) {
- memcpy(pageaddr, data_ptr + byte_offset, available_bytes);
- memset(pageaddr + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes);
- kunmap(page);
+ int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
+ PAGE_CACHE_SIZE : bytes - byte_offset;
+
+ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
+ bytes, i, byte_offset, available_bytes);
+
+ if (i == page->index) {
+ pageaddr = kmap_atomic(page, KM_USER0);
+ memcpy(pageaddr, data_ptr + byte_offset,
+ available_bytes);
+ memset(pageaddr + available_bytes, 0,
+ PAGE_CACHE_SIZE - available_bytes);
+ kunmap_atomic(pageaddr, KM_USER0);
flush_dcache_page(page);
SetPageUptodate(page);
UnlockPage(page);
- } else if((push_page = grab_cache_page_nowait(page->mapping, i))) {
- void *pageaddr = kmap(push_page);
- memcpy(pageaddr, data_ptr + byte_offset, available_bytes);
- memset(pageaddr + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes);
- kunmap(push_page);
+ } else if ((push_page =
+ grab_cache_page_nowait(page->mapping, i))) {
+ pageaddr = kmap_atomic(push_page, KM_USER0);
+
+ memcpy(pageaddr, data_ptr + byte_offset,
+ available_bytes);
+ memset(pageaddr + available_bytes, 0,
+ PAGE_CACHE_SIZE - available_bytes);
+ kunmap_atomic(pageaddr, KM_USER0);
flush_dcache_page(push_page);
SetPageUptodate(push_page);
UnlockPage(push_page);
@@ -1219,16 +1575,19 @@ static int squashfs_readpage(struct file *file, struct page *page)
}
}
- if(inode->u.squashfs_i.fragment_start_block == SQUASHFS_INVALID_BLK || index < (inode->i_size >> sBlk->block_log))
- up(&msBlk->read_page_mutex);
+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
+ || index < (i_size_read(inode) >>
+ sblk->block_log))
+ up(&msblk->read_page_mutex);
else
- release_cached_fragment(msBlk, fragment);
+ release_cached_fragment(msblk, fragment);
return 0;
skip_read:
+ pageaddr = kmap_atomic(page, KM_USER0);
memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
- kunmap(page);
+ kunmap_atomic(pageaddr, KM_USER0);
flush_dcache_page(page);
SetPageUptodate(page);
UnlockPage(page);
@@ -1240,34 +1599,61 @@ skip_read:
static int squashfs_readpage4K(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
- squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
+ struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
unsigned char block_list[SIZE];
- unsigned int bsize, block, bytes = 0;
- void *pageaddr = kmap(page);
+ long long block;
+ unsigned int bsize, bytes = 0;
+ void *pageaddr;
- TRACE("Entered squashfs_readpage4K, page index %x, start block %x\n", (unsigned int) page->index,
- inode->u.squashfs_i.start_block);
+ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
+ page->index,
+ SQUASHFS_I(inode)->start_block);
- if(page->index < (inode->i_size >> sBlk->block_log)) {
- block = (msBlk->read_blocklist)(inode, page->index, 1, block_list, NULL, &bsize);
+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+ PAGE_CACHE_SHIFT)) {
+ pageaddr = kmap_atomic(page, KM_USER0);
+ goto skip_read;
+ }
- if(!(bytes = read_data(inode->i_sb, pageaddr, block, bsize, 1, NULL)))
- ERROR("Unable to read page, block %x, size %x\n", block, bsize);
+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
+ || page->index < (i_size_read(inode) >>
+ sblk->block_log)) {
+ block = (msblk->read_blocklist)(inode, page->index, 1,
+ block_list, NULL, &bsize);
+
+ down(&msblk->read_page_mutex);
+ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
+ bsize, NULL);
+ pageaddr = kmap_atomic(page, KM_USER0);
+ if (bytes)
+ memcpy(pageaddr, msblk->read_page, bytes);
+ else
+ ERROR("Unable to read page, block %llx, size %x\n",
+ block, bsize);
+ up(&msblk->read_page_mutex);
} else {
- struct squashfs_fragment_cache *fragment;
-
- if((fragment = get_cached_fragment(inode->i_sb, inode->u.squashfs_i.fragment_start_block, inode->u.squashfs_i.fragment_size)) == NULL)
- ERROR("Unable to read page, block %x, size %x\n", inode->u.squashfs_i.fragment_start_block, (int) inode->u.squashfs_i.fragment_size);
- else {
- bytes = inode->i_size & (sBlk->block_size - 1);
- memcpy(pageaddr, fragment->data + inode->u.squashfs_i.fragment_offset, bytes);
- release_cached_fragment(msBlk, fragment);
- }
+ struct squashfs_fragment_cache *fragment =
+ get_cached_fragment(inode->i_sb,
+ SQUASHFS_I(inode)->
+ u.s1.fragment_start_block,
+ SQUASHFS_I(inode)-> u.s1.fragment_size);
+ pageaddr = kmap_atomic(page, KM_USER0);
+ if (fragment) {
+ bytes = i_size_read(inode) & (sblk->block_size - 1);
+ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
+ u.s1.fragment_offset, bytes);
+ release_cached_fragment(msblk, fragment);
+ } else
+ ERROR("Unable to read page, block %llx, size %x\n",
+ SQUASHFS_I(inode)->
+ u.s1.fragment_start_block, (int)
+ SQUASHFS_I(inode)-> u.s1.fragment_size);
}
+skip_read:
memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
- kunmap(page);
+ kunmap_atomic(pageaddr, KM_USER0);
flush_dcache_page(page);
SetPageUptodate(page);
UnlockPage(page);
@@ -1276,191 +1662,331 @@ static int squashfs_readpage4K(struct file *file, struct page *page)
}
-#ifdef SQUASHFS_1_0_COMPATIBILITY
-static int squashfs_readpage_lessthan4K(struct file *file, struct page *page)
+static int get_dir_index_using_offset(struct super_block *s, long long
+ *next_block, unsigned int *next_offset,
+ long long index_start,
+ unsigned int index_offset, int i_count,
+ long long f_pos)
{
- struct inode *inode = page->mapping->host;
- squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
- unsigned char block_list[SIZE];
- unsigned short *block_listp, block, bytes = 0;
- int index = page->index << (PAGE_CACHE_SHIFT - sBlk->block_log);
- int file_blocks = ((inode->i_size - 1) >> sBlk->block_log) + 1;
- int readahead_blks = 1 << (PAGE_CACHE_SHIFT - sBlk->block_log);
- void *pageaddr = kmap(page);
-
- int i_end = index + (1 << (PAGE_CACHE_SHIFT - sBlk->block_log));
- int byte;
-
- TRACE("Entered squashfs_readpage_lessthan4K, page index %x, start block %x\n", (unsigned int) page->index,
- inode->u.squashfs_i.start_block);
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ int i, length = 0;
+ struct squashfs_dir_index index;
+
+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
+ i_count, (unsigned int) f_pos);
+
+ f_pos -= 3;
+ if (f_pos == 0)
+ goto finish;
+
+ for (i = 0; i < i_count; i++) {
+ if (msblk->swap) {
+ struct squashfs_dir_index sindex;
+ squashfs_get_cached_block(s, (char *) &sindex,
+ index_start, index_offset,
+ sizeof(sindex), &index_start,
+ &index_offset);
+ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
+ } else
+ squashfs_get_cached_block(s, (char *) &index,
+ index_start, index_offset,
+ sizeof(index), &index_start,
+ &index_offset);
- block = read_blocklist_1(inode, index, readahead_blks, block_list, (char **) &block_listp, NULL);
+ if (index.index > f_pos)
+ break;
- if(i_end > file_blocks)
- i_end = file_blocks;
+ squashfs_get_cached_block(s, NULL, index_start, index_offset,
+ index.size + 1, &index_start,
+ &index_offset);
- while(index < i_end) {
- if(!(byte = read_data(inode->i_sb, pageaddr, block, *block_listp, 0, NULL))) {
- ERROR("Unable to read page, block %x, size %x\n", block, *block_listp);
- goto skip_read;
- }
- block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
- pageaddr += byte;
- bytes += byte;
- index ++;
- block_listp ++;
+ length = index.index;
+ *next_block = index.start_block + sblk->directory_table_start;
}
-skip_read:
- memset(pageaddr, 0, PAGE_CACHE_SIZE - bytes);
- kunmap(page);
- flush_dcache_page(page);
- SetPageUptodate(page);
- UnlockPage(page);
+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
- return 0;
+finish:
+ return length + 3;
}
-#endif
+static int get_dir_index_using_name(struct super_block *s, long long
+ *next_block, unsigned int *next_offset,
+ long long index_start,
+ unsigned int index_offset, int i_count,
+ const char *name, int size)
+{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ int i, length = 0;
+ char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
+ struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
+ char str[SQUASHFS_NAME_LEN + 1];
+
+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
+
+ strncpy(str, name, size);
+ str[size] = '\0';
+
+ for (i = 0; i < i_count; i++) {
+ if (msblk->swap) {
+ struct squashfs_dir_index sindex;
+ squashfs_get_cached_block(s, (char *) &sindex,
+ index_start, index_offset,
+ sizeof(sindex), &index_start,
+ &index_offset);
+ SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
+ } else
+ squashfs_get_cached_block(s, (char *) index,
+ index_start, index_offset,
+ sizeof(struct squashfs_dir_index),
+ &index_start, &index_offset);
+
+ squashfs_get_cached_block(s, index->name, index_start,
+ index_offset, index->size + 1,
+ &index_start, &index_offset);
+
+ index->name[index->size + 1] = '\0';
+
+ if (strcmp(index->name, str) > 0)
+ break;
+
+ length = index->index;
+ *next_block = index->start_block + sblk->directory_table_start;
+ }
+
+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+ return length + 3;
+}
+
+
static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
{
struct inode *i = file->f_dentry->d_inode;
- squashfs_sb_info *msBlk = &i->i_sb->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
- int next_block = i->u.squashfs_i.start_block + sBlk->directory_table_start, next_offset =
- i->u.squashfs_i.offset, length = 0, dirs_read = 0, dir_count;
- squashfs_dir_header dirh;
- char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
- squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
+ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ long long next_block = SQUASHFS_I(i)->start_block +
+ sblk->directory_table_start;
+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
+ dir_count;
+ struct squashfs_dir_header dirh;
+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
+
+ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
+
+ while(file->f_pos < 3) {
+ char *name;
+ int size, i_ino;
+
+ if(file->f_pos == 0) {
+ name = ".";
+ size = 1;
+ i_ino = i->i_ino;
+ } else {
+ name = "..";
+ size = 2;
+ i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
+ }
+ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
+ (unsigned int) dirent, name, size, (int)
+ file->f_pos, i_ino,
+ squashfs_filetype_table[1]);
+
+ if (filldir(dirent, name, size,
+ file->f_pos, i_ino,
+ squashfs_filetype_table[1]) < 0) {
+ TRACE("Filldir returned less than 0\n");
+ goto finish;
+ }
+ file->f_pos += size;
+ dirs_read++;
+ }
- TRACE("Entered squashfs_readdir [%x:%x]\n", next_block, next_offset);
+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_start,
+ SQUASHFS_I(i)->u.s2.directory_index_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_count,
+ file->f_pos);
- while(length < i->i_size) {
+ while (length < i_size_read(i)) {
/* read directory header */
- if(msBlk->swap) {
- squashfs_dir_header sdirh;
- if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block,
- next_offset, sizeof(sdirh), &next_block, &next_offset))
+ if (msblk->swap) {
+ struct squashfs_dir_header sdirh;
+
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+ next_block, next_offset, sizeof(sdirh),
+ &next_block, &next_offset))
goto failed_read;
+
length += sizeof(sdirh);
SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
} else {
- if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block,
- next_offset, sizeof(dirh), &next_block, &next_offset))
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+ next_block, next_offset, sizeof(dirh),
+ &next_block, &next_offset))
goto failed_read;
+
length += sizeof(dirh);
}
dir_count = dirh.count + 1;
- while(dir_count--) {
- if(msBlk->swap) {
- squashfs_dir_entry sdire;
- if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire, next_block,
- next_offset, sizeof(sdire), &next_block, &next_offset))
+ while (dir_count--) {
+ if (msblk->swap) {
+ struct squashfs_dir_entry sdire;
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ &sdire, next_block, next_offset,
+ sizeof(sdire), &next_block,
+ &next_offset))
goto failed_read;
+
length += sizeof(sdire);
SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
} else {
- if(!squashfs_get_cached_block(i->i_sb, (char *) dire, next_block,
- next_offset, sizeof(*dire), &next_block, &next_offset))
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ dire, next_block, next_offset,
+ sizeof(*dire), &next_block,
+ &next_offset))
goto failed_read;
+
length += sizeof(*dire);
}
- if(!squashfs_get_cached_block(i->i_sb, dire->name, next_block,
- next_offset, dire->size + 1, &next_block, &next_offset))
+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
+ next_block, next_offset,
+ dire->size + 1, &next_block,
+ &next_offset))
goto failed_read;
+
length += dire->size + 1;
- if(file->f_pos >= length)
+ if (file->f_pos >= length)
continue;
dire->name[dire->size + 1] = '\0';
- TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", (unsigned int) dirent,
- dire->name, dire->size + 1, (int) file->f_pos,
- dirh.start_block, dire->offset, squashfs_filetype_table[dire->type]);
-
- if(filldir(dirent, dire->name, dire->size + 1, file->f_pos, SQUASHFS_MK_VFS_INODE(dirh.start_block,
- dire->offset), squashfs_filetype_table[dire->type]) < 0) {
+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
+ (unsigned int) dirent, dire->name,
+ dire->size + 1, (int) file->f_pos,
+ dirh.start_block, dire->offset,
+ dirh.inode_number + dire->inode_number,
+ squashfs_filetype_table[dire->type]);
+
+ if (filldir(dirent, dire->name, dire->size + 1,
+ file->f_pos,
+ dirh.inode_number + dire->inode_number,
+ squashfs_filetype_table[dire->type])
+ < 0) {
TRACE("Filldir returned less than 0\n");
- return dirs_read;
+ goto finish;
}
-
file->f_pos = length;
- dirs_read ++;
+ dirs_read++;
}
}
+finish:
return dirs_read;
failed_read:
- ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);
+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+ next_offset);
return 0;
}
static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry)
{
- const char *name =dentry->d_name.name;
+ const unsigned char *name = dentry->d_name.name;
int len = dentry->d_name.len;
struct inode *inode = NULL;
- squashfs_sb_info *msBlk = &i->i_sb->u.squashfs_sb;
- squashfs_super_block *sBlk = &msBlk->sBlk;
- int next_block = i->u.squashfs_i.start_block + sBlk->directory_table_start, next_offset =
- i->u.squashfs_i.offset, length = 0, dir_count;
- squashfs_dir_header dirh;
- char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN];
- squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
-
- TRACE("Entered squashfs_lookup [%x:%x]\n", next_block, next_offset);
-
- while(length < i->i_size) {
+ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ long long next_block = SQUASHFS_I(i)->start_block +
+ sblk->directory_table_start;
+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
+ dir_count;
+ struct squashfs_dir_header dirh;
+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
+
+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
+
+ if (len > SQUASHFS_NAME_LEN)
+ goto exit_loop;
+
+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_start,
+ SQUASHFS_I(i)->u.s2.directory_index_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_count, name,
+ len);
+
+ while (length < i_size_read(i)) {
/* read directory header */
- if(msBlk->swap) {
- squashfs_dir_header sdirh;
- if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, next_offset,
- sizeof(sdirh), &next_block, &next_offset))
+ if (msblk->swap) {
+ struct squashfs_dir_header sdirh;
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+ next_block, next_offset, sizeof(sdirh),
+ &next_block, &next_offset))
goto failed_read;
+
length += sizeof(sdirh);
SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
} else {
- if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, next_offset,
- sizeof(dirh), &next_block, &next_offset))
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+ next_block, next_offset, sizeof(dirh),
+ &next_block, &next_offset))
goto failed_read;
+
length += sizeof(dirh);
}
dir_count = dirh.count + 1;
- while(dir_count--) {
- if(msBlk->swap) {
- squashfs_dir_entry sdire;
- if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire,
- next_block,next_offset, sizeof(sdire), &next_block, &next_offset))
+ while (dir_count--) {
+ if (msblk->swap) {
+ struct squashfs_dir_entry sdire;
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ &sdire, next_block,next_offset,
+ sizeof(sdire), &next_block,
+ &next_offset))
goto failed_read;
+
length += sizeof(sdire);
SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
} else {
- if(!squashfs_get_cached_block(i->i_sb, (char *) dire,
- next_block,next_offset, sizeof(*dire), &next_block, &next_offset))
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ dire, next_block,next_offset,
+ sizeof(*dire), &next_block,
+ &next_offset))
goto failed_read;
+
length += sizeof(*dire);
}
- if(!squashfs_get_cached_block(i->i_sb, dire->name,
- next_block, next_offset, dire->size + 1, &next_block, &next_offset))
+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
+ next_block, next_offset, dire->size + 1,
+ &next_block, &next_offset))
goto failed_read;
+
length += dire->size + 1;
- if((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
- squashfs_inode ino = SQUASHFS_MKINODE(dirh.start_block, dire->offset);
+ if (name[0] < dire->name[0])
+ goto exit_loop;
+
+ if ((len == dire->size + 1) && !strncmp(name,
+ dire->name, len)) {
+ squashfs_inode_t ino =
+ SQUASHFS_MKINODE(dirh.start_block,
+ dire->offset);
- TRACE("calling squashfs_iget for directory entry %s, inode %x:%x\n",
- name, dirh.start_block, dire->offset);
+ TRACE("calling squashfs_iget for directory "
+ "entry %s, inode %x:%x, %d\n", name,
+ dirh.start_block, dire->offset,
+ dirh.inode_number + dire->inode_number);
- inode = (msBlk->iget)(i->i_sb, ino);
+ inode = (msblk->iget)(i->i_sb, ino);
goto exit_loop;
}
@@ -1472,36 +1998,63 @@ exit_loop:
return ERR_PTR(0);
failed_read:
- ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);
+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+ next_offset);
goto exit_loop;
}
static void squashfs_put_super(struct super_block *s)
{
- if(s->u.squashfs_sb.block_cache) kfree(s->u.squashfs_sb.block_cache);
- if(s->u.squashfs_sb.read_data) kfree(s->u.squashfs_sb.read_data);
- if(s->u.squashfs_sb.read_page) kfree(s->u.squashfs_sb.read_page);
- if(s->u.squashfs_sb.uid) kfree(s->u.squashfs_sb.uid);
- s->u.squashfs_sb.block_cache = (void *) s->u.squashfs_sb.uid =
- s->u.squashfs_sb.read_data = s->u.squashfs_sb.read_page = NULL;
+ int i;
+
+ struct squashfs_sb_info *sbi = &s->u.squashfs_sb;
+ if (sbi->block_cache)
+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
+ if (sbi->block_cache[i].block !=
+ SQUASHFS_INVALID_BLK)
+ kfree(sbi->block_cache[i].data);
+ if (sbi->fragment)
+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
+ SQUASHFS_FREE(sbi->fragment[i].data);
+ kfree(sbi->fragment);
+ kfree(sbi->block_cache);
+ kfree(sbi->read_data);
+ kfree(sbi->read_page);
+ kfree(sbi->uid);
+ kfree(sbi->fragment_index);
+ kfree(sbi->fragment_index_2);
+ sbi->block_cache = NULL;
+ sbi->uid = NULL;
+ sbi->read_data = NULL;
+ sbi->read_page = NULL;
+ sbi->fragment = NULL;
+ sbi->fragment_index = NULL;
+ sbi->fragment_index_2 = NULL;
}
static int __init init_squashfs_fs(void)
{
- if(!(stream.workspace = (char *) vmalloc(zlib_inflate_workspacesize()))) {
+ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
+ "Phillip Lougher\n");
+
+#ifndef SQUASHFS_LZMA
+ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
ERROR("Failed to allocate zlib workspace\n");
return -ENOMEM;
}
+#endif
return register_filesystem(&squashfs_fs_type);
}
static void __exit exit_squashfs_fs(void)
{
+#ifndef SQUASHFS_LZMA
vfree(stream.workspace);
+#endif
unregister_filesystem(&squashfs_fs_type);
}
@@ -1511,5 +2064,5 @@ EXPORT_NO_SYMBOLS;
module_init(init_squashfs_fs);
module_exit(exit_squashfs_fs);
MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
-MODULE_AUTHOR("Phillip Lougher <plougher@users.sourceforge.net>");
+MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/fs/squashfs/squashfs.h b/release/src/linux/linux/fs/squashfs/squashfs.h
new file mode 100644
index 00000000..e53ceeff
--- /dev/null
+++ b/release/src/linux/linux/fs/squashfs/squashfs.h
@@ -0,0 +1,85 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs.h
+ */
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+#endif
+#ifdef SQUASHFS_TRACE
+#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
+#else
+#define TRACE(s, args...) {}
+#endif
+
+#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
+
+#define SERROR(s, args...) do { \
+ if (!silent) \
+ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
+ } while(0)
+
+#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
+
+#define SQUASHFS_I(INO) (&INO->u.squashfs_i)
+
+#define i_size_read(INO) (INO->i_size)
+
+#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
+#define SQSH_EXTERN
+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+ long long index, unsigned int length,
+ long long *next_index);
+extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
+ long long block, unsigned int offset,
+ int length, long long *next_block,
+ unsigned int *next_offset);
+extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
+ squashfs_fragment_cache *fragment);
+extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
+ *s, long long start_block,
+ int length);
+extern struct address_space_operations squashfs_symlink_aops;
+extern struct address_space_operations squashfs_aops;
+extern struct address_space_operations squashfs_aops_4K;
+extern struct file_operations squashfs_dir_ops;
+extern struct inode_operations squashfs_dir_inode_ops;
+#else
+#define SQSH_EXTERN static
+#endif
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
+#else
+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
+#else
+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
+{
+ return 0;
+}
+#endif
diff --git a/release/src/linux/linux/fs/squashfs/squashfs2_0.c b/release/src/linux/linux/fs/squashfs/squashfs2_0.c
new file mode 100644
index 00000000..d4efd8a9
--- /dev/null
+++ b/release/src/linux/linux/fs/squashfs/squashfs2_0.c
@@ -0,0 +1,751 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs2_0.c
+ */
+
+#include <linux/types.h>
+#include <linux/squashfs_fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/locks.h>
+#include <linux/init.h>
+#include <linux/dcache.h>
+#include <linux/wait.h>
+#include <linux/zlib.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include "squashfs.h"
+
+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry);
+
+static struct file_operations squashfs_dir_ops_2 = {
+ .read = generic_read_dir,
+ .readdir = squashfs_readdir_2
+};
+
+static struct inode_operations squashfs_dir_inode_ops_2 = {
+ .lookup = squashfs_lookup_2
+};
+
+static unsigned char squashfs_filetype_table[] = {
+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
+};
+
+static int read_fragment_index_table_2(struct super_block *s)
+{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+
+ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
+ (sblk->fragments), GFP_KERNEL))) {
+ ERROR("Failed to allocate uid/gid table\n");
+ return 0;
+ }
+
+ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
+ !squashfs_read_data(s, (char *)
+ msblk->fragment_index_2,
+ sblk->fragment_table_start,
+ SQUASHFS_FRAGMENT_INDEX_BYTES_2
+ (sblk->fragments) |
+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+ ERROR("unable to read fragment index table\n");
+ return 0;
+ }
+
+ if (msblk->swap) {
+ int i;
+ unsigned int fragment;
+
+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
+ i++) {
+ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
+ &msblk->fragment_index_2[i], 1);
+ msblk->fragment_index_2[i] = fragment;
+ }
+ }
+
+ return 1;
+}
+
+
+static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
+ long long *fragment_start_block,
+ unsigned int *fragment_size)
+{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ long long start_block =
+ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
+ struct squashfs_fragment_entry_2 fragment_entry;
+
+ if (msblk->swap) {
+ struct squashfs_fragment_entry_2 sfragment_entry;
+
+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
+ start_block, offset,
+ sizeof(sfragment_entry), &start_block,
+ &offset))
+ goto out;
+ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
+ } else
+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
+ start_block, offset,
+ sizeof(fragment_entry), &start_block,
+ &offset))
+ goto out;
+
+ *fragment_start_block = fragment_entry.start_block;
+ *fragment_size = fragment_entry.size;
+
+ return 1;
+
+out:
+ return 0;
+}
+
+
+static struct inode *squashfs_new_inode(struct super_block *s,
+ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
+{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ struct inode *i = new_inode(s);
+
+ if (i) {
+ i->i_ino = ino;
+ i->i_mtime = sblk->mkfs_time;
+ i->i_atime = sblk->mkfs_time;
+ i->i_ctime = sblk->mkfs_time;
+ i->i_uid = msblk->uid[inodeb->uid];
+ i->i_mode = inodeb->mode;
+ i->i_nlink = 1;
+ i->i_size = 0;
+ if (inodeb->guid == SQUASHFS_GUIDS)
+ i->i_gid = i->i_uid;
+ else
+ i->i_gid = msblk->guid[inodeb->guid];
+ }
+
+ return i;
+}
+
+
+static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
+{
+ struct inode *i;
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ unsigned int block = SQUASHFS_INODE_BLK(inode) +
+ sblk->inode_table_start;
+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+ unsigned int ino = SQUASHFS_MK_VFS_INODE(block
+ - sblk->inode_table_start, offset);
+ long long next_block;
+ unsigned int next_offset;
+ union squashfs_inode_header_2 id, sid;
+ struct squashfs_base_inode_header_2 *inodeb = &id.base,
+ *sinodeb = &sid.base;
+
+ TRACE("Entered squashfs_iget\n");
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
+ offset, sizeof(*sinodeb), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
+ sizeof(*sinodeb));
+ } else
+ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
+ offset, sizeof(*inodeb), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ switch(inodeb->inode_type) {
+ case SQUASHFS_FILE_TYPE: {
+ struct squashfs_reg_inode_header_2 *inodep = &id.reg;
+ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
+ long long frag_blk;
+ unsigned int frag_size;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ frag_blk = SQUASHFS_INVALID_BLK;
+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
+ !get_fragment_location_2(s,
+ inodep->fragment, &frag_blk, &frag_size))
+ goto failed_read;
+
+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+ goto failed_read1;
+
+ i->i_size = inodep->file_size;
+ i->i_fop = &generic_ro_fops;
+ i->i_mode |= S_IFREG;
+ i->i_mtime = inodep->mtime;
+ i->i_atime = inodep->mtime;
+ i->i_ctime = inodep->mtime;
+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+ i->i_blksize = PAGE_CACHE_SIZE;
+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
+ SQUASHFS_I(i)->start_block = inodep->start_block;
+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
+ SQUASHFS_I(i)->offset = next_offset;
+ if (sblk->block_size > 4096)
+ i->i_data.a_ops = &squashfs_aops;
+ else
+ i->i_data.a_ops = &squashfs_aops_4K;
+
+ TRACE("File inode %x:%x, start_block %x, "
+ "block_list_start %llx, offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep->start_block, next_block,
+ next_offset);
+ break;
+ }
+ case SQUASHFS_DIR_TYPE: {
+ struct squashfs_dir_inode_header_2 *inodep = &id.dir;
+ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+ goto failed_read1;
+
+ i->i_size = inodep->file_size;
+ i->i_op = &squashfs_dir_inode_ops_2;
+ i->i_fop = &squashfs_dir_ops_2;
+ i->i_mode |= S_IFDIR;
+ i->i_mtime = inodep->mtime;
+ i->i_atime = inodep->mtime;
+ i->i_ctime = inodep->mtime;
+ SQUASHFS_I(i)->start_block = inodep->start_block;
+ SQUASHFS_I(i)->offset = inodep->offset;
+ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
+ SQUASHFS_I(i)->u.s2.parent_inode = 0;
+
+ TRACE("Directory inode %x:%x, start_block %x, offset "
+ "%x\n", SQUASHFS_INODE_BLK(inode),
+ offset, inodep->start_block,
+ inodep->offset);
+ break;
+ }
+ case SQUASHFS_LDIR_TYPE: {
+ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
+ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
+ sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+ goto failed_read1;
+
+ i->i_size = inodep->file_size;
+ i->i_op = &squashfs_dir_inode_ops_2;
+ i->i_fop = &squashfs_dir_ops_2;
+ i->i_mode |= S_IFDIR;
+ i->i_mtime = inodep->mtime;
+ i->i_atime = inodep->mtime;
+ i->i_ctime = inodep->mtime;
+ SQUASHFS_I(i)->start_block = inodep->start_block;
+ SQUASHFS_I(i)->offset = inodep->offset;
+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
+ SQUASHFS_I(i)->u.s2.directory_index_offset =
+ next_offset;
+ SQUASHFS_I(i)->u.s2.directory_index_count =
+ inodep->i_count;
+ SQUASHFS_I(i)->u.s2.parent_inode = 0;
+
+ TRACE("Long directory inode %x:%x, start_block %x, "
+ "offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep->start_block, inodep->offset);
+ break;
+ }
+ case SQUASHFS_SYMLINK_TYPE: {
+ struct squashfs_symlink_inode_header_2 *inodep =
+ &id.symlink;
+ struct squashfs_symlink_inode_header_2 *sinodep =
+ &sid.symlink;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
+ sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+ goto failed_read1;
+
+ i->i_size = inodep->symlink_size;
+ i->i_op = &page_symlink_inode_operations;
+ i->i_data.a_ops = &squashfs_symlink_aops;
+ i->i_mode |= S_IFLNK;
+ SQUASHFS_I(i)->start_block = next_block;
+ SQUASHFS_I(i)->offset = next_offset;
+
+ TRACE("Symbolic link inode %x:%x, start_block %llx, "
+ "offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ next_block, next_offset);
+ break;
+ }
+ case SQUASHFS_BLKDEV_TYPE:
+ case SQUASHFS_CHRDEV_TYPE: {
+ struct squashfs_dev_inode_header_2 *inodep = &id.dev;
+ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
+
+ if (msblk->swap) {
+ if (!squashfs_get_cached_block(s, (char *)
+ sinodep, block, offset,
+ sizeof(*sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ inodep, block, offset,
+ sizeof(*inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+ goto failed_read1;
+
+ i->i_mode |= (inodeb->inode_type ==
+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
+ S_IFBLK;
+ init_special_inode(i, i->i_mode, inodep->rdev);
+
+ TRACE("Device inode %x:%x, rdev %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep->rdev);
+ break;
+ }
+ case SQUASHFS_FIFO_TYPE:
+ case SQUASHFS_SOCKET_TYPE: {
+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+ goto failed_read1;
+
+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
+ ? S_IFIFO : S_IFSOCK;
+ init_special_inode(i, i->i_mode, 0);
+ break;
+ }
+ default:
+ ERROR("Unknown inode type %d in squashfs_iget!\n",
+ inodeb->inode_type);
+ goto failed_read1;
+ }
+
+ insert_inode_hash(i);
+ return i;
+
+failed_read:
+ ERROR("Unable to read inode [%x:%x]\n", block, offset);
+
+failed_read1:
+ return NULL;
+}
+
+
+static int get_dir_index_using_offset(struct super_block *s, long long
+ *next_block, unsigned int *next_offset,
+ long long index_start,
+ unsigned int index_offset, int i_count,
+ long long f_pos)
+{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ int i, length = 0;
+ struct squashfs_dir_index_2 index;
+
+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
+ i_count, (unsigned int) f_pos);
+
+ if (f_pos == 0)
+ goto finish;
+
+ for (i = 0; i < i_count; i++) {
+ if (msblk->swap) {
+ struct squashfs_dir_index_2 sindex;
+ squashfs_get_cached_block(s, (char *) &sindex,
+ index_start, index_offset,
+ sizeof(sindex), &index_start,
+ &index_offset);
+ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
+ } else
+ squashfs_get_cached_block(s, (char *) &index,
+ index_start, index_offset,
+ sizeof(index), &index_start,
+ &index_offset);
+
+ if (index.index > f_pos)
+ break;
+
+ squashfs_get_cached_block(s, NULL, index_start, index_offset,
+ index.size + 1, &index_start,
+ &index_offset);
+
+ length = index.index;
+ *next_block = index.start_block + sblk->directory_table_start;
+ }
+
+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+
+finish:
+ return length;
+}
+
+
+static int get_dir_index_using_name(struct super_block *s, long long
+ *next_block, unsigned int *next_offset,
+ long long index_start,
+ unsigned int index_offset, int i_count,
+ const char *name, int size)
+{
+ struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ int i, length = 0;
+ char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
+ struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
+ char str[SQUASHFS_NAME_LEN + 1];
+
+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
+
+ strncpy(str, name, size);
+ str[size] = '\0';
+
+ for (i = 0; i < i_count; i++) {
+ if (msblk->swap) {
+ struct squashfs_dir_index_2 sindex;
+ squashfs_get_cached_block(s, (char *) &sindex,
+ index_start, index_offset,
+ sizeof(sindex), &index_start,
+ &index_offset);
+ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
+ } else
+ squashfs_get_cached_block(s, (char *) index,
+ index_start, index_offset,
+ sizeof(struct squashfs_dir_index_2),
+ &index_start, &index_offset);
+
+ squashfs_get_cached_block(s, index->name, index_start,
+ index_offset, index->size + 1,
+ &index_start, &index_offset);
+
+ index->name[index->size + 1] = '\0';
+
+ if (strcmp(index->name, str) > 0)
+ break;
+
+ length = index->index;
+ *next_block = index->start_block + sblk->directory_table_start;
+ }
+
+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+ return length;
+}
+
+
+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
+{
+ struct inode *i = file->f_dentry->d_inode;
+ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ long long next_block = SQUASHFS_I(i)->start_block +
+ sblk->directory_table_start;
+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
+ dir_count;
+ struct squashfs_dir_header_2 dirh;
+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+
+ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
+
+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_start,
+ SQUASHFS_I(i)->u.s2.directory_index_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_count,
+ file->f_pos);
+
+ while (length < i_size_read(i)) {
+ /* read directory header */
+ if (msblk->swap) {
+ struct squashfs_dir_header_2 sdirh;
+
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+ next_block, next_offset, sizeof(sdirh),
+ &next_block, &next_offset))
+ goto failed_read;
+
+ length += sizeof(sdirh);
+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
+ } else {
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+ next_block, next_offset, sizeof(dirh),
+ &next_block, &next_offset))
+ goto failed_read;
+
+ length += sizeof(dirh);
+ }
+
+ dir_count = dirh.count + 1;
+ while (dir_count--) {
+ if (msblk->swap) {
+ struct squashfs_dir_entry_2 sdire;
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ &sdire, next_block, next_offset,
+ sizeof(sdire), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ length += sizeof(sdire);
+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
+ } else {
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ dire, next_block, next_offset,
+ sizeof(*dire), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ length += sizeof(*dire);
+ }
+
+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
+ next_block, next_offset,
+ dire->size + 1, &next_block,
+ &next_offset))
+ goto failed_read;
+
+ length += dire->size + 1;
+
+ if (file->f_pos >= length)
+ continue;
+
+ dire->name[dire->size + 1] = '\0';
+
+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
+ (unsigned int) dirent, dire->name,
+ dire->size + 1, (int) file->f_pos,
+ dirh.start_block, dire->offset,
+ squashfs_filetype_table[dire->type]);
+
+ if (filldir(dirent, dire->name, dire->size + 1,
+ file->f_pos, SQUASHFS_MK_VFS_INODE(
+ dirh.start_block, dire->offset),
+ squashfs_filetype_table[dire->type])
+ < 0) {
+ TRACE("Filldir returned less than 0\n");
+ goto finish;
+ }
+ file->f_pos = length;
+ dirs_read++;
+ }
+ }
+
+finish:
+ return dirs_read;
+
+failed_read:
+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+ next_offset);
+ return 0;
+}
+
+
+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry)
+{
+ const unsigned char *name = dentry->d_name.name;
+ int len = dentry->d_name.len;
+ struct inode *inode = NULL;
+ struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
+ struct squashfs_super_block *sblk = &msblk->sblk;
+ long long next_block = SQUASHFS_I(i)->start_block +
+ sblk->directory_table_start;
+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
+ dir_count;
+ struct squashfs_dir_header_2 dirh;
+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
+
+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
+
+ if (len > SQUASHFS_NAME_LEN)
+ goto exit_loop;
+
+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_start,
+ SQUASHFS_I(i)->u.s2.directory_index_offset,
+ SQUASHFS_I(i)->u.s2.directory_index_count, name,
+ len);
+
+ while (length < i_size_read(i)) {
+ /* read directory header */
+ if (msblk->swap) {
+ struct squashfs_dir_header_2 sdirh;
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+ next_block, next_offset, sizeof(sdirh),
+ &next_block, &next_offset))
+ goto failed_read;
+
+ length += sizeof(sdirh);
+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
+ } else {
+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+ next_block, next_offset, sizeof(dirh),
+ &next_block, &next_offset))
+ goto failed_read;
+
+ length += sizeof(dirh);
+ }
+
+ dir_count = dirh.count + 1;
+ while (dir_count--) {
+ if (msblk->swap) {
+ struct squashfs_dir_entry_2 sdire;
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ &sdire, next_block,next_offset,
+ sizeof(sdire), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ length += sizeof(sdire);
+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
+ } else {
+ if (!squashfs_get_cached_block(i->i_sb, (char *)
+ dire, next_block,next_offset,
+ sizeof(*dire), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ length += sizeof(*dire);
+ }
+
+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
+ next_block, next_offset, dire->size + 1,
+ &next_block, &next_offset))
+ goto failed_read;
+
+ length += dire->size + 1;
+
+ if (sorted && name[0] < dire->name[0])
+ goto exit_loop;
+
+ if ((len == dire->size + 1) && !strncmp(name,
+ dire->name, len)) {
+ squashfs_inode_t ino =
+ SQUASHFS_MKINODE(dirh.start_block,
+ dire->offset);
+
+ TRACE("calling squashfs_iget for directory "
+ "entry %s, inode %x:%x, %d\n", name,
+ dirh.start_block, dire->offset, ino);
+
+ inode = (msblk->iget)(i->i_sb, ino);
+
+ goto exit_loop;
+ }
+ }
+ }
+
+exit_loop:
+ d_add(dentry, inode);
+ return ERR_PTR(0);
+
+failed_read:
+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+ next_offset);
+ goto exit_loop;
+}
+
+
+int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
+{
+ struct squashfs_super_block *sblk = &msblk->sblk;
+
+ msblk->iget = squashfs_iget_2;
+ msblk->read_fragment_index_table = read_fragment_index_table_2;
+
+ sblk->bytes_used = sblk->bytes_used_2;
+ sblk->uid_start = sblk->uid_start_2;
+ sblk->guid_start = sblk->guid_start_2;
+ sblk->inode_table_start = sblk->inode_table_start_2;
+ sblk->directory_table_start = sblk->directory_table_start_2;
+ sblk->fragment_table_start = sblk->fragment_table_start_2;
+
+ return 1;
+}
diff --git a/release/src/linux/linux/include/linux/fs.h b/release/src/linux/linux/include/linux/fs.h
index 0b85bf9e..db1a1572 100644
--- a/release/src/linux/linux/include/linux/fs.h
+++ b/release/src/linux/linux/include/linux/fs.h
@@ -1421,7 +1421,7 @@ extern int block_write_full_page(struct page*, get_block_t*);
extern int block_read_full_page(struct page*, get_block_t*);
extern int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
extern int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
- unsigned long *);
+ loff_t *);
extern int generic_cont_expand(struct inode *inode, loff_t size) ;
extern int block_commit_write(struct page *page, unsigned from, unsigned to);
extern int block_sync_page(struct page *);
diff --git a/release/src/linux/linux/include/linux/imq.h b/release/src/linux/linux/include/linux/imq.h
new file mode 100644
index 00000000..8bf3f959
--- /dev/null
+++ b/release/src/linux/linux/include/linux/imq.h
@@ -0,0 +1,9 @@
+#ifndef _IMQ_H
+#define _IMQ_H
+
+#define IMQ_MAX_DEVS 16
+
+#define IMQ_F_IFMASK 0x7f
+#define IMQ_F_ENQUEUE 0x80
+
+#endif /* _IMQ_H */
diff --git a/release/src/linux/linux/include/linux/jhash.h b/release/src/linux/linux/include/linux/jhash.h
new file mode 100644
index 00000000..82c7ae41
--- /dev/null
+++ b/release/src/linux/linux/include/linux/jhash.h
@@ -0,0 +1,143 @@
+#ifndef _LINUX_JHASH_H
+#define _LINUX_JHASH_H
+
+/* jhash.h: Jenkins hash support.
+ *
+ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
+ *
+ * http://burtleburtle.net/bob/hash/
+ *
+ * These are the credits from Bob's sources:
+ *
+ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+ * hash(), hash2(), hash3, and mix() are externally useful functions.
+ * Routines to test the hash are included if SELF_TEST is defined.
+ * You can use this free for any purpose. It has no warranty.
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ *
+ * I've modified Bob's hash to be useful in the Linux kernel, and
+ * any bugs present are surely my fault. -DaveM
+ */
+
+/* NOTE: Arguments are modified. */
+#define __jhash_mix(a, b, c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<<8); \
+ c -= a; c -= b; c ^= (b>>13); \
+ a -= b; a -= c; a ^= (c>>12); \
+ b -= c; b -= a; b ^= (a<<16); \
+ c -= a; c -= b; c ^= (b>>5); \
+ a -= b; a -= c; a ^= (c>>3); \
+ b -= c; b -= a; b ^= (a<<10); \
+ c -= a; c -= b; c ^= (b>>15); \
+}
+
+/* The golden ration: an arbitrary value */
+#define JHASH_GOLDEN_RATIO 0x9e3779b9
+
+/* The most generic version, hashes an arbitrary sequence
+ * of bytes. No alignment or length assumptions are made about
+ * the input key.
+ */
+static inline u32 jhash(const void *key, u32 length, u32 initval)
+{
+ u32 a, b, c, len;
+ const u8 *k = key;
+
+ len = length;
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+
+ while (len >= 12) {
+ a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
+ b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
+ c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
+
+ __jhash_mix(a,b,c);
+
+ k += 12;
+ len -= 12;
+ }
+
+ c += length;
+ switch (len) {
+ case 11: c += ((u32)k[10]<<24);
+ case 10: c += ((u32)k[9]<<16);
+ case 9 : c += ((u32)k[8]<<8);
+ case 8 : b += ((u32)k[7]<<24);
+ case 7 : b += ((u32)k[6]<<16);
+ case 6 : b += ((u32)k[5]<<8);
+ case 5 : b += k[4];
+ case 4 : a += ((u32)k[3]<<24);
+ case 3 : a += ((u32)k[2]<<16);
+ case 2 : a += ((u32)k[1]<<8);
+ case 1 : a += k[0];
+ };
+
+ __jhash_mix(a,b,c);
+
+ return c;
+}
+
+/* A special optimized version that handles 1 or more of u32s.
+ * The length parameter here is the number of u32s in the key.
+ */
+static inline u32 jhash2(u32 *k, u32 length, u32 initval)
+{
+ u32 a, b, c, len;
+
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+ len = length;
+
+ while (len >= 3) {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ __jhash_mix(a, b, c);
+ k += 3; len -= 3;
+ }
+
+ c += length * 4;
+
+ switch (len) {
+ case 2 : b += k[1];
+ case 1 : a += k[0];
+ };
+
+ __jhash_mix(a,b,c);
+
+ return c;
+}
+
+
+/* A special ultra-optimized versions that knows they are hashing exactly
+ * 3, 2 or 1 word(s).
+ *
+ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
+ * done at the end is not done here.
+ */
+static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
+{
+ a += JHASH_GOLDEN_RATIO;
+ b += JHASH_GOLDEN_RATIO;
+ c += initval;
+
+ __jhash_mix(a, b, c);
+
+ return c;
+}
+
+static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
+{
+ return jhash_3words(a, b, 0, initval);
+}
+
+static inline u32 jhash_1word(u32 a, u32 initval)
+{
+ return jhash_3words(a, 0, 0, initval);
+}
+
+#endif /* _LINUX_JHASH_H */
diff --git a/release/src/linux/linux/include/linux/list.h b/release/src/linux/linux/include/linux/list.h
index 9d98ba31..dafdfc87 100644
--- a/release/src/linux/linux/include/linux/list.h
+++ b/release/src/linux/linux/include/linux/list.h
@@ -227,6 +227,33 @@ static inline void list_splice_init(struct list_head *list,
pos = list_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next))
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_continue - iterate over list of given type
+ * continuing after existing point
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
#endif /* __KERNEL__ || _LVM_H_INCLUDE */
#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack.h
index 314f6cc3..2e75b782 100644
--- a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -6,6 +6,7 @@
#include <linux/config.h>
#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/bitops.h>
#include <asm/atomic.h>
enum ip_conntrack_info
@@ -41,6 +42,10 @@ enum ip_conntrack_status {
/* Conntrack should never be early-expired. */
IPS_ASSURED_BIT = 2,
IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+
+ /* Connection is confirmed: originating packet has left box */
+ IPS_CONFIRMED_BIT = 3,
+ IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
};
#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
@@ -62,31 +67,27 @@ union ip_conntrack_expect_proto {
};
/* Add protocol helper include file here */
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
-#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
-
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
-#ifdef CONFIG_IP_NF_NAT_RTSP
-#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
-#endif
#include <linux/netfilter_ipv4/ip_autofw.h>
+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
/* per expectation: application helper private data */
union ip_conntrack_expect_help {
/* insert conntrack helper private data (expect) here */
+ struct ip_ct_h225_expect exp_h225_info;
struct ip_ct_pptp_expect exp_pptp_info;
struct ip_ct_sip_expect exp_sip_info;
struct ip_ct_mms_expect exp_mms_info;
- struct ip_ct_h225_expect exp_h225_info;
struct ip_ct_ftp_expect exp_ftp_info;
struct ip_ct_irc_expect exp_irc_info;
struct ip_autofw_expect exp_autofw_info;
-#ifdef CONFIG_IP_NF_NAT_RTSP
- struct ip_ct_rtsp_expect exp_rtsp_info;
-#endif
+ struct ip_ct_rtsp_expect exp_rtsp_info;
+
#ifdef CONFIG_IP_NF_NAT_NEEDED
union {
/* insert nat helper private data (expect) here */
@@ -97,15 +98,13 @@ union ip_conntrack_expect_help {
/* per conntrack: application helper private data */
union ip_conntrack_help {
/* insert conntrack helper private data (master) here */
+ struct ip_ct_h225_master ct_h225_info;
struct ip_ct_pptp_master ct_pptp_info;
struct ip_ct_sip_master ct_sip_info;
struct ip_ct_mms_master ct_mms_info;
- struct ip_ct_h225_master ct_h225_info;
struct ip_ct_ftp_master ct_ftp_info;
struct ip_ct_irc_master ct_irc_info;
-#ifdef CONFIG_IP_NF_NAT_RTSP
- struct ip_ct_rtsp_master ct_rtsp_info;
-#endif
+ struct ip_ct_rtsp_master ct_rtsp_info;
};
#ifdef CONFIG_IP_NF_NAT_NEEDED
@@ -188,7 +187,7 @@ struct ip_conntrack
struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
/* Have we seen traffic both ways yet? (bitset) */
- volatile unsigned long status;
+ unsigned long status;
/* Timer function; drops refcnt when it goes off. */
struct timer_list timeout;
@@ -227,6 +226,29 @@ struct ip_conntrack
} nat;
#endif /* CONFIG_IP_NF_NAT_NEEDED */
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+ unsigned long mark;
+#endif
+
+#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
+ struct {
+ unsigned int numpackets; /* surely this is kept track of somewhere else, right? I can't find it... */
+ char * app_proto; /* "http", "ftp", etc. NULL if unclassifed */
+
+ /* the application layer data so far. NULL if ->numpackets > numpackets */
+ char * app_data;
+
+ unsigned int app_data_len;
+ } layer7;
+#endif
+
+#if defined(CONFIG_IP_NF_TARGET_BCOUNT) || defined(CONFIG_IP_NF_TARGET_BCOUNT_MODULE)
+ u_int32_t bcount;
+#endif
+
+#if defined(CONFIG_IP_NF_TARGET_MACSAVE) || defined(CONFIG_IP_NF_TARGET_MACSAVE_MODULE)
+ unsigned char macsave[6];
+#endif
};
/* get master conntrack via master expectation */
@@ -283,7 +305,7 @@ ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
/* It's confirmed if it is, or has been in the hash table. */
static inline int is_confirmed(struct ip_conntrack *ct)
{
- return ct->tuplehash[IP_CT_DIR_ORIGINAL].list.next != NULL;
+ return test_bit(IPS_CONFIRMED_BIT, &ct->status);
}
extern unsigned int ip_conntrack_htable_size;
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 10221fe9..3803c126 100644
--- a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -4,6 +4,7 @@
#ifdef __KERNEL__
/* Protects H.323 related data */
+#include <linux/netfilter_ipv4/lockhelp.h>
DECLARE_LOCK_EXTERN(ip_h323_lock);
#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_esp.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_esp.h
index acb4d9ec..acb4d9ec 100755..100644
--- a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_esp.h
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_esp.h
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
index 738e99a2..07646857 100644
--- a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
@@ -77,13 +77,13 @@ struct ip_ct_gre_expect {
};
#ifdef __KERNEL__
+struct ip_conntrack_expect;
/* structure for original <-> reply keymap */
struct ip_ct_gre_keymap {
struct list_head list;
struct ip_conntrack_tuple tuple;
- struct ip_conntrack_expect *master;
};
@@ -96,6 +96,8 @@ int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
struct ip_conntrack_tuple *t);
+/* delete keymap entries */
+void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
/* get pointer to gre key, if present */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
index 770935d3..0f103d35 100644
--- a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
@@ -57,7 +57,6 @@ struct ip_conntrack_tuple
} tcp;
struct {
u_int16_t port;
- unsigned int init_cookie;//xiaoqin add for multi-ipsec passthrough,2005.12.19
} udp;
struct {
u_int8_t type, code;
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_tables.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_tables.h
index d2a7f4b4..11e0cfcf 100644
--- a/release/src/linux/linux/include/linux/netfilter_ipv4/ip_tables.h
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ip_tables.h
@@ -104,7 +104,8 @@ struct ipt_counters
/* Values for "flag" field in struct ipt_ip (general ip structure). */
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
-#define IPT_F_MASK 0x01 /* All possible flag bits mask. */
+#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
+#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
/* Values for "inv" field in struct ipt_ip. */
#define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_BCOUNT.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_BCOUNT.h
new file mode 100644
index 00000000..34b56aef
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_BCOUNT.h
@@ -0,0 +1,16 @@
+/*
+
+ BCOUNT target
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#ifndef _IPT_BCOUNT_TARGET_H
+#define _IPT_BCOUNT_TARGET_H
+
+struct ipt_BCOUNT_target {
+// int debug;
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CLASSIFY.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
new file mode 100644
index 00000000..7596e3dd
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
@@ -0,0 +1,8 @@
+#ifndef _IPT_CLASSIFY_H
+#define _IPT_CLASSIFY_H
+
+struct ipt_classify_target_info {
+ u_int32_t priority;
+};
+
+#endif /*_IPT_CLASSIFY_H */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CONNMARK.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CONNMARK.h
new file mode 100644
index 00000000..f9099f92
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_CONNMARK.h
@@ -0,0 +1,26 @@
+#ifndef _IPT_CONNMARK_H_target
+#define _IPT_CONNMARK_H_target
+
+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * 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.
+ */
+
+enum {
+ IPT_CONNMARK_SET = 0,
+ IPT_CONNMARK_SAVE,
+ IPT_CONNMARK_RESTORE,
+ IPT_CONNMARK_SET_RETURN
+};
+
+struct ipt_connmark_target_info {
+ unsigned long mark;
+ unsigned long mask;
+ u_int8_t mode;
+};
+
+#endif /*_IPT_CONNMARK_H_target*/
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_IMQ.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_IMQ.h
new file mode 100644
index 00000000..45d57713
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_IMQ.h
@@ -0,0 +1,8 @@
+#ifndef _IPT_IMQ_H
+#define _IPT_IMQ_H
+
+struct ipt_imq_info {
+ unsigned int todev; /* target imq device */
+};
+
+#endif /* _IPT_IMQ_H */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_MACSAVE.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_MACSAVE.h
new file mode 100644
index 00000000..dc426893
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_MACSAVE.h
@@ -0,0 +1,16 @@
+/*
+
+ MACSAVE target
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#ifndef _IPT_MACSAVE_TARGET_H
+#define _IPT_MACSAVE_TARGET_H
+
+struct ipt_MACSAVE_target_info {
+// int debug;
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
new file mode 100644
index 00000000..41b1a9c8
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
@@ -0,0 +1,23 @@
+/* Header file for iptables ipt_ROUTE target
+ *
+ * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IPT_ROUTE_IFNAMSIZ 16
+
+struct ipt_route_target_info {
+ char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw; /* IP address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IPT_ROUTE_CONTINUE 0x01
+#define IPT_ROUTE_TEE 0x02
+
+#endif /*_IPT_ROUTE_H_target*/
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_TTL.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_TTL.h
new file mode 100644
index 00000000..edf49e80
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_TTL.h
@@ -0,0 +1,21 @@
+/* TTL modification module for IP tables
+ * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
+
+#ifndef _IPT_TTL_H
+#define _IPT_TTL_H
+
+enum {
+ IPT_TTL_SET = 0,
+ IPT_TTL_INC,
+ IPT_TTL_DEC
+};
+
+#define IPT_TTL_MAXMODE IPT_TTL_DEC
+
+struct ipt_TTL_info {
+ u_int8_t mode;
+ u_int8_t ttl;
+};
+
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_account.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_account.h
new file mode 100644
index 00000000..6068d86d
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_account.h
@@ -0,0 +1,26 @@
+/*
+ * accounting match (ipt_account.c)
+ * (C) 2003,2004 by Piotr Gasidlo (quaker@barbara.eu.org)
+ *
+ * Version: 0.1.7
+ *
+ * This software is distributed under the terms of GNU GPL
+ */
+
+#ifndef _IPT_ACCOUNT_H_
+#define _IPT_ACCOUNT_H_
+
+#define IPT_ACCOUNT_NAME_LEN 64
+
+#define IPT_ACCOUNT_NAME "ipt_account"
+#define IPT_ACCOUNT_VERSION "0.1.7"
+
+struct t_ipt_account_info {
+ char name[IPT_ACCOUNT_NAME_LEN];
+ u_int32_t network;
+ u_int32_t netmask;
+ int shortlisting:1;
+};
+
+#endif
+
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_bcount.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_bcount.h
new file mode 100644
index 00000000..66f5ed9c
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_bcount.h
@@ -0,0 +1,18 @@
+/*
+
+ bcount match (experimental)
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#ifndef _IPT_BCOUNT_H
+#define _IPT_BCOUNT_H
+
+struct ipt_bcount_match {
+ u_int32_t min;
+ u_int32_t max;
+ int invert;
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_condition.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_condition.h
new file mode 100644
index 00000000..2bc5b0c8
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_condition.h
@@ -0,0 +1,11 @@
+#ifndef __IPT_CONDITION_MATCH__
+#define __IPT_CONDITION_MATCH__
+
+#define CONDITION_NAME_LEN 32
+
+struct condition_info {
+ char name[CONDITION_NAME_LEN];
+ int invert;
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connlimit.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connlimit.h
new file mode 100644
index 00000000..d99193b7
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connlimit.h
@@ -0,0 +1,12 @@
+#ifndef _IPT_CONNLIMIT_H
+#define _IPT_CONNLIMIT_H
+
+struct ipt_connlimit_data;
+
+struct ipt_connlimit_info {
+ int limit;
+ int inverse;
+ u_int32_t mask;
+ struct ipt_connlimit_data *data;
+};
+#endif /* _IPT_CONNLIMIT_H */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connmark.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connmark.h
new file mode 100644
index 00000000..46573270
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_connmark.h
@@ -0,0 +1,18 @@
+#ifndef _IPT_CONNMARK_H
+#define _IPT_CONNMARK_H
+
+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * 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.
+ */
+
+struct ipt_connmark_info {
+ unsigned long mark, mask;
+ u_int8_t invert;
+};
+
+#endif /*_IPT_CONNMARK_H*/
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_exp.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_exp.h
new file mode 100644
index 00000000..51319cb2
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_exp.h
@@ -0,0 +1,15 @@
+/*
+
+ Experimental Netfilter Crap
+ Copyright (C) 2006 Jonathan Zarate
+
+*/
+
+#ifndef _IPT_EXP_H
+#define _IPT_EXP_H
+
+struct ipt_exp_info {
+ char dummy;
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_geoip.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_geoip.h
new file mode 100644
index 00000000..15764e8b
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_geoip.h
@@ -0,0 +1,51 @@
+/* ipt_geoip.h header file for libipt_geoip.c and ipt_geoip.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.
+ *
+ * Copyright (c) 2004 Cookinglinux
+ */
+#ifndef _IPT_GEOIP_H
+#define _IPT_GEOIP_H
+
+#define IPT_GEOIP_SRC 0x01 /* Perform check on Source IP */
+#define IPT_GEOIP_DST 0x02 /* Perform check on Destination IP */
+#define IPT_GEOIP_INV 0x04 /* Negate the condition */
+
+#define IPT_GEOIP_MAX 15 /* Maximum of countries */
+
+struct geoip_subnet {
+ u_int32_t begin;
+ u_int32_t end;
+};
+
+struct geoip_info {
+ struct geoip_subnet *subnets;
+ u_int32_t count;
+ u_int32_t ref;
+ u_int16_t cc;
+ struct geoip_info *next;
+ struct geoip_info *prev;
+};
+
+struct ipt_geoip_info {
+ u_int8_t flags;
+ u_int8_t count;
+ u_int16_t cc[IPT_GEOIP_MAX];
+
+ /* Used internally by the kernel */
+ struct geoip_info *mem[IPT_GEOIP_MAX];
+ u_int8_t *refcount;
+
+ /* not implemented yet:
+ void *fini;
+ */
+};
+
+#define COUNTRY(cc) (cc >> 8), (cc & 0x00FF)
+
+#endif
+
+/* End of ipt_geoip.h */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h
new file mode 100644
index 00000000..1bd3f649
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h
@@ -0,0 +1,31 @@
+#ifndef __IPT_IPP2P_H
+#define __IPT_IPP2P_H
+#define IPP2P_VERSION "0.8.1_rc1"
+
+struct ipt_p2p_info {
+ int cmd;
+ int debug;
+};
+
+#endif //__IPT_IPP2P_H
+
+#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
+//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
+#define SHORT_HAND_NONE 5 /* no short hand*/
+
+#define IPP2P_EDK (1 << 1)
+#define IPP2P_DATA_KAZAA (1 << 2)
+#define IPP2P_DATA_EDK (1 << 3)
+#define IPP2P_DATA_DC (1 << 4)
+#define IPP2P_DC (1 << 5)
+#define IPP2P_DATA_GNU (1 << 6)
+#define IPP2P_GNU (1 << 7)
+#define IPP2P_KAZAA (1 << 8)
+#define IPP2P_BIT (1 << 9)
+#define IPP2P_APPLE (1 << 10)
+#define IPP2P_SOUL (1 << 11)
+#define IPP2P_WINMX (1 << 12)
+#define IPP2P_ARES (1 << 13)
+#define IPP2P_MUTE (1 << 14)
+#define IPP2P_WASTE (1 << 15)
+#define IPP2P_XDCC (1 << 16)
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_iprange.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_iprange.h
new file mode 100644
index 00000000..3ecb3bd6
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_iprange.h
@@ -0,0 +1,23 @@
+#ifndef _IPT_IPRANGE_H
+#define _IPT_IPRANGE_H
+
+#define IPRANGE_SRC 0x01 /* Match source IP address */
+#define IPRANGE_DST 0x02 /* Match destination IP address */
+#define IPRANGE_SRC_INV 0x10 /* Negate the condition */
+#define IPRANGE_DST_INV 0x20 /* Negate the condition */
+
+struct ipt_iprange {
+ /* Inclusive: network order. */
+ u_int32_t min_ip, max_ip;
+};
+
+struct ipt_iprange_info
+{
+ struct ipt_iprange src;
+ struct ipt_iprange dst;
+
+ /* Flags from above */
+ u_int8_t flags;
+};
+
+#endif /* _IPT_IPRANGE_H */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_layer7.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_layer7.h
new file mode 100644
index 00000000..aee1f5d5
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_layer7.h
@@ -0,0 +1,26 @@
+/*
+ By Matthew Strait <quadong@users.sf.net>, Dec 2003.
+ http://l7-filter.sf.net
+
+ 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.
+ http://www.gnu.org/licenses/gpl.txt
+*/
+
+#ifndef _IPT_LAYER7_H
+#define _IPT_LAYER7_H
+
+#define MAX_PATTERN_LEN 8192
+#define MAX_PROTOCOL_LEN 256
+
+typedef char *(*proc_ipt_search) (char *, char, char *);
+
+struct ipt_layer7_info {
+ char protocol[MAX_PROTOCOL_LEN];
+ char invert:1;
+ char pattern[MAX_PATTERN_LEN];
+};
+
+#endif /* _IPT_LAYER7_H */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_macsave.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_macsave.h
new file mode 100644
index 00000000..9d5b218d
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_macsave.h
@@ -0,0 +1,17 @@
+/*
+
+ macsave match
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#ifndef _IPT_MACSAVE_MATCH_H
+#define _IPT_MACSAVE_MATCH_H
+
+struct ipt_macsave_match_info {
+ int invert;
+ unsigned char mac[6];
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_quota.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_quota.h
new file mode 100644
index 00000000..f2a06716
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_quota.h
@@ -0,0 +1,12 @@
+#ifndef _IPT_QUOTA_H
+#define _IPT_QUOTA_H
+
+/* print debug info in both kernel/netfilter module & iptable library */
+//#define DEBUG_IPT_QUOTA
+
+struct ipt_quota_info {
+ u_int64_t quota;
+ struct ipt_quota_info *master;
+};
+
+#endif /*_IPT_QUOTA_H*/
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_recent.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_recent.h
new file mode 100644
index 00000000..eb008fb4
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_recent.h
@@ -0,0 +1,28 @@
+#ifndef _IPT_RECENT_H
+#define _IPT_RECENT_H
+
+#define RECENT_NAME "ipt_recent"
+#define RECENT_VER "v0.3.1"
+
+#define IPT_RECENT_CHECK 1
+#define IPT_RECENT_SET 2
+#define IPT_RECENT_UPDATE 4
+#define IPT_RECENT_REMOVE 8
+#define IPT_RECENT_TTL 16
+
+#define IPT_RECENT_SOURCE 0
+#define IPT_RECENT_DEST 1
+
+#define IPT_RECENT_NAME_LEN 200
+
+struct ipt_recent_info {
+ u_int32_t seconds;
+ u_int32_t hit_count;
+ u_int8_t check_set;
+ u_int8_t invert;
+ char name[IPT_RECENT_NAME_LEN];
+ u_int8_t side;
+};
+
+#endif /*_IPT_RECENT_H*/
+
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_string.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_string.h
new file mode 100644
index 00000000..17d71034
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_string.h
@@ -0,0 +1,21 @@
+#ifndef _IPT_STRING_H
+#define _IPT_STRING_H
+
+/* *** PERFORMANCE TWEAK ***
+ * Packet size and search string threshold,
+ * above which sublinear searches is used. */
+#define IPT_STRING_HAYSTACK_THRESH 100
+#define IPT_STRING_NEEDLE_THRESH 20
+
+#define BM_MAX_NLEN 256
+#define BM_MAX_HLEN 1024
+
+typedef char *(*proc_ipt_search) (char *, char *, int, int);
+
+struct ipt_string_info {
+ char string[BM_MAX_NLEN];
+ u_int16_t invert;
+ u_int16_t len;
+};
+
+#endif /* _IPT_STRING_H */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_time.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_time.h
index 1ccdbb3d..277c6de5 100644
--- a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_time.h
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_time.h
@@ -3,10 +3,12 @@
struct ipt_time_info {
- unsigned int days_match; /* 1 bit per day (bit 0 = Sunday) */
- unsigned int time_start; /* 0 < time_start < 24*60*60-1 = 86399 */
- unsigned int time_stop; /* 0 < time_end < 24*60*60-1 = 86399 */
- int kerneltime; /* ignore skb time (and use kerneltime) or not. */
+ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
+ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
+ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
+ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
+ time_t date_start;
+ time_t date_stop;
};
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_u32.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_u32.h
new file mode 100644
index 00000000..694fdc08
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_u32.h
@@ -0,0 +1,40 @@
+#ifndef _IPT_U32_H
+#define _IPT_U32_H
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+enum ipt_u32_ops
+{
+ IPT_U32_AND,
+ IPT_U32_LEFTSH,
+ IPT_U32_RIGHTSH,
+ IPT_U32_AT
+};
+
+struct ipt_u32_location_element
+{
+ u_int32_t number;
+ u_int8_t nextop;
+};
+struct ipt_u32_value_element
+{
+ u_int32_t min;
+ u_int32_t max;
+};
+/* *** any way to allow for an arbitrary number of elements?
+ for now I settle for a limit of 10 of each */
+#define U32MAXSIZE 10
+struct ipt_u32_test
+{
+ u_int8_t nnums;
+ struct ipt_u32_location_element location[U32MAXSIZE+1];
+ u_int8_t nvalues;
+ struct ipt_u32_value_element value[U32MAXSIZE+1];
+};
+
+struct ipt_u32
+{
+ u_int8_t ntests;
+ struct ipt_u32_test tests[U32MAXSIZE+1];
+};
+
+#endif /*_IPT_U32_H*/
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_web.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_web.h
new file mode 100644
index 00000000..176208e2
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_web.h
@@ -0,0 +1,30 @@
+/*
+
+ web (experimental)
+ HTTP client match
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#ifndef _IPT_WEB_H
+#define _IPT_WEB_H
+
+#define IPT_WEB_MAXTEXT 512
+
+typedef enum {
+ IPT_WEB_HTTP,
+ IPT_WEB_RURI,
+ IPT_WEB_PATH,
+ IPT_WEB_QUERY,
+ IPT_WEB_HOST,
+ IPT_WEB_HORE
+} ipt_web_mode_t;
+
+struct ipt_web_info {
+ ipt_web_mode_t mode;
+ int invert;
+ char text[IPT_WEB_MAXTEXT];
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_IMQ.h b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_IMQ.h
new file mode 100644
index 00000000..4eefa612
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_IMQ.h
@@ -0,0 +1,8 @@
+#ifndef _IP6T_IMQ_H
+#define _IP6T_IMQ_H
+
+struct ip6t_imq_info {
+ unsigned int todev; /* target imq device */
+};
+
+#endif /* _IP6T_IMQ_H */
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h
new file mode 100644
index 00000000..c5ec871b
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h
@@ -0,0 +1,23 @@
+/* Header file for iptables ip6t_ROUTE target
+ *
+ * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IP6T_ROUTE_IFNAMSIZ 16
+
+struct ip6t_route_target_info {
+ char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw[4]; /* IPv6 address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IP6T_ROUTE_CONTINUE 0x01
+#define IP6T_ROUTE_TEE 0x02
+
+#endif /*_IP6T_ROUTE_H_target*/
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_condition.h b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_condition.h
new file mode 100644
index 00000000..164ff86e
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_condition.h
@@ -0,0 +1,11 @@
+#ifndef __IP6T_CONDITION_MATCH__
+#define __IP6T_CONDITION_MATCH__
+
+#define CONDITION6_NAME_LEN 32
+
+struct condition6_info {
+ char name[CONDITION6_NAME_LEN];
+ int invert;
+};
+
+#endif
diff --git a/release/src/linux/linux/include/linux/pkt_sched.h b/release/src/linux/linux/include/linux/pkt_sched.h
index fec8ad62..331feebf 100644
--- a/release/src/linux/linux/include/linux/pkt_sched.h
+++ b/release/src/linux/linux/include/linux/pkt_sched.h
@@ -173,8 +173,36 @@ struct tc_sfq_qopt
*
* The only reason for this is efficiency, it is possible
* to change these parameters in compile time.
+ *
+ * If you need to play with these values use esfq instead.
*/
+/* ESFQ section */
+
+enum
+{
+ /* traditional */
+ TCA_SFQ_HASH_CLASSIC,
+ TCA_SFQ_HASH_DST,
+ TCA_SFQ_HASH_SRC,
+ TCA_SFQ_HASH_FWMARK,
+ /* direct */
+ TCA_SFQ_HASH_DSTDIR,
+ TCA_SFQ_HASH_SRCDIR,
+ TCA_SFQ_HASH_FWMARKDIR,
+};
+
+struct tc_esfq_qopt
+{
+ unsigned quantum; /* Bytes per round allocated to flow */
+ int perturb_period; /* Period of hash perturbation */
+ __u32 limit; /* Maximal packets in queue */
+ unsigned divisor; /* Hash divisor */
+ unsigned flows; /* Maximal number of flows */
+ unsigned hash_kind; /* Hash function to use for flow identification */
+};
+
+
/* RED section */
enum
@@ -290,6 +318,37 @@ struct tc_htb_xstats
__u32 ctokens;
};
+/* HFSC section */
+
+struct tc_hfsc_qopt
+{
+ __u16 defcls; /* default class */
+};
+
+struct tc_service_curve
+{
+ __u32 m1; /* slope of the first segment in bps */
+ __u32 d; /* x-projection of the first segment in us */
+ __u32 m2; /* slope of the second segment in bps */
+};
+
+struct tc_hfsc_stats
+{
+ __u64 work; /* total work done */
+ __u64 rtwork; /* work done by real-time criteria */
+ __u32 period; /* current period */
+ __u32 level; /* class level in hierarchy */
+};
+
+enum
+{
+ TCA_HFSC_UNSPEC,
+ TCA_HFSC_RSC,
+ TCA_HFSC_FSC,
+ TCA_HFSC_USC,
+ TCA_HFSC_MAX = TCA_HFSC_USC
+};
+
/* CBQ section */
#define TC_CBQ_MAXPRIO 8
diff --git a/release/src/linux/linux/include/linux/rbtree.h b/release/src/linux/linux/include/linux/rbtree.h
index 96f20e14..d7ba5df4 100644
--- a/release/src/linux/linux/include/linux/rbtree.h
+++ b/release/src/linux/linux/include/linux/rbtree.h
@@ -121,6 +121,12 @@ rb_root_t;
extern void rb_insert_color(rb_node_t *, rb_root_t *);
extern void rb_erase(rb_node_t *, rb_root_t *);
+/* Find logical next and previous nodes in a tree */
+extern rb_node_t *rb_next(rb_node_t *);
+extern rb_node_t *rb_prev(rb_node_t *);
+extern rb_node_t *rb_first(rb_root_t *);
+extern rb_node_t *rb_last(rb_root_t *);
+
static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link)
{
node->rb_parent = parent;
diff --git a/release/src/linux/linux/include/linux/skbuff.h b/release/src/linux/linux/include/linux/skbuff.h
index 7529ded2..c39889d6 100644
--- a/release/src/linux/linux/include/linux/skbuff.h
+++ b/release/src/linux/linux/include/linux/skbuff.h
@@ -93,6 +93,9 @@ struct nf_ct_info {
struct nf_conntrack *master;
};
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+struct nf_info;
+#endif
struct sk_buff_head {
/* These two members must be first. */
@@ -178,7 +181,7 @@ struct sk_buff {
unsigned int len; /* Length of actual data */
unsigned int data_len;
unsigned int csum; /* Checksum */
- unsigned char __unused, /* Dead field, may be reused */
+ unsigned char imq_flags, /* intermediate queueing device */
cloned, /* head may be cloned (check refcnt to be sure). */
pkt_type, /* Packet class */
ip_summed; /* Driver fed us an IP checksum */
@@ -215,6 +218,9 @@ struct sk_buff {
#ifdef CONFIG_NET_SCHED
__u32 tc_index; /* traffic control index */
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ struct nf_info *nf_info;
+#endif
};
#define SK_WMEM_MAX 65535
diff --git a/release/src/linux/linux/include/linux/squashfs_fs.h b/release/src/linux/linux/include/linux/squashfs_fs.h
index d810c596..5c79e38b 100644
--- a/release/src/linux/linux/include/linux/squashfs_fs.h
+++ b/release/src/linux/linux/include/linux/squashfs_fs.h
@@ -1,9 +1,11 @@
#ifndef SQUASHFS_FS
#define SQUASHFS_FS
+
/*
* Squashfs
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,7 +24,23 @@
* squashfs_fs.h
*/
-#define SQUASHFS_MAJOR 2
+#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
+#endif
+
+#ifdef CONFIG_SQUASHFS_VMALLOC
+#define SQUASHFS_ALLOC(a) vmalloc(a)
+#define SQUASHFS_FREE(a) vfree(a)
+#else
+#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
+#define SQUASHFS_FREE(a) kfree(a)
+#endif
+#ifdef CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
+#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
+#else
+#define SQUASHFS_CACHED_FRAGMENTS 3
+#endif
+#define SQUASHFS_MAJOR 3
#define SQUASHFS_MINOR 0
#define SQUASHFS_MAGIC 0x73717368
#define SQUASHFS_MAGIC_SWAP 0x68737173
@@ -46,8 +64,9 @@
#define SQUASHFS_NAME_LEN 256
#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
-#define SQUASHFS_INVALID_BLK ((long long) 0xffffffff)
-#define SQUASHFS_USED_BLK ((long long) 0xfffffffe)
+#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
+#define SQUASHFS_INVALID_BLK ((long long) -1)
+#define SQUASHFS_USED_BLK ((long long) -2)
/* Filesystem flags */
#define SQUASHFS_NOI 0
@@ -57,15 +76,34 @@
#define SQUASHFS_NO_FRAG 4
#define SQUASHFS_ALWAYS_FRAG 5
#define SQUASHFS_DUPLICATE 6
+
#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
-#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, SQUASHFS_NOI)
-#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_NOD)
-#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NOF)
-#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NO_FRAG)
-#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_ALWAYS_FRAG)
-#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, SQUASHFS_DUPLICATE)
-#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_CHECK)
-#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, duplicate_checking) (noi | (nod << 1) | (check_data << 2) | (nof << 3) | (no_frag << 4) | (always_frag << 5) | (duplicate_checking << 6))
+
+#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOI)
+
+#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOD)
+
+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOF)
+
+#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NO_FRAG)
+
+#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_ALWAYS_FRAG)
+
+#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_DUPLICATE)
+
+#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_CHECK)
+
+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
+ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \
+ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
+ (duplicate_checking << 6))
/* Max number of types and file types */
#define SQUASHFS_DIR_TYPE 1
@@ -75,73 +113,114 @@
#define SQUASHFS_CHRDEV_TYPE 5
#define SQUASHFS_FIFO_TYPE 6
#define SQUASHFS_SOCKET_TYPE 7
+#define SQUASHFS_LDIR_TYPE 8
+#define SQUASHFS_LREG_TYPE 9
/* 1.0 filesystem type definitions */
#define SQUASHFS_TYPES 5
#define SQUASHFS_IPC_TYPE 0
-/* Flag whether block is compressed or uncompressed, bit is set if block is uncompressed */
+/* Flag whether block is compressed or uncompressed, bit is set if block is
+ * uncompressed */
#define SQUASHFS_COMPRESSED_BIT (1 << 15)
+
#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
- (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
+ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
-#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? \
- (B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
-#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
+ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
+ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
+
+#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
/*
- * Inode number ops. Inodes consist of a compressed block number, and an uncompressed
- * offset within that block
+ * Inode number ops. Inodes consist of a compressed block number, and an
+ * uncompressed offset within that block
*/
#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
+
#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
-#define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A) << 16)\
- + (B)))
+
+#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
+ << 16) + (B)))
/* Compute 32 bit VFS inode number from squashfs inode number */
-#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + ((b) >> 2) + 1))
+#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
+ ((b) >> 2) + 1))
+/* XXX */
/* Translate between VFS mode and squashfs mode */
#define SQUASHFS_MODE(a) ((a) & 0xfff)
/* fragment and fragment table defines */
-typedef unsigned int squashfs_fragment_index;
-#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(squashfs_fragment_entry))
-#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / SQUASHFS_METADATA_SIZE)
-#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % SQUASHFS_METADATA_SIZE)
-#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE)
-#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) * sizeof(squashfs_fragment_index))
-#define SQUASHFS_CACHED_FRAGMENTS 3
+#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry))
+
+#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
+ SQUASHFS_METADATA_SIZE - 1) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
+ sizeof(long long))
/* cached data constants for filesystem */
#define SQUASHFS_CACHED_BLKS 8
-#define SQUASHFS_MAX_FILE_SIZE_LOG 32
-#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << (SQUASHFS_MAX_FILE_SIZE_LOG - 1))
+#define SQUASHFS_MAX_FILE_SIZE_LOG 64
+
+#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
+ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
#define SQUASHFS_MARKER_BYTE 0xff
+/* meta index cache */
+#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
+#define SQUASHFS_META_ENTRIES 31
+#define SQUASHFS_META_NUMBER 8
+#define SQUASHFS_SLOTS 4
+
+struct meta_entry {
+ long long data_block;
+ unsigned int index_block;
+ unsigned short offset;
+ unsigned short pad;
+};
+
+struct meta_index {
+ unsigned int inode_number;
+ unsigned int offset;
+ unsigned short entries;
+ unsigned short skip;
+ unsigned short locked;
+ unsigned short pad;
+ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
+};
+
+
/*
* definitions for structures on disk
*/
-typedef unsigned int squashfs_block;
-typedef long long squashfs_inode;
-
-typedef unsigned int squashfs_uid;
+typedef long long squashfs_block_t;
+typedef long long squashfs_inode_t;
-typedef struct squashfs_super_block {
+struct squashfs_super_block {
unsigned int s_magic;
unsigned int inodes;
- unsigned int bytes_used;
- unsigned int uid_start;
- unsigned int guid_start;
- unsigned int inode_table_start;
- unsigned int directory_table_start;
+ unsigned int bytes_used_2;
+ unsigned int uid_start_2;
+ unsigned int guid_start_2;
+ unsigned int inode_table_start_2;
+ unsigned int directory_table_start_2;
unsigned int s_major:16;
unsigned int s_minor:16;
unsigned int block_size_1:16;
@@ -150,88 +229,125 @@ typedef struct squashfs_super_block {
unsigned int no_uids:8;
unsigned int no_guids:8;
unsigned int mkfs_time /* time of filesystem creation */;
- squashfs_inode root_inode;
+ squashfs_inode_t root_inode;
unsigned int block_size;
unsigned int fragments;
- unsigned int fragment_table_start;
-} __attribute__ ((packed)) squashfs_super_block;
-
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
-} __attribute__ ((packed)) squashfs_base_inode_header;
-
-typedef squashfs_base_inode_header squashfs_ipc_inode_header;
-
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
+ unsigned int fragment_table_start_2;
+ long long bytes_used;
+ long long uid_start;
+ long long guid_start;
+ long long inode_table_start;
+ long long directory_table_start;
+ long long fragment_table_start;
+ long long unused;
+} __attribute__ ((packed));
+
+struct squashfs_dir_index {
+ unsigned int index;
+ unsigned int start_block;
+ unsigned char size;
+ unsigned char name[0];
+} __attribute__ ((packed));
+
+#define SQUASHFS_BASE_INODE_HEADER \
+ unsigned int inode_type:4; \
+ unsigned int mode:12; \
+ unsigned int uid:8; \
+ unsigned int guid:8; \
+ unsigned int mtime; \
+ unsigned int inode_number;
+
+struct squashfs_base_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+} __attribute__ ((packed));
+
+struct squashfs_ipc_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
+} __attribute__ ((packed));
+
+struct squashfs_dev_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
unsigned short rdev;
-} __attribute__ ((packed)) squashfs_dev_inode_header;
+} __attribute__ ((packed));
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
+struct squashfs_symlink_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
unsigned short symlink_size;
char symlink[0];
-} __attribute__ ((packed)) squashfs_symlink_inode_header;
+} __attribute__ ((packed));
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
- unsigned int mtime;
- squashfs_block start_block;
+struct squashfs_reg_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ squashfs_block_t start_block;
unsigned int fragment;
unsigned int offset;
- unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+ unsigned int file_size;
unsigned short block_list[0];
-} __attribute__ ((packed)) squashfs_reg_inode_header;
+} __attribute__ ((packed));
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
+struct squashfs_lreg_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
+ squashfs_block_t start_block;
+ unsigned int fragment;
+ unsigned int offset;
+ long long file_size;
+ unsigned short block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
unsigned int file_size:19;
unsigned int offset:13;
- unsigned int mtime;
- unsigned int start_block:24;
-} __attribute__ ((packed)) squashfs_dir_inode_header;
-
-typedef union {
- squashfs_base_inode_header base;
- squashfs_dev_inode_header dev;
- squashfs_symlink_inode_header symlink;
- squashfs_reg_inode_header reg;
- squashfs_dir_inode_header dir;
- squashfs_ipc_inode_header ipc;
-} squashfs_inode_header;
+ unsigned int start_block;
+ unsigned int parent_inode;
+} __attribute__ ((packed));
+
+struct squashfs_ldir_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
+ unsigned int file_size:27;
+ unsigned int offset:13;
+ unsigned int start_block;
+ unsigned int i_count:16;
+ unsigned int parent_inode;
+ struct squashfs_dir_index index[0];
+} __attribute__ ((packed));
+
+union squashfs_inode_header {
+ struct squashfs_base_inode_header base;
+ struct squashfs_dev_inode_header dev;
+ struct squashfs_symlink_inode_header symlink;
+ struct squashfs_reg_inode_header reg;
+ struct squashfs_lreg_inode_header lreg;
+ struct squashfs_dir_inode_header dir;
+ struct squashfs_ldir_inode_header ldir;
+ struct squashfs_ipc_inode_header ipc;
+};
-typedef struct {
+struct squashfs_dir_entry {
unsigned int offset:13;
unsigned int type:3;
unsigned int size:8;
+ int inode_number:16;
char name[0];
-} __attribute__ ((packed)) squashfs_dir_entry;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_dir_header {
unsigned int count:8;
- unsigned int start_block:24;
-} __attribute__ ((packed)) squashfs_dir_header;
-
-
-typedef struct {
unsigned int start_block;
+ unsigned int inode_number;
+} __attribute__ ((packed));
+
+struct squashfs_fragment_entry {
+ long long start_block;
unsigned int size;
-} __attribute__ ((packed)) squashfs_fragment_entry;
+ unsigned int unused;
+} __attribute__ ((packed));
extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
extern int squashfs_uncompress_init(void);
@@ -239,20 +355,28 @@ extern int squashfs_uncompress_exit(void);
/*
* macros to convert each packed bitfield structure from little endian to big
- * endian and vice versa. These are needed when creating or using a filesystem on a
- * machine with different byte ordering to the target architecture.
+ * endian and vice versa. These are needed when creating or using a filesystem
+ * on a machine with different byte ordering to the target architecture.
*
*/
+#define SQUASHFS_SWAP_START \
+ int bits;\
+ int b_pos;\
+ unsigned long long val;\
+ unsigned char *s;\
+ unsigned char *d;
+
#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
- SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\
- SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\
- SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\
- SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\
- SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\
+ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
+ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
+ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
+ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
+ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
@@ -264,137 +388,218 @@ extern int squashfs_uncompress_exit(void);
SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
- SQUASHFS_SWAP((s)->fragment_table_start, d, 472, 32);\
+ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
+ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
+ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
+ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
+ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
+ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
+ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
+ SQUASHFS_SWAP((s)->unused, d, 888, 64);\
}
-#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
SQUASHFS_MEMSET(s, d, n);\
SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
SQUASHFS_SWAP((s)->mode, d, 4, 12);\
SQUASHFS_SWAP((s)->uid, d, 16, 8);\
SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
}
-#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ipc_inode_header))
+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_ipc_inode_header))\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+}
#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dev_inode_header));\
- SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_dev_inode_header)); \
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
}
#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header));\
- SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_symlink_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
}
#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header));\
- SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
- SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
- SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
- SQUASHFS_SWAP((s)->offset, d, 128, 32);\
- SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_reg_inode_header));\
+ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
+ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
+ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
+}
+
+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_lreg_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
+ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
+ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
}
#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header));\
- SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
- SQUASHFS_SWAP((s)->offset, d, 51, 13);\
- SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
- SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_dir_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
+ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
+ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
+ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
+}
+
+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_ldir_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
+ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
+ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
+ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
+ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
+}
+
+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
+ SQUASHFS_SWAP((s)->index, d, 0, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
+ SQUASHFS_SWAP((s)->size, d, 64, 8);\
}
#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
SQUASHFS_SWAP((s)->count, d, 0, 8);\
- SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
+ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
+ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
}
#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
SQUASHFS_SWAP((s)->offset, d, 0, 13);\
SQUASHFS_SWAP((s)->type, d, 13, 3);\
SQUASHFS_SWAP((s)->size, d, 16, 8);\
+ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
}
#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_fragment_entry));\
- SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
- SQUASHFS_SWAP((s)->size, d, 32, 32);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
+ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
+ SQUASHFS_SWAP((s)->size, d, 64, 32);\
}
#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
int entry;\
int bit_position;\
+ SQUASHFS_SWAP_START\
SQUASHFS_MEMSET(s, d, n * 2);\
- for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 16)\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 16)\
SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
}
#define SQUASHFS_SWAP_INTS(s, d, n) {\
int entry;\
int bit_position;\
+ SQUASHFS_SWAP_START\
SQUASHFS_MEMSET(s, d, n * 4);\
- for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 32)\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 32)\
SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
}
+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
+ int entry;\
+ int bit_position;\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, n * 8);\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 64)\
+ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
+}
+
#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
int entry;\
int bit_position;\
+ SQUASHFS_SWAP_START\
SQUASHFS_MEMSET(s, d, n * bits / 8);\
- for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += bits)\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ bits)\
SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
}
-#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
-#ifdef SQUASHFS_1_0_COMPATIBILITY
-typedef struct {
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+
+struct squashfs_base_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
-} __attribute__ ((packed)) squashfs_base_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_ipc_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned int type:4;
unsigned int offset:4;
-} __attribute__ ((packed)) squashfs_ipc_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_dev_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned short rdev;
-} __attribute__ ((packed)) squashfs_dev_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_symlink_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned short symlink_size;
char symlink[0];
-} __attribute__ ((packed)) squashfs_symlink_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_reg_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned int mtime;
- squashfs_block start_block;
- unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+ unsigned int start_block;
+ unsigned int file_size:32;
unsigned short block_list[0];
-} __attribute__ ((packed)) squashfs_reg_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_dir_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
@@ -403,72 +608,308 @@ typedef struct {
unsigned int offset:13;
unsigned int mtime;
unsigned int start_block:24;
-} __attribute__ ((packed)) squashfs_dir_inode_header_1;
+} __attribute__ ((packed));
-#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
SQUASHFS_MEMSET(s, d, n);\
SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
SQUASHFS_SWAP((s)->mode, d, 4, 12);\
SQUASHFS_SWAP((s)->uid, d, 16, 4);\
- SQUASHFS_SWAP((s)->guid, d, 20, 4);\
+ SQUASHFS_SWAP((s)->guid, d, 20, 4);
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
}
#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_ipc_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_ipc_inode_header_1));\
SQUASHFS_SWAP((s)->type, d, 24, 4);\
SQUASHFS_SWAP((s)->offset, d, 28, 4);\
}
#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_dev_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_dev_inode_header_1));\
SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
}
#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_symlink_inode_header_1));\
SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
}
#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_reg_inode_header_1));\
SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
- SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\
+ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
}
#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_dir_inode_header_1));\
SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
SQUASHFS_SWAP((s)->offset, d, 43, 13);\
SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
}
+
+#endif
+
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+
+struct squashfs_dir_index_2 {
+ unsigned int index:27;
+ unsigned int start_block:29;
+ unsigned char size;
+ unsigned char name[0];
+} __attribute__ ((packed));
+
+struct squashfs_base_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+} __attribute__ ((packed));
+
+struct squashfs_ipc_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+} __attribute__ ((packed));
+
+struct squashfs_dev_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned short rdev;
+} __attribute__ ((packed));
+
+struct squashfs_symlink_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned short symlink_size;
+ char symlink[0];
+} __attribute__ ((packed));
+
+struct squashfs_reg_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int mtime;
+ unsigned int start_block;
+ unsigned int fragment;
+ unsigned int offset;
+ unsigned int file_size:32;
+ unsigned short block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int file_size:19;
+ unsigned int offset:13;
+ unsigned int mtime;
+ unsigned int start_block:24;
+} __attribute__ ((packed));
+
+struct squashfs_ldir_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int file_size:27;
+ unsigned int offset:13;
+ unsigned int mtime;
+ unsigned int start_block:24;
+ unsigned int i_count:16;
+ struct squashfs_dir_index_2 index[0];
+} __attribute__ ((packed));
+
+union squashfs_inode_header_2 {
+ struct squashfs_base_inode_header_2 base;
+ struct squashfs_dev_inode_header_2 dev;
+ struct squashfs_symlink_inode_header_2 symlink;
+ struct squashfs_reg_inode_header_2 reg;
+ struct squashfs_dir_inode_header_2 dir;
+ struct squashfs_ldir_inode_header_2 ldir;
+ struct squashfs_ipc_inode_header_2 ipc;
+};
+
+struct squashfs_dir_header_2 {
+ unsigned int count:8;
+ unsigned int start_block:24;
+} __attribute__ ((packed));
+
+struct squashfs_dir_entry_2 {
+ unsigned int offset:13;
+ unsigned int type:3;
+ unsigned int size:8;
+ char name[0];
+} __attribute__ ((packed));
+
+struct squashfs_fragment_entry_2 {
+ unsigned int start_block;
+ unsigned int size;
+} __attribute__ ((packed));
+
+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
+ SQUASHFS_MEMSET(s, d, n);\
+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_dev_inode_header_2)); \
+ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_symlink_inode_header_2));\
+ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_reg_inode_header_2));\
+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
+ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
+ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_dir_inode_header_2));\
+ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
+ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
+ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
+}
+
+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_ldir_inode_header_2));\
+ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
+ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
+ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
+ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
+}
+
+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
+ SQUASHFS_SWAP((s)->index, d, 0, 27);\
+ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
+ SQUASHFS_SWAP((s)->size, d, 56, 8);\
+}
+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
+ SQUASHFS_SWAP((s)->count, d, 0, 8);\
+ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
+}
+
+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
+ SQUASHFS_SWAP((s)->type, d, 13, 3);\
+ SQUASHFS_SWAP((s)->size, d, 16, 8);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
+ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
+ SQUASHFS_SWAP((s)->size, d, 32, 32);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
+
+/* fragment and fragment table defines */
+#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
+
+#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
+ SQUASHFS_METADATA_SIZE - 1) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
+ sizeof(int))
+
#endif
#ifdef __KERNEL__
+
/*
* macros used to swap each structure entry, taking into account
- * bitfields and different bitfield placing conventions on differing architectures
+ * bitfields and different bitfield placing conventions on differing
+ * architectures
*/
+
#include <asm/byteorder.h>
+
#ifdef __BIG_ENDIAN
/* convert from little endian to big endian */
-#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos)
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+ tbits, b_pos)
#else
/* convert from big endian to little endian */
-#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos)
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+ tbits, 64 - tbits - b_pos)
#endif
#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
- int bits;\
- int b_pos = pos % 8;\
- unsigned long long val = 0;\
- unsigned char *s = (unsigned char *)p + (pos / 8);\
- unsigned char *d = ((unsigned char *) &val) + 7;\
+ b_pos = pos % 8;\
+ val = 0;\
+ s = (unsigned char *)p + (pos / 8);\
+ d = ((unsigned char *) &val) + 7;\
for(bits = 0; bits < (tbits + b_pos); bits += 8) \
*d-- = *s++;\
value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
}
+
#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
+
#endif
#endif
diff --git a/release/src/linux/linux/include/linux/squashfs_fs_i.h b/release/src/linux/linux/include/linux/squashfs_fs_i.h
index 47043b37..0fe28cc4 100644
--- a/release/src/linux/linux/include/linux/squashfs_fs_i.h
+++ b/release/src/linux/linux/include/linux/squashfs_fs_i.h
@@ -3,7 +3,8 @@
/*
* Squashfs
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,12 +23,22 @@
* squashfs_fs_i.h
*/
-typedef struct squashfs_inode_info {
- unsigned int start_block;
- unsigned int block_list_start;
+struct squashfs_inode_info {
+ long long start_block;
unsigned int offset;
- unsigned int fragment_start_block;
- unsigned int fragment_size;
- unsigned int fragment_offset;
- } squashfs_inode_info;
+ union {
+ struct {
+ long long fragment_start_block;
+ unsigned int fragment_size;
+ unsigned int fragment_offset;
+ long long block_list_start;
+ } s1;
+ struct {
+ long long directory_index_start;
+ unsigned int directory_index_offset;
+ unsigned int directory_index_count;
+ unsigned int parent_inode;
+ } s2;
+ } u;
+};
#endif
diff --git a/release/src/linux/linux/include/linux/squashfs_fs_sb.h b/release/src/linux/linux/include/linux/squashfs_fs_sb.h
index 6ce5e228..9ea7a11c 100644
--- a/release/src/linux/linux/include/linux/squashfs_fs_sb.h
+++ b/release/src/linux/linux/include/linux/squashfs_fs_sb.h
@@ -3,7 +3,8 @@
/*
* Squashfs
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,42 +25,50 @@
#include <linux/squashfs_fs.h>
-typedef struct {
- unsigned int block;
+struct squashfs_cache {
+ long long block;
int length;
- unsigned int next_index;
+ long long next_index;
char *data;
- } squashfs_cache;
+};
struct squashfs_fragment_cache {
- unsigned int block;
+ long long block;
int length;
unsigned int locked;
char *data;
- };
+};
-typedef struct squashfs_sb_info {
- squashfs_super_block sBlk;
+struct squashfs_sb_info {
+ struct squashfs_super_block sblk;
int devblksize;
int devblksize_log2;
int swap;
- squashfs_cache *block_cache;
+ struct squashfs_cache *block_cache;
struct squashfs_fragment_cache *fragment;
int next_cache;
int next_fragment;
- squashfs_uid *uid;
- squashfs_uid *guid;
- squashfs_fragment_index *fragment_index;
+ int next_meta_index;
+ unsigned int *uid;
+ unsigned int *guid;
+ long long *fragment_index;
+ unsigned int *fragment_index_2;
unsigned int read_size;
char *read_data;
char *read_page;
+ struct semaphore read_data_mutex;
struct semaphore read_page_mutex;
struct semaphore block_cache_mutex;
struct semaphore fragment_mutex;
+ struct semaphore meta_index_mutex;
wait_queue_head_t waitq;
wait_queue_head_t fragment_wait_queue;
- struct inode *(*iget)(struct super_block *s, squashfs_inode inode);
- unsigned int (*read_blocklist)(struct inode *inode, int index, int readahead_blks,
- char *block_list, char **block_p, unsigned int *bsize);
- } squashfs_sb_info;
+ struct meta_index *meta_index;
+ struct inode *(*iget)(struct super_block *s, squashfs_inode_t \
+ inode);
+ long long (*read_blocklist)(struct inode *inode, int \
+ index, int readahead_blks, char *block_list, \
+ unsigned short **block_p, unsigned int *bsize);
+ int (*read_fragment_index_table)(struct super_block *s);
+};
#endif
diff --git a/release/src/linux/linux/include/linux/sysctl.h b/release/src/linux/linux/include/linux/sysctl.h
index ef417f6b..5742f382 100644
--- a/release/src/linux/linux/include/linux/sysctl.h
+++ b/release/src/linux/linux/include/linux/sysctl.h
@@ -292,7 +292,11 @@ enum
NET_IPV4_NONLOCAL_BIND=88,
NET_IPV4_ICMP_RATELIMIT=89,
NET_IPV4_ICMP_RATEMASK=90,
- NET_TCP_TW_REUSE=91
+ NET_TCP_TW_REUSE=91,
+ NET_TCP_VEGAS=92,
+ NET_TCP_VEGAS_ALPHA=93,
+ NET_TCP_VEGAS_BETA=94,
+ NET_TCP_VEGAS_GAMMA=95
};
enum {
diff --git a/release/src/linux/linux/include/net/pkt_cls.h b/release/src/linux/linux/include/net/pkt_cls.h
index cb2bde23..0926f823 100644
--- a/release/src/linux/linux/include/net/pkt_cls.h
+++ b/release/src/linux/linux/include/net/pkt_cls.h
@@ -77,7 +77,11 @@ static inline int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, struct
return -1;
}
-
+static inline void tcf_destroy(struct tcf_proto *tp)
+{
+ tp->ops->destroy(tp);
+ kfree(tp);
+}
extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
diff --git a/release/src/linux/linux/include/net/pkt_sched.h b/release/src/linux/linux/include/net/pkt_sched.h
index a9027b90..7b91dac6 100644
--- a/release/src/linux/linux/include/net/pkt_sched.h
+++ b/release/src/linux/linux/include/net/pkt_sched.h
@@ -198,6 +198,7 @@ typedef long psched_tdiff_t;
#define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
+#define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ))
#define PSCHED_EXPORTLIST EXPORT_SYMBOL(psched_tod_diff);
@@ -212,12 +213,16 @@ extern psched_time_t psched_time_base;
#if PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES
-#if HZ == 100
+#if HZ < 96
+#define PSCHED_JSCALE 14
+#elif HZ >= 96 && HZ < 192
#define PSCHED_JSCALE 13
-#elif HZ == 1024
+#elif HZ >= 192 && HZ < 384
+#define PSCHED_JSCALE 12
+#elif HZ >= 384 && HZ < 768
+#define PSCHED_JSCALE 11
+#elif HZ >= 768
#define PSCHED_JSCALE 10
-#else
-#define PSCHED_JSCALE 0
#endif
#define PSCHED_EXPORTLIST_2
@@ -242,6 +247,7 @@ extern PSCHED_WATCHER psched_time_mark;
#endif
#define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE)
+#define PSCHED_JIFFIE2US(delay) ((delay)<<PSCHED_JSCALE)
#elif PSCHED_CLOCK_SOURCE == PSCHED_CPU
@@ -252,6 +258,7 @@ extern int psched_clock_scale;
EXPORT_SYMBOL(psched_clock_scale);
#define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
+#define PSCHED_JIFFIE2US(delay) ((delay)*psched_clock_per_hz)
#ifdef CONFIG_X86_TSC
diff --git a/release/src/linux/linux/include/net/sock.h b/release/src/linux/linux/include/net/sock.h
index 0482a102..a2824afb 100644
--- a/release/src/linux/linux/include/net/sock.h
+++ b/release/src/linux/linux/include/net/sock.h
@@ -417,7 +417,19 @@ struct tcp_opt {
unsigned int keepalive_intvl; /* time interval between keep alive probes */
int linger2;
- unsigned long last_synq_overflow;
+ unsigned long last_synq_overflow;
+
+/* Vegas variables */
+ struct {
+ __u32 beg_snd_nxt; /* right edge during last RTT */
+ __u32 beg_snd_una; /* left edge during last RTT */
+ __u32 beg_snd_cwnd; /* saves the size of the cwnd */
+ __u8 do_vegas; /* do vegas for this connection */
+ __u8 doing_vegas_now;/* if true, do vegas for this RTT */
+ __u16 cntRTT; /* # of RTTs measured within last RTT */
+ __u32 minRTT; /* min of RTTs measured within last RTT (in usec) */
+ __u32 baseRTT; /* the min of all Vegas RTT measurements seen (in usec) */
+ } vegas;
};
diff --git a/release/src/linux/linux/include/net/tcp.h b/release/src/linux/linux/include/net/tcp.h
index 6571f4b2..e9a9e254 100644
--- a/release/src/linux/linux/include/net/tcp.h
+++ b/release/src/linux/linux/include/net/tcp.h
@@ -456,6 +456,10 @@ extern int sysctl_tcp_rmem[3];
extern int sysctl_tcp_app_win;
extern int sysctl_tcp_adv_win_scale;
extern int sysctl_tcp_tw_reuse;
+extern int sysctl_tcp_vegas_cong_avoid;
+extern int sysctl_tcp_vegas_alpha;
+extern int sysctl_tcp_vegas_beta;
+extern int sysctl_tcp_vegas_gamma;
extern atomic_t tcp_memory_allocated;
extern atomic_t tcp_sockets_allocated;
@@ -1070,6 +1074,59 @@ static inline __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
return max(tp->snd_cwnd >> 1U, 2U);
}
+/* Stop taking Vegas samples for now. */
+#define tcp_vegas_disable(__tp) ((__tp)->vegas.doing_vegas_now = 0)
+
+/* Is this TCP connection using Vegas (regardless of whether it is taking
+ * Vegas measurements at the current time)?
+ */
+#define tcp_is_vegas(__tp) ((__tp)->vegas.do_vegas)
+
+static inline void tcp_vegas_enable(struct tcp_opt *tp)
+{
+ /* There are several situations when we must "re-start" Vegas:
+ *
+ * o when a connection is established
+ * o after an RTO
+ * o after fast recovery
+ * o when we send a packet and there is no outstanding
+ * unacknowledged data (restarting an idle connection)
+ *
+ * In these circumstances we cannot do a Vegas calculation at the
+ * end of the first RTT, because any calculation we do is using
+ * stale info -- both the saved cwnd and congestion feedback are
+ * stale.
+ *
+ * Instead we must wait until the completion of an RTT during
+ * which we actually receive ACKs.
+ */
+
+ /* Begin taking Vegas samples next time we send something. */
+ tp->vegas.doing_vegas_now = 1;
+
+ /* Set the beginning of the next send window. */
+ tp->vegas.beg_snd_nxt = tp->snd_nxt;
+
+ tp->vegas.cntRTT = 0;
+ tp->vegas.minRTT = 0x7fffffff;
+}
+
+/* Should we be taking Vegas samples right now? */
+#define tcp_vegas_enabled(__tp) ((__tp)->vegas.doing_vegas_now)
+
+extern void tcp_vegas_init(struct tcp_opt *tp);
+
+static inline void tcp_set_ca_state(struct tcp_opt *tp, u8 ca_state)
+{
+ if (tcp_is_vegas(tp)) {
+ if (ca_state == TCP_CA_Open)
+ tcp_vegas_enable(tp);
+ else
+ tcp_vegas_disable(tp);
+ }
+ tp->ca_state = ca_state;
+}
+
/* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd.
* The exception is rate halving phase, when cwnd is decreasing towards
* ssthresh.
@@ -1129,7 +1186,7 @@ static inline void tcp_enter_cwr(struct tcp_opt *tp)
tp->prior_ssthresh = 0;
if (tp->ca_state < TCP_CA_CWR) {
__tcp_enter_cwr(tp);
- tp->ca_state = TCP_CA_CWR;
+ tcp_set_ca_state(tp, TCP_CA_CWR);
}
}
diff --git a/release/src/linux/linux/lib/Config.in b/release/src/linux/linux/lib/Config.in
index 527477aa..5edba1f5 100644
--- a/release/src/linux/linux/lib/Config.in
+++ b/release/src/linux/linux/lib/Config.in
@@ -8,14 +8,12 @@ comment 'Library routines'
# Do we need the compression support?
#
if [ "$CONFIG_CRAMFS" = "y" -o \
- "$CONFIG_SQUASHFS" = "y" -o \
"$CONFIG_PPP_DEFLATE" = "y" -o \
"$CONFIG_JFFS2_FS" = "y" -o \
"$CONFIG_ZISOFS_FS" = "y" ]; then
define_tristate CONFIG_ZLIB_INFLATE y
else
if [ "$CONFIG_CRAMFS" = "m" -o \
- "$CONFIG_SQUASHFS" = "m" -o \
"$CONFIG_PPP_DEFLATE" = "m" -o \
"$CONFIG_JFFS2_FS" = "m" -o \
"$CONFIG_ZISOFS_FS" = "m" ]; then
diff --git a/release/src/linux/linux/lib/rbtree.c b/release/src/linux/linux/lib/rbtree.c
index bed359bd..f941d73e 100644
--- a/release/src/linux/linux/lib/rbtree.c
+++ b/release/src/linux/linux/lib/rbtree.c
@@ -294,3 +294,76 @@ void rb_erase(rb_node_t * node, rb_root_t * root)
__rb_erase_color(child, parent, root);
}
EXPORT_SYMBOL(rb_erase);
+
+/*
+ * This function returns the first node (in sort order) of the tree.
+ */
+rb_node_t *rb_first(rb_root_t *root)
+{
+ rb_node_t *n;
+
+ n = root->rb_node;
+ if (!n)
+ return NULL;
+ while (n->rb_left)
+ n = n->rb_left;
+ return n;
+}
+EXPORT_SYMBOL(rb_first);
+
+rb_node_t *rb_last(rb_root_t *root)
+{
+ rb_node_t *n;
+
+ n = root->rb_node;
+ if (!n)
+ return NULL;
+ while (n->rb_right)
+ n = n->rb_right;
+ return n;
+}
+EXPORT_SYMBOL(rb_last);
+
+rb_node_t *rb_next(rb_node_t *node)
+{
+ /* If we have a right-hand child, go down and then left as far
+ as we can. */
+ if (node->rb_right) {
+ node = node->rb_right;
+ while (node->rb_left)
+ node = node->rb_left;
+ return node;
+ }
+
+ /* No right-hand children. Everything down and left is
+ smaller than us, so any 'next' node must be in the general
+ direction of our parent. Go up the tree; any time the
+ ancestor is a right-hand child of its parent, keep going
+ up. First time it's a left-hand child of its parent, said
+ parent is our 'next' node. */
+ while (node->rb_parent && node == node->rb_parent->rb_right)
+ node = node->rb_parent;
+
+ return node->rb_parent;
+}
+EXPORT_SYMBOL(rb_next);
+
+rb_node_t *rb_prev(rb_node_t *node)
+{
+ /* If we have a left-hand child, go down and then right as far
+ as we can. */
+ if (node->rb_left) {
+ node = node->rb_left;
+ while (node->rb_right)
+ node = node->rb_right;
+ return node;
+ }
+
+ /* No left-hand children. Go up till we find an ancestor which
+ is a right-hand child of its parent */
+ while (node->rb_parent && node == node->rb_parent->rb_left)
+ node = node->rb_parent;
+
+ return node->rb_parent;
+}
+EXPORT_SYMBOL(rb_prev);
diff --git a/release/src/linux/linux/net/core/skbuff.c b/release/src/linux/linux/net/core/skbuff.c
index 57d19374..32476545 100644
--- a/release/src/linux/linux/net/core/skbuff.c
+++ b/release/src/linux/linux/net/core/skbuff.c
@@ -201,6 +201,10 @@ struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
/* Set up other state */
skb->len = 0;
skb->cloned = 0;
+#if defined(CONFIG_IMQ) || defined (CONFIG_IMQ_MODULE)
+ skb->imq_flags = 0;
+ skb->nf_info = NULL;
+#endif
skb->data_len = 0;
atomic_set(&skb->users, 1);
@@ -248,6 +252,10 @@ static inline void skb_headerinit(void *p, kmem_cache_t *cache,
#ifdef CONFIG_NET_SCHED
skb->tc_index = 0;
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ skb->imq_flags = 0;
+ skb->nf_info = NULL;
+#endif
}
static void skb_drop_fraglist(struct sk_buff *skb)
@@ -397,6 +405,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
#ifdef CONFIG_NET_SCHED
C(tc_index);
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ C(imq_flags);
+ C(nf_info);
+#endif
atomic_inc(&(skb_shinfo(skb)->dataref));
skb->cloned = 1;
@@ -440,6 +452,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
#ifdef CONFIG_NET_SCHED
new->tc_index = old->tc_index;
#endif
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ new->imq_flags=old->imq_flags;
+ new->nf_info=old->nf_info;
+#endif
}
/**
diff --git a/release/src/linux/linux/net/ipv4/arp.c b/release/src/linux/linux/net/ipv4/arp.c
index aecd020a..e458f7d5 100644
--- a/release/src/linux/linux/net/ipv4/arp.c
+++ b/release/src/linux/linux/net/ipv4/arp.c
@@ -171,8 +171,8 @@ struct neigh_table arp_tbl = {
id: "arp_cache",
parms: {
tbl: &arp_tbl,
- /*zhijian 2006-10-23 modify to solve arp entry timeout problem(cdrouter3.3 scaling module)*/
- #if 0
+/*zhijian 2006-10-23 modify to solve arp entry timeout problem(cdrouter3.3 scaling module)*/
+#if 0
base_reachable_time: 30 * HZ,
retrans_time: 1 * HZ,
gc_staletime: 60 * HZ,
@@ -181,16 +181,16 @@ struct neigh_table arp_tbl = {
queue_len: 3,
ucast_probes: 3,
mcast_probes: 3,
- #else
- base_reachable_time: 60 * HZ,
- retrans_time: 5 * HZ,
- gc_staletime: 120 * HZ,
- reachable_time: 60 * HZ,
- delay_probe_time: 10 * HZ,
- queue_len: 3,
- ucast_probes: 6,
- mcast_probes: 6,
- #endif
+#else
+ base_reachable_time: 60 * HZ,
+ retrans_time: 5 * HZ,
+ gc_staletime: 120 * HZ,
+ reachable_time: 60 * HZ,
+ delay_probe_time: 10 * HZ,
+ queue_len: 3,
+ ucast_probes: 6,
+ mcast_probes: 6,
+#endif
anycast_delay: 1 * HZ,
proxy_delay: (8 * HZ) / 10,
proxy_qlen: 64,
diff --git a/release/src/linux/linux/net/ipv4/igmp.c b/release/src/linux/linux/net/ipv4/igmp.c
index 3f718f2a..c53d8feb 100644
--- a/release/src/linux/linux/net/ipv4/igmp.c
+++ b/release/src/linux/linux/net/ipv4/igmp.c
@@ -677,8 +677,9 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
count++;
}
err = -ENOBUFS;
- //if (iml == NULL || count >= sysctl_igmp_max_memberships)
- if (iml == NULL || count > sysctl_igmp_max_memberships)// modify for cdrouter v3.3 item 300(cdrouter_mcast_100) bug
+ // if (iml == NULL || count >= sysctl_igmp_max_memberships)
+ // 43011: modify for cdrouter v3.3 item 300(cdrouter_mcast_100) bug
+ if (iml == NULL || count > sysctl_igmp_max_memberships)
goto done;
memcpy(&iml->multi, imr, sizeof(*imr));
iml->next = sk->protinfo.af_inet.mc_list;
diff --git a/release/src/linux/linux/net/ipv4/netfilter/Config.in b/release/src/linux/linux/net/ipv4/netfilter/Config.in
index 7662305e..b1f7f985 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/Config.in
+++ b/release/src/linux/linux/net/ipv4/netfilter/Config.in
@@ -7,16 +7,17 @@ comment ' IP: Netfilter Configuration'
tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP_NF_CONNTRACK
if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
dep_tristate ' FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK
- dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
+ bool ' Connection mark tracking support' CONFIG_IP_NF_CONNTRACK_MARK
dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
+ dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
dep_tristate ' CuSeeMe protocol support' CONFIG_IP_NF_CUSEEME $CONFIG_IP_NF_CONNTRACK
dep_tristate ' Quake III protocol support' CONFIG_IP_NF_QUAKE3 $CONFIG_IP_NF_CONNTRACK
dep_tristate ' RTSP protocol support' CONFIG_IP_NF_RTSP $CONFIG_IP_NF_CONNTRACK
dep_tristate ' MMS protocol support' CONFIG_IP_NF_MMS $CONFIG_IP_NF_CONNTRACK
- dep_tristate ' SIP protocol support' CONFIG_IP_NF_SIP $CONFIG_IP_NF_CONNTRACK
dep_tristate ' GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+ dep_tristate ' SIP protocol support' CONFIG_IP_NF_SIP $CONFIG_IP_NF_CONNTRACK
dep_tristate ' ESP protocol support' CONFIG_IP_NF_CT_PROTO_ESP $CONFIG_IP_NF_CONNTRACK
fi
@@ -27,6 +28,10 @@ tristate 'IP tables support (required for filtering/masq/NAT)' CONFIG_IP_NF_IPTA
if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
# The simple matches.
dep_tristate ' limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' IPP2P match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' geoip match support' CONFIG_IP_NF_MATCH_GEOIP $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' quota match support' CONFIG_IP_NF_MATCH_QUOTA $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' IP range match support' CONFIG_IP_NF_MATCH_IPRANGE $CONFIG_IP_NF_IPTABLES
dep_tristate ' IP address pool support' CONFIG_IP_NF_POOL $CONFIG_IP_NF_IPTABLES
if [ "$CONFIG_IP_NF_POOL" = "y" -o "$CONFIG_IP_NF_POOL" = "m" ]; then
@@ -39,6 +44,12 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
dep_tristate ' Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES
dep_tristate ' Multiple port with ranges match support' CONFIG_IP_NF_MATCH_MPORT $CONFIG_IP_NF_IPTABLES
dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' account match support' CONFIG_IP_NF_MATCH_ACCOUNT $CONFIG_IP_NF_IPTABLES $CONFIG_PROC_FS
+ if [ "$CONFIG_IP_NF_MATCH_ACCOUNT" != "n" ]; then
+ bool ' account debugging output' CONFIG_IP_NF_MATCH_ACCOUNT_DEBUG
+ fi
+ dep_tristate ' condition match support' CONFIG_IP_NF_MATCH_CONDITION $CONFIG_IP_NF_IPTABLES
dep_tristate ' TIME match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_TIME $CONFIG_IP_NF_IPTABLES
dep_tristate ' ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
@@ -46,19 +57,36 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
dep_tristate ' AH/ESP match support' CONFIG_IP_NF_MATCH_AH_ESP $CONFIG_IP_NF_IPTABLES
dep_tristate ' LENGTH match support' CONFIG_IP_NF_MATCH_LENGTH $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' U32 match support' CONFIG_IP_NF_MATCH_U32 $CONFIG_IP_NF_U32
dep_tristate ' TTL match support' CONFIG_IP_NF_MATCH_TTL $CONFIG_IP_NF_IPTABLES
dep_tristate ' tcpmss match support' CONFIG_IP_NF_MATCH_TCPMSS $CONFIG_IP_NF_IPTABLES
+
if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
dep_tristate ' Helper match support' CONFIG_IP_NF_MATCH_HELPER $CONFIG_IP_NF_IPTABLES
fi
if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Connections/IP limit match support' CONFIG_IP_NF_MATCH_CONNLIMIT $CONFIG_IP_NF_IPTABLES
+ if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
+ dep_tristate ' Connection mark match support' CONFIG_IP_NF_MATCH_CONNMARK $CONFIG_IP_NF_IPTABLES
+ fi
dep_tristate ' Connection tracking match support' CONFIG_IP_NF_MATCH_CONNTRACK $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' String match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_STRING $CONFIG_IP_NF_IPTABLES
dep_tristate ' Webstr match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_WEBSTR $CONFIG_IP_NF_IPTABLES
dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' Layer 7 match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7 $CONFIG_IP_NF_CONNTRACK
+ dep_mbool ' Layer 7 debugging output (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7_DEBUG $CONFIG_IP_NF_MATCH_LAYER7
+
+ dep_tristate ' web match' CONFIG_IP_NF_MATCH_WEB $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' BCOUNT target' CONFIG_IP_NF_TARGET_BCOUNT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' bcount match' CONFIG_IP_NF_MATCH_BCOUNT $CONFIG_IP_NF_TARGET_BCOUNT
+ dep_tristate ' MACSAVE target' CONFIG_IP_NF_TARGET_MACSAVE $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' macsave match' CONFIG_IP_NF_MATCH_MACSAVE $CONFIG_IP_NF_TARGET_MACSAVE
+ dep_tristate ' exp match (experimental rig - do not use)' CONFIG_IP_NF_MATCH_EXP $CONFIG_IP_NF_IPTABLES
+
fi
# The targets
dep_tristate ' Packet filtering' CONFIG_IP_NF_FILTER $CONFIG_IP_NF_IPTABLES
@@ -75,8 +103,6 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
define_bool CONFIG_IP_NF_NAT_NEEDED y
dep_tristate ' MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT
dep_tristate ' REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT
- dep_tristate ' Automatic port forwarding (autofw) target support' CONFIG_IP_NF_AUTOFW $CONFIG_IP_NF_NAT
- dep_tristate ' TRIGGER target support (port-trigger)' CONFIG_IP_NF_TARGET_TRIGGER $CONFIG_IP_NF_NAT
if [ "$CONFIG_IP_NF_H323" = "m" ]; then
define_tristate CONFIG_IP_NF_NAT_H323 m
else
@@ -84,6 +110,8 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
fi
fi
+ dep_tristate ' Automatic port forwarding (autofw) target support' CONFIG_IP_NF_AUTOFW $CONFIG_IP_NF_NAT
+ dep_tristate ' TRIGGER target support (port-trigger)' CONFIG_IP_NF_TARGET_TRIGGER $CONFIG_IP_NF_NAT
if [ "$CONFIG_IP_NF_PPTP" = "m" ]; then
define_tristate CONFIG_IP_NF_NAT_PPTP m
else
@@ -109,13 +137,20 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
fi
+ if [ "$CONFIG_IP_NF_RTSP" = "m" ]; then
+ define_tristate CONFIG_IP_NF_NAT_RTSP m
+ else
+ if [ "$CONFIG_IP_NF_RTSP" = "y" ]; then
+ define_tristate CONFIG_IP_NF_NAT_RTSP $CONFIG_IP_NF_NAT
+ fi
+ fi
if [ "$CONFIG_IP_NF_IRC" = "m" ]; then
define_tristate CONFIG_IP_NF_NAT_IRC m
else
if [ "$CONFIG_IP_NF_IRC" = "y" ]; then
define_tristate CONFIG_IP_NF_NAT_IRC $CONFIG_IP_NF_NAT
fi
- fi
+ fi
if [ "$CONFIG_IP_NF_CUSEEME" = "m" ]; then
define_tristate CONFIG_IP_NF_NAT_CUSEEME m
else
@@ -153,13 +188,6 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
define_tristate CONFIG_IP_NF_NAT_TFTP $CONFIG_IP_NF_NAT
fi
fi
- if [ "$CONFIG_IP_NF_RTSP" = "m" ]; then
- define_tristate CONFIG_IP_NF_NAT_RTSP m
- else
- if [ "$CONFIG_IP_NF_RTSP" = "y" ]; then
- define_tristate CONFIG_IP_NF_NAT_RTSP $CONFIG_IP_NF_NAT
- fi
- fi
if [ "$CONFIG_IP_NF_CT_PROTO_ESP" = "m" ]; then
define_tristate CONFIG_IP_NF_NAT_PROTO_ESP m
else
@@ -178,8 +206,15 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
dep_tristate ' DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+ dep_tristate ' ROUTE target support' CONFIG_IP_NF_TARGET_ROUTE $CONFIG_IP_NF_MANGLE
+ dep_tristate ' CLASSIFY target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_CLASSIFY $CONFIG_IP_NF_FILTER
+ dep_tristate ' IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
fi
dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
+ if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
+ dep_tristate ' CONNMARK target support' CONFIG_IP_NF_TARGET_CONNMARK $CONFIG_IP_NF_IPTABLES
+ fi
+ dep_tristate ' TTL target support' CONFIG_IP_NF_TARGET_TTL $CONFIG_IP_NF_IPTABLES
dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES
fi
@@ -189,6 +224,10 @@ if [ "$CONFIG_IP_NF_ARPTABLES" != "n" ]; then
dep_tristate ' ARP packet filtering' CONFIG_IP_NF_ARPFILTER $CONFIG_IP_NF_ARPTABLES
fi
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'tomato_ct' CONFIG_IP_NF_TOMATOCT
+fi
+
# Backwards compatibility modules: only if you don't build in the others.
if [ "$CONFIG_IP_NF_CONNTRACK" != "y" ]; then
if [ "$CONFIG_IP_NF_IPTABLES" != "y" ]; then
diff --git a/release/src/linux/linux/net/ipv4/netfilter/Makefile b/release/src/linux/linux/net/ipv4/netfilter/Makefile
index abf55469..80de56f3 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/Makefile
+++ b/release/src/linux/linux/net/ipv4/netfilter/Makefile
@@ -33,10 +33,10 @@ obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
# H.323 support
obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
-obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
-ifdef CONFIG_IP_NF_NAT_H323
+ifdef CONFIG_IP_NF_H323
export-objs += ip_conntrack_h323.o
endif
+obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
# connection tracking protocol helpers
@@ -83,10 +83,14 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
ifdef CONFIG_IP_NF_NAT_IRC
export-objs += ip_conntrack_irc.o
endif
+
+# rtsp protocol support
obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
ifdef CONFIG_IP_NF_NAT_RTSP
export-objs += ip_conntrack_rtsp.o
endif
+obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
+
# NAT helpers
obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
@@ -95,7 +99,6 @@ obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
-obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
# generic IP tables
@@ -109,48 +112,64 @@ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
# matches
obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
+obj-$(CONFIG_IP_NF_MATCH_GEOIP) += ipt_geoip.o
+obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
+obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ip_pool.o
obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
-
obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
-
obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
-
obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
-
+obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
+obj-$(CONFIG_IP_NF_MATCH_ACCOUNT) += ipt_account.o
+obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
-
obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
-
obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
-
+obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
+obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
+obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
+obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
obj-$(CONFIG_IP_NF_MATCH_WEBSTR) += ipt_webstr.o
obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
+obj-$(CONFIG_IP_NF_MATCH_WEB) += ipt_web.o
+obj-$(CONFIG_IP_NF_MATCH_MACSAVE) += ipt_macsave.o
+obj-$(CONFIG_IP_NF_MATCH_EXP) += ipt_exp.o
+obj-$(CONFIG_IP_NF_MATCH_BCOUNT) += ipt_bcount.o
# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o
+obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
+obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
+obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
+obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
obj-$(CONFIG_IP_NF_AUTOFW) += ip_autofw.o
obj-$(CONFIG_IP_NF_TARGET_TRIGGER) += ipt_TRIGGER.o
+obj-$(CONFIG_IP_NF_TARGET_MACSAVE) += ipt_MACSAVE.o
+obj-$(CONFIG_IP_NF_TARGET_BCOUNT) += ipt_BCOUNT.o
# generic ARP tables
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
@@ -164,6 +183,8 @@ obj-$(CONFIG_IP_NF_COMPAT_IPFWADM) += ipfwadm.o
obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
+obj-$(CONFIG_IP_NF_TOMATOCT) += tomato_ct.o
+
include $(TOPDIR)/Rules.make
ip_conntrack.o: $(ip_conntrack-objs)
diff --git a/release/src/linux/linux/net/ipv4/netfilter/arp_tables.c b/release/src/linux/linux/net/ipv4/netfilter/arp_tables.c
index aa1c034a..757fc2ab 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/arp_tables.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/arp_tables.c
@@ -986,13 +986,12 @@ static int do_add_counters(void *user, unsigned int len)
goto free;
write_lock_bh(&t->lock);
- /*************************************
- * modify by tanghui @ 2006-10-11
- * for a RACE CONDITION in the "do_add_counters()" function
- *************************************/
- //if (t->private->number != paddc->num_counters) {
- if (t->private->number != tmp.num_counters) {
- /*************************************/
+
+#if 0 // removed 1.11 forward bug test
+ // 43011 (09?): checkme: modify by tanghui @ 2006-10-11 for a RACE CONDITION in the "do_add_counters()" function
+ // if (t->private->number != tmp.num_counters) {
+#endif
+ if (t->private->number != paddc->num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_core.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_core.c
index 9c6f040f..324951ee 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_core.c
@@ -34,7 +34,12 @@
/* For ERR_PTR(). Yeah, I know... --RR */
#include <linux/fs.h>
-#include <linux/netdevice.h>
+#define TEST_JHASH // test jhash from 2.4.33 -- zzz
+
+#ifdef TEST_JHASH
+#include <linux/jhash.h>
+#include <linux/random.h>
+#endif
/* This rwlock protects the main hash table, protocol/helper/expected
registrations, conntrack timers*/
@@ -71,7 +76,7 @@ static kmem_cache_t *ip_conntrack_cachep;
int sysctl_ip_conntrack_tcp_timeouts[10] = {
30 MINS, /* TCP_CONNTRACK_NONE, */
- 5 DAYS, /* TCP_CONNTRACK_ESTABLISHED, */
+ 4 HOURS, /* TCP_CONNTRACK_ESTABLISHED, */ // was 5 days zzz
2 MINS, /* TCP_CONNTRACK_SYN_SENT, */
60 SECS, /* TCP_CONNTRACK_SYN_RECV, */
2 MINS, /* TCP_CONNTRACK_FIN_WAIT, */
@@ -128,9 +133,20 @@ ip_conntrack_put(struct ip_conntrack *ct)
nf_conntrack_put(&ct->infos[0]);
}
+#ifdef TEST_JHASH
+static int ip_conntrack_hash_rnd_initted;
+static unsigned int ip_conntrack_hash_rnd;
+#endif
+
static inline u_int32_t
hash_conntrack(const struct ip_conntrack_tuple *tuple)
{
+#ifdef TEST_JHASH
+ return (jhash_3words(tuple->src.ip,
+ (tuple->dst.ip ^ tuple->dst.protonum),
+ (tuple->src.u.all | (tuple->dst.u.all << 16)),
+ ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
+#else
/* ntohl because more differences in low bits. */
/* To ensure that halves of the same connection don't hash
clash, we add the source per-proto again. */
@@ -139,6 +155,7 @@ hash_conntrack(const struct ip_conntrack_tuple *tuple)
+ tuple->dst.protonum)
+ ntohs(tuple->src.u.all))
% ip_conntrack_htable_size;
+#endif
}
inline int
@@ -314,9 +331,6 @@ clean_from_lists(struct ip_conntrack *ct)
{
DEBUGP("clean_from_lists(%p)\n", ct);
MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
- /* Remove from both hash lists: must not NULL out next ptrs,
- otherwise we'll look unconfirmed. Fortunately, LIST_DELETE
- doesn't do this. --RR */
LIST_DELETE(&ip_conntrack_hash
[hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)],
&ct->tuplehash[IP_CT_DIR_ORIGINAL]);
@@ -359,6 +373,14 @@ destroy_conntrack(struct nf_conntrack *nfct)
list_del(&ct->master->expected_list);
kfree(ct->master);
}
+
+ #if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
+ if(ct->layer7.app_proto)
+ kfree(ct->layer7.app_proto);
+ if(ct->layer7.app_data)
+ kfree(ct->layer7.app_data);
+ #endif
+
WRITE_UNLOCK(&ip_conntrack_lock);
DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
@@ -489,6 +511,7 @@ __ip_conntrack_confirm(struct nf_ct_info *nfct)
ct->timeout.expires += jiffies;
add_timer(&ct->timeout);
atomic_inc(&ct->ct_general.use);
+ set_bit(IPS_CONFIRMED_BIT, &ct->status);
WRITE_UNLOCK(&ip_conntrack_lock);
return NF_ACCEPT;
}
@@ -606,7 +629,7 @@ icmp_error_track(struct sk_buff *skb,
connection. Too bad: we're in trouble anyway. */
static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
{
- return !(i->ctrack->status & IPS_ASSURED);
+ return !(test_bit(IPS_ASSURED_BIT, &i->ctrack->status));
}
static int early_drop(struct list_head *chain)
@@ -632,31 +655,6 @@ static int early_drop(struct list_head *chain)
return dropped;
}
-/******************lzh add ***************************************
-* DESCRIPTION:delete seleted ip conntrack from conntrack_hash list
-* INPUT : ip_conntrack_tuple_hash h
-* OUTPUT: NULL
-* AUTHOR: linzhihong
-* DATE : 2006.7.20
-*****************************************************************/
-void del_selected_conntrack(struct ip_conntrack_tuple_hash *h)
-{
- DEBUGP("hahaha enter %s\n", __FUNCTION__);
- if(h)
- {
- #if 1
- ip_ct_refresh(h->ctrack, 1*HZ);
- #else
- if(del_timer(&h->ctrack->timeout))
- {
- death_by_timeout((unsigned long)h->ctrack);
- }
- //ip_conntrack_put(h->ctrack);
- #endif
- }
-}
-/**************************** lzh end ******************************/
-
static inline int helper_cmp(const struct ip_conntrack_helper *i,
const struct ip_conntrack_tuple *rtuple)
{
@@ -670,41 +668,6 @@ struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *t
tuple);
}
-#define RESERVE_CONNTRACK_FOR_ROUTER
-#ifdef RESERVE_CONNTRACK_FOR_ROUTER
-#define RESERVE_CONNTRACK_NUM 20
-/*
- Check if the packet is for Router AP(LAN side only), or generate from
- Router itself(Both sides).
- */
-static int cmp_local_ip(u_int32_t dst, u_int32_t src)
-{
-#define IF_LAN_NAME "br0"
-
- int ret = -1;
- struct in_device *in_dev;
- struct net_device *dev;
- struct in_ifaddr **ifap = NULL;
- struct in_ifaddr *ifa = NULL;
-
- for(dev = dev_base; dev != NULL; dev = dev->next){
- if((in_dev=__in_dev_get(dev)) != NULL){
- for(ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next){
- if((ifa->ifa_address == dst && !strcmp(IF_LAN_NAME, ifa->ifa_label)) || ifa->ifa_address == src){
- /*match*/
- ret = 0;
- break;
- }
- }
- }
- }
-
- return ret;
-
-#undef IF_LAN_NAME
-}
-#endif
-
/* Allocate a new conntrack: we return -ENOMEM if classification
failed due to stress. Otherwise it really is unclassifiable. */
static struct ip_conntrack_tuple_hash *
@@ -719,9 +682,15 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
int i;
static unsigned int drop_next = 0;
+#ifdef TEST_JHASH
+ if (!ip_conntrack_hash_rnd_initted) {
+ get_random_bytes(&ip_conntrack_hash_rnd, 4);
+ ip_conntrack_hash_rnd_initted = 1;
+ }
+#endif
+
hash = hash_conntrack(tuple);
- #ifndef RESERVE_CONNTRACK_FOR_ROUTER
if (ip_conntrack_max &&
atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
/* Try dropping from random chain, or else from the
@@ -738,32 +707,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
return ERR_PTR(-ENOMEM);
}
}
- #else
-#define IPV4_BROADCAST_ADDR 0x000000FF
-#define IPV4_MULTICAST_ADDR 0xE0000000
- if (ip_conntrack_max &&
- (ip_conntrack_max - atomic_read(&ip_conntrack_count)) <= RESERVE_CONNTRACK_NUM){
- if((atomic_read(&ip_conntrack_count) < ip_conntrack_max) &&
- (((tuple->dst).ip & IPV4_BROADCAST_ADDR == IPV4_BROADCAST_ADDR) || ((tuple->dst).ip & IPV4_BROADCAST_ADDR == IPV4_MULTICAST_ADDR) || !cmp_local_ip((tuple->dst).ip, (tuple->src).ip))){
- //packet for router(LAN side only) or packet from router, let it go thru
- }
- else{
- /* Try dropping from random chain, or else from the
- chain about to put into (in case they're trying to
- bomb one hash chain). */
- unsigned int next = (drop_next++)%ip_conntrack_htable_size;
-
- if (!early_drop(&ip_conntrack_hash[next])
- && !early_drop(&ip_conntrack_hash[hash])) {
- if (net_ratelimit())
- printk(KERN_WARNING
- "ip_conntrack: table full, dropping"
- " packet.\n");
- return ERR_PTR(-ENOMEM);
- }
- }
- }
- #endif
if (!invert_tuple(&repl_tuple, tuple, protocol)) {
DEBUGP("Can't invert tuple.\n");
@@ -829,9 +772,12 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
conntrack, expected);
/* Welcome, Mr. Bond. We've been expecting you... */
IP_NF_ASSERT(master_ct(conntrack));
- conntrack->status = IPS_EXPECTED;
+ __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
conntrack->master = expected;
expected->sibling = conntrack;
+#if CONFIG_IP_NF_CONNTRACK_MARK
+ conntrack->mark = expected->expectant->mark;
+#endif
LIST_DELETE(&ip_conntrack_expect_list, expected);
INIT_LIST_HEAD(&expected->list);
expected->expectant->expecting--;
@@ -878,11 +824,11 @@ resolve_normal_ct(struct sk_buff *skb,
*set_reply = 1;
} else {
/* Once we've had two way comms, always ESTABLISHED. */
- if (h->ctrack->status & IPS_SEEN_REPLY) {
+ if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) {
DEBUGP("ip_conntrack_in: normal packet for %p\n",
h->ctrack);
*ctinfo = IP_CT_ESTABLISHED;
- } else if (h->ctrack->status & IPS_EXPECTED) {
+ } else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) {
DEBUGP("ip_conntrack_in: related packet for %p\n",
h->ctrack);
*ctinfo = IP_CT_RELATED;
@@ -1056,16 +1002,15 @@ int ip_conntrack_expect_related(struct ip_conntrack *related_to,
}
if (old) {
- /************************* lzh add ******************************************
- * fix sip alg CDROUTE test fail
- * 2007/3/16
- ***************************************************************************/
- if (old->help.exp_sip_info.nated && (old->help.exp_sip_info.type == CONN_RTP))
- {
- DEBUGP("%s: found old exp and nated, rtp port=%d\n", __FUNCTION__,ntohs(old->tuple.dst.u.udp.port));
- related_to->help.ct_sip_info.rtpport = ntohs(old->tuple.dst.u.udp.port);
+#if 0 // removed 1.11 forward bug test
+ if (1) { // 43011 (09?): checkme
+ // lzh add, fix sip alg CDROUTE test fail, 2007/3/16
+ if (old->help.exp_sip_info.nated && (old->help.exp_sip_info.type == CONN_RTP)) {
+ DEBUGP("%s: found old exp and nated, rtp port=%d\n", __FUNCTION__,ntohs(old->tuple.dst.u.udp.port));
+ related_to->help.ct_sip_info.rtpport = ntohs(old->tuple.dst.u.udp.port);
+ }
}
- /************************ lzh end ******************************************/
+#endif
WRITE_UNLOCK(&ip_conntrack_lock);
return -EEXIST;
}
@@ -1530,6 +1475,7 @@ int __init ip_conntrack_init(void)
unsigned int i;
int ret;
+#if 0
/* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB
* machine has 256 buckets. >= 1GB machines have 8192 buckets. */
if (hashsize) {
@@ -1544,6 +1490,33 @@ int __init ip_conntrack_init(void)
ip_conntrack_htable_size = 16;
}
ip_conntrack_max = 8 * ip_conntrack_htable_size;
+#else
+/*
+
+ sizeof(list_head) = 8
+ x 4096 = 32K
+
+ sizeof(ip_conntrack) = 368
+ x 2048 = 736K
+
+*/
+
+#ifdef TEST_JHASH
+/*
+ if (hashsize) ip_conntrack_htable_size = hashsize;
+ else ip_conntrack_htable_size = 4096;
+ ip_conntrack_max = 2048;
+*/
+ if (hashsize) ip_conntrack_htable_size = hashsize;
+ else ip_conntrack_htable_size = 8092;
+ ip_conntrack_max = 4096;
+#else
+ if (hashsize) ip_conntrack_htable_size = hashsize;
+ else ip_conntrack_htable_size = 4099;
+ ip_conntrack_max = 2048;
+#endif
+
+#endif
printk("ip_conntrack version %s (%u buckets, %d max)"
" - %d bytes per conntrack\n", IP_CONNTRACK_VERSION,
@@ -1605,3 +1578,5 @@ err_unreg_sockopt:
return -ENOMEM;
}
+
+
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_h323.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_h323.c
index cb0b1da5..c6172945 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_h323.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_h323.c
@@ -104,30 +104,26 @@ static int h245_help(const struct iphdr *iph, size_t len,
exp->seq = ntohl(tcph->seq) + i;
- *((u_int32_t *)data) = ct->tuplehash[!dir].tuple.dst.ip; //!!! Netmeeting fix
-
- {
- unsigned int chksum;
-
- chksum = csum_partial((char *)tcph + tcph->doff*4,
- datalen, 0);
-
- tcph->check = 0;
- tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
- csum_partial((char *)tcph, tcph->doff*4, chksum));
-
- }
-
+ // 43011 (09?): checkme
+ if (1) {
+ unsigned int chksum;
+
+ *((u_int32_t *)data) = ct->tuplehash[!dir].tuple.dst.ip; //!!! Netmeeting fix
+ chksum = csum_partial((char *)tcph + tcph->doff*4, datalen, 0);
+ tcph->check = 0;
+ tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
+ csum_partial((char *)tcph, tcph->doff*4, chksum));
+ }
exp->tuple = ((struct ip_conntrack_tuple)
{ { ct->tuplehash[!dir].tuple.src.ip,
{ 0 } },
{ data_ip,
- { data_port },
+ { .tcp = { data_port } },
IPPROTO_UDP }});
exp->mask = ((struct ip_conntrack_tuple)
{ { 0xFFFFFFFF, { 0 } },
- { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
exp->expectfn = NULL;
@@ -252,11 +248,11 @@ static int h225_help(const struct iphdr *iph, size_t len,
{ { ct->tuplehash[!dir].tuple.src.ip,
{ 0 } },
{ data_ip,
- { data_port },
+ { .tcp = { data_port } },
IPPROTO_TCP }});
exp->mask = ((struct ip_conntrack_tuple)
{ { 0xFFFFFFFF, { 0 } },
- { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
exp->expectfn = h225_expect;
@@ -317,9 +313,7 @@ static void __exit fini(void)
ip_conntrack_helper_unregister(&h225);
}
-#ifdef CONFIG_IP_NF_NAT_NEEDED
EXPORT_SYMBOL(ip_h323_lock);
-#endif
module_init(init);
module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c
index 17cf2b7b..a0b41051 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c
@@ -1,5 +1,5 @@
/*
- * ip_conntrack_pptp.c - Version 1.11
+ * ip_conntrack_pptp.c - Version 1.9
*
* Connection tracking support for PPTP (Point to Point Tunneling Protocol).
* PPTP is a a protocol for creating virtual private networks.
@@ -9,7 +9,7 @@
* GRE is defined in RFC 1701 and RFC 1702. Documentation of
* PPTP can be found in RFC 2637
*
- * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>,
+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
@@ -21,6 +21,18 @@
* TODO: - finish support for multiple calls within one session
* (needs expect reservations in newnat)
* - testing of incoming PPTP calls
+ *
+ * Changes:
+ * 2002-02-05 - Version 1.3
+ * - Call ip_conntrack_unexpect_related() from
+ * pptp_timeout_related() to destroy expectations in case
+ * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
+ * (Philip Craig <philipc@snapgear.com>)
+ * - Add Version information at module loadtime
+ * 2002-02-10 - Version 1.6
+ * - move to C99 style initializers
+ * - remove second expectation if first arrives
+ *
*/
#include <linux/config.h>
@@ -35,13 +47,21 @@
#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+#define IP_CT_PPTP_VERSION "1.9"
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
DECLARE_LOCK(ip_pptp_lock);
+#if 0
+#include "ip_conntrack_pptp_priv.h"
+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
+ ": " format, ## args)
+#else
#define DEBUGP(format, args...)
+#endif
#define SECS *HZ
#define MINS * 60 SECS
@@ -53,8 +73,8 @@ DECLARE_LOCK(ip_pptp_lock);
static int pptp_expectfn(struct ip_conntrack *ct)
{
- struct ip_conntrack_expect *exp, *other_exp;
struct ip_conntrack *master;
+ struct ip_conntrack_expect *exp;
DEBUGP("increasing timeouts\n");
/* increase timeout of GRE data channel conntrack entry */
@@ -67,6 +87,12 @@ static int pptp_expectfn(struct ip_conntrack *ct)
return 0;
}
+ exp = ct->master;
+ if (!exp) {
+ DEBUGP("no expectation!!\n");
+ return 0;
+ }
+
DEBUGP("completing tuples with ct info\n");
/* we can do this, since we're unconfirmed */
if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
@@ -83,6 +109,26 @@ static int pptp_expectfn(struct ip_conntrack *ct)
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
htonl(master->help.ct_pptp_info.pac_call_id);
}
+
+ /* delete other expectation */
+ if (exp->expected_list.next != &exp->expected_list) {
+ struct ip_conntrack_expect *other_exp;
+ struct list_head *cur_item, *next;
+
+ for (cur_item = master->sibling_list.next;
+ cur_item != &master->sibling_list; cur_item = next) {
+ next = cur_item->next;
+ other_exp = list_entry(cur_item,
+ struct ip_conntrack_expect,
+ expected_list);
+ /* remove only if occurred at same sequence number */
+ if (other_exp != exp && other_exp->seq == exp->seq) {
+ DEBUGP("unexpecting other direction\n");
+ ip_ct_gre_keymap_destroy(other_exp);
+ ip_conntrack_unexpect_related(other_exp);
+ }
+ }
+ }
return 0;
}
@@ -90,15 +136,21 @@ static int pptp_expectfn(struct ip_conntrack *ct)
/* timeout GRE data connections */
static int pptp_timeout_related(struct ip_conntrack *ct)
{
- struct list_head *cur_item;
+ struct list_head *cur_item, *next;
struct ip_conntrack_expect *exp;
- list_for_each(cur_item, &ct->sibling_list) {
+ /* FIXME: do we have to lock something ? */
+ for (cur_item = ct->sibling_list.next;
+ cur_item != &ct->sibling_list; cur_item = next) {
+ next = cur_item->next;
exp = list_entry(cur_item, struct ip_conntrack_expect,
expected_list);
- if (!exp->sibling)
+ ip_ct_gre_keymap_destroy(exp);
+ if (!exp->sibling) {
+ ip_conntrack_unexpect_related(exp);
continue;
+ }
DEBUGP("setting timeout of conntrack %p to 0\n",
exp->sibling);
@@ -110,7 +162,7 @@ static int pptp_timeout_related(struct ip_conntrack *ct)
return 0;
}
-/* expect GRE connection in PNS->PAC direction */
+/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
static inline int
exp_gre(struct ip_conntrack *master,
u_int32_t seq,
@@ -121,7 +173,7 @@ exp_gre(struct ip_conntrack *master,
struct ip_conntrack_tuple inv_tuple;
memset(&exp, 0, sizeof(exp));
- /* tuple in original direction, PAC->PNS */
+ /* tuple in original direction, PNS->PAC */
exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
@@ -149,11 +201,43 @@ exp_gre(struct ip_conntrack *master,
DUMP_TUPLE_RAW(&exp.tuple);
/* Add GRE keymap entries */
+ if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
+ return 1;
+
+ invert_tuplepr(&inv_tuple, &exp.tuple);
+ if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
+ ip_ct_gre_keymap_destroy(&exp);
+ return 1;
+ }
+
+ if (ip_conntrack_expect_related(master, &exp) != 0) {
+ ip_ct_gre_keymap_destroy(&exp);
+ DEBUGP("cannot expect_related()\n");
+ return 1;
+ }
+
+ /* tuple in reply direction, PAC->PNS */
+ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
+ exp.tuple.src.u.gre.key = htonl(ntohs(callid));
+ exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+ exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
+
+ DEBUGP("calling expect_related ");
+ DUMP_TUPLE_RAW(&exp.tuple);
+
+ /* Add GRE keymap entries */
ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
invert_tuplepr(&inv_tuple, &exp.tuple);
ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
+ /* FIXME: cannot handle error correctly, since we need to free
+ * the above keymap :( */
- ip_conntrack_expect_related(master, &exp);
+ if (ip_conntrack_expect_related(master, &exp) != 0) {
+ /* free the second pair of keypmaps */
+ ip_ct_gre_keymap_destroy(&exp);
+ DEBUGP("cannot expect_related():\n");
+ return 1;
+ }
return 0;
}
@@ -240,7 +324,8 @@ pptp_inbound_pkt(struct tcphdr *tcph,
info->cstate = PPTP_CALL_OUT_CONF;
seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
- exp_gre(ct, seq, *cid, *pcid);
+ if (exp_gre(ct, seq, *cid, *pcid) != 0)
+ printk("ip_conntrack_pptp: error during exp_gre\n");
break;
case PPTP_IN_CALL_REQUEST:
@@ -282,7 +367,8 @@ pptp_inbound_pkt(struct tcphdr *tcph,
/* we expect a GRE connection from PAC to PNS */
seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
- exp_gre(ct, seq, *cid, *pcid);
+ if (exp_gre(ct, seq, *cid, *pcid) != 0)
+ printk("ip_conntrack_pptp: error during exp_gre\n");
break;
@@ -294,7 +380,6 @@ pptp_inbound_pkt(struct tcphdr *tcph,
/* untrack this call id, unexpect GRE packets */
pptp_timeout_related(ct);
- /* NEWNAT: look up exp for call id and unexpct_related */
break;
case PPTP_WAN_ERROR_NOTIFY:
@@ -446,7 +531,8 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len,
if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
csum_partial((char *) tcph, tcplen, 0))) {
printk(KERN_NOTICE __FILE__ ": bad csum\n");
-// return NF_ACCEPT;
+ /* W2K PPTP server sends TCP packets with wrong checksum :(( */
+ //return NF_ACCEPT;
}
if (tcph->fin || tcph->rst) {
@@ -456,8 +542,6 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len,
/* untrack this call id, unexpect GRE packets */
pptp_timeout_related(ct);
- /* no need to call unexpect_related since master conn
- * dies anyway */
}
@@ -482,6 +566,8 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len,
LOCK_BH(&ip_pptp_lock);
+ /* FIXME: We just blindly assume that the control connection is always
+ * established from PNS->PAC. However, RFC makes no guarantee */
if (dir == IP_CT_DIR_ORIGINAL)
/* client -> server (PNS -> PAC) */
ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
@@ -497,13 +583,31 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len,
/* control protocol helper */
static struct ip_conntrack_helper pptp = {
- { NULL, NULL },
- "pptp", IP_CT_HELPER_F_REUSE_EXPECT, THIS_MODULE, 2, 0,
- { { 0, { tcp: { port: __constant_htons(PPTP_CONTROL_PORT) } } },
- { 0, { 0 }, IPPROTO_TCP } },
- { { 0, { tcp: { port: 0xffff } } },
- { 0, { 0 }, 0xffff } },
- conntrack_pptp_help };
+ .list = { NULL, NULL },
+ .name = "pptp",
+ .flags = IP_CT_HELPER_F_REUSE_EXPECT,
+ .me = THIS_MODULE,
+ .max_expected = 2,
+ .timeout = 0,
+ .tuple = { .src = { .ip = 0,
+ .u = { .tcp = { .port =
+ __constant_htons(PPTP_CONTROL_PORT) } }
+ },
+ .dst = { .ip = 0,
+ .u = { .all = 0 },
+ .protonum = IPPROTO_TCP
+ }
+ },
+ .mask = { .src = { .ip = 0,
+ .u = { .tcp = { .port = 0xffff } }
+ },
+ .dst = { .ip = 0,
+ .u = { .all = 0 },
+ .protonum = 0xffff
+ }
+ },
+ .help = conntrack_pptp_help
+};
/* ip_conntrack_pptp initialization */
static int __init init(void)
@@ -517,12 +621,14 @@ static int __init init(void)
return -EIO;
}
+ printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
return 0;
}
static void __exit fini(void)
{
ip_conntrack_helper_unregister(&pptp);
+ printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
}
module_init(init);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_esp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_esp.c
index bcb8d892..bcb8d892 100755..100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_esp.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_esp.c
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c
index 4ff06dcb..55b3ecea 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -1,5 +1,5 @@
/*
- * ip_conntrack_proto_gre.c - Version 1.11
+ * ip_conntrack_proto_gre.c - Version 1.2
*
* Connection tracking protocol helper module for GRE.
*
@@ -17,7 +17,7 @@
*
* Documentation about PPTP can be found in RFC 2637
*
- * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
@@ -54,8 +54,18 @@ MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
#define GRE_TIMEOUT (30*HZ)
#define GRE_STREAM_TIMEOUT (180*HZ)
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
+ ": " format, ## args)
+#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
+ NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
+ NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key), \
+ (x)->dst.u.gre.version, \
+ ntohs((x)->dst.u.gre.protocol))
+#else
#define DEBUGP(x, args...)
#define DUMP_TUPLE_GRE(x)
+#endif
/* GRE KEYMAP HANDLING FUNCTIONS */
static LIST_HEAD(gre_keymap_list);
@@ -103,7 +113,6 @@ int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
memset(km, 0, sizeof(*km));
memcpy(&km->tuple, t, sizeof(*t));
- km->master = exp;
if (!reply)
exp->proto.gre.keymap_orig = km;
@@ -132,6 +141,26 @@ void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
WRITE_UNLOCK(&ip_ct_gre_lock);
}
+/* destroy the keymap entries associated with specified expect */
+void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
+{
+ DEBUGP("entering for exp %p\n", exp);
+ WRITE_LOCK(&ip_ct_gre_lock);
+ if (exp->proto.gre.keymap_orig) {
+ DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
+ list_del(&exp->proto.gre.keymap_orig->list);
+ kfree(exp->proto.gre.keymap_orig);
+ exp->proto.gre.keymap_orig = NULL;
+ }
+ if (exp->proto.gre.keymap_reply) {
+ DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
+ list_del(&exp->proto.gre.keymap_reply->list);
+ kfree(exp->proto.gre.keymap_reply);
+ exp->proto.gre.keymap_reply = NULL;
+ }
+ WRITE_UNLOCK(&ip_ct_gre_lock);
+}
+
/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
@@ -186,6 +215,10 @@ static int gre_pkt_to_tuple(const void *datah, size_t datalen,
srckey = gre_keymap_lookup(tuple);
+#if 0
+ DEBUGP("found src key %x for tuple ", ntohl(srckey));
+ DUMP_TUPLE_GRE(tuple);
+#endif
tuple->src.u.gre.key = srckey;
return 1;
@@ -256,18 +289,7 @@ static void gre_destroy(struct ip_conntrack *ct)
return;
}
- WRITE_LOCK(&ip_ct_gre_lock);
- if (master->proto.gre.keymap_orig) {
- DEBUGP("removing %p from list\n", master->proto.gre.keymap_orig);
- list_del(&master->proto.gre.keymap_orig->list);
- kfree(master->proto.gre.keymap_orig);
- }
- if (master->proto.gre.keymap_reply) {
- DEBUGP("removing %p from list\n", master->proto.gre.keymap_reply);
- list_del(&master->proto.gre.keymap_reply->list);
- kfree(master->proto.gre.keymap_reply);
- }
- WRITE_UNLOCK(&ip_ct_gre_lock);
+ ip_ct_gre_keymap_destroy(master);
}
/* protocol helper struct */
@@ -304,7 +326,7 @@ static void __exit fini(void)
/* delete all keymap entries */
WRITE_LOCK(&ip_ct_gre_lock);
list_for_each_safe(pos, n, &gre_keymap_list) {
- DEBUGP("deleting keymap %p\n", pos);
+ DEBUGP("deleting keymap %p at module unload time\n", pos);
list_del(pos);
kfree(pos);
}
@@ -315,6 +337,7 @@ static void __exit fini(void)
EXPORT_SYMBOL(ip_ct_gre_keymap_add);
EXPORT_SYMBOL(ip_ct_gre_keymap_change);
+EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
module_init(init);
module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 02f20742..ebb9b493 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -173,7 +173,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
have an established connection: this is a fairly common
problem case, so we can delete the conntrack
immediately. --RR */
- if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) {
+ if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph->rst) {
WRITE_UNLOCK(&tcp_lock);
if (del_timer(&conntrack->timeout))
conntrack->timeout.function((unsigned long)conntrack);
@@ -211,12 +211,6 @@ static int tcp_new(struct ip_conntrack *conntrack,
return 0;
}
- if (tcph->syn && tcph->ack)
- {
- DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
- return 0;
- }
-
conntrack->proto.tcp.state = newconntrack;
return 1;
}
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 49ac62c7..af660a27 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -7,25 +7,13 @@
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#include <linux/netfilter_ipv4/ip_conntrack_udp.h>
-unsigned long ip_ct_udp_isakmp_timeout = (300*HZ);
-
static int udp_pkt_to_tuple(const void *datah, size_t datalen,
struct ip_conntrack_tuple *tuple)
{
const struct udphdr *hdr = datah;
- struct isakmp_hdr *isakmp_h = (void *)hdr + 8;
tuple->src.u.udp.port = hdr->source;
tuple->dst.u.udp.port = hdr->dest;
- if(ntohs(hdr->source) == 500 && ntohs(hdr->dest) == 500)
- {
- if(NULL == isakmp_h)
- tuple->dst.u.udp.init_cookie = 0;
- else
- tuple->dst.u.udp.init_cookie = (unsigned int)(isakmp_h->init_cookie[0]);
- }
- else
- tuple->dst.u.udp.init_cookie = 0;
return 1;
}
@@ -35,7 +23,6 @@ static int udp_invert_tuple(struct ip_conntrack_tuple *tuple,
{
tuple->src.u.udp.port = orig->dst.u.udp.port;
tuple->dst.u.udp.port = orig->src.u.udp.port;
- tuple->dst.u.udp.init_cookie = orig->dst.u.udp.init_cookie;
return 1;
}
@@ -60,21 +47,16 @@ static int udp_packet(struct ip_conntrack *conntrack,
struct iphdr *iph, size_t len,
enum ip_conntrack_info conntrackinfo)
{
- u_int16_t *portptr;
- portptr = &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
/* If we've seen traffic both ways, this is some kind of UDP
stream. Extend timeout. */
- if (conntrack->status & IPS_SEEN_REPLY)
- {
- if(ntohs(*portptr) == 500)
- ip_ct_refresh(conntrack, ip_ct_udp_isakmp_timeout);
- else
- ip_ct_refresh(conntrack, sysctl_ip_conntrack_udp_timeouts[UDP_STREAM_TIMEOUT]);
+ if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+ ip_ct_refresh(conntrack,
+ sysctl_ip_conntrack_udp_timeouts[UDP_STREAM_TIMEOUT]);
/* Also, more likely to be important, and not a probe */
set_bit(IPS_ASSURED_BIT, &conntrack->status);
- }
- else
- ip_ct_refresh(conntrack, sysctl_ip_conntrack_udp_timeouts[UDP_TIMEOUT]);
+ } else
+ ip_ct_refresh(conntrack,
+ sysctl_ip_conntrack_udp_timeouts[UDP_TIMEOUT]);
return NF_ACCEPT;
}
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_standalone.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_standalone.c
index c7e31931..78c3062c 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -32,503 +32,6 @@
struct module *ip_conntrack_module = THIS_MODULE;
MODULE_LICENSE("GPL");
-#define CLEAR_IP_CONNTRACK
-#define DEL_IP_CONNTRACK_ENTRY 1
-#ifdef DEL_IP_CONNTRACK_ENTRY
-/*
- *
- *This part of code add for delete an entry in ip_conntrack table.
- *
- */
-
-
-#define DEL_LIST_PATH "/tmp/.del_ip_conntrack"
-#define printkerrline() printk("del_ip_conntrack error : %s %s %d\n", __FILE__, __func__, __LINE__)
-
-struct del_list
-{
- unsigned short proto;
- unsigned int begin_port;
- unsigned int end_port;
- unsigned int ip;
- struct del_list *next;
-};
-
-void free_del_list(struct del_list *head);
-void print_del_list(struct del_list *head);
-static struct del_list * malloc_new_node(const char *buf, struct del_list * head);
-struct del_list * init_del_list(const char *buf, size_t size);
-static int read_del_file(char * buf, unsigned int size, char *path);
-static int del_match_method(const struct ip_conntrack_tuple_hash *pConn, const struct del_list * pList);
-static int del_conntrack_check(const struct ip_conntrack_tuple_hash *pConn, const struct del_list * head);
-void pf_del_ip_conntrack(void);
-static int proc_read_del_ip_conntrack(char *page, char **start, off_t off, int count, int *eof, void *context);
-static int proc_write_del_ip_conntrack(struct file *file, const char *buffer, unsigned long count, void *data);
-static int end_proc_read(const char *p, char *page, off_t off, int count, char **start, int *eof);
-
-void pf_del_ip_conntrack(void)
-{
-#define MAX_BUF_SIZE 1024*2
- int i;
- char buf[MAX_BUF_SIZE];
- struct del_list * del_head = NULL;
- struct list_head *head, *temp_head;
- struct ip_conntrack_tuple_hash *tuple_hash;
-
- //printk("pf_del_ip_conntrack---------------------------------------1\n");
- memset(buf, 0, MAX_BUF_SIZE);
-
- if(read_del_file(buf, MAX_BUF_SIZE, DEL_LIST_PATH) == -1)
- {
- goto final_return;
- }
-
- buf[MAX_BUF_SIZE - 1] = '\0';
- del_head = init_del_list(buf, MAX_BUF_SIZE - 1);
- //print_del_list(del_head);
- READ_LOCK(&ip_conntrack_lock);
- for (i = 0; i < ip_conntrack_htable_size; i++)
- {
- head = &ip_conntrack_hash[i];
- temp_head = head;
- while(1)
- {
- temp_head = temp_head->next;
- if(temp_head == head)
- {
- head = NULL;
- temp_head = NULL;
- break;
- }
- tuple_hash = (struct ip_conntrack_tuple_hash *)temp_head;
- if(del_conntrack_check(tuple_hash, del_head) == 1)
- {
- del_selected_conntrack(tuple_hash);
- }
- }
- }
- READ_UNLOCK(&ip_conntrack_lock);
- free_del_list(del_head);
-
-final_return:
-
- //printk("pf_del_ip_conntrack---------------------------------------2\n");
- return;
-#undef MAX_BUF_SIZE
-}
-
-static int del_conntrack_check(const struct ip_conntrack_tuple_hash *pConn, const struct del_list * head)
-{
- int ret;
- const struct del_list * p;
-
- ret = 0;
-
- if(pConn == NULL || head == NULL)
- {
- ret = -1;
- goto final_return;
- }
-
- for(p = head; p; p = p->next)
- {
- if(del_match_method(pConn, p) == 1)
- {
- //Match,jump out
- ret = 1;
- break;
- }
- }
-
-final_return:
- return ret;
-}
-
-static int del_match_method(const struct ip_conntrack_tuple_hash *pConn, const struct del_list * pList)
-{
- int ret;
- typedef enum
- {
- TCP_PROTO = 0x06,
- UDP_PROTO = 0x11,
- }proto_type;
- proto_type pt[2] = {TCP_PROTO, UDP_PROTO};
-
- ret = 0;
- //Check tcp and udp only
- if(pConn->tuple.dst.protonum == TCP_PROTO || pConn->tuple.dst.protonum == UDP_PROTO)
- {
- //Check proto match
- if((pList->proto == 3) ||
- ((pList->proto == 0 || pList->proto == 1) && (pConn->tuple.dst.protonum == pt[pList->proto])))
- {
- //Chcek ip address match
- if(pConn->ctrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == pList->ip)
- {
- //Check port match
- unsigned int tport;
- if(pConn->tuple.dst.protonum == TCP_PROTO)
- {
- //TCP
- tport = pConn->ctrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port;
- }
- else
- {
- //UDP
- tport = pConn->ctrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
- }
- tport = htons(tport);
- if(tport >= pList->begin_port && tport <= pList->end_port)
- {
- ret = 1;
- }
- }
- }
- }
- return ret;
-}
-
-static int read_del_file(char * buf, unsigned int size, char *path)
-{
- int retval, orgfsuid, orgfsgid;
- mm_segment_t orgfs;
- struct file *srcf;
-
- // Save uid and gid used for filesystem access.
- // Set user and group to 0 (root)
- orgfsuid = current->fsuid;
- orgfsgid = current->fsgid;
- current->fsuid=current->fsgid = 0;
- orgfs = get_fs();
- set_fs(KERNEL_DS);
-
- if(path && *path)
- {
- srcf = filp_open(path, O_RDONLY, 0);
- if(IS_ERR(srcf))
- {
- printkerrline();
- retval = -1;
- goto final_return;
- }
- else
- {
- if(srcf->f_op && srcf->f_op->read)
- {
- memset(buf, 0x00, size);
- retval=srcf->f_op->read(srcf, buf, size, &srcf->f_pos);
- if(retval < 0)
- {
- printkerrline();
- retval = -1;
- goto final_return;
- }
- else
- {
- //Success,go!
- retval = 0;
- goto final_return;
- }
- }
- else
- {
- printkerrline();
- retval = -1;
- goto final_return;
- }
- }
- }
- else
- {
- printkerrline();
- retval = -1;
- goto final_return;
- }
-
-final_return:
- if(!IS_ERR(srcf))
- {
- retval=filp_close(srcf,NULL);
- if(retval)
- {
- printkerrline();
- retval = -1;
- }
- }
- set_fs(orgfs);
- current->fsuid = orgfsuid;
- current->fsgid = orgfsgid;
-
- return retval;
-}
-
-struct del_list * init_del_list(const char *buf, size_t size)
-{
-#define LINE_FEED "\n"
-#define TMP_BUF_SIZE 100
- const char *begin, *end;
- char tmpbuf[TMP_BUF_SIZE];
- struct del_list * head = NULL, *tmp_p;
-
- if(buf == NULL || size <= 0 || buf[size] != '\0')
- {
- head = NULL;
- goto final_return;
- }
-
- for(begin = end = buf; begin && (begin - buf < size); begin = end + strlen(LINE_FEED))
- {
- end = strstr(begin, LINE_FEED);
- if(end)
- {
- if((end - begin) > (TMP_BUF_SIZE - 1))
- {
- //Too large,go on
- continue;
- }
- else
- {
- memcpy(tmpbuf, begin, end - begin);
- tmpbuf[end - begin] = '\0';
- //printk("obtain string : %s\n", tmpbuf);
- if((tmp_p = malloc_new_node(tmpbuf, head)) == NULL)
- {
- //Invalid format or malloc fail,go on
- continue;
- }
- else
- {
- head = tmp_p;
- }
- }
- }
- else
- {
- //printk("Last string : %s\n", begin);
- if((tmp_p = malloc_new_node(begin, head)) == NULL)
- {
- //Invalid format or malloc fail,jump out
- break;
- }
- else
- {
- head = tmp_p;
- }
- }
- }
-
-final_return:
- return head;
-
-#undef TMP_BUF_SIZE
-#undef LINE_FEED
-}
-
-static struct del_list * malloc_new_node(const char *buf, struct del_list * head)
-{
-#define SSCANF_MATCH_NUM 7
- int i, j, k, c1, c2, c3, c4;
- struct del_list *p = NULL;
-
- if(sscanf(buf, "%d %d.%d.%d.%d %d-%d", &i, &c4, &c3, &c2, &c1, &j, &k) != SSCANF_MATCH_NUM)
- {
- p = NULL;
- goto final_return;
- }
- else
- {
- if(p = (struct del_list *)kmalloc(sizeof(struct del_list), GFP_ATOMIC))
- {
- p->proto = i;
- #if 0
- //Big endian
- ((char *)&(p->ip))[0] = (char)c1;
- ((char *)&(p->ip))[1] = (char)c2;
- ((char *)&(p->ip))[2] = (char)c3;
- ((char *)&(p->ip))[3] = (char)c4;
- #else
- //Little endian
- ((char *)&(p->ip))[3] = (char)c1;
- ((char *)&(p->ip))[2] = (char)c2;
- ((char *)&(p->ip))[1] = (char)c3;
- ((char *)&(p->ip))[0] = (char)c4;
- #endif
- p->begin_port = j;
- p->end_port = k;
- p->next = head;
- }
- else
- {
- p = NULL;
- goto final_return;
- }
- }
-
-final_return:
- return p;
-#undef SSCANF_MATCH_NUM
-}
-
-void print_del_list(struct del_list *head)
-{
- int i;
- struct del_list *tmp_p;
-
- for(i = 1, tmp_p = head; tmp_p; tmp_p = tmp_p->next, i++)
- {
- printk("Node(%d): proto=%d | ip=%0x | port=[%d-%d]\n", i, tmp_p->proto, tmp_p->ip, tmp_p->begin_port, tmp_p->end_port);
- }
-}
-
-void free_del_list(struct del_list *head)
-{
- int i;
- struct del_list *tmp_p;
-
- if(head == NULL)
- {
- goto final_return;
- }
- for(i = 1, tmp_p = head; head; head = tmp_p, i++)
- {
- tmp_p = head->next;
- //printk("Free@Node(%d):proto=%d | ip=%0x | port=[%d-%d]\n", i, head->proto, head->ip, head->begin_port, head->end_port);
- kfree(head);
- }
-
-final_return:
- return;
-}
-
-static int proc_read_del_ip_conntrack(char *page, char **start, off_t off, int count, int *eof, void *context)
-{
- char *p;
-
- p = page;
- p += sprintf(page, "%s\n", "use echo \"1(0)\" to enable or disbable");
- return end_proc_read(p, page, off, count, start, eof);
-}
-
-static int proc_write_del_ip_conntrack(struct file *file, const char *buffer, unsigned long count, void *data)
-{
- unsigned char tmp[2];
-
- if(buffer)
- {
- memset(tmp, 0, sizeof(tmp));
- copy_from_user(tmp, buffer, count);
- tmp[1] = 0x00;
- switch(*tmp)
- {
- case '0':
- //Do something here
- break;
-
- case '1':
- pf_del_ip_conntrack();
- break;
-
- default:
- printk("<1>invalid args\n");
- }
- return count;
- }
- return 0;
-}
-
-static int end_proc_read(const char *p, char *page, off_t off, int count, char **start, int *eof)
-{
- int len = p - page;
-
- if(len < off + count)
- {
- *eof = 1;
- }
-
- *start = page + off;
- len -= off;
- if(len > count)
- {
- len = count;
- }
-
- if(len < 0)
- {
- len = 0;
- }
-
- return len;
-}
-
-#endif
-
-#ifdef CLEAR_IP_CONNTRACK
-void clear_ip_conntrack(void)
-{
- int i;
- struct list_head *head, *temp_head;
- struct ip_conntrack_tuple_hash *tuple_hash;
-
- printk("warning : %s %d\n", __func__, __LINE__);
-
- READ_LOCK(&ip_conntrack_lock);
- for (i = 0; i < ip_conntrack_htable_size; i++)
- {
- head = &ip_conntrack_hash[i];
- temp_head = head;
- while(1)
- {
- temp_head = temp_head->next;
- if(temp_head == head)
- {
- head = NULL;
- temp_head = NULL;
- break;
- }
- tuple_hash = (struct ip_conntrack_tuple_hash *)temp_head;
- del_selected_conntrack(tuple_hash);
- }
- }
- READ_UNLOCK(&ip_conntrack_lock);
-}
-
-static int proc_read_clear_ip_conntrack(char *page, char **start, off_t off, int count, int *eof, void *context)
-{
- char *p;
-
- p = page;
- p += sprintf(page, "%s\n", "use echo \"1(0)\" to enable or disbable");
- return end_proc_read(p, page, off, count, start, eof);
-}
-
-static int proc_write_clear_ip_conntrack(struct file *file, const char *buffer, unsigned long count, void *data)
-{
- unsigned char tmp[2];
-
- if(buffer)
- {
- memset(tmp, 0, sizeof(tmp));
- copy_from_user(tmp, buffer, count);
- tmp[1] = 0x00;
- switch(*tmp)
- {
- case '0':
- //Do something here
- break;
-
- case '1':
- clear_ip_conntrack();
- break;
-
- default:
- printk("<1>invalid args\n");
- }
- return count;
- }
- return 0;
-}
-#endif
-
static int kill_proto(const struct ip_conntrack *i, void *data)
{
return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
@@ -575,7 +78,7 @@ print_expect(char *buffer, const struct ip_conntrack_expect *expect)
}
static unsigned int
-print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
+print_conntrack(char *buffer, struct ip_conntrack *conntrack)
{
unsigned int len;
struct ip_conntrack_protocol *proto
@@ -593,15 +96,38 @@ print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
len += print_tuple(buffer + len,
&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
proto);
- if (!(conntrack->status & IPS_SEEN_REPLY))
+ if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
len += sprintf(buffer + len, "[UNREPLIED] ");
len += print_tuple(buffer + len,
&conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
proto);
- if (conntrack->status & IPS_ASSURED)
+ if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
len += sprintf(buffer + len, "[ASSURED] ");
len += sprintf(buffer + len, "use=%u ",
atomic_read(&conntrack->ct_general.use));
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+ len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
+#endif
+#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE)
+ if(conntrack->layer7.app_proto)
+ len += sprintf(buffer + len, "l7proto=%s ",
+ conntrack->layer7.app_proto);
+#endif
+#if defined(CONFIG_IP_NF_TARGET_MACSAVE) || defined(CONFIG_IP_NF_TARGET_MACSAVE_MODULE)
+ if ((*((u32 *)conntrack->macsave) != 0) || (*((u16*)(conntrack->macsave + 4)) != 0)) {
+ len += sprintf(buffer + len, "macsave=%02X:%02X:%02X:%02X:%02X:%02X ",
+ conntrack->macsave[0], conntrack->macsave[1], conntrack->macsave[2],
+ conntrack->macsave[3], conntrack->macsave[4], conntrack->macsave[5]);
+ }
+#endif
+#if defined(CONFIG_IP_NF_TARGET_BCOUNT) || defined(CONFIG_IP_NF_TARGET_BCOUNT_MODULE)
+#if 0
+ if (conntrack->bcount != 0) {
+// len += sprintf(buffer + len, "bcount=0x%lx ", conntrack->bcount);
+ len += sprintf(buffer + len, "bcount=%ldK ", conntrack->bcount / 1024);
+ }
+#endif
+#endif
len += sprintf(buffer + len, "\n");
return len;
@@ -748,30 +274,6 @@ static int init_or_cleanup(int init)
if (ret < 0)
goto cleanup_nothing;
-#ifdef DEL_IP_CONNTRACK_ENTRY
- proc = proc_net_create("del_ip_conntrack", S_IFREG | S_IRUGO | S_IWUSR, proc_read_del_ip_conntrack);
- if(proc)
- {
- proc->write_proc = proc_write_del_ip_conntrack;
- proc->owner = THIS_MODULE;
- }
- else
- {
- //Maybe we can just let it go!
- }
-#endif
-#ifdef CLEAR_IP_CONNTRACK
- proc = proc_net_create("clear_ip_conntrack", S_IFREG | S_IRUGO | S_IWUSR, proc_read_clear_ip_conntrack);
- if(proc)
- {
- proc->write_proc = proc_write_clear_ip_conntrack;
- proc->owner = THIS_MODULE;
- }
- else
- {
- //Maybe we can just let it go!
- }
-#endif
proc = proc_net_create("ip_conntrack",0,list_conntracks);
if (!proc) goto cleanup_init;
proc->owner = THIS_MODULE;
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_core.c b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_core.c
index f64ddabf..de6b4925 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_core.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_core.c
@@ -763,12 +763,11 @@ do_bindings(struct ip_conntrack *ct,
/* if this expectation is already established, skip */
if (exp->sibling)
{
- //lzh add 2007/3/16 for fix sip alg CDROUTE test
- exp = NULL;
- //lzh end
+#if 0 // removed 1.11 forward bug test
+ exp = NULL; // lzh add 2007/3/16 for fix sip alg CDROUTE test
+#endif
continue;
}
-
if (exp_for_packet(exp, pskb)) {
DEBUGP("calling nat helper (exp=%p) for packet\n",
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_h323.c b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_h323.c
index 2c080cf3..bcf886e8 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_h323.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_h323.c
@@ -129,7 +129,7 @@ h225_nat_expected(struct sk_buff **pskb,
mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
mr.range[0].min = mr.range[0].max
= ((union ip_conntrack_manip_proto)
- { port });
+ { .tcp = { port } });
}
ret = ip_nat_setup_info(ct, &mr, hooknum);
@@ -184,12 +184,14 @@ static int h323_signal_address_fixup(struct ip_conntrack *ct,
if (!between(info->seq[i] + 6, ntohl(tcph->seq),
ntohl(tcph->seq) + datalen)) {
/* Partial retransmisison. It's a cracker being funky. */
+#if 0 // ... or a miss id? zzz
if (net_ratelimit()) {
printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
info->seq[i],
ntohl(tcph->seq),
ntohl(tcph->seq) + datalen);
}
+#endif
return 0;
}
@@ -252,18 +254,18 @@ static int h323_data_fixup(struct ip_ct_h225_expect *info,
DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-
- memset(&newtuple, 0, sizeof(newtuple));
if (!between(expect->seq + 6, ntohl(tcph->seq),
ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
/* Partial retransmisison. It's a cracker being funky. */
+#if 1 // also caused by bad id?
if (net_ratelimit()) {
printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
expect->seq,
ntohl(tcph->seq),
ntohl(tcph->seq) + tcplen - tcph->doff * 4);
}
+#endif
return 0;
}
@@ -392,9 +394,9 @@ static struct ip_nat_helper h225 =
"H.225", /* name */
IP_NAT_HELPER_F_ALWAYS, /* flags */
THIS_MODULE, /* module */
- { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
+ { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
{ 0, { 0 }, IPPROTO_TCP } },
- { { 0, { 0xFFFF } }, /* mask */
+ { { 0, { .tcp = { 0xFFFF } } }, /* mask */
{ 0, { 0 }, 0xFFFF } },
h225_nat_help, /* helper */
h225_nat_expected /* expectfn */
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_helper.c b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_helper.c
index ffde5133..e7987430 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_helper.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_helper.c
@@ -79,7 +79,6 @@ ip_nat_resize_packet(struct sk_buff **skb,
iph = (*skb)->nh.iph;
if (iph->protocol == IPPROTO_TCP) {
struct tcphdr *tcph = (void *)iph + iph->ihl*4;
- void *data = (void *)tcph + tcph->doff*4;
DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
DUMP_OFFSET(this_way);
@@ -354,54 +353,49 @@ sack_adjust(struct tcphdr *tcph,
}
-/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted */
-static inline int
+/* TCP SACK sequence number adjustment. */
+static inline void
ip_nat_sack_adjust(struct sk_buff *skb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo)
{
- struct iphdr *iph;
struct tcphdr *tcph;
- unsigned char *ptr;
- int length, dir, sack_adjusted = 0;
+ unsigned char *ptr, *optend;
+ unsigned int dir;
- iph = skb->nh.iph;
- tcph = (void *)iph + iph->ihl*4;
- length = (tcph->doff*4)-sizeof(struct tcphdr);
+ tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
+ optend = (unsigned char *)tcph + tcph->doff*4;
ptr = (unsigned char *)(tcph+1);
dir = CTINFO2DIR(ctinfo);
- while (length > 0) {
- int opcode = *ptr++;
+ while (ptr < optend) {
+ int opcode = ptr[0];
int opsize;
switch (opcode) {
case TCPOPT_EOL:
- return !sack_adjusted;
+ return;
case TCPOPT_NOP:
- length--;
+ ptr++;
continue;
default:
- opsize = *ptr++;
- if (opsize > length) /* no partial opts */
- return !sack_adjusted;
+ opsize = ptr[1];
+ /* no partial opts */
+ if (ptr + opsize > optend || opsize < 2)
+ return;
if (opcode == TCPOPT_SACK) {
/* found SACK */
if((opsize >= (TCPOLEN_SACK_BASE
+TCPOLEN_SACK_PERBLOCK)) &&
!((opsize - TCPOLEN_SACK_BASE)
% TCPOLEN_SACK_PERBLOCK))
- sack_adjust(tcph, ptr-2,
+ sack_adjust(tcph, ptr,
&ct->nat.info.seq[!dir]);
-
- sack_adjusted = 1;
}
- ptr += opsize-2;
- length -= opsize;
+ ptr += opsize;
}
}
- return !sack_adjusted;
}
/* TCP sequence number adjustment */
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_pptp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_pptp.c
index 71077933..358a4579 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_pptp.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_pptp.c
@@ -1,5 +1,5 @@
/*
- * ip_nat_pptp.c - Version 1.11
+ * ip_nat_pptp.c - Version 1.5
*
* NAT support for PPTP (Point to Point Tunneling Protocol).
* PPTP is a a protocol for creating virtual private networks.
@@ -9,7 +9,7 @@
* GRE is defined in RFC 1701 and RFC 1702. Documentation of
* PPTP can be found in RFC 2637
*
- * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
@@ -17,7 +17,18 @@
* (needs netfilter newnat code)
* - NAT to a unique tuple, not to TCP source port
* (needs netfilter tuple reservation)
- * - Support other NAT scenarios than SNAT of PNS
+ *
+ * Changes:
+ * 2002-02-10 - Version 1.3
+ * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
+ * in local connections (Philip Craig <philipc@snapgear.com>)
+ * - add checks for magicCookie and pptp version
+ * - make argument list of pptp_{out,in}bound_packet() shorter
+ * - move to C99 style initializers
+ * - print version number at module loadtime
+ * 2003-09-22 - Version 1.5
+ * - use SNATed tcp sourceport as callid, since we get called before
+ * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
*
*/
@@ -34,6 +45,8 @@
#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+#define IP_NAT_PPTP_VERSION "1.5"
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
@@ -57,7 +70,7 @@ pptp_nat_expected(struct sk_buff **pskb,
struct ip_nat_multi_range mr;
struct ip_ct_pptp_master *ct_pptp_info;
struct ip_nat_pptp *nat_pptp_info;
- u_int32_t newsrcip, newdstip, newcid;
+ u_int32_t newip, newcid;
int ret;
IP_NF_ASSERT(info);
@@ -72,7 +85,7 @@ pptp_nat_expected(struct sk_buff **pskb,
/* need to alter GRE tuple because conntrack expectfn() used 'wrong'
* (unmanipulated) values */
- if (hooknum == NF_IP_PRE_ROUTING) {
+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
DEBUGP("completing tuples with NAT info \n");
/* we can do this, since we're unconfirmed */
if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
@@ -80,68 +93,43 @@ pptp_nat_expected(struct sk_buff **pskb,
/* assume PNS->PAC */
ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
htonl(nat_pptp_info->pns_call_id);
-// ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.gre.key =
-// htonl(nat_pptp_info->pac_call_id);
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
htonl(nat_pptp_info->pns_call_id);
+ newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
+ newcid = htonl(nat_pptp_info->pac_call_id);
} else {
/* assume PAC->PNS */
- DEBUGP("WRONG DIRECTION\n");
ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
htonl(nat_pptp_info->pac_call_id);
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
htonl(nat_pptp_info->pac_call_id);
- }
- }
-
- if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST)
- {
- if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == htonl(ct_pptp_info->pac_call_id))
- {
- /* assume PNS->PAC */
- newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
- newcid = htonl(nat_pptp_info->pac_call_id);
- }
- else
- {
- /* assume PAC->PNS */
- newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+ newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
newcid = htonl(nat_pptp_info->pns_call_id);
}
- mr.rangesize = 1;
- mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
- mr.range[0].min_ip = mr.range[0].max_ip = newdstip;
- mr.range[0].min = mr.range[0].max =
- ((union ip_conntrack_manip_proto ) { newcid });
- DEBUGP("change dest ip to %u.%u.%u.%u\n",
- NIPQUAD(newdstip));
- DEBUGP("change dest key to 0x%x\n", ntohl(newcid));
- ret = ip_nat_setup_info(ct, &mr, hooknum);
} else {
- if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == htonl(ct_pptp_info->pac_call_id))
- {
- newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
+ htonl(ct_pptp_info->pac_call_id)) {
+ /* assume PNS->PAC */
+ newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
newcid = htonl(ct_pptp_info->pns_call_id);
}
- else
- {
+ else {
/* assume PAC->PNS */
- newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+ newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
newcid = htonl(ct_pptp_info->pac_call_id);
}
-
- mr.rangesize = 1;
- mr.range[0].flags = IP_NAT_RANGE_MAP_IPS
- |IP_NAT_RANGE_PROTO_SPECIFIED;
- mr.range[0].min_ip = mr.range[0].max_ip = newsrcip;
- mr.range[0].min = mr.range[0].max =
- ((union ip_conntrack_manip_proto ) { newcid });
- DEBUGP("change src ip to %u.%u.%u.%u\n",
- NIPQUAD(newsrcip));
- DEBUGP("change 'src' key to 0x%x\n", ntohl(newcid));
- ret = ip_nat_setup_info(ct, &mr, hooknum);
}
+ mr.rangesize = 1;
+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
+ mr.range[0].min = mr.range[0].max =
+ ((union ip_conntrack_manip_proto ) { newcid });
+ DEBUGP("change ip to %u.%u.%u.%u\n",
+ NIPQUAD(newip));
+ DEBUGP("change key to 0x%x\n", ntohl(newcid));
+ ret = ip_nat_setup_info(ct, &mr, hooknum);
+
UNLOCK_BH(&ip_pptp_lock);
return ret;
@@ -150,13 +138,17 @@ pptp_nat_expected(struct sk_buff **pskb,
/* outbound packets == from PNS to PAC */
static inline unsigned int
-pptp_outbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
- size_t datalen,
+pptp_outbound_pkt(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
struct ip_conntrack_expect *exp)
{
+ struct iphdr *iph = (*pskb)->nh.iph;
+ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
+ struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
+ ((void *)tcph + tcph->doff*4);
+
struct PptpControlHeader *ctlh;
union pptp_ctrl_union pptpReq;
struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
@@ -164,6 +156,7 @@ pptp_outbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
u_int16_t msg, *cid = NULL, new_callid;
+ /* FIXME: size checks !!! */
ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
@@ -172,11 +165,18 @@ pptp_outbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
switch (msg = ntohs(ctlh->messageType)) {
case PPTP_OUT_CALL_REQUEST:
cid = &pptpReq.ocreq->callID;
+ /* FIXME: ideally we would want to reserve a call ID
+ * here. current netfilter NAT core is not able to do
+ * this :( For now we use TCP source port. This breaks
+ * multiple calls within one control session */
/* save original call ID in nat_info */
nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
- new_callid = tcph->source;
+ /* don't use tcph->source since we are at a DSTmanip
+ * hook (e.g. PREROUTING) and pkt is not mangled yet */
+ new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
+
/* save new call ID in ct info */
ct_pptp_info->pns_call_id = ntohs(new_callid);
break;
@@ -186,10 +186,6 @@ pptp_outbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
case PPTP_CALL_CLEAR_REQUEST:
cid = &pptpReq.clrreq->callID;
break;
- case PPTP_CALL_DISCONNECT_NOTIFY:
- cid = &pptpReq.disc->callID;
- break;
-
default:
DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
(msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
@@ -204,11 +200,6 @@ pptp_outbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
case PPTP_ECHO_REQUEST:
case PPTP_ECHO_REPLY:
/* no need to alter packet */
- DEBUGP("outbound control message %s\n", strMName[msg]);
- DEBUGP("ct->pac_call_id = %d\n", ct_pptp_info->pac_call_id);
- DEBUGP("ct->pns_call_id = %d\n", ct_pptp_info->pns_call_id);
- DEBUGP("nat->pac_call_id = %d\n", nat_pptp_info->pac_call_id);
- DEBUGP("nat->pns_call_id = %d\n", nat_pptp_info->pns_call_id);
return NF_ACCEPT;
}
@@ -216,27 +207,27 @@ pptp_outbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
DEBUGP("altering call id from 0x%04x to 0x%04x\n",
ntohs(*cid), ntohs(new_callid));
+
/* mangle packet */
- tcph->check = ip_nat_cheat_check(*cid^0xFFFF,
- new_callid, tcph->check);
- *cid = new_callid;
-
- DEBUGP("outbound control message %s\n", strMName[msg]);
- DEBUGP("ct->pac_call_id = %d\n", ct_pptp_info->pac_call_id);
- DEBUGP("ct->pns_call_id = %d\n", ct_pptp_info->pns_call_id);
- DEBUGP("nat->pac_call_id = %d\n", nat_pptp_info->pac_call_id);
- DEBUGP("nat->pns_call_id = %d\n", nat_pptp_info->pns_call_id);
+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
+ sizeof(new_callid), (char *)&new_callid,
+ sizeof(new_callid));
+
return NF_ACCEPT;
}
/* inbound packets == from PAC to PNS */
static inline unsigned int
-pptp_inbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
- size_t datalen,
+pptp_inbound_pkt(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
struct ip_conntrack_expect *oldexp)
{
+ struct iphdr *iph = (*pskb)->nh.iph;
+ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
+ struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
+ ((void *)tcph + tcph->doff*4);
+
struct PptpControlHeader *ctlh;
union pptp_ctrl_union pptpReq;
struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
@@ -245,8 +236,10 @@ pptp_inbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
u_int32_t old_dst_ip;
- struct ip_conntrack_tuple t;
+ struct ip_conntrack_tuple t, inv_t;
+ struct ip_conntrack_tuple *orig_t, *reply_t;
+ /* FIXME: size checks !!! */
ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
@@ -262,23 +255,30 @@ pptp_inbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
}
old_dst_ip = oldexp->tuple.dst.ip;
t = oldexp->tuple;
+ invert_tuplepr(&inv_t, &t);
/* save original PAC call ID in nat_info */
nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
- /* store new callID in ct_info, so conntrack works */
- //ct_pptp_info->pac_call_id = ntohs(tcph->source);
- //new_cid = htons(ct_pptp_info->pac_call_id);
-
/* alter expectation */
- if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
+ orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+ if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
/* expectation for PNS->PAC direction */
- t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
+ t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
+ inv_t.src.ip = reply_t->src.ip;
+ inv_t.dst.ip = reply_t->dst.ip;
+ inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
+ inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
} else {
/* expectation for PAC->PNS direction */
- t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
- DEBUGP("EXPECTATION IN WRONG DIRECTION!!!\n");
+ t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
+ t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
+ inv_t.src.ip = orig_t->src.ip;
+ inv_t.dst.ip = orig_t->dst.ip;
+ inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
+ inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
}
if (!ip_conntrack_change_expect(oldexp, &t)) {
@@ -287,13 +287,7 @@ pptp_inbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
DEBUGP("can't change expect\n");
}
ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
- /* reply keymap */
- t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
- t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
- t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
- t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
- ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &t);
-
+ ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
break;
case PPTP_IN_CALL_CONNECT:
pcid = &pptpReq.iccon->peersCallID;
@@ -323,9 +317,10 @@ pptp_inbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
case PPTP_WAN_ERROR_NOTIFY:
pcid = &pptpReq.wanerr->peersCallID;
break;
- case PPTP_SET_LINK_INFO:
- pcid = &pptpReq.setlink->peersCallID;
+ case PPTP_CALL_DISCONNECT_NOTIFY:
+ pcid = &pptpReq.disc->callID;
break;
+
default:
DEBUGP("unknown inbound packet %s\n",
(msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
@@ -334,14 +329,10 @@ pptp_inbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
case PPTP_START_SESSION_REQUEST:
case PPTP_START_SESSION_REPLY:
case PPTP_STOP_SESSION_REQUEST:
+ case PPTP_STOP_SESSION_REPLY:
case PPTP_ECHO_REQUEST:
case PPTP_ECHO_REPLY:
/* no need to alter packet */
- DEBUGP("inbound control message %s\n", strMName[msg]);
- DEBUGP("ct->pac_call_id = %d\n", ct_pptp_info->pac_call_id);
- DEBUGP("ct->pns_call_id = %d\n", ct_pptp_info->pns_call_id);
- DEBUGP("nat->pac_call_id = %d\n", nat_pptp_info->pac_call_id);
- DEBUGP("nat->pns_call_id = %d\n", nat_pptp_info->pns_call_id);
return NF_ACCEPT;
}
@@ -349,25 +340,21 @@ pptp_inbound_pkt(struct tcphdr *tcph, struct pptp_pkt_hdr *pptph,
IP_NF_ASSERT(pcid);
DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
ntohs(*pcid), ntohs(new_pcid));
- tcph->check = ip_nat_cheat_check(*pcid^0xFFFF,
- new_pcid, tcph->check);
- *pcid = new_pcid;
+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
+ sizeof(new_pcid), (char *)&new_pcid,
+ sizeof(new_pcid));
if (new_cid) {
IP_NF_ASSERT(cid);
DEBUGP("altering call id from 0x%04x to 0x%04x\n",
ntohs(*cid), ntohs(new_cid));
- tcph->check = ip_nat_cheat_check(*cid^0xFFFF,
- new_cid, tcph->check);
- *cid = new_cid;
+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ (void *)cid - (void *)pptph,
+ sizeof(new_cid), (char *)&new_cid,
+ sizeof(new_cid));
}
/* great, at least we don't need to resize packets */
- DEBUGP("inbound control message %s\n", strMName[msg]);
- DEBUGP("ct->pac_call_id = %d\n", ct_pptp_info->pac_call_id);
- DEBUGP("ct->pns_call_id = %d\n", ct_pptp_info->pns_call_id);
- DEBUGP("nat->pac_call_id = %d\n", nat_pptp_info->pac_call_id);
- DEBUGP("nat->pns_call_id = %d\n", nat_pptp_info->pns_call_id);
return NF_ACCEPT;
}
@@ -387,12 +374,13 @@ static unsigned int tcp_help(struct ip_conntrack *ct,
DEBUGP("entering\n");
- /* Only mangle things once: original direction in POST_ROUTING
- and reply direction on PRE_ROUTING. */
+ /* Only mangle things once: DST for original direction
+ and SRC for reply direction. */
dir = CTINFO2DIR(ctinfo);
- if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC && dir == IP_CT_DIR_ORIGINAL)
- || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST && dir == IP_CT_DIR_REPLY)))
- {
+ if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+ && dir == IP_CT_DIR_ORIGINAL)
+ || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
+ && dir == IP_CT_DIR_REPLY))) {
DEBUGP("Not touching dir %s at hook %s\n",
dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
@@ -409,13 +397,11 @@ static unsigned int tcp_help(struct ip_conntrack *ct,
return NF_ACCEPT;
}
-
pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
/* if it's not a control message, we can't handle it */
if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
- ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE)
- {
+ ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
DEBUGP("not a pptp control packet\n");
return NF_ACCEPT;
}
@@ -424,10 +410,10 @@ static unsigned int tcp_help(struct ip_conntrack *ct,
if (dir == IP_CT_DIR_ORIGINAL) {
/* reuqests sent by client to server (PNS->PAC) */
- pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo, exp);
+ pptp_outbound_pkt(pskb, ct, ctinfo, exp);
} else {
/* response from the server to the client (PAC->PNS) */
- pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo, exp);
+ pptp_inbound_pkt(pskb, ct, ctinfo, exp);
}
UNLOCK_BH(&ip_pptp_lock);
@@ -437,29 +423,52 @@ static unsigned int tcp_help(struct ip_conntrack *ct,
/* nat helper struct for control connection */
static struct ip_nat_helper pptp_tcp_helper = {
- { NULL, NULL },
- "pptp", IP_NAT_HELPER_F_ALWAYS, THIS_MODULE,
- { { 0, { tcp: { port: __constant_htons(PPTP_CONTROL_PORT) } } },
- { 0, { 0 }, IPPROTO_TCP } },
- { { 0, { tcp: { port: 0xFFFF } } },
- { 0, { 0 }, 0xFFFF } },
- tcp_help, pptp_nat_expected };
+ .list = { NULL, NULL },
+ .name = "pptp",
+ .flags = IP_NAT_HELPER_F_ALWAYS,
+ .me = THIS_MODULE,
+ .tuple = { .src = { .ip = 0,
+ .u = { .tcp = { .port =
+ __constant_htons(PPTP_CONTROL_PORT) }
+ }
+ },
+ .dst = { .ip = 0,
+ .u = { .all = 0 },
+ .protonum = IPPROTO_TCP
+ }
+ },
+
+ .mask = { .src = { .ip = 0,
+ .u = { .tcp = { .port = 0xFFFF } }
+ },
+ .dst = { .ip = 0,
+ .u = { .all = 0 },
+ .protonum = 0xFFFF
+ }
+ },
+ .help = tcp_help,
+ .expect = pptp_nat_expected
+};
static int __init init(void)
{
- DEBUGP("init_module\n" );
-
- if (ip_nat_helper_register(&pptp_tcp_helper))
+ DEBUGP("%s: registering NAT helper\n", __FILE__);
+ if (ip_nat_helper_register(&pptp_tcp_helper)) {
+ printk(KERN_ERR "Unable to register NAT application helper "
+ "for pptp\n");
return -EIO;
+ }
- return 0;
+ printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
+ return 0;
}
static void __exit fini(void)
{
DEBUGP("cleanup_module\n" );
- ip_nat_helper_unregister(&pptp_tcp_helper);
+ ip_nat_helper_unregister(&pptp_tcp_helper);
+ printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
}
module_init(init);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_esp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_esp.c
index a985539e..a985539e 100755..100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_esp.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_esp.c
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_gre.c b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_gre.c
index 25aa1786..9be95857 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_gre.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -1,5 +1,5 @@
/*
- * ip_nat_proto_gre.c - Version 1.11
+ * ip_nat_proto_gre.c - Version 1.2
*
* NAT protocol helper module for GRE.
*
@@ -17,7 +17,7 @@
*
* Documentation about PPTP can be found in RFC 2637
*
- * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
@@ -35,7 +35,12 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
+ ": " format, ## args)
+#else
#define DEBUGP(x, args...)
+#endif
/* is key in given range between min and max */
static int
@@ -44,8 +49,15 @@ gre_in_range(const struct ip_conntrack_tuple *tuple,
const union ip_conntrack_manip_proto *min,
const union ip_conntrack_manip_proto *max)
{
- return ntohl(tuple->src.u.gre.key) >= ntohl(min->gre.key)
- && ntohl(tuple->src.u.gre.key) <= ntohl(max->gre.key);
+ u_int32_t key;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ key = tuple->src.u.gre.key;
+ else
+ key = tuple->dst.u.gre.key;
+
+ return ntohl(key) >= ntohl(min->gre.key)
+ && ntohl(key) <= ntohl(max->gre.key);
}
/* generate unique tuple ... */
@@ -122,6 +134,7 @@ gre_manip_pkt(struct iphdr *iph, size_t len,
break;
}
if (greh->csum) {
+ /* FIXME: Never tested this code... */
*(gre_csum(greh)) =
ip_nat_cheat_check(~*(gre_key(greh)),
manip->u.gre.key,
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_udp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_udp.c
index 05aefcd4..622aee05 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -40,9 +40,6 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
else
portptr = &tuple->dst.u.udp.port;
- if(ntohs(*portptr) == 500)
- return 0;//must not be "return 1"
-
/* If no range specified... */
if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
/* If it's dst rewrite, can't change port */
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_tables.c b/release/src/linux/linux/net/ipv4/netfilter/ip_tables.c
index 99438ca0..2e3004db 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ip_tables.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ip_tables.c
@@ -332,7 +332,7 @@ ipt_do_table(struct sk_buff **pskb,
continue;
}
if (table_base + v
- != (void *)e + e->next_offset) {
+ != (void *)e + e->next_offset && !(e->ip.flags & IPT_F_GOTO)) {
/* Save old back ptr in next entry */
struct ipt_entry *next
= (void *)e + e->next_offset;
@@ -374,6 +374,12 @@ ipt_do_table(struct sk_buff **pskb,
if (verdict == IPT_CONTINUE)
e = (void *)e + e->next_offset;
+ else if (verdict == IPT_RETURN) { // added -- zzz
+ e = back;
+ back = get_entry(table_base,
+ back->comefrom);
+ continue;
+ }
else
/* Verdict */
break;
@@ -1169,13 +1175,11 @@ do_add_counters(void *user, unsigned int len)
goto free;
write_lock_bh(&t->lock);
- /*************************************
- * modify by tanghui @ 2006-10-11
- * for a RACE CONDITION in the "do_add_counters()" function
- *************************************/
- //if (t->private->number != paddc->num_counters) {
- if (t->private->number != tmp.num_counters) {
- /*************************************/
+
+#if 0 // removed 1.11 forward bug test
+ // if (t->private->number != tmp.num_counters) { // 43011: modify by tanghui @ 2006-10-11 for a RACE CONDITION in the "do_add_counters()" function
+#endif
+ if (t->private->number != paddc->num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1676,7 +1680,7 @@ static struct ipt_match icmp_matchstruct
= { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL };
#ifdef CONFIG_PROC_FS
-static inline int print_name(const char *i,
+static int print_name(const char *i,
off_t start_offset, char *buffer, int length,
off_t *pos, unsigned int *count)
{
@@ -1694,6 +1698,15 @@ static inline int print_name(const char *i,
return 0;
}
+static inline int print_target(const struct ipt_target *t,
+ off_t start_offset, char *buffer, int length,
+ off_t *pos, unsigned int *count)
+{
+ if (t == &ipt_standard_target || t == &ipt_error_target)
+ return 0;
+ return print_name((char *)t, start_offset, buffer, length, pos, count);
+}
+
static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
{
off_t pos = 0;
@@ -1720,7 +1733,7 @@ static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
if (down_interruptible(&ipt_mutex) != 0)
return 0;
- LIST_FIND(&ipt_target, print_name, void *,
+ LIST_FIND(&ipt_target, print_target, struct ipt_target *,
offset, buffer, length, &pos, &count);
up(&ipt_mutex);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_BCOUNT.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_BCOUNT.c
new file mode 100644
index 00000000..b40e7e2e
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_BCOUNT.c
@@ -0,0 +1,63 @@
+/*
+
+ BCOUNT target
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_BCOUNT.h>
+
+// #define DEBUG_BCOUNT
+
+static unsigned int target(struct sk_buff **pskb, unsigned int hooknum,
+ const struct net_device *in, const struct net_device *out,
+ const void *targinfo, void *userinfo)
+{
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get(*pskb, &ctinfo);
+ if (ct) {
+ ct->bcount += (*pskb)->len;
+ if (ct->bcount >= 0x0FFFFFFF) ct->bcount = 0x0FFFFFFF;
+#ifdef DEBUG_BCOUNT
+ if (net_ratelimit())
+ printf(KERN_DEBUG "BCOUNT %lx %lx\n", (*pskb)->len, ct->bcount);
+#endif
+ }
+ return IPT_CONTINUE;
+}
+
+static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo,
+ unsigned int targinfosize, unsigned int hook_mask)
+{
+ return (targinfosize == IPT_ALIGN(sizeof(struct ipt_BCOUNT_target)));
+}
+
+static struct ipt_target BCOUNT_target
+= { { NULL, NULL }, "BCOUNT", target, checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_target(&BCOUNT_target);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&BCOUNT_target);
+}
+
+module_init(init);
+module_exit(fini);
+
+
+MODULE_AUTHOR("Jonathan Zarate");
+MODULE_DESCRIPTION("BCOUNT target");
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_CLASSIFY.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_CLASSIFY.c
new file mode 100644
index 00000000..f7320721
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_CLASSIFY.c
@@ -0,0 +1,82 @@
+/*
+ * This is a module which is used for setting the skb->priority field
+ * of an skb for qdisc classification.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("iptables qdisc classification target module");
+
+static unsigned int
+target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_classify_target_info *clinfo = targinfo;
+
+ if((*pskb)->priority != clinfo->priority) {
+ (*pskb)->priority = clinfo->priority;
+ (*pskb)->nfcache |= NFC_ALTERED;
+ }
+
+ return IPT_CONTINUE;
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){
+ printk(KERN_ERR "CLASSIFY: invalid size (%u != %u).\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_classify_target_info)));
+ return 0;
+ }
+
+ if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
+ printk(KERN_ERR "CLASSIFY: only valid in POST_ROUTING.\n");
+ return 0;
+ }
+
+ if (strcmp(tablename, "mangle") != 0) {
+ printk(KERN_WARNING "CLASSIFY: can only be called from "
+ "\"mangle\" table, not \"%s\".\n",
+ tablename);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_classify_reg
+= { { NULL, NULL }, "CLASSIFY", target, checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ if (ipt_register_target(&ipt_classify_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_classify_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_CONNMARK.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_CONNMARK.c
new file mode 100644
index 00000000..a6038378
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_CONNMARK.c
@@ -0,0 +1,128 @@
+/* This kernel module is used to modify the connection mark values, or
+ * to optionally restore the skb nfmark from the connection mark
+ *
+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
+MODULE_DESCRIPTION("IP tables CONNMARK matching module");
+MODULE_LICENSE("GPL");
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+
+static unsigned int
+target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_connmark_target_info *markinfo = targinfo;
+ unsigned long diff;
+ unsigned long nfmark;
+ unsigned long newmark;
+
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
+ if (ct) {
+ switch(markinfo->mode) {
+ case IPT_CONNMARK_SET:
+ newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
+ if (newmark != ct->mark)
+ ct->mark = newmark;
+ break;
+ case IPT_CONNMARK_SET_RETURN:
+ // Set connmark and nfmark, apply mask to nfmark, do IPT_RETURN - zzz
+ newmark = ct->mark = markinfo->mark;
+ newmark &= markinfo->mask;
+ nfmark = (*pskb)->nfmark;
+ if (newmark != nfmark) {
+ (*pskb)->nfmark = newmark;
+ (*pskb)->nfcache |= NFC_ALTERED;
+ }
+ return IPT_RETURN;
+ case IPT_CONNMARK_SAVE:
+ newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
+ if (ct->mark != newmark)
+ ct->mark = newmark;
+ break;
+ case IPT_CONNMARK_RESTORE:
+ nfmark = (*pskb)->nfmark;
+ diff = (ct->mark ^ nfmark) & markinfo->mask; // zzz
+ if (diff != 0) {
+ (*pskb)->nfmark = nfmark ^ diff;
+ (*pskb)->nfcache |= NFC_ALTERED;
+ }
+ break;
+ }
+ }
+
+ return IPT_CONTINUE;
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ struct ipt_connmark_target_info *matchinfo = targinfo;
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
+ printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
+ return 0;
+ }
+
+ if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
+ if (strcmp(tablename, "mangle") != 0) {
+ printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_connmark_reg = {
+ .name = "CONNMARK",
+ .target = &target,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_target(&ipt_connmark_reg);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_connmark_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_IMQ.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_IMQ.c
new file mode 100644
index 00000000..2ba068b3
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_IMQ.c
@@ -0,0 +1,78 @@
+/* This target marks packets to be enqueued to an imq device */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_IMQ.h>
+#include <linux/imq.h>
+
+static unsigned int imq_target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
+
+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
+ (*pskb)->nfcache |= NFC_ALTERED;
+
+ return IPT_CONTINUE;
+}
+
+static int imq_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ struct ipt_imq_info *mr;
+
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
+ return 0;
+ }
+ mr = (struct ipt_imq_info*)targinfo;
+
+ if (strcmp(tablename, "mangle") != 0) {
+ printk(KERN_WARNING
+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
+ tablename);
+ return 0;
+ }
+
+ if (mr->todev > IMQ_MAX_DEVS) {
+ printk(KERN_WARNING
+ "IMQ: invalid device specified, highest is %u\n",
+ IMQ_MAX_DEVS);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_imq_reg = {
+ { NULL, NULL},
+ "IMQ",
+ imq_target,
+ imq_checkentry,
+ NULL,
+ THIS_MODULE
+};
+
+static int __init init(void)
+{
+ if (ipt_register_target(&ipt_imq_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_imq_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_MACSAVE.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_MACSAVE.c
new file mode 100644
index 00000000..62677279
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_MACSAVE.c
@@ -0,0 +1,65 @@
+/*
+
+ MACSAVE target
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_MACSAVE.h>
+
+static unsigned int target(struct sk_buff **pskb, unsigned int hooknum,
+ const struct net_device *in, const struct net_device *out,
+ const void *targinfo, void *userinfo)
+{
+// const struct ipt_MACSAVE_target_info *info = targinfo;
+ struct sk_buff *skb = *pskb;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ if ((skb->mac.raw >= skb->head) && ((skb->mac.raw + ETH_HLEN) <= skb->data)) {
+ ct = ip_conntrack_get(skb, &ctinfo);
+ if (ct) {
+ memcpy(ct->macsave, skb->mac.ethernet->h_source, sizeof(ct->macsave));
+ }
+ }
+ return IPT_CONTINUE;
+}
+
+static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo,
+ unsigned int targinfosize, unsigned int hook_mask)
+{
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_MACSAVE_target_info))) {
+ printk(KERN_ERR "MACSAVE: Invalid data size\n");
+ return 0;
+ }
+
+ if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_IN))) {
+ printk(KERN_ERR "MACSAVE: Valid only in PREROUTING, FORWARD and INPUT\n");
+ return 0;
+ }
+ return 1;
+}
+
+static struct ipt_target macsave_target
+= { { NULL, NULL }, "MACSAVE", target, checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_target(&macsave_target);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&macsave_target);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c
new file mode 100644
index 00000000..b97d7792
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c
@@ -0,0 +1,422 @@
+/*
+ * This implements the ROUTE target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * v 1.11 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_ROUTE.h>
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/icmp.h>
+#include <net/checksum.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+
+/* Try to route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: -1 if an error occured
+ * 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int route(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ipt_route_target_info *route_info)
+{
+ int err;
+ struct rtable *rt;
+ struct iphdr *iph = skb->nh.iph;
+ struct rt_key key = {
+ dst:iph->daddr,
+ src:0,
+ oif:ifindex,
+ tos:RT_TOS(iph->tos)
+ };
+
+ /* The destination address may be overloaded by the target */
+ if (route_info->gw)
+ key.dst = route_info->gw;
+
+ /* Trying to route the packet using the standard routing table. */
+ if ((err = ip_route_output_key(&rt, &key))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
+ return -1;
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ /* Success if no oif specified or if the oif correspond to the
+ * one desired */
+ if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
+ skb->dst = &rt->u.dst;
+ skb->dev = skb->dst->dev;
+ return 1;
+ }
+
+ /* The interface selected by the routing table is not the one
+ * specified by the user. This may happen because the dst address
+ * is one of our own addresses.
+ */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
+ NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
+
+ return 0;
+}
+
+
+/* Stolen from ip_finish_output2
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+/* PRE : skb->dev is set to the device we are leaving by
+ * POST: - the packet is directly sent to the skb->dev device, without
+ * pushing the link layer header.
+ * - the packet is destroyed
+ */
+static inline int dev_direct_send(struct sk_buff *skb)
+{
+ return dev_queue_xmit(skb);
+}
+
+
+static unsigned int route_oif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ switch (route(skb, ifindex, route_info)) {
+ case 1:
+ dev_put(dev_out);
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+
+ case 0:
+ /* Failed to send to oif. Trying the hard way */
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return NF_DROP;
+
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: forcing the use of %i\n",
+ ifindex);
+
+ /* We have to force the use of an interface.
+ * This interface must be a tunnel interface since
+ * otherwise we can't guess the hw address for
+ * the packet. For a tunnel interface, no hw address
+ * is needed.
+ */
+ if ((dev_out->type != ARPHRD_TUNNEL)
+ && (dev_out->type != ARPHRD_IPGRE)) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+
+ /* Send the packet. This will also free skb
+ * Do not go through the POST_ROUTING hook because
+ * skb->dst is not set and because it will probably
+ * get confused by the destination IP address.
+ */
+ skb->dev = dev_out;
+ dev_direct_send(skb);
+ dev_put(dev_out);
+ return NF_STOLEN;
+
+ default:
+ /* Unexpected error */
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+}
+
+
+static unsigned int route_iif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ struct net_device *dev_in = NULL;
+
+ /* Getting the current interface index. */
+ if (!(dev_in = dev_get_by_name(route_info->iif))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
+ return NF_DROP;
+ }
+
+ skb->dev = dev_in;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ netif_rx(skb);
+ dev_put(dev_in);
+ return NF_STOLEN;
+}
+
+
+static unsigned int route_gw(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route(skb, 0, route_info)!=1)
+ return NF_DROP;
+
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+}
+
+/* To detect and deter routed packet loopback when using the --tee option,
+ * we take a page out of the raw.patch book: on the copied skb, we set up
+ * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
+ * routing packets when we see they already have that ->nfct.
+ */
+
+static struct ip_conntrack route_tee_track;
+
+static unsigned int ipt_route_target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ unsigned int res;
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP_PRE_ROUTING ||
+ hooknum == NF_IP_LOCAL_IN) {
+
+ struct iphdr *iph = skb->nh.iph;
+
+ if (iph->ttl <= 1) {
+ struct rtable *rt;
+
+ if (ip_route_output(&rt, iph->saddr, iph->daddr,
+ RT_TOS(iph->tos) | RTO_CONN,
+ 0)) {
+ return NF_DROP;
+ }
+
+ if (skb->dev == rt->u.dst.dev) {
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+
+ /* this will traverse normal stack, and
+ * thus call conntrack on the icmp packet */
+ icmp_send(skb, ICMP_TIME_EXCEEDED,
+ ICMP_EXC_TTL, 0);
+ }
+
+ return NF_DROP;
+ }
+
+ /*
+ * If we are at INPUT the checksum must be recalculated since
+ * the length could change as the result of a defragmentation.
+ * -- Rickard Molin
+ */
+ if(hooknum == NF_IP_LOCAL_IN) {
+ iph->ttl = iph->ttl - 1;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ } else {
+ ip_decrease_ttl(iph);
+ }
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IPT_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
+ return IPT_CONTINUE;
+ }
+ }
+
+ /* Tell conntrack to forget this packet since it may get confused
+ * when a packet is leaving with dst address == our address.
+ * Good idea ? Dunno. Need advice.
+ *
+ * NEW: mark the skb with our &route_tee_track, so we avoid looping
+ * on any already routed packet.
+ */
+ if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = &route_tee_track.infos[IP_CT_NEW];
+ nf_conntrack_get(skb->nfct);
+ skb->nfcache = 0;
+#ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+#endif
+ }
+
+ if (route_info->oif[0]) {
+ res = route_oif(route_info, skb);
+ } else if (route_info->iif[0]) {
+ res = route_iif(route_info, skb);
+ } else if (route_info->gw) {
+ res = route_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
+ res = IPT_CONTINUE;
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE))
+ res = IPT_CONTINUE;
+
+ return res;
+}
+
+
+static int ipt_route_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
+ tablename);
+ return 0;
+ }
+
+ if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
+ | (1 << NF_IP_LOCAL_IN)
+ | (1 << NF_IP_FORWARD)
+ | (1 << NF_IP_LOCAL_OUT)
+ | (1 << NF_IP_POST_ROUTING))) {
+ printk("ipt_ROUTE: bad hook\n");
+ return 0;
+ }
+
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
+ printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_route_target_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static struct ipt_target ipt_route_reg
+= { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
+ THIS_MODULE };
+
+
+static int __init init(void)
+{
+ /* Set up fake conntrack (stolen from raw.patch):
+ - to never be deleted, not in any hashes */
+ atomic_set(&route_tee_track.ct_general.use, 1);
+ /* - and look it like as a confirmed connection */
+ set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
+ /* - and prepare the ctinfo field for REJECT/NAT. */
+ route_tee_track.infos[IP_CT_NEW].master =
+ route_tee_track.infos[IP_CT_RELATED].master =
+ route_tee_track.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master =
+ &route_tee_track.ct_general;
+ /* Initialize fake conntrack so that NAT will skip it */
+ route_tee_track.nat.info.initialized |=
+ (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
+
+ if (ipt_register_target(&ipt_route_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_TRIGGER.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_TRIGGER.c
index 99e7dfe7..07103fa5 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ipt_TRIGGER.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_TRIGGER.c
@@ -62,7 +62,8 @@ LIST_HEAD(trigger_list);
static void trigger_refresh(struct ipt_trigger *trig, unsigned long extra_jiffies)
{
- DEBUGP("%s: \n", __FUNCTION__);
+ DEBUGP("%s: mport=%u-%u\n", __FUNCTION__, trig->ports.mport[0], trig->ports.mport[1]);
+
IP_NF_ASSERT(trig);
WRITE_LOCK(&ip_conntrack_lock);
@@ -77,7 +78,8 @@ static void trigger_refresh(struct ipt_trigger *trig, unsigned long extra_jiffie
static void __del_trigger(struct ipt_trigger *trig)
{
- DEBUGP("%s: \n", __FUNCTION__);
+ DEBUGP("%s: mport=%u-%u\n", __FUNCTION__, trig->ports.mport[0], trig->ports.mport[1]);
+
IP_NF_ASSERT(trig);
MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
@@ -90,7 +92,9 @@ static void trigger_timeout(unsigned long ul_trig)
{
struct ipt_trigger *trig= (void *) ul_trig;
- DEBUGP("trigger list %p timed out\n", trig);
+// DEBUGP("trigger list %p timed out\n", trig);
+ DEBUGP("%s: mport=%u-%u\n", __FUNCTION__, trig->ports.mport[0], trig->ports.mport[1]);
+
WRITE_LOCK(&ip_conntrack_lock);
__del_trigger(trig);
WRITE_UNLOCK(&ip_conntrack_lock);
@@ -250,7 +254,7 @@ trigger_dnat(struct sk_buff **pskb,
IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW));
DEBUGP("%s: got ", __FUNCTION__);
- DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ DUMP_TUPLE_RAW(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
/* Alter the destination of imcoming packet. */
newrange = ((struct ip_nat_multi_range)
@@ -310,7 +314,7 @@ trigger_check(const char *tablename,
DEBUGP("trigger_check: size %u.\n", targinfosize);
return 0;
}
- if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD))) {
+ if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
DEBUGP("trigger_check: bad hooks %x.\n", hook_mask);
return 0;
}
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_TTL.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_TTL.c
new file mode 100644
index 00000000..2f0a4e7a
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_TTL.c
@@ -0,0 +1,110 @@
+/* TTL modification target for IP tables
+ * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Version: 1.8
+ *
+ * This software is distributed under the terms of GNU GPL
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_TTL.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("IP tables TTL modification module");
+MODULE_LICENSE("GPL");
+
+static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
+ const struct net_device *in, const struct net_device *out,
+ const void *targinfo, void *userinfo)
+{
+ struct iphdr *iph = (*pskb)->nh.iph;
+ const struct ipt_TTL_info *info = targinfo;
+ u_int16_t diffs[2];
+ int new_ttl;
+
+ switch (info->mode) {
+ case IPT_TTL_SET:
+ new_ttl = info->ttl;
+ break;
+ case IPT_TTL_INC:
+ new_ttl = iph->ttl + info->ttl;
+ if (new_ttl > 255)
+ new_ttl = 255;
+ break;
+ case IPT_TTL_DEC:
+ new_ttl = iph->ttl - info->ttl;
+ if (new_ttl < 0)
+ new_ttl = 0;
+ break;
+ default:
+ new_ttl = iph->ttl;
+ break;
+ }
+
+ if (new_ttl != iph->ttl) {
+ diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
+ iph->ttl = new_ttl;
+ diffs[1] = htons(((unsigned)iph->ttl) << 8);
+ iph->check = csum_fold(csum_partial((char *)diffs,
+ sizeof(diffs),
+ iph->check^0xFFFF));
+ (*pskb)->nfcache |= NFC_ALTERED;
+ }
+
+ return IPT_CONTINUE;
+}
+
+static int ipt_ttl_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ struct ipt_TTL_info *info = targinfo;
+
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
+ printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_TTL_info)));
+ return 0;
+ }
+
+ if (strcmp(tablename, "mangle")) {
+ printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
+ return 0;
+ }
+
+ if (info->mode > IPT_TTL_MAXMODE) {
+ printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
+ info->mode);
+ return 0;
+ }
+
+ if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
+ printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
+ ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_target(&ipt_TTL);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_TTL);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_account.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_account.c
new file mode 100644
index 00000000..7fd34562
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_account.c
@@ -0,0 +1,942 @@
+/*
+ * accounting match (ipt_account.c)
+ * (C) 2003,2004 by Piotr Gasidlo (quaker@barbara.eu.org)
+ *
+ * Version: 0.1.7
+ *
+ * This software is distributed under the terms of GNU GPL
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+
+#include <linux/seq_file.h>
+
+#include <asm/uaccess.h>
+
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_account.h>
+
+#if defined(CONFIG_IP_NF_MATCH_ACCOUNT_DEBUG)
+ #define dprintk(format,args...) printk(format,##args)
+#else
+ #define dprintk(format,args...)
+#endif
+
+static char version[] =
+KERN_INFO IPT_ACCOUNT_NAME " " IPT_ACCOUNT_VERSION " : Piotr Gasid³o <quaker@barbara.eu.org>, http://www.barbara.eu.org/~quaker/ipt_account/\n";
+
+/* rights for files created in /proc/net/ipt_account/ */
+static int permissions = 0644;
+/* maximal netmask for single table */
+static int netmask = 16;
+
+/* module information */
+MODULE_AUTHOR("Piotr Gasidlo <quaker@barbara.eu.org>");
+MODULE_DESCRIPTION("Traffic accounting modules");
+MODULE_LICENSE("GPL");
+MODULE_PARM(permissions,"i");
+MODULE_PARM_DESC(permissions,"permissions on /proc/net/ipt_account/* files");
+MODULE_PARM(netmask, "i");
+MODULE_PARM_DESC(netmask, "maximum *save* size of one list (netmask)");
+
+/* structure with statistics counters */
+struct t_ipt_account_stat {
+ u_int64_t b_all, b_tcp, b_udp, b_icmp, b_other; /* byte counters for all/tcp/udp/icmp/other traffic */
+ u_int64_t p_all, p_tcp, p_udp, p_icmp, p_other; /* packet counters for all/tcp/udp/icmp/other traffic */
+};
+
+/* stucture with statistics counters, used when table is created with --ashort switch */
+struct t_ipt_account_stat_short {
+ u_int64_t b_all; /* byte counters for all traffic */
+ u_int64_t p_all; /* packet counters for all traffic */
+};
+
+/* structure holding to/from statistics for single ip */
+struct t_ipt_account_ip_list {
+ struct t_ipt_account_stat src;
+ struct t_ipt_account_stat dest;
+ unsigned long time; /* time when this record was last updated */
+
+};
+
+/* same as above, for tables with --ashort switch */
+struct t_ipt_account_ip_list_short {
+ struct t_ipt_account_stat_short src;
+ struct t_ipt_account_stat_short dest;
+ unsigned long time;
+};
+
+/* structure describing single table */
+struct t_ipt_account_table {
+ char name[IPT_ACCOUNT_NAME_LEN]; /* table name ( = filename in /proc/net/ipt_account/) */
+ union { /* table with statistics for each ip in network/netmask */
+ struct t_ipt_account_ip_list *l;
+ struct t_ipt_account_ip_list_short *s;
+ } ip_list;
+ u_int32_t network; /* network/netmask covered by table*/
+ u_int32_t netmask;
+ u_int32_t count;
+ int shortlisting:1; /* show only total columns of counters */
+ int use_count; /* rules counter - counting number of rules using this table */
+ struct t_ipt_account_table *next;
+ spinlock_t ip_list_lock;
+ struct proc_dir_entry *status_file;
+};
+
+/* we must use spinlocks to avoid parallel modifications of table list */
+static spinlock_t account_lock = SPIN_LOCK_UNLOCKED;
+
+static struct proc_dir_entry *proc_net_ipt_account = NULL;
+
+/* root pointer holding list of the tables */
+static struct t_ipt_account_table *account_tables = NULL;
+
+/* convert ascii to ip */
+int atoip(char *buffer, u_int32_t *ip) {
+
+ char *bufferptr = buffer;
+ int part, shift;
+
+ /* zero ip */
+ *ip = 0;
+
+ /* first must be a digit */
+ if (!isdigit(*bufferptr))
+ return 0;
+
+ /* parse first 3 octets (III.III.III.iii) */
+ for (part = 0, shift = 24; *bufferptr && shift; bufferptr++) {
+ if (isdigit(*bufferptr)) {
+ part = part * 10 + (*bufferptr - '0');
+ continue;
+ }
+ if (*bufferptr == '.') {
+ if (part > 255)
+ return 0;
+ *ip |= part << shift;
+ shift -= 8;
+ part = 0;
+ continue;
+ }
+ return 0;
+ }
+
+ /* we expect more digts */
+ if (!*bufferptr)
+ return 0;
+ /* parse last octet (iii.iii.iii.III) */
+ for (; *bufferptr; bufferptr++) {
+ if (isdigit(*bufferptr)) {
+ part = part * 10 + (*bufferptr - '0');
+ continue;
+ } else {
+ if (part > 255)
+ return 0;
+ *ip |= part;
+ break;
+ }
+ }
+ return (bufferptr - buffer);
+}
+
+/* convert ascii to 64bit integer */
+int atoi64(char *buffer, u_int64_t *i) {
+ char *bufferptr = buffer;
+
+ /* zero integer */
+ *i = 0;
+
+ while (isdigit(*bufferptr)) {
+ *i = *i * 10 + (*bufferptr - '0');
+ bufferptr++;
+ }
+ return (bufferptr - buffer);
+}
+
+static void *account_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct proc_dir_entry *pde = s->private;
+ struct t_ipt_account_table *table = pde->data;
+
+ unsigned int *bucket;
+
+ spin_lock_bh(&table->ip_list_lock);
+ if (*pos >= table->count)
+ return NULL;
+
+ bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
+ if (!bucket)
+ return ERR_PTR(-ENOMEM);
+ *bucket = *pos;
+ return bucket;
+}
+
+static void *account_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct proc_dir_entry *pde = s->private;
+ struct t_ipt_account_table *table = pde->data;
+
+ unsigned int *bucket = (unsigned int *)v;
+
+ *pos = ++(*bucket);
+ if (*pos >= table->count) {
+ kfree(v);
+ return NULL;
+ }
+ return bucket;
+}
+
+static void account_seq_stop(struct seq_file *s, void *v)
+{
+ struct proc_dir_entry *pde = s->private;
+ struct t_ipt_account_table *table = pde->data;
+ unsigned int *bucket = (unsigned int *)v;
+ kfree(bucket);
+ spin_unlock_bh(&table->ip_list_lock);
+}
+
+static int account_seq_write(struct file *file, const char *ubuffer,
+ size_t ulength, loff_t *pos)
+{
+ struct proc_dir_entry *pde = ((struct seq_file *)file->private_data)->private;
+ struct t_ipt_account_table *table = pde->data;
+ char buffer[1024], *bufferptr;
+ int length;
+
+ u_int32_t ip;
+ int len, i;
+ struct t_ipt_account_ip_list l;
+ struct t_ipt_account_ip_list_short s;
+ u_int64_t *p, dummy;
+
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() entered.\n");
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() ulength = %zi.\n", ulength);
+
+ length = ulength;
+ if (ulength > 1024)
+ length = 1024;
+ if (copy_from_user(buffer, ubuffer, length))
+ return -EFAULT;
+ buffer[length - 1] = 0;
+ bufferptr = buffer;
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() buffer = \'%s\' length = %i.\n", buffer, length);
+
+ /* reset table counters */
+ if (!memcmp(buffer, "reset", 5)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got \"reset\".\n");
+ if (!table->shortlisting) {
+ spin_lock_bh(&table->ip_list_lock);
+ memset(table->ip_list.l, 0, sizeof(struct t_ipt_account_ip_list) * table->count);
+ spin_unlock_bh(&table->ip_list_lock);
+ } else {
+ spin_lock_bh(&table->ip_list_lock);
+ memset(table->ip_list.s, 0, sizeof(struct t_ipt_account_ip_list_short) * table->count);
+ spin_unlock_bh(&table->ip_list_lock);
+ }
+ return length;
+ }
+
+ if (!memcmp(buffer, "ip", 2)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got \"ip\".\n");
+ bufferptr += 2;
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (*bufferptr != '=') {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
+ return length; /* expected equal */
+ }
+ bufferptr += 1;
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (!(len = atoip(bufferptr, &ip))) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected ip (%ti).\n", bufferptr - buffer);
+ return length; /* expected ip */
+ }
+ bufferptr += len;
+ if ((ip & table->netmask) != table->network) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected ip [%u.%u.%u.%u] from table's network/netmask [%u.%u.%u.%u/%u.%u.%u.%u].\n", HIPQUAD(ip), HIPQUAD(table->network), HIPQUAD(table->netmask));
+ return length; /* expected ip from table's network/netmask */
+ }
+ if (!table->shortlisting) {
+ memset(&l, 0, sizeof(struct t_ipt_account_ip_list));
+ while(*bufferptr) {
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (!memcmp(bufferptr, "bytes_src", 9)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_src (%ti).\n", bufferptr - buffer);
+ p = &l.src.b_all;
+ bufferptr += 9;
+ } else if (!memcmp(bufferptr, "bytes_dest", 10)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_dest (%ti).\n", bufferptr - buffer);
+ p = &l.dest.b_all;
+ bufferptr += 10;
+ } else if (!memcmp(bufferptr, "packets_src", 11)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_src (%ti).\n", bufferptr - buffer);
+ p = &l.src.p_all;
+ bufferptr += 11;
+ } else if (!memcmp(bufferptr, "packets_dest", 12)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_dest (%ti).\n", bufferptr - buffer);
+ p = &l.dest.p_all;
+ bufferptr += 12;
+ } else if (!memcmp(bufferptr, "time", 4)) {
+ /* time hack, ignore time tokens */
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got time (%ti).\n", bufferptr - buffer);
+ bufferptr += 4;
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (*bufferptr != '=') {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
+ return length; /* expected equal */
+ }
+ bufferptr += 1;
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (!(len = atoi64(bufferptr, &dummy))) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
+ return length; /* expected int64 */
+ }
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", dummy, bufferptr - buffer);
+ bufferptr += len;
+ continue; /* skip time token */
+ } else
+ return length; /* expected token */
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (*bufferptr != '=') {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
+ return length; /* expected equal */
+ }
+ bufferptr += 1;
+ for (i = 0; i < 5; i++) {
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (!(len = atoi64(bufferptr, p))) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
+ return length; /* expected int64 */
+ }
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", *p, bufferptr - buffer);
+ bufferptr += len;
+ p++;
+ }
+ }
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() updating row.\n");
+ spin_lock_bh(&table->ip_list_lock);
+ /* update counters, do not overwrite time field */
+ memcpy(&table->ip_list.l[ip - table->network], &l, sizeof(struct t_ipt_account_ip_list) - sizeof(unsigned long));
+ spin_unlock_bh(&table->ip_list_lock);
+ } else {
+ memset(&s, 0, sizeof(struct t_ipt_account_ip_list_short));
+ while(*bufferptr) {
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (!memcmp(bufferptr, "bytes_src", 9)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_src (%ti).\n", bufferptr - buffer);
+ p = &s.src.b_all;
+ bufferptr += 9;
+ } else if (!memcmp(bufferptr, "bytes_dest", 10)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got bytes_dest (%ti).\n", bufferptr - buffer);
+ p = &s.dest.b_all;
+ bufferptr += 10;
+ } else if (!memcmp(bufferptr, "packets_src", 11)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_src (%ti).\n", bufferptr - buffer);
+ p = &s.src.p_all;
+ bufferptr += 11;
+ } else if (!memcmp(bufferptr, "packets_dest", 12)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got packets_dest (%ti).\n", bufferptr - buffer);
+ p = &s.dest.p_all;
+ bufferptr += 12;
+ } else if (!memcmp(bufferptr, "time", 4)) {
+ /* time hack, ignore time tokens */
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got time (%ti).\n", bufferptr - buffer);
+ bufferptr += 4;
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (*bufferptr != '=') {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
+ return length; /* expected equal */
+ }
+ bufferptr += 1;
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (!(len = atoi64(bufferptr, &dummy))) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
+ return length; /* expected int64 */
+ }
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", dummy, bufferptr - buffer);
+ bufferptr += len;
+ continue; /* skip time token */
+ } else {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected token (%ti).\n", bufferptr - buffer);
+ return length; /* expected token */
+ }
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (*bufferptr != '=') {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected equal (%ti).\n", bufferptr - buffer);
+ return length; /* expected equal */
+ }
+ bufferptr += 1;
+ if (!isspace(*bufferptr)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected space (%ti).\n", bufferptr - buffer);
+ return length; /* expected space */
+ }
+ bufferptr += 1;
+ if (!(len = atoi64(bufferptr, p))) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() expected int64 (%ti).\n", bufferptr - buffer);
+ return length; /* expected int64 */
+ }
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() got %llu (%ti).\n", *p, bufferptr - buffer);
+ bufferptr += len;
+ }
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() updating row.\n");
+ spin_lock_bh(&table->ip_list_lock);
+ /* update counters, do not overwrite time field */
+ memcpy(&table->ip_list.s[ip - table->network], &s, sizeof(struct t_ipt_account_ip_list_short) - sizeof(unsigned long));
+ spin_unlock_bh(&table->ip_list_lock);
+ }
+ }
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": account_seq_write() left.\n");
+ return length;
+}
+
+
+static int account_seq_show(struct seq_file *s, void *v)
+{
+ struct proc_dir_entry *pde = s->private;
+ struct t_ipt_account_table *table = pde->data;
+ unsigned int *bucket = (unsigned int *)v;
+
+ u_int32_t address = table->network + *bucket;
+ struct timespec last;
+
+ if (!table->shortlisting) {
+ jiffies_to_timespec(jiffies - table->ip_list.l[*bucket].time, &last);
+ seq_printf(s,
+ "ip = %u.%u.%u.%u bytes_src = %llu %llu %llu %llu %llu packets_src = %llu %llu %llu %llu %llu bytes_dest = %llu %llu %llu %llu %llu packets_dest = %llu %llu %llu %llu %llu time = %lu\n",
+ HIPQUAD(address),
+ table->ip_list.l[*bucket].src.b_all,
+ table->ip_list.l[*bucket].src.b_tcp,
+ table->ip_list.l[*bucket].src.b_udp,
+ table->ip_list.l[*bucket].src.b_icmp,
+ table->ip_list.l[*bucket].src.b_other,
+ table->ip_list.l[*bucket].src.p_all,
+ table->ip_list.l[*bucket].src.p_tcp,
+ table->ip_list.l[*bucket].src.p_udp,
+ table->ip_list.l[*bucket].src.p_icmp,
+ table->ip_list.l[*bucket].src.p_other,
+ table->ip_list.l[*bucket].dest.b_all,
+ table->ip_list.l[*bucket].dest.b_tcp,
+ table->ip_list.l[*bucket].dest.b_udp,
+ table->ip_list.l[*bucket].dest.b_icmp,
+ table->ip_list.l[*bucket].dest.b_other,
+ table->ip_list.l[*bucket].dest.p_all,
+ table->ip_list.l[*bucket].dest.p_tcp,
+ table->ip_list.l[*bucket].dest.p_udp,
+ table->ip_list.l[*bucket].dest.p_icmp,
+ table->ip_list.l[*bucket].dest.p_other,
+ last.tv_sec
+ );
+ } else {
+ jiffies_to_timespec(jiffies - table->ip_list.s[*bucket].time, &last);
+ seq_printf(s,
+ "ip = %u.%u.%u.%u bytes_src = %llu packets_src = %llu bytes_dest = %llu packets_dest = %llu time = %lu\n",
+ HIPQUAD(address),
+ table->ip_list.s[*bucket].src.b_all,
+ table->ip_list.s[*bucket].src.p_all,
+ table->ip_list.s[*bucket].dest.b_all,
+ table->ip_list.s[*bucket].dest.p_all,
+ last.tv_sec
+ );
+ }
+ return 0;
+}
+
+static struct seq_operations account_seq_ops = {
+ .start = account_seq_start,
+ .next = account_seq_next,
+ .stop = account_seq_stop,
+ .show = account_seq_show
+};
+
+static int account_seq_open(struct inode *inode, struct file *file)
+{
+ int ret = seq_open(file, &account_seq_ops);
+
+ if (!ret) {
+ struct seq_file *sf = file->private_data;
+ sf->private = PDE(inode);
+ }
+ return ret;
+}
+
+static struct file_operations account_file_ops = {
+ .owner = THIS_MODULE,
+ .open = account_seq_open,
+ .read = seq_read,
+ .write = account_seq_write,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/* do raw accounting */
+static inline void do_account(struct t_ipt_account_stat *stat, const struct sk_buff *skb) {
+
+ /* update packet & bytes counters in *stat structure */
+ stat->b_all += skb->len;
+ stat->p_all++;
+
+ switch (skb->nh.iph->protocol) {
+ case IPPROTO_TCP:
+ stat->b_tcp += skb->len;
+ stat->p_tcp++;
+ break;
+ case IPPROTO_UDP:
+ stat->b_udp += skb->len;
+ stat->p_udp++;
+ break;
+ case IPPROTO_ICMP:
+ stat->b_icmp += skb->len;
+ stat->p_icmp++;
+ break;
+ default:
+ stat->b_other += skb->len;
+ stat->p_other++;
+ }
+}
+
+static inline void do_account_short(struct t_ipt_account_stat_short *stat, const struct sk_buff *skb) {
+
+ /* update packet & bytes counters in *stat structure */
+ stat->b_all += skb->len;
+ stat->p_all++;
+}
+
+static int match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+
+ const struct t_ipt_account_info *info = (struct t_ipt_account_info*)matchinfo;
+ struct t_ipt_account_table *table;
+ int ret;
+ unsigned long now;
+
+ u_int32_t address;
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() entered.\n");
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() match name = %s.\n", info->name);
+
+ spin_lock_bh(&account_lock);
+ /* find the right table */
+ table = account_tables;
+ while (table && strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
+ spin_unlock_bh(&account_lock);
+
+ if (table == NULL) {
+ /* ups, no table with that name */
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() table %s not found. Leaving.\n", info->name);
+ return 0;
+ }
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() table found %s\n", table->name);
+
+ /* lock table while updating statistics */
+ spin_lock_bh(&table->ip_list_lock);
+
+ /* default: no match */
+ ret = 0;
+
+ /* get current time */
+ now = jiffies;
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() got packet src = %u.%u.%u.%u, dst = %u.%u.%u.%u, proto = %u.\n", NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr), skb->nh.iph->protocol);
+
+ /* check whether traffic from source ip address ... */
+ address = ntohl(skb->nh.iph->saddr);
+ /* ... is being accounted by this table */
+ if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {
+ /* yes, account this packet */
+ dprintk(KERN_INFO "ipt_account: match() accounting packet src = %u.%u.%u.%u, proto = %u.\n", HIPQUAD(address), skb->nh.iph->protocol);
+ /* update counters this host */
+ if (!table->shortlisting) {
+ do_account(&table->ip_list.l[address - table->network].src, skb);
+ table->ip_list.l[address - table->network].time = now;
+ /* update also counters for all hosts in this table (network address) */
+ if (table->netmask != INADDR_BROADCAST) {
+ do_account(&table->ip_list.l[0].src, skb);
+ table->ip_list.l[0].time = now;
+ }
+ } else {
+ do_account_short(&table->ip_list.s[address - table->network].src, skb);
+ table->ip_list.s[address - table->network].time = now;
+ /* update also counters for all hosts in this table (network address) */
+ if (table->netmask != INADDR_BROADCAST) {
+ do_account_short(&table->ip_list.s[0].src, skb);
+ table->ip_list.s[0].time = now;
+ }
+ }
+ /* yes, it's a match */
+ ret = 1;
+ }
+
+ /* do the same thing with destination ip address */
+ address = ntohl(skb->nh.iph->daddr);
+ if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() accounting packet dst = %u.%u.%u.%u, proto = %u.\n", HIPQUAD(address), skb->nh.iph->protocol);
+ if (!table->shortlisting) {
+ do_account(&table->ip_list.l[address - table->network].dest, skb);
+ table->ip_list.l[address - table->network].time = now;
+ if (table->netmask != INADDR_BROADCAST) {
+ do_account(&table->ip_list.l[0].dest, skb);
+ table->ip_list.s[0].time = now;
+ }
+ } else {
+ do_account_short(&table->ip_list.s[address - table->network].dest, skb);
+ table->ip_list.s[address - table->network].time = now;
+ if (table->netmask != INADDR_BROADCAST) {
+ do_account_short(&table->ip_list.s[0].dest, skb);
+ table->ip_list.s[0].time = now;
+ }
+ }
+ ret = 1;
+ }
+ spin_unlock_bh(&table->ip_list_lock);
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": match() left.\n");
+
+ return ret;
+}
+
+static int checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask)
+{
+ const struct t_ipt_account_info *info = matchinfo;
+ struct t_ipt_account_table *table, *find_table, *last_table;
+ int ret = 0;
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() entered.\n");
+
+ if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info))) return 0;
+ if (!info->name || !info->name[0]) return 0;
+
+ /* find whether table with this name already exists */
+ spin_lock_bh(&account_lock);
+ find_table = account_tables;
+ while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_ACCOUNT_NAME_LEN) && (find_table = find_table->next) );
+ if (find_table != NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() table %s found.\n", info->name);
+ /* if table exists, check whether table network/netmask equals rule network/netmask */
+ if (find_table->network != info->network || find_table->netmask != info->netmask || find_table->shortlisting != info->shortlisting) {
+ spin_unlock_bh(&account_lock);
+ printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() wrong parameters (not equals existing table parameters).\n");
+ ret = 0;
+ goto failure;
+ }
+ /* increment table use count */
+ find_table->use_count++;
+ spin_unlock_bh(&account_lock);
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() incrementing use count.\n");
+ ret = 1;
+ goto failure;
+ }
+ spin_unlock_bh(&account_lock);
+
+ /* check netmask first, before allocating memory */
+ if (info->netmask < ((1 << netmask) - 1)) {
+ printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() too big netmask.\n");
+ ret = 0;
+ goto failure;
+ }
+
+ /* table doesn't exist - create new */
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() allocating %zu for new table %s.\n", sizeof(struct t_ipt_account_table), info->name);
+ table = vmalloc(sizeof(struct t_ipt_account_table));
+ if (table == NULL) {
+ printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to allocate %zu for new table %s.\n", sizeof(struct t_ipt_account_table), info->name);
+ ret = 0; /* was -ENOMEM */
+ goto failure;
+ }
+
+ /* setup table parameters */
+ table->ip_list_lock = SPIN_LOCK_UNLOCKED;
+ table->next = NULL;
+ table->use_count = 1;
+ table->network = info->network;
+ table->netmask = info->netmask;
+ table->shortlisting = info->shortlisting;
+ table->count = (~table->netmask) + 1;
+ strncpy(table->name,info->name,IPT_ACCOUNT_NAME_LEN);
+ table->name[IPT_ACCOUNT_NAME_LEN - 1] = '\0';
+
+ /* allocate memory for table->ip_list */
+ if (!table->shortlisting) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() allocating %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list) * table->count);
+ table->ip_list.l = vmalloc(sizeof(struct t_ipt_account_ip_list) * table->count);
+ if (table->ip_list.l == NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to allocate %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list) * table->count);
+ ret = 0; /* was -ENOMEM */
+ goto failure_table;
+ }
+ memset(table->ip_list.l, 0, sizeof(struct t_ipt_account_ip_list) * table->count);
+ } else {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() allocating %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list_short) * table->count);
+ table->ip_list.s = vmalloc(sizeof(struct t_ipt_account_ip_list_short) * table->count);
+ if (table->ip_list.s == NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to allocate %zu for ip_list.\n", sizeof(struct t_ipt_account_ip_list_short) * table->count);
+ ret = 0; /* was -ENOMEM */
+ goto failure_table;
+ }
+ memset(table->ip_list.s, 0, sizeof(struct t_ipt_account_ip_list_short) * table->count);
+ }
+
+ /* put table into chain */
+ spin_lock_bh(&account_lock);
+ find_table = account_tables;
+ while( (last_table = find_table) && strncmp(info->name, find_table->name, IPT_ACCOUNT_NAME_LEN) && (find_table = find_table->next) );
+ if (find_table != NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() table %s found.\n", info->name);
+ if (find_table->network != info->network || find_table->netmask != info->netmask) {
+ spin_unlock_bh(&account_lock);
+ printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() wrong network/netmask.\n");
+ ret = 0;
+ goto failure_ip_list;
+ }
+ find_table->use_count++;
+ spin_unlock_bh(&account_lock);
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() incrementing use count.\n");
+ ret = 1;
+ goto failure_ip_list;
+ }
+ if (!last_table)
+ account_tables = table;
+ else
+ last_table->next = table;
+ spin_unlock_bh(&account_lock);
+
+ /* create procfs status file */
+ table->status_file = create_proc_entry(table->name, permissions, proc_net_ipt_account);
+ if (table->status_file == NULL) {
+ ret = 0; /* was -ENOMEM */
+ goto failure_unlink;
+ }
+ table->status_file->owner = THIS_MODULE;
+ table->status_file->data = table;
+ wmb();
+// if (!table->shortlisting)
+ table->status_file->proc_fops = &account_file_ops;
+// else
+// table->status_file->proc_fops = &account_file_ops_short;
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() left.\n");
+ /* everything went just okey */
+ return 1;
+
+ /* do cleanup in case of failure */
+failure_unlink:
+ /* remove table from list */
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() removing table.\n");
+ spin_lock_bh(&account_lock);
+ last_table = NULL;
+ table = account_tables;
+ if (table == NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() no table found. Leaving.\n");
+ spin_unlock_bh(&account_lock);
+ return 0; /* was -ENOMEM */
+ }
+ while (strncmp(info->name, table->name, IPT_ACCOUNT_NAME_LEN) && (last_table = table) && (table = table->next));
+ if (table == NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() table already destroyed. Leaving.\n");
+ spin_unlock_bh(&account_lock);
+ return 0; /* was -ENOMEM */
+ }
+ if (last_table)
+ last_table->next = table->next;
+ else
+ account_tables = table->next;
+ spin_unlock_bh(&account_lock);
+failure_ip_list:
+ /* free memory allocated for statistics table */
+ if (!table->shortlisting)
+ vfree(table->ip_list.l);
+ else
+ vfree(table->ip_list.s);
+failure_table:
+ /* free table */
+ vfree(table);
+failure:
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() left. Table not created.\n");
+ /* failure return */
+ return ret;
+}
+
+static void destroy(void *matchinfo,
+ unsigned int matchinfosize)
+{
+ const struct t_ipt_account_info *info = matchinfo;
+ struct t_ipt_account_table *table, *last_table;
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() entered.\n");
+
+ if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info))) return;
+
+ /* search for table */
+ spin_lock_bh(&account_lock);
+ last_table = NULL;
+ table = account_tables;
+ if(table == NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() no tables found. Leaving.\n");
+ spin_unlock_bh(&account_lock);
+ return;
+ }
+ while( strncmp(info->name,table->name,IPT_ACCOUNT_NAME_LEN) && (last_table = table) && (table = table->next) );
+ if (table == NULL) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() no table %s not found. Leaving.\n", info->name);
+ spin_unlock_bh(&account_lock);
+ return;
+ }
+
+ /* decrement table use-count */
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() decrementing use count.\n");
+ table->use_count--;
+ if (table->use_count) {
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() table still in use. Leaving.\n");
+ spin_unlock_bh(&account_lock);
+ return;
+ }
+
+ /* remove table if use-count is zero */
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() table %s not used. Removing.\n", table->name);
+
+ /* unlink table */
+ if(last_table)
+ last_table->next = table->next;
+ else
+ account_tables = table->next;
+ spin_unlock_bh(&account_lock);
+
+ /* wait while table is still in use */
+ spin_lock_bh(&table->ip_list_lock);
+ spin_unlock_bh(&table->ip_list_lock);
+
+ /* remove proc entries */
+ remove_proc_entry(table->name, proc_net_ipt_account);
+
+ /* remove table */
+ if (!table->shortlisting)
+ vfree(table->ip_list.l);
+ else
+ vfree(table->ip_list.s);
+ vfree(table);
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": destory() left.\n");
+ return;
+}
+
+static struct ipt_match account_match = {
+ .name = "account",
+ .match = &match,
+ .checkentry = &checkentry,
+ .destroy = &destroy,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ int err;
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __init() entered.\n");
+ printk(version);
+ /* check params */
+ if (netmask > 32 || netmask < 0) {
+ printk(KERN_INFO "account: Wrong netmask given by netmask parameter (%i). Valid is 32 to 0.\n", netmask);
+ err = -EINVAL;
+ goto doexit;
+ }
+
+ /* create /proc/net/ipt_account directory */
+ proc_net_ipt_account = proc_mkdir("ipt_account", proc_net);
+ if (!proc_net_ipt_account) {
+ printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to create procfs entry.\n");
+ err = -ENOMEM;
+ goto doexit;
+ }
+ proc_net_ipt_account->owner = THIS_MODULE;
+
+ err = ipt_register_match(&account_match);
+ if (err) {
+ printk(KERN_INFO IPT_ACCOUNT_NAME ": checkentry() failed to register match.\n");
+ remove_proc_entry("ipt_account", proc_net);
+ }
+doexit:
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __init() left.\n");
+ return err;
+}
+
+static void __exit fini(void)
+{
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __exit() entered.\n");
+
+ ipt_unregister_match(&account_match);
+ /* remove /proc/net/ipt_account/ directory */
+ remove_proc_entry("ipt_account", proc_net);
+
+ dprintk(KERN_INFO IPT_ACCOUNT_NAME ": __exit() left.\n");
+}
+
+module_init(init);
+module_exit(fini);
+
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_bcount.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_bcount.c
new file mode 100644
index 00000000..63f93a14
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_bcount.c
@@ -0,0 +1,59 @@
+/*
+
+ bcount match (experimental)
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_bcount.h>
+
+// #define LOG printk
+#define LOG(...) do { } while (0);
+
+
+static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
+ const void *matchinfo, int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+ const struct ipt_bcount_match *info = matchinfo;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
+ if (!ct) return !info->invert;
+ return ((ct->bcount >= info->min) && (ct->bcount <= info->max)) ^ info->invert;
+}
+
+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
+ unsigned int matchsize, unsigned int hook_mask)
+{
+ return (matchsize == IPT_ALIGN(sizeof(struct ipt_bcount_match)));
+}
+
+
+static struct ipt_match bcount_match
+= { { NULL, NULL }, "bcount", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ LOG(KERN_INFO "ipt_bcount <" __DATE__ " " __TIME__ "> loaded\n");
+ return ipt_register_match(&bcount_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&bcount_match);
+}
+
+module_init(init);
+module_exit(fini);
+
+
+MODULE_AUTHOR("Jonathan Zarate");
+MODULE_DESCRIPTION("bcount match");
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_condition.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_condition.c
new file mode 100644
index 00000000..c8ee72d5
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_condition.c
@@ -0,0 +1,256 @@
+/*-------------------------------------------*\
+| Netfilter Condition Module |
+| |
+| Description: This module allows firewall |
+| rules to match using condition variables |
+| stored in /proc files. |
+| |
+| Author: Stephane Ouellette 2002-10-22 |
+| <ouellettes@videotron.ca> |
+| |
+| History: |
+| 2003-02-10 Second version with improved |
+| locking and simplified code. |
+| |
+| This software is distributed under the |
+| terms of the GNU GPL. |
+\*-------------------------------------------*/
+
+#include<linux/module.h>
+#include<linux/proc_fs.h>
+#include<linux/spinlock.h>
+#include<linux/string.h>
+#include<asm/atomic.h>
+#include<linux/netfilter_ipv4/ip_tables.h>
+#include<linux/netfilter_ipv4/ipt_condition.h>
+
+
+#ifndef CONFIG_PROC_FS
+#error "Proc file system support is required for this module"
+#endif
+
+
+MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
+MODULE_DESCRIPTION("Allows rules to match against condition variables");
+MODULE_LICENSE("GPL");
+
+
+struct condition_variable {
+ struct condition_variable *next;
+ struct proc_dir_entry *status_proc;
+ atomic_t refcount;
+ int enabled; /* TRUE == 1, FALSE == 0 */
+};
+
+
+static rwlock_t list_lock;
+static struct condition_variable *head = NULL;
+static struct proc_dir_entry *proc_net_condition = NULL;
+
+
+static int
+ipt_condition_read_info(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ struct condition_variable *var =
+ (struct condition_variable *) data;
+
+ if (offset == 0) {
+ *start = buffer;
+ buffer[0] = (var->enabled) ? '1' : '0';
+ buffer[1] = '\n';
+ return 2;
+ }
+
+ *eof = 1;
+ return 0;
+}
+
+
+static int
+ipt_condition_write_info(struct file *file, const char *buffer,
+ unsigned long length, void *data)
+{
+ struct condition_variable *var =
+ (struct condition_variable *) data;
+
+ if (length) {
+ /* Match only on the first character */
+ switch (buffer[0]) {
+ case '0':
+ var->enabled = 0;
+ break;
+ case '1':
+ var->enabled = 1;
+ }
+ }
+
+ return (int) length;
+}
+
+
+static int
+match(const struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, const void *matchinfo, int offset,
+ const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+ const struct condition_info *info =
+ (const struct condition_info *) matchinfo;
+ struct condition_variable *var;
+ int condition_status = 0;
+
+ read_lock(&list_lock);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ condition_status = var->enabled;
+ break;
+ }
+ }
+
+ read_unlock(&list_lock);
+
+ return condition_status ^ info->invert;
+}
+
+
+
+static int
+checkentry(const char *tablename, const struct ipt_ip *ip,
+ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+ struct condition_info *info = (struct condition_info *) matchinfo;
+ struct condition_variable *var, *newvar;
+
+ if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
+ return 0;
+
+ /* The first step is to check if the condition variable already exists. */
+ /* Here, a read lock is sufficient because we won't change the list */
+ read_lock(&list_lock);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ atomic_inc(&var->refcount);
+ read_unlock(&list_lock);
+ return 1;
+ }
+ }
+
+ read_unlock(&list_lock);
+
+ /* At this point, we need to allocate a new condition variable */
+ newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
+
+ if (!newvar)
+ return -ENOMEM;
+
+ /* Create the condition variable's proc file entry */
+ newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
+
+ if (!newvar->status_proc) {
+ /*
+ * There are two possibilities:
+ * 1- Another condition variable with the same name has been created, which is valid.
+ * 2- There was a memory allocation error.
+ */
+ kfree(newvar);
+ read_lock(&list_lock);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ atomic_inc(&var->refcount);
+ read_unlock(&list_lock);
+ return 1;
+ }
+ }
+
+ read_unlock(&list_lock);
+ return -ENOMEM;
+ }
+
+ atomic_set(&newvar->refcount, 1);
+ newvar->enabled = 0;
+ newvar->status_proc->owner = THIS_MODULE;
+ newvar->status_proc->data = newvar;
+ wmb();
+ newvar->status_proc->read_proc = ipt_condition_read_info;
+ newvar->status_proc->write_proc = ipt_condition_write_info;
+
+ write_lock(&list_lock);
+
+ newvar->next = head;
+ head = newvar;
+
+ write_unlock(&list_lock);
+
+ return 1;
+}
+
+
+static void
+destroy(void *matchinfo, unsigned int matchsize)
+{
+ struct condition_info *info = (struct condition_info *) matchinfo;
+ struct condition_variable *var, *prev = NULL;
+
+ if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
+ return;
+
+ write_lock(&list_lock);
+
+ for (var = head; var && strcmp(info->name, var->status_proc->name);
+ prev = var, var = var->next);
+
+ if (var && atomic_dec_and_test(&var->refcount)) {
+ if (prev)
+ prev->next = var->next;
+ else
+ head = var->next;
+
+ write_unlock(&list_lock);
+ remove_proc_entry(var->status_proc->name, proc_net_condition);
+ kfree(var);
+ } else
+ write_unlock(&list_lock);
+}
+
+
+static struct ipt_match condition_match = {
+ .name = "condition",
+ .match = &match,
+ .checkentry = &checkentry,
+ .destroy = &destroy,
+ .me = THIS_MODULE
+};
+
+
+static int __init
+init(void)
+{
+ int errorcode;
+
+ rwlock_init(&list_lock);
+ proc_net_condition = proc_mkdir("ipt_condition", proc_net);
+
+ if (proc_net_condition) {
+ errorcode = ipt_register_match(&condition_match);
+
+ if (errorcode)
+ remove_proc_entry("ipt_condition", proc_net);
+ } else
+ errorcode = -EACCES;
+
+ return errorcode;
+}
+
+
+static void __exit
+fini(void)
+{
+ ipt_unregister_match(&condition_match);
+ remove_proc_entry("ipt_condition", proc_net);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c
new file mode 100644
index 00000000..abf8efff
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c
@@ -0,0 +1,222 @@
+/*
+ * netfilter module to limit the number of parallel tcp
+ * connections per IP address.
+ * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
+ * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
+ * only ignore TIME_WAIT or gone connections
+ *
+ * based on ...
+ *
+ * Kernel module to match connection tracking information.
+ * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/version.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_connlimit.h>
+
+#define DEBUG 0
+
+MODULE_LICENSE("GPL");
+
+/* we'll save the tuples of all connections we care about */
+struct ipt_connlimit_conn
+{
+ struct list_head list;
+ struct ip_conntrack_tuple tuple;
+};
+
+struct ipt_connlimit_data {
+ spinlock_t lock;
+ struct list_head iphash[256];
+};
+
+static inline unsigned ipt_iphash(const unsigned addr)
+{
+ return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff);
+}
+
+static int count_them(struct ipt_connlimit_data *data,
+ u_int32_t addr, u_int32_t mask,
+ struct ip_conntrack *ct)
+{
+#if DEBUG
+ const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
+ "fin_wait", "time_wait", "close", "close_wait",
+ "last_ack", "listen" };
+#endif
+ int addit = 1, matches = 0;
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack_tuple_hash *found;
+ struct ipt_connlimit_conn *conn;
+ struct list_head *hash,*lh;
+
+ spin_lock_bh(&data->lock);
+ tuple = ct->tuplehash[0].tuple;
+ hash = &data->iphash[ipt_iphash(addr & mask)];
+
+ /* check the saved connections */
+ for (lh = hash->next; lh != hash; lh = lh->next) {
+ conn = list_entry(lh,struct ipt_connlimit_conn,list);
+ found = ip_conntrack_find_get(&conn->tuple,ct);
+ if (found != NULL &&
+ 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
+ found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
+ /* Just to be sure we have it only once in the list.
+ We should'nt see tuples twice unless someone hooks this
+ into a table without "-p tcp --syn" */
+ addit = 0;
+ }
+#if DEBUG
+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
+ ipt_iphash(addr & mask),
+ NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
+ NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
+ (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
+#endif
+ if (NULL == found) {
+ /* this one is gone */
+ lh = lh->prev;
+ list_del(lh->next);
+ kfree(conn);
+ continue;
+ }
+ if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
+ /* we don't care about connections which are
+ closed already -> ditch it */
+ lh = lh->prev;
+ list_del(lh->next);
+ kfree(conn);
+ nf_conntrack_put(&found->ctrack->infos[0]);
+ continue;
+ }
+ if ((addr & mask) == (conn->tuple.src.ip & mask)) {
+ /* same source IP address -> be counted! */
+ matches++;
+ }
+ nf_conntrack_put(&found->ctrack->infos[0]);
+ }
+ if (addit) {
+ /* save the new connection in our list */
+#if DEBUG
+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
+ ipt_iphash(addr & mask),
+ NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
+ NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
+#endif
+ conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
+ if (NULL == conn)
+ return -1;
+ memset(conn,0,sizeof(*conn));
+ INIT_LIST_HEAD(&conn->list);
+ conn->tuple = tuple;
+ list_add(&conn->list,hash);
+ matches++;
+ }
+ spin_unlock_bh(&data->lock);
+ return matches;
+}
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_connlimit_info *info = matchinfo;
+ int connections, match;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
+ if (NULL == ct) {
+ printk("ipt_connlimit: Oops: invalid ct state ?\n");
+ *hotdrop = 1;
+ return 0;
+ }
+ connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
+ if (-1 == connections) {
+ printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
+ *hotdrop = 1; /* let's free some memory :-) */
+ return 0;
+ }
+ match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
+#if DEBUG
+ printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
+ "connections=%d limit=%d match=%s\n",
+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
+ connections, info->limit, match ? "yes" : "no");
+#endif
+
+ return match;
+}
+
+static int check(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ struct ipt_connlimit_info *info = matchinfo;
+ int i;
+
+ /* verify size */
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
+ return 0;
+
+ /* refuse anything but tcp */
+ if (ip->proto != IPPROTO_TCP)
+ return 0;
+
+ /* init private data */
+ info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
+ spin_lock_init(&(info->data->lock));
+ for (i = 0; i < 256; i++)
+ INIT_LIST_HEAD(&(info->data->iphash[i]));
+
+ return 1;
+}
+
+static void destroy(void *matchinfo, unsigned int matchinfosize)
+{
+ struct ipt_connlimit_info *info = matchinfo;
+ struct ipt_connlimit_conn *conn;
+ struct list_head *hash;
+ int i;
+
+ /* cleanup */
+ for (i = 0; i < 256; i++) {
+ hash = &(info->data->iphash[i]);
+ while (hash != hash->next) {
+ conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
+ list_del(hash->next);
+ kfree(conn);
+ }
+ }
+ kfree(info->data);
+}
+
+static struct ipt_match connlimit_match
+= { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_match(&connlimit_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&connlimit_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_connmark.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_connmark.c
new file mode 100644
index 00000000..d795a339
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_connmark.c
@@ -0,0 +1,83 @@
+/* This kernel module matches connection mark values set by the
+ * CONNMARK target
+ *
+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
+MODULE_DESCRIPTION("IP tables connmark match module");
+MODULE_LICENSE("GPL");
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_connmark.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_connmark_info *info = matchinfo;
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
+ if (!ct)
+ return 0;
+
+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
+ return 0;
+
+ return 1;
+}
+
+static struct ipt_match connmark_match = {
+ .name = "connmark",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_match(&connmark_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&connmark_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_exp.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_exp.c
new file mode 100644
index 00000000..1b682b9c
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_exp.c
@@ -0,0 +1,57 @@
+/*
+
+ Experimental Netfilter Crap
+ Copyright (C) 2006 Jonathan Zarate
+
+*/
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/file.h>
+#include <net/sock.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_exp.h>
+#include "../../bridge/br_private.h"
+
+
+static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
+ const void *matchinfo, int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+// const struct ipt_exp_info *info = matchinfo;
+
+ if ((skb->mac.raw >= skb->head) && ((skb->mac.raw + ETH_HLEN) <= skb->data)) {
+ printk(KERN_INFO "exp src=%02X:%02X:%02X:%02X:%02X:%02X dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
+ skb->mac.ethernet->h_source[0], skb->mac.ethernet->h_source[1], skb->mac.ethernet->h_source[2],
+ skb->mac.ethernet->h_source[3], skb->mac.ethernet->h_source[4], skb->mac.ethernet->h_source[5],
+ skb->mac.ethernet->h_dest[0], skb->mac.ethernet->h_dest[1], skb->mac.ethernet->h_dest[2],
+ skb->mac.ethernet->h_dest[3], skb->mac.ethernet->h_dest[4], skb->mac.ethernet->h_dest[5]);
+ return 1;
+ }
+ printk(KERN_INFO "exp mac=%p head=%p in=%p\n", skb->mac.raw, skb->head, in);
+ return 0;
+}
+
+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
+ unsigned int matchsize, unsigned int hook_mask)
+{
+ return (matchsize == IPT_ALIGN(sizeof(struct ipt_exp_info)));
+}
+
+static struct ipt_match exp_match
+ = { { NULL, NULL }, "exp", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ printk(KERN_INFO "exp init " __DATE__ " " __TIME__ "\n");
+ return ipt_register_match(&exp_match);
+}
+
+static void __exit fini(void)
+{
+ printk(KERN_INFO "exp fini\n");
+ ipt_unregister_match(&exp_match);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_geoip.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_geoip.c
new file mode 100644
index 00000000..fbd1a95c
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_geoip.c
@@ -0,0 +1,272 @@
+/* netfilter's kernel module for the geoip match
+ *
+ * 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.
+ *
+ * Copyright (c) 2004 Cookinglinux
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+
+#include <linux/netfilter_ipv4/ipt_geoip.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Samuel Jean, Nicolas Bouliane");
+MODULE_DESCRIPTION("iptables/netfilter's geoip match");
+
+struct geoip_info *head = NULL;
+static spinlock_t geoip_lock = SPIN_LOCK_UNLOCKED;
+
+static struct geoip_info *add_node(struct geoip_info *memcpy)
+{
+ struct geoip_info *p =
+ (struct geoip_info *)kmalloc(sizeof(struct geoip_info), GFP_KERNEL);
+
+ struct geoip_subnet *s;
+
+ if ((p == NULL) || (copy_from_user(p, memcpy, sizeof(struct geoip_info)) != 0))
+ return NULL;
+
+ s = (struct geoip_subnet *)kmalloc(p->count * sizeof(struct geoip_subnet), GFP_KERNEL);
+ if ((s == NULL) || (copy_from_user(s, p->subnets, p->count * sizeof(struct geoip_subnet)) != 0))
+ return NULL;
+
+ spin_lock_bh(&geoip_lock);
+
+ p->subnets = s;
+ p->ref = 1;
+ p->next = head;
+ p->prev = NULL;
+ if (p->next) p->next->prev = p;
+ head = p;
+
+ spin_unlock_bh(&geoip_lock);
+ return p;
+}
+
+static void remove_node(struct geoip_info *p)
+ {
+ spin_lock_bh(&geoip_lock);
+
+ if (p->next) { /* Am I following a node ? */
+ p->next->prev = p->prev;
+ if (p->prev) p->prev->next = p->next; /* Is there a node behind me ? */
+ else head = p->next; /* No? Then I was the head */
+ }
+
+ else
+ if (p->prev) /* Is there a node behind me ? */
+ p->prev->next = NULL;
+ else
+ head = NULL; /* No, we're alone */
+
+ /* So now am unlinked or the only one alive, right ?
+ * What are you waiting ? Free up some memory!
+ */
+
+ kfree(p->subnets);
+ kfree(p);
+
+ spin_unlock_bh(&geoip_lock);
+ return;
+}
+
+static struct geoip_info *find_node(u_int16_t cc)
+{
+ struct geoip_info *p = head;
+ spin_lock_bh(&geoip_lock);
+
+ while (p) {
+ if (p->cc == cc) {
+ spin_unlock_bh(&geoip_lock);
+ return p;
+ }
+ p = p->next;
+ }
+ spin_unlock_bh(&geoip_lock);
+ return NULL;
+}
+
+static int match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_geoip_info *info = matchinfo;
+ const struct geoip_info *node; /* This keeps the code sexy */
+ const struct iphdr *iph = skb->nh.iph;
+ u_int32_t ip, j;
+ u_int8_t i;
+
+ if (info->flags & IPT_GEOIP_SRC)
+ ip = ntohl(iph->saddr);
+ else
+ ip = ntohl(iph->daddr);
+
+ spin_lock_bh(&geoip_lock);
+ for (i = 0; i < info->count; i++) {
+ if ((node = info->mem[i]) == NULL) {
+ printk(KERN_ERR "ipt_geoip: what the hell ?? '%c%c' isn't loaded into memory... skip it!\n",
+ COUNTRY(info->cc[i]));
+
+ continue;
+ }
+
+ for (j = 0; j < node->count; j++)
+ if ((ip > node->subnets[j].begin) && (ip < node->subnets[j].end)) {
+ spin_unlock_bh(&geoip_lock);
+ return (info->flags & IPT_GEOIP_INV) ? 0 : 1;
+ }
+ }
+
+ spin_unlock_bh(&geoip_lock);
+ return (info->flags & IPT_GEOIP_INV) ? 1 : 0;
+}
+
+static int geoip_checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ struct ipt_geoip_info *info = matchinfo;
+ struct geoip_info *node;
+ u_int8_t i;
+
+ /* FIXME: Call a function to free userspace allocated memory.
+ * As Martin J. said; this match might eat lot of memory
+ * if commited with iptables-restore --noflush
+ void (*gfree)(struct geoip_info *oldmem);
+ gfree = info->fini;
+ */
+
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_geoip_info))) {
+ printk(KERN_ERR "ipt_geoip: matchsize differ, you may have forgotten to recompile me\n");
+ return 0;
+ }
+
+ /* If info->refcount isn't NULL, then
+ * it means that checkentry() already
+ * initialized this entry. Increase a
+ * refcount to prevent destroy() of
+ * this entry. */
+ if (info->refcount != NULL) {
+ atomic_inc((atomic_t *)info->refcount);
+ return 1;
+ }
+
+
+ for (i = 0; i < info->count; i++) {
+
+ if ((node = find_node(info->cc[i])) != NULL)
+ atomic_inc((atomic_t *)&node->ref); //increase the reference
+ else
+ if ((node = add_node(info->mem[i])) == NULL) {
+ printk(KERN_ERR
+ "ipt_geoip: unable to load '%c%c' into memory\n",
+ COUNTRY(info->cc[i]));
+ return 0;
+ }
+
+ /* Free userspace allocated memory for that country.
+ * FIXME: It's a bit odd to call this function everytime
+ * we process a country. Would be nice to call
+ * it once after all countries've been processed.
+ * - SJ
+ * *not implemented for now*
+ gfree(info->mem[i]);
+ */
+
+ /* Overwrite the now-useless pointer info->mem[i] with
+ * a pointer to the node's kernelspace structure.
+ * This avoids searching for a node in the match() and
+ * destroy() functions.
+ */
+ info->mem[i] = node;
+ }
+
+ /* We allocate some memory and give info->refcount a pointer
+ * to this memory. This prevents checkentry() from increasing a refcount
+ * different from the one used by destroy().
+ * For explanation, see http://www.mail-archive.com/netfilter-devel@lists.samba.org/msg00625.html
+ */
+ info->refcount = kmalloc(sizeof(u_int8_t), GFP_KERNEL);
+ if (info->refcount == NULL) {
+ printk(KERN_ERR "ipt_geoip: failed to allocate `refcount' memory\n");
+ return 0;
+ }
+ *(info->refcount) = 1;
+
+ return 1;
+}
+
+static void geoip_destroy(void *matchinfo, unsigned int matchsize)
+{
+ struct ipt_geoip_info *info = matchinfo;
+ struct geoip_info *node; /* this keeps the code sexy */
+ u_int8_t i;
+
+ /* Decrease the previously increased refcount in checkentry()
+ * If it's equal to 1, we know this entry is just moving
+ * but not removed. We simply return to avoid useless destroy()
+ * processing.
+ */
+ atomic_dec((atomic_t *)info->refcount);
+ if (*info->refcount)
+ return;
+
+ /* Don't leak my memory, you idiot.
+ * Bug found with nfsim.. the netfilter's best
+ * friend. --peejix */
+ kfree(info->refcount);
+
+ /* This entry has been removed from the table so
+ * decrease the refcount of all countries it is
+ * using.
+ */
+
+ for (i = 0; i < info->count; i++)
+ if ((node = info->mem[i]) != NULL) {
+ atomic_dec((atomic_t *)&node->ref);
+
+ /* Free up some memory if that node isn't used
+ * anymore. */
+ if (node->ref < 1)
+ remove_node(node);
+ }
+ else
+ /* Something strange happened. There's no memory allocated for this
+ * country. Please send this bug to the mailing list. */
+ printk(KERN_ERR
+ "ipt_geoip: What happened peejix ? What happened acidmen ?\n"
+ "ipt_geoip: please report this bug to the maintainers\n");
+ return;
+}
+
+static struct ipt_match geoip_match
+= { { NULL, NULL }, "geoip", &match, &geoip_checkentry, &geoip_destroy, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_match(&geoip_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&geoip_match);
+ return;
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c
new file mode 100644
index 00000000..c36b2005
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c
@@ -0,0 +1,868 @@
+#if defined(MODVERSIONS)
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_ipp2p.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+#define get_u8(X,O) (*(__u8 *)(X + O))
+#define get_u16(X,O) (*(__u16 *)(X + O))
+#define get_u32(X,O) (*(__u32 *)(X + O))
+
+MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
+MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
+MODULE_LICENSE("GPL");
+
+
+/*Search for UDP eDonkey/eMule/Kad commands*/
+int
+udp_search_edk (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ t += 8;
+
+ switch (t[0]) {
+ case 0xe3:
+ { /*edonkey*/
+ switch (t[1])
+ {
+ /* client -> server status request */
+ case 0x96:
+ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
+ break;
+ /* server -> client status request */
+ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
+ break;
+ /* server description request */
+ /* e3 2a ff f0 .. | size == 6 */
+ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
+ break;
+ /* server description response */
+ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
+ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
+ // break;
+ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
+ break;
+
+ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
+ break;
+ }
+ break;
+ }
+ case 0xe4:
+ {
+ switch (t[1])
+ {
+ /* e4 20 .. | size == 43 */
+ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
+ break;
+ /* e4 00 .. 00 | size == 35 ? */
+ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
+ break;
+ /* e4 10 .. 00 | size == 35 ? */
+ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
+ break;
+ /* e4 18 .. 00 | size == 35 ? */
+ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
+ break;
+ /* e4 52 .. | size = 44 */
+ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
+ break;
+ /* e4 58 .. | size == 6 */
+ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
+ break;
+ /* e4 59 .. | size == 2 */
+ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
+ break;
+ /* e4 28 .. | packet_len == 52,77,102,127... */
+ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
+ break;
+ /* e4 50 xx xx | size == 4 */
+ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
+ break;
+ /* e4 40 xx xx | size == 48 */
+ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
+ break;
+ }
+ break;
+ }
+ } /* end of switch (t[0]) */
+ return 0;
+}/*udp_search_edk*/
+
+
+/*Search for UDP Gnutella commands*/
+int
+udp_search_gnu (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ t += 8;
+
+ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
+ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
+ return 0;
+}/*udp_search_gnu*/
+
+
+/*Search for UDP KaZaA commands*/
+int
+udp_search_kazaa (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+
+ if (t[packet_len-1] == 0x00){
+ t += (packet_len - 6);
+ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
+ }
+
+ return 0;
+}/*udp_search_kazaa*/
+
+/*Search for UDP DirectConnect commands*/
+int
+udp_search_directconnect (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
+ t+=8;
+ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
+ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
+ }
+ return 0;
+}/*udp_search_directconnect*/
+
+
+
+/*Search for UDP BitTorrent commands*/
+int
+udp_search_bit (unsigned char *haystack, int packet_len)
+{
+ switch(packet_len)
+ {
+ case 24:
+ /* ^ 00 00 04 17 27 10 19 80 */
+ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
+ return (IPP2P_BIT * 100 + 50);
+ break;
+ case 44:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 51);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
+ return (IPP2P_BIT * 100 + 61);
+ break;
+ case 65:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 52);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
+ return (IPP2P_BIT * 100 + 62);
+ break;
+ case 67:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 53);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
+ return (IPP2P_BIT * 100 + 63);
+ break;
+ case 211:
+ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
+ return (IPP2P_BIT * 100 + 54);
+ break;
+ case 29:
+ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
+ return (IPP2P_BIT * 100 + 55);
+ break;
+ case 52:
+ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
+ get_u32(haystack,12) == __constant_htonl(0x37502950))
+ return (IPP2P_BIT * 100 + 80);
+ break;
+ default:
+ /* this packet does not have a constant size */
+ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 56);
+ break;
+ }
+
+ /* some extra-bitcomet rules:
+ * "d1:" [a|r] "d2:id20:"
+ */
+ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
+ {
+ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
+ {
+ if (memcmp(haystack+12,"d2:id20:",8)==0)
+ return (IPP2P_BIT * 100 + 57);
+ }
+ }
+
+#if 0
+ /* bitlord rules */
+ /* packetlen must be bigger than 40 */
+ /* first 4 bytes are zero */
+ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
+ {
+ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
+ if (get_u32(haystack, 12) == 0x00000000 &&
+ get_u32(haystack, 16) == 0x00010000 &&
+ get_u32(haystack, 24) == 0x00000000 )
+ return (IPP2P_BIT * 100 + 71);
+
+ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
+ if (get_u32(haystack, 12) == 0x00000001 &&
+ get_u32(haystack, 16) == 0x000d0000 &&
+ get_u32(haystack, 24) == 0x00000000 )
+ return (IPP2P_BIT * 100 + 71);
+
+
+ }
+#endif
+
+ return 0;
+}/*udp_search_bit*/
+
+
+
+/*Search for Ares commands*/
+//#define IPP2P_DEBUG_ARES
+int
+search_ares (const unsigned char *payload, const u16 plen)
+//int search_ares (unsigned char *haystack, int packet_len, int head_len)
+{
+// const unsigned char *t = haystack + head_len;
+
+ /* all ares packets start with */
+ if (payload[1] == 0 && (plen - payload[0]) == 3)
+ {
+ switch (payload[2])
+ {
+ case 0x5a:
+ /* ares connect */
+ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
+ break;
+ case 0x09:
+ /* ares search, min 3 chars --> 14 bytes
+ * lets define a search can be up to 30 chars --> max 34 bytes
+ */
+ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
+ break;
+#ifdef IPP2P_DEBUG_ARES
+ default:
+ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
+#endif /* IPP2P_DEBUG_ARES */
+ }
+ }
+
+#if 0
+ /* found connect packet: 03 00 5a 04 03 05 */
+ /* new version ares 1.8: 03 00 5a xx xx 05 */
+ if ((plen) == 6){ /* possible connect command*/
+ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
+ return ((IPP2P_ARES * 100) + 1);
+ }
+ if ((plen) == 60){ /* possible download command*/
+ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
+ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
+ return ((IPP2P_ARES * 100) + 2);
+ }
+ }
+#endif
+
+ return 0;
+} /*search_ares*/
+
+/*Search for SoulSeek commands*/
+int
+search_soul (const unsigned char *payload, const u16 plen)
+{
+//#define IPP2P_DEBUG_SOUL
+ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
+ if (get_u32(payload, 0) == (plen - 4)){
+ const __u32 m=get_u32(payload, 4);
+ /* match 00 yy yy 00, yy can be everything */
+ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 1);
+ }
+
+ /* next match: 01 yy 00 00 | yy can be everything */
+ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 2);
+ }
+
+ /* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */
+ /* try to do this in an intelligent way */
+ /* get all small commandos */
+ switch(m)
+ {
+ case 7:
+ case 9:
+ case 22:
+ case 23:
+ case 26:
+ case 28:
+ case 50:
+ case 51:
+ case 60:
+ case 91:
+ case 92:
+ case 1001:
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 3);
+ }
+
+ if (m > 0 && m < 6 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 4);
+ }
+ if (m > 12 && m < 19 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 5);
+ }
+
+ if (m > 34 && m < 38 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 6);
+ }
+
+ if (m > 39 && m < 47 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 7);
+ }
+
+ if (m > 61 && m < 70 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 8);
+ }
+
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
+#endif /* IPP2P_DEBUG_SOUL */
+ }
+
+ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
+ /* without size at the beginning !!! */
+ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
+ {
+ __u32 y=get_u32(payload, 5);
+ /* we need 19 chars + string */
+ if ( (y + 19) <= (plen) )
+ {
+ const unsigned char *w=payload+9+y;
+ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "Soulssek special client command recognized\n");
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 9);
+ }
+ }
+ return 0;
+}
+
+
+/*Search for WinMX commands*/
+int
+search_winmx (const unsigned char *payload, const u16 plen)
+{
+//#define IPP2P_DEBUG_WINMX
+ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
+ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
+ //if (packet_len < (head_len + 10)) return 0;
+ if (plen < 10) return 0;
+
+ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
+ u16 c=4;
+ const u16 end=plen-2;
+ u8 count=0;
+ while (c < end)
+ {
+ if (payload[c]== 0x20 && payload[c+1] == 0x22)
+ {
+ c++;
+ count++;
+ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
+ }
+ c++;
+ }
+ }
+
+ if ( plen == 149 && payload[0] == '8' )
+ {
+#ifdef IPP2P_DEBUG_WINMX
+ printk(KERN_INFO "maybe WinMX\n");
+#endif
+ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
+// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
+// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
+ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
+
+ {
+#ifdef IPP2P_DEBUG_WINMX
+ printk(KERN_INFO "got WinMX\n");
+#endif
+ return ((IPP2P_WINMX * 100) + 4);
+ }
+ }
+ return 0;
+} /*search_winmx*/
+
+
+/*Search for appleJuice commands*/
+int
+search_apple (const unsigned char *payload, const u16 plen)
+{
+ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
+
+ return 0;
+}
+
+
+/*Search for BitTorrent commands*/
+int
+search_bittorrent (const unsigned char *payload, const u16 plen)
+{
+ if (plen > 20)
+ {
+ /* test for match 0x13+"BitTorrent protocol" */
+ if (payload[0] == 0x13)
+ {
+ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
+ }
+
+ /* get tracker commandos, all starts with GET /
+ * then it can follow: scrape| announce
+ * and then ?hash_info=
+ */
+ if (memcmp(payload,"GET /",5) == 0)
+ {
+ /* message scrape */
+ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
+ /* message announce */
+ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
+ }
+ }
+ else
+ {
+ /* bitcomet encryptes the first packet, so we have to detect another
+ * one later in the flow */
+ /* first try failed, too many missdetections */
+ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
+
+ /* second try: block request packets */
+ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
+ }
+
+ return 0;
+}
+
+
+
+/*check for Kazaa get command*/
+int
+search_kazaa (const unsigned char *payload, const u16 plen)
+
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
+ return (IPP2P_DATA_KAZAA * 100);
+
+ return 0;
+}
+
+
+/*check for gnutella get command*/
+int
+search_gnu (const unsigned char *payload, const u16 plen)
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
+ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
+ }
+ return 0;
+}
+
+
+/*check for gnutella get commands and other typical data*/
+int
+search_all_gnu (const unsigned char *payload, const u16 plen)
+{
+
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+
+ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
+ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
+
+
+ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
+ {
+ u16 c=8;
+ const u16 end=plen-22;
+ while (c < end) {
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
+ return ((IPP2P_GNU * 100) + 3);
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*check for KaZaA download commands and other typical data*/
+int
+search_all_kazaa (const unsigned char *payload, const u16 plen)
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+
+ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
+
+ if (memcmp(payload, "GET /", 5) == 0) {
+ u16 c = 8;
+ const u16 end=plen-22;
+ while (c < end) {
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
+ return ((IPP2P_KAZAA * 100) + 2);
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+/*fast check for edonkey file segment transfer command*/
+int
+search_edk (const unsigned char *payload, const u16 plen)
+{
+ if (payload[0] != 0xe3)
+ return 0;
+ else {
+ if (payload[5] == 0x47)
+ return (IPP2P_DATA_EDK * 100);
+ else
+ return 0;
+ }
+}
+
+
+
+/*intensive but slower search for some edonkey packets including size-check*/
+int
+search_all_edk (const unsigned char *payload, const u16 plen)
+{
+ if (payload[0] != 0xe3)
+ return 0;
+ else {
+ //t += head_len;
+ const u16 cmd = get_u16(payload, 1);
+ if (cmd == (plen - 5)) {
+ switch (payload[5]) {
+ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
+ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
+ }
+ }
+ return 0;
+ }
+}
+
+
+/*fast check for Direct Connect send command*/
+int
+search_dc (const unsigned char *payload, const u16 plen)
+{
+
+ if (payload[0] != 0x24 )
+ return 0;
+ else {
+ if (memcmp(&payload[1], "Send|", 5) == 0)
+ return (IPP2P_DATA_DC * 100);
+ else
+ return 0;
+ }
+
+}
+
+
+/*intensive but slower check for all direct connect packets*/
+int
+search_all_dc (const unsigned char *payload, const u16 plen)
+{
+// unsigned char *t = haystack;
+
+ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
+ {
+ const unsigned char *t=&payload[1];
+ /* Client-Hub-Protocol */
+ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
+ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
+ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
+ }
+ return 0;
+}
+
+/*check for mute*/
+int
+search_mute (const unsigned char *payload, const u16 plen)
+{
+ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
+ {
+ //printk(KERN_DEBUG "size hit: %u",size);
+ if (memcmp(payload,"PublicKey: ",11) == 0 )
+ {
+ return ((IPP2P_MUTE * 100) + 0);
+
+/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
+ {
+ printk(KERN_DEBUG "end pubic key hit: %u",size);
+
+ }*/
+ }
+ }
+ return 0;
+}
+
+
+/* check for xdcc */
+int
+search_xdcc (const unsigned char *payload, const u16 plen)
+{
+ /* search in small packets only */
+ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
+ {
+
+ u16 x=10;
+ const u16 end=plen - 13;
+
+ /* is seems to be a irc private massage, chedck for xdcc command */
+ while (x < end)
+ {
+ if (payload[x] == ':')
+ {
+ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
+ return ((IPP2P_XDCC * 100) + 0);
+ }
+ x++;
+ }
+ }
+ return 0;
+}
+
+/* search for waste */
+int search_waste(const unsigned char *payload, const u16 plen)
+{
+ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
+ return ((IPP2P_WASTE * 100) + 0);
+
+ return 0;
+}
+
+
+static struct {
+ int command;
+ __u8 short_hand; /*for fucntions included in short hands*/
+ int packet_len;
+ int (*function_name) (const unsigned char *, const u16);
+} matchlist[] = {
+ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
+// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
+// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
+// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
+ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
+// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
+ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
+ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
+ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
+ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
+ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
+ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
+ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
+ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
+ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
+ {0,0,0,NULL}
+};
+
+
+static struct {
+ int command;
+ __u8 short_hand; /*for fucntions included in short hands*/
+ int packet_len;
+ int (*function_name) (unsigned char *, int);
+} udp_list[] = {
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
+ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
+ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
+ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
+ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
+ {0,0,0,NULL}
+};
+
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ const void *hdr,
+ u_int16_t datalen,
+#endif
+
+ int *hotdrop)
+{
+ const struct ipt_p2p_info *info = matchinfo;
+ unsigned char *haystack;
+ struct iphdr *ip = skb->nh.iph;
+ int p2p_result = 0, i = 0;
+// int head_len;
+ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
+
+ /*must not be a fragment*/
+ if (offset) {
+ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
+ return 0;
+ }
+
+ /*make sure that skb is linear*/
+ if(skb_is_nonlinear(skb)){
+ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
+ return 0;
+ }
+
+
+ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
+
+ switch (ip->protocol){
+ case IPPROTO_TCP: /*what to do with a TCP packet*/
+ {
+ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
+
+ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
+ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
+ if (tcph->rst) return 0; /*if RST bit is set bail out*/
+
+ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
+ hlen -= tcph->doff * 4;
+ while (matchlist[i].command) {
+ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
+ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
+ (hlen > matchlist[i].packet_len)) {
+ p2p_result = matchlist[i].function_name(haystack, hlen);
+ if (p2p_result)
+ {
+ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
+ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
+ return p2p_result;
+ }
+ }
+ i++;
+ }
+ return p2p_result;
+ }
+
+ case IPPROTO_UDP: /*what to do with an UDP packet*/
+ {
+ struct udphdr *udph = (void *) ip + ip->ihl * 4;
+
+ while (udp_list[i].command){
+ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
+ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
+ (hlen > udp_list[i].packet_len)) {
+ p2p_result = udp_list[i].function_name(haystack, hlen);
+ if (p2p_result){
+ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
+ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
+ return p2p_result;
+ }
+ }
+ i++;
+ }
+ return p2p_result;
+ }
+
+ default: return 0;
+ }
+}
+
+
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ /* Must specify -p tcp */
+/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
+ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
+ * return 0;
+ * }*/
+ return 1;
+}
+
+
+
+
+static struct ipt_match ipp2p_match = {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ { NULL, NULL },
+ "ipp2p",
+ &match,
+ &checkentry,
+ NULL,
+ THIS_MODULE
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ .name = "ipp2p",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+#endif
+};
+
+
+static int __init init(void)
+{
+ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
+ return ipt_register_match(&ipp2p_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&ipp2p_match);
+ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
+
+
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_iprange.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_iprange.c
new file mode 100644
index 00000000..38902524
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_iprange.c
@@ -0,0 +1,101 @@
+/*
+ * iptables module to match IP address ranges
+ * (c) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * Released under the terms of GNU GPLv2.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_iprange.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("iptables arbitrary IP range match module");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_iprange_info *info = matchinfo;
+ const struct iphdr *iph = skb->nh.iph;
+
+
+ if (info->flags & IPRANGE_SRC) {
+ if (((ntohl(iph->saddr) < ntohl(info->src.min_ip))
+ || (ntohl(iph->saddr) > ntohl(info->src.max_ip)))
+ ^ !!(info->flags & IPRANGE_SRC_INV)) {
+ DEBUGP("src IP %u.%u.%u.%u NOT in range %s"
+ "%u.%u.%u.%u-%u.%u.%u.%u\n",
+ NIPQUAD(iph->saddr),
+ info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
+ NIPQUAD(info->src.min_ip),
+ NIPQUAD(info->src.max_ip));
+ return 0;
+ }
+ }
+ if (info->flags & IPRANGE_DST) {
+ if (((ntohl(iph->daddr) < ntohl(info->dst.min_ip))
+ || (ntohl(iph->daddr) > ntohl(info->dst.max_ip)))
+ ^ !!(info->flags & IPRANGE_DST_INV)) {
+ DEBUGP("dst IP %u.%u.%u.%u NOT in range %s"
+ "%u.%u.%u.%u-%u.%u.%u.%u\n",
+ NIPQUAD(iph->daddr),
+ info->flags & IPRANGE_DST_INV ? "(INV) " : "",
+ NIPQUAD(info->dst.min_ip),
+ NIPQUAD(info->dst.max_ip));
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int check(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ /* verify size */
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_iprange_info)))
+ return 0;
+
+ return 1;
+}
+
+static struct ipt_match iprange_match =
+{
+ .list = { NULL, NULL },
+ .name = "iprange",
+ .match = &match,
+ .checkentry = &check,
+ .destroy = NULL,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_match(&iprange_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&iprange_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_layer7.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_layer7.c
new file mode 100644
index 00000000..567e3847
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_layer7.c
@@ -0,0 +1,570 @@
+/*
+ Kernel module to match application layer (OSI layer 7)
+ data in connections.
+
+ http://l7-filter.sf.net
+
+ By Matthew Strait and Ethan Sommer, 2003-2005.
+
+ 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.
+ http://www.gnu.org/licenses/gpl.txt
+
+ Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>
+ and cls_layer7.c (C) 2003 Matthew Strait, Ethan Sommer, Justin Levandoski
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/netfilter_ipv4/lockhelp.h>
+
+#include "regexp/regexp.c"
+
+#include <linux/netfilter_ipv4/ipt_layer7.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("iptables application layer match module");
+
+static int maxdatalen = 2048; // this is the default
+MODULE_PARM(maxdatalen,"i");
+MODULE_PARM_DESC(maxdatalen,"maximum bytes of data looked at by l7-filter");
+
+#if defined(CONFIG_IP_NF_MATCH_LAYER7_DEBUG)
+ #define DPRINTK(format,args...) printk(format,##args)
+#else
+ #define DPRINTK(format,args...)
+#endif
+
+#define TOTAL_PACKETS master_conntrack->layer7.numpackets
+
+/* Number of packets whose data we look at.
+This can be modified through /proc/net/layer7_numpackets */
+static int num_packets = 10;
+
+static struct pattern_cache {
+ char * regex_string;
+ regexp * pattern;
+ struct pattern_cache * next;
+} * first_pattern_cache = NULL;
+
+/* I'm new to locking. Here are my assumptions:
+
+- No one will write to /proc/net/layer7_numpackets over and over very fast;
+ if they did, nothing awful would happen.
+
+- This code will never be processing the same packet twice at the same time,
+ because iptables rules are traversed in order.
+
+- It doesn't matter if two packets from different connections are in here at
+ the same time, because they don't share any data.
+
+- It _does_ matter if two packets from the same connection are here at the same
+ time. In this case, we have to protect the conntracks and the list of
+ compiled patterns.
+*/
+DECLARE_RWLOCK(ct_lock);
+DECLARE_LOCK(list_lock);
+
+#if CONFIG_IP_NF_MATCH_LAYER7_DEBUG
+/* Converts an unfriendly string into a friendly one by
+replacing unprintables with periods and all whitespace with " ". */
+static char * friendly_print(unsigned char * s)
+{
+ char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
+ int i;
+
+ if(!f) {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in friendly_print, bailing.\n");
+ return NULL;
+ }
+
+ for(i = 0; i < strlen(s); i++){
+ if(isprint(s[i]) && s[i] < 128) f[i] = s[i];
+ else if(isspace(s[i])) f[i] = ' ';
+ else f[i] = '.';
+ }
+ f[i] = '\0';
+ return f;
+}
+
+static char dec2hex(int i)
+{
+ switch (i) {
+ case 0 ... 9:
+ return (char)(i + '0');
+ break;
+ case 10 ... 15:
+ return (char)(i - 10 + 'a');
+ break;
+ default:
+ if (net_ratelimit())
+ printk("Problem in dec2hex\n");
+ return '\0';
+ }
+}
+
+static char * hex_print(unsigned char * s)
+{
+ char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
+ int i;
+
+ if(!g) {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in hex_print, bailing.\n");
+ return NULL;
+ }
+
+ for(i = 0; i < strlen(s); i++) {
+ g[i*3 ] = dec2hex(s[i]/16);
+ g[i*3 + 1] = dec2hex(s[i]%16);
+ g[i*3 + 2] = ' ';
+ }
+ g[i*3] = '\0';
+
+ return g;
+}
+#endif // DEBUG
+
+/* Use instead of regcomp. As we expect to be seeing the same regexps over and
+over again, it make sense to cache the results. */
+static regexp * compile_and_cache(char * regex_string, char * protocol)
+{
+ struct pattern_cache * node = first_pattern_cache;
+ struct pattern_cache * last_pattern_cache = first_pattern_cache;
+ struct pattern_cache * tmp;
+ unsigned int len;
+
+ while (node != NULL) {
+ if (!strcmp(node->regex_string, regex_string))
+ return node->pattern;
+
+ last_pattern_cache = node;/* points at the last non-NULL node */
+ node = node->next;
+ }
+
+ /* If we reach the end of the list, then we have not yet cached
+ the pattern for this regex. Let's do that now.
+ Be paranoid about running out of memory to avoid list corruption. */
+ tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
+
+ if(!tmp) {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n");
+ return NULL;
+ }
+
+ tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
+ tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC);
+ tmp->next = NULL;
+
+ if(!tmp->regex_string || !tmp->pattern) {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n");
+ kfree(tmp->regex_string);
+ kfree(tmp->pattern);
+ kfree(tmp);
+ return NULL;
+ }
+
+ /* Ok. The new node is all ready now. */
+ node = tmp;
+
+ if(first_pattern_cache == NULL) /* list is empty */
+ first_pattern_cache = node; /* make node the beginning */
+ else
+ last_pattern_cache->next = node; /* attach node to the end */
+
+ /* copy the string and compile the regex */
+ len = strlen(regex_string);
+ DPRINTK("About to compile this: \"%s\"\n", regex_string);
+ node->pattern = regcomp(regex_string, &len);
+ if ( !node->pattern ) {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: Error compiling regexp \"%s\" (%s)\n", regex_string, protocol);
+ /* pattern is now cached as NULL, so we won't try again. */
+ }
+
+ strcpy(node->regex_string, regex_string);
+ return node->pattern;
+}
+
+static int can_handle(const struct sk_buff *skb)
+{
+ if(!skb->nh.iph) /* not IP */
+ return 0;
+ if(skb->nh.iph->protocol != IPPROTO_TCP &&
+ skb->nh.iph->protocol != IPPROTO_UDP &&
+ skb->nh.iph->protocol != IPPROTO_ICMP)
+ return 0;
+ return 1;
+}
+
+/* Returns offset the into the skb->data that the application data starts */
+static int app_data_offset(const struct sk_buff *skb)
+{
+ /* In case we are ported somewhere (ebtables?) where skb->nh.iph
+ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
+ int ip_hl = 4*skb->nh.iph->ihl;
+
+ if( skb->nh.iph->protocol == IPPROTO_TCP ) {
+ /* 12 == offset into TCP header for the header length field.
+ Can't get this with skb->h.th->doff because the tcphdr
+ struct doesn't get set when routing (this is confirmed to be
+ true in Netfilter as well as QoS.) */
+ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
+
+ return ip_hl + tcp_hl;
+ } else if( skb->nh.iph->protocol == IPPROTO_UDP ) {
+ return ip_hl + 8; /* UDP header is always 8 bytes */
+ } else if( skb->nh.iph->protocol == IPPROTO_ICMP ) {
+ return ip_hl + 8; /* ICMP header is 8 bytes */
+ } else {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: tried to handle unknown protocol!\n");
+ return ip_hl + 8; /* something reasonable */
+ }
+}
+
+/* handles whether there's a match when we aren't appending data anymore */
+static int match_no_append(struct ip_conntrack * conntrack, struct ip_conntrack * master_conntrack,
+ enum ip_conntrack_info ctinfo, enum ip_conntrack_info master_ctinfo,
+ struct ipt_layer7_info * info)
+{
+ /* If we're in here, throw the app data away */
+ WRITE_LOCK(&ct_lock);
+ if(master_conntrack->layer7.app_data != NULL) {
+
+ #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
+ if(!master_conntrack->layer7.app_proto) {
+ char * f = friendly_print(master_conntrack->layer7.app_data);
+ char * g = hex_print(master_conntrack->layer7.app_data);
+ DPRINTK("\nl7-filter gave up after %d bytes (%d packets):\n%s\n",
+ strlen(f),
+ TOTAL_PACKETS, f);
+ kfree(f);
+ DPRINTK("In hex: %s\n", g);
+ kfree(g);
+ }
+ #endif
+
+ kfree(master_conntrack->layer7.app_data);
+ master_conntrack->layer7.app_data = NULL; /* don't free again */
+ }
+ WRITE_UNLOCK(&ct_lock);
+
+ if(master_conntrack->layer7.app_proto){
+ /* Here child connections set their .app_proto (for /proc/net/ip_conntrack) */
+ WRITE_LOCK(&ct_lock);
+ if(!conntrack->layer7.app_proto) {
+ conntrack->layer7.app_proto = kmalloc(strlen(master_conntrack->layer7.app_proto)+1, GFP_ATOMIC);
+ if(!conntrack->layer7.app_proto){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n");
+ WRITE_UNLOCK(&ct_lock);
+ return 1;
+ }
+ strcpy(conntrack->layer7.app_proto, master_conntrack->layer7.app_proto);
+ }
+ WRITE_UNLOCK(&ct_lock);
+
+ return (!strcmp(master_conntrack->layer7.app_proto, info->protocol));
+ }
+ else {
+ /* If not classified, set to "unknown" to distinguish from
+ connections that are still being tested. */
+ WRITE_LOCK(&ct_lock);
+ master_conntrack->layer7.app_proto = kmalloc(strlen("unknown")+1, GFP_ATOMIC);
+ if(!master_conntrack->layer7.app_proto){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n");
+ WRITE_UNLOCK(&ct_lock);
+ return 1;
+ }
+ strcpy(master_conntrack->layer7.app_proto, "unknown");
+ WRITE_UNLOCK(&ct_lock);
+ return 0;
+ }
+}
+
+/* add the new app data to the conntrack. Return number of bytes added. */
+static int add_data(struct ip_conntrack * master_conntrack,
+ char * app_data, int appdatalen)
+{
+ int length = 0, i;
+ int oldlength = master_conntrack->layer7.app_data_len;
+
+ /* Strip nulls. Make everything lower case (our regex lib doesn't
+ do case insensitivity). Add it to the end of the current data. */
+ for(i = 0; i < maxdatalen-oldlength-1 && i < appdatalen; i++) {
+ if(app_data[i] != '\0') {
+ master_conntrack->layer7.app_data[length+oldlength] =
+ /* the kernel version of tolower mungs 'upper ascii' */
+ isascii(app_data[i])? tolower(app_data[i]) : app_data[i];
+ length++;
+ }
+ }
+
+ master_conntrack->layer7.app_data[length+oldlength] = '\0';
+ master_conntrack->layer7.app_data_len = length + oldlength;
+
+ return length;
+}
+
+/* Returns true on match and false otherwise. */
+static int match(/* const */struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, const void *matchinfo,
+ int offset, int *hotdrop)
+{
+ struct ipt_layer7_info * info = (struct ipt_layer7_info *)matchinfo;
+ enum ip_conntrack_info master_ctinfo, ctinfo;
+ struct ip_conntrack *master_conntrack, *conntrack;
+ unsigned char * app_data;
+ unsigned int pattern_result, appdatalen;
+ regexp * comppattern;
+
+ if(!can_handle(skb)){
+ DPRINTK("layer7: This is some protocol I can't handle.\n");
+ return info->invert;
+ }
+
+ /* Treat the parent and all its children together as one connection,
+ except for the purpose of setting conntrack->layer7.app_proto in the
+ actual connection. This makes /proc/net/ip_conntrack somewhat more
+ satisfying. */
+ if(!(conntrack = ip_conntrack_get((struct sk_buff *)skb, &ctinfo)) ||
+ !(master_conntrack = ip_conntrack_get((struct sk_buff *)skb, &master_ctinfo))) {
+ DPRINTK("layer7: packet is not from a known connection, giving up.\n");
+ return info->invert;
+ }
+
+ /* Try to get a master conntrack (and its master etc) for FTP, etc. */
+ while (master_ct(master_conntrack) != NULL)
+ master_conntrack = master_ct(master_conntrack);
+
+ if(!skb->cb[0]){
+ WRITE_LOCK(&ct_lock);
+ master_conntrack->layer7.numpackets++;/*starts at 0 via memset*/
+ WRITE_UNLOCK(&ct_lock);
+ }
+
+ /* if we've classified it or seen too many packets */
+ if(TOTAL_PACKETS > num_packets ||
+ master_conntrack->layer7.app_proto) {
+
+ pattern_result = match_no_append(conntrack, master_conntrack, ctinfo, master_ctinfo, info);
+
+ /* skb->cb[0] == seen. Avoid doing things twice if there are two l7
+ rules. I'm not sure that using cb for this purpose is correct, although
+ it says "put your private variables there". But it doesn't look like it
+ is being used for anything else in the skbs that make it here. How can
+ I write to cb without making the compiler angry? */
+ skb->cb[0] = 1; /* marking it seen here is probably irrelevant, but consistant */
+
+ return (pattern_result ^ info->invert);
+ }
+
+ if(skb_is_nonlinear(skb)){
+ if(skb_linearize(skb, GFP_ATOMIC) != 0){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: failed to linearize packet, bailing.\n");
+ return info->invert;
+ }
+ }
+
+ /* now that the skb is linearized, it's safe to set these. */
+ app_data = skb->data + app_data_offset(skb);
+ appdatalen = skb->tail - app_data;
+
+ LOCK_BH(&list_lock);
+ /* the return value gets checked later, when we're ready to use it */
+ comppattern = compile_and_cache(info->pattern, info->protocol);
+ UNLOCK_BH(&list_lock);
+
+ /* On the first packet of a connection, allocate space for app data */
+ WRITE_LOCK(&ct_lock);
+ if(TOTAL_PACKETS == 1 && !skb->cb[0] && !master_conntrack->layer7.app_data) {
+ master_conntrack->layer7.app_data = kmalloc(maxdatalen, GFP_ATOMIC);
+ if(!master_conntrack->layer7.app_data){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
+ WRITE_UNLOCK(&ct_lock);
+ return info->invert;
+ }
+
+ master_conntrack->layer7.app_data[0] = '\0';
+ }
+ WRITE_UNLOCK(&ct_lock);
+
+ /* Can be here, but unallocated, if numpackets is increased near
+ the beginning of a connection */
+ if(master_conntrack->layer7.app_data == NULL)
+ return (info->invert); /* unmatched */
+
+ if(!skb->cb[0]){
+ int newbytes;
+ WRITE_LOCK(&ct_lock);
+ newbytes = add_data(master_conntrack, app_data, appdatalen);
+ WRITE_UNLOCK(&ct_lock);
+
+ if(newbytes == 0) { /* didn't add any data */
+ skb->cb[0] = 1;
+ /* Didn't match before, not going to match now */
+ return info->invert;
+ }
+ }
+
+ /* If looking for "unknown", then never match. "Unknown" means that
+ we've given up; we're still trying with these packets. */
+ if(!strcmp(info->protocol, "unknown")) {
+ pattern_result = 0;
+ /* If the regexp failed to compile, don't bother running it */
+ } else if(comppattern && regexec(comppattern, master_conntrack->layer7.app_data)) {
+ DPRINTK("layer7: regexec positive: %s!\n", info->protocol);
+ pattern_result = 1;
+ } else pattern_result = 0;
+
+ if(pattern_result) {
+ WRITE_LOCK(&ct_lock);
+ master_conntrack->layer7.app_proto = kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
+ if(!master_conntrack->layer7.app_proto){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
+ WRITE_UNLOCK(&ct_lock);
+ return (pattern_result ^ info->invert);
+ }
+ strcpy(master_conntrack->layer7.app_proto, info->protocol);
+ WRITE_UNLOCK(&ct_lock);
+ }
+
+ /* mark the packet seen */
+ skb->cb[0] = 1;
+
+ return (pattern_result ^ info->invert);
+}
+
+static int checkentry(const char *tablename, const struct ipt_ip *ip,
+ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_layer7_info)))
+ return 0;
+ return 1;
+}
+
+static struct ipt_match layer7_match = {
+ .name = "layer7",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE
+};
+
+/* taken from drivers/video/modedb.c */
+static int my_atoi(const char *s)
+{
+ int val = 0;
+
+ for (;; s++) {
+ switch (*s) {
+ case '0'...'9':
+ val = 10*val+(*s-'0');
+ break;
+ default:
+ return val;
+ }
+ }
+}
+
+/* write out num_packets to userland. */
+static int layer7_read_proc(char* page, char ** start, off_t off, int count,
+ int* eof, void * data)
+{
+ if(num_packets > 99 && net_ratelimit())
+ printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n");
+
+ page[0] = num_packets/10 + '0';
+ page[1] = num_packets%10 + '0';
+ page[2] = '\n';
+ page[3] = '\0';
+
+ *eof=1;
+
+ return 3;
+}
+
+/* Read in num_packets from userland */
+static int layer7_write_proc(struct file* file, const char* buffer,
+ unsigned long count, void *data)
+{
+ char * foo = kmalloc(count, GFP_ATOMIC);
+
+ if(!foo){
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory, bailing. num_packets unchanged.\n");
+ return count;
+ }
+
+ copy_from_user(foo, buffer, count);
+
+ num_packets = my_atoi(foo);
+ kfree (foo);
+
+ /* This has an arbitrary limit to make the math easier. I'm lazy.
+ But anyway, 99 is a LOT! If you want more, you're doing it wrong! */
+ if(num_packets > 99) {
+ printk(KERN_WARNING "layer7: num_packets can't be > 99.\n");
+ num_packets = 99;
+ } else if(num_packets < 1) {
+ printk(KERN_WARNING "layer7: num_packets can't be < 1.\n");
+ num_packets = 1;
+ }
+
+ return count;
+}
+
+/* register the proc file */
+static void layer7_init_proc(void)
+{
+ struct proc_dir_entry* entry;
+ entry = create_proc_entry("layer7_numpackets", 0644, proc_net);
+ entry->read_proc = layer7_read_proc;
+ entry->write_proc = layer7_write_proc;
+}
+
+static void layer7_cleanup_proc(void)
+{
+ remove_proc_entry("layer7_numpackets", proc_net);
+}
+
+static int __init init(void)
+{
+ layer7_init_proc();
+ if(maxdatalen < 1) {
+ printk(KERN_WARNING "layer7: maxdatalen can't be < 1, using 1\n");
+ maxdatalen = 1;
+ }
+ /* This is not a hard limit. It's just here to prevent people from
+ bringing their slow machines to a grinding halt. */
+ else if(maxdatalen > 65536) {
+ printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, using 65536\n");
+ maxdatalen = 65536;
+ }
+ return ipt_register_match(&layer7_match);
+}
+
+static void __exit fini(void)
+{
+ layer7_cleanup_proc();
+ ipt_unregister_match(&layer7_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_mac.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_mac.c
index b320e29b..d0475155 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ipt_mac.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_mac.c
@@ -19,7 +19,8 @@ match(const struct sk_buff *skb,
const struct ipt_mac_info *info = matchinfo;
/* Is mac pointer valid? */
- return (skb->mac.raw >= skb->head
+ return (in != NULL // added for OUTPUT experiment -- zzz
+ && skb->mac.raw >= skb->head
&& (skb->mac.raw + ETH_HLEN) <= skb->data
/* If so, compare... */
&& ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
@@ -33,6 +34,7 @@ ipt_mac_checkentry(const char *tablename,
unsigned int matchsize,
unsigned int hook_mask)
{
+#if 0 // removed for OUTPUT experiment --jz
/* FORWARD isn't always valid, but it's nice to be able to do --RR */
if (hook_mask
& ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
@@ -40,7 +42,7 @@ ipt_mac_checkentry(const char *tablename,
printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
return 0;
}
-
+#endif
if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info)))
return 0;
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_macsave.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_macsave.c
new file mode 100644
index 00000000..25fa26a4
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_macsave.c
@@ -0,0 +1,62 @@
+/*
+
+ macsave match
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_macsave.h>
+
+#define DEBUG 1
+
+#ifdef DEBUG
+#define DLOG printk
+#else
+#define DLOG(...) do { } while (0);
+#endif
+
+
+static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
+ const void *matchinfo, int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+ const struct ipt_macsave_match_info *info = matchinfo;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); // note about cast: ip_conntrack_get() will not modify skb
+ if (ct) return (memcmp(ct->macsave, info->mac, sizeof(ct->macsave)) == 0) ^ info->invert;
+ return info->invert;
+}
+
+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
+ unsigned int matchsize, unsigned int hook_mask)
+{
+ return (matchsize == IPT_ALIGN(sizeof(struct ipt_macsave_match_info)));
+}
+
+
+static struct ipt_match macsave_match
+= { { NULL, NULL }, "macsave", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ DLOG(KERN_INFO "macsave match init " __DATE__ " " __TIME__ "\n");
+ return ipt_register_match(&macsave_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&macsave_match);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_mport.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_mport.c
index ca99b764..836d3f2f 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ipt_mport.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_mport.c
@@ -10,7 +10,11 @@
MODULE_LICENSE("GPL");
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
#define duprintf(format, args...)
+#endif
/* Returns 1 if the port is matched by the test, 0 otherwise. */
static inline int
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_quota.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_quota.c
new file mode 100644
index 00000000..d7ab39cf
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_quota.c
@@ -0,0 +1,88 @@
+/*
+ * netfilter module to enforce network quotas
+ *
+ * Sam Johnston <samj@samj.net>
+ *
+ * 30/01/05: Fixed on SMP --Pablo Neira <pablo@eurodev.net>
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_quota.h>
+
+MODULE_LICENSE("GPL");
+
+static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+ struct ipt_quota_info *q =
+ ((struct ipt_quota_info *) matchinfo)->master;
+
+ spin_lock_bh(&quota_lock);
+
+ if (q->quota >= datalen) {
+ /* we can afford this one */
+ q->quota -= datalen;
+ spin_unlock_bh(&quota_lock);
+
+#ifdef DEBUG_IPT_QUOTA
+ printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
+#endif
+ return 1;
+ }
+
+ /* so we do not allow even small packets from now on */
+ q->quota = 0;
+
+#ifdef DEBUG_IPT_QUOTA
+ printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
+#endif
+
+ spin_unlock_bh(&quota_lock);
+ return 0;
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+ /* TODO: spinlocks? sanity checks? */
+ struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
+
+ if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
+ return 0;
+
+ /* For SMP, we only want to use one set of counters. */
+ q->master = q;
+
+ return 1;
+}
+
+static struct ipt_match quota_match
+ = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init
+init(void)
+{
+ return ipt_register_match(&quota_match);
+}
+
+static void __exit
+fini(void)
+{
+ ipt_unregister_match(&quota_match);
+}
+
+module_init(init);
+module_exit(fini);
+
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_recent.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_recent.c
new file mode 100644
index 00000000..808ae78f
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_recent.c
@@ -0,0 +1,998 @@
+/* Kernel module to check if the source address has been seen recently. */
+/* Copyright 2002-2003, Stephen Frost */
+/* Author: Stephen Frost <sfrost@snowman.net> */
+/* Project Page: http://snowman.net/projects/ipt_recent/ */
+/* This software is distributed under the terms of the GPL, Version 2 */
+/* This copyright does not cover user programs that use kernel services
+ * by normal system calls. */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/ctype.h>
+#include <linux/ip.h>
+#include <linux/vmalloc.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_recent.h>
+
+#undef DEBUG
+#define HASH_LOG 9
+
+/* Defaults, these can be overridden on the module command-line. */
+static int ip_list_tot = 100;
+static int ip_pkt_list_tot = 20;
+static int ip_list_hash_size = 0;
+static int ip_list_perms = 0644;
+#ifdef DEBUG
+static int debug = 1;
+#endif
+
+static char version[] =
+KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n";
+
+MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
+MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
+MODULE_LICENSE("GPL");
+MODULE_PARM(ip_list_tot,"i");
+MODULE_PARM(ip_pkt_list_tot,"i");
+MODULE_PARM(ip_list_hash_size,"i");
+MODULE_PARM(ip_list_perms,"i");
+#ifdef DEBUG
+MODULE_PARM(debug,"i");
+MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
+#endif
+MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
+MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember");
+MODULE_PARM_DESC(ip_list_hash_size,"size of hash table used to look up IPs");
+MODULE_PARM_DESC(ip_list_perms,"permissions on /proc/net/ipt_recent/* files");
+
+/* Structure of our list of recently seen addresses. */
+struct recent_ip_list {
+ u_int32_t addr;
+ u_int8_t ttl;
+ u_int32_t last_seen;
+ u_int32_t *last_pkts;
+ u_int32_t oldest_pkt;
+ u_int32_t hash_entry;
+ u_int32_t time_pos;
+};
+
+struct time_info_list {
+ u_int32_t position;
+ u_int32_t time;
+};
+
+/* Structure of our linked list of tables of recent lists. */
+struct recent_ip_tables {
+ char name[IPT_RECENT_NAME_LEN];
+ int count;
+ int time_pos;
+ struct recent_ip_list *table;
+ struct recent_ip_tables *next;
+ spinlock_t list_lock;
+ int *hash_table;
+ struct time_info_list *time_info;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *status_proc;
+#endif /* CONFIG_PROC_FS */
+};
+
+/* Our current list of addresses we have recently seen.
+ * Only added to on a --set, and only updated on --set || --update
+ */
+static struct recent_ip_tables *r_tables = NULL;
+
+/* We protect r_list with this spinlock so two processors are not modifying
+ * the list at the same time.
+ */
+static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
+
+/* Our /proc/net/ipt_recent entry */
+static struct proc_dir_entry *proc_net_ipt_recent = NULL;
+
+/* Function declaration for later. */
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop);
+
+/* Function to hash a given address into the hash table of table_size size */
+int hash_func(unsigned int addr, int table_size)
+{
+ int result = 0;
+ unsigned int value = addr;
+ do { result ^= value; } while((value >>= HASH_LOG));
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": %d = hash_func(%u,%d)\n",
+ result & (table_size - 1),
+ addr,
+ table_size);
+#endif
+
+ return(result & (table_size - 1));
+}
+
+#ifdef CONFIG_PROC_FS
+/* This is the function which produces the output for our /proc output
+ * interface which lists each IP address, the last seen time and the
+ * other recent times the address was seen.
+ */
+
+static int ip_recent_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ int len = 0, count, last_len = 0, pkt_count;
+ off_t pos = 0;
+ off_t begin = 0;
+ struct recent_ip_tables *curr_table;
+
+ curr_table = (struct recent_ip_tables*) data;
+
+ spin_lock_bh(&curr_table->list_lock);
+ for(count = 0; count < ip_list_tot; count++) {
+ if(!curr_table->table[count].addr) continue;
+ last_len = len;
+ len += sprintf(buffer+len,"src=%u.%u.%u.%u ",NIPQUAD(curr_table->table[count].addr));
+ len += sprintf(buffer+len,"ttl: %u ",curr_table->table[count].ttl);
+ len += sprintf(buffer+len,"last_seen: %u ",curr_table->table[count].last_seen);
+ len += sprintf(buffer+len,"oldest_pkt: %u ",curr_table->table[count].oldest_pkt);
+ len += sprintf(buffer+len,"last_pkts: %u",curr_table->table[count].last_pkts[0]);
+ for(pkt_count = 1; pkt_count < ip_pkt_list_tot; pkt_count++) {
+ if(!curr_table->table[count].last_pkts[pkt_count]) break;
+ len += sprintf(buffer+len,", %u",curr_table->table[count].last_pkts[pkt_count]);
+ }
+ len += sprintf(buffer+len,"\n");
+ pos = begin + len;
+ if(pos < offset) { len = 0; begin = pos; }
+ if(pos > offset + length) { len = last_len; break; }
+ }
+
+ *start = buffer + (offset - begin);
+ len -= (offset - begin);
+ if(len > length) len = length;
+
+ spin_unlock_bh(&curr_table->list_lock);
+ return len;
+}
+
+/* ip_recent_ctrl provides an interface for users to modify the table
+ * directly. This allows adding entries, removing entries, and
+ * flushing the entire table.
+ * This is done by opening up the appropriate table for writing and
+ * sending one of:
+ * xx.xx.xx.xx -- Add entry to table with current time
+ * +xx.xx.xx.xx -- Add entry to table with current time
+ * -xx.xx.xx.xx -- Remove entry from table
+ * clear -- Flush table, remove all entries
+ */
+
+static int ip_recent_ctrl(struct file *file, const char *input, unsigned long size, void *data)
+{
+ static const u_int32_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
+ u_int32_t val;
+ int base, used = 0;
+ char c, *cp;
+ union iaddr {
+ uint8_t bytes[4];
+ uint32_t word;
+ } res;
+ uint8_t *pp = res.bytes;
+ int digit;
+
+ char buffer[20];
+ int len, check_set = 0, count;
+ u_int32_t addr = 0;
+ struct sk_buff *skb;
+ struct ipt_recent_info *info;
+ struct recent_ip_tables *curr_table;
+
+ curr_table = (struct recent_ip_tables*) data;
+
+ if(size > 20) len = 20; else len = size;
+
+ if(copy_from_user(buffer,input,len)) return -EFAULT;
+
+ if(len < 20) buffer[len] = '\0';
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl len: %d, input: `%.20s'\n",len,buffer);
+#endif
+
+ cp = buffer;
+ while(isspace(*cp)) { cp++; used++; if(used >= len-5) return used; }
+
+ /* Check if we are asked to flush the entire table */
+ if(!memcmp(cp,"clear",5)) {
+ used += 5;
+ spin_lock_bh(&curr_table->list_lock);
+ curr_table->time_pos = 0;
+ for(count = 0; count < ip_list_hash_size; count++) {
+ curr_table->hash_table[count] = -1;
+ }
+ for(count = 0; count < ip_list_tot; count++) {
+ curr_table->table[count].last_seen = 0;
+ curr_table->table[count].addr = 0;
+ curr_table->table[count].ttl = 0;
+ memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ curr_table->table[count].oldest_pkt = 0;
+ curr_table->table[count].time_pos = 0;
+ curr_table->time_info[count].position = count;
+ curr_table->time_info[count].time = 0;
+ }
+ spin_unlock_bh(&curr_table->list_lock);
+ return used;
+ }
+
+ check_set = IPT_RECENT_SET;
+ switch(*cp) {
+ case '+': check_set = IPT_RECENT_SET; cp++; used++; break;
+ case '-': check_set = IPT_RECENT_REMOVE; cp++; used++; break;
+ default: if(!isdigit(*cp)) return (used+1); break;
+ }
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl cp: `%c', check_set: %d\n",*cp,check_set);
+#endif
+ /* Get addr (effectively inet_aton()) */
+ /* Shamelessly stolen from libc, a function in the kernel for doing
+ * this would, of course, be greatly preferred, but our options appear
+ * to be rather limited, so we will just do it ourselves here.
+ */
+ res.word = 0;
+
+ c = *cp;
+ for(;;) {
+ if(!isdigit(c)) return used;
+ val = 0; base = 10; digit = 0;
+ if(c == '0') {
+ c = *++cp;
+ if(c == 'x' || c == 'X') base = 16, c = *++cp;
+ else { base = 8; digit = 1; }
+ }
+ for(;;) {
+ if(isascii(c) && isdigit(c)) {
+ if(base == 8 && (c == '8' || c == '0')) return used;
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ digit = 1;
+ } else if(base == 16 && isascii(c) && isxdigit(c)) {
+ val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A'));
+ c = *++cp;
+ digit = 1;
+ } else break;
+ }
+ if(c == '.') {
+ if(pp > res.bytes + 2 || val > 0xff) return used;
+ *pp++ = val;
+ c = *++cp;
+ } else break;
+ }
+ used = cp - buffer;
+ if(c != '\0' && (!isascii(c) || !isspace(c))) return used;
+ if(c == '\n') used++;
+ if(!digit) return used;
+
+ if(val > max[pp - res.bytes]) return used;
+ addr = res.word | htonl(val);
+
+ if(!addr && check_set == IPT_RECENT_SET) return used;
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl c: %c, addr: %u used: %d\n",c,addr,used);
+#endif
+
+ /* Set up and just call match */
+ info = kmalloc(sizeof(struct ipt_recent_info),GFP_KERNEL);
+ if(!info) { return -ENOMEM; }
+ info->seconds = 0;
+ info->hit_count = 0;
+ info->check_set = check_set;
+ info->invert = 0;
+ info->side = IPT_RECENT_SOURCE;
+ strncpy(info->name,curr_table->name,IPT_RECENT_NAME_LEN);
+ info->name[IPT_RECENT_NAME_LEN-1] = '\0';
+
+ skb = kmalloc(sizeof(struct sk_buff),GFP_KERNEL);
+ if (!skb) {
+ used = -ENOMEM;
+ goto out_free_info;
+ }
+ skb->nh.iph = kmalloc(sizeof(struct iphdr),GFP_KERNEL);
+ if (!skb->nh.iph) {
+ used = -ENOMEM;
+ goto out_free_skb;
+ }
+
+ skb->nh.iph->saddr = addr;
+ skb->nh.iph->daddr = 0;
+ /* Clear ttl since we have no way of knowing it */
+ skb->nh.iph->ttl = 0;
+ match(skb,NULL,NULL,info,0,NULL,sizeof(struct ipt_recent_info),NULL);
+
+ kfree(skb->nh.iph);
+out_free_skb:
+ kfree(skb);
+out_free_info:
+ kfree(info);
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": Leaving ip_recent_ctrl addr: %u used: %d\n",addr,used);
+#endif
+ return used;
+}
+
+#endif /* CONFIG_PROC_FS */
+
+/* 'match' is our primary function, called by the kernel whenever a rule is
+ * hit with our module as an option to it.
+ * What this function does depends on what was specifically asked of it by
+ * the user:
+ * --set -- Add or update last seen time of the source address of the packet
+ * -- matchinfo->check_set == IPT_RECENT_SET
+ * --rcheck -- Just check if the source address is in the list
+ * -- matchinfo->check_set == IPT_RECENT_CHECK
+ * --update -- If the source address is in the list, update last_seen
+ * -- matchinfo->check_set == IPT_RECENT_UPDATE
+ * --remove -- If the source address is in the list, remove it
+ * -- matchinfo->check_set == IPT_RECENT_REMOVE
+ * --seconds -- Option to --rcheck/--update, only match if last_seen within seconds
+ * -- matchinfo->seconds
+ * --hitcount -- Option to --rcheck/--update, only match if seen hitcount times
+ * -- matchinfo->hit_count
+ * --seconds and --hitcount can be combined
+ */
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ int pkt_count, hits_found, ans;
+ unsigned long now;
+ const struct ipt_recent_info *info = matchinfo;
+ u_int32_t addr = 0, time_temp;
+ u_int8_t ttl = skb->nh.iph->ttl;
+ int *hash_table;
+ int orig_hash_result, hash_result, temp, location = 0, time_loc, end_collision_chain = -1;
+ struct time_info_list *time_info;
+ struct recent_ip_tables *curr_table;
+ struct recent_ip_tables *last_table;
+ struct recent_ip_list *r_list;
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match() called\n");
+#endif
+
+ /* Default is false ^ info->invert */
+ ans = info->invert;
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): name = '%s'\n",info->name);
+#endif
+
+ /* if out != NULL then routing has been done and TTL changed.
+ * We change it back here internally for match what came in before routing. */
+ if(out) ttl++;
+
+ /* Find the right table */
+ spin_lock_bh(&recent_lock);
+ curr_table = r_tables;
+ while( (last_table = curr_table) && strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (curr_table = curr_table->next) );
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): table found('%s')\n",info->name);
+#endif
+
+ spin_unlock_bh(&recent_lock);
+
+ /* Table with this name not found, match impossible */
+ if(!curr_table) { return ans; }
+
+ /* Make sure no one is changing the list while we work with it */
+ spin_lock_bh(&curr_table->list_lock);
+
+ r_list = curr_table->table;
+ if(info->side == IPT_RECENT_DEST) addr = skb->nh.iph->daddr; else addr = skb->nh.iph->saddr;
+
+ if(!addr) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match() address (%u) invalid, leaving.\n",addr);
+#endif
+ spin_unlock_bh(&curr_table->list_lock);
+ return ans;
+ }
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): checking table, addr: %u, ttl: %u, orig_ttl: %u\n",addr,ttl,skb->nh.iph->ttl);
+#endif
+
+ /* Get jiffies now in case they changed while we were waiting for a lock */
+ now = jiffies;
+ hash_table = curr_table->hash_table;
+ time_info = curr_table->time_info;
+
+ orig_hash_result = hash_result = hash_func(addr,ip_list_hash_size);
+ /* Hash entry at this result used */
+ /* Check for TTL match if requested. If TTL is zero then a match would never
+ * happen, so match regardless of existing TTL in that case. Zero means the
+ * entry was added via the /proc interface anyway, so we will just use the
+ * first TTL we get for that IP address. */
+ if(info->check_set & IPT_RECENT_TTL) {
+ while(hash_table[hash_result] != -1 && !(r_list[hash_table[hash_result]].addr == addr &&
+ (!r_list[hash_table[hash_result]].ttl || r_list[hash_table[hash_result]].ttl == ttl))) {
+ /* Collision in hash table */
+ hash_result = (hash_result + 1) % ip_list_hash_size;
+ }
+ } else {
+ while(hash_table[hash_result] != -1 && r_list[hash_table[hash_result]].addr != addr) {
+ /* Collision in hash table */
+ hash_result = (hash_result + 1) % ip_list_hash_size;
+ }
+ }
+
+ if(hash_table[hash_result] == -1 && !(info->check_set & IPT_RECENT_SET)) {
+ /* IP not in list and not asked to SET */
+ spin_unlock_bh(&curr_table->list_lock);
+ return ans;
+ }
+
+ /* Check if we need to handle the collision, do not need to on REMOVE */
+ if(orig_hash_result != hash_result && !(info->check_set & IPT_RECENT_REMOVE)) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision in hash table. (or: %d,hr: %d,oa: %u,ha: %u)\n",
+ orig_hash_result,
+ hash_result,
+ r_list[hash_table[orig_hash_result]].addr,
+ addr);
+#endif
+
+ /* We had a collision.
+ * orig_hash_result is where we started, hash_result is where we ended up.
+ * So, swap them because we are likely to see the same guy again sooner */
+#ifdef DEBUG
+ if(debug) {
+ printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[orig_hash_result] = %d\n",hash_table[orig_hash_result]);
+ printk(KERN_INFO RECENT_NAME ": match(): Collision; r_list[hash_table[orig_hash_result]].hash_entry = %d\n",
+ r_list[hash_table[orig_hash_result]].hash_entry);
+ }
+#endif
+
+ r_list[hash_table[orig_hash_result]].hash_entry = hash_result;
+
+
+ temp = hash_table[orig_hash_result];
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[hash_result] = %d\n",hash_table[hash_result]);
+#endif
+ hash_table[orig_hash_result] = hash_table[hash_result];
+ hash_table[hash_result] = temp;
+ temp = hash_result;
+ hash_result = orig_hash_result;
+ orig_hash_result = temp;
+ time_info[r_list[hash_table[orig_hash_result]].time_pos].position = hash_table[orig_hash_result];
+ if(hash_table[hash_result] != -1) {
+ r_list[hash_table[hash_result]].hash_entry = hash_result;
+ time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
+ }
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision handled.\n");
+#endif
+ }
+
+ if(hash_table[hash_result] == -1) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): New table entry. (hr: %d,ha: %u)\n",
+ hash_result, addr);
+#endif
+
+ /* New item found and IPT_RECENT_SET, so we need to add it */
+ location = time_info[curr_table->time_pos].position;
+ hash_table[r_list[location].hash_entry] = -1;
+ hash_table[hash_result] = location;
+ memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ r_list[location].time_pos = curr_table->time_pos;
+ r_list[location].addr = addr;
+ r_list[location].ttl = ttl;
+ r_list[location].last_seen = now;
+ r_list[location].oldest_pkt = 1;
+ r_list[location].last_pkts[0] = now;
+ r_list[location].hash_entry = hash_result;
+ time_info[curr_table->time_pos].time = r_list[location].last_seen;
+ curr_table->time_pos = (curr_table->time_pos + 1) % ip_list_tot;
+
+ ans = !info->invert;
+ } else {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): Existing table entry. (hr: %d,ha: %u)\n",
+ hash_result,
+ addr);
+#endif
+
+ /* Existing item found */
+ location = hash_table[hash_result];
+ /* We have a match on address, now to make sure it meets all requirements for a
+ * full match. */
+ if(info->check_set & IPT_RECENT_CHECK || info->check_set & IPT_RECENT_UPDATE) {
+ if(!info->seconds && !info->hit_count) ans = !info->invert; else ans = info->invert;
+ if(info->seconds && !info->hit_count) {
+ if(time_before_eq(now,r_list[location].last_seen+info->seconds*HZ)) ans = !info->invert; else ans = info->invert;
+ }
+ if(info->seconds && info->hit_count) {
+ for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
+ if(time_before_eq(now,r_list[location].last_pkts[pkt_count]+info->seconds*HZ)) hits_found++;
+ }
+ if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
+ }
+ if(info->hit_count && !info->seconds) {
+ for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
+ if(r_list[location].last_pkts[pkt_count] == 0) break;
+ hits_found++;
+ }
+ if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
+ }
+ }
+#ifdef DEBUG
+ if(debug) {
+ if(ans)
+ printk(KERN_INFO RECENT_NAME ": match(): match addr: %u\n",addr);
+ else
+ printk(KERN_INFO RECENT_NAME ": match(): no match addr: %u\n",addr);
+ }
+#endif
+
+ /* If and only if we have been asked to SET, or to UPDATE (on match) do we add the
+ * current timestamp to the last_seen. */
+ if((info->check_set & IPT_RECENT_SET && (ans = !info->invert)) || (info->check_set & IPT_RECENT_UPDATE && ans)) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): SET or UPDATE; updating time info.\n");
+#endif
+ /* Have to update our time info */
+ time_loc = r_list[location].time_pos;
+ time_info[time_loc].time = now;
+ time_info[time_loc].position = location;
+ while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
+ time_temp = time_info[time_loc].time;
+ time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
+ time_info[(time_loc+1)%ip_list_tot].time = time_temp;
+ time_temp = time_info[time_loc].position;
+ time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
+ time_info[(time_loc+1)%ip_list_tot].position = time_temp;
+ r_list[time_info[time_loc].position].time_pos = time_loc;
+ r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
+ time_loc = (time_loc+1) % ip_list_tot;
+ }
+ r_list[location].time_pos = time_loc;
+ r_list[location].ttl = ttl;
+ r_list[location].last_pkts[r_list[location].oldest_pkt] = now;
+ r_list[location].oldest_pkt = ++r_list[location].oldest_pkt % ip_pkt_list_tot;
+ r_list[location].last_seen = now;
+ }
+ /* If we have been asked to remove the entry from the list, just set it to 0 */
+ if(info->check_set & IPT_RECENT_REMOVE) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; clearing entry (or: %d, hr: %d).\n",orig_hash_result,hash_result);
+#endif
+ /* Check if this is part of a collision chain */
+ while(hash_table[(orig_hash_result+1) % ip_list_hash_size] != -1) {
+ orig_hash_result++;
+ if(hash_func(r_list[hash_table[orig_hash_result]].addr,ip_list_hash_size) == hash_result) {
+ /* Found collision chain, how deep does this rabbit hole go? */
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; found collision chain.\n");
+#endif
+ end_collision_chain = orig_hash_result;
+ }
+ }
+ if(end_collision_chain != -1) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; part of collision chain, moving to end.\n");
+#endif
+ /* Part of a collision chain, swap it with the end of the chain
+ * before removing. */
+ r_list[hash_table[end_collision_chain]].hash_entry = hash_result;
+ temp = hash_table[end_collision_chain];
+ hash_table[end_collision_chain] = hash_table[hash_result];
+ hash_table[hash_result] = temp;
+ time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
+ hash_result = end_collision_chain;
+ r_list[hash_table[hash_result]].hash_entry = hash_result;
+ time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
+ }
+ location = hash_table[hash_result];
+ hash_table[r_list[location].hash_entry] = -1;
+ time_loc = r_list[location].time_pos;
+ time_info[time_loc].time = 0;
+ time_info[time_loc].position = location;
+ while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
+ time_temp = time_info[time_loc].time;
+ time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
+ time_info[(time_loc+1)%ip_list_tot].time = time_temp;
+ time_temp = time_info[time_loc].position;
+ time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
+ time_info[(time_loc+1)%ip_list_tot].position = time_temp;
+ r_list[time_info[time_loc].position].time_pos = time_loc;
+ r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
+ time_loc = (time_loc+1) % ip_list_tot;
+ }
+ r_list[location].time_pos = time_loc;
+ r_list[location].last_seen = 0;
+ r_list[location].addr = 0;
+ r_list[location].ttl = 0;
+ memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ r_list[location].oldest_pkt = 0;
+ ans = !info->invert;
+ }
+ spin_unlock_bh(&curr_table->list_lock);
+ return ans;
+ }
+
+ spin_unlock_bh(&curr_table->list_lock);
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": match() left.\n");
+#endif
+ return ans;
+}
+
+/* This function is to verify that the rule given during the userspace iptables
+ * command is correct.
+ * If the command is valid then we check if the table name referred to by the
+ * rule exists, if not it is created.
+ */
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ int flag = 0, c;
+ u_int32_t *hold;
+ const struct ipt_recent_info *info = matchinfo;
+ struct recent_ip_tables *curr_table, *find_table, *last_table;
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
+#endif
+
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return 0;
+
+ /* seconds and hit_count only valid for CHECK/UPDATE */
+ if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; }
+ if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; }
+ if(info->check_set & IPT_RECENT_CHECK) flag++;
+ if(info->check_set & IPT_RECENT_UPDATE) flag++;
+
+ /* One and only one of these should ever be set */
+ if(flag != 1) return 0;
+
+ /* Name must be set to something */
+ if(!info->name || !info->name[0]) return 0;
+
+ /* Things look good, create a list for this if it does not exist */
+ /* Lock the linked list while we play with it */
+ spin_lock_bh(&recent_lock);
+
+ /* Look for an entry with this name already created */
+ /* Finds the end of the list and the entry before the end if current name does not exist */
+ find_table = r_tables;
+ while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
+
+ /* If a table already exists just increment the count on that table and return */
+ if(find_table) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), incrementing count.\n",info->name);
+#endif
+ find_table->count++;
+ spin_unlock_bh(&recent_lock);
+ return 1;
+ }
+
+ spin_unlock_bh(&recent_lock);
+
+ /* Table with this name not found */
+ /* Allocate memory for new linked list item */
+
+#ifdef DEBUG
+ if(debug) {
+ printk(KERN_INFO RECENT_NAME ": checkentry: no table found (%s)\n",info->name);
+ printk(KERN_INFO RECENT_NAME ": checkentry: Allocationg %d for link-list entry.\n",sizeof(struct recent_ip_tables));
+ }
+#endif
+
+ curr_table = vmalloc(sizeof(struct recent_ip_tables));
+ if(curr_table == NULL) return -ENOMEM;
+
+ curr_table->list_lock = SPIN_LOCK_UNLOCKED;
+ curr_table->next = NULL;
+ curr_table->count = 1;
+ curr_table->time_pos = 0;
+ strncpy(curr_table->name,info->name,IPT_RECENT_NAME_LEN);
+ curr_table->name[IPT_RECENT_NAME_LEN-1] = '\0';
+
+ /* Allocate memory for this table and the list of packets in each entry. */
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for table (%s).\n",
+ sizeof(struct recent_ip_list)*ip_list_tot,
+ info->name);
+#endif
+
+ curr_table->table = vmalloc(sizeof(struct recent_ip_list)*ip_list_tot);
+ if(curr_table->table == NULL) { vfree(curr_table); return -ENOMEM; }
+ memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for pkt_list.\n",
+ sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+#endif
+
+ hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
+#endif
+ if(hold == NULL) {
+ printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for pkt_list.\n");
+ vfree(curr_table->table);
+ vfree(curr_table);
+ return -ENOMEM;
+ }
+ for(c = 0; c < ip_list_tot; c++) {
+ curr_table->table[c].last_pkts = hold + c*ip_pkt_list_tot;
+ }
+
+ /* Allocate memory for the hash table */
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for hash_table.\n",
+ sizeof(int)*ip_list_hash_size);
+#endif
+
+ curr_table->hash_table = vmalloc(sizeof(int)*ip_list_hash_size);
+ if(!curr_table->hash_table) {
+ printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for hash_table.\n");
+ vfree(hold);
+ vfree(curr_table->table);
+ vfree(curr_table);
+ return -ENOMEM;
+ }
+
+ for(c = 0; c < ip_list_hash_size; c++) {
+ curr_table->hash_table[c] = -1;
+ }
+
+ /* Allocate memory for the time info */
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for time_info.\n",
+ sizeof(struct time_info_list)*ip_list_tot);
+#endif
+
+ curr_table->time_info = vmalloc(sizeof(struct time_info_list)*ip_list_tot);
+ if(!curr_table->time_info) {
+ printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for time_info.\n");
+ vfree(curr_table->hash_table);
+ vfree(hold);
+ vfree(curr_table->table);
+ vfree(curr_table);
+ return -ENOMEM;
+ }
+ for(c = 0; c < ip_list_tot; c++) {
+ curr_table->time_info[c].position = c;
+ curr_table->time_info[c].time = 0;
+ }
+
+ /* Put the new table in place */
+ spin_lock_bh(&recent_lock);
+ find_table = r_tables;
+ while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
+
+ /* If a table already exists just increment the count on that table and return */
+ if(find_table) {
+ find_table->count++;
+ spin_unlock_bh(&recent_lock);
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), created by other process.\n",info->name);
+#endif
+ vfree(curr_table->time_info);
+ vfree(curr_table->hash_table);
+ vfree(hold);
+ vfree(curr_table->table);
+ vfree(curr_table);
+ return 1;
+ }
+ if(!last_table) r_tables = curr_table; else last_table->next = curr_table;
+
+ spin_unlock_bh(&recent_lock);
+
+#ifdef CONFIG_PROC_FS
+ /* Create our proc 'status' entry. */
+ curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent);
+ if (!curr_table->status_proc) {
+ printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n");
+ /* Destroy the created table */
+ spin_lock_bh(&recent_lock);
+ last_table = NULL;
+ curr_table = r_tables;
+ if(!curr_table) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, no tables.\n");
+#endif
+ spin_unlock_bh(&recent_lock);
+ return -ENOMEM;
+ }
+ while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
+ if(!curr_table) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, table already destroyed.\n");
+#endif
+ spin_unlock_bh(&recent_lock);
+ return -ENOMEM;
+ }
+ if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
+ spin_unlock_bh(&recent_lock);
+ vfree(curr_table->time_info);
+ vfree(curr_table->hash_table);
+ vfree(hold);
+ vfree(curr_table->table);
+ vfree(curr_table);
+ return -ENOMEM;
+ }
+
+ curr_table->status_proc->owner = THIS_MODULE;
+ curr_table->status_proc->data = curr_table;
+ wmb();
+ curr_table->status_proc->read_proc = ip_recent_get_info;
+ curr_table->status_proc->write_proc = ip_recent_ctrl;
+#endif /* CONFIG_PROC_FS */
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() left.\n");
+#endif
+
+ return 1;
+}
+
+/* This function is called in the event that a rule matching this module is
+ * removed.
+ * When this happens we need to check if there are no other rules matching
+ * the table given. If that is the case then we remove the table and clean
+ * up its memory.
+ */
+static void
+destroy(void *matchinfo, unsigned int matchsize)
+{
+ const struct ipt_recent_info *info = matchinfo;
+ struct recent_ip_tables *curr_table, *last_table;
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": destroy() entered.\n");
+#endif
+
+ if(matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return;
+
+ /* Lock the linked list while we play with it */
+ spin_lock_bh(&recent_lock);
+
+ /* Look for an entry with this name already created */
+ /* Finds the end of the list and the entry before the end if current name does not exist */
+ last_table = NULL;
+ curr_table = r_tables;
+ if(!curr_table) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": destroy() No tables found, leaving.\n");
+#endif
+ spin_unlock_bh(&recent_lock);
+ return;
+ }
+ while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
+
+ /* If a table does not exist then do nothing and return */
+ if(!curr_table) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table not found, leaving.\n");
+#endif
+ spin_unlock_bh(&recent_lock);
+ return;
+ }
+
+ curr_table->count--;
+
+ /* If count is still non-zero then there are still rules referenceing it so we do nothing */
+ if(curr_table->count) {
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, non-zero count, leaving.\n");
+#endif
+ spin_unlock_bh(&recent_lock);
+ return;
+ }
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, zero count, removing.\n");
+#endif
+
+ /* Count must be zero so we remove this table from the list */
+ if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
+
+ spin_unlock_bh(&recent_lock);
+
+ /* lock to make sure any late-runners still using this after we removed it from
+ * the list finish up then remove everything */
+ spin_lock_bh(&curr_table->list_lock);
+ spin_unlock_bh(&curr_table->list_lock);
+
+#ifdef CONFIG_PROC_FS
+ if(curr_table->status_proc) remove_proc_entry(curr_table->name,proc_net_ipt_recent);
+#endif /* CONFIG_PROC_FS */
+ vfree(curr_table->table[0].last_pkts);
+ vfree(curr_table->table);
+ vfree(curr_table->hash_table);
+ vfree(curr_table->time_info);
+ vfree(curr_table);
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": destroy() left.\n");
+#endif
+
+ return;
+}
+
+/* This is the structure we pass to ipt_register to register our
+ * module with iptables.
+ */
+static struct ipt_match recent_match = {
+ .name = "recent",
+ .match = &match,
+ .checkentry = &checkentry,
+ .destroy = &destroy,
+ .me = THIS_MODULE
+};
+
+/* Kernel module initialization. */
+static int __init init(void)
+{
+ int count;
+
+ printk(version);
+ proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
+ if(!proc_net_ipt_recent) return -ENOMEM;
+
+ if(ip_list_hash_size && ip_list_hash_size <= ip_list_tot) {
+ printk(KERN_WARNING RECENT_NAME ": ip_list_hash_size too small, resetting to default.\n");
+ ip_list_hash_size = 0;
+ }
+
+ if(!ip_list_hash_size) {
+ ip_list_hash_size = ip_list_tot*3;
+ count = 2*2;
+ while(ip_list_hash_size > count) count = count*2;
+ ip_list_hash_size = count;
+ }
+
+#ifdef DEBUG
+ if(debug) printk(KERN_INFO RECENT_NAME ": ip_list_hash_size: %d\n",ip_list_hash_size);
+#endif
+
+ return ipt_register_match(&recent_match);
+}
+
+/* Kernel module destruction. */
+static void __exit fini(void)
+{
+ ipt_unregister_match(&recent_match);
+
+ remove_proc_entry("ipt_recent",proc_net);
+}
+
+/* Register our module with the kernel. */
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_string.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_string.c
new file mode 100644
index 00000000..a18b89d0
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_string.c
@@ -0,0 +1,218 @@
+/* Kernel module to match a string into a packet.
+ *
+ * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
+ *
+ * ChangeLog
+ * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
+ * Fixed SMP re-entrancy problem using per-cpu data areas
+ * for the skip/shift tables.
+ * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
+ * Fixed kernel panic, due to overrunning boyer moore string
+ * tables. Also slightly tweaked heuristic for deciding what
+ * search algo to use.
+ * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
+ * Implemented Boyer Moore Sublinear search algorithm
+ * alongside the existing linear search based on memcmp().
+ * Also a quick check to decide which method to use on a per
+ * packet basis.
+ */
+
+#include <linux/smp.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/file.h>
+#include <net/sock.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_string.h>
+
+MODULE_LICENSE("GPL");
+
+struct string_per_cpu {
+ int *skip;
+ int *shift;
+ int *len;
+};
+
+struct string_per_cpu *bm_string_data=NULL;
+
+/* Boyer Moore Sublinear string search - VERY FAST */
+char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
+{
+ int M1, right_end, sk, sh;
+ int ended, j, i;
+
+ int *skip, *shift, *len;
+
+ /* use data suitable for this CPU */
+ shift=bm_string_data[smp_processor_id()].shift;
+ skip=bm_string_data[smp_processor_id()].skip;
+ len=bm_string_data[smp_processor_id()].len;
+
+ /* Setup skip/shift tables */
+ M1 = right_end = needle_len-1;
+ for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
+ for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
+
+ for (i = 1; i < needle_len; i++) {
+ for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
+ len[i] = j;
+ }
+
+ shift[0] = 1;
+ for (i = 1; i < needle_len; i++) shift[i] = needle_len;
+ for (i = M1; i > 0; i--) shift[len[i]] = i;
+ ended = 0;
+
+ for (i = 0; i < needle_len; i++) {
+ if (len[i] == M1 - i) ended = i;
+ if (ended) shift[i] = ended;
+ }
+
+ /* Do the search*/
+ while (right_end < haystack_len)
+ {
+ for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
+ if (i == needle_len) {
+ return haystack+(right_end - M1);
+ }
+
+ sk = skip[haystack[right_end - i]];
+ sh = shift[i];
+ right_end = max(right_end - i + sk, right_end + sh);
+ }
+
+ return NULL;
+}
+
+/* Linear string search based on memcmp() */
+char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
+{
+ char *k = haystack + (haystack_len-needle_len);
+ char *t = haystack;
+
+ while ( t <= k ) {
+ if (memcmp(t, needle, needle_len) == 0)
+ return t;
+ t++;
+ }
+
+ return NULL;
+}
+
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_string_info *info = matchinfo;
+ struct iphdr *ip = skb->nh.iph;
+ int hlen, nlen;
+ char *needle, *haystack;
+ proc_ipt_search search=search_linear;
+
+ if ( !ip ) return 0;
+
+ /* get lenghts, and validate them */
+ nlen=info->len;
+ hlen=ntohs(ip->tot_len)-(ip->ihl*4);
+ if ( nlen > hlen ) return 0;
+
+ needle=(char *)&info->string;
+ haystack=(char *)ip+(ip->ihl*4);
+
+ /* The sublinear search comes in to its own
+ * on the larger packets */
+ if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
+ (nlen>IPT_STRING_NEEDLE_THRESH) ) {
+ if ( hlen < BM_MAX_HLEN ) {
+ search=search_sublinear;
+ }else{
+ if (net_ratelimit())
+ printk(KERN_INFO "ipt_string: Packet too big "
+ "to attempt sublinear string search "
+ "(%d bytes)\n", hlen );
+ }
+ }
+
+ return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
+ return 0;
+
+ return 1;
+}
+
+void string_freeup_data(void)
+{
+ int c;
+
+ if ( bm_string_data ) {
+ for(c=0; c<smp_num_cpus; c++) {
+ if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
+ if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
+ if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
+ }
+ kfree(bm_string_data);
+ }
+}
+
+static struct ipt_match string_match
+= { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ int c;
+ size_t tlen;
+ size_t alen;
+
+ tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
+ alen=sizeof(int)*BM_MAX_HLEN;
+
+ /* allocate array of structures */
+ if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
+ return 0;
+ }
+
+ memset(bm_string_data, 0, tlen);
+
+ /* allocate our skip/shift tables */
+ for(c=0; c<smp_num_cpus; c++) {
+ if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
+ goto alloc_fail;
+ if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
+ goto alloc_fail;
+ if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
+ goto alloc_fail;
+ }
+
+ return ipt_register_match(&string_match);
+
+alloc_fail:
+ string_freeup_data();
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&string_match);
+ string_freeup_data();
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_time.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_time.c
index 216098fc..d3484bd9 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ipt_time.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_time.c
@@ -10,6 +10,7 @@
2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
+ 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
*/
#include <linux/module.h>
@@ -19,7 +20,7 @@
#include <linux/time.h>
MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
-MODULE_DESCRIPTION("Match arrival timestamp");
+MODULE_DESCRIPTION("Match arrival timestamp/date");
MODULE_LICENSE("GPL");
struct tm
@@ -53,7 +54,8 @@ match(const struct sk_buff *skb,
{
const struct ipt_time_info *info = matchinfo; /* match info for rule */
struct tm currenttime; /* time human readable */
- unsigned int packet_time;
+ u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
+ u_int16_t packet_time;
struct timeval kerneltimeval;
time_t packet_local_time;
@@ -66,22 +68,21 @@ match(const struct sk_buff *skb,
else
packet_local_time = skb->stamp.tv_sec;
+ /* First we make sure we are in the date start-stop boundaries */
+ if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
+ return 0; /* We are outside the date boundaries */
+
/* Transform the timestamp of the packet, in a human readable form */
localtime(&packet_local_time, &currenttime);
/* check if we match this timestamp, we start by the days... */
- if (!((1 << currenttime.tm_wday) & info->days_match))
+ if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
return 0; /* the day doesn't match */
/* ... check the time now */
- packet_time = (currenttime.tm_hour * 60 * 60) + (currenttime.tm_min * 60) + currenttime.tm_sec;
- if (info->time_start < info->time_stop) {
- if ((packet_time < info->time_start) || (packet_time > info->time_stop))
- return 0;
- } else {
- if ((packet_time < info->time_start) && (packet_time > info->time_stop))
- return 0;
- }
+ packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
+ if ((packet_time < info->time_start) || (packet_time > info->time_stop))
+ return 0;
/* here we match ! */
return 1;
@@ -96,24 +97,25 @@ checkentry(const char *tablename,
{
struct ipt_time_info *info = matchinfo; /* match info for rule */
- /* First, check that we are in the correct hook */
- /* PRE_ROUTING, LOCAL_IN or FROWARD */
+ /* First, check that we are in the correct hooks */
if (hook_mask
& ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
{
printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
return 0;
}
-
- /* always use kerneltime */
+ /* we use the kerneltime if we are in forward or output */
info->kerneltime = 1;
+ if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
+ /* we use the skb time */
+ info->kerneltime = 0;
/* Check the size */
- if (matchsize < IPT_ALIGN(sizeof(struct ipt_time_info)))
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
return 0;
/* Now check the coherence of the data ... */
- if ((info->time_start > 86399) || /* 24*60*60-1 = 86399*/
- (info->time_stop > 86399))
+ if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
+ (info->time_stop > 1439))
{
printk(KERN_WARNING "ipt_time: invalid argument\n");
return 0;
@@ -122,8 +124,12 @@ checkentry(const char *tablename,
return 1;
}
-static struct ipt_match time_match
-= { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
+static struct ipt_match time_match = {
+ .name = "time",
+ .match = match,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
static int __init init(void)
{
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_u32.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_u32.c
new file mode 100644
index 00000000..0c749563
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_u32.c
@@ -0,0 +1,211 @@
+/* Kernel module to match u32 packet content. */
+
+/*
+U32 tests whether quantities of up to 4 bytes extracted from a packet
+have specified values. The specification of what to extract is general
+enough to find data at given offsets from tcp headers or payloads.
+
+ --u32 tests
+ The argument amounts to a program in a small language described below.
+ tests := location = value | tests && location = value
+ value := range | value , range
+ range := number | number : number
+ a single number, n, is interpreted the same as n:n
+ n:m is interpreted as the range of numbers >=n and <=m
+ location := number | location operator number
+ operator := & | << | >> | @
+
+ The operators &, <<, >>, && mean the same as in c. The = is really a set
+ membership operator and the value syntax describes a set. The @ operator
+ is what allows moving to the next header and is described further below.
+
+ *** Until I can find out how to avoid it, there are some artificial limits
+ on the size of the tests:
+ - no more than 10 ='s (and 9 &&'s) in the u32 argument
+ - no more than 10 ranges (and 9 commas) per value
+ - no more than 10 numbers (and 9 operators) per location
+
+ To describe the meaning of location, imagine the following machine that
+ interprets it. There are three registers:
+ A is of type char*, initially the address of the IP header
+ B and C are unsigned 32 bit integers, initially zero
+
+ The instructions are:
+ number B = number;
+ C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
+ &number C = C&number
+ <<number C = C<<number
+ >>number C = C>>number
+ @number A = A+C; then do the instruction number
+ Any access of memory outside [skb->head,skb->end] causes the match to fail.
+ Otherwise the result of the computation is the final value of C.
+
+ Whitespace is allowed but not required in the tests.
+ However the characters that do occur there are likely to require
+ shell quoting, so it's a good idea to enclose the arguments in quotes.
+
+Example:
+ match IP packets with total length >= 256
+ The IP header contains a total length field in bytes 2-3.
+ --u32 "0&0xFFFF=0x100:0xFFFF"
+ read bytes 0-3
+ AND that with FFFF (giving bytes 2-3),
+ and test whether that's in the range [0x100:0xFFFF]
+
+Example: (more realistic, hence more complicated)
+ match icmp packets with icmp type 0
+ First test that it's an icmp packet, true iff byte 9 (protocol) = 1
+ --u32 "6&0xFF=1 && ...
+ read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
+ Next test that it's not a fragment.
+ (If so it might be part of such a packet but we can't always tell.)
+ n.b. This test is generally needed if you want to match anything
+ beyond the IP header.
+ The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
+ packet (not a fragment). Alternatively, you can allow first fragments
+ by only testing the last 5 bits of byte 6.
+ ... 4&0x3FFF=0 && ...
+ Last test: the first byte past the IP header (the type) is 0
+ This is where we have to use the @syntax. The length of the IP header
+ (IHL) in 32 bit words is stored in the right half of byte 0 of the
+ IP header itself.
+ ... 0>>22&0x3C@0>>24=0"
+ The first 0 means read bytes 0-3,
+ >>22 means shift that 22 bits to the right. Shifting 24 bits would give
+ the first byte, so only 22 bits is four times that plus a few more bits.
+ &3C then eliminates the two extra bits on the right and the first four
+ bits of the first byte.
+ For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
+ In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
+ >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
+ @ means to use this number as a new offset into the packet, and read
+ four bytes starting from there. This is the first 4 bytes of the icmp
+ payload, of which byte 0 is the icmp type. Therefore we simply shift
+ the value 24 to the right to throw out all but the first byte and compare
+ the result with 0.
+
+Example:
+ tcp payload bytes 8-12 is any of 1, 2, 5 or 8
+ First we test that the packet is a tcp packet (similar to icmp).
+ --u32 "6&0xFF=6 && ...
+ Next, test that it's not a fragment (same as above).
+ ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
+ 0>>22&3C as above computes the number of bytes in the IP header.
+ @ makes this the new offset into the packet, which is the start of the
+ tcp header. The length of the tcp header (again in 32 bit words) is
+ the left half of byte 12 of the tcp header. The 12>>26&3C
+ computes this length in bytes (similar to the IP header before).
+ @ makes this the new offset, which is the start of the tcp payload.
+ Finally 8 reads bytes 8-12 of the payload and = checks whether the
+ result is any of 1, 2, 5 or 8
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter_ipv4/ipt_u32.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+/* #include <asm-i386/timex.h> for timing */
+
+MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
+MODULE_DESCRIPTION("IP tables u32 matching module");
+MODULE_LICENSE("GPL");
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_u32 *data = matchinfo;
+ int testind, i;
+ unsigned char* origbase = (char*)skb->nh.iph;
+ unsigned char* base = origbase;
+ unsigned char* head = skb->head;
+ unsigned char* end = skb->end;
+ int nnums, nvals;
+ u_int32_t pos, val;
+ /* unsigned long long cycles1, cycles2, cycles3, cycles4;
+ cycles1 = get_cycles(); */
+
+ for (testind=0; testind < data->ntests; testind++) {
+ base = origbase; /* reset for each test */
+ pos = data->tests[testind].location[0].number;
+ if (base+pos+3 > end || base+pos < head)
+ return 0;
+ val = (base[pos]<<24) + (base[pos+1]<<16) +
+ (base[pos+2]<<8) + base[pos+3];
+ nnums = data->tests[testind].nnums;
+ for (i=1; i < nnums; i++) {
+ u_int32_t number = data->tests[testind].location[i].number;
+ switch (data->tests[testind].location[i].nextop) {
+ case IPT_U32_AND:
+ val = val & number;
+ break;
+ case IPT_U32_LEFTSH:
+ val = val << number;
+ break;
+ case IPT_U32_RIGHTSH:
+ val = val >> number;
+ break;
+ case IPT_U32_AT:
+ base = base + val;
+ pos = number;
+ if (base+pos+3 > end || base+pos < head)
+ return 0;
+ val = (base[pos]<<24) + (base[pos+1]<<16) +
+ (base[pos+2]<<8) + base[pos+3];
+ break;
+ }
+ }
+ nvals = data->tests[testind].nvalues;
+ for (i=0; i < nvals; i++) {
+ if ((data->tests[testind].value[i].min <= val) &&
+ (val <= data->tests[testind].value[i].max)) {
+ break;
+ }
+ }
+ if (i >= data->tests[testind].nvalues) {
+ /* cycles2 = get_cycles();
+ printk("failed %d in %d cycles\n", testind,
+ cycles2-cycles1); */
+ return 0;
+ }
+ }
+ /* cycles2 = get_cycles();
+ printk("succeeded in %d cycles\n", cycles2-cycles1); */
+ return 1;
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
+ return 0;
+ return 1;
+}
+
+static struct ipt_match u32_match
+= { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ipt_register_match(&u32_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&u32_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_web.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_web.c
new file mode 100644
index 00000000..c32a860a
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_web.c
@@ -0,0 +1,246 @@
+/*
+
+ web (experimental)
+ HTTP client request match
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2 or later.
+
+*/
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_web.h>
+
+MODULE_AUTHOR("Jonathan Zarate");
+MODULE_DESCRIPTION("HTTP client request match (experimental)");
+MODULE_LICENSE("GPL");
+
+
+// #define LOG printk
+#define LOG(...) do { } while (0);
+
+
+static int find(const char *data, const char *tail, const char *text)
+{
+ int n, o;
+ int dlen;
+ const char *p, *e;
+
+ while ((data < tail) && (*data == ' ')) ++data;
+ while ((tail > data) && (*(tail - 1) == ' ')) --tail;
+
+ dlen = tail - data;
+
+#if 0
+ {
+ char tmp[128];
+ int z;
+ z = sizeof(tmp) - 1;
+ if (z > dlen) z = dlen;
+ memcpy(tmp, data, z);
+ tmp[z] = 0;
+ LOG(KERN_INFO "find in '%s'\n", tmp);
+ }
+#endif
+
+ // 012345
+ // text
+ // ^text
+ // text$
+ // ^text$
+ // 012345
+
+ while (*text) {
+ n = o = strlen(text);
+ if (*text == '^') {
+ --n;
+ if (*(text + n) == '$') {
+ // exact
+ --n;
+ if ((dlen == n) && (memcmp(data, text + 1, n) == 0)) {
+ LOG(KERN_INFO "matched %s\n", text);
+ return 1;
+ }
+ }
+ else {
+ // begins with
+ if ((dlen >= n) && (memcmp(data, text + 1, n) == 0)) {
+ LOG(KERN_INFO "matched %s\n", text);
+ return 1;
+ }
+ }
+ }
+ else if (*(text + n - 1) == '$') {
+ // ends with
+ --n;
+ if (memcmp(tail - n, text, n) == 0) {
+ LOG(KERN_INFO "matched %s\n", text);
+ return 1;
+ }
+ }
+ else {
+ // contains
+ p = data;
+ e = tail - n;
+ while (p <= e) {
+ if (memcmp(p, text, n) == 0) {
+ LOG(KERN_INFO "matched %s\n", text);
+ return 1;
+ }
+ ++p;
+ }
+ }
+
+ text += o + 1;
+ }
+ return 0;
+}
+
+static inline const char *findend(const char *data, const char *tail, int min)
+{
+ int n = tail - data;
+ if (n >= min) {
+ while (data < tail) {
+ if (*data == '\r') return data;
+ ++data;
+ }
+ }
+ return NULL;
+}
+
+static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
+ const void *matchinfo, int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+ const struct ipt_web_info *info;
+ const struct tcphdr *tcph;
+ const char *data;
+ const char *tail;
+ const char *p, *q;
+ int doff, dlen;
+
+ info = matchinfo;
+
+ if (offset != 0) return info->invert;
+
+ tcph = hdr;
+ doff = (tcph->doff * 4);
+ data = (char *)tcph + doff;
+ dlen = datalen - doff;
+
+#if 0
+ printk(KERN_INFO "datalen=%u dlen=%d doff=%d\n", datalen, dlen, doff);
+ char tmp[16];
+ memcpy(tmp, data, sizeof(tmp));
+ tmp[sizeof(tmp) - 1] = 0;
+ printk(KERN_INFO "[%s]\n", tmp);
+#endif
+
+ // POST / HTTP/1.0$$$$
+ // GET / HTTP/1.0$$$$
+ // 1234567890123456789
+ if (dlen < 18) return info->invert;
+
+ // "GET " or "POST"
+ __u32 sig = *(__u32 *)data;
+ if ((sig != __constant_htonl(0x47455420)) && (sig != __constant_htonl(0x504f5354))) {
+ return info->invert;
+ }
+
+ tail = data + dlen;
+ if (dlen > 1024) {
+ dlen = 1024;
+ tail = data + 1024;
+ }
+
+
+ // POST / HTTP/1.0$$$$
+ // GET / HTTP/1.0$$$$ -- minimum
+ // 0123456789012345678
+ // 9876543210
+ if (((p = findend(data + 14, tail, 18)) == NULL) || (memcmp(p - 9, " HTTP/", 6) != 0))
+ return info->invert;
+
+#if 0
+ {
+ const char *qq = info->text;
+ while (*qq) {
+ printk(KERN_INFO "text=%s\n", qq);
+ qq += strlen(qq) + 1;
+ }
+ }
+#endif
+
+ switch (info->mode) {
+ case IPT_WEB_HTTP:
+ return !info->invert;
+ case IPT_WEB_HORE:
+ // entire request line, else host line
+ if (find(data + 4, p - 9, info->text)) return !info->invert;
+ break;
+ case IPT_WEB_PATH:
+ // left side of '?' or entire line
+ q = data += 4;
+ p -= 9;
+ while ((q < p) && (*q != '?')) ++q;
+ return find(data, q, info->text) ^ info->invert;
+ case IPT_WEB_QUERY:
+ // right side of '?' or none
+ q = data + 4;
+ p -= 9;
+ while ((q < p) && (*q != '?')) ++q;
+ if (q >= p) return info->invert;
+ return find(q + 1, p, info->text) ^ info->invert;
+ case IPT_WEB_RURI:
+ // entire request line
+ return find(data + 4, p - 9, info->text) ^ info->invert;
+ default:
+ // shutup compiler
+ break;
+ }
+
+ // else, IPT_WEB_HOST
+
+ while (1) {
+ data = p + 2; // skip previous \r\n
+ p = findend(data, tail, 8); // p = current line's \r
+ if (p == NULL) return 0;
+
+#if 0
+ char tmp[64];
+ memcpy(tmp, data, 32);
+ tmp[32] = 0;
+ printk(KERN_INFO "data=[%s]\n", tmp);
+#endif
+
+ if (memcmp(data, "Host: ", 6) == 0)
+ return find(data + 6, p, info->text) ^ info->invert;
+ }
+
+ return !info->invert;
+}
+
+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
+ unsigned int matchsize, unsigned int hook_mask)
+{
+ return (matchsize == IPT_ALIGN(sizeof(struct ipt_web_info)));
+}
+
+
+static struct ipt_match web_match
+= { { NULL, NULL }, "web", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+// LOG(KERN_INFO "ipt_web <" __DATE__ " " __TIME__ "> loaded\n");
+ return ipt_register_match(&web_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&web_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.c b/release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.c
new file mode 100644
index 00000000..31ef35b9
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.c
@@ -0,0 +1,1195 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ * @(#)regexp.c 1.3 of 18 April 87
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions. Serious changes in
+ * regular-expression syntax might require a total rethink.
+ *
+ * This code was modified by Ethan Sommer to work within the kernel
+ * (it now uses kmalloc etc..)
+ *
+ * Modified slightly by Matthew Strait to use more modern C.
+ */
+
+#include "regexp.h"
+#include "regmagic.h"
+
+/* added by ethan and matt. Lets it work in both kernel and user space.
+(So iptables can use it, for instance.) Yea, it goes both ways... */
+#if __KERNEL__
+ #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
+#else
+ #define printk(format,args...) printf(format,##args)
+#endif
+
+void regerror(char * s)
+{
+ printk("<3>Regexp: %s\n", s);
+ /* NOTREACHED */
+}
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases. They are:
+ *
+ * regstart char that must begin a match; '\0' if none obvious
+ * reganch is the match anchored (at beginning-of-line only)?
+ * regmust string (pointer into program) that match must include, or NULL
+ * regmlen length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot. Regmust permits fast rejection
+ * of lines that cannot possibly match. The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program". This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology). Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives. (Here we
+ * have one of the subtle syntax dependencies: an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.) The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM. In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure: the tail of the branch connects
+ * to the thing following the set of BRANCHes.) The opcodes are:
+ */
+
+/* definition number opnd? meaning */
+#define END 0 /* no End of program. */
+#define BOL 1 /* no Match "" at beginning of line. */
+#define EOL 2 /* no Match "" at end of line. */
+#define ANY 3 /* no Match any one character. */
+#define ANYOF 4 /* str Match any character in this string. */
+#define ANYBUT 5 /* str Match any character not in this string. */
+#define BRANCH 6 /* node Match this alternative, or the next... */
+#define BACK 7 /* no Match "", "next" ptr points backward. */
+#define EXACTLY 8 /* str Match this string. */
+#define NOTHING 9 /* no Match empty string. */
+#define STAR 10 /* node Match this (simple) thing 0 or more times. */
+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
+#define OPEN 20 /* no Mark this point in input as start of #n. */
+ /* OPEN+1 is number 1, etc. */
+#define CLOSE 30 /* no Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH The set of branches constituting a single choice are hooked
+ * together with their "next" pointers, since precedence prevents
+ * anything being concatenated to any individual branch. The
+ * "next" pointer of the last BRANCH in a choice points to the
+ * thing following the whole choice. This is also where the
+ * final "next" pointer of each individual branch points; each
+ * branch starts with the operand node of a BRANCH node.
+ *
+ * BACK Normal "next" pointers all implicitly point forward; BACK
+ * exists to make loop structures possible.
+ *
+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+ * BRANCH structures using BACK. Simple cases (one character
+ * per match) are implemented with STAR and PLUS for speed
+ * and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE ...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node. (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define OP(p) (*(p))
+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define OPERAND(p) ((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+#define FAIL(m) { regerror(m); return(NULL); }
+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
+#define META "^$.[()|?+*\\"
+
+/*
+ * Flags to be passed up and down.
+ */
+#define HASWIDTH 01 /* Known never to match null string. */
+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
+#define SPSTART 04 /* Starts with * or +. */
+#define WORST 0 /* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+static char *regparse; /* Input-scan pointer. */
+static int regnpar; /* () count. */
+static char regdummy;
+static char *regcode; /* Code-emit pointer; &regdummy = don't. */
+static long regsize; /* Code size. */
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define STATIC static
+#endif
+STATIC char *reg(int paren,int *flagp);
+STATIC char *regbranch(int *flagp);
+STATIC char *regpiece(int *flagp);
+STATIC char *regatom(int *flagp);
+STATIC char *regnode(char op);
+STATIC char *regnext(char *p);
+STATIC void regc(char b);
+STATIC void reginsert(char op, char *opnd);
+STATIC void regtail(char *p, char *val);
+STATIC void regoptail(char *p, char *val);
+
+
+__kernel_size_t my_strcspn(const char *s1,const char *s2)
+{
+ char *scan1;
+ char *scan2;
+ int count;
+
+ count = 0;
+ for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {
+ for (scan2 = (char *)s2; *scan2 != '\0';) /* ++ moved down. */
+ if (*scan1 == *scan2++)
+ return(count);
+ count++;
+ }
+ return(count);
+}
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code. So we cheat: we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it. (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(char *exp,int *patternsize)
+{
+ register regexp *r;
+ register char *scan;
+ register char *longest;
+ register int len;
+ int flags;
+ /* commented out by ethan
+ extern char *malloc();
+ */
+
+ if (exp == NULL)
+ FAIL("NULL argument");
+
+ /* First pass: determine size, legality. */
+ regparse = exp;
+ regnpar = 1;
+ regsize = 0L;
+ regcode = &regdummy;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Small enough for pointer-storage convention? */
+ if (regsize >= 32767L) /* Probably could be 65535L. */
+ FAIL("regexp too big");
+
+ /* Allocate space. */
+ *patternsize=sizeof(regexp) + (unsigned)regsize;
+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
+ if (r == NULL)
+ FAIL("out of space");
+
+ /* Second pass: emit code. */
+ regparse = exp;
+ regnpar = 1;
+ regcode = r->program;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Dig out information for optimizations. */
+ r->regstart = '\0'; /* Worst-case defaults. */
+ r->reganch = 0;
+ r->regmust = NULL;
+ r->regmlen = 0;
+ scan = r->program+1; /* First BRANCH. */
+ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
+ scan = OPERAND(scan);
+
+ /* Starting-point info. */
+ if (OP(scan) == EXACTLY)
+ r->regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ r->reganch++;
+
+ /*
+ * If there's something expensive in the r.e., find the
+ * longest literal string that must appear and make it the
+ * regmust. Resolve ties in favor of later strings, since
+ * the regstart check works with the beginning of the r.e.
+ * and avoiding duplication strengthens checking. Not a
+ * strong reason, but sufficient in the absence of others.
+ */
+ if (flags&SPSTART) {
+ longest = NULL;
+ len = 0;
+ for (; scan != NULL; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+ longest = OPERAND(scan);
+ len = strlen(OPERAND(scan));
+ }
+ r->regmust = longest;
+ r->regmlen = len;
+ }
+ }
+
+ return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(int paren, int *flagp /* Parenthesized? */ )
+{
+ register char *ret;
+ register char *br;
+ register char *ender;
+ register int parno = 0; /* 0 makes gcc happy */
+ int flags;
+
+ *flagp = HASWIDTH; /* Tentatively. */
+
+ /* Make an OPEN node, if parenthesized. */
+ if (paren) {
+ if (regnpar >= NSUBEXP)
+ FAIL("too many ()");
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(OPEN+parno);
+ } else
+ ret = NULL;
+
+ /* Pick up the branches, linking them together. */
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ if (ret != NULL)
+ regtail(ret, br); /* OPEN -> first. */
+ else
+ ret = br;
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ while (*regparse == '|') {
+ regparse++;
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ regtail(ret, br); /* BRANCH -> BRANCH. */
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ }
+
+ /* Make a closing node, and hook it on the end. */
+ ender = regnode((paren) ? CLOSE+parno : END);
+ regtail(ret, ender);
+
+ /* Hook the tails of the branches to the closing node. */
+ for (br = ret; br != NULL; br = regnext(br))
+ regoptail(br, ender);
+
+ /* Check for proper termination. */
+ if (paren && *regparse++ != ')') {
+ FAIL("unmatched ()");
+ } else if (!paren && *regparse != '\0') {
+ if (*regparse == ')') {
+ FAIL("unmatched ()");
+ } else
+ FAIL("junk on end"); /* "Can't happen". */
+ /* NOTREACHED */
+ }
+
+ return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch(int *flagp)
+{
+ register char *ret;
+ register char *chain;
+ register char *latest;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ ret = regnode(BRANCH);
+ chain = NULL;
+ while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+ latest = regpiece(&flags);
+ if (latest == NULL)
+ return(NULL);
+ *flagp |= flags&HASWIDTH;
+ if (chain == NULL) /* First piece. */
+ *flagp |= flags&SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == NULL) /* Loop ran zero times. */
+ (void) regnode(NOTHING);
+
+ return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized: they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece(int *flagp)
+{
+ register char *ret;
+ register char op;
+ register char *next;
+ int flags;
+
+ ret = regatom(&flags);
+ if (ret == NULL)
+ return(NULL);
+
+ op = *regparse;
+ if (!ISMULT(op)) {
+ *flagp = flags;
+ return(ret);
+ }
+
+ if (!(flags&HASWIDTH) && op != '?')
+ FAIL("*+ operand could be empty");
+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+ if (op == '*' && (flags&SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*') {
+ /* Emit x* as (x&|), where & means "self". */
+ reginsert(BRANCH, ret); /* Either x */
+ regoptail(ret, regnode(BACK)); /* and loop */
+ regoptail(ret, ret); /* back */
+ regtail(ret, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '+' && (flags&SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+') {
+ /* Emit x+ as x(&|), where & means "self". */
+ next = regnode(BRANCH); /* Either */
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); /* loop back */
+ regtail(next, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '?') {
+ /* Emit x? as (x|) */
+ reginsert(BRANCH, ret); /* Either x */
+ regtail(ret, regnode(BRANCH)); /* or */
+ next = regnode(NOTHING); /* null. */
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISMULT(*regparse))
+ FAIL("nested *?+");
+
+ return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization: gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run. Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom(int *flagp)
+{
+ register char *ret;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ switch (*regparse++) {
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ case '[': {
+ register int class;
+ register int classend;
+
+ if (*regparse == '^') { /* Complement of range. */
+ ret = regnode(ANYBUT);
+ regparse++;
+ } else
+ ret = regnode(ANYOF);
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+ while (*regparse != '\0' && *regparse != ']') {
+ if (*regparse == '-') {
+ regparse++;
+ if (*regparse == ']' || *regparse == '\0')
+ regc('-');
+ else {
+ class = UCHARAT(regparse-2)+1;
+ classend = UCHARAT(regparse);
+ if (class > classend+1)
+ FAIL("invalid [] range");
+ for (; class <= classend; class++)
+ regc(class);
+ regparse++;
+ }
+ } else
+ regc(*regparse++);
+ }
+ regc('\0');
+ if (*regparse != ']')
+ FAIL("unmatched []");
+ regparse++;
+ *flagp |= HASWIDTH|SIMPLE;
+ }
+ break;
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == NULL)
+ return(NULL);
+ *flagp |= flags&(HASWIDTH|SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case ')':
+ FAIL("internal urp"); /* Supposed to be caught earlier. */
+ break;
+ case '?':
+ case '+':
+ case '*':
+ FAIL("?+* follows nothing");
+ break;
+ case '\\':
+ if (*regparse == '\0')
+ FAIL("trailing \\");
+ ret = regnode(EXACTLY);
+ regc(*regparse++);
+ regc('\0');
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ default: {
+ register int len;
+ register char ender;
+
+ regparse--;
+ len = my_strcspn((const char *)regparse, (const char *)META);
+ if (len <= 0)
+ FAIL("internal disaster");
+ ender = *(regparse+len);
+ if (len > 1 && ISMULT(ender))
+ len--; /* Back off clear of ?+* operand. */
+ *flagp |= HASWIDTH;
+ if (len == 1)
+ *flagp |= SIMPLE;
+ ret = regnode(EXACTLY);
+ while (len > 0) {
+ regc(*regparse++);
+ len--;
+ }
+ regc('\0');
+ }
+ break;
+ }
+
+ return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char * /* Location. */
+regnode(char op)
+{
+ register char *ret;
+ register char *ptr;
+
+ ret = regcode;
+ if (ret == &regdummy) {
+ regsize += 3;
+ return(ret);
+ }
+
+ ptr = ret;
+ *ptr++ = op;
+ *ptr++ = '\0'; /* Null "next" pointer. */
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc(char b)
+{
+ if (regcode != &regdummy)
+ *regcode++ = b;
+ else
+ regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(char op, char* opnd)
+{
+ register char *src;
+ register char *dst;
+ register char *place;
+
+ if (regcode == &regdummy) {
+ regsize += 3;
+ return;
+ }
+
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; /* Op node, where operand used to be. */
+ *place++ = op;
+ *place++ = '\0';
+ *place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(char *p, char *val)
+{
+ register char *scan;
+ register char *temp;
+ register int offset;
+
+ if (p == &regdummy)
+ return;
+
+ /* Find last node. */
+ scan = p;
+ for (;;) {
+ temp = regnext(scan);
+ if (temp == NULL)
+ break;
+ scan = temp;
+ }
+
+ if (OP(scan) == BACK)
+ offset = scan - val;
+ else
+ offset = val - scan;
+ *(scan+1) = (offset>>8)&0377;
+ *(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void
+regoptail(char *p, char *val)
+{
+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+ if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+ return;
+ regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+static char *reginput; /* String-input pointer. */
+static char *regbol; /* Beginning of input, for ^ check. */
+static char **regstartp; /* Pointer to startp array. */
+static char **regendp; /* Ditto for endp. */
+
+/*
+ * Forwards.
+ */
+STATIC int regtry(regexp *prog, char *string);
+STATIC int regmatch(char *prog);
+STATIC int regrepeat(char *p);
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop(char *op);
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(regexp *prog, char *string)
+{
+ register char *s;
+
+ /* Be paranoid... */
+ if (prog == NULL || string == NULL) {
+ printk("<3>Regexp: NULL parameter\n");
+ return(0);
+ }
+
+ /* Check validity of program. */
+ if (UCHARAT(prog->program) != MAGIC) {
+ printk("<3>Regexp: corrupted program\n");
+ return(0);
+ }
+
+ /* If there is a "must appear" string, look for it. */
+ if (prog->regmust != NULL) {
+ s = string;
+ while ((s = strchr(s, prog->regmust[0])) != NULL) {
+ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+ break; /* Found it. */
+ s++;
+ }
+ if (s == NULL) /* Not present. */
+ return(0);
+ }
+
+ /* Mark beginning of line for ^ . */
+ regbol = string;
+
+ /* Simplest case: anchored match need be tried only once. */
+ if (prog->reganch)
+ return(regtry(prog, string));
+
+ /* Messy cases: unanchored match. */
+ s = string;
+ if (prog->regstart != '\0')
+ /* We know what char it must start with. */
+ while ((s = strchr(s, prog->regstart)) != NULL) {
+ if (regtry(prog, s))
+ return(1);
+ s++;
+ }
+ else
+ /* We don't -- general case. */
+ do {
+ if (regtry(prog, s))
+ return(1);
+ } while (*s++ != '\0');
+
+ /* Failure. */
+ return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int /* 0 failure, 1 success */
+regtry(regexp *prog, char *string)
+{
+ register int i;
+ register char **sp;
+ register char **ep;
+
+ reginput = string;
+ regstartp = prog->startp;
+ regendp = prog->endp;
+
+ sp = prog->startp;
+ ep = prog->endp;
+ for (i = NSUBEXP; i > 0; i--) {
+ *sp++ = NULL;
+ *ep++ = NULL;
+ }
+ if (regmatch(prog->program + 1)) {
+ prog->startp[0] = string;
+ prog->endp[0] = reginput;
+ return(1);
+ } else
+ return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple: check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly. In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int /* 0 failure, 1 success */
+regmatch(char *prog)
+{
+ register char *scan = prog; /* Current node. */
+ char *next; /* Next node. */
+
+#ifdef DEBUG
+ if (scan != NULL && regnarrate)
+ fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+ while (scan != NULL) {
+#ifdef DEBUG
+ if (regnarrate)
+ fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+ next = regnext(scan);
+
+ switch (OP(scan)) {
+ case BOL:
+ if (reginput != regbol)
+ return(0);
+ break;
+ case EOL:
+ if (*reginput != '\0')
+ return(0);
+ break;
+ case ANY:
+ if (*reginput == '\0')
+ return(0);
+ reginput++;
+ break;
+ case EXACTLY: {
+ register int len;
+ register char *opnd;
+
+ opnd = OPERAND(scan);
+ /* Inline the first character, for speed. */
+ if (*opnd != *reginput)
+ return(0);
+ len = strlen(opnd);
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return(0);
+ reginput += len;
+ }
+ break;
+ case ANYOF:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+ return(0);
+ reginput++;
+ break;
+ case ANYBUT:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+ return(0);
+ reginput++;
+ break;
+ case NOTHING:
+ case BACK:
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - OPEN;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set startp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regstartp[no] == NULL)
+ regstartp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9:
+ {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - CLOSE;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set endp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regendp[no] == NULL)
+ regendp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case BRANCH: {
+ register char *save;
+
+ if (OP(next) != BRANCH) /* No choice. */
+ next = OPERAND(scan); /* Avoid recursion. */
+ else {
+ do {
+ save = reginput;
+ if (regmatch(OPERAND(scan)))
+ return(1);
+ reginput = save;
+ scan = regnext(scan);
+ } while (scan != NULL && OP(scan) == BRANCH);
+ return(0);
+ /* NOTREACHED */
+ }
+ }
+ break;
+ case STAR:
+ case PLUS: {
+ register char nextch;
+ register int no;
+ register char *save;
+ register int min;
+
+ /*
+ * Lookahead to avoid useless match attempts
+ * when we know what character comes next.
+ */
+ nextch = '\0';
+ if (OP(next) == EXACTLY)
+ nextch = *OPERAND(next);
+ min = (OP(scan) == STAR) ? 0 : 1;
+ save = reginput;
+ no = regrepeat(OPERAND(scan));
+ while (no >= min) {
+ /* If it could work, try it. */
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return(1);
+ /* Couldn't or didn't -- back up. */
+ no--;
+ reginput = save + no;
+ }
+ return(0);
+ }
+ break;
+ case END:
+ return(1); /* Success! */
+ break;
+ default:
+ printk("<3>Regexp: memory corruption\n");
+ return(0);
+ break;
+ }
+
+ scan = next;
+ }
+
+ /*
+ * We get here only if there's trouble -- normally "case END" is
+ * the terminating point.
+ */
+ printk("<3>Regexp: corrupted pointers\n");
+ return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat(char *p)
+{
+ register int count = 0;
+ register char *scan;
+ register char *opnd;
+
+ scan = reginput;
+ opnd = OPERAND(p);
+ switch (OP(p)) {
+ case ANY:
+ count = strlen(scan);
+ scan += count;
+ break;
+ case EXACTLY:
+ while (*opnd == *scan) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYOF:
+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYBUT:
+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ default: /* Oh dear. Called inappropriately. */
+ printk("<3>Regexp: internal foulup\n");
+ count = 0; /* Best compromise. */
+ break;
+ }
+ reginput = scan;
+
+ return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char*
+regnext(char *p)
+{
+ register int offset;
+
+ if (p == &regdummy)
+ return(NULL);
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return(NULL);
+
+ if (OP(p) == BACK)
+ return(p-offset);
+ else
+ return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(regexp *r)
+{
+ register char *s;
+ register char op = EXACTLY; /* Arbitrary non-END op. */
+ register char *next;
+ /* extern char *strchr(); */
+
+
+ s = r->program + 1;
+ while (op != END) { /* While that wasn't END last time... */
+ op = OP(s);
+ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
+ next = regnext(s);
+ if (next == NULL) /* Next ptr. */
+ printf("(0)");
+ else
+ printf("(%d)", (s-r->program)+(next-s));
+ s += 3;
+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+ /* Literal string, where present. */
+ while (*s != '\0') {
+ putchar(*s);
+ s++;
+ }
+ s++;
+ }
+ putchar('\n');
+ }
+
+ /* Header fields of interest. */
+ if (r->regstart != '\0')
+ printf("start `%c' ", r->regstart);
+ if (r->reganch)
+ printf("anchored ");
+ if (r->regmust != NULL)
+ printf("must have \"%s\"", r->regmust);
+ printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop(char *op)
+{
+#define BUFLEN 50
+ register char *p;
+ static char buf[BUFLEN];
+
+ strcpy(buf, ":");
+
+ switch (OP(op)) {
+ case BOL:
+ p = "BOL";
+ break;
+ case EOL:
+ p = "EOL";
+ break;
+ case ANY:
+ p = "ANY";
+ break;
+ case ANYOF:
+ p = "ANYOF";
+ break;
+ case ANYBUT:
+ p = "ANYBUT";
+ break;
+ case BRANCH:
+ p = "BRANCH";
+ break;
+ case EXACTLY:
+ p = "EXACTLY";
+ break;
+ case NOTHING:
+ p = "NOTHING";
+ break;
+ case BACK:
+ p = "BACK";
+ break;
+ case END:
+ p = "END";
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9:
+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN);
+ p = NULL;
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9:
+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+ p = NULL;
+ break;
+ case STAR:
+ p = "STAR";
+ break;
+ case PLUS:
+ p = "PLUS";
+ break;
+ default:
+ printk("<3>Regexp: corrupted opcode\n");
+ break;
+ }
+ if (p != NULL)
+ strncat(buf, p, BUFLEN-strlen(buf));
+ return(buf);
+}
+#endif
+
+
diff --git a/release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.h b/release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.h
new file mode 100644
index 00000000..fda9a7c4
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/regexp/regexp.h
@@ -0,0 +1,40 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+
+#ifndef REGEXP_H
+#define REGEXP_H
+
+/*
+http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h ,
+which contains a version of this library, says:
+
+ *
+ * NSUBEXP must be at least 10, and no greater than 117 or the parser
+ * will not work properly.
+ *
+
+However, it looks rather like this library is limited to 10. If you think
+otherwise, let us know.
+*/
+
+#define NSUBEXP 10
+typedef struct regexp {
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
+ char regstart; /* Internal use only. */
+ char reganch; /* Internal use only. */
+ char *regmust; /* Internal use only. */
+ int regmlen; /* Internal use only. */
+ char program[1]; /* Unwarranted chumminess with compiler. */
+} regexp;
+
+regexp * regcomp(char *exp, int *patternsize);
+int regexec(regexp *prog, char *string);
+void regsub(regexp *prog, char *source, char *dest);
+void regerror(char *s);
+
+#endif
diff --git a/release/src/linux/linux/net/ipv4/netfilter/regexp/regmagic.h b/release/src/linux/linux/net/ipv4/netfilter/regexp/regmagic.h
new file mode 100644
index 00000000..5acf4478
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/regexp/regmagic.h
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
diff --git a/release/src/linux/linux/net/ipv4/netfilter/regexp/regsub.c b/release/src/linux/linux/net/ipv4/netfilter/regexp/regsub.c
new file mode 100644
index 00000000..339631f0
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/regexp/regsub.c
@@ -0,0 +1,95 @@
+/*
+ * regsub
+ * @(#)regsub.c 1.3 of 2 April 86
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ *
+ * This code was modified by Ethan Sommer to work within the kernel
+ * (it now uses kmalloc etc..)
+ *
+ */
+#include "regexp.h"
+#include "regmagic.h"
+#include <linux/string.h>
+
+
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+#if 0
+//void regerror(char * s)
+//{
+// printk("regexp(3): %s", s);
+// /* NOTREACHED */
+//}
+#endif
+
+/*
+ - regsub - perform substitutions after a regexp match
+ */
+void
+regsub(regexp * prog, char * source, char * dest)
+{
+ register char *src;
+ register char *dst;
+ register char c;
+ register int no;
+ register int len;
+
+ /* Not necessary and gcc doesn't like it -MLS */
+ /*extern char *strncpy();*/
+
+ if (prog == NULL || source == NULL || dest == NULL) {
+ regerror("NULL parm to regsub");
+ return;
+ }
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("damaged regexp fed to regsub");
+ return;
+ }
+
+ src = source;
+ dst = dest;
+ while ((c = *src++) != '\0') {
+ if (c == '&')
+ no = 0;
+ else if (c == '\\' && '0' <= *src && *src <= '9')
+ no = *src++ - '0';
+ else
+ no = -1;
+
+ if (no < 0) { /* Ordinary character. */
+ if (c == '\\' && (*src == '\\' || *src == '&'))
+ c = *src++;
+ *dst++ = c;
+ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+ len = prog->endp[no] - prog->startp[no];
+ (void) strncpy(dst, prog->startp[no], len);
+ dst += len;
+ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
+ regerror("damaged match string");
+ return;
+ }
+ }
+ }
+ *dst++ = '\0';
+}
diff --git a/release/src/linux/linux/net/ipv4/netfilter/tomato_ct.c b/release/src/linux/linux/net/ipv4/netfilter/tomato_ct.c
new file mode 100644
index 00000000..a84cab09
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/tomato_ct.c
@@ -0,0 +1,181 @@
+/*
+
+ tomato_ct.c
+ Copyright (C) 2006 Jonathan Zarate
+
+ Licensed under GNU GPL v2.
+
+*/
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+
+// #define TEST_HASHDIST
+
+
+#ifdef TEST_HASHDIST
+static int hashdist_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ struct list_head *h;
+ struct list_head *e;
+ int i;
+ int n;
+ int count;
+ char *buf;
+ int max;
+
+ // do this the easy way...
+ max = ip_conntrack_htable_size * sizeof("12345\t12345\n");
+ buf = kmalloc(max + 1, GFP_KERNEL);
+ if (buf == NULL) return 0;
+
+ n = 0;
+ max -= sizeof("12345\t12345\n");
+
+ READ_LOCK(&ip_conntrack_lock);
+
+ for (i = 0; i < ip_conntrack_htable_size; ++i) {
+ count = 0;
+ h = &ip_conntrack_hash[i];
+ if (h) {
+ e = h;
+ while (e->next != h) {
+ ++count;
+ e = e->next;
+ }
+ }
+
+ n += sprintf(buf + n, "%d\t%d\n", i, count);
+ if (n > max) {
+ printk("hashdist: %d > %d\n", n, max);
+ break;
+ }
+ }
+
+ READ_UNLOCK(&ip_conntrack_lock);
+
+ if (offset < n) {
+ n = n - offset;
+ if (n > length) {
+ n = length;
+ *eof = 0;
+ }
+ else {
+ *eof = 1;
+ }
+ memcpy(buffer, buf + offset, n);
+ *start = buffer;
+ }
+ else {
+ n = 0;
+ *eof = 1;
+ }
+
+ kfree(buf);
+ return n;
+}
+#endif
+
+
+static void interate_all(void (*func)(struct ip_conntrack *, unsigned long), unsigned long data)
+{
+ int i;
+ struct list_head *h;
+ struct list_head *e;
+
+ WRITE_LOCK(&ip_conntrack_lock);
+ for (i = 0; i < ip_conntrack_htable_size; ++i) {
+ h = &ip_conntrack_hash[i];
+ if (h) {
+ e = h;
+ while (e->next != h) {
+ e = e->next;
+ func(((struct ip_conntrack_tuple_hash *)e)->ctrack, data);
+ }
+ }
+ }
+ WRITE_UNLOCK(&ip_conntrack_lock);
+}
+
+static void expireearly(struct ip_conntrack *ct, unsigned long data)
+{
+ if (ct->timeout.expires > data) {
+ if (del_timer(&ct->timeout)) {
+ ct->timeout.expires = data;
+ add_timer(&ct->timeout);
+ }
+ }
+}
+
+static int expireearly_write(struct file *file, const char *buffer, unsigned long length, void *data)
+{
+ char s[8];
+ unsigned long n;
+
+ if ((length > 0) && (length < 6)) {
+ memcpy(s, buffer, length);
+ s[length] = 0;
+ n = simple_strtoul(s, NULL, 10);
+ if (n < 10) n = 10;
+ else if (n > 86400) n = 86400;
+
+ interate_all(expireearly, jiffies + (n * HZ));
+ }
+
+/*
+ if ((length > 0) && (buffer[0] == '1')) {
+ interate_all(expireearly, jiffies + (20 * HZ));
+ }
+*/
+
+ return length;
+}
+
+
+static void clearmarks(struct ip_conntrack *ct, unsigned long data)
+{
+ ct->mark = 0;
+}
+
+static int clearmarks_write(struct file *file, const char *buffer, unsigned long length, void *data)
+{
+ if ((length > 0) && (buffer[0] == '1')) {
+ interate_all(clearmarks, 0);
+ }
+ return length;
+}
+
+static int __init init(void)
+{
+ struct proc_dir_entry *p;
+
+ printk(__FILE__ " [" __DATE__ " " __TIME__ "]\n");
+
+#ifdef TEST_HASHDIST
+ p = create_proc_entry("hash_dist", 0400, proc_net);
+ if (p) p->read_proc = hashdist_read;
+#endif
+
+ p = create_proc_entry("expire_early", 0200, proc_net);
+ if (p) p->write_proc = expireearly_write;
+
+ p = create_proc_entry("clear_marks", 0200, proc_net);
+ if (p) p->write_proc = clearmarks_write;
+
+ return 0;
+}
+
+static void __exit fini(void)
+{
+#ifdef TEST_HASHDIST
+ remove_proc_entry("hash_dist", proc_net);
+#endif
+ remove_proc_entry("expire_early", proc_net);
+ remove_proc_entry("clear_marks", proc_net);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/route.c b/release/src/linux/linux/net/ipv4/route.c
index dfae0871..f3cf20df 100644
--- a/release/src/linux/linux/net/ipv4/route.c
+++ b/release/src/linux/linux/net/ipv4/route.c
@@ -2465,6 +2465,7 @@ void __init ip_rt_init(void)
panic("IP: failed to allocate ip_dst_cache\n");
goal = num_physpages >> (26 - PAGE_SHIFT);
+// goal = num_physpages >> (21 - PAGE_SHIFT);
for (order = 0; (1UL << order) < goal; order++)
/* NOTHING */;
@@ -2494,9 +2495,18 @@ void __init ip_rt_init(void)
rt_hash_table[i].chain = NULL;
}
+// ip_rt_max_size = (rt_hash_mask + 1) * 2;
+// ipv4_dst_ops.gc_thresh = (ip_rt_max_size / 4);
+
ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
ip_rt_max_size = (rt_hash_mask + 1) * 16;
+// printk("gc_thresh=%d\n", ipv4_dst_ops.gc_thresh);
+// printk("ip_rt_max_size=%d\n", ip_rt_max_size);
+// printk("rt_hash_mask=%d\n", rt_hash_mask);
+// printk("goal=%d\n", goal);
+
+
devinet_init();
ip_fib_init();
diff --git a/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c b/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c
index 1f4081a9..7fe16445 100644
--- a/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c
+++ b/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c
@@ -221,6 +221,18 @@ ctl_table ipv4_table[] = {
&sysctl_icmp_ratemask, sizeof(int), 0644, NULL, &proc_dointvec},
{NET_TCP_TW_REUSE, "tcp_tw_reuse",
&sysctl_tcp_tw_reuse, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_TCP_VEGAS, "tcp_vegas_cong_avoid",
+ &sysctl_tcp_vegas_cong_avoid, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_TCP_VEGAS_ALPHA, "tcp_vegas_alpha",
+ &sysctl_tcp_vegas_alpha, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_TCP_VEGAS_BETA, "tcp_vegas_beta",
+ &sysctl_tcp_vegas_beta, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_TCP_VEGAS_GAMMA, "tcp_vegas_gamma",
+ &sysctl_tcp_vegas_gamma, sizeof(int), 0644, NULL,
+ &proc_dointvec},
{0}
};
diff --git a/release/src/linux/linux/net/ipv4/tcp_input.c b/release/src/linux/linux/net/ipv4/tcp_input.c
index 8c99dd52..243e2991 100644
--- a/release/src/linux/linux/net/ipv4/tcp_input.c
+++ b/release/src/linux/linux/net/ipv4/tcp_input.c
@@ -87,6 +87,16 @@ int sysctl_tcp_stdurg = 0;
int sysctl_tcp_rfc1337 = 0;
int sysctl_tcp_max_orphans = NR_FILE;
+int sysctl_tcp_vegas_cong_avoid = 0;
+
+/* Default values of the Vegas variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+int sysctl_tcp_vegas_alpha = 1<<V_PARAM_SHIFT;
+int sysctl_tcp_vegas_beta = 3<<V_PARAM_SHIFT;
+int sysctl_tcp_vegas_gamma = 1<<V_PARAM_SHIFT;
+
#define FLAG_DATA 0x01 /* Incoming frame contained data. */
#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
#define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */
@@ -399,6 +409,42 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_opt *tp, struct sk_b
tcp_grow_window(sk, tp, skb);
}
+/* Set up a new TCP connection, depending on whether it should be
+ * using Vegas or not.
+ */
+void tcp_vegas_init(struct tcp_opt *tp)
+{
+ if (sysctl_tcp_vegas_cong_avoid) {
+ tp->vegas.do_vegas = 1;
+ tp->vegas.baseRTT = 0x7fffffff;
+ tcp_vegas_enable(tp);
+ } else
+ tcp_vegas_disable(tp);
+}
+
+/* Do RTT sampling needed for Vegas.
+ * Basically we:
+ * o min-filter RTT samples from within an RTT to get the current
+ * propagation delay + queuing delay (we are min-filtering to try to
+ * avoid the effects of delayed ACKs)
+ * o min-filter RTT samples from a much longer window (forever for now)
+ * to find the propagation delay (baseRTT)
+ */
+static inline void vegas_rtt_calc(struct tcp_opt *tp, __u32 rtt)
+{
+ __u32 vrtt = rtt + 1; /* Never allow zero rtt or baseRTT */
+
+ /* Filter to find propagation delay: */
+ if (vrtt < tp->vegas.baseRTT)
+ tp->vegas.baseRTT = vrtt;
+
+ /* Find the min RTT during the last RTT to find
+ * the current prop. delay + queuing delay:
+ */
+ tp->vegas.minRTT = min(tp->vegas.minRTT, vrtt);
+ tp->vegas.cntRTT++;
+}
+
/* Called to compute a smoothed rtt estimate. The data fed to this
* routine either comes from timestamps, or from segments that were
* known _not_ to have been retransmitted [see Karn/Partridge
@@ -412,6 +458,9 @@ static __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
{
long m = mrtt; /* RTT */
+ if (tcp_vegas_enabled(tp))
+ vegas_rtt_calc(tp, mrtt);
+
/* The following amusing code comes from Jacobson's
* article in SIGCOMM '88. Note that rtt and mdev
* are scaled versions of rtt and mean deviation.
@@ -1013,7 +1062,7 @@ void tcp_enter_loss(struct sock *sk, int how)
tcp_sync_left_out(tp);
tp->reordering = min_t(unsigned int, tp->reordering, sysctl_tcp_reordering);
- tp->ca_state = TCP_CA_Loss;
+ tcp_set_ca_state(tp, TCP_CA_Loss);
tp->high_seq = tp->snd_nxt;
TCP_ECN_queue_cwr(tp);
}
@@ -1375,7 +1424,7 @@ static int tcp_try_undo_recovery(struct sock *sk, struct tcp_opt *tp)
tcp_moderate_cwnd(tp);
return 1;
}
- tp->ca_state = TCP_CA_Open;
+ tcp_set_ca_state(tp, TCP_CA_Open);
return 0;
}
@@ -1435,7 +1484,7 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp)
tp->retransmits = 0;
tp->undo_marker = 0;
if (!IsReno(tp))
- tp->ca_state = TCP_CA_Open;
+ tcp_set_ca_state(tp, TCP_CA_Open);
return 1;
}
return 0;
@@ -1466,7 +1515,7 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_opt *tp, int flag)
state = TCP_CA_Disorder;
if (tp->ca_state != state) {
- tp->ca_state = state;
+ tcp_set_ca_state(tp, state);
tp->high_seq = tp->snd_nxt;
}
tcp_moderate_cwnd(tp);
@@ -1540,7 +1589,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
* is ACKed for CWR bit to reach receiver. */
if (tp->snd_una != tp->high_seq) {
tcp_complete_cwr(tp);
- tp->ca_state = TCP_CA_Open;
+ tcp_set_ca_state(tp, TCP_CA_Open);
}
break;
@@ -1551,7 +1600,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
* catching for all duplicate ACKs. */
IsReno(tp) || tp->snd_una != tp->high_seq) {
tp->undo_marker = 0;
- tp->ca_state = TCP_CA_Open;
+ tcp_set_ca_state(tp, TCP_CA_Open);
}
break;
@@ -1625,7 +1674,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
}
tp->snd_cwnd_cnt = 0;
- tp->ca_state = TCP_CA_Recovery;
+ tcp_set_ca_state(tp, TCP_CA_Recovery);
}
if (is_dupack || tcp_head_timedout(sk, tp))
@@ -1696,7 +1745,7 @@ tcp_ack_update_rtt(struct tcp_opt *tp, int flag, s32 seq_rtt)
/* This is Jacobson's slow start and congestion avoidance.
* SIGCOMM '88, p. 328.
*/
-static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
+static __inline__ void reno_cong_avoid(struct tcp_opt *tp)
{
if (tp->snd_cwnd <= tp->snd_ssthresh) {
/* In "safe" area, increase. */
@@ -1716,6 +1765,236 @@ static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
tp->snd_cwnd_stamp = tcp_time_stamp;
}
+/* This is based on the congestion detection/avoidance scheme described in
+ * Lawrence S. Brakmo and Larry L. Peterson.
+ * "TCP Vegas: End to end congestion avoidance on a global internet."
+ * IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
+ * October 1995. Available from:
+ * ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
+ *
+ * See http://www.cs.arizona.edu/xkernel/ for their implementation.
+ * The main aspects that distinguish this implementation from the
+ * Arizona Vegas implementation are:
+ * o We do not change the loss detection or recovery mechanisms of
+ * Linux in any way. Linux already recovers from losses quite well,
+ * using fine-grained timers, NewReno, and FACK.
+ * o To avoid the performance penalty imposed by increasing cwnd
+ * only every-other RTT during slow start, we increase during
+ * every RTT during slow start, just like Reno.
+ * o Largely to allow continuous cwnd growth during slow start,
+ * we use the rate at which ACKs come back as the "actual"
+ * rate, rather than the rate at which data is sent.
+ * o To speed convergence to the right rate, we set the cwnd
+ * to achieve the right ("actual") rate when we exit slow start.
+ * o To filter out the noise caused by delayed ACKs, we use the
+ * minimum RTT sample observed during the last RTT to calculate
+ * the actual rate.
+ * o When the sender re-starts from idle, it waits until it has
+ * received ACKs for an entire flight of new data before making
+ * a cwnd adjustment decision. The original Vegas implementation
+ * assumed senders never went idle.
+ */
+static void vegas_cong_avoid(struct tcp_opt *tp, u32 ack, u32 seq_rtt)
+{
+ /* The key players are v_beg_snd_una and v_beg_snd_nxt.
+ *
+ * These are so named because they represent the approximate values
+ * of snd_una and snd_nxt at the beginning of the current RTT. More
+ * precisely, they represent the amount of data sent during the RTT.
+ * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
+ * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
+ * bytes of data have been ACKed during the course of the RTT, giving
+ * an "actual" rate of:
+ *
+ * (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
+ *
+ * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
+ * because delayed ACKs can cover more than one segment, so they
+ * don't line up nicely with the boundaries of RTTs.
+ *
+ * Another unfortunate fact of life is that delayed ACKs delay the
+ * advance of the left edge of our send window, so that the number
+ * of bytes we send in an RTT is often less than our cwnd will allow.
+ * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
+ */
+
+ if (after(ack, tp->vegas.beg_snd_nxt)) {
+ /* Do the Vegas once-per-RTT cwnd adjustment. */
+ u32 old_wnd, old_snd_cwnd;
+
+
+ /* Here old_wnd is essentially the window of data that was
+ * sent during the previous RTT, and has all
+ * been acknowledged in the course of the RTT that ended
+ * with the ACK we just received. Likewise, old_snd_cwnd
+ * is the cwnd during the previous RTT.
+ */
+ old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una) /
+ tp->mss_cache;
+ old_snd_cwnd = tp->vegas.beg_snd_cwnd;
+
+ /* Save the extent of the current window so we can use this
+ * at the end of the next RTT.
+ */
+ tp->vegas.beg_snd_una = tp->vegas.beg_snd_nxt;
+ tp->vegas.beg_snd_nxt = tp->snd_nxt;
+ tp->vegas.beg_snd_cwnd = tp->snd_cwnd;
+
+ /* Take into account the current RTT sample too, to
+ * decrease the impact of delayed acks. This double counts
+ * this sample since we count it for the next window as well,
+ * but that's not too awful, since we're taking the min,
+ * rather than averaging.
+ */
+ vegas_rtt_calc(tp, seq_rtt);
+
+ /* We do the Vegas calculations only if we got enough RTT
+ * samples that we can be reasonably sure that we got
+ * at least one RTT sample that wasn't from a delayed ACK.
+ * If we only had 2 samples total,
+ * then that means we're getting only 1 ACK per RTT, which
+ * means they're almost certainly delayed ACKs.
+ * If we have 3 samples, we should be OK.
+ */
+
+ if (tp->vegas.cntRTT <= 2) {
+ /* We don't have enough RTT samples to do the Vegas
+ * calculation, so we'll behave like Reno.
+ */
+ if (tp->snd_cwnd > tp->snd_ssthresh)
+ tp->snd_cwnd++;
+ } else {
+ u32 rtt, target_cwnd, diff;
+
+ /* We have enough RTT samples, so, using the Vegas
+ * algorithm, we determine if we should increase or
+ * decrease cwnd, and by how much.
+ */
+
+ /* Pluck out the RTT we are using for the Vegas
+ * calculations. This is the min RTT seen during the
+ * last RTT. Taking the min filters out the effects
+ * of delayed ACKs, at the cost of noticing congestion
+ * a bit later.
+ */
+ rtt = tp->vegas.minRTT;
+
+ /* Calculate the cwnd we should have, if we weren't
+ * going too fast.
+ *
+ * This is:
+ * (actual rate in segments) * baseRTT
+ * We keep it as a fixed point number with
+ * V_PARAM_SHIFT bits to the right of the binary point.
+ */
+ target_cwnd = ((old_wnd * tp->vegas.baseRTT)
+ << V_PARAM_SHIFT) / rtt;
+
+ /* Calculate the difference between the window we had,
+ * and the window we would like to have. This quantity
+ * is the "Diff" from the Arizona Vegas papers.
+ *
+ * Again, this is a fixed point number with
+ * V_PARAM_SHIFT bits to the right of the binary
+ * point.
+ */
+ diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
+
+ if (tp->snd_cwnd < tp->snd_ssthresh) {
+ /* Slow start. */
+ if (diff > sysctl_tcp_vegas_gamma) {
+ /* Going too fast. Time to slow down
+ * and switch to congestion avoidance.
+ */
+ tp->snd_ssthresh = 2;
+
+ /* Set cwnd to match the actual rate
+ * exactly:
+ * cwnd = (actual rate) * baseRTT
+ * Then we add 1 because the integer
+ * truncation robs us of full link
+ * utilization.
+ */
+ tp->snd_cwnd = min(tp->snd_cwnd,
+ (target_cwnd >>
+ V_PARAM_SHIFT)+1);
+
+ }
+ } else {
+ /* Congestion avoidance. */
+ u32 next_snd_cwnd;
+
+ /* Figure out where we would like cwnd
+ * to be.
+ */
+ if (diff > sysctl_tcp_vegas_beta) {
+ /* The old window was too fast, so
+ * we slow down.
+ */
+ next_snd_cwnd = old_snd_cwnd - 1;
+ } else if (diff < sysctl_tcp_vegas_alpha) {
+ /* We don't have enough extra packets
+ * in the network, so speed up.
+ */
+ next_snd_cwnd = old_snd_cwnd + 1;
+ } else {
+ /* Sending just as fast as we
+ * should be.
+ */
+ next_snd_cwnd = old_snd_cwnd;
+ }
+
+ /* Adjust cwnd upward or downward, toward the
+ * desired value.
+ */
+ if (next_snd_cwnd > tp->snd_cwnd)
+ tp->snd_cwnd++;
+ else if (next_snd_cwnd < tp->snd_cwnd)
+ tp->snd_cwnd--;
+ }
+ }
+
+ /* Wipe the slate clean for the next RTT. */
+ tp->vegas.cntRTT = 0;
+ tp->vegas.minRTT = 0x7fffffff;
+ }
+
+ /* The following code is executed for every ack we receive,
+ * except for conditions checked in should_advance_cwnd()
+ * before the call to tcp_cong_avoid(). Mainly this means that
+ * we only execute this code if the ack actually acked some
+ * data.
+ */
+
+ /* If we are in slow start, increase our cwnd in response to this ACK.
+ * (If we are not in slow start then we are in congestion avoidance,
+ * and adjust our congestion window only once per RTT. See the code
+ * above.)
+ */
+ if (tp->snd_cwnd <= tp->snd_ssthresh)
+ tp->snd_cwnd++;
+
+ /* to keep cwnd from growing without bound */
+ tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
+
+ /* Make sure that we are never so timid as to reduce our cwnd below
+ * 2 MSS.
+ *
+ * Going below 2 MSS would risk huge delayed ACKs from our receiver.
+ */
+ tp->snd_cwnd = max(tp->snd_cwnd, 2U);
+
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+}
+
+static inline void tcp_cong_avoid(struct tcp_opt *tp, u32 ack, u32 seq_rtt)
+{
+ if (tcp_vegas_enabled(tp))
+ vegas_cong_avoid(tp, ack, seq_rtt);
+ else
+ reno_cong_avoid(tp);
+}
+
/* Restart timer after forward progress on connection.
* RFC2988 recommends to restart timer to now+rto.
*/
@@ -1730,7 +2009,7 @@ static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
}
/* Remove acknowledged frames from the retransmission queue. */
-static int tcp_clean_rtx_queue(struct sock *sk)
+static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
struct sk_buff *skb;
@@ -1813,6 +2092,7 @@ static int tcp_clean_rtx_queue(struct sock *sk)
}
}
#endif
+ *seq_rtt_p = seq_rtt;
return acked;
}
@@ -1900,6 +2180,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
u32 ack_seq = TCP_SKB_CB(skb)->seq;
u32 ack = TCP_SKB_CB(skb)->ack_seq;
u32 prior_in_flight;
+ s32 seq_rtt;
int prior_packets;
/* If the ack is newer than sent or older than previous acks
@@ -1947,17 +2228,19 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
prior_in_flight = tcp_packets_in_flight(tp);
/* See if we can take anything off of the retransmit queue. */
- flag |= tcp_clean_rtx_queue(sk);
+ flag |= tcp_clean_rtx_queue(sk, &seq_rtt);
if (tcp_ack_is_dubious(tp, flag)) {
/* Advanve CWND, if state allows this. */
- if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd &&
+ if ((flag&FLAG_DATA_ACKED) &&
+ (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd) &&
tcp_may_raise_cwnd(tp, flag))
- tcp_cong_avoid(tp);
+ tcp_cong_avoid(tp, ack, seq_rtt);
tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
} else {
- if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd)
- tcp_cong_avoid(tp);
+ if ((flag & FLAG_DATA_ACKED) &&
+ (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd))
+ tcp_cong_avoid(tp, ack, seq_rtt);
}
if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
diff --git a/release/src/linux/linux/net/ipv4/tcp_minisocks.c b/release/src/linux/linux/net/ipv4/tcp_minisocks.c
index b69cc32c..6fdb7681 100644
--- a/release/src/linux/linux/net/ipv4/tcp_minisocks.c
+++ b/release/src/linux/linux/net/ipv4/tcp_minisocks.c
@@ -715,7 +715,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->snd_cwnd = 2;
newtp->snd_cwnd_cnt = 0;
- newtp->ca_state = TCP_CA_Open;
+ tcp_set_ca_state(newtp, TCP_CA_Open);
tcp_init_xmit_timers(newsk);
skb_queue_head_init(&newtp->out_of_order_queue);
newtp->send_head = NULL;
@@ -783,6 +783,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->mss_clamp = req->mss;
TCP_ECN_openreq_child(newtp, req);
+ tcp_vegas_init(newtp);
TCP_INC_STATS_BH(TcpPassiveOpens);
}
return newsk;
diff --git a/release/src/linux/linux/net/ipv4/tcp_output.c b/release/src/linux/linux/net/ipv4/tcp_output.c
index 35cbbbf7..3fd4871f 100644
--- a/release/src/linux/linux/net/ipv4/tcp_output.c
+++ b/release/src/linux/linux/net/ipv4/tcp_output.c
@@ -105,6 +105,9 @@ static void tcp_cwnd_restart(struct tcp_opt *tp)
u32 restart_cwnd = tcp_init_cwnd(tp);
u32 cwnd = tp->snd_cwnd;
+ if (tcp_is_vegas(tp))
+ tcp_vegas_enable(tp);
+
tp->snd_ssthresh = tcp_current_ssthresh(tp);
restart_cwnd = min(restart_cwnd, cwnd);
@@ -223,6 +226,19 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
tcp_header_size += (TCPOLEN_SACK_BASE_ALIGNED +
(tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
}
+
+ /*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Vegas calculations
+ * until we get fresh RTT samples. So when we
+ * restart, we reset our Vegas state to a clean
+ * slate. After we get acks for this flight of
+ * packets, _then_ we can make Vegas calculations
+ * again.
+ */
+ if (tcp_is_vegas(tp) && tcp_packets_in_flight(tp) == 0)
+ tcp_vegas_enable(tp);
+
th = (struct tcphdr *) skb_push(skb, tcp_header_size);
skb->h.th = th;
skb_set_owner_w(skb, sk);
@@ -800,7 +816,7 @@ void tcp_simple_retransmit(struct sock *sk)
tp->snd_ssthresh = tcp_current_ssthresh(tp);
tp->prior_ssthresh = 0;
tp->undo_marker = 0;
- tp->ca_state = TCP_CA_Loss;
+ tcp_set_ca_state(tp, TCP_CA_Loss);
}
tcp_xmit_retransmit_queue(sk);
}
@@ -1181,6 +1197,7 @@ static inline void tcp_connect_init(struct sock *sk)
tp->window_clamp = dst->window;
tp->advmss = dst->advmss;
tcp_initialize_rcv_mss(sk);
+ tcp_vegas_init(tp);
tcp_select_initial_window(tcp_full_space(sk),
tp->advmss - (tp->ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
@@ -1231,6 +1248,7 @@ int tcp_connect(struct sock *sk)
TCP_SKB_CB(buff)->end_seq = tp->write_seq;
tp->snd_nxt = tp->write_seq;
tp->pushed_seq = tp->write_seq;
+ tcp_vegas_init(tp);
/* Send it off. */
TCP_SKB_CB(buff)->when = tcp_time_stamp;
diff --git a/release/src/linux/linux/net/ipv6/netfilter/Config.in b/release/src/linux/linux/net/ipv6/netfilter/Config.in
index 062ed247..5d2dac2f 100644
--- a/release/src/linux/linux/net/ipv6/netfilter/Config.in
+++ b/release/src/linux/linux/net/ipv6/netfilter/Config.in
@@ -17,6 +17,7 @@ tristate 'IP6 tables support (required for filtering/masq/NAT)' CONFIG_IP6_NF_IP
if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
# The simple matches.
dep_tristate ' limit match support' CONFIG_IP6_NF_MATCH_LIMIT $CONFIG_IP6_NF_IPTABLES
+ dep_tristate ' condition match support' CONFIG_IP6_NF_MATCH_CONDITION $CONFIG_IP6_NF_IPTABLES
dep_tristate ' MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
dep_tristate ' Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -55,6 +56,9 @@ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
if [ "$CONFIG_IP6_NF_MANGLE" != "n" ]; then
# dep_tristate ' TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
dep_tristate ' MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
+ dep_tristate ' ROUTE target support' CONFIG_IP6_NF_TARGET_ROUTE $CONFIG_IP6_NF_MANGLE
+
+ dep_tristate ' IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE
fi
#dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
fi
diff --git a/release/src/linux/linux/net/ipv6/netfilter/Makefile b/release/src/linux/linux/net/ipv6/netfilter/Makefile
index dfd36a89..2bd664f4 100644
--- a/release/src/linux/linux/net/ipv6/netfilter/Makefile
+++ b/release/src/linux/linux/net/ipv6/netfilter/Makefile
@@ -14,6 +14,7 @@ export-objs := ip6_tables.o
# Link order matters here.
obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
+obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
@@ -23,6 +24,8 @@ obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
diff --git a/release/src/linux/linux/net/ipv6/netfilter/ip6_tables.c b/release/src/linux/linux/net/ipv6/netfilter/ip6_tables.c
index b521af78..8eac7586 100644
--- a/release/src/linux/linux/net/ipv6/netfilter/ip6_tables.c
+++ b/release/src/linux/linux/net/ipv6/netfilter/ip6_tables.c
@@ -1241,13 +1241,7 @@ do_add_counters(void *user, unsigned int len)
goto free;
write_lock_bh(&t->lock);
- /*************************************
- * modify by tanghui @ 2006-10-11
- * for a RACE CONDITION in the "do_add_counters()" function
- *************************************/
if (t->private->number != paddc->num_counters) {
- if (t->private->number != tmp.num_counters) {
- /*************************************/
ret = -EINVAL;
goto unlock_up_free;
}
diff --git a/release/src/linux/linux/net/ipv6/netfilter/ip6t_IMQ.c b/release/src/linux/linux/net/ipv6/netfilter/ip6t_IMQ.c
new file mode 100644
index 00000000..760d7447
--- /dev/null
+++ b/release/src/linux/linux/net/ipv6/netfilter/ip6t_IMQ.c
@@ -0,0 +1,78 @@
+/* This target marks packets to be enqueued to an imq device */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_IMQ.h>
+#include <linux/imq.h>
+
+static unsigned int imq_target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
+
+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
+ (*pskb)->nfcache |= NFC_ALTERED;
+
+ return IP6T_CONTINUE;
+}
+
+static int imq_checkentry(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ struct ip6t_imq_info *mr;
+
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
+ return 0;
+ }
+ mr = (struct ip6t_imq_info*)targinfo;
+
+ if (strcmp(tablename, "mangle") != 0) {
+ printk(KERN_WARNING
+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
+ tablename);
+ return 0;
+ }
+
+ if (mr->todev > IMQ_MAX_DEVS) {
+ printk(KERN_WARNING
+ "IMQ: invalid device specified, highest is %u\n",
+ IMQ_MAX_DEVS);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ip6t_target ip6t_imq_reg = {
+ { NULL, NULL},
+ "IMQ",
+ imq_target,
+ imq_checkentry,
+ NULL,
+ THIS_MODULE
+};
+
+static int __init init(void)
+{
+ if (ip6t_register_target(&ip6t_imq_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_target(&ip6t_imq_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c b/release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c
new file mode 100644
index 00000000..bb6d11f8
--- /dev/null
+++ b/release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c
@@ -0,0 +1,308 @@
+/*
+ * This implements the ROUTE v6 target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
+ *
+ * v 1.1 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
+#include <linux/netdevice.h>
+#include <net/ipv6.h>
+#include <net/ndisc.h>
+#include <net/ip6_route.h>
+#include <linux/icmpv6.h>
+
+#if 1
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define NIP6(addr) \
+ ntohs((addr).s6_addr16[0]), \
+ ntohs((addr).s6_addr16[1]), \
+ ntohs((addr).s6_addr16[2]), \
+ ntohs((addr).s6_addr16[3]), \
+ ntohs((addr).s6_addr16[4]), \
+ ntohs((addr).s6_addr16[5]), \
+ ntohs((addr).s6_addr16[6]), \
+ ntohs((addr).s6_addr16[7])
+
+/* Route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int
+route6(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ip6t_route_target_info *route_info)
+{
+ struct rt6_info *rt = NULL;
+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+
+ DEBUGP("ip6t_ROUTE: called with: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
+ DEBUGP("OUT=%s\n", route_info->oif);
+
+ if (ipv6_addr_any(gw))
+ rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
+ else
+ rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
+
+ if (!rt)
+ goto no_route;
+
+ DEBUGP("ip6t_ROUTE: routing gives: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
+ DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
+
+ if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
+ goto wrong_route;
+
+ if (!rt->rt6i_nexthop) {
+ DEBUGP("ip6t_ROUTE: discovering neighbour\n");
+ rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+ skb->dev = rt->rt6i_dev;
+ return 1;
+
+ wrong_route:
+ dst_release(&rt->u.dst);
+ no_route:
+ if (!net_ratelimit())
+ return 0;
+
+ printk("ip6t_ROUTE: no explicit route found ");
+ if (ifindex)
+ printk("via interface %s ", route_info->oif);
+ if (!ipv6_addr_any(gw))
+ printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
+ printk("\n");
+ return 0;
+}
+
+
+/* Stolen from ip6_output_finish
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+static unsigned int
+route6_oif(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+ else
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ if (route6(skb, ifindex, route_info)) {
+ dev_put(dev_out);
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+route6_gw(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route6(skb, 0, route_info)) {
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+ip6t_route_target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ip6t_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+ unsigned int res;
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ goto do_it;
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP6_PRE_ROUTING ||
+ hooknum == NF_IP6_LOCAL_IN) {
+
+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+
+ if (ipv6h->hop_limit <= 1) {
+ /* Force OUTPUT device used as source address */
+ skb->dev = skb->dst->dev;
+
+ icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+ ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
+
+ return NF_DROP;
+ }
+
+ ipv6h->hop_limit--;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IP6T_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
+ return IP6T_CONTINUE;
+ }
+ }
+
+do_it:
+ if (route_info->oif[0]) {
+ res = route6_oif(route_info, skb);
+ } else if (!ipv6_addr_any(gw)) {
+ res = route6_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+ res = IP6T_CONTINUE;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE))
+ res = IP6T_CONTINUE;
+
+ return res;
+}
+
+
+static int
+ip6t_route_checkentry(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
+ return 0;
+ }
+
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
+ printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static struct ip6t_target ip6t_route_reg = {
+ .name = "ROUTE",
+ .target = ip6t_route_target,
+ .checkentry = ip6t_route_checkentry,
+ .me = THIS_MODULE
+};
+
+
+static int __init init(void)
+{
+ printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
+ if (ip6t_register_target(&ip6t_route_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void __exit fini(void)
+{
+ ip6t_unregister_target(&ip6t_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv6/netfilter/ip6t_condition.c b/release/src/linux/linux/net/ipv6/netfilter/ip6t_condition.c
new file mode 100644
index 00000000..15d805e6
--- /dev/null
+++ b/release/src/linux/linux/net/ipv6/netfilter/ip6t_condition.c
@@ -0,0 +1,254 @@
+/*-------------------------------------------*\
+| Netfilter Condition Module for IPv6 |
+| |
+| Description: This module allows firewall |
+| rules to match using condition variables |
+| stored in /proc files. |
+| |
+| Author: Stephane Ouellette 2003-02-10 |
+| <ouellettes@videotron.ca> |
+| |
+| This software is distributed under the |
+| terms of the GNU GPL. |
+\*-------------------------------------------*/
+
+#include<linux/module.h>
+#include<linux/proc_fs.h>
+#include<linux/spinlock.h>
+#include<linux/string.h>
+#include<asm/atomic.h>
+#include<linux/netfilter_ipv6/ip6_tables.h>
+#include<linux/netfilter_ipv6/ip6t_condition.h>
+
+
+#ifndef CONFIG_PROC_FS
+#error "Proc file system support is required for this module"
+#endif
+
+
+MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
+MODULE_DESCRIPTION("Allows rules to match against condition variables");
+MODULE_LICENSE("GPL");
+
+
+struct condition_variable {
+ struct condition_variable *next;
+ struct proc_dir_entry *status_proc;
+ atomic_t refcount;
+ int enabled; /* TRUE == 1, FALSE == 0 */
+};
+
+
+static rwlock_t list_lock;
+static struct condition_variable *head = NULL;
+static struct proc_dir_entry *proc_net_condition = NULL;
+
+
+static int
+ipt_condition_read_info(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ struct condition_variable *var =
+ (struct condition_variable *) data;
+
+ if (offset == 0) {
+ *start = buffer;
+ buffer[0] = (var->enabled) ? '1' : '0';
+ buffer[1] = '\n';
+ return 2;
+ }
+
+ *eof = 1;
+ return 0;
+}
+
+
+static int
+ipt_condition_write_info(struct file *file, const char *buffer,
+ unsigned long length, void *data)
+{
+ struct condition_variable *var =
+ (struct condition_variable *) data;
+
+ if (length) {
+ /* Match only on the first character */
+ switch (buffer[0]) {
+ case '0':
+ var->enabled = 0;
+ break;
+ case '1':
+ var->enabled = 1;
+ }
+ }
+
+ return (int) length;
+}
+
+
+static int
+match(const struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, const void *matchinfo, int offset,
+ const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+ const struct condition6_info *info =
+ (const struct condition6_info *) matchinfo;
+ struct condition_variable *var;
+ int condition_status = 0;
+
+ read_lock(&list_lock);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ condition_status = var->enabled;
+ break;
+ }
+ }
+
+ read_unlock(&list_lock);
+
+ return condition_status ^ info->invert;
+}
+
+
+
+static int
+checkentry(const char *tablename, const struct ip6t_ip6 *ip,
+ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+ struct condition6_info *info =
+ (struct condition6_info *) matchinfo;
+ struct condition_variable *var, *newvar;
+
+ if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
+ return 0;
+
+ /* The first step is to check if the condition variable already exists. */
+ /* Here, a read lock is sufficient because we won't change the list */
+ read_lock(&list_lock);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ atomic_inc(&var->refcount);
+ read_unlock(&list_lock);
+ return 1;
+ }
+ }
+
+ read_unlock(&list_lock);
+
+ /* At this point, we need to allocate a new condition variable */
+ newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
+
+ if (!newvar)
+ return -ENOMEM;
+
+ /* Create the condition variable's proc file entry */
+ newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
+
+ if (!newvar->status_proc) {
+ /*
+ * There are two possibilities:
+ * 1- Another condition variable with the same name has been created, which is valid.
+ * 2- There was a memory allocation error.
+ */
+ kfree(newvar);
+ read_lock(&list_lock);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ atomic_inc(&var->refcount);
+ read_unlock(&list_lock);
+ return 1;
+ }
+ }
+
+ read_unlock(&list_lock);
+ return -ENOMEM;
+ }
+
+ atomic_set(&newvar->refcount, 1);
+ newvar->enabled = 0;
+ newvar->status_proc->owner = THIS_MODULE;
+ newvar->status_proc->data = newvar;
+ wmb();
+ newvar->status_proc->read_proc = ipt_condition_read_info;
+ newvar->status_proc->write_proc = ipt_condition_write_info;
+
+ write_lock(&list_lock);
+
+ newvar->next = head;
+ head = newvar;
+
+ write_unlock(&list_lock);
+
+ return 1;
+}
+
+
+static void
+destroy(void *matchinfo, unsigned int matchsize)
+{
+ struct condition6_info *info =
+ (struct condition6_info *) matchinfo;
+ struct condition_variable *var, *prev = NULL;
+
+ if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
+ return;
+
+ write_lock(&list_lock);
+
+ for (var = head; var && strcmp(info->name, var->status_proc->name);
+ prev = var, var = var->next);
+
+ if (var && atomic_dec_and_test(&var->refcount)) {
+ if (prev)
+ prev->next = var->next;
+ else
+ head = var->next;
+
+ write_unlock(&list_lock);
+ remove_proc_entry(var->status_proc->name, proc_net_condition);
+ kfree(var);
+ } else
+ write_unlock(&list_lock);
+}
+
+
+static struct ip6t_match condition_match = {
+ .name = "condition",
+ .match = &match,
+ .checkentry = &checkentry,
+ .destroy = &destroy,
+ .me = THIS_MODULE
+};
+
+
+static int __init
+init(void)
+{
+ int errorcode;
+
+ rwlock_init(&list_lock);
+ proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
+
+ if (proc_net_condition) {
+ errorcode = ipt_register_match(&condition_match);
+
+ if (errorcode)
+ remove_proc_entry("ip6t_condition", proc_net);
+ } else
+ errorcode = -EACCES;
+
+ return errorcode;
+}
+
+
+static void __exit
+fini(void)
+{
+ ipt_unregister_match(&condition_match);
+ remove_proc_entry("ip6t_condition", proc_net);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/release/src/linux/linux/net/sched/Config.in b/release/src/linux/linux/net/sched/Config.in
index 8e203456..468fdf2a 100644
--- a/release/src/linux/linux/net/sched/Config.in
+++ b/release/src/linux/linux/net/sched/Config.in
@@ -5,13 +5,14 @@ tristate ' CBQ packet scheduler' CONFIG_NET_SCH_CBQ
tristate ' HTB packet scheduler' CONFIG_NET_SCH_HTB
tristate ' CSZ packet scheduler' CONFIG_NET_SCH_CSZ
#tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
-#tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
+tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFSC
if [ "$CONFIG_ATM" = "y" ]; then
bool ' ATM pseudo-scheduler' CONFIG_NET_SCH_ATM
fi
tristate ' The simplest PRIO pseudoscheduler' CONFIG_NET_SCH_PRIO
tristate ' RED queue' CONFIG_NET_SCH_RED
tristate ' SFQ queue' CONFIG_NET_SCH_SFQ
+tristate ' ESFQ queue' CONFIG_NET_SCH_ESFQ
tristate ' TEQL queue' CONFIG_NET_SCH_TEQL
tristate ' TBF queue' CONFIG_NET_SCH_TBF
tristate ' GRED queue' CONFIG_NET_SCH_GRED
diff --git a/release/src/linux/linux/net/sched/Makefile b/release/src/linux/linux/net/sched/Makefile
index e48e5c3e..49cf71e7 100644
--- a/release/src/linux/linux/net/sched/Makefile
+++ b/release/src/linux/linux/net/sched/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
obj-$(CONFIG_NET_SCH_RED) += sch_red.o
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
diff --git a/release/src/linux/linux/net/sched/sch_api.c b/release/src/linux/linux/net/sched/sch_api.c
index a5d8945e..ae384433 100644
--- a/release/src/linux/linux/net/sched/sch_api.c
+++ b/release/src/linux/linux/net/sched/sch_api.c
@@ -1232,6 +1232,9 @@ int __init pktsched_init(void)
#ifdef CONFIG_NET_SCH_SFQ
INIT_QDISC(sfq);
#endif
+#ifdef CONFIG_NET_SCH_ESFQ
+ INIT_QDISC(esfq);
+#endif
#ifdef CONFIG_NET_SCH_TBF
INIT_QDISC(tbf);
#endif
diff --git a/release/src/linux/linux/net/sched/sch_esfq.c b/release/src/linux/linux/net/sched/sch_esfq.c
new file mode 100644
index 00000000..26640f18
--- /dev/null
+++ b/release/src/linux/linux/net/sched/sch_esfq.c
@@ -0,0 +1,652 @@
+/*
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
+ *
+ * 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.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
+ * Added dynamic depth,limit,divisor,hash_kind options.
+ * Added dst and src hashes.
+ *
+ * Alexander Clouter, <alex@digriz.org.uk>
+ * Ported ESFQ to Linux 2.6.
+ *
+ * Corey Hickey, <bugfood-c@fatooh.org>
+ * Maintenance of the Linux 2.6 port.
+ * Added fwmark hash (thanks to Robert Kurjata)
+ * Added direct hashing for src, dst, and fwmark.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/route.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+
+/* Stochastic Fairness Queuing algorithm.
+ For more comments look at sch_sfq.c.
+ The difference is that you can change limit, depth,
+ hash table size and choose 7 hash types.
+
+ classic: same as in sch_sfq.c
+ dst: destination IP address
+ src: source IP address
+ fwmark: netfilter mark value
+ dst_direct:
+ src_direct:
+ fwmark_direct: direct hashing of the above sources
+
+ TODO:
+ make sfq_change work.
+*/
+
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+#ifndef IPPROTO_DCCP
+#define IPPROTO_DCCP 33
+#endif
+
+/* This type should contain at least SFQ_DEPTH*2 values */
+typedef unsigned int esfq_index;
+
+struct esfq_head
+{
+ esfq_index next;
+ esfq_index prev;
+};
+
+struct esfq_sched_data
+{
+/* Parameters */
+ int perturb_period;
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
+ int limit;
+ unsigned depth;
+ unsigned hash_divisor;
+ unsigned hash_kind;
+/* Variables */
+ struct timer_list perturb_timer;
+ int perturbation;
+ esfq_index tail; /* Index of current slot in round */
+ esfq_index max_depth; /* Maximal depth */
+
+ esfq_index *ht; /* Hash table */
+ esfq_index *next; /* Active slots link */
+ short *allot; /* Current allotment per slot */
+ unsigned short *hash; /* Hash value indexed by slots */
+ struct sk_buff_head *qs; /* Slot queue */
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
+ unsigned dyn_min; /* For dynamic divisor adjustment; minimum value seen */
+ unsigned dyn_max; /* maximum value seen */
+ unsigned dyn_range; /* saved range */
+};
+
+static __inline__ unsigned esfq_hash_u32(struct esfq_sched_data *q,u32 h)
+{
+ int pert = q->perturbation;
+
+ if (pert)
+ h = (h<<pert) ^ (h>>(0x1F - pert));
+
+ h = ntohl(h) * 2654435761UL;
+ return h & (q->hash_divisor-1);
+}
+
+/* Hash input values directly into the "nearest" slot, taking into account the
+ * range of input values seen. This is most useful when the hash table is at
+ * least as large as the range of possible values. */
+static __inline__ unsigned esfq_hash_direct(struct esfq_sched_data *q, u32 h)
+{
+ /* adjust minimum and maximum */
+ if (h < q->dyn_min || h > q->dyn_max) {
+ q->dyn_min = h < q->dyn_min ? h : q->dyn_min;
+ q->dyn_max = h > q->dyn_max ? h : q->dyn_max;
+
+ /* find new range */
+ if ((q->dyn_range = q->dyn_max - q->dyn_min) >= q->hash_divisor)
+ printk(KERN_WARNING "ESFQ: (direct hash) Input range %u is larger than hash "
+ "table. See ESFQ README for details.\n", q->dyn_range);
+ }
+
+ /* hash input values into slot numbers */
+ if (q->dyn_min == q->dyn_max)
+ return 0; /* only one value seen; avoid division by 0 */
+ else
+ return (h - q->dyn_min) * (q->hash_divisor - 1) / q->dyn_range;
+}
+
+static __inline__ unsigned esfq_fold_hash_classic(struct esfq_sched_data *q, u32 h, u32 h1)
+{
+ int pert = q->perturbation;
+
+ /* Have we any rotation primitives? If not, WHY? */
+ h ^= (h1<<pert) ^ (h1>>(0x1F - pert));
+ h ^= h>>10;
+ return h & (q->hash_divisor-1);
+}
+
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
+{
+ u32 h, h2;
+ u32 hs;
+ u32 nfm;
+
+ switch (skb->protocol) {
+ case __constant_htons(ETH_P_IP):
+ {
+ struct iphdr *iph = skb->nh.iph;
+ h = iph->daddr;
+ hs = iph->saddr;
+ nfm = skb->nfmark;
+ h2 = hs^iph->protocol;
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
+ (iph->protocol == IPPROTO_TCP ||
+ iph->protocol == IPPROTO_UDP ||
+ iph->protocol == IPPROTO_SCTP ||
+ iph->protocol == IPPROTO_DCCP ||
+ iph->protocol == IPPROTO_ESP))
+ h2 ^= *(((u32*)iph) + iph->ihl);
+ break;
+ }
+ case __constant_htons(ETH_P_IPV6):
+ {
+ struct ipv6hdr *iph = skb->nh.ipv6h;
+ h = iph->daddr.s6_addr32[3];
+ hs = iph->saddr.s6_addr32[3];
+ nfm = skb->nfmark;
+ h2 = hs^iph->nexthdr;
+ if (iph->nexthdr == IPPROTO_TCP ||
+ iph->nexthdr == IPPROTO_UDP ||
+ iph->nexthdr == IPPROTO_SCTP ||
+ iph->nexthdr == IPPROTO_DCCP ||
+ iph->nexthdr == IPPROTO_ESP)
+ h2 ^= *(u32*)&iph[1];
+ break;
+ }
+ default:
+ h = (u32)(unsigned long)skb->dst;
+ hs = (u32)(unsigned long)skb->sk;
+ nfm = skb->nfmark;
+ h2 = hs^skb->protocol;
+ }
+ switch(q->hash_kind)
+ {
+ case TCA_SFQ_HASH_CLASSIC:
+ return esfq_fold_hash_classic(q, h, h2);
+ case TCA_SFQ_HASH_DST:
+ return esfq_hash_u32(q,h);
+ case TCA_SFQ_HASH_DSTDIR:
+ return esfq_hash_direct(q, ntohl(h));
+ case TCA_SFQ_HASH_SRC:
+ return esfq_hash_u32(q,hs);
+ case TCA_SFQ_HASH_SRCDIR:
+ return esfq_hash_direct(q, ntohl(hs));
+#ifdef CONFIG_NETFILTER
+ case TCA_SFQ_HASH_FWMARK:
+ return esfq_hash_u32(q,nfm);
+ case TCA_SFQ_HASH_FWMARKDIR:
+ return esfq_hash_direct(q,nfm);
+#endif
+ default:
+ if (net_ratelimit())
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
+ }
+ return esfq_fold_hash_classic(q, h, h2);
+}
+
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+ int d = q->qs[x].qlen + q->depth;
+
+ p = d;
+ n = q->dep[d].next;
+ q->dep[x].next = n;
+ q->dep[x].prev = p;
+ q->dep[p].next = q->dep[n].prev = x;
+}
+
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+
+ n = q->dep[x].next;
+ p = q->dep[x].prev;
+ q->dep[p].next = n;
+ q->dep[n].prev = p;
+
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
+ q->max_depth--;
+
+ esfq_link(q, x);
+}
+
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
+{
+ esfq_index p, n;
+ int d;
+
+ n = q->dep[x].next;
+ p = q->dep[x].prev;
+ q->dep[p].next = n;
+ q->dep[n].prev = p;
+ d = q->qs[x].qlen;
+ if (q->max_depth < d)
+ q->max_depth = d;
+
+ esfq_link(q, x);
+}
+
+static int esfq_drop(struct Qdisc *sch)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ esfq_index d = q->max_depth;
+ struct sk_buff *skb;
+ unsigned int len;
+
+ /* Queue is full! Find the longest slot and
+ drop a packet from it */
+
+ if (d > 1) {
+ esfq_index x = q->dep[d+q->depth].next;
+ skb = q->qs[x].prev;
+ len = skb->len;
+ __skb_unlink(skb, &q->qs[x]);
+ kfree_skb(skb);
+ esfq_dec(q, x);
+ sch->q.qlen--;
+ sch->stats.drops++;
+ return len;
+ }
+
+ if (d == 1) {
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
+ d = q->next[q->tail];
+ q->next[q->tail] = q->next[d];
+ q->allot[q->next[d]] += q->quantum;
+ skb = q->qs[d].prev;
+ len = skb->len;
+ __skb_unlink(skb, &q->qs[d]);
+ kfree_skb(skb);
+ esfq_dec(q, d);
+ sch->q.qlen--;
+ q->ht[q->hash[d]] = q->depth;
+ sch->stats.drops++;
+ return len;
+ }
+
+ return 0;
+}
+
+static int
+esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ unsigned hash = esfq_hash(q, skb);
+ unsigned depth = q->depth;
+ esfq_index x;
+
+ x = q->ht[hash];
+ if (x == depth) {
+ q->ht[hash] = x = q->dep[depth].next;
+ q->hash[x] = hash;
+ }
+ __skb_queue_tail(&q->qs[x], skb);
+ esfq_inc(q, x);
+ if (q->qs[x].qlen == 1) { /* The flow is new */
+ if (q->tail == depth) { /* It is the first flow */
+ q->tail = x;
+ q->next[x] = x;
+ q->allot[x] = q->quantum;
+ } else {
+ q->next[x] = q->next[q->tail];
+ q->next[q->tail] = x;
+ q->tail = x;
+ }
+ }
+ if (++sch->q.qlen < q->limit-1) {
+ sch->stats.bytes += skb->len;
+ sch->stats.packets++;
+ return 0;
+ }
+
+ esfq_drop(sch);
+ return NET_XMIT_CN;
+}
+
+static int
+esfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ unsigned hash = esfq_hash(q, skb);
+ unsigned depth = q->depth;
+ esfq_index x;
+
+ x = q->ht[hash];
+ if (x == depth) {
+ q->ht[hash] = x = q->dep[depth].next;
+ q->hash[x] = hash;
+ }
+ __skb_queue_head(&q->qs[x], skb);
+ esfq_inc(q, x);
+ if (q->qs[x].qlen == 1) { /* The flow is new */
+ if (q->tail == depth) { /* It is the first flow */
+ q->tail = x;
+ q->next[x] = x;
+ q->allot[x] = q->quantum;
+ } else {
+ q->next[x] = q->next[q->tail];
+ q->next[q->tail] = x;
+ q->tail = x;
+ }
+ }
+ if (++sch->q.qlen < q->limit - 1) {
+// sch->stats.requeues++;
+ return 0;
+ }
+
+ sch->stats.drops++;
+ esfq_drop(sch);
+ return NET_XMIT_CN;
+}
+
+
+
+
+static struct sk_buff *
+esfq_dequeue(struct Qdisc* sch)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ struct sk_buff *skb;
+ unsigned depth = q->depth;
+ esfq_index a, old_a;
+
+ /* No active slots */
+ if (q->tail == depth)
+ return NULL;
+
+ a = old_a = q->next[q->tail];
+
+ /* Grab packet */
+ skb = __skb_dequeue(&q->qs[a]);
+ esfq_dec(q, a);
+ sch->q.qlen--;
+
+ /* Is the slot empty? */
+ if (q->qs[a].qlen == 0) {
+ q->ht[q->hash[a]] = depth;
+ a = q->next[a];
+ if (a == old_a) {
+ q->tail = depth;
+ return skb;
+ }
+ q->next[q->tail] = a;
+ q->allot[a] += q->quantum;
+ } else if ((q->allot[a] -= skb->len) <= 0) {
+ q->tail = a;
+ a = q->next[a];
+ q->allot[a] += q->quantum;
+ }
+
+ return skb;
+}
+
+static void
+esfq_reset(struct Qdisc* sch)
+{
+ struct sk_buff *skb;
+
+ while ((skb = esfq_dequeue(sch)) != NULL)
+ kfree_skb(skb);
+}
+
+static void esfq_perturbation(unsigned long arg)
+{
+ struct Qdisc *sch = (struct Qdisc*)arg;
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+
+ q->perturbation = net_random()&0x1F;
+
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ }
+}
+
+/*
+static int esfq_change(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
+ int old_perturb = q->perturb_period;
+
+ if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+ return -EINVAL;
+
+ sch_tree_lock(sch);
+ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
+ q->perturb_period = ctl->perturb_period*HZ;
+// q->hash_divisor = ctl->divisor;
+// q->tail = q->limit = q->depth = ctl->flows;
+
+ if (ctl->limit)
+ q->limit = min_t(u32, ctl->limit, q->depth);
+
+ if (ctl->hash_kind) {
+ q->hash_kind = ctl->hash_kind;
+ if (q->hash_kind != TCA_SFQ_HASH_CLASSIC)
+ q->perturb_period = 0;
+ }
+
+ // is sch_tree_lock enough to do this ?
+ while (sch->q.qlen >= q->limit-1)
+ esfq_drop(sch);
+
+ if (old_perturb)
+ del_timer(&q->perturb_timer);
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ } else {
+ q->perturbation = 0;
+ }
+ sch_tree_unlock(sch);
+ return 0;
+}
+*/
+
+static int esfq_init(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ struct tc_esfq_qopt *ctl;
+ esfq_index p = ~0UL/2;
+ int i;
+
+ if (opt && opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+ return -EINVAL;
+
+ init_timer(&q->perturb_timer);
+ q->perturb_timer.data = (unsigned long)sch;
+ q->perturb_timer.function = esfq_perturbation;
+ q->perturbation = 0;
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
+ q->max_depth = 0;
+ q->dyn_min = ~0U; /* maximum value for this type */
+ q->dyn_max = 0; /* dyn_min/dyn_max will be set properly upon first packet */
+ if (opt == NULL) {
+ q->quantum = psched_mtu(sch->dev);
+ q->perturb_period = 0;
+ q->hash_divisor = 1024;
+ q->tail = q->limit = q->depth = 128;
+
+ } else {
+ ctl = RTA_DATA(opt);
+ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
+ q->perturb_period = ctl->perturb_period*HZ;
+ q->hash_divisor = ctl->divisor ? : 1024;
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
+
+ if ( q->depth > p - 1 )
+ return -EINVAL;
+
+ if (ctl->limit)
+ q->limit = min_t(u32, ctl->limit, q->depth);
+
+ if (ctl->hash_kind) {
+ q->hash_kind = ctl->hash_kind;
+ }
+
+ if (q->perturb_period) {
+ q->perturb_timer.expires = jiffies + q->perturb_period;
+ add_timer(&q->perturb_timer);
+ }
+ }
+
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
+ if (!q->ht)
+ goto err_case;
+
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
+ if (!q->dep)
+ goto err_case;
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
+ if (!q->next)
+ goto err_case;
+
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
+ if (!q->allot)
+ goto err_case;
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
+ if (!q->hash)
+ goto err_case;
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
+ if (!q->qs)
+ goto err_case;
+
+ for (i=0; i< q->hash_divisor; i++)
+ q->ht[i] = q->depth;
+ for (i=0; i<q->depth; i++) {
+ skb_queue_head_init(&q->qs[i]);
+ q->dep[i+q->depth].next = i+q->depth;
+ q->dep[i+q->depth].prev = i+q->depth;
+ }
+
+ for (i=0; i<q->depth; i++)
+ esfq_link(q, i);
+ return 0;
+err_case:
+ del_timer(&q->perturb_timer);
+ if (q->ht)
+ kfree(q->ht);
+ if (q->dep)
+ kfree(q->dep);
+ if (q->next)
+ kfree(q->next);
+ if (q->allot)
+ kfree(q->allot);
+ if (q->hash)
+ kfree(q->hash);
+ if (q->qs)
+ kfree(q->qs);
+ return -ENOBUFS;
+}
+
+static void esfq_destroy(struct Qdisc *sch)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ del_timer(&q->perturb_timer);
+ if(q->ht)
+ kfree(q->ht);
+ if(q->dep)
+ kfree(q->dep);
+ if(q->next)
+ kfree(q->next);
+ if(q->allot)
+ kfree(q->allot);
+ if(q->hash)
+ kfree(q->hash);
+ if(q->qs)
+ kfree(q->qs);
+}
+
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct esfq_sched_data *q = (struct esfq_sched_data *)sch->data;
+ unsigned char *b = skb->tail;
+ struct tc_esfq_qopt opt;
+
+ opt.quantum = q->quantum;
+ opt.perturb_period = q->perturb_period/HZ;
+
+ opt.limit = q->limit;
+ opt.divisor = q->hash_divisor;
+ opt.flows = q->depth;
+ opt.hash_kind = q->hash_kind;
+
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+ return skb->len;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static struct Qdisc_ops esfq_qdisc_ops =
+{
+ .next = NULL,
+ .cl_ops = NULL,
+ .id = "esfq",
+ .priv_size = sizeof(struct esfq_sched_data),
+ .enqueue = esfq_enqueue,
+ .dequeue = esfq_dequeue,
+ .requeue = esfq_requeue,
+ .drop = esfq_drop,
+ .init = esfq_init,
+ .reset = esfq_reset,
+ .destroy = esfq_destroy,
+ .change = NULL, /* esfq_change - needs more work */
+ .dump = esfq_dump,
+// .owner = THIS_MODULE,
+};
+
+static int __init esfq_module_init(void)
+{
+ return register_qdisc(&esfq_qdisc_ops);
+}
+static void __exit esfq_module_exit(void)
+{
+ unregister_qdisc(&esfq_qdisc_ops);
+}
+module_init(esfq_module_init)
+module_exit(esfq_module_exit)
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/sched/sch_fifo.c b/release/src/linux/linux/net/sched/sch_fifo.c
index d8ce46f2..3a7741e9 100644
--- a/release/src/linux/linux/net/sched/sch_fifo.c
+++ b/release/src/linux/linux/net/sched/sch_fifo.c
@@ -46,7 +46,7 @@ bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
{
struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data;
- if (sch->stats.backlog <= q->limit) {
+ if (sch->stats.backlog + skb->len <= q->limit) {
__skb_queue_tail(&sch->q, skb);
sch->stats.backlog += skb->len;
sch->stats.bytes += skb->len;
@@ -87,9 +87,10 @@ fifo_drop(struct Qdisc* sch)
skb = __skb_dequeue_tail(&sch->q);
if (skb) {
- sch->stats.backlog -= skb->len;
+ int len = skb->len;
+ sch->stats.backlog -= len;
kfree_skb(skb);
- return 1;
+ return len;
}
return 0;
}
@@ -106,7 +107,7 @@ pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
{
struct fifo_sched_data *q = (struct fifo_sched_data *)sch->data;
- if (sch->q.qlen <= q->limit) {
+ if (sch->q.qlen < q->limit) {
__skb_queue_tail(&sch->q, skb);
sch->stats.bytes += skb->len;
sch->stats.packets++;
@@ -139,10 +140,12 @@ static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
struct fifo_sched_data *q = (void*)sch->data;
if (opt == NULL) {
+ unsigned int limit = sch->dev->tx_queue_len ? : 1;
+
if (sch->ops == &bfifo_qdisc_ops)
- q->limit = sch->dev->tx_queue_len*sch->dev->mtu;
+ q->limit = limit*sch->dev->mtu;
else
- q->limit = sch->dev->tx_queue_len;
+ q->limit = limit;
} else {
struct tc_fifo_qopt *ctl = RTA_DATA(opt);
if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
diff --git a/release/src/linux/linux/net/sched/sch_generic.c b/release/src/linux/linux/net/sched/sch_generic.c
index 7b0d49e7..ca30d124 100644
--- a/release/src/linux/linux/net/sched/sch_generic.c
+++ b/release/src/linux/linux/net/sched/sch_generic.c
@@ -29,6 +29,9 @@
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+#include <linux/imq.h>
+#endif
#include <net/sock.h>
#include <net/pkt_sched.h>
@@ -79,6 +82,10 @@ int qdisc_restart(struct net_device *dev)
struct Qdisc *q = dev->qdisc;
struct sk_buff *skb;
+ /* BRCM: bail out if queue is null */
+ if (!q)
+ return 0;
+
/* Dequeue packet */
if ((skb = q->dequeue(q)) != NULL) {
if (spin_trylock(&dev->xmit_lock)) {
@@ -89,7 +96,11 @@ int qdisc_restart(struct net_device *dev)
spin_unlock(&dev->queue_lock);
if (!netif_queue_stopped(dev)) {
- if (netdev_nit)
+ if (netdev_nit
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
+#endif
+ )
dev_queue_xmit_nit(skb, dev);
if (dev->hard_start_xmit(skb, dev) == 0) {
diff --git a/release/src/linux/linux/net/sched/sch_hfsc.c b/release/src/linux/linux/net/sched/sch_hfsc.c
new file mode 100644
index 00000000..0b6e6d38
--- /dev/null
+++ b/release/src/linux/linux/net/sched/sch_hfsc.c
@@ -0,0 +1,1817 @@
+/*
+ * Copyright (c) 2003 Patrick McHardy, <kaber@trash.net>
+ *
+ * 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.
+ *
+ * 2003-10-17 - Ported from altq
+ */
+/*
+ * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation is hereby granted (including for commercial or
+ * for-profit use), provided that both the copyright notice and this
+ * permission notice appear in all copies of the software, derivative
+ * works, or modified versions, and any portions thereof.
+ *
+ * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF
+ * WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS
+ * SOFTWARE IN ITS ``AS IS'' CONDITION, 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 CARNEGIE MELLON UNIVERSITY 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.
+ *
+ * Carnegie Mellon encourages (but does not require) users of this
+ * software to return any improvements or extensions that they make,
+ * and to grant Carnegie Mellon the rights to redistribute these
+ * changes without encumbrance.
+ */
+/*
+ * H-FSC is described in Proceedings of SIGCOMM'97,
+ * "A Hierarchical Fair Service Curve Algorithm for Link-Sharing,
+ * Real-Time and Priority Service"
+ * by Ion Stoica, Hui Zhang, and T. S. Eugene Ng.
+ *
+ * Oleg Cherevko <olwi@aq.ml.com.ua> added the upperlimit for link-sharing.
+ * when a class has an upperlimit, the fit-time is computed from the
+ * upperlimit service curve. the link-sharing scheduler does not schedule
+ * a class whose fit-time exceeds the current time.
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/pkt_sched.h>
+#include <net/pkt_sched.h>
+#include <net/pkt_cls.h>
+#include <asm/system.h>
+#include <asm/div64.h>
+
+#define HFSC_DEBUG 0
+
+/*
+ * kernel internal service curve representation:
+ * coordinates are given by 64 bit unsigned integers.
+ * x-axis: unit is clock count.
+ * y-axis: unit is byte.
+ *
+ * The service curve parameters are converted to the internal
+ * representation. The slope values are scaled to avoid overflow.
+ * the inverse slope values as well as the y-projection of the 1st
+ * segment are kept in order to to avoid 64-bit divide operations
+ * that are expensive on 32-bit architectures.
+ */
+
+struct internal_sc
+{
+ u64 sm1; /* scaled slope of the 1st segment */
+ u64 ism1; /* scaled inverse-slope of the 1st segment */
+ u64 dx; /* the x-projection of the 1st segment */
+ u64 dy; /* the y-projection of the 1st segment */
+ u64 sm2; /* scaled slope of the 2nd segment */
+ u64 ism2; /* scaled inverse-slope of the 2nd segment */
+};
+
+/* runtime service curve */
+struct runtime_sc
+{
+ u64 x; /* current starting position on x-axis */
+ u64 y; /* current starting position on y-axis */
+ u64 sm1; /* scaled slope of the 1st segment */
+ u64 ism1; /* scaled inverse-slope of the 1st segment */
+ u64 dx; /* the x-projection of the 1st segment */
+ u64 dy; /* the y-projection of the 1st segment */
+ u64 sm2; /* scaled slope of the 2nd segment */
+ u64 ism2; /* scaled inverse-slope of the 2nd segment */
+};
+
+enum hfsc_class_flags
+{
+ HFSC_RSC = 0x1,
+ HFSC_FSC = 0x2,
+ HFSC_USC = 0x4
+};
+
+struct hfsc_class
+{
+ u32 classid; /* class id */
+ unsigned int refcnt; /* usage count */
+
+ struct tc_stats stats; /* generic statistics */
+ unsigned int level; /* class level in hierarchy */
+ struct tcf_proto *filter_list; /* filter list */
+ unsigned int filter_cnt; /* filter count */
+
+ struct hfsc_sched *sched; /* scheduler data */
+ struct hfsc_class *cl_parent; /* parent class */
+ struct list_head siblings; /* sibling classes */
+ struct list_head children; /* child classes */
+ struct Qdisc *qdisc; /* leaf qdisc */
+
+ rb_node_t el_node; /* qdisc's eligible tree member */
+ rb_root_t vt_tree; /* active children sorted by cl_vt */
+ rb_node_t vt_node; /* parent's vt_tree member */
+ rb_root_t cf_tree; /* active children sorted by cl_f */
+ rb_node_t cf_node; /* parent's cf_heap member */
+ struct list_head hlist; /* hash list member */
+ struct list_head dlist; /* drop list member */
+
+ u64 cl_total; /* total work in bytes */
+ u64 cl_cumul; /* cumulative work in bytes done by
+ real-time criteria */
+
+ u64 cl_d; /* deadline*/
+ u64 cl_e; /* eligible time */
+ u64 cl_vt; /* virtual time */
+ u64 cl_f; /* time when this class will fit for
+ link-sharing, max(myf, cfmin) */
+ u64 cl_myf; /* my fit-time (calculated from this
+ class's own upperlimit curve) */
+ u64 cl_myfadj; /* my fit-time adjustment (to cancel
+ history dependence) */
+ u64 cl_cfmin; /* earliest children's fit-time (used
+ with cl_myf to obtain cl_f) */
+ u64 cl_cvtmin; /* minimal virtual time among the
+ children fit for link-sharing
+ (monotonic within a period) */
+ u64 cl_vtadj; /* intra-period cumulative vt
+ adjustment */
+ u64 cl_vtoff; /* inter-period cumulative vt offset */
+ u64 cl_cvtmax; /* max child's vt in the last period */
+ u64 cl_cvtoff; /* cumulative cvtmax of all periods */
+ u64 cl_pcvtoff; /* parent's cvtoff at initalization
+ time */
+
+ struct internal_sc cl_rsc; /* internal real-time service curve */
+ struct internal_sc cl_fsc; /* internal fair service curve */
+ struct internal_sc cl_usc; /* internal upperlimit service curve */
+ struct runtime_sc cl_deadline; /* deadline curve */
+ struct runtime_sc cl_eligible; /* eligible curve */
+ struct runtime_sc cl_virtual; /* virtual curve */
+ struct runtime_sc cl_ulimit; /* upperlimit curve */
+
+ unsigned long cl_flags; /* which curves are valid */
+ unsigned long cl_vtperiod; /* vt period sequence number */
+ unsigned long cl_parentperiod;/* parent's vt period sequence number*/
+ unsigned long cl_nactive; /* number of active children */
+};
+
+#define HFSC_HSIZE 16
+
+struct hfsc_sched
+{
+ u16 defcls; /* default class id */
+ struct hfsc_class root; /* root class */
+ struct list_head clhash[HFSC_HSIZE]; /* class hash */
+ rb_root_t eligible; /* eligible tree */
+ struct list_head droplist; /* active leaf class list (for
+ dropping) */
+ struct sk_buff_head requeue; /* requeued packet */
+ struct timer_list wd_timer; /* watchdog timer */
+};
+
+/*
+ * macros
+ */
+#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
+#include <linux/time.h>
+#undef PSCHED_GET_TIME
+#define PSCHED_GET_TIME(stamp) \
+do { \
+ struct timeval tv; \
+ do_gettimeofday(&tv); \
+ (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec; \
+} while (0)
+#endif
+
+#if HFSC_DEBUG
+#define ASSERT(cond) \
+do { \
+ if (unlikely(!(cond))) \
+ printk("assertion %s failed at %s:%i (%s)\n", \
+ #cond, __FILE__, __LINE__, __FUNCTION__); \
+} while (0)
+#else
+#define ASSERT(cond)
+#endif /* HFSC_DEBUG */
+
+#define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */
+
+
+/*
+ * eligible tree holds backlogged classes being sorted by their eligible times.
+ * there is one eligible tree per hfsc instance.
+ */
+
+static void
+eltree_insert(struct hfsc_class *cl)
+{
+ rb_node_t **p = &cl->sched->eligible.rb_node;
+ rb_node_t *parent = NULL;
+ struct hfsc_class *cl1;
+
+ while (*p != NULL) {
+ parent = *p;
+ cl1 = rb_entry(parent, struct hfsc_class, el_node);
+ if (cl->cl_e >= cl1->cl_e)
+ p = &parent->rb_right;
+ else
+ p = &parent->rb_left;
+ }
+ rb_link_node(&cl->el_node, parent, p);
+ rb_insert_color(&cl->el_node, &cl->sched->eligible);
+}
+
+static inline void
+eltree_remove(struct hfsc_class *cl)
+{
+ rb_erase(&cl->el_node, &cl->sched->eligible);
+}
+
+static inline void
+eltree_update(struct hfsc_class *cl)
+{
+ eltree_remove(cl);
+ eltree_insert(cl);
+}
+
+/* find the class with the minimum deadline among the eligible classes */
+static inline struct hfsc_class *
+eltree_get_mindl(struct hfsc_sched *q, u64 cur_time)
+{
+ struct hfsc_class *p, *cl = NULL;
+ rb_node_t *n;
+
+ for (n = rb_first(&q->eligible); n != NULL; n = rb_next(n)) {
+ p = rb_entry(n, struct hfsc_class, el_node);
+ if (p->cl_e > cur_time)
+ break;
+ if (cl == NULL || p->cl_d < cl->cl_d)
+ cl = p;
+ }
+ return cl;
+}
+
+/* find the class with minimum eligible time among the eligible classes */
+static inline struct hfsc_class *
+eltree_get_minel(struct hfsc_sched *q)
+{
+ rb_node_t *n;
+
+ n = rb_first(&q->eligible);
+ if (n == NULL)
+ return NULL;
+ return rb_entry(n, struct hfsc_class, el_node);
+}
+
+/*
+ * vttree holds holds backlogged child classes being sorted by their virtual
+ * time. each intermediate class has one vttree.
+ */
+static void
+vttree_insert(struct hfsc_class *cl)
+{
+ rb_node_t **p = &cl->cl_parent->vt_tree.rb_node;
+ rb_node_t *parent = NULL;
+ struct hfsc_class *cl1;
+
+ while (*p != NULL) {
+ parent = *p;
+ cl1 = rb_entry(parent, struct hfsc_class, vt_node);
+ if (cl->cl_vt >= cl1->cl_vt)
+ p = &parent->rb_right;
+ else
+ p = &parent->rb_left;
+ }
+ rb_link_node(&cl->vt_node, parent, p);
+ rb_insert_color(&cl->vt_node, &cl->cl_parent->vt_tree);
+}
+
+static inline void
+vttree_remove(struct hfsc_class *cl)
+{
+ rb_erase(&cl->vt_node, &cl->cl_parent->vt_tree);
+}
+
+static inline void
+vttree_update(struct hfsc_class *cl)
+{
+ vttree_remove(cl);
+ vttree_insert(cl);
+}
+
+static inline struct hfsc_class *
+vttree_firstfit(struct hfsc_class *cl, u64 cur_time)
+{
+ struct hfsc_class *p;
+ rb_node_t *n;
+
+ for (n = rb_first(&cl->vt_tree); n != NULL; n = rb_next(n)) {
+ p = rb_entry(n, struct hfsc_class, vt_node);
+ if (p->cl_f <= cur_time)
+ return p;
+ }
+ return NULL;
+}
+
+/*
+ * get the leaf class with the minimum vt in the hierarchy
+ */
+static struct hfsc_class *
+vttree_get_minvt(struct hfsc_class *cl, u64 cur_time)
+{
+ /* if root-class's cfmin is bigger than cur_time nothing to do */
+ if (cl->cl_cfmin > cur_time)
+ return NULL;
+
+ while (cl->level > 0) {
+ cl = vttree_firstfit(cl, cur_time);
+ if (cl == NULL)
+ return NULL;
+ /*
+ * update parent's cl_cvtmin.
+ */
+ if (cl->cl_parent->cl_cvtmin < cl->cl_vt)
+ cl->cl_parent->cl_cvtmin = cl->cl_vt;
+ }
+ return cl;
+}
+
+static void
+cftree_insert(struct hfsc_class *cl)
+{
+ rb_node_t **p = &cl->cl_parent->cf_tree.rb_node;
+ rb_node_t *parent = NULL;
+ struct hfsc_class *cl1;
+
+ while (*p != NULL) {
+ parent = *p;
+ cl1 = rb_entry(parent, struct hfsc_class, cf_node);
+ if (cl->cl_f >= cl1->cl_f)
+ p = &parent->rb_right;
+ else
+ p = &parent->rb_left;
+ }
+ rb_link_node(&cl->cf_node, parent, p);
+ rb_insert_color(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_remove(struct hfsc_class *cl)
+{
+ rb_erase(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_update(struct hfsc_class *cl)
+{
+ cftree_remove(cl);
+ cftree_insert(cl);
+}
+
+/*
+ * service curve support functions
+ *
+ * external service curve parameters
+ * m: bps
+ * d: us
+ * internal service curve parameters
+ * sm: (bytes/psched_us) << SM_SHIFT
+ * ism: (psched_us/byte) << ISM_SHIFT
+ * dx: psched_us
+ *
+ * Time source resolution
+ * PSCHED_JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us.
+ * PSCHED_CPU: resolution is between 0.5us and 1us.
+ * PSCHED_GETTIMEOFDAY: resolution is exactly 1us.
+ *
+ * sm and ism are scaled in order to keep effective digits.
+ * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective
+ * digits in decimal using the following table.
+ *
+ * Note: We can afford the additional accuracy (altq hfsc keeps at most
+ * 3 effective digits) thanks to the fact that linux clock is bounded
+ * much more tightly.
+ *
+ * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps
+ * ------------+-------------------------------------------------------
+ * bytes/0.5us 6.25e-3 62.5e-3 625e-3 6250e-e 62500e-3
+ * bytes/us 12.5e-3 125e-3 1250e-3 12500e-3 125000e-3
+ * bytes/1.27us 15.875e-3 158.75e-3 1587.5e-3 15875e-3 158750e-3
+ *
+ * 0.5us/byte 160 16 1.6 0.16 0.016
+ * us/byte 80 8 0.8 0.08 0.008
+ * 1.27us/byte 63 6.3 0.63 0.063 0.0063
+ */
+#define SM_SHIFT 20
+#define ISM_SHIFT 18
+
+#define SM_MASK ((1ULL << SM_SHIFT) - 1)
+#define ISM_MASK ((1ULL << ISM_SHIFT) - 1)
+
+static inline u64
+seg_x2y(u64 x, u64 sm)
+{
+ u64 y;
+
+ /*
+ * compute
+ * y = x * sm >> SM_SHIFT
+ * but divide it for the upper and lower bits to avoid overflow
+ */
+ y = (x >> SM_SHIFT) * sm + (((x & SM_MASK) * sm) >> SM_SHIFT);
+ return y;
+}
+
+static inline u64
+seg_y2x(u64 y, u64 ism)
+{
+ u64 x;
+
+ if (y == 0)
+ x = 0;
+ else if (ism == HT_INFINITY)
+ x = HT_INFINITY;
+ else {
+ x = (y >> ISM_SHIFT) * ism
+ + (((y & ISM_MASK) * ism) >> ISM_SHIFT);
+ }
+ return x;
+}
+
+/* Convert m (bps) into sm (bytes/psched us) */
+static u64
+m2sm(u32 m)
+{
+ u64 sm;
+
+ sm = ((u64)m << SM_SHIFT);
+ sm += PSCHED_JIFFIE2US(HZ) - 1;
+ do_div(sm, PSCHED_JIFFIE2US(HZ));
+ return sm;
+}
+
+/* convert m (bps) into ism (psched us/byte) */
+static u64
+m2ism(u32 m)
+{
+ u64 ism;
+
+ if (m == 0)
+ ism = HT_INFINITY;
+ else {
+ ism = ((u64)PSCHED_JIFFIE2US(HZ) << ISM_SHIFT);
+ ism += m - 1;
+ do_div(ism, m);
+ }
+ return ism;
+}
+
+/* convert d (us) into dx (psched us) */
+static u64
+d2dx(u32 d)
+{
+ u64 dx;
+
+ dx = ((u64)d * PSCHED_JIFFIE2US(HZ));
+ dx += 1000000 - 1;
+ do_div(dx, 1000000);
+ return dx;
+}
+
+/* convert sm (bytes/psched us) into m (bps) */
+static u32
+sm2m(u64 sm)
+{
+ u64 m;
+
+ m = (sm * PSCHED_JIFFIE2US(HZ)) >> SM_SHIFT;
+ return (u32)m;
+}
+
+/* convert dx (psched us) into d (us) */
+static u32
+dx2d(u64 dx)
+{
+ u64 d;
+
+ d = dx * 1000000;
+ do_div(d, PSCHED_JIFFIE2US(HZ));
+ return (u32)d;
+}
+
+static void
+sc2isc(struct tc_service_curve *sc, struct internal_sc *isc)
+{
+ isc->sm1 = m2sm(sc->m1);
+ isc->ism1 = m2ism(sc->m1);
+ isc->dx = d2dx(sc->d);
+ isc->dy = seg_x2y(isc->dx, isc->sm1);
+ isc->sm2 = m2sm(sc->m2);
+ isc->ism2 = m2ism(sc->m2);
+}
+
+/*
+ * initialize the runtime service curve with the given internal
+ * service curve starting at (x, y).
+ */
+static void
+rtsc_init(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y)
+{
+ rtsc->x = x;
+ rtsc->y = y;
+ rtsc->sm1 = isc->sm1;
+ rtsc->ism1 = isc->ism1;
+ rtsc->dx = isc->dx;
+ rtsc->dy = isc->dy;
+ rtsc->sm2 = isc->sm2;
+ rtsc->ism2 = isc->ism2;
+}
+
+/*
+ * calculate the y-projection of the runtime service curve by the
+ * given x-projection value
+ */
+static u64
+rtsc_y2x(struct runtime_sc *rtsc, u64 y)
+{
+ u64 x;
+
+ if (y < rtsc->y)
+ x = rtsc->x;
+ else if (y <= rtsc->y + rtsc->dy) {
+ /* x belongs to the 1st segment */
+ if (rtsc->dy == 0)
+ x = rtsc->x + rtsc->dx;
+ else
+ x = rtsc->x + seg_y2x(y - rtsc->y, rtsc->ism1);
+ } else {
+ /* x belongs to the 2nd segment */
+ x = rtsc->x + rtsc->dx
+ + seg_y2x(y - rtsc->y - rtsc->dy, rtsc->ism2);
+ }
+ return x;
+}
+
+static u64
+rtsc_x2y(struct runtime_sc *rtsc, u64 x)
+{
+ u64 y;
+
+ if (x <= rtsc->x)
+ y = rtsc->y;
+ else if (x <= rtsc->x + rtsc->dx)
+ /* y belongs to the 1st segment */
+ y = rtsc->y + seg_x2y(x - rtsc->x, rtsc->sm1);
+ else
+ /* y belongs to the 2nd segment */
+ y = rtsc->y + rtsc->dy
+ + seg_x2y(x - rtsc->x - rtsc->dx, rtsc->sm2);
+ return y;
+}
+
+/*
+ * update the runtime service curve by taking the minimum of the current
+ * runtime service curve and the service curve starting at (x, y).
+ */
+static void
+rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y)
+{
+ u64 y1, y2, dx, dy;
+ u32 dsm;
+
+ if (isc->sm1 <= isc->sm2) {
+ /* service curve is convex */
+ y1 = rtsc_x2y(rtsc, x);
+ if (y1 < y)
+ /* the current rtsc is smaller */
+ return;
+ rtsc->x = x;
+ rtsc->y = y;
+ return;
+ }
+
+ /*
+ * service curve is concave
+ * compute the two y values of the current rtsc
+ * y1: at x
+ * y2: at (x + dx)
+ */
+ y1 = rtsc_x2y(rtsc, x);
+ if (y1 <= y) {
+ /* rtsc is below isc, no change to rtsc */
+ return;
+ }
+
+ y2 = rtsc_x2y(rtsc, x + isc->dx);
+ if (y2 >= y + isc->dy) {
+ /* rtsc is above isc, replace rtsc by isc */
+ rtsc->x = x;
+ rtsc->y = y;
+ rtsc->dx = isc->dx;
+ rtsc->dy = isc->dy;
+ return;
+ }
+
+ /*
+ * the two curves intersect
+ * compute the offsets (dx, dy) using the reverse
+ * function of seg_x2y()
+ * seg_x2y(dx, sm1) == seg_x2y(dx, sm2) + (y1 - y)
+ */
+ dx = (y1 - y) << SM_SHIFT;
+ dsm = isc->sm1 - isc->sm2;
+ do_div(dx, dsm);
+ /*
+ * check if (x, y1) belongs to the 1st segment of rtsc.
+ * if so, add the offset.
+ */
+ if (rtsc->x + rtsc->dx > x)
+ dx += rtsc->x + rtsc->dx - x;
+ dy = seg_x2y(dx, isc->sm1);
+
+ rtsc->x = x;
+ rtsc->y = y;
+ rtsc->dx = dx;
+ rtsc->dy = dy;
+ return;
+}
+
+static void
+init_ed(struct hfsc_class *cl, unsigned int next_len)
+{
+ u64 cur_time;
+
+ PSCHED_GET_TIME(cur_time);
+
+ /* update the deadline curve */
+ rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
+
+ /*
+ * update the eligible curve.
+ * for concave, it is equal to the deadline curve.
+ * for convex, it is a linear curve with slope m2.
+ */
+ cl->cl_eligible = cl->cl_deadline;
+ if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) {
+ cl->cl_eligible.dx = 0;
+ cl->cl_eligible.dy = 0;
+ }
+
+ /* compute e and d */
+ cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
+ cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+
+ eltree_insert(cl);
+}
+
+static void
+update_ed(struct hfsc_class *cl, unsigned int next_len)
+{
+ cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
+ cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+
+ eltree_update(cl);
+}
+
+static inline void
+update_d(struct hfsc_class *cl, unsigned int next_len)
+{
+ cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+}
+
+static inline void
+update_cfmin(struct hfsc_class *cl)
+{
+ rb_node_t *n = rb_first(&cl->cf_tree);
+ struct hfsc_class *p;
+
+ if (n == NULL) {
+ cl->cl_cfmin = 0;
+ return;
+ }
+ p = rb_entry(n, struct hfsc_class, cf_node);
+ cl->cl_cfmin = p->cl_f;
+}
+
+static void
+init_vf(struct hfsc_class *cl, unsigned int len)
+{
+ struct hfsc_class *max_cl;
+ rb_node_t *n;
+ u64 vt, f, cur_time;
+ int go_active;
+
+ cur_time = 0;
+ go_active = 1;
+ for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
+ if (go_active && cl->cl_nactive++ == 0)
+ go_active = 1;
+ else
+ go_active = 0;
+
+ if (go_active) {
+ n = rb_last(&cl->cl_parent->vt_tree);
+ if (n != NULL) {
+ max_cl = rb_entry(n, struct hfsc_class,vt_node);
+ /*
+ * set vt to the average of the min and max
+ * classes. if the parent's period didn't
+ * change, don't decrease vt of the class.
+ */
+ vt = max_cl->cl_vt;
+ if (cl->cl_parent->cl_cvtmin != 0)
+ vt = (cl->cl_parent->cl_cvtmin + vt)/2;
+
+ if (cl->cl_parent->cl_vtperiod !=
+ cl->cl_parentperiod || vt > cl->cl_vt)
+ cl->cl_vt = vt;
+ } else {
+ /*
+ * first child for a new parent backlog period.
+ * add parent's cvtmax to cvtoff to make a new
+ * vt (vtoff + vt) larger than the vt in the
+ * last period for all children.
+ */
+ vt = cl->cl_parent->cl_cvtmax;
+ cl->cl_parent->cl_cvtoff += vt;
+ cl->cl_parent->cl_cvtmax = 0;
+ cl->cl_parent->cl_cvtmin = 0;
+ cl->cl_vt = 0;
+ }
+
+ cl->cl_vtoff = cl->cl_parent->cl_cvtoff -
+ cl->cl_pcvtoff;
+
+ /* update the virtual curve */
+ vt = cl->cl_vt + cl->cl_vtoff;
+ rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
+ cl->cl_total);
+ if (cl->cl_virtual.x == vt) {
+ cl->cl_virtual.x -= cl->cl_vtoff;
+ cl->cl_vtoff = 0;
+ }
+ cl->cl_vtadj = 0;
+
+ cl->cl_vtperiod++; /* increment vt period */
+ cl->cl_parentperiod = cl->cl_parent->cl_vtperiod;
+ if (cl->cl_parent->cl_nactive == 0)
+ cl->cl_parentperiod++;
+ cl->cl_f = 0;
+
+ vttree_insert(cl);
+ cftree_insert(cl);
+
+ if (cl->cl_flags & HFSC_USC) {
+ /* class has upper limit curve */
+ if (cur_time == 0)
+ PSCHED_GET_TIME(cur_time);
+
+ /* update the ulimit curve */
+ rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time,
+ cl->cl_total);
+ /* compute myf */
+ cl->cl_myf = rtsc_y2x(&cl->cl_ulimit,
+ cl->cl_total);
+ cl->cl_myfadj = 0;
+ }
+ }
+
+ f = max(cl->cl_myf, cl->cl_cfmin);
+ if (f != cl->cl_f) {
+ cl->cl_f = f;
+ cftree_update(cl);
+ update_cfmin(cl->cl_parent);
+ }
+ }
+}
+
+static void
+update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
+{
+ u64 f; /* , myf_bound, delta; */
+ int go_passive = 0;
+
+ if (cl->qdisc->q.qlen == 0 && cl->cl_flags & HFSC_FSC)
+ go_passive = 1;
+
+ for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
+ cl->cl_total += len;
+
+ if (!(cl->cl_flags & HFSC_FSC) || cl->cl_nactive == 0)
+ continue;
+
+ if (go_passive && --cl->cl_nactive == 0)
+ go_passive = 1;
+ else
+ go_passive = 0;
+
+ if (go_passive) {
+ /* no more active child, going passive */
+
+ /* update cvtmax of the parent class */
+ if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
+ cl->cl_parent->cl_cvtmax = cl->cl_vt;
+
+ /* remove this class from the vt tree */
+ vttree_remove(cl);
+
+ cftree_remove(cl);
+ update_cfmin(cl->cl_parent);
+
+ continue;
+ }
+
+ /*
+ * update vt and f
+ */
+ cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total)
+ - cl->cl_vtoff + cl->cl_vtadj;
+
+ /*
+ * if vt of the class is smaller than cvtmin,
+ * the class was skipped in the past due to non-fit.
+ * if so, we need to adjust vtadj.
+ */
+ if (cl->cl_vt < cl->cl_parent->cl_cvtmin) {
+ cl->cl_vtadj += cl->cl_parent->cl_cvtmin - cl->cl_vt;
+ cl->cl_vt = cl->cl_parent->cl_cvtmin;
+ }
+
+ /* update the vt tree */
+ vttree_update(cl);
+
+ if (cl->cl_flags & HFSC_USC) {
+ cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
+ cl->cl_total);
+#if 0
+ /*
+ * This code causes classes to stay way under their
+ * limit when multiple classes are used at gigabit
+ * speed. needs investigation. -kaber
+ */
+ /*
+ * if myf lags behind by more than one clock tick
+ * from the current time, adjust myfadj to prevent
+ * a rate-limited class from going greedy.
+ * in a steady state under rate-limiting, myf
+ * fluctuates within one clock tick.
+ */
+ myf_bound = cur_time - PSCHED_JIFFIE2US(1);
+ if (cl->cl_myf < myf_bound) {
+ delta = cur_time - cl->cl_myf;
+ cl->cl_myfadj += delta;
+ cl->cl_myf += delta;
+ }
+#endif
+ }
+
+ f = max(cl->cl_myf, cl->cl_cfmin);
+ if (f != cl->cl_f) {
+ cl->cl_f = f;
+ cftree_update(cl);
+ update_cfmin(cl->cl_parent);
+ }
+ }
+}
+
+static void
+set_active(struct hfsc_class *cl, unsigned int len)
+{
+ if (cl->cl_flags & HFSC_RSC)
+ init_ed(cl, len);
+ if (cl->cl_flags & HFSC_FSC)
+ init_vf(cl, len);
+
+ list_add_tail(&cl->dlist, &cl->sched->droplist);
+}
+
+static void
+set_passive(struct hfsc_class *cl)
+{
+ if (cl->cl_flags & HFSC_RSC)
+ eltree_remove(cl);
+
+ list_del(&cl->dlist);
+
+ /*
+ * vttree is now handled in update_vf() so that update_vf(cl, 0, 0)
+ * needs to be called explicitly to remove a class from vttree.
+ */
+}
+
+/*
+ * hack to get length of first packet in queue.
+ */
+static unsigned int
+qdisc_peek_len(struct Qdisc *sch)
+{
+ struct sk_buff *skb;
+ unsigned int len;
+
+ skb = sch->dequeue(sch);
+ if (skb == NULL) {
+ if (net_ratelimit())
+ printk("qdisc_peek_len: non work-conserving qdisc ?\n");
+ return 0;
+ }
+ len = skb->len;
+ if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
+ if (net_ratelimit())
+ printk("qdisc_peek_len: failed to requeue\n");
+ return 0;
+ }
+ return len;
+}
+
+static void
+hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
+{
+ unsigned int len = cl->qdisc->q.qlen;
+
+ qdisc_reset(cl->qdisc);
+ if (len > 0) {
+ update_vf(cl, 0, 0);
+ set_passive(cl);
+ sch->q.qlen -= len;
+ }
+}
+
+static void
+hfsc_adjust_levels(struct hfsc_class *cl)
+{
+ struct hfsc_class *p;
+ unsigned int level;
+
+ do {
+ level = 0;
+ list_for_each_entry(p, &cl->children, siblings) {
+ if (p->level > level)
+ level = p->level;
+ }
+ cl->level = level + 1;
+ } while ((cl = cl->cl_parent) != NULL);
+}
+
+static inline unsigned int
+hfsc_hash(u32 h)
+{
+ h ^= h >> 8;
+ h ^= h >> 4;
+
+ return h & (HFSC_HSIZE - 1);
+}
+
+static inline struct hfsc_class *
+hfsc_find_class(u32 classid, struct Qdisc *sch)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl;
+
+ list_for_each_entry(cl, &q->clhash[hfsc_hash(classid)], hlist) {
+ if (cl->classid == classid)
+ return cl;
+ }
+ return NULL;
+}
+
+static void
+hfsc_change_rsc(struct hfsc_class *cl, struct tc_service_curve *rsc,
+ u64 cur_time)
+{
+ sc2isc(rsc, &cl->cl_rsc);
+ rtsc_init(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
+ cl->cl_eligible = cl->cl_deadline;
+ if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) {
+ cl->cl_eligible.dx = 0;
+ cl->cl_eligible.dy = 0;
+ }
+ cl->cl_flags |= HFSC_RSC;
+}
+
+static void
+hfsc_change_fsc(struct hfsc_class *cl, struct tc_service_curve *fsc)
+{
+ sc2isc(fsc, &cl->cl_fsc);
+ rtsc_init(&cl->cl_virtual, &cl->cl_fsc, cl->cl_vt, cl->cl_total);
+ cl->cl_flags |= HFSC_FSC;
+}
+
+static void
+hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
+ u64 cur_time)
+{
+ sc2isc(usc, &cl->cl_usc);
+ rtsc_init(&cl->cl_ulimit, &cl->cl_usc, cur_time, cl->cl_total);
+ cl->cl_flags |= HFSC_USC;
+}
+
+static int
+hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
+ struct rtattr **tca, unsigned long *arg)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl = (struct hfsc_class *)*arg;
+ struct hfsc_class *parent = NULL;
+ struct rtattr *opt = tca[TCA_OPTIONS-1];
+ struct rtattr *tb[TCA_HFSC_MAX];
+ struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
+ u64 cur_time;
+
+ if (opt == NULL ||
+ rtattr_parse(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
+ return -EINVAL;
+
+ if (tb[TCA_HFSC_RSC-1]) {
+ if (RTA_PAYLOAD(tb[TCA_HFSC_RSC-1]) < sizeof(*rsc))
+ return -EINVAL;
+ rsc = RTA_DATA(tb[TCA_HFSC_RSC-1]);
+ if (rsc->m1 == 0 && rsc->m2 == 0)
+ rsc = NULL;
+ }
+
+ if (tb[TCA_HFSC_FSC-1]) {
+ if (RTA_PAYLOAD(tb[TCA_HFSC_FSC-1]) < sizeof(*fsc))
+ return -EINVAL;
+ fsc = RTA_DATA(tb[TCA_HFSC_FSC-1]);
+ if (fsc->m1 == 0 && fsc->m2 == 0)
+ fsc = NULL;
+ }
+
+ if (tb[TCA_HFSC_USC-1]) {
+ if (RTA_PAYLOAD(tb[TCA_HFSC_USC-1]) < sizeof(*usc))
+ return -EINVAL;
+ usc = RTA_DATA(tb[TCA_HFSC_USC-1]);
+ if (usc->m1 == 0 && usc->m2 == 0)
+ usc = NULL;
+ }
+
+ if (cl != NULL) {
+ if (parentid) {
+ if (cl->cl_parent && cl->cl_parent->classid != parentid)
+ return -EINVAL;
+ if (cl->cl_parent == NULL && parentid != TC_H_ROOT)
+ return -EINVAL;
+ }
+ PSCHED_GET_TIME(cur_time);
+
+ sch_tree_lock(sch);
+ if (rsc != NULL)
+ hfsc_change_rsc(cl, rsc, cur_time);
+ if (fsc != NULL)
+ hfsc_change_fsc(cl, fsc);
+ if (usc != NULL)
+ hfsc_change_usc(cl, usc, cur_time);
+
+ if (cl->qdisc->q.qlen != 0) {
+ if (cl->cl_flags & HFSC_RSC)
+ update_ed(cl, qdisc_peek_len(cl->qdisc));
+ if (cl->cl_flags & HFSC_FSC)
+ update_vf(cl, 0, cur_time);
+ }
+ sch_tree_unlock(sch);
+
+#ifdef CONFIG_NET_ESTIMATOR
+ if (tca[TCA_RATE-1]) {
+ qdisc_kill_estimator(&cl->stats);
+ qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
+ }
+#endif
+ return 0;
+ }
+
+ if (parentid == TC_H_ROOT)
+ return -EEXIST;
+
+ parent = &q->root;
+ if (parentid) {
+ parent = hfsc_find_class(parentid, sch);
+ if (parent == NULL)
+ return -ENOENT;
+ }
+
+ if (classid == 0 || TC_H_MAJ(classid ^ sch->handle) != 0)
+ return -EINVAL;
+ if (hfsc_find_class(classid, sch))
+ return -EEXIST;
+
+ if (rsc == NULL && fsc == NULL)
+ return -EINVAL;
+
+ cl = kmalloc(sizeof(struct hfsc_class), GFP_KERNEL);
+ if (cl == NULL)
+ return -ENOBUFS;
+ memset(cl, 0, sizeof(struct hfsc_class));
+
+ if (rsc != NULL)
+ hfsc_change_rsc(cl, rsc, 0);
+ if (fsc != NULL)
+ hfsc_change_fsc(cl, fsc);
+ if (usc != NULL)
+ hfsc_change_usc(cl, usc, 0);
+
+ cl->refcnt = 1;
+ cl->classid = classid;
+ cl->sched = q;
+ cl->cl_parent = parent;
+ cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ if (cl->qdisc == NULL)
+ cl->qdisc = &noop_qdisc;
+ cl->stats.lock = &sch->dev->queue_lock;
+ INIT_LIST_HEAD(&cl->children);
+ cl->vt_tree = RB_ROOT;
+ cl->cf_tree = RB_ROOT;
+
+ sch_tree_lock(sch);
+ list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]);
+ list_add_tail(&cl->siblings, &parent->children);
+ if (parent->level == 0)
+ hfsc_purge_queue(sch, parent);
+ hfsc_adjust_levels(parent);
+ cl->cl_pcvtoff = parent->cl_cvtoff;
+ sch_tree_unlock(sch);
+
+#ifdef CONFIG_NET_ESTIMATOR
+ if (tca[TCA_RATE-1])
+ qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]);
+#endif
+ *arg = (unsigned long)cl;
+ return 0;
+}
+
+static void
+hfsc_destroy_filters(struct tcf_proto **fl)
+{
+ struct tcf_proto *tp;
+
+ while ((tp = *fl) != NULL) {
+ *fl = tp->next;
+ tcf_destroy(tp);
+ }
+}
+
+static void
+hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+
+ hfsc_destroy_filters(&cl->filter_list);
+ qdisc_destroy(cl->qdisc);
+#ifdef CONFIG_NET_ESTIMATOR
+ qdisc_kill_estimator(&cl->stats);
+#endif
+ if (cl != &q->root)
+ kfree(cl);
+}
+
+static int
+hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (cl->level > 0 || cl->filter_cnt > 0 || cl == &q->root)
+ return -EBUSY;
+
+ sch_tree_lock(sch);
+
+ list_del(&cl->hlist);
+ list_del(&cl->siblings);
+ hfsc_adjust_levels(cl->cl_parent);
+ hfsc_purge_queue(sch, cl);
+ if (--cl->refcnt == 0)
+ hfsc_destroy_class(sch, cl);
+
+ sch_tree_unlock(sch);
+ return 0;
+}
+
+static struct hfsc_class *
+hfsc_classify(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl;
+ struct tcf_result res;
+ struct tcf_proto *tcf;
+ int result;
+
+ if (TC_H_MAJ(skb->priority ^ sch->handle) == 0 &&
+ (cl = hfsc_find_class(skb->priority, sch)) != NULL)
+ if (cl->level == 0)
+ return cl;
+
+ tcf = q->root.filter_list;
+ while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
+#ifdef CONFIG_NET_CLS_POLICE
+ if (result == TC_POLICE_SHOT)
+ return NULL;
+#endif
+ if ((cl = (struct hfsc_class *)res.class) == NULL) {
+ if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
+ break; /* filter selected invalid classid */
+ }
+
+ if (cl->level == 0)
+ return cl; /* hit leaf class */
+
+ /* apply inner filter chain */
+ tcf = cl->filter_list;
+ }
+
+ /* classification failed, try default class */
+ cl = hfsc_find_class(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
+ if (cl == NULL || cl->level > 0)
+ return NULL;
+
+ return cl;
+}
+
+static int
+hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+ struct Qdisc **old)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (cl == NULL)
+ return -ENOENT;
+ if (cl->level > 0)
+ return -EINVAL;
+ if (new == NULL) {
+ new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ if (new == NULL)
+ new = &noop_qdisc;
+ }
+
+ sch_tree_lock(sch);
+ hfsc_purge_queue(sch, cl);
+ *old = xchg(&cl->qdisc, new);
+ sch_tree_unlock(sch);
+ return 0;
+}
+
+static struct Qdisc *
+hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (cl != NULL && cl->level == 0)
+ return cl->qdisc;
+
+ return NULL;
+}
+
+static unsigned long
+hfsc_get_class(struct Qdisc *sch, u32 classid)
+{
+ struct hfsc_class *cl = hfsc_find_class(classid, sch);
+
+ if (cl != NULL)
+ cl->refcnt++;
+
+ return (unsigned long)cl;
+}
+
+static void
+hfsc_put_class(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (--cl->refcnt == 0)
+ hfsc_destroy_class(sch, cl);
+}
+
+static unsigned long
+hfsc_bind_tcf(struct Qdisc *sch, unsigned long parent, u32 classid)
+{
+ struct hfsc_class *p = (struct hfsc_class *)parent;
+ struct hfsc_class *cl = hfsc_find_class(classid, sch);
+
+ if (cl != NULL) {
+ if (p != NULL && p->level <= cl->level)
+ return 0;
+ cl->filter_cnt++;
+ }
+
+ return (unsigned long)cl;
+}
+
+static void
+hfsc_unbind_tcf(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ cl->filter_cnt--;
+}
+
+static struct tcf_proto **
+hfsc_tcf_chain(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (cl == NULL)
+ cl = &q->root;
+
+ return &cl->filter_list;
+}
+
+static int
+hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc)
+{
+ struct tc_service_curve tsc;
+
+ tsc.m1 = sm2m(sc->sm1);
+ tsc.d = dx2d(sc->dx);
+ tsc.m2 = sm2m(sc->sm2);
+ RTA_PUT(skb, attr, sizeof(tsc), &tsc);
+
+ return skb->len;
+
+ rtattr_failure:
+ return -1;
+}
+
+static inline int
+hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl)
+{
+ if ((cl->cl_flags & HFSC_RSC) &&
+ (hfsc_dump_sc(skb, TCA_HFSC_RSC, &cl->cl_rsc) < 0))
+ goto rtattr_failure;
+
+ if ((cl->cl_flags & HFSC_FSC) &&
+ (hfsc_dump_sc(skb, TCA_HFSC_FSC, &cl->cl_fsc) < 0))
+ goto rtattr_failure;
+
+ if ((cl->cl_flags & HFSC_USC) &&
+ (hfsc_dump_sc(skb, TCA_HFSC_USC, &cl->cl_usc) < 0))
+ goto rtattr_failure;
+
+ return skb->len;
+
+ rtattr_failure:
+ return -1;
+}
+
+static inline int
+hfsc_dump_stats(struct sk_buff *skb, struct hfsc_class *cl)
+{
+ cl->stats.qlen = cl->qdisc->q.qlen;
+ if (qdisc_copy_stats(skb, &cl->stats) < 0)
+ goto rtattr_failure;
+
+ return skb->len;
+
+ rtattr_failure:
+ return -1;
+}
+
+static inline int
+hfsc_dump_xstats(struct sk_buff *skb, struct hfsc_class *cl)
+{
+ struct tc_hfsc_stats xstats;
+
+ xstats.level = cl->level;
+ xstats.period = cl->cl_vtperiod;
+ xstats.work = cl->cl_total;
+ xstats.rtwork = cl->cl_cumul;
+ RTA_PUT(skb, TCA_XSTATS, sizeof(xstats), &xstats);
+
+ return skb->len;
+
+ rtattr_failure:
+ return -1;
+}
+
+static int
+hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
+ struct tcmsg *tcm)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+ unsigned char *b = skb->tail;
+ struct rtattr *rta = (struct rtattr *)b;
+
+ tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT;
+ tcm->tcm_handle = cl->classid;
+ if (cl->level == 0)
+ tcm->tcm_info = cl->qdisc->handle;
+
+ RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ if (hfsc_dump_curves(skb, cl) < 0)
+ goto rtattr_failure;
+ rta->rta_len = skb->tail - b;
+
+ if ((hfsc_dump_stats(skb, cl) < 0) ||
+ (hfsc_dump_xstats(skb, cl) < 0))
+ goto rtattr_failure;
+
+ return skb->len;
+
+ rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static void
+hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl;
+ unsigned int i;
+
+ if (arg->stop)
+ return;
+
+ for (i = 0; i < HFSC_HSIZE; i++) {
+ list_for_each_entry(cl, &q->clhash[i], hlist) {
+ if (arg->count < arg->skip) {
+ arg->count++;
+ continue;
+ }
+ if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
+ arg->stop = 1;
+ return;
+ }
+ arg->count++;
+ }
+ }
+}
+
+static void
+hfsc_watchdog(unsigned long arg)
+{
+ struct Qdisc *sch = (struct Qdisc *)arg;
+
+ sch->flags &= ~TCQ_F_THROTTLED;
+ netif_schedule(sch->dev);
+}
+
+static void
+hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl;
+ u64 next_time = 0;
+ long delay;
+
+ if ((cl = eltree_get_minel(q)) != NULL)
+ next_time = cl->cl_e;
+ if (q->root.cl_cfmin != 0) {
+ if (next_time == 0 || next_time > q->root.cl_cfmin)
+ next_time = q->root.cl_cfmin;
+ }
+ ASSERT(next_time != 0);
+ delay = next_time - cur_time;
+ delay = PSCHED_US2JIFFIE(delay);
+
+ sch->flags |= TCQ_F_THROTTLED;
+ mod_timer(&q->wd_timer, jiffies + delay);
+}
+
+static int
+hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct tc_hfsc_qopt *qopt;
+ unsigned int i;
+
+ if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+ return -EINVAL;
+ qopt = RTA_DATA(opt);
+
+ sch->stats.lock = &sch->dev->queue_lock;
+
+ q->defcls = qopt->defcls;
+ for (i = 0; i < HFSC_HSIZE; i++)
+ INIT_LIST_HEAD(&q->clhash[i]);
+ q->eligible = RB_ROOT;
+ INIT_LIST_HEAD(&q->droplist);
+ skb_queue_head_init(&q->requeue);
+
+ q->root.refcnt = 1;
+ q->root.classid = sch->handle;
+ q->root.sched = q;
+ q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ if (q->root.qdisc == NULL)
+ q->root.qdisc = &noop_qdisc;
+ q->root.stats.lock = &sch->dev->queue_lock;
+ INIT_LIST_HEAD(&q->root.children);
+ q->root.vt_tree = RB_ROOT;
+ q->root.cf_tree = RB_ROOT;
+
+ list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]);
+
+ init_timer(&q->wd_timer);
+ q->wd_timer.function = hfsc_watchdog;
+ q->wd_timer.data = (unsigned long)sch;
+
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+hfsc_change_qdisc(struct Qdisc *sch, struct rtattr *opt)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct tc_hfsc_qopt *qopt;
+
+ if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+ return -EINVAL;;
+ qopt = RTA_DATA(opt);
+
+ sch_tree_lock(sch);
+ q->defcls = qopt->defcls;
+ sch_tree_unlock(sch);
+
+ return 0;
+}
+
+static void
+hfsc_reset_class(struct hfsc_class *cl)
+{
+ cl->cl_total = 0;
+ cl->cl_cumul = 0;
+ cl->cl_d = 0;
+ cl->cl_e = 0;
+ cl->cl_vt = 0;
+ cl->cl_vtadj = 0;
+ cl->cl_vtoff = 0;
+ cl->cl_cvtmin = 0;
+ cl->cl_cvtmax = 0;
+ cl->cl_cvtoff = 0;
+ cl->cl_pcvtoff = 0;
+ cl->cl_vtperiod = 0;
+ cl->cl_parentperiod = 0;
+ cl->cl_f = 0;
+ cl->cl_myf = 0;
+ cl->cl_myfadj = 0;
+ cl->cl_cfmin = 0;
+ cl->cl_nactive = 0;
+
+ cl->vt_tree = RB_ROOT;
+ cl->cf_tree = RB_ROOT;
+ qdisc_reset(cl->qdisc);
+
+ if (cl->cl_flags & HFSC_RSC)
+ rtsc_init(&cl->cl_deadline, &cl->cl_rsc, 0, 0);
+ if (cl->cl_flags & HFSC_FSC)
+ rtsc_init(&cl->cl_virtual, &cl->cl_fsc, 0, 0);
+ if (cl->cl_flags & HFSC_USC)
+ rtsc_init(&cl->cl_ulimit, &cl->cl_usc, 0, 0);
+}
+
+static void
+hfsc_reset_qdisc(struct Qdisc *sch)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl;
+ unsigned int i;
+
+ for (i = 0; i < HFSC_HSIZE; i++) {
+ list_for_each_entry(cl, &q->clhash[i], hlist)
+ hfsc_reset_class(cl);
+ }
+ __skb_queue_purge(&q->requeue);
+ q->eligible = RB_ROOT;
+ INIT_LIST_HEAD(&q->droplist);
+ del_timer(&q->wd_timer);
+ sch->flags &= ~TCQ_F_THROTTLED;
+ sch->q.qlen = 0;
+}
+
+static void
+hfsc_destroy_qdisc(struct Qdisc *sch)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl, *next;
+ unsigned int i;
+
+ for (i = 0; i < HFSC_HSIZE; i++) {
+ list_for_each_entry_safe(cl, next, &q->clhash[i], hlist)
+ hfsc_destroy_class(sch, cl);
+ }
+ __skb_queue_purge(&q->requeue);
+ del_timer(&q->wd_timer);
+ MOD_DEC_USE_COUNT;
+}
+
+static int
+hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ unsigned char *b = skb->tail;
+ struct tc_hfsc_qopt qopt;
+
+ qopt.defcls = q->defcls;
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+
+ return skb->len;
+
+ rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static int
+hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct hfsc_class *cl = hfsc_classify(skb, sch);
+ unsigned int len = skb->len;
+ int err;
+
+ if (cl == NULL) {
+ kfree_skb(skb);
+ sch->stats.drops++;
+ return NET_XMIT_DROP;
+ }
+
+ err = cl->qdisc->enqueue(skb, cl->qdisc);
+ if (unlikely(err != NET_XMIT_SUCCESS)) {
+ cl->stats.drops++;
+ sch->stats.drops++;
+ return err;
+ }
+
+ if (cl->qdisc->q.qlen == 1)
+ set_active(cl, len);
+
+ cl->stats.packets++;
+ cl->stats.bytes += len;
+ sch->stats.packets++;
+ sch->stats.bytes += len;
+ sch->q.qlen++;
+
+ return NET_XMIT_SUCCESS;
+}
+
+static struct sk_buff *
+hfsc_dequeue(struct Qdisc *sch)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl;
+ struct sk_buff *skb;
+ u64 cur_time;
+ unsigned int next_len;
+ int realtime = 0;
+
+ if (sch->q.qlen == 0)
+ return NULL;
+ if ((skb = __skb_dequeue(&q->requeue)))
+ goto out;
+
+ PSCHED_GET_TIME(cur_time);
+
+ /*
+ * if there are eligible classes, use real-time criteria.
+ * find the class with the minimum deadline among
+ * the eligible classes.
+ */
+ if ((cl = eltree_get_mindl(q, cur_time)) != NULL) {
+ realtime = 1;
+ } else {
+ /*
+ * use link-sharing criteria
+ * get the class with the minimum vt in the hierarchy
+ */
+ cl = vttree_get_minvt(&q->root, cur_time);
+ if (cl == NULL) {
+ sch->stats.overlimits++;
+ hfsc_schedule_watchdog(sch, cur_time);
+ return NULL;
+ }
+ }
+
+ skb = cl->qdisc->dequeue(cl->qdisc);
+ if (skb == NULL) {
+ if (net_ratelimit())
+ printk("HFSC: Non-work-conserving qdisc ?\n");
+ return NULL;
+ }
+
+ update_vf(cl, skb->len, cur_time);
+ if (realtime)
+ cl->cl_cumul += skb->len;
+
+ if (cl->qdisc->q.qlen != 0) {
+ if (cl->cl_flags & HFSC_RSC) {
+ /* update ed */
+ next_len = qdisc_peek_len(cl->qdisc);
+ if (realtime)
+ update_ed(cl, next_len);
+ else
+ update_d(cl, next_len);
+ }
+ } else {
+ /* the class becomes passive */
+ set_passive(cl);
+ }
+
+ out:
+ sch->flags &= ~TCQ_F_THROTTLED;
+ sch->q.qlen--;
+
+ return skb;
+}
+
+static int
+hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+
+ __skb_queue_head(&q->requeue, skb);
+ sch->q.qlen++;
+ return NET_XMIT_SUCCESS;
+}
+
+static unsigned int
+hfsc_drop(struct Qdisc *sch)
+{
+ struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
+ struct hfsc_class *cl;
+ unsigned int len;
+
+ list_for_each_entry(cl, &q->droplist, dlist) {
+ if (cl->qdisc->ops->drop != NULL &&
+ (len = cl->qdisc->ops->drop(cl->qdisc)) > 0) {
+ if (cl->qdisc->q.qlen == 0) {
+ update_vf(cl, 0, 0);
+ set_passive(cl);
+ } else {
+ list_move_tail(&cl->dlist, &q->droplist);
+ }
+ cl->stats.drops++;
+ sch->stats.drops++;
+ sch->q.qlen--;
+ return len;
+ }
+ }
+ return 0;
+}
+
+static struct Qdisc_class_ops hfsc_class_ops = {
+ .change = hfsc_change_class,
+ .delete = hfsc_delete_class,
+ .graft = hfsc_graft_class,
+ .leaf = hfsc_class_leaf,
+ .get = hfsc_get_class,
+ .put = hfsc_put_class,
+ .bind_tcf = hfsc_bind_tcf,
+ .unbind_tcf = hfsc_unbind_tcf,
+ .tcf_chain = hfsc_tcf_chain,
+ .dump = hfsc_dump_class,
+ .walk = hfsc_walk
+};
+
+struct Qdisc_ops hfsc_qdisc_ops = {
+ .id = "hfsc",
+ .init = hfsc_init_qdisc,
+ .change = hfsc_change_qdisc,
+ .reset = hfsc_reset_qdisc,
+ .destroy = hfsc_destroy_qdisc,
+ .dump = hfsc_dump_qdisc,
+ .enqueue = hfsc_enqueue,
+ .dequeue = hfsc_dequeue,
+ .requeue = hfsc_requeue,
+ .drop = hfsc_drop,
+ .cl_ops = &hfsc_class_ops,
+ .priv_size = sizeof(struct hfsc_sched)
+};
+
+static int __init
+hfsc_init(void)
+{
+ return register_qdisc(&hfsc_qdisc_ops);
+}
+
+static void __exit
+hfsc_cleanup(void)
+{
+ unregister_qdisc(&hfsc_qdisc_ops);
+}
+
+MODULE_LICENSE("GPL");
+module_init(hfsc_init);
+module_exit(hfsc_cleanup);
diff --git a/release/src/linux/linux/net/sched/sch_htb.c b/release/src/linux/linux/net/sched/sch_htb.c
index 7539e490..944cb555 100644
--- a/release/src/linux/linux/net/sched/sch_htb.c
+++ b/release/src/linux/linux/net/sched/sch_htb.c
@@ -9,6 +9,8 @@
* Authors: Martin Devera, <devik@cdi.cz>
*
* Credits (in time order) for older HTB versions:
+ * Stef Coene <stef.coene@docum.org>
+ * HTB support at LARTC mailing list
* Ondrej Kraus, <krauso@barr.cz>
* found missing INIT_QDISC(htb)
* Vladimir Smelhaus, Aamer Akhter, Bert Hubert
@@ -17,9 +19,13 @@
* code review and helpful comments on shaping
* Tomasz Wrona, <tw@eter.tym.pl>
* created test case so that I was able to fix nasty bug
+ * Wilfried Weissmann
+ * spotted bug in dequeue code and helped with fix
+ * Jiri Fojtasek
+ * fixed requeue routine
* and many others. thanks.
*
- * $Id: sch_htb.c,v 1.1.1.4 2003/10/14 08:09:35 sparq Exp $
+ * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $
*/
#include <linux/config.h>
#include <linux/module.h>
@@ -66,21 +72,17 @@
#define HTB_HSIZE 16 /* classid hash size */
#define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */
-#define HTB_DEBUG 1 /* compile debugging support (activated by tc tool) */
+//#define HTB_DEBUG 1 /* compile debugging support (activated by tc tool) */
#define HTB_RATECM 1 /* whether to use rate computer */
-#define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */
+#define HTB_HYSTERESIS 0/* whether to use mode hysteresis for speedup */
#define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock)
#define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock)
-#define HTB_VER 0x30007 /* major must be matched with number suplied by TC as version */
+#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
#if HTB_VER >> 16 != TC_HTB_PROTOVER
#error "Mismatched sch_htb.c and pkt_sch.h"
#endif
-/* temporary debug defines to be removed after beta stage */
-#define DEVIK_MEND(N)
-#define DEVIK_MSTART(N)
-
/* debugging support; S is subsystem, these are defined:
0 - netlink messages
1 - enqueue
@@ -100,13 +102,16 @@
from LSB
*/
#ifdef HTB_DEBUG
-#define HTB_DBG(S,L,FMT,ARG...) if (((q->debug>>(2*S))&3) >= L) \
+#define HTB_DBG_COND(S,L) (((q->debug>>(2*S))&3) >= L)
+#define HTB_DBG(S,L,FMT,ARG...) if (HTB_DBG_COND(S,L)) \
printk(KERN_DEBUG FMT,##ARG)
#define HTB_CHCL(cl) BUG_TRAP((cl)->magic == HTB_CMAGIC)
#define HTB_PASSQ q,
#define HTB_ARGQ struct htb_sched *q,
#define static
+#undef __inline__
#define __inline__
+#undef inline
#define inline
#define HTB_CMAGIC 0xFEFAFEF1
#define htb_safe_rb_erase(N,R) do { BUG_TRAP((N)->rb_color != -1); \
@@ -114,6 +119,7 @@
rb_erase(N,R); \
(N)->rb_color = -1; } while (0)
#else
+#define HTB_DBG_COND(S,L) (0)
#define HTB_DBG(S,L,FMT,ARG...)
#define HTB_PASSQ
#define HTB_ARGQ
@@ -166,6 +172,11 @@ struct htb_class
struct htb_class_inner {
rb_root_t feed[TC_HTB_NUMPRIO]; /* feed trees */
rb_node_t *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
+ /* When class changes from state 1->2 and disconnects from
+ parent's feed then we lost ptr value and start from the
+ first child again. Here we store classid of the
+ last valid ptr (used when ptr is NULL). */
+ u32 last_ptr_id[TC_HTB_NUMPRIO];
} inner;
} un;
rb_node_t node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
@@ -212,6 +223,7 @@ struct htb_sched
rb_root_t row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
int row_mask[TC_HTB_MAXDEPTH];
rb_node_t *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
+ u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
/* self wait list - roots of wait PQs per row */
rb_root_t wait_pq[TC_HTB_MAXDEPTH];
@@ -219,6 +231,9 @@ struct htb_sched
/* time of nearest event per level (row) */
unsigned long near_ev_cache[TC_HTB_MAXDEPTH];
+ /* cached value of jiffies in dequeue */
+ unsigned long jiffies;
+
/* whether we hit non-work conserving class during this dequeue; we use */
int nwc_hit; /* this to disable mindelay complaint in dequeue */
@@ -297,7 +312,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch)
rules in it */
if (skb->priority == sch->handle)
return HTB_DIRECT; /* X:0 (direct flow) selected */
- if ((cl = htb_find(skb->priority,sch)) != NULL)
+ if ((cl = htb_find(skb->priority,sch)) != NULL && cl->level == 0)
return cl;
tcf = q->filter_list;
@@ -338,7 +353,7 @@ static void htb_next_rb_node(rb_node_t **n);
static void htb_debug_dump (struct htb_sched *q)
{
int i,p;
- printk(KERN_DEBUG "htb*g j=%lu\n",jiffies);
+ printk(KERN_DEBUG "htb*g j=%lu lj=%lu\n",jiffies,q->jiffies);
/* rows */
for (i=TC_HTB_MAXDEPTH-1;i>=0;i--) {
printk(KERN_DEBUG "htb*r%d m=%x",i,q->row_mask[i]);
@@ -421,26 +436,24 @@ static void htb_add_to_wait_tree (struct htb_sched *q,
if ((delay <= 0 || delay > cl->mbuffer) && net_ratelimit())
printk(KERN_ERR "HTB: suspicious delay in wait_tree d=%ld cl=%X h=%d\n",delay,cl->classid,debug_hint);
#endif
- DEVIK_MSTART(9);
- cl->pq_key = jiffies + PSCHED_US2JIFFIE(delay);
- if (cl->pq_key == jiffies)
+ cl->pq_key = q->jiffies + PSCHED_US2JIFFIE(delay);
+ if (cl->pq_key == q->jiffies)
cl->pq_key++;
/* update the nearest event cache */
- if (q->near_ev_cache[cl->level] - cl->pq_key < 0x80000000)
+ if (time_after(q->near_ev_cache[cl->level], cl->pq_key))
q->near_ev_cache[cl->level] = cl->pq_key;
while (*p) {
struct htb_class *c; parent = *p;
c = rb_entry(parent, struct htb_class, pq_node);
- if (cl->pq_key - c->pq_key < 0x80000000)
+ if (time_after_eq(cl->pq_key, c->pq_key))
p = &parent->rb_right;
else
p = &parent->rb_left;
}
rb_link_node(&cl->pq_node, parent, p);
rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]);
- DEVIK_MEND(9);
}
/**
@@ -453,12 +466,14 @@ static void htb_next_rb_node(rb_node_t **n)
{
rb_node_t *p;
if ((*n)->rb_right) {
+ /* child at right. use it or its leftmost ancestor */
*n = (*n)->rb_right;
while ((*n)->rb_left)
*n = (*n)->rb_left;
return;
}
while ((p = (*n)->rb_parent) != NULL) {
+ /* if we've arrived from left child then we have next node */
if (p->rb_left == *n) break;
*n = p;
}
@@ -567,8 +582,13 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
int prio = ffz(~m);
m &= ~(1 << prio);
- if (p->un.inner.ptr[prio] == cl->node+prio)
- htb_next_rb_node(p->un.inner.ptr + prio);
+ if (p->un.inner.ptr[prio] == cl->node+prio) {
+ /* we are removing child which is pointed to from
+ parent feed - forget the pointer but remember
+ classid */
+ p->un.inner.last_ptr_id[prio] = cl->classid;
+ p->un.inner.ptr[prio] = NULL;
+ }
htb_safe_rb_erase(cl->node + prio,p->un.inner.feed + prio);
@@ -602,7 +622,7 @@ htb_class_mode(struct htb_class *cl,long *diff)
long toks;
if ((toks = (cl->ctokens + *diff)) < (
-#ifdef HTB_HYSTERESIS
+#if HTB_HYSTERESIS
cl->cmode != HTB_CANT_SEND ? -cl->cbuffer :
#endif
0)) {
@@ -610,7 +630,7 @@ htb_class_mode(struct htb_class *cl,long *diff)
return HTB_CANT_SEND;
}
if ((toks = (cl->tokens + *diff)) >= (
-#ifdef HTB_HYSTERESIS
+#if HTB_HYSTERESIS
cl->cmode == HTB_CAN_SEND ? -cl->buffer :
#endif
0))
@@ -689,7 +709,6 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
struct htb_sched *q = (struct htb_sched *)sch->data;
struct htb_class *cl = htb_classify(skb,sch);
- DEVIK_MSTART(0);
if (cl == HTB_DIRECT || !cl) {
/* enqueue to helper queue */
if (q->direct_queue.qlen < q->direct_qlen && cl) {
@@ -698,25 +717,20 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
} else {
kfree_skb (skb);
sch->stats.drops++;
- DEVIK_MEND(0);
return NET_XMIT_DROP;
}
} else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
sch->stats.drops++;
cl->stats.drops++;
- DEVIK_MEND(0);
return NET_XMIT_DROP;
} else {
cl->stats.packets++; cl->stats.bytes += skb->len;
- DEVIK_MSTART(1);
htb_activate (q,cl);
- DEVIK_MEND(1);
}
sch->q.qlen++;
sch->stats.packets++; sch->stats.bytes += skb->len;
- HTB_DBG(1,1,"htb_enq_ok cl=%X skb=%p\n",cl?cl->classid:0,skb);
- DEVIK_MEND(0);
+ HTB_DBG(1,1,"htb_enq_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb);
return NET_XMIT_SUCCESS;
}
@@ -725,16 +739,18 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
struct htb_sched *q = (struct htb_sched *)sch->data;
struct htb_class *cl = htb_classify(skb,sch);
+ struct sk_buff *tskb;
if (cl == HTB_DIRECT || !cl) {
/* enqueue to helper queue */
if (q->direct_queue.qlen < q->direct_qlen && cl) {
- __skb_queue_tail(&q->direct_queue, skb);
- q->direct_pkts++;
+ __skb_queue_head(&q->direct_queue, skb);
} else {
- kfree_skb (skb);
- sch->stats.drops++;
- return NET_XMIT_DROP;
+ __skb_queue_head(&q->direct_queue, skb);
+ tskb = __skb_dequeue_tail(&q->direct_queue);
+ kfree_skb (tskb);
+ sch->stats.drops++;
+ return NET_XMIT_CN;
}
} else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
sch->stats.drops++;
@@ -744,7 +760,7 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
htb_activate (q,cl);
sch->q.qlen++;
- HTB_DBG(1,1,"htb_req_ok cl=%X skb=%p\n",cl?cl->classid:0,skb);
+ HTB_DBG(1,1,"htb_req_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb);
return NET_XMIT_SUCCESS;
}
@@ -819,7 +835,7 @@ static void htb_charge_class(struct htb_sched *q,struct htb_class *cl,
cl->classid, diff,
(unsigned long long) q->now,
(unsigned long long) cl->t_c,
- jiffies);
+ q->jiffies);
diff = 1000;
}
#endif
@@ -862,6 +878,7 @@ static void htb_charge_class(struct htb_sched *q,struct htb_class *cl,
*
* Scans event queue for pending events and applies them. Returns jiffies to
* next pending event (0 for no event in pq).
+ * Note: Aplied are events whose have cl->pq_key <= jiffies.
*/
static long htb_do_events(struct htb_sched *q,int level)
{
@@ -876,9 +893,9 @@ static long htb_do_events(struct htb_sched *q,int level)
while (p->rb_left) p = p->rb_left;
cl = rb_entry(p, struct htb_class, pq_node);
- if (cl->pq_key - (jiffies+1) < 0x80000000) {
- HTB_DBG(8,3,"htb_do_ev_ret delay=%ld\n",cl->pq_key - jiffies);
- return cl->pq_key - jiffies;
+ if (time_after(cl->pq_key, q->jiffies)) {
+ HTB_DBG(8,3,"htb_do_ev_ret delay=%ld\n",cl->pq_key - q->jiffies);
+ return cl->pq_key - q->jiffies;
}
htb_safe_rb_erase(p,q->wait_pq+level);
diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer, 0);
@@ -889,7 +906,7 @@ static long htb_do_events(struct htb_sched *q,int level)
cl->classid, diff,
(unsigned long long) q->now,
(unsigned long long) cl->t_c,
- jiffies);
+ q->jiffies);
diff = 1000;
}
#endif
@@ -902,24 +919,56 @@ static long htb_do_events(struct htb_sched *q,int level)
return HZ/10;
}
+/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
+ is no such one exists. */
+static rb_node_t *
+htb_id_find_next_upper(int prio,rb_node_t *n,u32 id)
+{
+ rb_node_t *r = NULL;
+ while (n) {
+ struct htb_class *cl = rb_entry(n,struct htb_class,node[prio]);
+ if (id == cl->classid) return n;
+
+ if (id > cl->classid) {
+ n = n->rb_right;
+ } else {
+ r = n;
+ n = n->rb_left;
+ }
+ }
+ return r;
+}
+
/**
* htb_lookup_leaf - returns next leaf class in DRR order
*
* Find leaf where current feed pointers points to.
*/
static struct htb_class *
-htb_lookup_leaf(rb_root_t *tree,int prio,rb_node_t **pptr)
+htb_lookup_leaf(HTB_ARGQ rb_root_t *tree,int prio,rb_node_t **pptr,u32 *pid)
{
int i;
struct {
rb_node_t *root;
rb_node_t **pptr;
+ u32 *pid;
} stk[TC_HTB_MAXDEPTH],*sp = stk;
+ BUG_TRAP(tree->rb_node);
sp->root = tree->rb_node;
sp->pptr = pptr;
+ sp->pid = pid;
for (i = 0; i < 65535; i++) {
+ HTB_DBG(4,2,"htb_lleaf ptr=%p pid=%X\n",*sp->pptr,*sp->pid);
+
+ if (!*sp->pptr && *sp->pid) {
+ /* ptr was invalidated but id is valid - try to recover
+ the original or next ptr */
+ *sp->pptr = htb_id_find_next_upper(prio,sp->root,*sp->pid);
+ }
+ *sp->pid = 0; /* ptr is valid now so that remove this hint as it
+ can become out of date quickly */
if (!*sp->pptr) { /* we are at right end; rewind & go up */
*sp->pptr = sp->root;
while ((*sp->pptr)->rb_left)
@@ -937,6 +986,7 @@ htb_lookup_leaf(rb_root_t *tree,int prio,rb_node_t **pptr)
return cl;
(++sp)->root = cl->un.inner.feed[prio].rb_node;
sp->pptr = cl->un.inner.ptr+prio;
+ sp->pid = cl->un.inner.last_ptr_id+prio;
}
}
BUG_TRAP(0);
@@ -949,16 +999,37 @@ static struct sk_buff *
htb_dequeue_tree(struct htb_sched *q,int prio,int level)
{
struct sk_buff *skb = NULL;
- //struct htb_sched *q = (struct htb_sched *)sch->data;
struct htb_class *cl,*start;
/* look initial class up in the row */
- DEVIK_MSTART(6);
- start = cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio);
+ start = cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,
+ q->ptr[level]+prio,q->last_ptr_id[level]+prio);
do {
- BUG_TRAP(cl && cl->un.leaf.q->q.qlen); if (!cl) return NULL;
+next:
+ BUG_TRAP(cl);
+ if (!cl) return NULL;
HTB_DBG(4,1,"htb_deq_tr prio=%d lev=%d cl=%X defic=%d\n",
prio,level,cl->classid,cl->un.leaf.deficit[level]);
+
+ /* class can be empty - it is unlikely but can be true if leaf
+ qdisc drops packets in enqueue routine or if someone used
+ graft operation on the leaf since last dequeue;
+ simply deactivate and skip such class */
+ if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
+ struct htb_class *next;
+ htb_deactivate(q,cl);
+
+ /* row/level might become empty */
+ if ((q->row_mask[level] & (1 << prio)) == 0)
+ return NULL;
+
+ next = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,
+ prio,q->ptr[level]+prio,q->last_ptr_id[level]+prio);
+ if (cl == start) /* fix start if we just deleted it */
+ start = next;
+ cl = next;
+ goto next;
+ }
if (likely((skb = cl->un.leaf.q->dequeue(cl->un.leaf.q)) != NULL))
break;
@@ -968,11 +1039,10 @@ htb_dequeue_tree(struct htb_sched *q,int prio,int level)
}
q->nwc_hit++;
htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio);
- cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio);
+ cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,q->ptr[level]+prio,
+ q->last_ptr_id[level]+prio);
} while (cl != start);
- DEVIK_MEND(6);
- DEVIK_MSTART(7);
if (likely(skb != NULL)) {
if ((cl->un.leaf.deficit[level] -= skb->len) < 0) {
HTB_DBG(4,2,"htb_next_cl oldptr=%p quant_add=%d\n",
@@ -984,27 +1054,22 @@ htb_dequeue_tree(struct htb_sched *q,int prio,int level)
gives us slightly better performance */
if (!cl->un.leaf.q->q.qlen)
htb_deactivate (q,cl);
- DEVIK_MSTART(8);
htb_charge_class (q,cl,level,skb->len);
- DEVIK_MEND(8);
}
- DEVIK_MEND(7);
return skb;
}
static void htb_delay_by(struct Qdisc *sch,long delay)
{
struct htb_sched *q = (struct htb_sched *)sch->data;
- if (netif_queue_stopped(sch->dev)) return;
if (delay <= 0) delay = 1;
if (unlikely(delay > 5*HZ)) {
if (net_ratelimit())
printk(KERN_INFO "HTB delay %ld > 5sec\n", delay);
delay = 5*HZ;
}
- del_timer(&q->timer);
- q->timer.expires = jiffies + delay;
- add_timer(&q->timer);
+ /* why don't use jiffies here ? because expires can be in past */
+ mod_timer(&q->timer, q->jiffies + delay);
sch->flags |= TCQ_F_THROTTLED;
sch->stats.overlimits++;
HTB_DBG(3,1,"htb_deq t_delay=%ld\n",delay);
@@ -1016,7 +1081,11 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
struct htb_sched *q = (struct htb_sched *)sch->data;
int level;
long min_delay;
+#ifdef HTB_DEBUG
+ int evs_used = 0;
+#endif
+ q->jiffies = jiffies;
HTB_DBG(3,1,"htb_deq dircnt=%d qlen=%d\n",skb_queue_len(&q->direct_queue),
sch->q.qlen);
@@ -1027,27 +1096,26 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
return skb;
}
- DEVIK_MSTART(2);
if (!sch->q.qlen) goto fin;
PSCHED_GET_TIME(q->now);
- min_delay = HZ*5;
+ min_delay = LONG_MAX;
q->nwc_hit = 0;
for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
/* common case optimization - skip event handler quickly */
int m;
long delay;
- DEVIK_MSTART(3);
- if (jiffies - q->near_ev_cache[level] < 0x80000000 || 0) {
+ if (time_after_eq(q->jiffies, q->near_ev_cache[level])) {
delay = htb_do_events(q,level);
- q->near_ev_cache[level] += delay ? delay : HZ;
+ q->near_ev_cache[level] = q->jiffies + (delay ? delay : HZ);
+#ifdef HTB_DEBUG
+ evs_used++;
+#endif
} else
- delay = q->near_ev_cache[level] - jiffies;
+ delay = q->near_ev_cache[level] - q->jiffies;
if (delay && min_delay > delay)
min_delay = delay;
- DEVIK_MEND(3);
- DEVIK_MSTART(5);
m = ~q->row_mask[level];
while (m != (int)(-1)) {
int prio = ffz (m);
@@ -1056,29 +1124,29 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
if (likely(skb != NULL)) {
sch->q.qlen--;
sch->flags &= ~TCQ_F_THROTTLED;
- DEVIK_MEND(5);
goto fin;
}
}
- DEVIK_MEND(5);
}
- DEVIK_MSTART(4);
#ifdef HTB_DEBUG
- if (!q->nwc_hit && min_delay >= 5*HZ && net_ratelimit()) {
- printk(KERN_ERR "HTB: mindelay=%ld, report it please !\n",min_delay);
- htb_debug_dump(q);
+ if (!q->nwc_hit && min_delay >= 10*HZ && net_ratelimit()) {
+ if (min_delay == LONG_MAX) {
+ printk(KERN_ERR "HTB: dequeue bug (%d,%lu,%lu), report it please !\n",
+ evs_used,q->jiffies,jiffies);
+ htb_debug_dump(q);
+ } else
+ printk(KERN_WARNING "HTB: mindelay=%ld, some class has "
+ "too small rate\n",min_delay);
}
#endif
- htb_delay_by (sch,min_delay);
- DEVIK_MEND(4);
+ htb_delay_by (sch,min_delay > 5*HZ ? 5*HZ : min_delay);
fin:
- HTB_DBG(3,1,"htb_deq_end %s j=%lu skb=%p\n",sch->dev->name,jiffies,skb);
- DEVIK_MEND(2);
+ HTB_DBG(3,1,"htb_deq_end %s j=%lu skb=%p\n",sch->dev->name,q->jiffies,skb);
return skb;
}
/* try to drop from each class (by prio) until one succeed */
-static int htb_drop(struct Qdisc* sch)
+static unsigned int htb_drop(struct Qdisc* sch)
{
struct htb_sched *q = (struct htb_sched *)sch->data;
int prio;
@@ -1086,14 +1154,15 @@ static int htb_drop(struct Qdisc* sch)
for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
struct list_head *p;
list_for_each (p,q->drops+prio) {
- struct htb_class *cl = list_entry(p,struct htb_class,
- un.leaf.drop_list);
+ struct htb_class *cl = list_entry(p, struct htb_class,
+ un.leaf.drop_list);
+ unsigned int len;
if (cl->un.leaf.q->ops->drop &&
- cl->un.leaf.q->ops->drop(cl->un.leaf.q)) {
+ (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
sch->q.qlen--;
if (!cl->un.leaf.q->q.qlen)
htb_deactivate (q,cl);
- return 1;
+ return len;
}
}
}
@@ -1162,7 +1231,6 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
HTB_VER >> 16,HTB_VER & 0xffff,gopt->version);
return -EINVAL;
}
- memset(q,0,sizeof(*q));
q->debug = gopt->debug;
HTB_DBG(0,1,"htb_init sch=%p handle=%X r2q=%d\n",sch,sch->handle,gopt->rate2quantum);
@@ -1208,7 +1276,8 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
gopt.direct_pkts = q->direct_pkts;
#ifdef HTB_DEBUG
- htb_debug_dump(q);
+ if (HTB_DBG_COND(0,2))
+ htb_debug_dump(q);
#endif
gopt.version = HTB_VER;
gopt.rate2quantum = q->rate2quantum;
@@ -1218,8 +1287,6 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
rta->rta_len = skb->tail - b;
- sch->stats.qlen = sch->q.qlen;
- RTA_PUT(skb, TCA_STATS, sizeof(sch->stats), &sch->stats);
HTB_QUNLOCK(sch);
return skb->len;
rtattr_failure:
@@ -1289,6 +1356,9 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
return -ENOBUFS;
sch_tree_lock(sch);
if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) {
+ if (cl->prio_activity)
+ htb_deactivate ((struct htb_sched*)sch->data,cl);
+
/* TODO: is it correct ? Why CBQ doesn't do it ? */
sch->q.qlen -= (*old)->q.qlen;
qdisc_reset(*old);
@@ -1323,7 +1393,7 @@ static void htb_destroy_filters(struct tcf_proto **fl)
while ((tp = *fl) != NULL) {
*fl = tp->next;
- tp->ops->destroy(tp);
+ tcf_destroy(tp);
}
}
@@ -1371,11 +1441,16 @@ static void htb_destroy(struct Qdisc* sch)
#ifdef HTB_RATECM
del_timer_sync (&q->rttim);
#endif
+ /* This line used to be after htb_destroy_class call below
+ and surprisingly it worked in 2.4. But it must precede it
+ because filter need its target class alive to be able to call
+ unbind_filter on it (without Oops). */
+ htb_destroy_filters(&q->filter_list);
+
while (!list_empty(&q->root))
htb_destroy_class (sch,list_entry(q->root.next,
struct htb_class,sibling));
- htb_destroy_filters(&q->filter_list);
__skb_queue_purge(&q->direct_queue);
MOD_DEC_USE_COUNT;
}
@@ -1438,12 +1513,13 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
parent = parentid == TC_H_ROOT ? NULL : htb_find (parentid,sch);
hopt = RTA_DATA(tb[TCA_HTB_PARMS-1]);
- HTB_DBG(0,1,"htb_chg cl=%p, clid=%X, opt/prio=%d, rate=%u, buff=%d, quant=%d\n", cl,cl?cl->classid:0,(int)hopt->prio,hopt->rate.rate,hopt->buffer,hopt->quantum);
+ HTB_DBG(0,1,"htb_chg cl=%p(%X), clid=%X, parid=%X, opt/prio=%d, rate=%u, buff=%d, quant=%d\n", cl,cl?cl->classid:0,classid,parentid,(int)hopt->prio,hopt->rate.rate,hopt->buffer,hopt->quantum);
rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB-1]);
ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB-1]);
if (!rtab || !ctab) goto failure;
if (!cl) { /* new class */
+ struct Qdisc *new_q;
/* check for valid classid */
if (!classid || TC_H_MAJ(classid^sch->handle) || htb_find(classid,sch))
goto failure;
@@ -1467,6 +1543,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
cl->magic = HTB_CMAGIC;
#endif
+ /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
+ so that can't be used inside of sch_tree_lock
+ -- thanks to Karlis Peisenieks */
+ new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
sch_tree_lock(sch);
if (parent && !parent->level) {
/* turn parent into inner node */
@@ -1485,8 +1565,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
memset (&parent->un.inner,0,sizeof(parent->un.inner));
}
/* leaf (we) needs elementary qdisc */
- if (!(cl->un.leaf.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
- cl->un.leaf.q = &noop_qdisc;
+ cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
cl->classid = classid; cl->parent = parent;
@@ -1514,11 +1593,11 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if (!cl->level) {
cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum;
if (!hopt->quantum && cl->un.leaf.quantum < 1000) {
- printk(KERN_WARNING "HTB: quantum of class %X is small. Consider r2q change.", cl->classid);
+ printk(KERN_WARNING "HTB: quantum of class %X is small. Consider r2q change.\n", cl->classid);
cl->un.leaf.quantum = 1000;
}
if (!hopt->quantum && cl->un.leaf.quantum > 200000) {
- printk(KERN_WARNING "HTB: quantum of class %X is big. Consider r2q change.", cl->classid);
+ printk(KERN_WARNING "HTB: quantum of class %X is big. Consider r2q change.\n", cl->classid);
cl->un.leaf.quantum = 200000;
}
if (hopt->quantum)
diff --git a/release/src/linux/linux/net/sched/sch_ingress.c b/release/src/linux/linux/net/sched/sch_ingress.c
index 2b30fce0..70698728 100644
--- a/release/src/linux/linux/net/sched/sch_ingress.c
+++ b/release/src/linux/linux/net/sched/sch_ingress.c
@@ -250,7 +250,6 @@ int ingress_init(struct Qdisc *sch,struct rtattr *opt)
}
DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
- memset(p, 0, sizeof(*p));
p->filter_list = NULL;
p->q = &noop_qdisc;
MOD_INC_USE_COUNT;
@@ -286,10 +285,7 @@ static void ingress_destroy(struct Qdisc *sch)
p->filter_list = tp->next;
tp->ops->destroy(tp);
}
- memset(p, 0, sizeof(*p));
- p->filter_list = NULL;
-
MOD_DEC_USE_COUNT;
}
diff --git a/release/src/linux/linux/net/sched/sch_sfq.c b/release/src/linux/linux/net/sched/sch_sfq.c
index c96762fb..a6c17424 100644
--- a/release/src/linux/linux/net/sched/sch_sfq.c
+++ b/release/src/linux/linux/net/sched/sch_sfq.c
@@ -218,6 +218,7 @@ static int sfq_drop(struct Qdisc *sch)
struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data;
sfq_index d = q->max_depth;
struct sk_buff *skb;
+ int len;
/* Queue is full! Find the longest slot and
drop a packet from it */
@@ -225,12 +226,13 @@ static int sfq_drop(struct Qdisc *sch)
if (d > 1) {
sfq_index x = q->dep[d+SFQ_DEPTH].next;
skb = q->qs[x].prev;
+ len = skb->len;
__skb_unlink(skb, &q->qs[x]);
kfree_skb(skb);
sfq_dec(q, x);
sch->q.qlen--;
sch->stats.drops++;
- return 1;
+ return len;
}
if (d == 1) {
@@ -239,13 +241,14 @@ static int sfq_drop(struct Qdisc *sch)
q->next[q->tail] = q->next[d];
q->allot[q->next[d]] += q->quantum;
skb = q->qs[d].prev;
+ len = skb->len;
__skb_unlink(skb, &q->qs[d]);
kfree_skb(skb);
sfq_dec(q, d);
sch->q.qlen--;
q->ht[q->hash[d]] = SFQ_DEPTH;
sch->stats.drops++;
- return 1;
+ return len;
}
return 0;
@@ -342,6 +345,7 @@ sfq_dequeue(struct Qdisc* sch)
/* Is the slot empty? */
if (q->qs[a].qlen == 0) {
+ q->ht[q->hash[a]] = SFQ_DEPTH;
a = q->next[a];
if (a == old_a) {
q->tail = SFQ_DEPTH;
diff --git a/release/src/linux/linux/net/socket.c b/release/src/linux/linux/net/socket.c
index d8b479c9..4816eeb6 100644
--- a/release/src/linux/linux/net/socket.c
+++ b/release/src/linux/linux/net/socket.c
@@ -607,6 +607,9 @@ ssize_t sock_sendpage(struct file *file, struct page *page,
if (more)
flags |= MSG_MORE;
+ if (!sock->ops->sendpage)
+ return sock_no_sendpage(sock, page, offset, size, flags);
+
return sock->ops->sendpage(sock, page, offset, size, flags);
}
diff --git a/release/src/linux/linux/scripts/squashfs/Makefile b/release/src/linux/linux/scripts/squashfs/Makefile
index f563eceb..fa3f29e4 100644
--- a/release/src/linux/linux/scripts/squashfs/Makefile
+++ b/release/src/linux/linux/scripts/squashfs/Makefile
@@ -1,17 +1,39 @@
-INCLUDEDIR = .
-
CC=gcc
+CXX=g++
+INCLUDEDIR = .
+LZMALIB = lzma/C/7zip/Compress/LZMA_Lib
+LZMAPATH = lzma/C/7zip/Compress/LZMA_Alone
CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2
+all: liblzma.a mksquashfs unsquashfs mksquashfs-lzma lzma
+
mksquashfs: mksquashfs.o read_fs.o sort.o
$(CC) mksquashfs.o read_fs.o sort.o -lz -o $@
-mksquashfs.o: mksquashfs.c mksquashfs.h
+mksquashfs-lzma: liblzma.a mksquashfs.o read_fs.o sort.o
+ $(CXX) mksquashfs.o read_fs.o sort.o -L$(LZMALIB) -llzma -o $@
+
+mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h
-read_fs.o: read_fs.c read_fs.h
+read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h
-sort.o: sort.c
+sort.o: sort.c squashfs_fs.h global.h sort.h
+
+unsquashfs: unsquashfs.o
+ $(CC) unsquashfs.o -lz -o $@
+
+unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h
+
+liblzma.a:
+ $(MAKE) -C $(LZMALIB)
+
+lzma:
+ $(MAKE) -C $(LZMAPATH) -f makefile.gcc
clean:
- rm -f *.o mksquashfs
+ find . -iname "*.o" -exec rm -f {} \;
+ find . -iname "*.a" -exec rm -f {} \;
+ rm -f mksquashfs unsquashfs mksquashfs-lzma $(LZMAPATH)/lzma
+
+.PHONY: lzma
diff --git a/release/src/linux/linux/scripts/squashfs/global.h b/release/src/linux/linux/scripts/squashfs/global.h
new file mode 100644
index 00000000..2c45c4a4
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/global.h
@@ -0,0 +1,46 @@
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * global.h
+ */
+
+typedef struct squashfs_super_block squashfs_super_block;
+typedef struct squashfs_dir_index squashfs_dir_index;
+typedef struct squashfs_base_inode_header squashfs_base_inode_header;
+typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header;
+typedef struct squashfs_dev_inode_header squashfs_dev_inode_header;
+typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header;
+typedef struct squashfs_reg_inode_header squashfs_reg_inode_header;
+typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header;
+typedef struct squashfs_dir_inode_header squashfs_dir_inode_header;
+typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header;
+typedef struct squashfs_dir_entry squashfs_dir_entry;
+typedef struct squashfs_dir_header squashfs_dir_header;
+typedef struct squashfs_fragment_entry squashfs_fragment_entry;
+
+typedef union squashfs_inode_header squashfs_inode_header;
+typedef unsigned int squashfs_uid;
+typedef long long squashfs_fragment_index;
+typedef squashfs_inode_t squashfs_inode;
+typedef squashfs_block_t squashfs_block;
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/7zC.txt b/release/src/linux/linux/scripts/squashfs/lzma/7zC.txt
new file mode 100644
index 00000000..1c81eacf
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/7zC.txt
@@ -0,0 +1,235 @@
+7z ANSI-C Decoder 4.23
+----------------------
+
+7z ANSI-C Decoder 4.23 Copyright (C) 1999-2005 Igor Pavlov
+
+7z ANSI-C provides 7z/LZMA decoding.
+7z ANSI-C version is simplified version ported from C++ code.
+
+LZMA is default and general compression method of 7z format
+in 7-Zip compression program (www.7-zip.org). LZMA provides high
+compression ratio and very fast decompression.
+
+
+LICENSE
+-------
+
+Read lzma.txt for information about license.
+
+
+Files
+---------------------
+
+7zAlloc.* - Allocate and Free
+7zBuffer.* - Buffer structure
+7zCrc.* - CRC32 code
+7zDecode.* - Low level memory->memory decoding
+7zExtract.* - High level stream->memory decoding
+7zHeader.* - .7z format constants
+7zIn.* - .7z archive opening
+7zItem.* - .7z structures
+7zMain.c - Test application
+7zMethodID.* - MethodID structure
+7zTypes.h - Base types and constants
+
+
+How To Use
+----------
+
+You must download 7-Zip program from www.7-zip.org.
+
+You can create .7z archive with 7z.exe or 7za.exe:
+
+ 7za.exe a archive.7z *.htm -r -mx -m0fb=255
+
+If you have big number of files in archive, and you need fast extracting,
+you can use partly-solid archives:
+
+ 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
+
+In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
+512KB for extracting one file from such archive.
+
+
+Limitations of current version of 7z ANSI-C Decoder
+---------------------------------------------------
+
+ - It reads only "FileName", "Size", and "CRC" information for each file in archive.
+ - It supports only LZMA and Copy (no compression) methods.
+ - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
+
+These limitations will be fixed in future versions.
+
+
+Using 7z ANSI-C Decoder Test application:
+-----------------------------------------
+
+Usage: 7zDec <command> <archive_name>
+
+<Command>:
+ e: Extract files from archive
+ l: List contents of archive
+ t: Test integrity of archive
+
+Example:
+
+ 7zDec l archive.7z
+
+lists contents of archive.7z
+
+ 7zDec e archive.7z
+
+extracts files from archive.7z to current folder.
+
+
+How to use .7z Decoder
+----------------------
+
+.7z Decoder can be compiled in one of two modes:
+
+1) Default mode. In that mode 7z Decoder will read full compressed
+ block to RAM before decompressing.
+
+2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read
+ compressed block by parts. And you can specify desired buffer size.
+ So memory requirements can be reduced. But decompressing speed will
+ be 5-10% lower and code size is slightly larger.
+
+
+Memory allocation
+~~~~~~~~~~~~~~~~~
+
+7z Decoder uses two memory pools:
+1) Temporary pool
+2) Main pool
+Such scheme can allow you to avoid fragmentation of allocated blocks.
+
+Steps for using 7z decoder
+--------------------------
+
+Use code at 7zMain.c as example.
+
+1) Declare variables:
+ inStream /* implements ISzInStream interface */
+ CArchiveDatabaseEx db; /* 7z archive database structure */
+ ISzAlloc allocImp; /* memory functions for main pool */
+ ISzAlloc allocTempImp; /* memory functions for temporary pool */
+
+2) call InitCrcTable(); function to initialize CRC structures.
+
+3) call SzArDbExInit(&db); function to initialize db structures.
+
+4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive
+
+This function opens archive "inStream" and reads headers to "db".
+All items in "db" will be allocated with "allocMain" functions.
+SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions.
+
+5) List items or Extract items
+
+ Listing code:
+ ~~~~~~~~~~~~~
+ {
+ UInt32 i;
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ CFileItem *f = db.Database.Files + i;
+ printf("%10d %s\n", (int)f->Size, f->Name);
+ }
+ }
+
+ Extracting code:
+ ~~~~~~~~~~~~~~~~
+
+ SZ_RESULT SzExtract(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ UInt32 fileIndex, /* index of file */
+ UInt32 *blockIndex, /* index of solid block */
+ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
+ size_t *outBufferSize, /* buffer size for output buffer */
+ size_t *offset, /* offset of stream for required file in *outBuffer */
+ size_t *outSizeProcessed, /* size of file in *outBuffer */
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp);
+
+ If you need to decompress more than one file, you can send these values from previous call:
+ blockIndex,
+ outBuffer,
+ outBufferSize,
+ You can consider "outBuffer" as cache of solid block. If your archive is solid,
+ it will increase decompression speed.
+
+ After decompressing you must free "outBuffer":
+ allocImp.Free(outBuffer);
+
+6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db".
+
+
+
+
+Memory requirements for .7z decoding
+------------------------------------
+
+Memory usage for Archive opening:
+ - Temporary pool:
+ - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined)
+ - Memory for uncompressed .7z headers
+ - some other temporary blocks
+ - Main pool:
+ - Memory for database:
+ Estimated size of one file structures in solid archive:
+ - Size (4 or 8 Bytes)
+ - CRC32 (4 bytes)
+ - Some file information (4 bytes)
+ - File Name (variable length) + pointer + allocation structures
+
+Memory usage for archive Decompressing:
+ - Temporary pool:
+ - Memory for compressed solid block (if _LZMA_IN_CB is not defined)
+ - Memory for LZMA decompressing structures
+ - Main pool:
+ - Memory for decompressed solid block
+
+
+If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for
+compressed blocks. Instead of this, you must allocate buffer with desired
+size before calling 7z Decoder. Use 7zMain.c as example.
+
+
+
+EXIT codes
+-----------
+
+7z Decoder functions can return one of the following codes:
+
+#define SZ_OK (0)
+#define SZE_DATA_ERROR (1)
+#define SZE_OUTOFMEMORY (2)
+#define SZE_CRC_ERROR (3)
+
+#define SZE_NOTIMPL (4)
+#define SZE_FAIL (5)
+
+#define SZE_ARCHIVE_ERROR (6)
+
+
+
+LZMA Defines
+------------
+
+_LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements
+
+_SZ_FILE_SIZE_64 - define it if you need support for files larger than 4 GB
+_SZ_NO_INT_64 - define it if your compiler doesn't support long long int
+
+_LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs.
+
+_SZ_ONE_DIRECTORY - define it if you want to locate all source files to one directory
+_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
+
+
+---
+
+http://www.7-zip.org
+http://www.7-zip.org/support.html
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/7zFormat.txt b/release/src/linux/linux/scripts/squashfs/lzma/7zFormat.txt
new file mode 100644
index 00000000..7e2b14ad
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/7zFormat.txt
@@ -0,0 +1,471 @@
+7z Format description (2.30 Beta 25)
+-----------------------------------
+
+This file contains description of 7z archive format.
+7z archive can contain files compressed with any method.
+See "Methods.txt" for description for defined compressing methods.
+
+
+Format structure Overview
+-------------------------
+
+Some fields can be optional.
+
+Archive structure
+~~~~~~~~~~~~~~~~~
+SignatureHeader
+[PackedStreams]
+[PackedStreamsForHeaders]
+[
+ Header
+ or
+ {
+ Packed Header
+ HeaderInfo
+ }
+]
+
+
+
+Header structure
+~~~~~~~~~~~~~~~~
+{
+ ArchiveProperties
+ AdditionalStreams
+ {
+ PackInfo
+ {
+ PackPos
+ NumPackStreams
+ Sizes[NumPackStreams]
+ CRCs[NumPackStreams]
+ }
+ CodersInfo
+ {
+ NumFolders
+ Folders[NumFolders]
+ {
+ NumCoders
+ CodersInfo[NumCoders]
+ {
+ ID
+ NumInStreams;
+ NumOutStreams;
+ PropertiesSize
+ Properties[PropertiesSize]
+ }
+ NumBindPairs
+ BindPairsInfo[NumBindPairs]
+ {
+ InIndex;
+ OutIndex;
+ }
+ PackedIndices
+ }
+ UnPackSize[Folders][Folders.NumOutstreams]
+ CRCs[NumFolders]
+ }
+ SubStreamsInfo
+ {
+ NumUnPackStreamsInFolders[NumFolders];
+ UnPackSizes[]
+ CRCs[]
+ }
+ }
+ MainStreamsInfo
+ {
+ (Same as in AdditionalStreams)
+ }
+ FilesInfo
+ {
+ NumFiles
+ Properties[]
+ {
+ ID
+ Size
+ Data
+ }
+ }
+}
+
+HeaderInfo structure
+~~~~~~~~~~~~~~~~~~~~
+{
+ (Same as in AdditionalStreams)
+}
+
+
+
+Notes about Notation and encoding
+---------------------------------
+
+7z uses little endian encoding.
+
+7z archive format has optional headers that are marked as
+[]
+Header
+[]
+
+REAL_UINT64 means real UINT64.
+
+UINT64 means real UINT64 encoded with the following scheme:
+
+ Size of encoding sequence depends from first byte:
+ First_Byte Extra_Bytes Value
+ (binary)
+ 0xxxxxxx : ( xxxxxxx )
+ 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y
+ 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y
+ ...
+ 1111110x BYTE y[6] : ( x << (8 * 6)) + y
+ 11111110 BYTE y[7] : y
+ 11111111 BYTE y[8] : y
+
+
+
+Property IDs
+------------
+
+0x00 = kEnd,
+
+0x01 = kHeader,
+
+0x02 = kArchiveProperties,
+
+0x03 = kAdditionalStreamsInfo,
+0x04 = kMainStreamsInfo,
+0x05 = kFilesInfo,
+
+0x06 = kPackInfo,
+0x07 = kUnPackInfo,
+0x08 = kSubStreamsInfo,
+
+0x09 = kSize,
+0x0A = kCRC,
+
+0x0B = kFolder,
+
+0x0C = kCodersUnPackSize,
+0x0D = kNumUnPackStream,
+
+0x0E = kEmptyStream,
+0x0F = kEmptyFile,
+0x10 = kAnti,
+
+0x11 = kName,
+0x12 = kCreationTime,
+0x13 = kLastAccessTime,
+0x14 = kLastWriteTime,
+0x15 = kWinAttributes,
+0x16 = kComment,
+
+0x17 = kEncodedHeader,
+
+
+7z format headers
+-----------------
+
+SignatureHeader
+~~~~~~~~~~~~~~~
+ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
+
+ ArchiveVersion
+ {
+ BYTE Major; // now = 0
+ BYTE Minor; // now = 2
+ };
+
+ UINT32 StartHeaderCRC;
+
+ StartHeader
+ {
+ REAL_UINT64 NextHeaderOffset
+ REAL_UINT64 NextHeaderSize
+ UINT32 NextHeaderCRC
+ }
+
+
+...........................
+
+
+ArchiveProperties
+~~~~~~~~~~~~~~~~~
+BYTE NID::kArchiveProperties (0x02)
+while(true)
+{
+ BYTE PropertyType;
+ if (aType == 0)
+ break;
+ UINT64 PropertySize;
+ BYTE PropertyData[PropertySize];
+}
+
+
+Digests (NumStreams)
+~~~~~~~~~~~~~~~~~~~~~
+ BYTE AllAreDefined
+ if (AllAreDefined == 0)
+ {
+ for(NumStreams)
+ BIT Defined
+ }
+ UINT32 CRCs[NumDefined]
+
+
+PackInfo
+~~~~~~~~~~~~
+ BYTE NID::kPackInfo (0x06)
+ UINT64 PackPos
+ UINT64 NumPackStreams
+
+ []
+ BYTE NID::kSize (0x09)
+ UINT64 PackSizes[NumPackStreams]
+ []
+
+ []
+ BYTE NID::kCRC (0x0A)
+ PackStreamDigests[NumPackStreams]
+ []
+
+ BYTE NID::kEnd
+
+
+Folder
+~~~~~~
+ UINT64 NumCoders;
+ for (NumCoders)
+ {
+ BYTE
+ {
+ 0:3 DecompressionMethod.IDSize
+ 4:
+ 0 - IsSimple
+ 1 - Is not simple
+ 5:
+ 0 - No Attributes
+ 1 - There Are Attributes
+ 7:
+ 0 - Last Method in Alternative_Method_List
+ 1 - There are more alternative methods
+ }
+ BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]
+ if (!IsSimple)
+ {
+ UINT64 NumInStreams;
+ UINT64 NumOutStreams;
+ }
+ if (DecompressionMethod[0] != 0)
+ {
+ UINT64 PropertiesSize
+ BYTE Properties[PropertiesSize]
+ }
+ }
+
+ NumBindPairs = NumOutStreamsTotal - 1;
+
+ for (NumBindPairs)
+ {
+ UINT64 InIndex;
+ UINT64 OutIndex;
+ }
+
+ NumPackedStreams = NumInStreamsTotal - NumBindPairs;
+ if (NumPackedStreams > 1)
+ for(NumPackedStreams)
+ {
+ UINT64 Index;
+ };
+
+
+
+
+Coders Info
+~~~~~~~~~~~
+
+ BYTE NID::kUnPackInfo (0x07)
+
+
+ BYTE NID::kFolder (0x0B)
+ UINT64 NumFolders
+ BYTE External
+ switch(External)
+ {
+ case 0:
+ Folders[NumFolders]
+ case 1:
+ UINT64 DataStreamIndex
+ }
+
+
+ BYTE ID::kCodersUnPackSize (0x0C)
+ for(Folders)
+ for(Folder.NumOutStreams)
+ UINT64 UnPackSize;
+
+
+ []
+ BYTE NID::kCRC (0x0A)
+ UnPackDigests[NumFolders]
+ []
+
+
+
+ BYTE NID::kEnd
+
+
+
+SubStreams Info
+~~~~~~~~~~~~~~
+ BYTE NID::kSubStreamsInfo; (0x08)
+
+ []
+ BYTE NID::kNumUnPackStream; (0x0D)
+ UINT64 NumUnPackStreamsInFolders[NumFolders];
+ []
+
+
+ []
+ BYTE NID::kSize (0x09)
+ UINT64 UnPackSizes[]
+ []
+
+
+ []
+ BYTE NID::kCRC (0x0A)
+ Digests[Number of streams with unknown CRC]
+ []
+
+
+ BYTE NID::kEnd
+
+
+Streams Info
+~~~~~~~~~~~~
+
+ []
+ PackInfo
+ []
+
+
+ []
+ CodersInfo
+ []
+
+
+ []
+ SubStreamsInfo
+ []
+
+ BYTE NID::kEnd
+
+
+FilesInfo
+~~~~~~~~~
+ BYTE NID::kFilesInfo; (0x05)
+ UINT64 NumFiles
+
+ while(true)
+ {
+ BYTE PropertyType;
+ if (aType == 0)
+ break;
+
+ UINT64 Size;
+
+ switch(PropertyType)
+ {
+ kEmptyStream: (0x0E)
+ for(NumFiles)
+ BIT IsEmptyStream
+
+ kEmptyFile: (0x0F)
+ for(EmptyStreams)
+ BIT IsEmptyFile
+
+ kAnti: (0x10)
+ for(EmptyStreams)
+ BIT IsAntiFile
+
+ case kCreationTime: (0x12)
+ case kLastAccessTime: (0x13)
+ case kLastWriteTime: (0x14)
+ BYTE AllAreDefined
+ if (AllAreDefined == 0)
+ {
+ for(NumFiles)
+ BIT TimeDefined
+ }
+ BYTE External;
+ if(External != 0)
+ UINT64 DataIndex
+ []
+ for(Definded Items)
+ UINT32 Time
+ []
+
+ kNames: (0x11)
+ BYTE External;
+ if(External != 0)
+ UINT64 DataIndex
+ []
+ for(Files)
+ {
+ wchar_t Names[NameSize];
+ wchar_t 0;
+ }
+ []
+
+ kAttributes: (0x15)
+ BYTE AllAreDefined
+ if (AllAreDefined == 0)
+ {
+ for(NumFiles)
+ BIT AttributesAreDefined
+ }
+ BYTE External;
+ if(External != 0)
+ UINT64 DataIndex
+ []
+ for(Definded Attributes)
+ UINT32 Attributes
+ []
+ }
+ }
+
+
+Header
+~~~~~~
+ BYTE NID::kHeader (0x01)
+
+ []
+ ArchiveProperties
+ []
+
+ []
+ BYTE NID::kAdditionalStreamsInfo; (0x03)
+ StreamsInfo
+ []
+
+ []
+ BYTE NID::kMainStreamsInfo; (0x04)
+ StreamsInfo
+ []
+
+ []
+ FilesInfo
+ []
+
+ BYTE NID::kEnd
+
+
+HeaderInfo
+~~~~~~~~~~
+ []
+ BYTE NID::kEncodedHeader; (0x17)
+ StreamsInfo for Encoded Header
+ []
+
+
+---
+End of document
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.c
new file mode 100644
index 00000000..d5da81b1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.c
@@ -0,0 +1,70 @@
+/* 7zAlloc.c */
+
+#include <stdlib.h>
+#include "7zAlloc.h"
+
+/* #define _SZ_ALLOC_DEBUG */
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
+
+#ifdef _SZ_ALLOC_DEBUG
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <stdio.h>
+int g_allocCount = 0;
+int g_allocCountTemp = 0;
+#endif
+
+void *SzAlloc(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
+ g_allocCount++;
+ #endif
+ return malloc(size);
+}
+
+void SzFree(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ {
+ g_allocCount--;
+ fprintf(stderr, "\nFree; count = %10d", g_allocCount);
+ }
+ #endif
+ free(address);
+}
+
+void *SzAllocTemp(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
+ g_allocCountTemp++;
+ #ifdef _WIN32
+ return HeapAlloc(GetProcessHeap(), 0, size);
+ #endif
+ #endif
+ return malloc(size);
+}
+
+void SzFreeTemp(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ {
+ g_allocCountTemp--;
+ fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
+ }
+ #ifdef _WIN32
+ HeapFree(GetProcessHeap(), 0, address);
+ return;
+ #endif
+ #endif
+ free(address);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.h
new file mode 100644
index 00000000..b02c1dea
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zAlloc.h
@@ -0,0 +1,20 @@
+/* 7zAlloc.h */
+
+#ifndef __7Z_ALLOC_H
+#define __7Z_ALLOC_H
+
+#include <stddef.h>
+
+typedef struct _ISzAlloc
+{
+ void *(*Alloc)(size_t size);
+ void (*Free)(void *address); /* address can be 0 */
+} ISzAlloc;
+
+void *SzAlloc(size_t size);
+void SzFree(void *address);
+
+void *SzAllocTemp(size_t size);
+void SzFreeTemp(void *address);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.c
new file mode 100644
index 00000000..8bc8e067
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.c
@@ -0,0 +1,29 @@
+/* 7zBuffer.c */
+
+#include "7zBuffer.h"
+#include "7zAlloc.h"
+
+void SzByteBufferInit(CSzByteBuffer *buffer)
+{
+ buffer->Capacity = 0;
+ buffer->Items = 0;
+}
+
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
+{
+ buffer->Capacity = newCapacity;
+ if (newCapacity == 0)
+ {
+ buffer->Items = 0;
+ return 1;
+ }
+ buffer->Items = (Byte *)allocFunc(newCapacity);
+ return (buffer->Items != 0);
+}
+
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
+{
+ freeFunc(buffer->Items);
+ buffer->Items = 0;
+ buffer->Capacity = 0;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.h
new file mode 100644
index 00000000..afea3ca8
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zBuffer.h
@@ -0,0 +1,19 @@
+/* 7zBuffer.h */
+
+#ifndef __7Z_BUFFER_H
+#define __7Z_BUFFER_H
+
+#include <stddef.h>
+#include "7zTypes.h"
+
+typedef struct _CSzByteBuffer
+{
+ size_t Capacity;
+ Byte *Items;
+}CSzByteBuffer;
+
+void SzByteBufferInit(CSzByteBuffer *buffer);
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.c
new file mode 100644
index 00000000..6dc7dd32
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.c
@@ -0,0 +1,76 @@
+/* 7zCrc.c */
+
+#include "7zCrc.h"
+
+#define kCrcPoly 0xEDB88320
+
+UInt32 g_CrcTable[256];
+
+void InitCrcTable()
+{
+ UInt32 i;
+ for (i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ int j;
+ for (j = 0; j < 8; j++)
+ if (r & 1)
+ r = (r >> 1) ^ kCrcPoly;
+ else
+ r >>= 1;
+ g_CrcTable[i] = r;
+ }
+}
+
+void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; }
+UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; }
+
+void CrcUpdateByte(UInt32 *crc, Byte b)
+{
+ *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8);
+}
+
+void CrcUpdateUInt16(UInt32 *crc, UInt16 v)
+{
+ CrcUpdateByte(crc, (Byte)v);
+ CrcUpdateByte(crc, (Byte)(v >> 8));
+}
+
+void CrcUpdateUInt32(UInt32 *crc, UInt32 v)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ CrcUpdateByte(crc, (Byte)(v >> (8 * i)));
+}
+
+void CrcUpdateUInt64(UInt32 *crc, UInt64 v)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ CrcUpdateByte(crc, (Byte)(v));
+ v >>= 8;
+ }
+}
+
+void CrcUpdate(UInt32 *crc, const void *data, size_t size)
+{
+ UInt32 v = *crc;
+ const Byte *p = (const Byte *)data;
+ for (; size > 0 ; size--, p++)
+ v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8);
+ *crc = v;
+}
+
+UInt32 CrcCalculateDigest(const void *data, size_t size)
+{
+ UInt32 crc;
+ CrcInit(&crc);
+ CrcUpdate(&crc, data, size);
+ return CrcGetDigest(&crc);
+}
+
+int CrcVerifyDigest(UInt32 digest, const void *data, size_t size)
+{
+ return (CrcCalculateDigest(data, size) == digest);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.h
new file mode 100644
index 00000000..bac26b14
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zCrc.h
@@ -0,0 +1,24 @@
+/* 7zCrc.h */
+
+#ifndef __7Z_CRC_H
+#define __7Z_CRC_H
+
+#include <stddef.h>
+
+#include "7zTypes.h"
+
+extern UInt32 g_CrcTable[256];
+void InitCrcTable();
+
+void CrcInit(UInt32 *crc);
+UInt32 CrcGetDigest(UInt32 *crc);
+void CrcUpdateByte(UInt32 *crc, Byte v);
+void CrcUpdateUInt16(UInt32 *crc, UInt16 v);
+void CrcUpdateUInt32(UInt32 *crc, UInt32 v);
+void CrcUpdateUInt64(UInt32 *crc, UInt64 v);
+void CrcUpdate(UInt32 *crc, const void *data, size_t size);
+
+UInt32 CrcCalculateDigest(const void *data, size_t size);
+int CrcVerifyDigest(UInt32 digest, const void *data, size_t size);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.c
new file mode 100644
index 00000000..9dfbe7dc
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.c
@@ -0,0 +1,150 @@
+/* 7zDecode.c */
+
+#include "7zDecode.h"
+#ifdef _SZ_ONE_DIRECTORY
+#include "LzmaDecode.h"
+#else
+#include "../../Compress/LZMA_C/LzmaDecode.h"
+#endif
+
+CMethodID k_Copy = { { 0x0 }, 1 };
+CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+
+#ifdef _LZMA_IN_CB
+
+typedef struct _CLzmaInCallbackImp
+{
+ ILzmaInCallback InCallback;
+ ISzInStream *InStream;
+ size_t Size;
+} CLzmaInCallbackImp;
+
+int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
+{
+ CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
+ size_t processedSize;
+ SZ_RESULT res;
+ *size = 0;
+ res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize);
+ *size = (SizeT)processedSize;
+ if (processedSize > cb->Size)
+ return (int)SZE_FAIL;
+ cb->Size -= processedSize;
+ if (res == SZ_OK)
+ return 0;
+ return (int)res;
+}
+
+#endif
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+ #ifdef _LZMA_IN_CB
+ ISzInStream *inStream,
+ #else
+ const Byte *inBuffer,
+ #endif
+ Byte *outBuffer, size_t outSize,
+ size_t *outSizeProcessed, ISzAlloc *allocMain)
+{
+ UInt32 si;
+ size_t inSize = 0;
+ CCoderInfo *coder;
+ if (folder->NumPackStreams != 1)
+ return SZE_NOTIMPL;
+ if (folder->NumCoders != 1)
+ return SZE_NOTIMPL;
+ coder = folder->Coders;
+ *outSizeProcessed = 0;
+
+ for (si = 0; si < folder->NumPackStreams; si++)
+ inSize += (size_t)packSizes[si];
+
+ if (AreMethodsEqual(&coder->MethodID, &k_Copy))
+ {
+ size_t i;
+ if (inSize != outSize)
+ return SZE_DATA_ERROR;
+ #ifdef _LZMA_IN_CB
+ for (i = 0; i < inSize;)
+ {
+ size_t j;
+ Byte *inBuffer;
+ size_t bufferSize;
+ RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize));
+ if (bufferSize == 0)
+ return SZE_DATA_ERROR;
+ if (bufferSize > inSize - i)
+ return SZE_FAIL;
+ *outSizeProcessed += bufferSize;
+ for (j = 0; j < bufferSize && i < inSize; j++, i++)
+ outBuffer[i] = inBuffer[j];
+ }
+ #else
+ for (i = 0; i < inSize; i++)
+ outBuffer[i] = inBuffer[i];
+ *outSizeProcessed = inSize;
+ #endif
+ return SZ_OK;
+ }
+
+ if (AreMethodsEqual(&coder->MethodID, &k_LZMA))
+ {
+ #ifdef _LZMA_IN_CB
+ CLzmaInCallbackImp lzmaCallback;
+ #else
+ SizeT inProcessed;
+ #endif
+
+ CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
+ int result;
+ SizeT outSizeProcessedLoc;
+
+ #ifdef _LZMA_IN_CB
+ lzmaCallback.Size = inSize;
+ lzmaCallback.InStream = inStream;
+ lzmaCallback.InCallback.Read = LzmaReadImp;
+ #endif
+
+ if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
+ coder->Properties.Capacity) != LZMA_RESULT_OK)
+ return SZE_FAIL;
+
+ state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return SZE_OUTOFMEMORY;
+
+ #ifdef _LZMA_OUT_READ
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ {
+ state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
+ if (state.Dictionary == 0)
+ {
+ allocMain->Free(state.Probs);
+ return SZE_OUTOFMEMORY;
+ }
+ }
+ LzmaDecoderInit(&state);
+ #endif
+
+ result = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &lzmaCallback.InCallback,
+ #else
+ inBuffer, (SizeT)inSize, &inProcessed,
+ #endif
+ outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
+ *outSizeProcessed = (size_t)outSizeProcessedLoc;
+ allocMain->Free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ allocMain->Free(state.Dictionary);
+ #endif
+ if (result == LZMA_RESULT_DATA_ERROR)
+ return SZE_DATA_ERROR;
+ if (result != LZMA_RESULT_OK)
+ return SZE_FAIL;
+ return SZ_OK;
+ }
+ return SZE_NOTIMPL;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.h
new file mode 100644
index 00000000..432b7ce3
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zDecode.h
@@ -0,0 +1,21 @@
+/* 7zDecode.h */
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+#ifdef _LZMA_IN_CB
+#include "7zIn.h"
+#endif
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+ #ifdef _LZMA_IN_CB
+ ISzInStream *stream,
+ #else
+ const Byte *inBuffer,
+ #endif
+ Byte *outBuffer, size_t outSize,
+ size_t *outSizeProcessed, ISzAlloc *allocMain);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.c
new file mode 100644
index 00000000..21fb0131
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.c
@@ -0,0 +1,116 @@
+/* 7zExtract.c */
+
+#include "7zExtract.h"
+#include "7zDecode.h"
+#include "7zCrc.h"
+
+SZ_RESULT SzExtract(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ UInt32 fileIndex,
+ UInt32 *blockIndex,
+ Byte **outBuffer,
+ size_t *outBufferSize,
+ size_t *offset,
+ size_t *outSizeProcessed,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
+ SZ_RESULT res = SZ_OK;
+ *offset = 0;
+ *outSizeProcessed = 0;
+ if (folderIndex == (UInt32)-1)
+ {
+ allocMain->Free(*outBuffer);
+ *blockIndex = folderIndex;
+ *outBuffer = 0;
+ *outBufferSize = 0;
+ return SZ_OK;
+ }
+
+ if (*outBuffer == 0 || *blockIndex != folderIndex)
+ {
+ CFolder *folder = db->Database.Folders + folderIndex;
+ CFileSize unPackSize = SzFolderGetUnPackSize(folder);
+ #ifndef _LZMA_IN_CB
+ CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex);
+ Byte *inBuffer = 0;
+ size_t processedSize;
+ #endif
+ *blockIndex = folderIndex;
+ allocMain->Free(*outBuffer);
+ *outBuffer = 0;
+
+ RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0)));
+
+ #ifndef _LZMA_IN_CB
+ if (packSize != 0)
+ {
+ inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize);
+ if (inBuffer == 0)
+ return SZE_OUTOFMEMORY;
+ }
+ res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize);
+ if (res == SZ_OK && processedSize != (size_t)packSize)
+ res = SZE_FAIL;
+ #endif
+ if (res == SZ_OK)
+ {
+ *outBufferSize = (size_t)unPackSize;
+ if (unPackSize != 0)
+ {
+ *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize);
+ if (*outBuffer == 0)
+ res = SZE_OUTOFMEMORY;
+ }
+ if (res == SZ_OK)
+ {
+ size_t outRealSize;
+ res = SzDecode(db->Database.PackSizes +
+ db->FolderStartPackStreamIndex[folderIndex], folder,
+ #ifdef _LZMA_IN_CB
+ inStream,
+ #else
+ inBuffer,
+ #endif
+ *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp);
+ if (res == SZ_OK)
+ {
+ if (outRealSize == (size_t)unPackSize)
+ {
+ if (folder->UnPackCRCDefined)
+ {
+ if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize))
+ res = SZE_FAIL;
+ }
+ }
+ else
+ res = SZE_FAIL;
+ }
+ }
+ }
+ #ifndef _LZMA_IN_CB
+ allocTemp->Free(inBuffer);
+ #endif
+ }
+ if (res == SZ_OK)
+ {
+ UInt32 i;
+ CFileItem *fileItem = db->Database.Files + fileIndex;
+ *offset = 0;
+ for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
+ *offset += (UInt32)db->Database.Files[i].Size;
+ *outSizeProcessed = (size_t)fileItem->Size;
+ if (*offset + *outSizeProcessed > *outBufferSize)
+ return SZE_FAIL;
+ {
+ if (fileItem->IsFileCRCDefined)
+ {
+ if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed))
+ res = SZE_FAIL;
+ }
+ }
+ }
+ return res;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.h
new file mode 100644
index 00000000..4ae2a056
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zExtract.h
@@ -0,0 +1,40 @@
+/* 7zExtract.h */
+
+#ifndef __7Z_EXTRACT_H
+#define __7Z_EXTRACT_H
+
+#include "7zIn.h"
+
+/*
+ SzExtract extracts file from archive
+
+ *outBuffer must be 0 before first call for each new archive.
+
+ Extracting cache:
+ If you need to decompress more than one file, you can send
+ these values from previous call:
+ *blockIndex,
+ *outBuffer,
+ *outBufferSize
+ You can consider "*outBuffer" as cache of solid block. If your archive is solid,
+ it will increase decompression speed.
+
+ If you use external function, you can declare these 3 cache variables
+ (blockIndex, outBuffer, outBufferSize) as static in that external function.
+
+ Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
+*/
+
+SZ_RESULT SzExtract(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ UInt32 fileIndex, /* index of file */
+ UInt32 *blockIndex, /* index of solid block */
+ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
+ size_t *outBufferSize, /* buffer size for output buffer */
+ size_t *offset, /* offset of stream for required file in *outBuffer */
+ size_t *outSizeProcessed, /* size of file in *outBuffer */
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.c
new file mode 100644
index 00000000..e26c0143
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.c
@@ -0,0 +1,5 @@
+/* 7zHeader.c */
+
+#include "7zHeader.h"
+
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.h
new file mode 100644
index 00000000..7edf640f
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zHeader.h
@@ -0,0 +1,55 @@
+/* 7zHeader.h */
+
+#ifndef __7Z_HEADER_H
+#define __7Z_HEADER_H
+
+#include "7zTypes.h"
+
+#define k7zSignatureSize 6
+extern Byte k7zSignature[k7zSignatureSize];
+
+#define k7zMajorVersion 0
+
+#define k7zStartHeaderSize 0x20
+
+enum EIdEnum
+{
+ k7zIdEnd,
+
+ k7zIdHeader,
+
+ k7zIdArchiveProperties,
+
+ k7zIdAdditionalStreamsInfo,
+ k7zIdMainStreamsInfo,
+ k7zIdFilesInfo,
+
+ k7zIdPackInfo,
+ k7zIdUnPackInfo,
+ k7zIdSubStreamsInfo,
+
+ k7zIdSize,
+ k7zIdCRC,
+
+ k7zIdFolder,
+
+ k7zIdCodersUnPackSize,
+ k7zIdNumUnPackStream,
+
+ k7zIdEmptyStream,
+ k7zIdEmptyFile,
+ k7zIdAnti,
+
+ k7zIdName,
+ k7zIdCreationTime,
+ k7zIdLastAccessTime,
+ k7zIdLastWriteTime,
+ k7zIdWinAttributes,
+ k7zIdComment,
+
+ k7zIdEncodedHeader,
+
+ k7zIdStartPos
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.c
new file mode 100644
index 00000000..6d910b6c
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.c
@@ -0,0 +1,1292 @@
+/* 7zIn.c */
+
+#include "7zIn.h"
+#include "7zCrc.h"
+#include "7zDecode.h"
+
+#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; }
+
+void SzArDbExInit(CArchiveDatabaseEx *db)
+{
+ SzArchiveDatabaseInit(&db->Database);
+ db->FolderStartPackStreamIndex = 0;
+ db->PackStreamStartPositions = 0;
+ db->FolderStartFileIndex = 0;
+ db->FileIndexToFolderIndexMap = 0;
+}
+
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *))
+{
+ freeFunc(db->FolderStartPackStreamIndex);
+ freeFunc(db->PackStreamStartPositions);
+ freeFunc(db->FolderStartFileIndex);
+ freeFunc(db->FileIndexToFolderIndexMap);
+ SzArchiveDatabaseFree(&db->Database, freeFunc);
+ SzArDbExInit(db);
+}
+
+/*
+CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const
+{
+ return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+}
+
+CFileSize GetFilePackSize(int fileIndex) const
+{
+ int folderIndex = FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex >= 0)
+ {
+ const CFolder &folderInfo = Folders[folderIndex];
+ if (FolderStartFileIndex[folderIndex] == fileIndex)
+ return GetFolderFullPackSize(folderIndex);
+ }
+ return 0;
+}
+*/
+
+
+SZ_RESULT MySzInAlloc(void **p, size_t size, void * (*allocFunc)(size_t size))
+{
+ if (size == 0)
+ *p = 0;
+ else
+ {
+ *p = allocFunc(size);
+ RINOM(*p);
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
+{
+ UInt32 startPos = 0;
+ CFileSize startPosSize = 0;
+ UInt32 i;
+ UInt32 folderIndex = 0;
+ UInt32 indexInFolder = 0;
+ RINOK(MySzInAlloc((void **)&db->FolderStartPackStreamIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc));
+ for(i = 0; i < db->Database.NumFolders; i++)
+ {
+ db->FolderStartPackStreamIndex[i] = startPos;
+ startPos += db->Database.Folders[i].NumPackStreams;
+ }
+
+ RINOK(MySzInAlloc((void **)&db->PackStreamStartPositions, db->Database.NumPackStreams * sizeof(CFileSize), allocFunc));
+
+ for(i = 0; i < db->Database.NumPackStreams; i++)
+ {
+ db->PackStreamStartPositions[i] = startPosSize;
+ startPosSize += db->Database.PackSizes[i];
+ }
+
+ RINOK(MySzInAlloc((void **)&db->FolderStartFileIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc));
+ RINOK(MySzInAlloc((void **)&db->FileIndexToFolderIndexMap, db->Database.NumFiles * sizeof(UInt32), allocFunc));
+
+ for (i = 0; i < db->Database.NumFiles; i++)
+ {
+ CFileItem *file = db->Database.Files + i;
+ int emptyStream = !file->HasStream;
+ if (emptyStream && indexInFolder == 0)
+ {
+ db->FileIndexToFolderIndexMap[i] = (UInt32)-1;
+ continue;
+ }
+ if (indexInFolder == 0)
+ {
+ /*
+ v3.13 incorrectly worked with empty folders
+ v4.07: Loop for skipping empty folders
+ */
+ while(1)
+ {
+ if (folderIndex >= db->Database.NumFolders)
+ return SZE_ARCHIVE_ERROR;
+ db->FolderStartFileIndex[folderIndex] = i;
+ if (db->Database.Folders[folderIndex].NumUnPackStreams != 0)
+ break;
+ folderIndex++;
+ }
+ }
+ db->FileIndexToFolderIndexMap[i] = folderIndex;
+ if (emptyStream)
+ continue;
+ indexInFolder++;
+ if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams)
+ {
+ folderIndex++;
+ indexInFolder = 0;
+ }
+ }
+ return SZ_OK;
+}
+
+
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder)
+{
+ return db->ArchiveInfo.DataStartPosition +
+ db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
+}
+
+CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex)
+{
+ UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex];
+ CFolder *folder = db->Database.Folders + folderIndex;
+ CFileSize size = 0;
+ UInt32 i;
+ for (i = 0; i < folder->NumPackStreams; i++)
+ size += db->Database.PackSizes[packStreamIndex + i];
+ return size;
+}
+
+
+/*
+SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector,
+ CObjectVector<CFileItem> &files, UInt64 type)
+{
+ CBoolVector boolVector;
+ RINOK(ReadBoolVector2(files.Size(), boolVector))
+
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, &dataVector));
+
+ for(int i = 0; i < files.Size(); i++)
+ {
+ CFileItem &file = files[i];
+ CArchiveFileTime fileTime;
+ bool defined = boolVector[i];
+ if (defined)
+ {
+ UInt32 low, high;
+ RINOK(SzReadUInt32(low));
+ RINOK(SzReadUInt32(high));
+ fileTime.dwLowDateTime = low;
+ fileTime.dwHighDateTime = high;
+ }
+ switch(type)
+ {
+ case k7zIdCreationTime:
+ file.IsCreationTimeDefined = defined;
+ if (defined)
+ file.CreationTime = fileTime;
+ break;
+ case k7zIdLastWriteTime:
+ file.IsLastWriteTimeDefined = defined;
+ if (defined)
+ file.LastWriteTime = fileTime;
+ break;
+ case k7zIdLastAccessTime:
+ file.IsLastAccessTimeDefined = defined;
+ if (defined)
+ file.LastAccessTime = fileTime;
+ break;
+ }
+ }
+ return SZ_OK;
+}
+*/
+
+SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size)
+{
+ #ifdef _LZMA_IN_CB
+ while (size > 0)
+ {
+ Byte *inBuffer;
+ size_t processedSize;
+ RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize));
+ if (processedSize == 0 || processedSize > size)
+ return SZE_FAIL;
+ size -= processedSize;
+ do
+ {
+ *data++ = *inBuffer++;
+ }
+ while (--processedSize != 0);
+ }
+ #else
+ size_t processedSize;
+ RINOK(inStream->Read(inStream, data, size, &processedSize));
+ if (processedSize != size)
+ return SZE_FAIL;
+ #endif
+ return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data)
+{
+ return SafeReadDirect(inStream, data, 1);
+}
+
+SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(inStream, &b));
+ *value |= ((UInt32)b << (8 * i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 8; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(inStream, &b));
+ *value |= ((UInt32)b << (8 * i));
+ }
+ return SZ_OK;
+}
+
+int TestSignatureCandidate(Byte *testBytes)
+{
+ size_t i;
+ for (i = 0; i < k7zSignatureSize; i++)
+ if (testBytes[i] != k7zSignature[i])
+ return 0;
+ return 1;
+}
+
+typedef struct _CSzState
+{
+ Byte *Data;
+ size_t Size;
+}CSzData;
+
+SZ_RESULT SzReadByte(CSzData *sd, Byte *b)
+{
+ if (sd->Size == 0)
+ return SZE_ARCHIVE_ERROR;
+ sd->Size--;
+ *b = *sd->Data++;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size)
+{
+ size_t i;
+ for (i = 0; i < size; i++)
+ {
+ RINOK(SzReadByte(sd, data + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(SzReadByte(sd, &b));
+ *value |= ((UInt32)(b) << (8 * i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value)
+{
+ Byte firstByte;
+ Byte mask = 0x80;
+ int i;
+ RINOK(SzReadByte(sd, &firstByte));
+ *value = 0;
+ for (i = 0; i < 8; i++)
+ {
+ Byte b;
+ if ((firstByte & mask) == 0)
+ {
+ UInt64 highPart = firstByte & (mask - 1);
+ *value += (highPart << (8 * i));
+ return SZ_OK;
+ }
+ RINOK(SzReadByte(sd, &b));
+ *value |= ((UInt64)b << (8 * i));
+ mask >>= 1;
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value)
+{
+ UInt64 value64;
+ RINOK(SzReadNumber(sd, &value64));
+ *value = (CFileSize)value64;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value)
+{
+ UInt64 value64;
+ RINOK(SzReadNumber(sd, &value64));
+ if (value64 >= 0x80000000)
+ return SZE_NOTIMPL;
+ if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
+ return SZE_NOTIMPL;
+ *value = (UInt32)value64;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadID(CSzData *sd, UInt64 *value)
+{
+ return SzReadNumber(sd, value);
+}
+
+SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size)
+{
+ if (size > sd->Size)
+ return SZE_ARCHIVE_ERROR;
+ sd->Size -= (size_t)size;
+ sd->Data += (size_t)size;
+ return SZ_OK;
+}
+
+SZ_RESULT SzSkeepData(CSzData *sd)
+{
+ UInt64 size;
+ RINOK(SzReadNumber(sd, &size));
+ return SzSkeepDataSize(sd, size);
+}
+
+SZ_RESULT SzReadArchiveProperties(CSzData *sd)
+{
+ while(1)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ SzSkeepData(sd);
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute)
+{
+ while(1)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == attribute)
+ return SZ_OK;
+ if (type == k7zIdEnd)
+ return SZE_ARCHIVE_ERROR;
+ RINOK(SzSkeepData(sd));
+ }
+}
+
+SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+ Byte b = 0;
+ Byte mask = 0;
+ size_t i;
+ RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc));
+ for(i = 0; i < numItems; i++)
+ {
+ if (mask == 0)
+ {
+ RINOK(SzReadByte(sd, &b));
+ mask = 0x80;
+ }
+ (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
+ mask >>= 1;
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+ Byte allAreDefined;
+ size_t i;
+ RINOK(SzReadByte(sd, &allAreDefined));
+ if (allAreDefined == 0)
+ return SzReadBoolVector(sd, numItems, v, allocFunc);
+ RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc));
+ for(i = 0; i < numItems; i++)
+ (*v)[i] = 1;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadHashDigests(
+ CSzData *sd,
+ size_t numItems,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ void * (*allocFunc)(size_t size))
+{
+ size_t i;
+ RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc));
+ RINOK(MySzInAlloc((void **)digests, numItems * sizeof(UInt32), allocFunc));
+ for(i = 0; i < numItems; i++)
+ if ((*digestsDefined)[i])
+ {
+ RINOK(SzReadUInt32(sd, (*digests) + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadPackInfo(
+ CSzData *sd,
+ CFileSize *dataOffset,
+ UInt32 *numPackStreams,
+ CFileSize **packSizes,
+ Byte **packCRCsDefined,
+ UInt32 **packCRCs,
+ void * (*allocFunc)(size_t size))
+{
+ UInt32 i;
+ RINOK(SzReadSize(sd, dataOffset));
+ RINOK(SzReadNumber32(sd, numPackStreams));
+
+ RINOK(SzWaitAttribute(sd, k7zIdSize));
+
+ RINOK(MySzInAlloc((void **)packSizes, (size_t)*numPackStreams * sizeof(CFileSize), allocFunc));
+
+ for(i = 0; i < *numPackStreams; i++)
+ {
+ RINOK(SzReadSize(sd, (*packSizes) + i));
+ }
+
+ while(1)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ if (type == k7zIdCRC)
+ {
+ RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc));
+ continue;
+ }
+ RINOK(SzSkeepData(sd));
+ }
+ if (*packCRCsDefined == 0)
+ {
+ RINOK(MySzInAlloc((void **)packCRCsDefined, (size_t)*numPackStreams * sizeof(Byte), allocFunc));
+ RINOK(MySzInAlloc((void **)packCRCs, (size_t)*numPackStreams * sizeof(UInt32), allocFunc));
+ for(i = 0; i < *numPackStreams; i++)
+ {
+ (*packCRCsDefined)[i] = 0;
+ (*packCRCs)[i] = 0;
+ }
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadSwitch(CSzData *sd)
+{
+ Byte external;
+ RINOK(SzReadByte(sd, &external));
+ return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR;
+}
+
+SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size))
+{
+ UInt32 numCoders;
+ UInt32 numBindPairs;
+ UInt32 numPackedStreams;
+ UInt32 i;
+ UInt32 numInStreams = 0;
+ UInt32 numOutStreams = 0;
+ RINOK(SzReadNumber32(sd, &numCoders));
+ folder->NumCoders = numCoders;
+
+ RINOK(MySzInAlloc((void **)&folder->Coders, (size_t)numCoders * sizeof(CCoderInfo), allocFunc));
+
+ for (i = 0; i < numCoders; i++)
+ SzCoderInfoInit(folder->Coders + i);
+
+ for (i = 0; i < numCoders; i++)
+ {
+ Byte mainByte;
+ CCoderInfo *coder = folder->Coders + i;
+ {
+ RINOK(SzReadByte(sd, &mainByte));
+ coder->MethodID.IDSize = (Byte)(mainByte & 0xF);
+ RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize));
+ if ((mainByte & 0x10) != 0)
+ {
+ RINOK(SzReadNumber32(sd, &coder->NumInStreams));
+ RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
+ }
+ else
+ {
+ coder->NumInStreams = 1;
+ coder->NumOutStreams = 1;
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ UInt64 propertiesSize = 0;
+ RINOK(SzReadNumber(sd, &propertiesSize));
+ if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc))
+ return SZE_OUTOFMEMORY;
+ RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize));
+ }
+ }
+ while ((mainByte & 0x80) != 0)
+ {
+ RINOK(SzReadByte(sd, &mainByte));
+ RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
+ if ((mainByte & 0x10) != 0)
+ {
+ UInt32 n;
+ RINOK(SzReadNumber32(sd, &n));
+ RINOK(SzReadNumber32(sd, &n));
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ UInt64 propertiesSize = 0;
+ RINOK(SzReadNumber(sd, &propertiesSize));
+ RINOK(SzSkeepDataSize(sd, propertiesSize));
+ }
+ }
+ numInStreams += (UInt32)coder->NumInStreams;
+ numOutStreams += (UInt32)coder->NumOutStreams;
+ }
+
+ numBindPairs = numOutStreams - 1;
+ folder->NumBindPairs = numBindPairs;
+
+
+ RINOK(MySzInAlloc((void **)&folder->BindPairs, (size_t)numBindPairs * sizeof(CBindPair), allocFunc));
+
+ for (i = 0; i < numBindPairs; i++)
+ {
+ CBindPair *bindPair = folder->BindPairs + i;;
+ RINOK(SzReadNumber32(sd, &bindPair->InIndex));
+ RINOK(SzReadNumber32(sd, &bindPair->OutIndex));
+ }
+
+ numPackedStreams = numInStreams - (UInt32)numBindPairs;
+
+ folder->NumPackStreams = numPackedStreams;
+ RINOK(MySzInAlloc((void **)&folder->PackStreams, (size_t)numPackedStreams * sizeof(UInt32), allocFunc));
+
+ if (numPackedStreams == 1)
+ {
+ UInt32 j;
+ UInt32 pi = 0;
+ for (j = 0; j < numInStreams; j++)
+ if (SzFolderFindBindPairForInStream(folder, j) < 0)
+ {
+ folder->PackStreams[pi++] = j;
+ break;
+ }
+ }
+ else
+ for(i = 0; i < numPackedStreams; i++)
+ {
+ RINOK(SzReadNumber32(sd, folder->PackStreams + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadUnPackInfo(
+ CSzData *sd,
+ UInt32 *numFolders,
+ CFolder **folders, /* for allocFunc */
+ void * (*allocFunc)(size_t size),
+ ISzAlloc *allocTemp)
+{
+ UInt32 i;
+ RINOK(SzWaitAttribute(sd, k7zIdFolder));
+ RINOK(SzReadNumber32(sd, numFolders));
+ {
+ RINOK(SzReadSwitch(sd));
+
+
+ RINOK(MySzInAlloc((void **)folders, (size_t)*numFolders * sizeof(CFolder), allocFunc));
+
+ for(i = 0; i < *numFolders; i++)
+ SzFolderInit((*folders) + i);
+
+ for(i = 0; i < *numFolders; i++)
+ {
+ RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc));
+ }
+ }
+
+ RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize));
+
+ for(i = 0; i < *numFolders; i++)
+ {
+ UInt32 j;
+ CFolder *folder = (*folders) + i;
+ UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
+
+ RINOK(MySzInAlloc((void **)&folder->UnPackSizes, (size_t)numOutStreams * sizeof(CFileSize), allocFunc));
+
+ for(j = 0; j < numOutStreams; j++)
+ {
+ RINOK(SzReadSize(sd, folder->UnPackSizes + j));
+ }
+ }
+
+ while(1)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ return SZ_OK;
+ if (type == k7zIdCRC)
+ {
+ SZ_RESULT res;
+ Byte *crcsDefined = 0;
+ UInt32 *crcs = 0;
+ res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc);
+ if (res == SZ_OK)
+ {
+ for(i = 0; i < *numFolders; i++)
+ {
+ CFolder *folder = (*folders) + i;
+ folder->UnPackCRCDefined = crcsDefined[i];
+ folder->UnPackCRC = crcs[i];
+ }
+ }
+ allocTemp->Free(crcs);
+ allocTemp->Free(crcsDefined);
+ RINOK(res);
+ continue;
+ }
+ RINOK(SzSkeepData(sd));
+ }
+}
+
+SZ_RESULT SzReadSubStreamsInfo(
+ CSzData *sd,
+ UInt32 numFolders,
+ CFolder *folders,
+ UInt32 *numUnPackStreams,
+ CFileSize **unPackSizes,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ ISzAlloc *allocTemp)
+{
+ UInt64 type = 0;
+ UInt32 i;
+ UInt32 si = 0;
+ UInt32 numDigests = 0;
+
+ for(i = 0; i < numFolders; i++)
+ folders[i].NumUnPackStreams = 1;
+ *numUnPackStreams = numFolders;
+
+ while(1)
+ {
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdNumUnPackStream)
+ {
+ *numUnPackStreams = 0;
+ for(i = 0; i < numFolders; i++)
+ {
+ UInt32 numStreams;
+ RINOK(SzReadNumber32(sd, &numStreams));
+ folders[i].NumUnPackStreams = numStreams;
+ *numUnPackStreams += numStreams;
+ }
+ continue;
+ }
+ if (type == k7zIdCRC || type == k7zIdSize)
+ break;
+ if (type == k7zIdEnd)
+ break;
+ RINOK(SzSkeepData(sd));
+ }
+
+ if (*numUnPackStreams == 0)
+ {
+ *unPackSizes = 0;
+ *digestsDefined = 0;
+ *digests = 0;
+ }
+ else
+ {
+ *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize));
+ RINOM(*unPackSizes);
+ *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte));
+ RINOM(*digestsDefined);
+ *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32));
+ RINOM(*digests);
+ }
+
+ for(i = 0; i < numFolders; i++)
+ {
+ /*
+ v3.13 incorrectly worked with empty folders
+ v4.07: we check that folder is empty
+ */
+ CFileSize sum = 0;
+ UInt32 j;
+ UInt32 numSubstreams = folders[i].NumUnPackStreams;
+ if (numSubstreams == 0)
+ continue;
+ if (type == k7zIdSize)
+ for (j = 1; j < numSubstreams; j++)
+ {
+ CFileSize size;
+ RINOK(SzReadSize(sd, &size));
+ (*unPackSizes)[si++] = size;
+ sum += size;
+ }
+ (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum;
+ }
+ if (type == k7zIdSize)
+ {
+ RINOK(SzReadID(sd, &type));
+ }
+
+ for(i = 0; i < *numUnPackStreams; i++)
+ {
+ (*digestsDefined)[i] = 0;
+ (*digests)[i] = 0;
+ }
+
+
+ for(i = 0; i < numFolders; i++)
+ {
+ UInt32 numSubstreams = folders[i].NumUnPackStreams;
+ if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+ numDigests += numSubstreams;
+ }
+
+
+ si = 0;
+ while(1)
+ {
+ if (type == k7zIdCRC)
+ {
+ int digestIndex = 0;
+ Byte *digestsDefined2 = 0;
+ UInt32 *digests2 = 0;
+ SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc);
+ if (res == SZ_OK)
+ {
+ for (i = 0; i < numFolders; i++)
+ {
+ CFolder *folder = folders + i;
+ UInt32 numSubstreams = folder->NumUnPackStreams;
+ if (numSubstreams == 1 && folder->UnPackCRCDefined)
+ {
+ (*digestsDefined)[si] = 1;
+ (*digests)[si] = folder->UnPackCRC;
+ si++;
+ }
+ else
+ {
+ UInt32 j;
+ for (j = 0; j < numSubstreams; j++, digestIndex++)
+ {
+ (*digestsDefined)[si] = digestsDefined2[digestIndex];
+ (*digests)[si] = digests2[digestIndex];
+ si++;
+ }
+ }
+ }
+ }
+ allocTemp->Free(digestsDefined2);
+ allocTemp->Free(digests2);
+ RINOK(res);
+ }
+ else if (type == k7zIdEnd)
+ return SZ_OK;
+ else
+ {
+ RINOK(SzSkeepData(sd));
+ }
+ RINOK(SzReadID(sd, &type));
+ }
+}
+
+
+SZ_RESULT SzReadStreamsInfo(
+ CSzData *sd,
+ CFileSize *dataOffset,
+ CArchiveDatabase *db,
+ UInt32 *numUnPackStreams,
+ CFileSize **unPackSizes, /* allocTemp */
+ Byte **digestsDefined, /* allocTemp */
+ UInt32 **digests, /* allocTemp */
+ void * (*allocFunc)(size_t size),
+ ISzAlloc *allocTemp)
+{
+ while(1)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if ((UInt64)(int)type != type)
+ return SZE_FAIL;
+ switch((int)type)
+ {
+ case k7zIdEnd:
+ return SZ_OK;
+ case k7zIdPackInfo:
+ {
+ RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams,
+ &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc));
+ break;
+ }
+ case k7zIdUnPackInfo:
+ {
+ RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp));
+ break;
+ }
+ case k7zIdSubStreamsInfo:
+ {
+ RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders,
+ numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp));
+ break;
+ }
+ default:
+ return SZE_FAIL;
+ }
+ }
+}
+
+Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files,
+ void * (*allocFunc)(size_t size))
+{
+ UInt32 i;
+ for(i = 0; i < numFiles; i++)
+ {
+ UInt32 len = 0;
+ UInt32 pos = 0;
+ CFileItem *file = files + i;
+ while(pos + 2 <= sd->Size)
+ {
+ int numAdds;
+ UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+ pos += 2;
+ len++;
+ if (value == 0)
+ break;
+ if (value < 0x80)
+ continue;
+ if (value >= 0xD800 && value < 0xE000)
+ {
+ UInt32 c2;
+ if (value >= 0xDC00)
+ return SZE_ARCHIVE_ERROR;
+ if (pos + 2 > sd->Size)
+ return SZE_ARCHIVE_ERROR;
+ c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+ pos += 2;
+ if (c2 < 0xDC00 || c2 >= 0xE000)
+ return SZE_ARCHIVE_ERROR;
+ value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+ }
+ for (numAdds = 1; numAdds < 5; numAdds++)
+ if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+ break;
+ len += numAdds;
+ }
+
+ RINOK(MySzInAlloc((void **)&file->Name, (size_t)len * sizeof(char), allocFunc));
+
+ len = 0;
+ while(2 <= sd->Size)
+ {
+ int numAdds;
+ UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+ SzSkeepDataSize(sd, 2);
+ if (value < 0x80)
+ {
+ file->Name[len++] = (char)value;
+ if (value == 0)
+ break;
+ continue;
+ }
+ if (value >= 0xD800 && value < 0xE000)
+ {
+ UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+ SzSkeepDataSize(sd, 2);
+ value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+ }
+ for (numAdds = 1; numAdds < 5; numAdds++)
+ if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+ break;
+ file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
+ do
+ {
+ numAdds--;
+ file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
+ }
+ while(numAdds > 0);
+
+ len += numAdds;
+ }
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadHeader2(
+ CSzData *sd,
+ CArchiveDatabaseEx *db, /* allocMain */
+ CFileSize **unPackSizes, /* allocTemp */
+ Byte **digestsDefined, /* allocTemp */
+ UInt32 **digests, /* allocTemp */
+ Byte **emptyStreamVector, /* allocTemp */
+ Byte **emptyFileVector, /* allocTemp */
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ UInt64 type;
+ UInt32 numUnPackStreams = 0;
+ UInt32 numFiles = 0;
+ CFileItem *files = 0;
+ UInt32 numEmptyStreams = 0;
+ UInt32 i;
+
+ RINOK(SzReadID(sd, &type));
+
+ if (type == k7zIdArchiveProperties)
+ {
+ RINOK(SzReadArchiveProperties(sd));
+ RINOK(SzReadID(sd, &type));
+ }
+
+
+ if (type == k7zIdMainStreamsInfo)
+ {
+ RINOK(SzReadStreamsInfo(sd,
+ &db->ArchiveInfo.DataStartPosition,
+ &db->Database,
+ &numUnPackStreams,
+ unPackSizes,
+ digestsDefined,
+ digests, allocMain->Alloc, allocTemp));
+ db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader;
+ RINOK(SzReadID(sd, &type));
+ }
+
+ if (type == k7zIdEnd)
+ return SZ_OK;
+ if (type != k7zIdFilesInfo)
+ return SZE_ARCHIVE_ERROR;
+
+ RINOK(SzReadNumber32(sd, &numFiles));
+ db->Database.NumFiles = numFiles;
+
+ RINOK(MySzInAlloc((void **)&files, (size_t)numFiles * sizeof(CFileItem), allocMain->Alloc));
+
+ db->Database.Files = files;
+ for(i = 0; i < numFiles; i++)
+ SzFileInit(files + i);
+
+ while(1)
+ {
+ UInt64 type;
+ UInt64 size;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ RINOK(SzReadNumber(sd, &size));
+
+ if ((UInt64)(int)type != type)
+ {
+ RINOK(SzSkeepDataSize(sd, size));
+ }
+ else
+ switch((int)type)
+ {
+ case k7zIdName:
+ {
+ RINOK(SzReadSwitch(sd));
+ RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc))
+ break;
+ }
+ case k7zIdEmptyStream:
+ {
+ RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc));
+ numEmptyStreams = 0;
+ for (i = 0; i < numFiles; i++)
+ if ((*emptyStreamVector)[i])
+ numEmptyStreams++;
+ break;
+ }
+ case k7zIdEmptyFile:
+ {
+ RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc));
+ break;
+ }
+ default:
+ {
+ RINOK(SzSkeepDataSize(sd, size));
+ }
+ }
+ }
+
+ {
+ UInt32 emptyFileIndex = 0;
+ UInt32 sizeIndex = 0;
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem *file = files + i;
+ file->IsAnti = 0;
+ if (*emptyStreamVector == 0)
+ file->HasStream = 1;
+ else
+ file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
+ if(file->HasStream)
+ {
+ file->IsDirectory = 0;
+ file->Size = (*unPackSizes)[sizeIndex];
+ file->FileCRC = (*digests)[sizeIndex];
+ file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex];
+ sizeIndex++;
+ }
+ else
+ {
+ if (*emptyFileVector == 0)
+ file->IsDirectory = 1;
+ else
+ file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
+ emptyFileIndex++;
+ file->Size = 0;
+ file->IsFileCRCDefined = 0;
+ }
+ }
+ }
+ return SzArDbExFill(db, allocMain->Alloc);
+}
+
+SZ_RESULT SzReadHeader(
+ CSzData *sd,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ CFileSize *unPackSizes = 0;
+ Byte *digestsDefined = 0;
+ UInt32 *digests = 0;
+ Byte *emptyStreamVector = 0;
+ Byte *emptyFileVector = 0;
+ SZ_RESULT res = SzReadHeader2(sd, db,
+ &unPackSizes, &digestsDefined, &digests,
+ &emptyStreamVector, &emptyFileVector,
+ allocMain, allocTemp);
+ allocTemp->Free(unPackSizes);
+ allocTemp->Free(digestsDefined);
+ allocTemp->Free(digests);
+ allocTemp->Free(emptyStreamVector);
+ allocTemp->Free(emptyFileVector);
+ return res;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams2(
+ ISzInStream *inStream,
+ CSzData *sd,
+ CSzByteBuffer *outBuffer,
+ CFileSize baseOffset,
+ CArchiveDatabase *db,
+ CFileSize **unPackSizes,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ #ifndef _LZMA_IN_CB
+ Byte **inBuffer,
+ #endif
+ ISzAlloc *allocTemp)
+{
+
+ UInt32 numUnPackStreams = 0;
+ CFileSize dataStartPos;
+ CFolder *folder;
+ #ifndef _LZMA_IN_CB
+ CFileSize packSize = 0;
+ UInt32 i = 0;
+ #endif
+ CFileSize unPackSize;
+ size_t outRealSize;
+ SZ_RESULT res;
+
+ RINOK(SzReadStreamsInfo(sd, &dataStartPos, db,
+ &numUnPackStreams, unPackSizes, digestsDefined, digests,
+ allocTemp->Alloc, allocTemp));
+
+ dataStartPos += baseOffset;
+ if (db->NumFolders != 1)
+ return SZE_ARCHIVE_ERROR;
+
+ folder = db->Folders;
+ unPackSize = SzFolderGetUnPackSize(folder);
+
+ RINOK(inStream->Seek(inStream, dataStartPos));
+
+ #ifndef _LZMA_IN_CB
+ for (i = 0; i < db->NumPackStreams; i++)
+ packSize += db->PackSizes[i];
+
+ RINOK(MySzInAlloc((void **)inBuffer, (size_t)packSize, allocTemp->Alloc));
+
+ RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize));
+ #endif
+
+ if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc))
+ return SZE_OUTOFMEMORY;
+
+ res = SzDecode(db->PackSizes, folder,
+ #ifdef _LZMA_IN_CB
+ inStream,
+ #else
+ *inBuffer,
+ #endif
+ outBuffer->Items, (size_t)unPackSize,
+ &outRealSize, allocTemp);
+ RINOK(res)
+ if (outRealSize != (UInt32)unPackSize)
+ return SZE_FAIL;
+ if (folder->UnPackCRCDefined)
+ if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize))
+ return SZE_FAIL;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams(
+ ISzInStream *inStream,
+ CSzData *sd,
+ CSzByteBuffer *outBuffer,
+ CFileSize baseOffset,
+ ISzAlloc *allocTemp)
+{
+ CArchiveDatabase db;
+ CFileSize *unPackSizes = 0;
+ Byte *digestsDefined = 0;
+ UInt32 *digests = 0;
+ #ifndef _LZMA_IN_CB
+ Byte *inBuffer = 0;
+ #endif
+ SZ_RESULT res;
+ SzArchiveDatabaseInit(&db);
+ res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
+ &db, &unPackSizes, &digestsDefined, &digests,
+ #ifndef _LZMA_IN_CB
+ &inBuffer,
+ #endif
+ allocTemp);
+ SzArchiveDatabaseFree(&db, allocTemp->Free);
+ allocTemp->Free(unPackSizes);
+ allocTemp->Free(digestsDefined);
+ allocTemp->Free(digests);
+ #ifndef _LZMA_IN_CB
+ allocTemp->Free(inBuffer);
+ #endif
+ return res;
+}
+
+SZ_RESULT SzArchiveOpen2(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ Byte signature[k7zSignatureSize];
+ Byte version;
+ UInt32 crcFromArchive;
+ UInt64 nextHeaderOffset;
+ UInt64 nextHeaderSize;
+ UInt32 nextHeaderCRC;
+ UInt32 crc;
+ CFileSize pos = 0;
+ CSzByteBuffer buffer;
+ CSzData sd;
+ SZ_RESULT res;
+
+ RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize));
+
+ if (!TestSignatureCandidate(signature))
+ return SZE_ARCHIVE_ERROR;
+
+ /*
+ db.Clear();
+ db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+ */
+ RINOK(SafeReadDirectByte(inStream, &version));
+ if (version != k7zMajorVersion)
+ return SZE_ARCHIVE_ERROR;
+ RINOK(SafeReadDirectByte(inStream, &version));
+
+ RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive));
+
+ CrcInit(&crc);
+ RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset));
+ CrcUpdateUInt64(&crc, nextHeaderOffset);
+ RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize));
+ CrcUpdateUInt64(&crc, nextHeaderSize);
+ RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC));
+ CrcUpdateUInt32(&crc, nextHeaderCRC);
+
+ pos = k7zStartHeaderSize;
+ db->ArchiveInfo.StartPositionAfterHeader = pos;
+
+ if (CrcGetDigest(&crc) != crcFromArchive)
+ return SZE_ARCHIVE_ERROR;
+
+ if (nextHeaderSize == 0)
+ return SZ_OK;
+
+ RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset)));
+
+ if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc))
+ return SZE_OUTOFMEMORY;
+
+ res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
+ if (res == SZ_OK)
+ {
+ if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize))
+ {
+ while (1)
+ {
+ UInt64 type;
+ sd.Data = buffer.Items;
+ sd.Size = buffer.Capacity;
+ res = SzReadID(&sd, &type);
+ if (res != SZ_OK)
+ break;
+ if (type == k7zIdHeader)
+ {
+ res = SzReadHeader(&sd, db, allocMain, allocTemp);
+ break;
+ }
+ if (type != k7zIdEncodedHeader)
+ {
+ res = SZE_ARCHIVE_ERROR;
+ break;
+ }
+ {
+ CSzByteBuffer outBuffer;
+ res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer,
+ db->ArchiveInfo.StartPositionAfterHeader,
+ allocTemp);
+ if (res != SZ_OK)
+ {
+ SzByteBufferFree(&outBuffer, allocTemp->Free);
+ break;
+ }
+ SzByteBufferFree(&buffer, allocTemp->Free);
+ buffer.Items = outBuffer.Items;
+ buffer.Capacity = outBuffer.Capacity;
+ }
+ }
+ }
+ }
+ SzByteBufferFree(&buffer, allocTemp->Free);
+ return res;
+}
+
+SZ_RESULT SzArchiveOpen(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp);
+ if (res != SZ_OK)
+ SzArDbExFree(db, allocMain->Free);
+ return res;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.h
new file mode 100644
index 00000000..8ded0ecc
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zIn.h
@@ -0,0 +1,55 @@
+/* 7zIn.h */
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "7zHeader.h"
+#include "7zItem.h"
+#include "7zAlloc.h"
+
+typedef struct _CInArchiveInfo
+{
+ CFileSize StartPositionAfterHeader;
+ CFileSize DataStartPosition;
+}CInArchiveInfo;
+
+typedef struct _CArchiveDatabaseEx
+{
+ CArchiveDatabase Database;
+ CInArchiveInfo ArchiveInfo;
+ UInt32 *FolderStartPackStreamIndex;
+ CFileSize *PackStreamStartPositions;
+ UInt32 *FolderStartFileIndex;
+ UInt32 *FileIndexToFolderIndexMap;
+}CArchiveDatabaseEx;
+
+void SzArDbExInit(CArchiveDatabaseEx *db);
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
+CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex);
+
+typedef struct _ISzInStream
+{
+ #ifdef _LZMA_IN_CB
+ SZ_RESULT (*Read)(
+ void *object, /* pointer to ISzInStream itself */
+ void **buffer, /* out: pointer to buffer with data */
+ size_t maxRequiredSize, /* max required size to read */
+ size_t *processedSize); /* real processed size.
+ processedSize can be less than maxRequiredSize.
+ If processedSize == 0, then there are no more
+ bytes in stream. */
+ #else
+ SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
+ #endif
+ SZ_RESULT (*Seek)(void *object, CFileSize pos);
+} ISzInStream;
+
+
+int SzArchiveOpen(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.c
new file mode 100644
index 00000000..5f9a37f6
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.c
@@ -0,0 +1,133 @@
+/* 7zItem.c */
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+
+void SzCoderInfoInit(CCoderInfo *coder)
+{
+ SzByteBufferInit(&coder->Properties);
+}
+
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
+{
+ SzByteBufferFree(&coder->Properties, freeFunc);
+ SzCoderInfoInit(coder);
+}
+
+void SzFolderInit(CFolder *folder)
+{
+ folder->NumCoders = 0;
+ folder->Coders = 0;
+ folder->NumBindPairs = 0;
+ folder->BindPairs = 0;
+ folder->NumPackStreams = 0;
+ folder->PackStreams = 0;
+ folder->UnPackSizes = 0;
+ folder->UnPackCRCDefined = 0;
+ folder->UnPackCRC = 0;
+ folder->NumUnPackStreams = 0;
+}
+
+void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
+{
+ UInt32 i;
+ for (i = 0; i < folder->NumCoders; i++)
+ SzCoderInfoFree(&folder->Coders[i], freeFunc);
+ freeFunc(folder->Coders);
+ freeFunc(folder->BindPairs);
+ freeFunc(folder->PackStreams);
+ freeFunc(folder->UnPackSizes);
+ SzFolderInit(folder);
+}
+
+UInt32 SzFolderGetNumOutStreams(CFolder *folder)
+{
+ UInt32 result = 0;
+ UInt32 i;
+ for (i = 0; i < folder->NumCoders; i++)
+ result += folder->Coders[i].NumOutStreams;
+ return result;
+}
+
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
+{
+ UInt32 i;
+ for(i = 0; i < folder->NumBindPairs; i++)
+ if (folder->BindPairs[i].InIndex == inStreamIndex)
+ return i;
+ return -1;
+}
+
+
+int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
+{
+ UInt32 i;
+ for(i = 0; i < folder->NumBindPairs; i++)
+ if (folder->BindPairs[i].OutIndex == outStreamIndex)
+ return i;
+ return -1;
+}
+
+CFileSize SzFolderGetUnPackSize(CFolder *folder)
+{
+ int i = (int)SzFolderGetNumOutStreams(folder);
+ if (i == 0)
+ return 0;
+ for (i--; i >= 0; i--)
+ if (SzFolderFindBindPairForOutStream(folder, i) < 0)
+ return folder->UnPackSizes[i];
+ /* throw 1; */
+ return 0;
+}
+
+/*
+int FindPackStreamArrayIndex(int inStreamIndex) const
+{
+ for(int i = 0; i < PackStreams.Size(); i++)
+ if (PackStreams[i] == inStreamIndex)
+ return i;
+ return -1;
+}
+*/
+
+void SzFileInit(CFileItem *fileItem)
+{
+ fileItem->IsFileCRCDefined = 0;
+ fileItem->HasStream = 1;
+ fileItem->IsDirectory = 0;
+ fileItem->IsAnti = 0;
+ fileItem->Name = 0;
+}
+
+void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
+{
+ freeFunc(fileItem->Name);
+ SzFileInit(fileItem);
+}
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db)
+{
+ db->NumPackStreams = 0;
+ db->PackSizes = 0;
+ db->PackCRCsDefined = 0;
+ db->PackCRCs = 0;
+ db->NumFolders = 0;
+ db->Folders = 0;
+ db->NumFiles = 0;
+ db->Files = 0;
+}
+
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
+{
+ UInt32 i;
+ for (i = 0; i < db->NumFolders; i++)
+ SzFolderFree(&db->Folders[i], freeFunc);
+ for (i = 0; i < db->NumFiles; i++)
+ SzFileFree(&db->Files[i], freeFunc);
+ freeFunc(db->PackSizes);
+ freeFunc(db->PackCRCsDefined);
+ freeFunc(db->PackCRCs);
+ freeFunc(db->Folders);
+ freeFunc(db->Files);
+ SzArchiveDatabaseInit(db);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.h
new file mode 100644
index 00000000..e59b73f0
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zItem.h
@@ -0,0 +1,90 @@
+/* 7zItem.h */
+
+#ifndef __7Z_ITEM_H
+#define __7Z_ITEM_H
+
+#include "7zMethodID.h"
+#include "7zHeader.h"
+#include "7zBuffer.h"
+
+typedef struct _CCoderInfo
+{
+ UInt32 NumInStreams;
+ UInt32 NumOutStreams;
+ CMethodID MethodID;
+ CSzByteBuffer Properties;
+}CCoderInfo;
+
+void SzCoderInfoInit(CCoderInfo *coder);
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
+
+typedef struct _CBindPair
+{
+ UInt32 InIndex;
+ UInt32 OutIndex;
+}CBindPair;
+
+typedef struct _CFolder
+{
+ UInt32 NumCoders;
+ CCoderInfo *Coders;
+ UInt32 NumBindPairs;
+ CBindPair *BindPairs;
+ UInt32 NumPackStreams;
+ UInt32 *PackStreams;
+ CFileSize *UnPackSizes;
+ int UnPackCRCDefined;
+ UInt32 UnPackCRC;
+
+ UInt32 NumUnPackStreams;
+}CFolder;
+
+void SzFolderInit(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
+UInt32 SzFolderGetNumOutStreams(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+
+/* #define CArchiveFileTime UInt64 */
+
+typedef struct _CFileItem
+{
+ /*
+ CArchiveFileTime LastWriteTime;
+ CFileSize StartPos;
+ UInt32 Attributes;
+ */
+ CFileSize Size;
+ UInt32 FileCRC;
+ char *Name;
+
+ Byte IsFileCRCDefined;
+ Byte HasStream;
+ Byte IsDirectory;
+ Byte IsAnti;
+ /*
+ int AreAttributesDefined;
+ int IsLastWriteTimeDefined;
+ int IsStartPosDefined;
+ */
+}CFileItem;
+
+void SzFileInit(CFileItem *fileItem);
+
+typedef struct _CArchiveDatabase
+{
+ UInt32 NumPackStreams;
+ CFileSize *PackSizes;
+ Byte *PackCRCsDefined;
+ UInt32 *PackCRCs;
+ UInt32 NumFolders;
+ CFolder *Folders;
+ UInt32 NumFiles;
+ CFileItem *Files;
+}CArchiveDatabase;
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db);
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
+
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMain.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMain.c
new file mode 100644
index 00000000..6b496da9
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMain.c
@@ -0,0 +1,223 @@
+/*
+7zMain.c
+Test application for 7z Decoder
+LZMA SDK 4.26 Copyright (c) 1999-2005 Igor Pavlov (2005-08-02)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "7zCrc.h"
+#include "7zIn.h"
+#include "7zExtract.h"
+
+typedef struct _CFileInStream
+{
+ ISzInStream InStream;
+ FILE *File;
+} CFileInStream;
+
+#ifdef _LZMA_IN_CB
+
+#define kBufferSize (1 << 12)
+Byte g_Buffer[kBufferSize];
+
+SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
+{
+ CFileInStream *s = (CFileInStream *)object;
+ size_t processedSizeLoc;
+ if (maxRequiredSize > kBufferSize)
+ maxRequiredSize = kBufferSize;
+ processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File);
+ *buffer = g_Buffer;
+ if (processedSize != 0)
+ *processedSize = processedSizeLoc;
+ return SZ_OK;
+}
+
+#else
+
+SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
+{
+ CFileInStream *s = (CFileInStream *)object;
+ size_t processedSizeLoc = fread(buffer, 1, size, s->File);
+ if (processedSize != 0)
+ *processedSize = processedSizeLoc;
+ return SZ_OK;
+}
+
+#endif
+
+SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
+{
+ CFileInStream *s = (CFileInStream *)object;
+ int res = fseek(s->File, (long)pos, SEEK_SET);
+ if (res == 0)
+ return SZ_OK;
+ return SZE_FAIL;
+}
+
+void PrintError(char *sz)
+{
+ printf("\nERROR: %s\n", sz);
+}
+
+int main(int numargs, char *args[])
+{
+ CFileInStream archiveStream;
+ CArchiveDatabaseEx db;
+ SZ_RESULT res;
+ ISzAlloc allocImp;
+ ISzAlloc allocTempImp;
+
+ printf("\n7z ANSI-C Decoder 4.30 Copyright (c) 1999-2005 Igor Pavlov 2005-11-20\n");
+ if (numargs == 1)
+ {
+ printf(
+ "\nUsage: 7zDec <command> <archive_name>\n\n"
+ "<Commands>\n"
+ " e: Extract files from archive\n"
+ " l: List contents of archive\n"
+ " t: Test integrity of archive\n");
+ return 0;
+ }
+ if (numargs < 3)
+ {
+ PrintError("incorrect command");
+ return 1;
+ }
+
+ archiveStream.File = fopen(args[2], "rb");
+ if (archiveStream.File == 0)
+ {
+ PrintError("can not open input file");
+ return 1;
+ }
+
+ archiveStream.InStream.Read = SzFileReadImp;
+ archiveStream.InStream.Seek = SzFileSeekImp;
+
+ allocImp.Alloc = SzAlloc;
+ allocImp.Free = SzFree;
+
+ allocTempImp.Alloc = SzAllocTemp;
+ allocTempImp.Free = SzFreeTemp;
+
+ InitCrcTable();
+ SzArDbExInit(&db);
+ res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
+ if (res == SZ_OK)
+ {
+ char *command = args[1];
+ int listCommand = 0;
+ int testCommand = 0;
+ int extractCommand = 0;
+ if (strcmp(command, "l") == 0)
+ listCommand = 1;
+ if (strcmp(command, "t") == 0)
+ testCommand = 1;
+ else if (strcmp(command, "e") == 0)
+ extractCommand = 1;
+
+ if (listCommand)
+ {
+ UInt32 i;
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ CFileItem *f = db.Database.Files + i;
+ printf("%10d %s\n", (int)f->Size, f->Name);
+ }
+ }
+ else if (testCommand || extractCommand)
+ {
+ UInt32 i;
+
+ // if you need cache, use these 3 variables.
+ // if you use external function, you can make these variable as static.
+ UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0)
+ Byte *outBuffer = 0; // it must be 0 before first call for each new archive.
+ size_t outBufferSize = 0; // it can have any value before first call (if outBuffer = 0)
+
+ printf("\n");
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ size_t offset;
+ size_t outSizeProcessed;
+ CFileItem *f = db.Database.Files + i;
+ if (f->IsDirectory)
+ printf("Directory ");
+ else
+ printf(testCommand ?
+ "Testing ":
+ "Extracting");
+ printf(" %s", f->Name);
+ if (f->IsDirectory)
+ {
+ printf("\n");
+ continue;
+ }
+ res = SzExtract(&archiveStream.InStream, &db, i,
+ &blockIndex, &outBuffer, &outBufferSize,
+ &offset, &outSizeProcessed,
+ &allocImp, &allocTempImp);
+ if (res != SZ_OK)
+ break;
+ if (!testCommand)
+ {
+ FILE *outputHandle;
+ UInt32 processedSize;
+ char *fileName = f->Name;
+ size_t nameLen = strlen(f->Name);
+ for (; nameLen > 0; nameLen--)
+ if (f->Name[nameLen - 1] == '/')
+ {
+ fileName = f->Name + nameLen;
+ break;
+ }
+
+ outputHandle = fopen(fileName, "wb+");
+ if (outputHandle == 0)
+ {
+ PrintError("can not open output file");
+ res = SZE_FAIL;
+ break;
+ }
+ processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle);
+ if (processedSize != outSizeProcessed)
+ {
+ PrintError("can not write output file");
+ res = SZE_FAIL;
+ break;
+ }
+ if (fclose(outputHandle))
+ {
+ PrintError("can not close output file");
+ res = SZE_FAIL;
+ break;
+ }
+ }
+ printf("\n");
+ }
+ allocImp.Free(outBuffer);
+ }
+ else
+ {
+ PrintError("incorrect command");
+ res = SZE_FAIL;
+ }
+ }
+ SzArDbExFree(&db, allocImp.Free);
+
+ fclose(archiveStream.File);
+ if (res == SZ_OK)
+ {
+ printf("\nEverything is Ok\n");
+ return 0;
+ }
+ if (res == SZE_OUTOFMEMORY)
+ PrintError("can not allocate memory");
+ else
+ printf("\nERROR #%d\n", res);
+ return 1;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.c
new file mode 100644
index 00000000..9daf39c2
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.c
@@ -0,0 +1,14 @@
+/* 7zMethodID.c */
+
+#include "7zMethodID.h"
+
+int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
+{
+ int i;
+ if (a1->IDSize != a2->IDSize)
+ return 0;
+ for (i = 0; i < a1->IDSize; i++)
+ if (a1->ID[i] != a2->ID[i])
+ return 0;
+ return 1;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.h
new file mode 100644
index 00000000..4d886899
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zMethodID.h
@@ -0,0 +1,18 @@
+/* 7zMethodID.h */
+
+#ifndef __7Z_METHOD_ID_H
+#define __7Z_METHOD_ID_H
+
+#include "7zTypes.h"
+
+#define kMethodIDSize 15
+
+typedef struct _CMethodID
+{
+ Byte ID[kMethodIDSize];
+ Byte IDSize;
+} CMethodID;
+
+int AreMethodsEqual(CMethodID *a1, CMethodID *a2);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zTypes.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zTypes.h
new file mode 100644
index 00000000..28adc729
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7zTypes.h
@@ -0,0 +1,61 @@
+/* 7zTypes.h */
+
+#ifndef __COMMON_TYPES_H
+#define __COMMON_TYPES_H
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#ifndef UInt16
+#define UInt16 unsigned short
+#endif
+
+/* #define _SZ_NO_INT_64 */
+/* define it your compiler doesn't support long long int */
+
+#ifdef _SZ_NO_INT_64
+#define UInt64 unsigned long
+#else
+#ifdef _MSC_VER
+#define UInt64 unsigned __int64
+#else
+#define UInt64 unsigned long long int
+#endif
+#endif
+
+
+/* #define _SZ_FILE_SIZE_64 */
+/* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/
+
+#ifndef CFileSize
+#ifdef _SZ_FILE_SIZE_64
+#define CFileSize UInt64
+#else
+#define CFileSize UInt32
+#endif
+#endif
+
+#define SZ_RESULT int
+
+#define SZ_OK (0)
+#define SZE_DATA_ERROR (1)
+#define SZE_OUTOFMEMORY (2)
+#define SZE_CRC_ERROR (3)
+
+#define SZE_NOTIMPL (4)
+#define SZE_FAIL (5)
+
+#define SZE_ARCHIVE_ERROR (6)
+
+#define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; }
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsp
new file mode 100644
index 00000000..d83b30e3
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsp
@@ -0,0 +1,178 @@
+# Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=7z_C - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "7z_C.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "7z_C - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe"
+
+!ELSEIF "$(CFG)" == "7z_C - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "7z_C - Win32 Release"
+# Name "7z_C - Win32 Debug"
+# Begin Group "LZMA"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA_C\LzmaDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA_C\LzmaDecode.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7zAlloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zAlloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zCrc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zTypes.h
+# End Source File
+# End Target
+# End Project
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsw b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsw
new file mode 100644
index 00000000..f1ee72bf
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/7z_C.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "7z_C"=.\7z_C.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile
new file mode 100644
index 00000000..eafbd057
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile
@@ -0,0 +1,55 @@
+PROG = 7zDec.exe
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS-
+CFLAGS_O1 = $(CFLAGS) -O1
+CFLAGS_O2 = $(CFLAGS) -O2
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
+COMPL = $(CPP) $(CFLAGS_O1) $**
+
+
+7Z_OBJS = \
+ $O\7zAlloc.obj \
+ $O\7zBuffer.obj \
+ $O\7zCrc.obj \
+ $O\7zDecode.obj \
+ $O\7zExtract.obj \
+ $O\7zHeader.obj \
+ $O\7zIn.obj \
+ $O\7zItem.obj \
+ $O\7zMain.obj \
+ $O\7zMethodID.obj \
+
+OBJS = \
+ $(7Z_OBJS) \
+ $O\LzmaDecode.obj \
+
+all: $(PROGPATH)
+
+clean:
+ -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
+
+$O:
+ if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS)
+ link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+
+
+$(7Z_OBJS): $(*B).c
+ $(COMPL)
+$O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c
+ $(COMPL_O2)
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile.gcc b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile.gcc
new file mode 100644
index 00000000..cc8bebf7
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Archive/7z_C/makefile.gcc
@@ -0,0 +1,50 @@
+PROG = 7zDec
+CXX = g++
+LIB =
+RM = rm -f
+CFLAGS = -c -O2 -Wall
+
+OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
+
+7zAlloc.o: 7zAlloc.c
+ $(CXX) $(CFLAGS) 7zAlloc.c
+
+7zBuffer.o: 7zBuffer.c
+ $(CXX) $(CFLAGS) 7zBuffer.c
+
+7zCrc.o: 7zCrc.c
+ $(CXX) $(CFLAGS) 7zCrc.c
+
+7zDecode.o: 7zDecode.c
+ $(CXX) $(CFLAGS) 7zDecode.c
+
+7zExtract.o: 7zExtract.c
+ $(CXX) $(CFLAGS) 7zExtract.c
+
+7zHeader.o: 7zHeader.c
+ $(CXX) $(CFLAGS) 7zHeader.c
+
+7zIn.o: 7zIn.c
+ $(CXX) $(CFLAGS) 7zIn.c
+
+7zItem.o: 7zItem.c
+ $(CXX) $(CFLAGS) 7zItem.c
+
+7zMain.o: 7zMain.c
+ $(CXX) $(CFLAGS) 7zMain.c
+
+7zMethodID.o: 7zMethodID.c
+ $(CXX) $(CFLAGS) 7zMethodID.c
+
+LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c
+ $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c
+
+
+clean:
+ -$(RM) $(PROG) $(OBJS)
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.cpp
new file mode 100644
index 00000000..7a32c6e7
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.cpp
@@ -0,0 +1,251 @@
+// FileStreams.cpp
+
+#include "StdAfx.h"
+
+#ifndef _WIN32
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#include "FileStreams.h"
+
+static inline HRESULT ConvertBoolToHRESULT(bool result)
+{
+ // return result ? S_OK: E_FAIL;
+ #ifdef _WIN32
+ return result ? S_OK: (::GetLastError());
+ #else
+ return result ? S_OK: E_FAIL;
+ #endif
+}
+
+bool CInFileStream::Open(LPCTSTR fileName)
+{
+ return File.Open(fileName);
+}
+
+#ifdef _WIN32
+#ifndef _UNICODE
+bool CInFileStream::Open(LPCWSTR fileName)
+{
+ return File.Open(fileName);
+}
+#endif
+#endif
+
+STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ #ifdef _WIN32
+
+ UInt32 realProcessedSize;
+ bool result = File.ReadPart(data, size, realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return ConvertBoolToHRESULT(result);
+
+ #else
+
+ if(processedSize != NULL)
+ *processedSize = 0;
+ ssize_t res = File.Read(data, (size_t)size);
+ if (res == -1)
+ return E_FAIL;
+ if(processedSize != NULL)
+ *processedSize = (UInt32)res;
+ return S_OK;
+
+ #endif
+}
+
+#ifndef _WIN32_WCE
+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ #ifdef _WIN32
+ UInt32 realProcessedSize;
+ BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE),
+ data, size, (DWORD *)&realProcessedSize, NULL);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
+ return S_OK;
+ return ConvertBoolToHRESULT(res != FALSE);
+
+ #else
+
+ if(processedSize != NULL)
+ *processedSize = 0;
+ ssize_t res;
+ do
+ {
+ res = read(0, data, (size_t)size);
+ }
+ while (res < 0 && (errno == EINTR));
+ if (res == -1)
+ return E_FAIL;
+ if(processedSize != NULL)
+ *processedSize = (UInt32)res;
+ return S_OK;
+
+ #endif
+}
+
+#endif
+
+STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,
+ UInt64 *newPosition)
+{
+ if(seekOrigin >= 3)
+ return STG_E_INVALIDFUNCTION;
+
+ #ifdef _WIN32
+
+ UInt64 realNewPosition;
+ bool result = File.Seek(offset, seekOrigin, realNewPosition);
+ if(newPosition != NULL)
+ *newPosition = realNewPosition;
+ return ConvertBoolToHRESULT(result);
+
+ #else
+
+ off_t res = File.Seek(offset, seekOrigin);
+ if (res == -1)
+ return E_FAIL;
+ if(newPosition != NULL)
+ *newPosition = (UInt64)res;
+ return S_OK;
+
+ #endif
+}
+
+STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
+{
+ return ConvertBoolToHRESULT(File.GetLength(*size));
+}
+
+
+//////////////////////////
+// COutFileStream
+
+bool COutFileStream::Create(LPCTSTR fileName, bool createAlways)
+{
+ return File.Create(fileName, createAlways);
+}
+
+#ifdef _WIN32
+#ifndef _UNICODE
+bool COutFileStream::Create(LPCWSTR fileName, bool createAlways)
+{
+ return File.Create(fileName, createAlways);
+}
+#endif
+#endif
+
+STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ #ifdef _WIN32
+
+ UInt32 realProcessedSize;
+ bool result = File.WritePart(data, size, realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return ConvertBoolToHRESULT(result);
+
+ #else
+
+ if(processedSize != NULL)
+ *processedSize = 0;
+ ssize_t res = File.Write(data, (size_t)size);
+ if (res == -1)
+ return E_FAIL;
+ if(processedSize != NULL)
+ *processedSize = (UInt32)res;
+ return S_OK;
+
+ #endif
+}
+
+STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin,
+ UInt64 *newPosition)
+{
+ if(seekOrigin >= 3)
+ return STG_E_INVALIDFUNCTION;
+ #ifdef _WIN32
+
+ UInt64 realNewPosition;
+ bool result = File.Seek(offset, seekOrigin, realNewPosition);
+ if(newPosition != NULL)
+ *newPosition = realNewPosition;
+ return ConvertBoolToHRESULT(result);
+
+ #else
+
+ off_t res = File.Seek(offset, seekOrigin);
+ if (res == -1)
+ return E_FAIL;
+ if(newPosition != NULL)
+ *newPosition = (UInt64)res;
+ return S_OK;
+
+ #endif
+}
+
+STDMETHODIMP COutFileStream::SetSize(Int64 newSize)
+{
+ #ifdef _WIN32
+ UInt64 currentPos;
+ if(!File.Seek(0, FILE_CURRENT, currentPos))
+ return E_FAIL;
+ bool result = File.SetLength(newSize);
+ UInt64 currentPos2;
+ result = result && File.Seek(currentPos, currentPos2);
+ return result ? S_OK : E_FAIL;
+ #else
+ return E_FAIL;
+ #endif
+}
+
+#ifndef _WIN32_WCE
+STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if(processedSize != NULL)
+ *processedSize = 0;
+
+ #ifdef _WIN32
+ UInt32 realProcessedSize;
+ BOOL res = TRUE;
+ if (size > 0)
+ {
+ // Seems that Windows doesn't like big amounts writing to stdout.
+ // So we limit portions by 32KB.
+ UInt32 sizeTemp = (1 << 15);
+ if (sizeTemp > size)
+ sizeTemp = size;
+ res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
+ data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
+ size -= realProcessedSize;
+ data = (const void *)((const Byte *)data + realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize += realProcessedSize;
+ }
+ return ConvertBoolToHRESULT(res != FALSE);
+
+ #else
+
+ ssize_t res;
+ do
+ {
+ res = write(1, data, (size_t)size);
+ }
+ while (res < 0 && (errno == EINTR));
+ if (res == -1)
+ return E_FAIL;
+ if(processedSize != NULL)
+ *processedSize = (UInt32)res;
+ return S_OK;
+
+ return S_OK;
+ #endif
+}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.h
new file mode 100644
index 00000000..e6494f67
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/FileStreams.h
@@ -0,0 +1,98 @@
+// FileStreams.h
+
+#ifndef __FILESTREAMS_H
+#define __FILESTREAMS_H
+
+#ifdef _WIN32
+#include "../../Windows/FileIO.h"
+#else
+#include "../../Common/C_FileIO.h"
+#endif
+
+#include "../IStream.h"
+#include "../../Common/MyCom.h"
+
+class CInFileStream:
+ public IInStream,
+ public IStreamGetSize,
+ public CMyUnknownImp
+{
+public:
+ #ifdef _WIN32
+ NWindows::NFile::NIO::CInFile File;
+ #else
+ NC::NFile::NIO::CInFile File;
+ #endif
+ CInFileStream() {}
+ virtual ~CInFileStream() {}
+
+ bool Open(LPCTSTR fileName);
+ #ifdef _WIN32
+ #ifndef _UNICODE
+ bool Open(LPCWSTR fileName);
+ #endif
+ #endif
+
+ MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ STDMETHOD(GetSize)(UInt64 *size);
+};
+
+#ifndef _WIN32_WCE
+class CStdInFileStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ // HANDLE File;
+ // CStdInFileStream() File(INVALID_HANDLE_VALUE): {}
+ // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); };
+ MY_UNKNOWN_IMP
+
+ virtual ~CStdInFileStream() {}
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+#endif
+
+class COutFileStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+public:
+ #ifdef _WIN32
+ NWindows::NFile::NIO::COutFile File;
+ #else
+ NC::NFile::NIO::COutFile File;
+ #endif
+ virtual ~COutFileStream() {}
+ bool Create(LPCTSTR fileName, bool createAlways);
+ #ifdef _WIN32
+ #ifndef _UNICODE
+ bool Create(LPCWSTR fileName, bool createAlways);
+ #endif
+ #endif
+
+ MY_UNKNOWN_IMP1(IOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ STDMETHOD(SetSize)(Int64 newSize);
+};
+
+#ifndef _WIN32_WCE
+class CStdOutFileStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ virtual ~CStdOutFileStream() {}
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+#endif
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.cpp
new file mode 100644
index 00000000..17280b5b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.cpp
@@ -0,0 +1,80 @@
+// InBuffer.cpp
+
+#include "StdAfx.h"
+
+#include "InBuffer.h"
+
+#include "../../Common/Alloc.h"
+
+CInBuffer::CInBuffer():
+ _buffer(0),
+ _bufferLimit(0),
+ _bufferBase(0),
+ _stream(0),
+ _bufferSize(0)
+{}
+
+bool CInBuffer::Create(UInt32 bufferSize)
+{
+ const UInt32 kMinBlockSize = 1;
+ if (bufferSize < kMinBlockSize)
+ bufferSize = kMinBlockSize;
+ if (_bufferBase != 0 && _bufferSize == bufferSize)
+ return true;
+ Free();
+ _bufferSize = bufferSize;
+ _bufferBase = (Byte *)::MidAlloc(bufferSize);
+ return (_bufferBase != 0);
+}
+
+void CInBuffer::Free()
+{
+ ::MidFree(_bufferBase);
+ _bufferBase = 0;
+}
+
+void CInBuffer::SetStream(ISequentialInStream *stream)
+{
+ _stream = stream;
+}
+
+void CInBuffer::Init()
+{
+ _processedSize = 0;
+ _buffer = _bufferBase;
+ _bufferLimit = _buffer;
+ _wasFinished = false;
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = S_OK;
+ #endif
+}
+
+bool CInBuffer::ReadBlock()
+{
+ #ifdef _NO_EXCEPTIONS
+ if (ErrorCode != S_OK)
+ return false;
+ #endif
+ if (_wasFinished)
+ return false;
+ _processedSize += (_buffer - _bufferBase);
+ UInt32 numProcessedBytes;
+ HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes);
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = result;
+ #else
+ if (result != S_OK)
+ throw CInBufferException(result);
+ #endif
+ _buffer = _bufferBase;
+ _bufferLimit = _buffer + numProcessedBytes;
+ _wasFinished = (numProcessedBytes == 0);
+ return (!_wasFinished);
+}
+
+Byte CInBuffer::ReadBlock2()
+{
+ if(!ReadBlock())
+ return 0xFF;
+ return *_buffer++;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.h
new file mode 100644
index 00000000..a59ecefa
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/InBuffer.h
@@ -0,0 +1,76 @@
+// InBuffer.h
+
+#ifndef __INBUFFER_H
+#define __INBUFFER_H
+
+#include "../IStream.h"
+#include "../../Common/MyCom.h"
+
+#ifndef _NO_EXCEPTIONS
+class CInBufferException
+{
+public:
+ HRESULT ErrorCode;
+ CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {}
+};
+#endif
+
+class CInBuffer
+{
+ Byte *_buffer;
+ Byte *_bufferLimit;
+ Byte *_bufferBase;
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _processedSize;
+ UInt32 _bufferSize;
+ bool _wasFinished;
+
+ bool ReadBlock();
+ Byte ReadBlock2();
+
+public:
+ #ifdef _NO_EXCEPTIONS
+ HRESULT ErrorCode;
+ #endif
+
+ CInBuffer();
+ ~CInBuffer() { Free(); }
+
+ bool Create(UInt32 bufferSize);
+ void Free();
+
+ void SetStream(ISequentialInStream *stream);
+ void Init();
+ void ReleaseStream() { _stream.Release(); }
+
+ bool ReadByte(Byte &b)
+ {
+ if(_buffer >= _bufferLimit)
+ if(!ReadBlock())
+ return false;
+ b = *_buffer++;
+ return true;
+ }
+ Byte ReadByte()
+ {
+ if(_buffer >= _bufferLimit)
+ return ReadBlock2();
+ return *_buffer++;
+ }
+ void ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+ {
+ for(processedSize = 0; processedSize < size; processedSize++)
+ if (!ReadByte(((Byte *)data)[processedSize]))
+ return;
+ }
+ bool ReadBytes(void *data, UInt32 size)
+ {
+ UInt32 processedSize;
+ ReadBytes(data, size, processedSize);
+ return (processedSize == size);
+ }
+ UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }
+ bool WasFinished() const { return _wasFinished; }
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.cpp
new file mode 100644
index 00000000..e76e6f4d
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.cpp
@@ -0,0 +1,117 @@
+// OutByte.cpp
+
+#include "StdAfx.h"
+
+#include "OutBuffer.h"
+
+#include "../../Common/Alloc.h"
+
+bool COutBuffer::Create(UInt32 bufferSize)
+{
+ const UInt32 kMinBlockSize = 1;
+ if (bufferSize < kMinBlockSize)
+ bufferSize = kMinBlockSize;
+ if (_buffer != 0 && _bufferSize == bufferSize)
+ return true;
+ Free();
+ _bufferSize = bufferSize;
+ _buffer = (Byte *)::MidAlloc(bufferSize);
+ return (_buffer != 0);
+}
+
+void COutBuffer::Free()
+{
+ ::MidFree(_buffer);
+ _buffer = 0;
+}
+
+void COutBuffer::SetStream(ISequentialOutStream *stream)
+{
+ _stream = stream;
+}
+
+void COutBuffer::Init()
+{
+ _streamPos = 0;
+ _limitPos = _bufferSize;
+ _pos = 0;
+ _processedSize = 0;
+ _overDict = false;
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = S_OK;
+ #endif
+}
+
+UInt64 COutBuffer::GetProcessedSize() const
+{
+ UInt64 res = _processedSize + _pos - _streamPos;
+ if (_streamPos > _pos)
+ res += _bufferSize;
+ return res;
+}
+
+
+HRESULT COutBuffer::FlushPart()
+{
+ // _streamPos < _bufferSize
+ UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);
+ HRESULT result = S_OK;
+ #ifdef _NO_EXCEPTIONS
+ if (ErrorCode != S_OK)
+ result = ErrorCode;
+ #endif
+ if (_buffer2 != 0)
+ {
+ memmove(_buffer2, _buffer + _streamPos, size);
+ _buffer2 += size;
+ }
+
+ if (_stream != 0
+ #ifdef _NO_EXCEPTIONS
+ && (ErrorCode != S_OK)
+ #endif
+ )
+ {
+ UInt32 processedSize = 0;
+ result = _stream->Write(_buffer + _streamPos, size, &processedSize);
+ size = processedSize;
+ }
+ _streamPos += size;
+ if (_streamPos == _bufferSize)
+ _streamPos = 0;
+ if (_pos == _bufferSize)
+ {
+ _overDict = true;
+ _pos = 0;
+ }
+ _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;
+ _processedSize += size;
+ return result;
+}
+
+HRESULT COutBuffer::Flush()
+{
+ #ifdef _NO_EXCEPTIONS
+ if (ErrorCode != S_OK)
+ return ErrorCode;
+ #endif
+
+ while(_streamPos != _pos)
+ {
+ HRESULT result = FlushPart();
+ if (result != S_OK)
+ return result;
+ }
+ return S_OK;
+}
+
+void COutBuffer::FlushWithCheck()
+{
+ HRESULT result = FlushPart();
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = result;
+ #else
+ if (result != S_OK)
+ throw COutBufferException(result);
+ #endif
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.h
new file mode 100644
index 00000000..37eefbdf
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/OutBuffer.h
@@ -0,0 +1,64 @@
+// OutBuffer.h
+
+#ifndef __OUTBUFFER_H
+#define __OUTBUFFER_H
+
+#include "../IStream.h"
+#include "../../Common/MyCom.h"
+
+#ifndef _NO_EXCEPTIONS
+struct COutBufferException
+{
+ HRESULT ErrorCode;
+ COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {}
+};
+#endif
+
+class COutBuffer
+{
+protected:
+ Byte *_buffer;
+ UInt32 _pos;
+ UInt32 _limitPos;
+ UInt32 _streamPos;
+ UInt32 _bufferSize;
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _processedSize;
+ Byte *_buffer2;
+ bool _overDict;
+
+ HRESULT FlushPart();
+ void FlushWithCheck();
+public:
+ #ifdef _NO_EXCEPTIONS
+ HRESULT ErrorCode;
+ #endif
+
+ COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}
+ ~COutBuffer() { Free(); }
+
+ bool Create(UInt32 bufferSize);
+ void Free();
+
+ void SetMemStream(Byte *buffer) { _buffer2 = buffer; }
+ void SetStream(ISequentialOutStream *stream);
+ void Init();
+ HRESULT Flush();
+ void ReleaseStream() { _stream.Release(); }
+
+ void WriteByte(Byte b)
+ {
+ _buffer[_pos++] = b;
+ if(_pos == _limitPos)
+ FlushWithCheck();
+ }
+ void WriteBytes(const void *data, size_t size)
+ {
+ for (size_t i = 0; i < size; i++)
+ WriteByte(((const Byte *)data)[i]);
+ }
+
+ UInt64 GetProcessedSize() const;
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StdAfx.h
new file mode 100644
index 00000000..d7d9211b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../Common/MyWindows.h"
+#include "../../Common/NewHandler.h"
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.cpp
new file mode 100644
index 00000000..712a7858
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.cpp
@@ -0,0 +1,44 @@
+// StreamUtils.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyCom.h"
+#include "StreamUtils.h"
+
+HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize != 0)
+ *processedSize = 0;
+ while(size != 0)
+ {
+ UInt32 processedSizeLoc;
+ HRESULT res = stream->Read(data, size, &processedSizeLoc);
+ if (processedSize != 0)
+ *processedSize += processedSizeLoc;
+ data = (Byte *)((Byte *)data + processedSizeLoc);
+ size -= processedSizeLoc;
+ RINOK(res);
+ if (processedSizeLoc == 0)
+ return S_OK;
+ }
+ return S_OK;
+}
+
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize != 0)
+ *processedSize = 0;
+ while(size != 0)
+ {
+ UInt32 processedSizeLoc;
+ HRESULT res = stream->Write(data, size, &processedSizeLoc);
+ if (processedSize != 0)
+ *processedSize += processedSizeLoc;
+ data = (const void *)((const Byte *)data + processedSizeLoc);
+ size -= processedSizeLoc;
+ RINOK(res);
+ if (processedSizeLoc == 0)
+ break;
+ }
+ return S_OK;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.h
new file mode 100644
index 00000000..c8cd8cef
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Common/StreamUtils.h
@@ -0,0 +1,11 @@
+// StreamUtils.h
+
+#ifndef __STREAMUTILS_H
+#define __STREAMUTILS_H
+
+#include "../IStream.h"
+
+HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize);
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.cpp
new file mode 100644
index 00000000..1a52ea9e
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.cpp
@@ -0,0 +1,16 @@
+// ARM.cpp
+
+#include "StdAfx.h"
+#include "ARM.h"
+
+#include "BranchARM.c"
+
+UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::ARM_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::ARM_Convert(data, size, _bufferPos, 0);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.h
new file mode 100644
index 00000000..83c91e31
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARM.h
@@ -0,0 +1,10 @@
+// ARM.h
+
+#ifndef __ARM_H
+#define __ARM_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_ARM, 0x05, 1)
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.cpp
new file mode 100644
index 00000000..83f5d9b8
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.cpp
@@ -0,0 +1,16 @@
+// ARMThumb.cpp
+
+#include "StdAfx.h"
+#include "ARMThumb.h"
+
+#include "BranchARMThumb.c"
+
+UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::ARMThumb_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::ARMThumb_Convert(data, size, _bufferPos, 0);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.h
new file mode 100644
index 00000000..f59c737b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/ARMThumb.h
@@ -0,0 +1,10 @@
+// ARMThumb.h
+
+#ifndef __ARMTHUMB_H
+#define __ARMTHUMB_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_ARMThumb, 0x07, 1)
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.c
new file mode 100644
index 00000000..53680ef4
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.c
@@ -0,0 +1,26 @@
+// BranchARM.c
+
+#include "BranchARM.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ if (data[i + 3] == 0xEB)
+ {
+ UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
+ src <<= 2;
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + 8 + src;
+ else
+ dest = src - (nowPos + i + 8);
+ dest >>= 2;
+ data[i + 2] = (dest >> 16);
+ data[i + 1] = (dest >> 8);
+ data[i + 0] = dest;
+ }
+ }
+ return i;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.h
new file mode 100644
index 00000000..63e55dc8
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARM.h
@@ -0,0 +1,10 @@
+// BranchARM.h
+
+#ifndef __BRANCH_ARM_H
+#define __BRANCH_ARM_H
+
+#include "Common/Types.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.c
new file mode 100644
index 00000000..6d0f5ba1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.c
@@ -0,0 +1,35 @@
+// BranchARMThumb.c
+
+#include "BranchARMThumb.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 2)
+ {
+ if ((data[i + 1] & 0xF8) == 0xF0 &&
+ (data[i + 3] & 0xF8) == 0xF8)
+ {
+ UInt32 src =
+ ((data[i + 1] & 0x7) << 19) |
+ (data[i + 0] << 11) |
+ ((data[i + 3] & 0x7) << 8) |
+ (data[i + 2]);
+
+ src <<= 1;
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + 4 + src;
+ else
+ dest = src - (nowPos + i + 4);
+ dest >>= 1;
+
+ data[i + 1] = 0xF0 | ((dest >> 19) & 0x7);
+ data[i + 0] = (dest >> 11);
+ data[i + 3] = 0xF8 | ((dest >> 8) & 0x7);
+ data[i + 2] = (dest);
+ i += 2;
+ }
+ }
+ return i;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.h
new file mode 100644
index 00000000..032d94da
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchARMThumb.h
@@ -0,0 +1,10 @@
+// BranchARMThumb.h
+
+#ifndef __BRANCH_ARM_THUMB_H
+#define __BRANCH_ARM_THUMB_H
+
+#include "Common/Types.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.cpp
new file mode 100644
index 00000000..68e938bd
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.cpp
@@ -0,0 +1,18 @@
+// BranchCoder.cpp
+
+#include "StdAfx.h"
+#include "BranchCoder.h"
+
+STDMETHODIMP CBranchConverter::Init()
+{
+ _bufferPos = 0;
+ SubInit();
+ return S_OK;
+}
+
+STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size)
+{
+ UInt32 processedSize = SubFilter(data, size);
+ _bufferPos += processedSize;
+ return processedSize;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.h
new file mode 100644
index 00000000..b64562df
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchCoder.h
@@ -0,0 +1,54 @@
+// BranchCoder.h
+
+#ifndef __BRANCH_CODER_H
+#define __BRANCH_CODER_H
+
+#include "Common/MyCom.h"
+#include "Common/Types.h"
+#include "Common/Alloc.h"
+
+#include "../../ICoder.h"
+
+class CBranchConverter:
+ public ICompressFilter,
+ public CMyUnknownImp
+{
+protected:
+ UInt32 _bufferPos;
+ virtual void SubInit() {}
+ virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0;
+public:
+ MY_UNKNOWN_IMP;
+ STDMETHOD(Init)();
+ STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+};
+
+#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \
+ { public: UInt32 SubFilter(Byte *data, UInt32 size); };
+
+#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \
+ { public: UInt32 SubFilter(Byte *data, UInt32 size); };
+
+#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
+ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};
+
+#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
+ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};
+
+#define MyClass2b(Name, id, subId, encodingId) \
+DEFINE_GUID(CLSID_CCompressConvert ## Name, \
+0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00);
+
+#define MyClassA(Name, id, subId) \
+MyClass2b(Name ## _Encoder, id, subId, 0x01) \
+MyClassEncoderA(Name ## _Encoder) \
+MyClass2b(Name ## _Decoder, id, subId, 0x00) \
+MyClassDecoderA(Name ## _Decoder)
+
+#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \
+MyClass2b(Name ## _Encoder, id, subId, 0x01) \
+MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \
+MyClass2b(Name ## _Decoder, id, subId, 0x00) \
+MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT)
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.c
new file mode 100644
index 00000000..8571aac1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.c
@@ -0,0 +1,65 @@
+// BranchIA64.c
+
+#include "BranchIA64.h"
+
+const Byte kBranchTable[32] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 6, 6, 0, 0, 7, 7,
+ 4, 4, 0, 0, 4, 4, 0, 0
+};
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 16 <= size; i += 16)
+ {
+ UInt32 instrTemplate = data[i] & 0x1F;
+ UInt32 mask = kBranchTable[instrTemplate];
+ UInt32 bitPos = 5;
+ for (int slot = 0; slot < 3; slot++, bitPos += 41)
+ {
+ if (((mask >> slot) & 1) == 0)
+ continue;
+ UInt32 bytePos = (bitPos >> 3);
+ UInt32 bitRes = bitPos & 0x7;
+ // UInt64 instruction = *(UInt64 *)(data + i + bytePos);
+ UInt64 instruction = 0;
+ int j;
+ for (j = 0; j < 6; j++)
+ instruction += (UInt64)(data[i + j + bytePos]) << (8 * j);
+
+ UInt64 instNorm = instruction >> bitRes;
+ if (((instNorm >> 37) & 0xF) == 0x5
+ && ((instNorm >> 9) & 0x7) == 0
+ // && (instNorm & 0x3F)== 0
+ )
+ {
+ UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF);
+ src |= ((instNorm >> 36) & 1) << 20;
+
+ src <<= 4;
+
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+
+ dest >>= 4;
+
+ instNorm &= ~(UInt64(0x8FFFFF) << 13);
+ instNorm |= (UInt64(dest & 0xFFFFF) << 13);
+ instNorm |= (UInt64(dest & 0x100000) << (36 - 20));
+
+ instruction &= (1 << bitRes) - 1;
+ instruction |= (instNorm << bitRes);
+ // *(UInt64 *)(data + i + bytePos) = instruction;
+ for (j = 0; j < 6; j++)
+ data[i + j + bytePos] = Byte(instruction >> (8 * j));
+ }
+ }
+ }
+ return i;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.h
new file mode 100644
index 00000000..2e96c137
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchIA64.h
@@ -0,0 +1,10 @@
+// BranchIA64.h
+
+#ifndef __BRANCH_IA64_H
+#define __BRANCH_IA64_H
+
+#include "Common/Types.h"
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.c
new file mode 100644
index 00000000..407bae61
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.c
@@ -0,0 +1,36 @@
+// BranchPPC.c
+
+#include "BranchPPC.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ // PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
+ if ((data[i] >> 2) == 0x12 &&
+ (
+ (data[i + 3] & 3) == 1
+ // || (data[i+3] & 3) == 3
+ )
+ )
+ {
+ UInt32 src = ((data[i + 0] & 3) << 24) |
+ (data[i + 1] << 16) |
+ (data[i + 2] << 8) |
+ (data[i + 3] & (~3));
+
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+ data[i + 0] = 0x48 | ((dest >> 24) & 0x3);
+ data[i + 1] = (dest >> 16);
+ data[i + 2] = (dest >> 8);
+ data[i + 3] &= 0x3;
+ data[i + 3] |= dest;
+ }
+ }
+ return i;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.h
new file mode 100644
index 00000000..405efbb1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchPPC.h
@@ -0,0 +1,10 @@
+// BranchPPC.h
+
+#ifndef __BRANCH_PPC_H
+#define __BRANCH_PPC_H
+
+#include "Common/Types.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.c
new file mode 100644
index 00000000..abbf1d75
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.c
@@ -0,0 +1,36 @@
+// BranchSPARC.c
+
+#include "BranchSPARC.h"
+
+UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 ||
+ data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)
+ {
+ UInt32 src =
+ ((UInt32)data[i + 0] << 24) |
+ ((UInt32)data[i + 1] << 16) |
+ ((UInt32)data[i + 2] << 8) |
+ ((UInt32)data[i + 3]);
+
+ src <<= 2;
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+ dest >>= 2;
+
+ dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
+
+ data[i + 0] = (Byte)(dest >> 24);
+ data[i + 1] = (Byte)(dest >> 16);
+ data[i + 2] = (Byte)(dest >> 8);
+ data[i + 3] = (Byte)dest;
+ }
+ }
+ return i;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.h
new file mode 100644
index 00000000..431bac58
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchSPARC.h
@@ -0,0 +1,10 @@
+// BranchSPARC.h
+
+#ifndef __BRANCH_SPARC_H
+#define __BRANCH_SPARC_H
+
+#include "Common/Types.h"
+
+UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.c
new file mode 100644
index 00000000..2d2c03d2
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.c
@@ -0,0 +1,101 @@
+/* BranchX86.c */
+
+#include "BranchX86.h"
+
+/*
+static int inline Test86MSByte(Byte b)
+{
+ return (b == 0 || b == 0xFF);
+}
+*/
+#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
+
+const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
+const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
+
+/*
+void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos)
+{
+ *prevMask = 0;
+ *prevPos = (UInt32)(-5);
+}
+*/
+
+UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos,
+ UInt32 *prevMask, UInt32 *prevPos, int encoding)
+{
+ UInt32 bufferPos = 0;
+ UInt32 limit;
+
+ if (endPos < 5)
+ return 0;
+
+ if (nowPos - *prevPos > 5)
+ *prevPos = nowPos - 5;
+
+ limit = endPos - 5;
+ while(bufferPos <= limit)
+ {
+ Byte b = buffer[bufferPos];
+ UInt32 offset;
+ if (b != 0xE8 && b != 0xE9)
+ {
+ bufferPos++;
+ continue;
+ }
+ offset = (nowPos + bufferPos - *prevPos);
+ *prevPos = (nowPos + bufferPos);
+ if (offset > 5)
+ *prevMask = 0;
+ else
+ {
+ UInt32 i;
+ for (i = 0; i < offset; i++)
+ {
+ *prevMask &= 0x77;
+ *prevMask <<= 1;
+ }
+ }
+ b = buffer[bufferPos + 4];
+ if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] &&
+ (*prevMask >> 1) < 0x10)
+ {
+ UInt32 src =
+ ((UInt32)(b) << 24) |
+ ((UInt32)(buffer[bufferPos + 3]) << 16) |
+ ((UInt32)(buffer[bufferPos + 2]) << 8) |
+ (buffer[bufferPos + 1]);
+
+ UInt32 dest;
+ while(1)
+ {
+ UInt32 index;
+ if (encoding)
+ dest = (nowPos + bufferPos + 5) + src;
+ else
+ dest = src - (nowPos + bufferPos + 5);
+ if (*prevMask == 0)
+ break;
+ index = kMaskToBitNumber[*prevMask >> 1];
+ b = (Byte)(dest >> (24 - index * 8));
+ if (!Test86MSByte(b))
+ break;
+ src = dest ^ ((1 << (32 - index * 8)) - 1);
+ }
+ buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1));
+ buffer[bufferPos + 3] = (Byte)(dest >> 16);
+ buffer[bufferPos + 2] = (Byte)(dest >> 8);
+ buffer[bufferPos + 1] = (Byte)dest;
+ bufferPos += 5;
+ *prevMask = 0;
+ }
+ else
+ {
+ bufferPos++;
+ *prevMask |= 1;
+ if (Test86MSByte(b))
+ *prevMask |= 0x10;
+ }
+ }
+ return bufferPos;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.h
new file mode 100644
index 00000000..879fd50e
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/BranchX86.h
@@ -0,0 +1,19 @@
+/* BranchX86.h */
+
+#ifndef __BRANCHX86_H
+#define __BRANCHX86_H
+
+#ifndef UInt32
+#define UInt32 unsigned int
+#endif
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); }
+
+UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos,
+ UInt32 *prevMask, UInt32 *prevPos, int encoding);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.cpp
new file mode 100644
index 00000000..a579c408
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.cpp
@@ -0,0 +1,16 @@
+// IA64.cpp
+
+#include "StdAfx.h"
+#include "IA64.h"
+
+#include "BranchIA64.c"
+
+UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::IA64_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::IA64_Convert(data, size, _bufferPos, 0);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.h
new file mode 100644
index 00000000..f47d5e4b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/IA64.h
@@ -0,0 +1,10 @@
+// IA64.h
+
+#ifndef __IA64_H
+#define __IA64_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_IA64, 0x04, 1)
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.cpp
new file mode 100644
index 00000000..c191f519
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.cpp
@@ -0,0 +1,17 @@
+// PPC.cpp
+
+#include "StdAfx.h"
+#include "PPC.h"
+
+#include "Windows/Defs.h"
+#include "BranchPPC.c"
+
+UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::PPC_B_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::PPC_B_Convert(data, size, _bufferPos, 0);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.h
new file mode 100644
index 00000000..e2fbb409
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/PPC.h
@@ -0,0 +1,10 @@
+// PPC.h
+
+#ifndef __PPC_H
+#define __PPC_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_PPC_B, 0x02, 5)
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.cpp
new file mode 100644
index 00000000..552551db
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.cpp
@@ -0,0 +1,17 @@
+// SPARC.cpp
+
+#include "StdAfx.h"
+#include "SPARC.h"
+
+#include "Windows/Defs.h"
+#include "BranchSPARC.c"
+
+UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::SPARC_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::SPARC_Convert(data, size, _bufferPos, 0);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.h
new file mode 100644
index 00000000..1e2c8afe
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/SPARC.h
@@ -0,0 +1,10 @@
+// SPARC.h
+
+#ifndef __SPARC_H
+#define __SPARC_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_SPARC, 0x08, 5)
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/StdAfx.h
new file mode 100644
index 00000000..83fdd22d
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.cpp
new file mode 100644
index 00000000..929484ad
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.cpp
@@ -0,0 +1,18 @@
+// x86.cpp
+
+#include "StdAfx.h"
+#include "x86.h"
+
+#include "Windows/Defs.h"
+
+#include "BranchX86.c"
+
+UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1);
+}
+
+UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+ return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.h
new file mode 100644
index 00000000..85882d91
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86.h
@@ -0,0 +1,19 @@
+// x86.h
+
+#ifndef __X86_H
+#define __X86_H
+
+#include "BranchCoder.h"
+#include "BranchX86.h"
+
+struct CBranch86
+{
+ UInt32 _prevMask;
+ UInt32 _prevPos;
+ void x86Init() { x86_Convert_Init(_prevMask, _prevPos); }
+};
+
+MyClassB(BCJ_x86, 0x01, 3, CBranch86 ,
+ virtual void SubInit() { x86Init(); })
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.cpp
new file mode 100644
index 00000000..fc87bd93
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.cpp
@@ -0,0 +1,412 @@
+// x86_2.cpp
+
+#include "StdAfx.h"
+#include "x86_2.h"
+
+#include "../../../Common/Alloc.h"
+
+static const int kBufferSize = 1 << 17;
+
+inline bool IsJcc(Byte b0, Byte b1)
+{
+ return (b0 == 0x0F && (b1 & 0xF0) == 0x80);
+}
+
+#ifndef EXTRACT_ONLY
+
+static bool inline Test86MSByte(Byte b)
+{
+ return (b == 0 || b == 0xFF);
+}
+
+bool CBCJ2_x86_Encoder::Create()
+{
+ if (!_mainStream.Create(1 << 16))
+ return false;
+ if (!_callStream.Create(1 << 20))
+ return false;
+ if (!_jumpStream.Create(1 << 20))
+ return false;
+ if (!_rangeEncoder.Create(1 << 20))
+ return false;
+ if (_buffer == 0)
+ {
+ _buffer = (Byte *)MidAlloc(kBufferSize);
+ if (_buffer == 0)
+ return false;
+ }
+ return true;
+}
+
+CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
+{
+ ::MidFree(_buffer);
+}
+
+HRESULT CBCJ2_x86_Encoder::Flush()
+{
+ RINOK(_mainStream.Flush());
+ RINOK(_callStream.Flush());
+ RINOK(_jumpStream.Flush());
+ _rangeEncoder.FlushData();
+ return _rangeEncoder.FlushStream();
+}
+
+const UInt32 kDefaultLimit = (1 << 24);
+
+HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress)
+{
+ if (numInStreams != 1 || numOutStreams != 4)
+ return E_INVALIDARG;
+
+ if (!Create())
+ return E_OUTOFMEMORY;
+
+ bool sizeIsDefined = false;
+ UInt64 inSize;
+ if (inSizes != NULL)
+ if (inSizes[0] != NULL)
+ {
+ inSize = *inSizes[0];
+ if (inSize <= kDefaultLimit)
+ sizeIsDefined = true;
+ }
+
+ ISequentialInStream *inStream = inStreams[0];
+
+ _mainStream.SetStream(outStreams[0]);
+ _mainStream.Init();
+ _callStream.SetStream(outStreams[1]);
+ _callStream.Init();
+ _jumpStream.SetStream(outStreams[2]);
+ _jumpStream.Init();
+ _rangeEncoder.SetStream(outStreams[3]);
+ _rangeEncoder.Init();
+ for (int i = 0; i < 256; i++)
+ _statusE8Encoder[i].Init();
+ _statusE9Encoder.Init();
+ _statusJccEncoder.Init();
+ CCoderReleaser releaser(this);
+
+ CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
+ {
+ inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
+ }
+
+ UInt32 nowPos = 0;
+ UInt64 nowPos64 = 0;
+ UInt32 bufferPos = 0;
+
+ Byte prevByte = 0;
+
+ UInt64 subStreamIndex = 0;
+ UInt64 subStreamStartPos = 0;
+ UInt64 subStreamEndPos = 0;
+
+ while(true)
+ {
+ UInt32 processedSize = 0;
+ while(true)
+ {
+ UInt32 size = kBufferSize - (bufferPos + processedSize);
+ UInt32 processedSizeLoc;
+ if (size == 0)
+ break;
+ RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));
+ if (processedSizeLoc == 0)
+ break;
+ processedSize += processedSizeLoc;
+ }
+ UInt32 endPos = bufferPos + processedSize;
+
+ if (endPos < 5)
+ {
+ // change it
+ for (bufferPos = 0; bufferPos < endPos; bufferPos++)
+ {
+ Byte b = _buffer[bufferPos];
+ _mainStream.WriteByte(b);
+ if (b == 0xE8)
+ _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
+ else if (b == 0xE9)
+ _statusE9Encoder.Encode(&_rangeEncoder, 0);
+ else if (IsJcc(prevByte, b))
+ _statusJccEncoder.Encode(&_rangeEncoder, 0);
+ prevByte = b;
+ }
+ return Flush();
+ }
+
+ bufferPos = 0;
+
+ UInt32 limit = endPos - 5;
+ while(bufferPos <= limit)
+ {
+ Byte b = _buffer[bufferPos];
+ _mainStream.WriteByte(b);
+ if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
+ {
+ bufferPos++;
+ prevByte = b;
+ continue;
+ }
+ Byte nextByte = _buffer[bufferPos + 4];
+ UInt32 src =
+ (UInt32(nextByte) << 24) |
+ (UInt32(_buffer[bufferPos + 3]) << 16) |
+ (UInt32(_buffer[bufferPos + 2]) << 8) |
+ (_buffer[bufferPos + 1]);
+ UInt32 dest = (nowPos + bufferPos + 5) + src;
+ // if (Test86MSByte(nextByte))
+ bool convert;
+ if (getSubStreamSize != NULL)
+ {
+ UInt64 currentPos = (nowPos64 + bufferPos);
+ while (subStreamEndPos < currentPos)
+ {
+ UInt64 subStreamSize;
+ HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
+ if (result == S_OK)
+ {
+ subStreamStartPos = subStreamEndPos;
+ subStreamEndPos += subStreamSize;
+ subStreamIndex++;
+ }
+ else if (result == S_FALSE || result == E_NOTIMPL)
+ {
+ getSubStreamSize.Release();
+ subStreamStartPos = 0;
+ subStreamEndPos = subStreamStartPos - 1;
+ }
+ else
+ return result;
+ }
+ if (getSubStreamSize == NULL)
+ {
+ if (sizeIsDefined)
+ convert = (dest < inSize);
+ else
+ convert = Test86MSByte(nextByte);
+ }
+ else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
+ convert = Test86MSByte(nextByte);
+ else
+ {
+ UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
+ convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
+ }
+ }
+ else if (sizeIsDefined)
+ convert = (dest < inSize);
+ else
+ convert = Test86MSByte(nextByte);
+ if (convert)
+ {
+ if (b == 0xE8)
+ _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1);
+ else if (b == 0xE9)
+ _statusE9Encoder.Encode(&_rangeEncoder, 1);
+ else
+ _statusJccEncoder.Encode(&_rangeEncoder, 1);
+
+ bufferPos += 5;
+ if (b == 0xE8)
+ {
+ _callStream.WriteByte((Byte)(dest >> 24));
+ _callStream.WriteByte((Byte)(dest >> 16));
+ _callStream.WriteByte((Byte)(dest >> 8));
+ _callStream.WriteByte((Byte)(dest));
+ }
+ else
+ {
+ _jumpStream.WriteByte((Byte)(dest >> 24));
+ _jumpStream.WriteByte((Byte)(dest >> 16));
+ _jumpStream.WriteByte((Byte)(dest >> 8));
+ _jumpStream.WriteByte((Byte)(dest));
+ }
+ prevByte = nextByte;
+ }
+ else
+ {
+ if (b == 0xE8)
+ _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
+ else if (b == 0xE9)
+ _statusE9Encoder.Encode(&_rangeEncoder, 0);
+ else
+ _statusJccEncoder.Encode(&_rangeEncoder, 0);
+ bufferPos++;
+ prevByte = b;
+ }
+ }
+ nowPos += bufferPos;
+ nowPos64 += bufferPos;
+
+ if (progress != NULL)
+ {
+ RINOK(progress->SetRatioInfo(&nowPos64, NULL));
+ }
+
+ UInt32 i = 0;
+ while(bufferPos < endPos)
+ _buffer[i++] = _buffer[bufferPos++];
+ bufferPos = i;
+ }
+}
+
+STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress)
+{
+ try
+ {
+ return CodeReal(inStreams, inSizes, numInStreams,
+ outStreams, outSizes,numOutStreams, progress);
+ }
+ catch(const COutBufferException &e) { return e.ErrorCode; }
+ catch(...) { return S_FALSE; }
+}
+
+#endif
+
+HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress)
+{
+ if (numInStreams != 4 || numOutStreams != 1)
+ return E_INVALIDARG;
+
+ if (!_mainInStream.Create(1 << 16))
+ return E_OUTOFMEMORY;
+ if (!_callStream.Create(1 << 20))
+ return E_OUTOFMEMORY;
+ if (!_jumpStream.Create(1 << 16))
+ return E_OUTOFMEMORY;
+ if (!_rangeDecoder.Create(1 << 20))
+ return E_OUTOFMEMORY;
+ if (!_outStream.Create(1 << 16))
+ return E_OUTOFMEMORY;
+
+ _mainInStream.SetStream(inStreams[0]);
+ _callStream.SetStream(inStreams[1]);
+ _jumpStream.SetStream(inStreams[2]);
+ _rangeDecoder.SetStream(inStreams[3]);
+ _outStream.SetStream(outStreams[0]);
+
+ _mainInStream.Init();
+ _callStream.Init();
+ _jumpStream.Init();
+ _rangeDecoder.Init();
+ _outStream.Init();
+
+ for (int i = 0; i < 256; i++)
+ _statusE8Decoder[i].Init();
+ _statusE9Decoder.Init();
+ _statusJccDecoder.Init();
+
+ CCoderReleaser releaser(this);
+
+ Byte prevByte = 0;
+ UInt32 processedBytes = 0;
+ while(true)
+ {
+ if (processedBytes > (1 << 20) && progress != NULL)
+ {
+ UInt64 nowPos64 = _outStream.GetProcessedSize();
+ RINOK(progress->SetRatioInfo(NULL, &nowPos64));
+ processedBytes = 0;
+ }
+ processedBytes++;
+ Byte b;
+ if (!_mainInStream.ReadByte(b))
+ return Flush();
+ _outStream.WriteByte(b);
+ if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
+ {
+ prevByte = b;
+ continue;
+ }
+ bool status;
+ if (b == 0xE8)
+ status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1);
+ else if (b == 0xE9)
+ status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1);
+ else
+ status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1);
+ if (status)
+ {
+ UInt32 src;
+ if (b == 0xE8)
+ {
+ Byte b0;
+ if(!_callStream.ReadByte(b0))
+ return S_FALSE;
+ src = ((UInt32)b0) << 24;
+ if(!_callStream.ReadByte(b0))
+ return S_FALSE;
+ src |= ((UInt32)b0) << 16;
+ if(!_callStream.ReadByte(b0))
+ return S_FALSE;
+ src |= ((UInt32)b0) << 8;
+ if(!_callStream.ReadByte(b0))
+ return S_FALSE;
+ src |= ((UInt32)b0);
+ }
+ else
+ {
+ Byte b0;
+ if(!_jumpStream.ReadByte(b0))
+ return S_FALSE;
+ src = ((UInt32)b0) << 24;
+ if(!_jumpStream.ReadByte(b0))
+ return S_FALSE;
+ src |= ((UInt32)b0) << 16;
+ if(!_jumpStream.ReadByte(b0))
+ return S_FALSE;
+ src |= ((UInt32)b0) << 8;
+ if(!_jumpStream.ReadByte(b0))
+ return S_FALSE;
+ src |= ((UInt32)b0);
+ }
+ UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
+ _outStream.WriteByte((Byte)(dest));
+ _outStream.WriteByte((Byte)(dest >> 8));
+ _outStream.WriteByte((Byte)(dest >> 16));
+ _outStream.WriteByte((Byte)(dest >> 24));
+ prevByte = (dest >> 24);
+ processedBytes += 4;
+ }
+ else
+ prevByte = b;
+ }
+}
+
+STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress)
+{
+ try
+ {
+ return CodeReal(inStreams, inSizes, numInStreams,
+ outStreams, outSizes,numOutStreams, progress);
+ }
+ catch(const COutBufferException &e) { return e.ErrorCode; }
+ catch(...) { return S_FALSE; }
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.h
new file mode 100644
index 00000000..9e7780c8
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/Branch/x86_2.h
@@ -0,0 +1,133 @@
+// x86_2.h
+
+#ifndef __BRANCH_X86_2_H
+#define __BRANCH_X86_2_H
+
+#include "../../../Common/MyCom.h"
+#include "../RangeCoder/RangeCoderBit.h"
+#include "../../ICoder.h"
+
+// {23170F69-40C1-278B-0303-010100000100}
+#define MyClass2_a(Name, id, subId, encodingId) \
+DEFINE_GUID(CLSID_CCompressConvert ## Name, \
+0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00);
+
+#define MyClass_a(Name, id, subId) \
+MyClass2_a(Name ## _Encoder, id, subId, 0x01) \
+MyClass2_a(Name ## _Decoder, id, subId, 0x00)
+
+MyClass_a(BCJ2_x86, 0x01, 0x1B)
+
+const int kNumMoveBits = 5;
+
+#ifndef EXTRACT_ONLY
+
+class CBCJ2_x86_Encoder:
+ public ICompressCoder2,
+ public CMyUnknownImp
+{
+ Byte *_buffer;
+public:
+ CBCJ2_x86_Encoder(): _buffer(0) {};
+ ~CBCJ2_x86_Encoder();
+ bool Create();
+
+ COutBuffer _mainStream;
+ COutBuffer _callStream;
+ COutBuffer _jumpStream;
+ NCompress::NRangeCoder::CEncoder _rangeEncoder;
+ NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusE8Encoder[256];
+ NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusE9Encoder;
+ NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusJccEncoder;
+
+ HRESULT Flush();
+ void ReleaseStreams()
+ {
+ _mainStream.ReleaseStream();
+ _callStream.ReleaseStream();
+ _jumpStream.ReleaseStream();
+ _rangeEncoder.ReleaseStream();
+ }
+
+ class CCoderReleaser
+ {
+ CBCJ2_x86_Encoder *_coder;
+ public:
+ CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {}
+ ~CCoderReleaser() { _coder->ReleaseStreams(); }
+ };
+
+public:
+
+ MY_UNKNOWN_IMP
+
+ HRESULT CodeReal(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress);
+ STDMETHOD(Code)(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress);
+};
+
+#endif
+
+class CBCJ2_x86_Decoder:
+ public ICompressCoder2,
+ public CMyUnknownImp
+{
+public:
+ CInBuffer _mainInStream;
+ CInBuffer _callStream;
+ CInBuffer _jumpStream;
+ NCompress::NRangeCoder::CDecoder _rangeDecoder;
+ NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusE8Decoder[256];
+ NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusE9Decoder;
+ NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusJccDecoder;
+
+ COutBuffer _outStream;
+
+ void ReleaseStreams()
+ {
+ _mainInStream.ReleaseStream();
+ _callStream.ReleaseStream();
+ _jumpStream.ReleaseStream();
+ _rangeDecoder.ReleaseStream();
+ _outStream.ReleaseStream();
+ }
+
+ HRESULT Flush() { return _outStream.Flush(); }
+ class CCoderReleaser
+ {
+ CBCJ2_x86_Decoder *_coder;
+ public:
+ CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {}
+ ~CCoderReleaser() { _coder->ReleaseStreams(); }
+ };
+
+public:
+ MY_UNKNOWN_IMP
+ HRESULT CodeReal(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress);
+ STDMETHOD(Code)(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress);
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h
new file mode 100644
index 00000000..19a1de0e
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h
@@ -0,0 +1,55 @@
+// BinTree.h
+
+#include "../LZInWindow.h"
+#include "../IMatchFinder.h"
+
+namespace BT_NAMESPACE {
+
+typedef UInt32 CIndex;
+const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;
+
+class CMatchFinderBinTree:
+ public IMatchFinder,
+ public IMatchFinderSetCallback,
+ public CLZInWindow,
+ public CMyUnknownImp
+{
+ UInt32 _cyclicBufferPos;
+ UInt32 _cyclicBufferSize; // it must be historySize + 1
+ UInt32 _matchMaxLen;
+ CIndex *_hash;
+ UInt32 _cutValue;
+
+ CMyComPtr<IMatchFinderCallback> m_Callback;
+
+ void Normalize();
+ void FreeThisClassMemory();
+ void FreeMemory();
+
+ MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
+
+ STDMETHOD(Init)(ISequentialInStream *inStream);
+ STDMETHOD_(void, ReleaseStream)();
+ STDMETHOD(MovePos)();
+ STDMETHOD_(Byte, GetIndexByte)(Int32 index);
+ STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
+ STDMETHOD_(UInt32, GetNumAvailableBytes)();
+ STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
+ STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
+ STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
+ STDMETHOD_(void, DummyLongestMatch)();
+
+ // IMatchFinderSetCallback
+ STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
+
+ virtual void BeforeMoveBlock();
+ virtual void AfterMoveBlock();
+
+public:
+ CMatchFinderBinTree();
+ virtual ~CMatchFinderBinTree();
+ void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
+};
+
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h
new file mode 100644
index 00000000..9dbe35d6
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h
@@ -0,0 +1,12 @@
+// BinTree2.h
+
+#ifndef __BINTREE2_H
+#define __BINTREE2_H
+
+#undef BT_NAMESPACE
+#define BT_NAMESPACE NBT2
+
+#include "BinTree.h"
+#include "BinTreeMain.h"
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h
new file mode 100644
index 00000000..9a68669f
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h
@@ -0,0 +1,16 @@
+// BinTree3.h
+
+#ifndef __BINTREE3_H
+#define __BINTREE3_H
+
+#undef BT_NAMESPACE
+#define BT_NAMESPACE NBT3
+
+#define HASH_ARRAY_2
+
+#include "BinTree.h"
+#include "BinTreeMain.h"
+
+#undef HASH_ARRAY_2
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h
new file mode 100644
index 00000000..b77de3d9
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h
@@ -0,0 +1,16 @@
+// BinTree3Z.h
+
+#ifndef __BINTREE3Z_H
+#define __BINTREE3Z_H
+
+#undef BT_NAMESPACE
+#define BT_NAMESPACE NBT3Z
+
+#define HASH_ZIP
+
+#include "BinTree.h"
+#include "BinTreeMain.h"
+
+#undef HASH_ZIP
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h
new file mode 100644
index 00000000..bdc4a87b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h
@@ -0,0 +1,18 @@
+// BinTree4.h
+
+#ifndef __BINTREE4_H
+#define __BINTREE4_H
+
+#undef BT_NAMESPACE
+#define BT_NAMESPACE NBT4
+
+#define HASH_ARRAY_2
+#define HASH_ARRAY_3
+
+#include "BinTree.h"
+#include "BinTreeMain.h"
+
+#undef HASH_ARRAY_2
+#undef HASH_ARRAY_3
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4b.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4b.h
new file mode 100644
index 00000000..06f56662
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTree4b.h
@@ -0,0 +1,20 @@
+// BinTree4b.h
+
+#ifndef __BINTREE4B_H
+#define __BINTREE4B_H
+
+#undef BT_NAMESPACE
+#define BT_NAMESPACE NBT4B
+
+#define HASH_ARRAY_2
+#define HASH_ARRAY_3
+#define HASH_BIG
+
+#include "BinTree.h"
+#include "BinTreeMain.h"
+
+#undef HASH_ARRAY_2
+#undef HASH_ARRAY_3
+#undef HASH_BIG
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h
new file mode 100644
index 00000000..452466a7
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h
@@ -0,0 +1,444 @@
+// BinTreeMain.h
+
+#include "../../../../Common/Defs.h"
+#include "../../../../Common/CRC.h"
+#include "../../../../Common/Alloc.h"
+
+namespace BT_NAMESPACE {
+
+#ifdef HASH_ARRAY_2
+ static const UInt32 kHash2Size = 1 << 10;
+ #ifdef HASH_ARRAY_3
+ static const UInt32 kNumHashDirectBytes = 0;
+ static const UInt32 kNumHashBytes = 4;
+ static const UInt32 kHash3Size = 1 << 18;
+ #ifdef HASH_BIG
+ static const UInt32 kHashSize = 1 << 23;
+ #else
+ static const UInt32 kHashSize = 1 << 20;
+ #endif
+ #else
+ static const UInt32 kNumHashDirectBytes = 3;
+ static const UInt32 kNumHashBytes = 3;
+ static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
+ #endif
+#else
+ #ifdef HASH_ZIP
+ static const UInt32 kNumHashDirectBytes = 0;
+ static const UInt32 kNumHashBytes = 3;
+ static const UInt32 kHashSize = 1 << 16;
+ #else
+ #define THERE_ARE_DIRECT_HASH_BYTES
+ static const UInt32 kNumHashDirectBytes = 2;
+ static const UInt32 kNumHashBytes = 2;
+ static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
+ #endif
+#endif
+
+static const UInt32 kHashSizeSum = kHashSize
+ #ifdef HASH_ARRAY_2
+ + kHash2Size
+ #ifdef HASH_ARRAY_3
+ + kHash3Size
+ #endif
+ #endif
+ ;
+
+#ifdef HASH_ARRAY_2
+static const UInt32 kHash2Offset = kHashSize;
+#ifdef HASH_ARRAY_3
+static const UInt32 kHash3Offset = kHashSize + kHash2Size;
+#endif
+#endif
+
+CMatchFinderBinTree::CMatchFinderBinTree():
+ _hash(0),
+ _cutValue(0xFF)
+{
+}
+
+void CMatchFinderBinTree::FreeThisClassMemory()
+{
+ BigFree(_hash);
+ _hash = 0;
+}
+
+void CMatchFinderBinTree::FreeMemory()
+{
+ FreeThisClassMemory();
+ CLZInWindow::Free();
+}
+
+CMatchFinderBinTree::~CMatchFinderBinTree()
+{
+ FreeMemory();
+}
+
+STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
+{
+ UInt32 sizeReserv = (historySize + keepAddBufferBefore +
+ matchMaxLen + keepAddBufferAfter) / 2 + 256;
+ if (CLZInWindow::Create(historySize + keepAddBufferBefore,
+ matchMaxLen + keepAddBufferAfter, sizeReserv))
+ {
+ if (historySize + 256 > kMaxValForNormalize)
+ {
+ FreeMemory();
+ return E_INVALIDARG;
+ }
+ _matchMaxLen = matchMaxLen;
+ UInt32 newCyclicBufferSize = historySize + 1;
+ if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
+ return S_OK;
+ FreeThisClassMemory();
+ _cyclicBufferSize = newCyclicBufferSize; // don't change it
+ _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize * 2) * sizeof(CIndex));
+ if (_hash != 0)
+ return S_OK;
+ }
+ FreeMemory();
+ return E_OUTOFMEMORY;
+}
+
+static const UInt32 kEmptyHashValue = 0;
+
+STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream)
+{
+ RINOK(CLZInWindow::Init(stream));
+ for(UInt32 i = 0; i < kHashSizeSum; i++)
+ _hash[i] = kEmptyHashValue;
+ _cyclicBufferPos = 0;
+ ReduceOffsets(-1);
+ return S_OK;
+}
+
+STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream()
+{
+ // ReleaseStream();
+}
+
+#ifdef HASH_ARRAY_2
+#ifdef HASH_ARRAY_3
+inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value)
+{
+ UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
+ hash2Value = temp & (kHash2Size - 1);
+ hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1);
+ return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) &
+ (kHashSize - 1);
+}
+#else // no HASH_ARRAY_3
+inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value)
+{
+ hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1);
+ return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2];
+}
+#endif // HASH_ARRAY_3
+#else // no HASH_ARRAY_2
+#ifdef HASH_ZIP
+inline UInt32 Hash(const Byte *pointer)
+{
+ return ((UInt32(pointer[0]) << 8) ^
+ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
+}
+#else // no HASH_ZIP
+inline UInt32 Hash(const Byte *pointer)
+{
+ return pointer[0] ^ (UInt32(pointer[1]) << 8);
+}
+#endif // HASH_ZIP
+#endif // HASH_ARRAY_2
+
+STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances)
+{
+ UInt32 lenLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ lenLimit = _matchMaxLen;
+ else
+ {
+ lenLimit = _streamPos - _pos;
+ if(lenLimit < kNumHashBytes)
+ return 0;
+ }
+
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+ Byte *cur = _buffer + _pos;
+
+ UInt32 maxLen = 0;
+
+ #ifdef HASH_ARRAY_2
+ UInt32 hash2Value;
+ #ifdef HASH_ARRAY_3
+ UInt32 hash3Value;
+ UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
+ #else
+ UInt32 hashValue = Hash(cur, hash2Value);
+ #endif
+ #else
+ UInt32 hashValue = Hash(cur);
+ #endif
+
+ UInt32 curMatch = _hash[hashValue];
+ #ifdef HASH_ARRAY_2
+ UInt32 curMatch2 = _hash[kHash2Offset + hash2Value];
+ #ifdef HASH_ARRAY_3
+ UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
+ #endif
+ _hash[kHash2Offset + hash2Value] = _pos;
+ distances[2] = 0xFFFFFFFF;
+ if(curMatch2 > matchMinPos)
+ if (_buffer[curMatch2] == cur[0])
+ {
+ distances[2] = _pos - curMatch2 - 1;
+ maxLen = 2;
+ }
+
+ #ifdef HASH_ARRAY_3
+ _hash[kHash3Offset + hash3Value] = _pos;
+ distances[3] = 0xFFFFFFFF;
+ if(curMatch3 > matchMinPos)
+ if (_buffer[curMatch3] == cur[0])
+ {
+ distances[3] = _pos - curMatch3 - 1;
+ maxLen = 3;
+ }
+ #endif
+ #endif
+
+ _hash[hashValue] = _pos;
+
+ CIndex *son = _hash + kHashSizeSum;
+ CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CIndex *ptr1 = son + (_cyclicBufferPos << 1);
+
+ distances[kNumHashBytes] = 0xFFFFFFFF;
+
+ #ifdef THERE_ARE_DIRECT_HASH_BYTES
+ if (lenLimit == kNumHashDirectBytes)
+ {
+ if(curMatch > matchMinPos)
+ while (maxLen < kNumHashDirectBytes)
+ distances[++maxLen] = _pos - curMatch - 1;
+ // We don't need tree in this case
+ }
+ else
+ #endif
+ {
+ UInt32 len0, len1;
+ len0 = len1 = kNumHashDirectBytes;
+ UInt32 count = _cutValue;
+ while(true)
+ {
+ if(curMatch <= matchMinPos || count-- == 0)
+ {
+ *ptr0 = kEmptyHashValue;
+ *ptr1 = kEmptyHashValue;
+ break;
+ }
+ Byte *pb = _buffer + curMatch;
+ UInt32 len = MyMin(len0, len1);
+ do
+ {
+ if (pb[len] != cur[len])
+ break;
+ }
+ while(++len != lenLimit);
+
+ UInt32 delta = _pos - curMatch;
+ while (maxLen < len)
+ distances[++maxLen] = delta - 1;
+
+ UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
+ (_cyclicBufferPos - delta):
+ (_cyclicBufferPos - delta + _cyclicBufferSize);
+ CIndex *pair = son + (cyclicPos << 1);
+
+ if (len != lenLimit)
+ {
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ else
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ break;
+ }
+ }
+ }
+ #ifdef HASH_ARRAY_2
+ #ifdef HASH_ARRAY_3
+ if (distances[4] < distances[3])
+ distances[3] = distances[4];
+ #endif
+ if (distances[3] < distances[2])
+ distances[2] = distances[3];
+ #endif
+ return maxLen;
+}
+
+STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch()
+{
+ UInt32 lenLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ lenLimit = _matchMaxLen;
+ else
+ {
+ lenLimit = _streamPos - _pos;
+ if(lenLimit < kNumHashBytes)
+ return;
+ }
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+ Byte *cur = _buffer + _pos;
+
+ #ifdef HASH_ARRAY_2
+ UInt32 hash2Value;
+ #ifdef HASH_ARRAY_3
+ UInt32 hash3Value;
+ UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
+ _hash[kHash3Offset + hash3Value] = _pos;
+ #else
+ UInt32 hashValue = Hash(cur, hash2Value);
+ #endif
+ _hash[kHash2Offset + hash2Value] = _pos;
+ #else
+ UInt32 hashValue = Hash(cur);
+ #endif
+
+ UInt32 curMatch = _hash[hashValue];
+ _hash[hashValue] = _pos;
+
+ CIndex *son = _hash + kHashSizeSum;
+ CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CIndex *ptr1 = son + (_cyclicBufferPos << 1);
+
+ #ifdef THERE_ARE_DIRECT_HASH_BYTES
+ if (lenLimit != kNumHashDirectBytes)
+ #endif
+ {
+ UInt32 len0, len1;
+ len0 = len1 = kNumHashDirectBytes;
+ UInt32 count = _cutValue;
+ while(true)
+ {
+ if(curMatch <= matchMinPos || count-- == 0)
+ break;
+ Byte *pb = _buffer + curMatch;
+ UInt32 len = MyMin(len0, len1);
+ do
+ {
+ if (pb[len] != cur[len])
+ break;
+ }
+ while(++len != lenLimit);
+
+ UInt32 delta = _pos - curMatch;
+ UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
+ (_cyclicBufferPos - delta):
+ (_cyclicBufferPos - delta + _cyclicBufferSize);
+ CIndex *pair = son + (cyclicPos << 1);
+
+ if (len != lenLimit)
+ {
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ else
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return;
+ }
+ }
+ }
+ *ptr0 = kEmptyHashValue;
+ *ptr1 = kEmptyHashValue;
+}
+
+void CMatchFinderBinTree::Normalize()
+{
+ UInt32 subValue = _pos - _cyclicBufferSize;
+ CIndex *items = _hash;
+ UInt32 numItems = (kHashSizeSum + _cyclicBufferSize * 2);
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ value = kEmptyHashValue;
+ else
+ value -= subValue;
+ items[i] = value;
+ }
+ ReduceOffsets(subValue);
+}
+
+STDMETHODIMP CMatchFinderBinTree::MovePos()
+{
+ if (++_cyclicBufferPos == _cyclicBufferSize)
+ _cyclicBufferPos = 0;
+ RINOK(CLZInWindow::MovePos());
+ if (_pos == kMaxValForNormalize)
+ Normalize();
+ return S_OK;
+}
+
+STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index)
+ { return CLZInWindow::GetIndexByte(index); }
+
+STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index,
+ UInt32 back, UInt32 limit)
+ { return CLZInWindow::GetMatchLen(index, back, limit); }
+
+STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes()
+ { return CLZInWindow::GetNumAvailableBytes(); }
+
+STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos()
+ { return CLZInWindow::GetPointerToCurrentPos(); }
+
+// IMatchFinderSetCallback
+STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback)
+{
+ m_Callback = callback;
+ return S_OK;
+}
+
+void CMatchFinderBinTree::BeforeMoveBlock()
+{
+ if (m_Callback)
+ m_Callback->BeforeChangingBufferPos();
+ CLZInWindow::BeforeMoveBlock();
+}
+
+void CMatchFinderBinTree::AfterMoveBlock()
+{
+ if (m_Callback)
+ m_Callback->AfterChangingBufferPos();
+ CLZInWindow::AfterMoveBlock();
+}
+
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC.h
new file mode 100644
index 00000000..53f3e217
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC.h
@@ -0,0 +1,55 @@
+// HC.h
+
+#include "../LZInWindow.h"
+#include "../IMatchFinder.h"
+
+namespace HC_NAMESPACE {
+
+typedef UInt32 CIndex;
+const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;
+
+class CMatchFinderHC:
+ public IMatchFinder,
+ public IMatchFinderSetCallback,
+ public CLZInWindow,
+ public CMyUnknownImp
+{
+ UInt32 _cyclicBufferPos;
+ UInt32 _cyclicBufferSize; // it must be historySize + 1
+ UInt32 _matchMaxLen;
+ CIndex *_hash;
+ UInt32 _cutValue;
+
+ CMyComPtr<IMatchFinderCallback> m_Callback;
+
+ void Normalize();
+ void FreeThisClassMemory();
+ void FreeMemory();
+
+ MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
+
+ STDMETHOD(Init)(ISequentialInStream *inStream);
+ STDMETHOD_(void, ReleaseStream)();
+ STDMETHOD(MovePos)();
+ STDMETHOD_(Byte, GetIndexByte)(Int32 index);
+ STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
+ STDMETHOD_(UInt32, GetNumAvailableBytes)();
+ STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
+ STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
+ STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
+ STDMETHOD_(void, DummyLongestMatch)();
+
+ // IMatchFinderSetCallback
+ STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
+
+ virtual void BeforeMoveBlock();
+ virtual void AfterMoveBlock();
+
+public:
+ CMatchFinderHC();
+ virtual ~CMatchFinderHC();
+ void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
+};
+
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC2.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC2.h
new file mode 100644
index 00000000..7211cc50
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC2.h
@@ -0,0 +1,13 @@
+// HC2.h
+
+#ifndef __HC2_H
+#define __HC2_H
+
+#undef HC_NAMESPACE
+#define HC_NAMESPACE NHC2
+
+#include "HCMF.h"
+#include "HCMFMain.h"
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC3.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC3.h
new file mode 100644
index 00000000..38f05d23
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC3.h
@@ -0,0 +1,17 @@
+// HC3.h
+
+#ifndef __HC3_H
+#define __HC3_H
+
+#undef HC_NAMESPACE
+#define HC_NAMESPACE NHC3
+
+#define HASH_ARRAY_2
+
+#include "HC.h"
+#include "HCMain.h"
+
+#undef HASH_ARRAY_2
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4.h
new file mode 100644
index 00000000..7d4e2117
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4.h
@@ -0,0 +1,19 @@
+// HC4.h
+
+#ifndef __HC4_H
+#define __HC4_H
+
+#undef HC_NAMESPACE
+#define HC_NAMESPACE NHC4
+
+#define HASH_ARRAY_2
+#define HASH_ARRAY_3
+
+#include "HC.h"
+#include "HCMain.h"
+
+#undef HASH_ARRAY_2
+#undef HASH_ARRAY_3
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4b.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4b.h
new file mode 100644
index 00000000..229e5fdf
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HC4b.h
@@ -0,0 +1,21 @@
+// HC4b.h
+
+#ifndef __HC4B__H
+#define __HC4B__H
+
+#undef HC_NAMESPACE
+#define HC_NAMESPACE NHC4b
+
+#define HASH_ARRAY_2
+#define HASH_ARRAY_3
+#define HASH_BIG
+
+#include "HC.h"
+#include "HCMain.h"
+
+#undef HASH_ARRAY_2
+#undef HASH_ARRAY_3
+#undef HASH_BIG
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h
new file mode 100644
index 00000000..61d932cb
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h
@@ -0,0 +1,350 @@
+// HC.h
+
+#include "../../../../Common/Defs.h"
+#include "../../../../Common/CRC.h"
+#include "../../../../Common/Alloc.h"
+
+namespace HC_NAMESPACE {
+
+#ifdef HASH_ARRAY_2
+ static const UInt32 kHash2Size = 1 << 10;
+ #ifdef HASH_ARRAY_3
+ static const UInt32 kNumHashDirectBytes = 0;
+ static const UInt32 kNumHashBytes = 4;
+ static const UInt32 kHash3Size = 1 << 18;
+ #ifdef HASH_BIG
+ static const UInt32 kHashSize = 1 << 23;
+ #else
+ static const UInt32 kHashSize = 1 << 20;
+ #endif
+ #else
+ static const UInt32 kNumHashDirectBytes = 0;
+ static const UInt32 kNumHashBytes = 3;
+ static const UInt32 kHashSize = 1 << (16);
+ #endif
+#else
+ #ifdef HASH_ZIP
+ static const UInt32 kNumHashDirectBytes = 0;
+ static const UInt32 kNumHashBytes = 3;
+ static const UInt32 kHashSize = 1 << 16;
+ #else
+ #define THERE_ARE_DIRECT_HASH_BYTES
+ static const UInt32 kNumHashDirectBytes = 2;
+ static const UInt32 kNumHashBytes = 2;
+ static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
+ #endif
+#endif
+
+static const UInt32 kHashSizeSum = kHashSize
+ #ifdef HASH_ARRAY_2
+ + kHash2Size
+ #ifdef HASH_ARRAY_3
+ + kHash3Size
+ #endif
+ #endif
+ ;
+
+#ifdef HASH_ARRAY_2
+static const UInt32 kHash2Offset = kHashSize;
+#ifdef HASH_ARRAY_3
+static const UInt32 kHash3Offset = kHashSize + kHash2Size;
+#endif
+#endif
+
+CMatchFinderHC::CMatchFinderHC():
+ _hash(0),
+ _cutValue(16)
+{
+}
+
+void CMatchFinderHC::FreeThisClassMemory()
+{
+ BigFree(_hash);
+ _hash = 0;
+}
+
+void CMatchFinderHC::FreeMemory()
+{
+ FreeThisClassMemory();
+ CLZInWindow::Free();
+}
+
+CMatchFinderHC::~CMatchFinderHC()
+{
+ FreeMemory();
+}
+
+STDMETHODIMP CMatchFinderHC::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
+{
+ UInt32 sizeReserv = (historySize + keepAddBufferBefore +
+ matchMaxLen + keepAddBufferAfter) / 2 + 256;
+ if (CLZInWindow::Create(historySize + keepAddBufferBefore,
+ matchMaxLen + keepAddBufferAfter, sizeReserv))
+ {
+ if (historySize + 256 > kMaxValForNormalize)
+ {
+ FreeMemory();
+ return E_INVALIDARG;
+ }
+ _matchMaxLen = matchMaxLen;
+ UInt32 newCyclicBufferSize = historySize + 1;
+ if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
+ return S_OK;
+ FreeThisClassMemory();
+ _cyclicBufferSize = newCyclicBufferSize; // don't change it
+ _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize) * sizeof(CIndex));
+ if (_hash != 0)
+ return S_OK;
+ }
+ FreeMemory();
+ return E_OUTOFMEMORY;
+}
+
+static const UInt32 kEmptyHashValue = 0;
+
+STDMETHODIMP CMatchFinderHC::Init(ISequentialInStream *stream)
+{
+ RINOK(CLZInWindow::Init(stream));
+ for(UInt32 i = 0; i < kHashSizeSum; i++)
+ _hash[i] = kEmptyHashValue;
+ _cyclicBufferPos = 0;
+ ReduceOffsets(-1);
+ return S_OK;
+}
+
+STDMETHODIMP_(void) CMatchFinderHC::ReleaseStream()
+{
+ // ReleaseStream();
+}
+
+#ifdef HASH_ARRAY_2
+#ifdef HASH_ARRAY_3
+inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value)
+{
+ UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
+ hash2Value = temp & (kHash2Size - 1);
+ hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1);
+ return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) &
+ (kHashSize - 1);
+}
+#else // no HASH_ARRAY_3
+inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value)
+{
+ UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
+ hash2Value = temp & (kHash2Size - 1);
+ return (temp ^ (UInt32(pointer[2]) << 8)) & (kHashSize - 1);;
+}
+#endif // HASH_ARRAY_3
+#else // no HASH_ARRAY_2
+#ifdef HASH_ZIP
+inline UInt32 Hash(const Byte *pointer)
+{
+ return ((UInt32(pointer[0]) << 8) ^
+ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
+}
+#else // no HASH_ZIP
+inline UInt32 Hash(const Byte *pointer)
+{
+ return pointer[0] ^ (UInt32(pointer[1]) << 8);
+}
+#endif // HASH_ZIP
+#endif // HASH_ARRAY_2
+
+
+STDMETHODIMP_(UInt32) CMatchFinderHC::GetLongestMatch(UInt32 *distances)
+{
+ UInt32 lenLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ lenLimit = _matchMaxLen;
+ else
+ {
+ lenLimit = _streamPos - _pos;
+ if(lenLimit < kNumHashBytes)
+ return 0;
+ }
+
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+ Byte *cur = _buffer + _pos;
+
+ UInt32 maxLen = 0;
+
+ #ifdef HASH_ARRAY_2
+ UInt32 hash2Value;
+ #ifdef HASH_ARRAY_3
+ UInt32 hash3Value;
+ UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
+ #else
+ UInt32 hashValue = Hash(cur, hash2Value);
+ #endif
+ #else
+ UInt32 hashValue = Hash(cur);
+ #endif
+ #ifdef HASH_ARRAY_2
+
+ UInt32 curMatch2 = _hash[kHash2Offset + hash2Value];
+ _hash[kHash2Offset + hash2Value] = _pos;
+ distances[2] = 0xFFFFFFFF;
+ if(curMatch2 > matchMinPos)
+ if (_buffer[curMatch2] == cur[0])
+ {
+ distances[2] = _pos - curMatch2 - 1;
+ maxLen = 2;
+ }
+
+ #ifdef HASH_ARRAY_3
+
+ UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
+ _hash[kHash3Offset + hash3Value] = _pos;
+ distances[3] = 0xFFFFFFFF;
+ if(curMatch3 > matchMinPos)
+ if (_buffer[curMatch3] == cur[0])
+ {
+ distances[3] = _pos - curMatch3 - 1;
+ maxLen = 3;
+ }
+
+ #endif
+ #endif
+
+ UInt32 curMatch = _hash[hashValue];
+ _hash[hashValue] = _pos;
+ CIndex *chain = _hash + kHashSizeSum;
+ chain[_cyclicBufferPos] = curMatch;
+ distances[kNumHashBytes] = 0xFFFFFFFF;
+ #ifdef THERE_ARE_DIRECT_HASH_BYTES
+ if (lenLimit == kNumHashDirectBytes)
+ {
+ if(curMatch > matchMinPos)
+ while (maxLen < kNumHashDirectBytes)
+ distances[++maxLen] = _pos - curMatch - 1;
+ }
+ else
+ #endif
+ {
+ UInt32 count = _cutValue;
+ do
+ {
+ if(curMatch <= matchMinPos)
+ break;
+ Byte *pby1 = _buffer + curMatch;
+ UInt32 currentLen = kNumHashDirectBytes;
+ do
+ {
+ if (pby1[currentLen] != cur[currentLen])
+ break;
+ }
+ while(++currentLen != lenLimit);
+
+ UInt32 delta = _pos - curMatch;
+ while (maxLen < currentLen)
+ distances[++maxLen] = delta - 1;
+ if(currentLen == lenLimit)
+ break;
+
+ UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
+ (_cyclicBufferPos - delta):
+ (_cyclicBufferPos - delta + _cyclicBufferSize);
+
+ curMatch = chain[cyclicPos];
+ }
+ while(--count != 0);
+ }
+ #ifdef HASH_ARRAY_2
+ #ifdef HASH_ARRAY_3
+ if (distances[4] < distances[3])
+ distances[3] = distances[4];
+ #endif
+ if (distances[3] < distances[2])
+ distances[2] = distances[3];
+ #endif
+ return maxLen;
+}
+
+STDMETHODIMP_(void) CMatchFinderHC::DummyLongestMatch()
+{
+ if (_streamPos - _pos < kNumHashBytes)
+ return;
+
+ Byte *cur = _buffer + _pos;
+
+ #ifdef HASH_ARRAY_2
+ UInt32 hash2Value;
+ #ifdef HASH_ARRAY_3
+ UInt32 hash3Value;
+ UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
+ _hash[kHash3Offset + hash3Value] = _pos;
+ #else
+ UInt32 hashValue = Hash(cur, hash2Value);
+ #endif
+ _hash[kHash2Offset + hash2Value] = _pos;
+ #else
+ UInt32 hashValue = Hash(cur);
+ #endif
+
+ _hash[kHashSizeSum + _cyclicBufferPos] = _hash[hashValue];
+ _hash[hashValue] = _pos;
+}
+
+void CMatchFinderHC::Normalize()
+{
+ UInt32 subValue = _pos - _cyclicBufferSize;
+ CIndex *items = _hash;
+ UInt32 numItems = kHashSizeSum + _cyclicBufferSize;
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ value = kEmptyHashValue;
+ else
+ value -= subValue;
+ items[i] = value;
+ }
+ ReduceOffsets(subValue);
+}
+
+STDMETHODIMP CMatchFinderHC::MovePos()
+{
+ if (++_cyclicBufferPos == _cyclicBufferSize)
+ _cyclicBufferPos = 0;
+ RINOK(CLZInWindow::MovePos());
+ if (_pos == kMaxValForNormalize)
+ Normalize();
+ return S_OK;
+}
+
+STDMETHODIMP_(Byte) CMatchFinderHC::GetIndexByte(Int32 index)
+ { return CLZInWindow::GetIndexByte(index); }
+
+STDMETHODIMP_(UInt32) CMatchFinderHC::GetMatchLen(Int32 index,
+ UInt32 back, UInt32 limit)
+ { return CLZInWindow::GetMatchLen(index, back, limit); }
+
+STDMETHODIMP_(UInt32) CMatchFinderHC::GetNumAvailableBytes()
+ { return CLZInWindow::GetNumAvailableBytes(); }
+
+STDMETHODIMP_(const Byte *) CMatchFinderHC::GetPointerToCurrentPos()
+ { return CLZInWindow::GetPointerToCurrentPos(); }
+
+// IMatchFinderSetCallback
+STDMETHODIMP CMatchFinderHC::SetCallback(IMatchFinderCallback *callback)
+{
+ m_Callback = callback;
+ return S_OK;
+}
+
+void CMatchFinderHC::BeforeMoveBlock()
+{
+ if (m_Callback)
+ m_Callback->BeforeChangingBufferPos();
+ CLZInWindow::BeforeMoveBlock();
+}
+
+void CMatchFinderHC::AfterMoveBlock()
+{
+ if (m_Callback)
+ m_Callback->AfterChangingBufferPos();
+ CLZInWindow::AfterMoveBlock();
+}
+
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/IMatchFinder.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/IMatchFinder.h
new file mode 100644
index 00000000..1d9c88f2
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/IMatchFinder.h
@@ -0,0 +1,63 @@
+// MatchFinders/IMatchFinder.h
+
+#ifndef __IMATCHFINDER_H
+#define __IMATCHFINDER_H
+
+// {23170F69-40C1-278A-0000-000200010000}
+DEFINE_GUID(IID_IInWindowStream,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000")
+IInWindowStream: public IUnknown
+{
+ STDMETHOD(Init)(ISequentialInStream *inStream) PURE;
+ STDMETHOD_(void, ReleaseStream)() PURE;
+ STDMETHOD(MovePos)() PURE;
+ STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE;
+ STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE;
+ STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE;
+ STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE;
+};
+
+// {23170F69-40C1-278A-0000-000200020000}
+DEFINE_GUID(IID_IMatchFinder,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000")
+IMatchFinder: public IInWindowStream
+{
+ STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE;
+ STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances) PURE;
+ STDMETHOD_(void, DummyLongestMatch)() PURE;
+};
+
+// {23170F69-40C1-278A-0000-000200020100}
+DEFINE_GUID(IID_IMatchFinderCallback,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100")
+IMatchFinderCallback: public IUnknown
+{
+ STDMETHOD(BeforeChangingBufferPos)() PURE;
+ STDMETHOD(AfterChangingBufferPos)() PURE;
+};
+
+// {23170F69-40C1-278A-0000-000200020200}
+DEFINE_GUID(IID_IMatchFinderSetCallback,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020200")
+IMatchFinderSetCallback: public IUnknown
+{
+ STDMETHOD(SetCallback)(IMatchFinderCallback *callback) PURE;
+};
+
+/*
+// {23170F69-40C1-278A-0000-000200030000}
+DEFINE_GUID(IID_IInitMatchFinder,
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000200030000")
+IMatchFinderInit: public IUnknown
+{
+ STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder) PURE;
+};
+*/
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.cpp
new file mode 100644
index 00000000..a7b7a387
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.cpp
@@ -0,0 +1,102 @@
+// LZInWindow.cpp
+
+#include "StdAfx.h"
+
+#include "LZInWindow.h"
+#include "../../../Common/MyCom.h"
+#include "../../../Common/Alloc.h"
+
+void CLZInWindow::Free()
+{
+ ::BigFree(_bufferBase);
+ _bufferBase = 0;
+}
+
+bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
+{
+ _keepSizeBefore = keepSizeBefore;
+ _keepSizeAfter = keepSizeAfter;
+ _keepSizeReserv = keepSizeReserv;
+ UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
+ if (_bufferBase == 0 || _blockSize != blockSize)
+ {
+ Free();
+ _blockSize = blockSize;
+ if (_blockSize != 0)
+ _bufferBase = (Byte *)::BigAlloc(_blockSize);
+ }
+ _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter;
+ if (_blockSize == 0)
+ return true;
+ return (_bufferBase != 0);
+}
+
+
+HRESULT CLZInWindow::Init(ISequentialInStream *stream)
+{
+ _stream = stream;
+ _buffer = _bufferBase;
+ _pos = 0;
+ _streamPos = 0;
+ _streamEndWasReached = false;
+ return ReadBlock();
+}
+
+/*
+void CLZInWindow::ReleaseStream()
+{
+ _stream.Release();
+}
+*/
+
+///////////////////////////////////////////
+// ReadBlock
+
+// In State:
+// (_buffer + _streamPos) <= (_bufferBase + _blockSize)
+// Out State:
+// _posLimit <= _blockSize - _keepSizeAfter;
+// if(_streamEndWasReached == false):
+// _streamPos >= _pos + _keepSizeAfter
+// _posLimit = _streamPos - _keepSizeAfter;
+// else
+//
+
+HRESULT CLZInWindow::ReadBlock()
+{
+ if(_streamEndWasReached)
+ return S_OK;
+ while(true)
+ {
+ UInt32 size = UInt32(_bufferBase - _buffer) + _blockSize - _streamPos;
+ if(size == 0)
+ return S_OK;
+ UInt32 numReadBytes;
+ RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes));
+ if(numReadBytes == 0)
+ {
+ _posLimit = _streamPos;
+ const Byte *pointerToPostion = _buffer + _posLimit;
+ if(pointerToPostion > _pointerToLastSafePosition)
+ _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer);
+ _streamEndWasReached = true;
+ return S_OK;
+ }
+ _streamPos += numReadBytes;
+ if(_streamPos >= _pos + _keepSizeAfter)
+ {
+ _posLimit = _streamPos - _keepSizeAfter;
+ return S_OK;
+ }
+ }
+}
+
+void CLZInWindow::MoveBlock()
+{
+ BeforeMoveBlock();
+ UInt32 offset = UInt32(_buffer - _bufferBase) + _pos - _keepSizeBefore;
+ UInt32 numBytes = UInt32(_buffer - _bufferBase) + _streamPos - offset;
+ memmove(_bufferBase, _bufferBase + offset, numBytes);
+ _buffer -= offset;
+ AfterMoveBlock();
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.h
new file mode 100644
index 00000000..7dc194f2
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZInWindow.h
@@ -0,0 +1,84 @@
+// LZInWindow.h
+
+#ifndef __LZ_IN_WINDOW_H
+#define __LZ_IN_WINDOW_H
+
+#include "../../IStream.h"
+
+class CLZInWindow
+{
+ Byte *_bufferBase; // pointer to buffer with data
+ ISequentialInStream *_stream;
+ UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
+ bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
+ const Byte *_pointerToLastSafePosition;
+protected:
+ Byte *_buffer; // Pointer to virtual Buffer begin
+ UInt32 _blockSize; // Size of Allocated memory block
+ UInt32 _pos; // offset (from _buffer) of curent byte
+ UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
+ UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
+ UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv
+ UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
+
+ virtual void BeforeMoveBlock() {};
+ virtual void AfterMoveBlock() {};
+ void MoveBlock();
+ virtual HRESULT ReadBlock();
+ void Free();
+public:
+ CLZInWindow(): _bufferBase(0) {}
+ virtual ~CLZInWindow() { Free(); }
+
+ bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter,
+ UInt32 keepSizeReserv = (1<<17));
+
+ HRESULT Init(ISequentialInStream *stream);
+ // void ReleaseStream();
+
+ Byte *GetBuffer() const { return _buffer; }
+
+ const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; }
+
+ HRESULT MovePos()
+ {
+ _pos++;
+ if (_pos > _posLimit)
+ {
+ const Byte *pointerToPostion = _buffer + _pos;
+ if(pointerToPostion > _pointerToLastSafePosition)
+ MoveBlock();
+ return ReadBlock();
+ }
+ else
+ return S_OK;
+ }
+ Byte GetIndexByte(Int32 index)const
+ { return _buffer[(size_t)_pos + index]; }
+
+ // index + limit have not to exceed _keepSizeAfter;
+ UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const
+ {
+ if(_streamEndWasReached)
+ if ((_pos + index) + limit > _streamPos)
+ limit = _streamPos - (_pos + index);
+ distance++;
+ Byte *pby = _buffer + (size_t)_pos + index;
+ UInt32 i;
+ for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++);
+ return i;
+ }
+
+ UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; }
+
+ void ReduceOffsets(Int32 subValue)
+ {
+ _buffer += subValue;
+ _posLimit -= subValue;
+ _pos -= subValue;
+ _streamPos -= subValue;
+ }
+
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp
new file mode 100644
index 00000000..329a7db3
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp
@@ -0,0 +1,17 @@
+// LZOutWindow.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/Alloc.h"
+#include "LZOutWindow.h"
+
+void CLZOutWindow::Init(bool solid)
+{
+ if(!solid)
+ COutBuffer::Init();
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = S_OK;
+ #endif
+}
+
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.h
new file mode 100644
index 00000000..ba38c5e2
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/LZOutWindow.h
@@ -0,0 +1,64 @@
+// LZOutWindow.h
+
+#ifndef __LZ_OUT_WINDOW_H
+#define __LZ_OUT_WINDOW_H
+
+#include "../../IStream.h"
+#include "../../Common/OutBuffer.h"
+
+/*
+#ifndef _NO_EXCEPTIONS
+class CLZOutWindowException
+{
+public:
+ HRESULT ErrorCode;
+ CLZOutWindowException(HRESULT errorCode): ErrorCode(errorCode) {}
+};
+#endif
+*/
+typedef COutBufferException CLZOutWindowException;
+
+class CLZOutWindow: public COutBuffer
+{
+public:
+ void Init(bool solid = false);
+
+ // distance >= 0, len > 0,
+ bool CopyBlock(UInt32 distance, UInt32 len)
+ {
+ UInt32 pos = _pos - distance - 1;
+ if (pos >= _bufferSize)
+ {
+ if (!_overDict)
+ return false;
+ pos += _bufferSize;
+ }
+ do
+ {
+ if (pos == _bufferSize)
+ pos = 0;
+ _buffer[_pos++] = _buffer[pos++];
+ if (_pos == _limitPos)
+ FlushWithCheck();
+ }
+ while(--len != 0);
+ return true;
+ }
+
+ void PutByte(Byte b)
+ {
+ _buffer[_pos++] = b;
+ if (_pos == _limitPos)
+ FlushWithCheck();
+ }
+
+ Byte GetByte(UInt32 distance) const
+ {
+ UInt32 pos = _pos - distance - 1;
+ if (pos >= _bufferSize)
+ pos += _bufferSize;
+ return _buffer[pos];
+ }
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat.h
new file mode 100644
index 00000000..2d0ce6d0
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat.h
@@ -0,0 +1,318 @@
+// Pat.h
+
+// #ifndef __PATRICIA__H
+// #define __PATRICIA__H
+
+#include "../../../../Common/MyCom.h"
+#include "../../../../Common/Types.h"
+#include "../LZInWindow.h"
+
+namespace PAT_NAMESPACE {
+
+struct CNode;
+
+typedef CNode *CNodePointer;
+
+// #define __AUTO_REMOVE
+
+// #define __NODE_4_BITS
+// #define __NODE_3_BITS
+// #define __NODE_2_BITS
+// #define __NODE_2_BITS_PADDING
+
+// #define __HASH_3
+
+
+typedef UInt32 CIndex;
+
+#ifdef __NODE_4_BITS
+ typedef UInt32 CIndex2;
+ typedef UInt32 CSameBitsType;
+#else
+#ifdef __NODE_3_BITS
+ typedef UInt32 CIndex2;
+ typedef UInt32 CSameBitsType;
+#else
+
+ typedef UInt32 CIndex;
+ typedef UInt32 CSameBitsType;
+
+ typedef CIndex CIndex2;
+#endif
+#endif
+
+const UInt32 kNumBitsInIndex = sizeof(CIndex) * 8;
+const UInt32 kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1);
+// don't change kMatchStartValue definition, since it is used in
+// PatMain.h:
+
+typedef CIndex CMatchPointer;
+
+const UInt32 kDescendantEmptyValue = kMatchStartValue - 1;
+
+union CDescendant
+{
+ CIndex NodePointer;
+ CMatchPointer MatchPointer;
+ bool IsEmpty() const { return NodePointer == kDescendantEmptyValue; }
+ bool IsNode() const { return NodePointer < kDescendantEmptyValue; }
+ bool IsMatch() const { return NodePointer > kDescendantEmptyValue; }
+ void MakeEmpty() { NodePointer = kDescendantEmptyValue; }
+};
+
+#undef MY_BYTE_SIZE
+
+#ifdef __NODE_4_BITS
+ #define MY_BYTE_SIZE 8
+ const UInt32 kNumSubBits = 4;
+#else
+#ifdef __NODE_3_BITS
+ #define MY_BYTE_SIZE 9
+ const UInt32 kNumSubBits = 3;
+#else
+ #define MY_BYTE_SIZE 8
+ #ifdef __NODE_2_BITS
+ const UInt32 kNumSubBits = 2;
+ #else
+ const UInt32 kNumSubBits = 1;
+ #endif
+#endif
+#endif
+
+const UInt32 kNumSubNodes = 1 << kNumSubBits;
+const UInt32 kSubNodesMask = kNumSubNodes - 1;
+
+struct CNode
+{
+ CIndex2 LastMatch;
+ CSameBitsType NumSameBits;
+ union
+ {
+ CDescendant Descendants[kNumSubNodes];
+ UInt32 NextFreeNode;
+ };
+ #ifdef __NODE_2_BITS
+ #ifdef __NODE_2_BITS_PADDING
+ UInt32 Padding[2];
+ #endif
+ #endif
+};
+
+#undef kIDNumBitsByte
+#undef kIDNumBitsString
+
+#ifdef __NODE_4_BITS
+ #define kIDNumBitsByte 0x30
+ #define kIDNumBitsString TEXT("4")
+#else
+#ifdef __NODE_3_BITS
+ #define kIDNumBitsByte 0x20
+ #define kIDNumBitsString TEXT("3")
+#else
+#ifdef __NODE_2_BITS
+ #define kIDNumBitsByte 0x10
+ #define kIDNumBitsString TEXT("2")
+#else
+ #define kIDNumBitsByte 0x00
+ #define kIDNumBitsString TEXT("1")
+#endif
+#endif
+#endif
+
+#undef kIDManualRemoveByte
+#undef kIDManualRemoveString
+
+#ifdef __AUTO_REMOVE
+ #define kIDManualRemoveByte 0x00
+ #define kIDManualRemoveString TEXT("")
+#else
+ #define kIDManualRemoveByte 0x08
+ #define kIDManualRemoveString TEXT("R")
+#endif
+
+#undef kIDHash3Byte
+#undef kIDHash3String
+
+#ifdef __HASH_3
+ #define kIDHash3Byte 0x04
+ #define kIDHash3String TEXT("H")
+#else
+ #define kIDHash3Byte 0x00
+ #define kIDHash3String TEXT("")
+#endif
+
+#undef kIDUse3BytesByte
+#undef kIDUse3BytesString
+
+#define kIDUse3BytesByte 0x00
+#define kIDUse3BytesString TEXT("")
+
+#undef kIDPaddingByte
+#undef kIDPaddingString
+
+#ifdef __NODE_2_BITS_PADDING
+ #define kIDPaddingByte 0x01
+ #define kIDPaddingString TEXT("P")
+#else
+ #define kIDPaddingByte 0x00
+ #define kIDPaddingString TEXT("")
+#endif
+
+
+// #undef kIDString
+// #define kIDString TEXT("Compress.MatchFinderPat") kIDNumBitsString kIDManualRemoveString kIDUse3BytesString kIDPaddingString kIDHash3String
+
+// {23170F69-40C1-278C-01XX-0000000000}
+
+DEFINE_GUID(PAT_CLSID,
+0x23170F69, 0x40C1, 0x278C, 0x01,
+kIDNumBitsByte |
+kIDManualRemoveByte | kIDHash3Byte | kIDUse3BytesByte | kIDPaddingByte,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+// III(PAT_NAMESPACE)
+
+class CPatricia:
+ public IMatchFinder,
+ public IMatchFinderSetCallback,
+ public CMyUnknownImp,
+ CLZInWindow
+{
+ MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
+
+ STDMETHOD(Init)(ISequentialInStream *aStream);
+ STDMETHOD_(void, ReleaseStream)();
+ STDMETHOD(MovePos)();
+ STDMETHOD_(Byte, GetIndexByte)(Int32 index);
+ STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
+ STDMETHOD_(UInt32, GetNumAvailableBytes)();
+ STDMETHOD(Create)(UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen,
+ UInt32 keepAddBufferAfter);
+ STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
+ STDMETHOD_(void, DummyLongestMatch)();
+ STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
+
+ void FreeMemory();
+public:
+ CPatricia();
+ ~CPatricia();
+
+ UInt32 _sizeHistory;
+ UInt32 _matchMaxLen;
+
+ CDescendant *m_HashDescendants;
+ #ifdef __HASH_3
+ CDescendant *m_Hash2Descendants;
+ #endif
+
+ CNode *m_Nodes;
+
+ UInt32 m_FreeNode;
+ UInt32 m_FreeNodeMax;
+
+ #ifdef __AUTO_REMOVE
+ UInt32 m_NumUsedNodes;
+ UInt32 m_NumNodes;
+ #else
+ bool m_SpecialRemoveMode;
+ #endif
+
+ bool m_SpecialMode;
+ UInt32 m_NumNotChangedCycles;
+ UInt32 *m_TmpBacks;
+
+ CMyComPtr<IMatchFinderCallback> m_Callback;
+
+ virtual void BeforeMoveBlock();
+ virtual void AfterMoveBlock();
+
+ // IMatchFinderSetCallback
+ STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
+
+ void ChangeLastMatch(UInt32 hashValue);
+
+ #ifdef __AUTO_REMOVE
+ void TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos);
+ void TestRemoveNodes();
+ void RemoveNode(UInt32 index);
+ void TestRemoveAndNormalizeDescendant(CDescendant &descendant,
+ UInt32 limitPos, UInt32 subValue);
+ void TestRemoveNodesAndNormalize();
+ #else
+ void NormalizeDescendant(CDescendant &descendant, UInt32 subValue);
+ void Normalize();
+ void RemoveMatch();
+ #endif
+private:
+ void AddInternalNode(CNodePointer aNode, CIndex *aNodePointerPointer,
+ Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos)
+ {
+ while((aByteXOR & kSubNodesMask) == 0)
+ {
+ aByteXOR >>= kNumSubBits;
+ aByte >>= kNumSubBits;
+ aNumSameBits -= kNumSubBits;
+ }
+ // Insert New Node
+ CNodePointer aNewNode = &m_Nodes[m_FreeNode];
+ UInt32 aNodeIndex = *aNodePointerPointer;
+ *aNodePointerPointer = m_FreeNode;
+ m_FreeNode = aNewNode->NextFreeNode;
+ #ifdef __AUTO_REMOVE
+ m_NumUsedNodes++;
+ #endif
+ if (m_FreeNode > m_FreeNodeMax)
+ {
+ m_FreeNodeMax = m_FreeNode;
+ m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
+ }
+
+ UInt32 aBitsNew = aByte & kSubNodesMask;
+ UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask;
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue;
+ aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue;
+ aNewNode->Descendants[aBitsOld].NodePointer = aNodeIndex;
+ aNewNode->NumSameBits = CSameBitsType(aNode->NumSameBits - aNumSameBits);
+ aNewNode->LastMatch = aPos;
+
+ aNode->NumSameBits = CSameBitsType(aNumSameBits - kNumSubBits);
+ }
+
+ void AddLeafNode(CNodePointer aNode, Byte aByte, Byte aByteXOR,
+ UInt32 aNumSameBits, UInt32 aPos, UInt32 aDescendantIndex)
+ {
+ for(;(aByteXOR & kSubNodesMask) == 0; aNumSameBits += kNumSubBits)
+ {
+ aByte >>= kNumSubBits;
+ aByteXOR >>= kNumSubBits;
+ }
+ UInt32 aNewNodeIndex = m_FreeNode;
+ CNodePointer aNewNode = &m_Nodes[m_FreeNode];
+ m_FreeNode = aNewNode->NextFreeNode;
+ #ifdef __AUTO_REMOVE
+ m_NumUsedNodes++;
+ #endif
+ if (m_FreeNode > m_FreeNodeMax)
+ {
+ m_FreeNodeMax = m_FreeNode;
+ m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
+ }
+
+ UInt32 aBitsNew = (aByte & kSubNodesMask);
+ UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask;
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue;
+ aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue;
+ aNewNode->Descendants[aBitsOld].MatchPointer =
+ aNode->Descendants[aDescendantIndex].MatchPointer;
+ aNewNode->NumSameBits = CSameBitsType(aNumSameBits);
+ aNewNode->LastMatch = aPos;
+ aNode->Descendants[aDescendantIndex].NodePointer = aNewNodeIndex;
+ }
+};
+
+}
+
+// #endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2.h
new file mode 100644
index 00000000..0c97164d
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2.h
@@ -0,0 +1,22 @@
+// Pat2.h
+
+#ifndef __PAT2__H
+#define __PAT2__H
+
+#undef PAT_CLSID
+#define PAT_CLSID CLSID_CMatchFinderPat2
+
+#undef PAT_NAMESPACE
+#define PAT_NAMESPACE NPat2
+
+#define __AUTO_REMOVE
+#define __NODE_2_BITS
+
+#include "Pat.h"
+#include "PatMain.h"
+
+#undef __AUTO_REMOVE
+#undef __NODE_2_BITS
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2H.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2H.h
new file mode 100644
index 00000000..c3a374fa
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2H.h
@@ -0,0 +1,24 @@
+// Pat2H.h
+
+#ifndef __PAT2H__H
+#define __PAT2H__H
+
+#undef PAT_CLSID
+#define PAT_CLSID CLSID_CMatchFinderPat2H
+
+#undef PAT_NAMESPACE
+#define PAT_NAMESPACE NPat2H
+
+#define __AUTO_REMOVE
+#define __NODE_2_BITS
+#define __HASH_3
+
+#include "Pat.h"
+#include "PatMain.h"
+
+#undef __AUTO_REMOVE
+#undef __NODE_2_BITS
+#undef __HASH_3
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2R.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2R.h
new file mode 100644
index 00000000..2c6267e8
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat2R.h
@@ -0,0 +1,20 @@
+// Pat2R.h
+
+#ifndef __PAT2R__H
+#define __PAT2R__H
+
+#undef PAT_CLSID
+#define PAT_CLSID CLSID_CMatchFinderPat2R
+
+#undef PAT_NAMESPACE
+#define PAT_NAMESPACE NPat2R
+
+#define __NODE_2_BITS
+
+#include "Pat.h"
+#include "PatMain.h"
+
+#undef __NODE_2_BITS
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat3H.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat3H.h
new file mode 100644
index 00000000..96bdccd4
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat3H.h
@@ -0,0 +1,24 @@
+// Pat3H.h
+
+#ifndef __PAT3H__H
+#define __PAT3H__H
+
+#undef PAT_CLSID
+#define PAT_CLSID CLSID_CMatchFinderPat3H
+
+#undef PAT_NAMESPACE
+#define PAT_NAMESPACE NPat3H
+
+#define __AUTO_REMOVE
+#define __NODE_3_BITS
+#define __HASH_3
+
+#include "Pat.h"
+#include "PatMain.h"
+
+#undef __AUTO_REMOVE
+#undef __NODE_3_BITS
+#undef __HASH_3
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat4H.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat4H.h
new file mode 100644
index 00000000..ff5fdbf4
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/Pat4H.h
@@ -0,0 +1,24 @@
+// Pat4H.h
+
+#ifndef __PAT4H__H
+#define __PAT4H__H
+
+#undef PAT_CLSID
+#define PAT_CLSID CLSID_CMatchFinderPat4H
+
+#undef PAT_NAMESPACE
+#define PAT_NAMESPACE NPat4H
+
+#define __AUTO_REMOVE
+#define __NODE_4_BITS
+#define __HASH_3
+
+#include "Pat.h"
+#include "PatMain.h"
+
+#undef __AUTO_REMOVE
+#undef __NODE_4_BITS
+#undef __HASH_3
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/PatMain.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/PatMain.h
new file mode 100644
index 00000000..028f16ba
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/Patricia/PatMain.h
@@ -0,0 +1,989 @@
+// PatMain.h
+
+#include "../../../../Common/Defs.h"
+#include "../../../../Common/Alloc.h"
+
+namespace PAT_NAMESPACE {
+
+STDMETHODIMP CPatricia::SetCallback(IMatchFinderCallback *callback)
+{
+ m_Callback = callback;
+ return S_OK;
+}
+
+void CPatricia::BeforeMoveBlock()
+{
+ if (m_Callback)
+ m_Callback->BeforeChangingBufferPos();
+ CLZInWindow::BeforeMoveBlock();
+}
+
+void CPatricia::AfterMoveBlock()
+{
+ if (m_Callback)
+ m_Callback->AfterChangingBufferPos();
+ CLZInWindow::AfterMoveBlock();
+}
+
+const UInt32 kMatchStartValue2 = 2;
+const UInt32 kDescendantEmptyValue2 = kMatchStartValue2 - 1;
+const UInt32 kDescendantsNotInitilized2 = kDescendantEmptyValue2 - 1;
+
+#ifdef __HASH_3
+
+static const UInt32 kNumHashBytes = 3;
+static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
+
+static const UInt32 kNumHash2Bytes = 2;
+static const UInt32 kHash2Size = 1 << (8 * kNumHash2Bytes);
+static const UInt32 kPrevHashSize = kNumHash2Bytes;
+
+#else
+
+static const UInt32 kNumHashBytes = 2;
+static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
+static const UInt32 kPrevHashSize = 0;
+
+#endif
+
+
+CPatricia::CPatricia():
+ m_HashDescendants(0),
+ #ifdef __HASH_3
+ m_Hash2Descendants(0),
+ #endif
+ m_Nodes(0),
+ m_TmpBacks(0)
+{
+}
+
+CPatricia::~CPatricia()
+{
+ FreeMemory();
+}
+
+void CPatricia::FreeMemory()
+{
+ MyFree(m_TmpBacks);
+ m_TmpBacks = 0;
+
+ ::BigFree(m_Nodes);
+ m_Nodes = 0;
+
+ ::BigFree(m_HashDescendants);
+ m_HashDescendants = 0;
+
+ #ifdef __HASH_3
+
+ ::BigFree(m_Hash2Descendants);
+ m_Hash2Descendants = 0;
+
+ CLZInWindow::Free();
+
+ #endif
+}
+
+STDMETHODIMP CPatricia::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
+{
+ FreeMemory();
+ int kNumBitsInNumSameBits = sizeof(CSameBitsType) * 8;
+ if (kNumBitsInNumSameBits < 32 && ((matchMaxLen * MY_BYTE_SIZE) > ((UInt32)1 << kNumBitsInNumSameBits)))
+ return E_INVALIDARG;
+
+ const UInt32 kAlignMask = (1 << 16) - 1;
+ UInt32 windowReservSize = historySize;
+ windowReservSize += kAlignMask;
+ windowReservSize &= ~(kAlignMask);
+
+ const UInt32 kMinReservSize = (1 << 19);
+ if (windowReservSize < kMinReservSize)
+ windowReservSize = kMinReservSize;
+ windowReservSize += 256;
+
+ if (!CLZInWindow::Create(historySize + keepAddBufferBefore,
+ matchMaxLen + keepAddBufferAfter, windowReservSize))
+ return E_OUTOFMEMORY;
+
+ _sizeHistory = historySize;
+ _matchMaxLen = matchMaxLen;
+ m_HashDescendants = (CDescendant *)BigAlloc(kHashSize * sizeof(CDescendant));
+ if (m_HashDescendants == 0)
+ {
+ FreeMemory();
+ return E_OUTOFMEMORY;
+ }
+
+ #ifdef __HASH_3
+ m_Hash2Descendants = (CDescendant *)BigAlloc(kHash2Size * sizeof(CDescendant));
+ if (m_Hash2Descendants == 0)
+ {
+ FreeMemory();
+ return E_OUTOFMEMORY;
+ }
+ #endif
+
+ #ifdef __AUTO_REMOVE
+
+ #ifdef __HASH_3
+ m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 19);
+ #else
+ m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 10);
+ #endif
+
+ #else
+
+ UInt32 m_NumNodes = historySize;
+
+ #endif
+
+ const UInt32 kMaxNumNodes = UInt32(1) << (sizeof(CIndex) * 8 - 1);
+ if (m_NumNodes + 32 > kMaxNumNodes)
+ return E_INVALIDARG;
+
+ // m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 2) * sizeof(CNode));
+ m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 12) * sizeof(CNode));
+ if (m_Nodes == 0)
+ {
+ FreeMemory();
+ return E_OUTOFMEMORY;
+ }
+
+ m_TmpBacks = (UInt32 *)MyAlloc((_matchMaxLen + 1) * sizeof(UInt32));
+ if (m_TmpBacks == 0)
+ {
+ FreeMemory();
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CPatricia::Init(ISequentialInStream *aStream)
+{
+ RINOK(CLZInWindow::Init(aStream));
+
+ // memset(m_HashDescendants, 0xFF, kHashSize * sizeof(m_HashDescendants[0]));
+
+ #ifdef __HASH_3
+ for (UInt32 i = 0; i < kHash2Size; i++)
+ m_Hash2Descendants[i].MatchPointer = kDescendantsNotInitilized2;
+ #else
+ for (UInt32 i = 0; i < kHashSize; i++)
+ m_HashDescendants[i].MakeEmpty();
+ #endif
+
+ m_Nodes[0].NextFreeNode = 1;
+ m_FreeNode = 0;
+ m_FreeNodeMax = 0;
+ #ifdef __AUTO_REMOVE
+ m_NumUsedNodes = 0;
+ #else
+ m_SpecialRemoveMode = false;
+ #endif
+ m_SpecialMode = false;
+ return S_OK;
+}
+
+STDMETHODIMP_(void) CPatricia::ReleaseStream()
+{
+ // CLZInWindow::ReleaseStream();
+}
+
+// pos = _pos + kNumHashBytes
+// fullCurrentLimit = currentLimit + kNumHashBytes
+// fullMatchLen = matchLen + kNumHashBytes
+
+void CPatricia::ChangeLastMatch(UInt32 hashValue)
+{
+ UInt32 pos = _pos + kNumHashBytes - 1;
+ UInt32 descendantIndex;
+ const Byte *currentBytePointer = _buffer + pos;
+ UInt32 numLoadedBits = 0;
+ Byte curByte = 0; // = 0 to disable warning of GCC
+ CNodePointer node = &m_Nodes[m_HashDescendants[hashValue].NodePointer];
+
+ while(true)
+ {
+ UInt32 numSameBits = node->NumSameBits;
+ if(numSameBits > 0)
+ {
+ if (numLoadedBits < numSameBits)
+ {
+ numSameBits -= numLoadedBits;
+ currentBytePointer += (numSameBits / MY_BYTE_SIZE);
+ numSameBits %= MY_BYTE_SIZE;
+ curByte = *currentBytePointer++;
+ numLoadedBits = MY_BYTE_SIZE;
+ }
+ curByte >>= numSameBits;
+ numLoadedBits -= numSameBits;
+ }
+ if(numLoadedBits == 0)
+ {
+ curByte = *currentBytePointer++;
+ numLoadedBits = MY_BYTE_SIZE;
+ }
+ descendantIndex = (curByte & kSubNodesMask);
+ node->LastMatch = pos;
+ numLoadedBits -= kNumSubBits;
+ curByte >>= kNumSubBits;
+ if(node->Descendants[descendantIndex].IsNode())
+ node = &m_Nodes[node->Descendants[descendantIndex].NodePointer];
+ else
+ break;
+ }
+ node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
+}
+
+UInt32 CPatricia::GetLongestMatch(UInt32 *distances)
+{
+ UInt32 fullCurrentLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ fullCurrentLimit = _matchMaxLen;
+ else
+ {
+ fullCurrentLimit = _streamPos - _pos;
+ if(fullCurrentLimit < kNumHashBytes)
+ return 0;
+ }
+ UInt32 pos = _pos + kNumHashBytes;
+
+ #ifdef __HASH_3
+ UInt32 hash2Value = ((UInt32(_buffer[_pos])) << 8) | _buffer[_pos + 1];
+ UInt32 hashValue = (hash2Value << 8) | _buffer[_pos + 2];
+ CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value];
+ CDescendant &hashDescendant = m_HashDescendants[hashValue];
+ if(hash2Descendant.MatchPointer <= kDescendantEmptyValue2)
+ {
+ if(hash2Descendant.MatchPointer == kDescendantsNotInitilized2)
+ {
+ UInt32 base = hashValue & 0xFFFF00;
+ for (UInt32 i = 0; i < 0x100; i++)
+ m_HashDescendants[base + i].MakeEmpty();
+ }
+ hash2Descendant.MatchPointer = pos + kMatchStartValue2;
+ hashDescendant.MatchPointer = pos + kMatchStartValue;
+ return 0;
+ }
+
+ distances[kNumHash2Bytes] = pos - (hash2Descendant.MatchPointer - kMatchStartValue2) - 1;
+ hash2Descendant.MatchPointer = pos + kMatchStartValue2;
+ #ifdef __AUTO_REMOVE
+ if (distances[kNumHash2Bytes] >= _sizeHistory)
+ {
+ if (hashDescendant.IsNode())
+ RemoveNode(hashDescendant.NodePointer);
+ hashDescendant.MatchPointer = pos + kMatchStartValue;
+ return 0;
+ }
+ #endif
+ if (fullCurrentLimit == kNumHash2Bytes)
+ return kNumHash2Bytes;
+
+ #else
+ UInt32 hashValue = UInt32(GetIndexByte(1)) | (UInt32(GetIndexByte(0)) << 8);
+ CDescendant &hashDescendant = m_HashDescendants[hashValue];
+ #endif
+
+
+ if(m_SpecialMode)
+ {
+ if(hashDescendant.IsMatch())
+ m_NumNotChangedCycles = 0;
+ if(m_NumNotChangedCycles >= _sizeHistory - 1)
+ {
+ ChangeLastMatch(hashValue);
+ m_NumNotChangedCycles = 0;
+ }
+ if(GetIndexByte(fullCurrentLimit - 1) == GetIndexByte(fullCurrentLimit - 2))
+ {
+ if(hashDescendant.IsMatch())
+ hashDescendant.MatchPointer = pos + kMatchStartValue;
+ else
+ m_NumNotChangedCycles++;
+ for(UInt32 i = kNumHashBytes; i <= fullCurrentLimit; i++)
+ distances[i] = 0;
+ return fullCurrentLimit;
+ }
+ else if(m_NumNotChangedCycles > 0)
+ ChangeLastMatch(hashValue);
+ m_SpecialMode = false;
+ }
+
+ if(hashDescendant.IsEmpty())
+ {
+ hashDescendant.MatchPointer = pos + kMatchStartValue;
+ return kPrevHashSize;
+ }
+
+ UInt32 currentLimit = fullCurrentLimit - kNumHashBytes;
+
+ if(hashDescendant.IsMatch())
+ {
+ CMatchPointer matchPointer = hashDescendant.MatchPointer;
+ UInt32 backReal = pos - (matchPointer - kMatchStartValue);
+ UInt32 back = backReal - 1;
+ #ifdef __AUTO_REMOVE
+ if (back >= _sizeHistory)
+ {
+ hashDescendant.MatchPointer = pos + kMatchStartValue;
+ return kPrevHashSize;
+ }
+ #endif
+
+ UInt32 matchLen;
+ distances += kNumHashBytes;
+ Byte *buffer = _buffer + pos;
+ for(matchLen = 0; true; matchLen++)
+ {
+ *distances++ = back;
+ if (matchLen == currentLimit)
+ {
+ hashDescendant.MatchPointer = pos + kMatchStartValue;
+ return kNumHashBytes + matchLen;
+ }
+ if (buffer[matchLen] != buffer[(size_t)matchLen - backReal])
+ break;
+ }
+
+ // UInt32 matchLen = GetMatchLen(kNumHashBytes, back, currentLimit);
+
+ UInt32 fullMatchLen = matchLen + kNumHashBytes;
+ hashDescendant.NodePointer = m_FreeNode;
+ CNodePointer node = &m_Nodes[m_FreeNode];
+ m_FreeNode = node->NextFreeNode;
+ #ifdef __AUTO_REMOVE
+ m_NumUsedNodes++;
+ #endif
+ if (m_FreeNode > m_FreeNodeMax)
+ {
+ m_FreeNodeMax = m_FreeNode;
+ m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
+ }
+
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ node->Descendants[i].NodePointer = kDescendantEmptyValue;
+ node->LastMatch = pos;
+
+ Byte byteNew = GetIndexByte(fullMatchLen);
+ Byte byteOld = GetIndexByte(fullMatchLen - backReal);
+ Byte bitsNew, bitsOld;
+ UInt32 numSameBits = matchLen * MY_BYTE_SIZE;
+ while (true)
+ {
+ bitsNew = (byteNew & kSubNodesMask);
+ bitsOld = (byteOld & kSubNodesMask);
+ if(bitsNew != bitsOld)
+ break;
+ byteNew >>= kNumSubBits;
+ byteOld >>= kNumSubBits;
+ numSameBits += kNumSubBits;
+ }
+ node->NumSameBits = CSameBitsType(numSameBits);
+ node->Descendants[bitsNew].MatchPointer = pos + kMatchStartValue;
+ node->Descendants[bitsOld].MatchPointer = matchPointer;
+ return fullMatchLen;
+ }
+ const Byte *baseCurrentBytePointer = _buffer + pos;
+ const Byte *currentBytePointer = baseCurrentBytePointer;
+ UInt32 numLoadedBits = 0;
+ Byte curByte = 0;
+ CIndex *nodePointerPointer = &hashDescendant.NodePointer;
+ CNodePointer node = &m_Nodes[*nodePointerPointer];
+ distances += kNumHashBytes;
+ const Byte *bytePointerLimit = baseCurrentBytePointer + currentLimit;
+ const Byte *currentAddingOffset = _buffer;
+
+ #ifdef __AUTO_REMOVE
+ UInt32 lowPos;
+ if (pos > _sizeHistory)
+ lowPos = pos - _sizeHistory;
+ else
+ lowPos = 0;
+ #endif
+
+ while(true)
+ {
+ #ifdef __AUTO_REMOVE
+ if (node->LastMatch < lowPos)
+ {
+ RemoveNode(*nodePointerPointer);
+ *nodePointerPointer = pos + kMatchStartValue;
+ if (currentBytePointer == baseCurrentBytePointer)
+ return kPrevHashSize;
+ return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
+ }
+ #endif
+ if(numLoadedBits == 0)
+ {
+ *distances++ = pos - node->LastMatch - 1;
+ if(currentBytePointer >= bytePointerLimit)
+ {
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ node->Descendants[i].MatchPointer = pos + kMatchStartValue;
+ node->LastMatch = pos;
+ node->NumSameBits = 0;
+ return fullCurrentLimit;
+ }
+ curByte = (*currentBytePointer++);
+ currentAddingOffset++;
+ numLoadedBits = MY_BYTE_SIZE;
+ }
+ UInt32 numSameBits = node->NumSameBits;
+ if(numSameBits > 0)
+ {
+ Byte byteXOR = ((*(currentAddingOffset + node->LastMatch -1)) >>
+ (MY_BYTE_SIZE - numLoadedBits)) ^ curByte;
+ while(numLoadedBits <= numSameBits)
+ {
+ if(byteXOR != 0)
+ {
+ AddInternalNode(node, nodePointerPointer, curByte, byteXOR,
+ numSameBits, pos);
+ return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
+ }
+ *distances++ = pos - node->LastMatch - 1;
+ numSameBits -= numLoadedBits;
+ if(currentBytePointer >= bytePointerLimit)
+ {
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ node->Descendants[i].MatchPointer = pos + kMatchStartValue;
+ node->LastMatch = pos;
+ node->NumSameBits = CSameBitsType(node->NumSameBits - numSameBits);
+ return fullCurrentLimit;
+ }
+ numLoadedBits = MY_BYTE_SIZE;
+ curByte = (*currentBytePointer++);
+ byteXOR = curByte ^ (*(currentAddingOffset + node->LastMatch));
+ currentAddingOffset++;
+ }
+ if((byteXOR & ((1 << numSameBits) - 1)) != 0)
+ {
+ AddInternalNode(node, nodePointerPointer, curByte, byteXOR,
+ numSameBits, pos);
+ return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
+ }
+ curByte >>= numSameBits;
+ numLoadedBits -= numSameBits;
+ }
+ UInt32 descendantIndex = (curByte & kSubNodesMask);
+ numLoadedBits -= kNumSubBits;
+ nodePointerPointer = &node->Descendants[descendantIndex].NodePointer;
+ UInt32 nextNodeIndex = *nodePointerPointer;
+ node->LastMatch = pos;
+ if (nextNodeIndex < kDescendantEmptyValue)
+ {
+ curByte >>= kNumSubBits;
+ node = &m_Nodes[nextNodeIndex];
+ }
+ else if (nextNodeIndex == kDescendantEmptyValue)
+ {
+ node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
+ return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
+ }
+ else
+ break;
+ }
+
+ UInt32 descendantIndex = (curByte & kSubNodesMask);
+ curByte >>= kNumSubBits;
+ CMatchPointer matchPointer = node->Descendants[descendantIndex].MatchPointer;
+ CMatchPointer realMatchPointer;
+ realMatchPointer = matchPointer - kMatchStartValue;
+
+ #ifdef __AUTO_REMOVE
+ if (realMatchPointer < lowPos)
+ {
+ node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
+ return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
+ }
+ #endif
+
+ Byte byteXOR;
+ UInt32 numSameBits = 0;
+ if(numLoadedBits != 0)
+ {
+ Byte matchByte = *(currentAddingOffset + realMatchPointer -1);
+ matchByte >>= (MY_BYTE_SIZE - numLoadedBits);
+ byteXOR = matchByte ^ curByte;
+ if(byteXOR != 0)
+ {
+ AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex);
+ return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
+ }
+ numSameBits += numLoadedBits;
+ }
+
+ const Byte *matchBytePointer = _buffer + realMatchPointer +
+ (currentBytePointer - baseCurrentBytePointer);
+ for(; currentBytePointer < bytePointerLimit; numSameBits += MY_BYTE_SIZE)
+ {
+ curByte = (*currentBytePointer++);
+ *distances++ = pos - realMatchPointer - 1;
+ byteXOR = curByte ^ (*matchBytePointer++);
+ if(byteXOR != 0)
+ {
+ AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex);
+ return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1);
+ }
+ }
+ *distances = pos - realMatchPointer - 1;
+ node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
+
+ if(*distances == 0)
+ {
+ m_SpecialMode = true;
+ m_NumNotChangedCycles = 0;
+ }
+ return fullCurrentLimit;
+}
+
+STDMETHODIMP_(void) CPatricia::DummyLongestMatch()
+{
+ GetLongestMatch(m_TmpBacks);
+}
+
+
+// ------------------------------------
+// Remove Match
+
+typedef Byte CRemoveDataWord;
+
+static const int kSizeRemoveDataWordInBits = MY_BYTE_SIZE * sizeof(CRemoveDataWord);
+
+#ifndef __AUTO_REMOVE
+
+void CPatricia::RemoveMatch()
+{
+ if(m_SpecialRemoveMode)
+ {
+ if(GetIndexByte(_matchMaxLen - 1 - _sizeHistory) ==
+ GetIndexByte(_matchMaxLen - _sizeHistory))
+ return;
+ m_SpecialRemoveMode = false;
+ }
+ UInt32 pos = _pos + kNumHashBytes - _sizeHistory;
+
+ #ifdef __HASH_3
+ const Byte *pp = _buffer + _pos - _sizeHistory;
+ UInt32 hash2Value = ((UInt32(pp[0])) << 8) | pp[1];
+ UInt32 hashValue = (hash2Value << 8) | pp[2];
+ CDescendant &hashDescendant = m_HashDescendants[hashValue];
+ CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value];
+ if (hash2Descendant >= kMatchStartValue2)
+ if(hash2Descendant.MatchPointer == pos + kMatchStartValue2)
+ hash2Descendant.MatchPointer = kDescendantEmptyValue2;
+ #else
+ UInt32 hashValue = UInt32(GetIndexByte(1 - _sizeHistory)) |
+ (UInt32(GetIndexByte(0 - _sizeHistory)) << 8);
+ CDescendant &hashDescendant = m_HashDescendants[hashValue];
+ #endif
+
+ if(hashDescendant.IsEmpty())
+ return;
+ if(hashDescendant.IsMatch())
+ {
+ if(hashDescendant.MatchPointer == pos + kMatchStartValue)
+ hashDescendant.MakeEmpty();
+ return;
+ }
+
+ UInt32 descendantIndex;
+ const CRemoveDataWord *currentPointer = (const CRemoveDataWord *)(_buffer + pos);
+ UInt32 numLoadedBits = 0;
+ CRemoveDataWord curWord = 0; // = 0 to disable GCC warning
+
+ CIndex *nodePointerPointer = &hashDescendant.NodePointer;
+
+ CNodePointer node = &m_Nodes[hashDescendant.NodePointer];
+
+ while(true)
+ {
+ if(numLoadedBits == 0)
+ {
+ curWord = *currentPointer++;
+ numLoadedBits = kSizeRemoveDataWordInBits;
+ }
+ UInt32 numSameBits = node->NumSameBits;
+ if(numSameBits > 0)
+ {
+ if (numLoadedBits <= numSameBits)
+ {
+ numSameBits -= numLoadedBits;
+ currentPointer += (numSameBits / kSizeRemoveDataWordInBits);
+ numSameBits %= kSizeRemoveDataWordInBits;
+ curWord = *currentPointer++;
+ numLoadedBits = kSizeRemoveDataWordInBits;
+ }
+ curWord >>= numSameBits;
+ numLoadedBits -= numSameBits;
+ }
+ descendantIndex = (curWord & kSubNodesMask);
+ numLoadedBits -= kNumSubBits;
+ curWord >>= kNumSubBits;
+ UInt32 nextNodeIndex = node->Descendants[descendantIndex].NodePointer;
+ if (nextNodeIndex < kDescendantEmptyValue)
+ {
+ nodePointerPointer = &node->Descendants[descendantIndex].NodePointer;
+ node = &m_Nodes[nextNodeIndex];
+ }
+ else
+ break;
+ }
+ if (node->Descendants[descendantIndex].MatchPointer != pos + kMatchStartValue)
+ {
+ const Byte *currentBytePointer = _buffer + _pos - _sizeHistory;
+ const Byte *currentBytePointerLimit = currentBytePointer + _matchMaxLen;
+ for(;currentBytePointer < currentBytePointerLimit; currentBytePointer++)
+ if(*currentBytePointer != *(currentBytePointer+1))
+ return;
+ m_SpecialRemoveMode = true;
+ return;
+ }
+
+ UInt32 numNodes = 0, numMatches = 0;
+
+ UInt32 i;
+ for (i = 0; i < kNumSubNodes; i++)
+ {
+ UInt32 nodeIndex = node->Descendants[i].NodePointer;
+ if (nodeIndex < kDescendantEmptyValue)
+ numNodes++;
+ else if (nodeIndex > kDescendantEmptyValue)
+ numMatches++;
+ }
+ numMatches -= 1;
+ if (numNodes + numMatches > 1)
+ {
+ node->Descendants[descendantIndex].MakeEmpty();
+ return;
+ }
+ if(numNodes == 1)
+ {
+ UInt32 i;
+ for (i = 0; i < kNumSubNodes; i++)
+ if (node->Descendants[i].IsNode())
+ break;
+ UInt32 nextNodeIndex = node->Descendants[i].NodePointer;
+ CNodePointer nextNode = &m_Nodes[nextNodeIndex];
+ nextNode->NumSameBits += node->NumSameBits + kNumSubBits;
+ *node = *nextNode;
+
+ nextNode->NextFreeNode = m_FreeNode;
+ m_FreeNode = nextNodeIndex;
+ return;
+ }
+ UInt32 matchPointer = 0; // = 0 to disable GCC warning
+ for (i = 0; i < kNumSubNodes; i++)
+ if (node->Descendants[i].IsMatch() && i != descendantIndex)
+ {
+ matchPointer = node->Descendants[i].MatchPointer;
+ break;
+ }
+ node->NextFreeNode = m_FreeNode;
+ m_FreeNode = *nodePointerPointer;
+ *nodePointerPointer = matchPointer;
+}
+#endif
+
+
+// Commented code is more correct, but it gives warning
+// on GCC: (1 << 32)
+// So we use kMatchStartValue twice:
+// kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1);
+// must be defined in Pat.h
+/*
+const UInt32 kNormalizeStartPos = (UInt32(1) << (kNumBitsInIndex)) -
+ kMatchStartValue - kNumHashBytes - 1;
+*/
+const UInt32 kNormalizeStartPos = kMatchStartValue - kNumHashBytes - 1;
+
+STDMETHODIMP CPatricia::MovePos()
+{
+ #ifndef __AUTO_REMOVE
+ if(_pos >= _sizeHistory)
+ RemoveMatch();
+ #endif
+ RINOK(CLZInWindow::MovePos());
+ #ifdef __AUTO_REMOVE
+ if (m_NumUsedNodes >= m_NumNodes)
+ TestRemoveNodes();
+ #endif
+ if (_pos >= kNormalizeStartPos)
+ {
+ #ifdef __AUTO_REMOVE
+ TestRemoveNodesAndNormalize();
+ #else
+ Normalize();
+ #endif
+ }
+ return S_OK;
+}
+
+#ifndef __AUTO_REMOVE
+
+void CPatricia::NormalizeDescendant(CDescendant &descendant, UInt32 subValue)
+{
+ if (descendant.IsEmpty())
+ return;
+ if (descendant.IsMatch())
+ descendant.MatchPointer = descendant.MatchPointer - subValue;
+ else
+ {
+ CNode &node = m_Nodes[descendant.NodePointer];
+ node.LastMatch = node.LastMatch - subValue;
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ NormalizeDescendant(node.Descendants[i], subValue);
+ }
+}
+
+void CPatricia::Normalize()
+{
+ UInt32 subValue = _pos - _sizeHistory;
+ CLZInWindow::ReduceOffsets(subValue);
+
+ #ifdef __HASH_3
+
+ for(UInt32 hash = 0; hash < kHash2Size; hash++)
+ {
+ CDescendant &descendant = m_Hash2Descendants[hash];
+ if (descendant.MatchPointer != kDescendantsNotInitilized2)
+ {
+ UInt32 base = hash << 8;
+ for (UInt32 i = 0; i < 0x100; i++)
+ NormalizeDescendant(m_HashDescendants[base + i], subValue);
+ }
+ if (descendant.MatchPointer < kMatchStartValue2)
+ continue;
+ descendant.MatchPointer = descendant.MatchPointer - subValue;
+ }
+
+ #else
+
+ for(UInt32 hash = 0; hash < kHashSize; hash++)
+ NormalizeDescendant(m_HashDescendants[hash], subValue);
+
+ #endif
+
+}
+
+#else
+
+void CPatricia::TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos)
+{
+ CNode &node = m_Nodes[descendant.NodePointer];
+ UInt32 numChilds = 0;
+ UInt32 childIndex = 0; // = 0 to disable GCC warning
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ {
+ CDescendant &descendant2 = node.Descendants[i];
+ if (descendant2.IsEmpty())
+ continue;
+ if (descendant2.IsMatch())
+ {
+ if (descendant2.MatchPointer < limitPos)
+ descendant2.MakeEmpty();
+ else
+ {
+ numChilds++;
+ childIndex = i;
+ }
+ }
+ else
+ {
+ TestRemoveDescendant(descendant2, limitPos);
+ if (!descendant2.IsEmpty())
+ {
+ numChilds++;
+ childIndex = i;
+ }
+ }
+ }
+ if (numChilds > 1)
+ return;
+
+ CIndex nodePointerTemp = descendant.NodePointer;
+ if (numChilds == 1)
+ {
+ const CDescendant &descendant2 = node.Descendants[childIndex];
+ if (descendant2.IsNode())
+ m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits;
+ descendant = descendant2;
+ }
+ else
+ descendant.MakeEmpty();
+ node.NextFreeNode = m_FreeNode;
+ m_FreeNode = nodePointerTemp;
+ m_NumUsedNodes--;
+}
+
+void CPatricia::RemoveNode(UInt32 index)
+{
+ CNode &node = m_Nodes[index];
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ {
+ CDescendant &descendant2 = node.Descendants[i];
+ if (descendant2.IsNode())
+ RemoveNode(descendant2.NodePointer);
+ }
+ node.NextFreeNode = m_FreeNode;
+ m_FreeNode = index;
+ m_NumUsedNodes--;
+}
+
+void CPatricia::TestRemoveNodes()
+{
+ UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes;
+
+ #ifdef __HASH_3
+
+ UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes;
+ for(UInt32 hash = 0; hash < kHash2Size; hash++)
+ {
+ CDescendant &descendant = m_Hash2Descendants[hash];
+ if (descendant.MatchPointer != kDescendantsNotInitilized2)
+ {
+ UInt32 base = hash << 8;
+ for (UInt32 i = 0; i < 0x100; i++)
+ {
+ CDescendant &descendant = m_HashDescendants[base + i];
+ if (descendant.IsEmpty())
+ continue;
+ if (descendant.IsMatch())
+ {
+ if (descendant.MatchPointer < limitPos)
+ descendant.MakeEmpty();
+ }
+ else
+ TestRemoveDescendant(descendant, limitPos);
+ }
+ }
+ if (descendant.MatchPointer < kMatchStartValue2)
+ continue;
+ if (descendant.MatchPointer < limitPos2)
+ descendant.MatchPointer = kDescendantEmptyValue2;
+ }
+
+ #else
+
+ for(UInt32 hash = 0; hash < kHashSize; hash++)
+ {
+ CDescendant &descendant = m_HashDescendants[hash];
+ if (descendant.IsEmpty())
+ continue;
+ if (descendant.IsMatch())
+ {
+ if (descendant.MatchPointer < limitPos)
+ descendant.MakeEmpty();
+ }
+ else
+ TestRemoveDescendant(descendant, limitPos);
+ }
+
+ #endif
+}
+
+void CPatricia::TestRemoveAndNormalizeDescendant(CDescendant &descendant,
+ UInt32 limitPos, UInt32 subValue)
+{
+ if (descendant.IsEmpty())
+ return;
+ if (descendant.IsMatch())
+ {
+ if (descendant.MatchPointer < limitPos)
+ descendant.MakeEmpty();
+ else
+ descendant.MatchPointer = descendant.MatchPointer - subValue;
+ return;
+ }
+ CNode &node = m_Nodes[descendant.NodePointer];
+ UInt32 numChilds = 0;
+ UInt32 childIndex = 0; // = 0 to disable GCC warning
+ for (UInt32 i = 0; i < kNumSubNodes; i++)
+ {
+ CDescendant &descendant2 = node.Descendants[i];
+ TestRemoveAndNormalizeDescendant(descendant2, limitPos, subValue);
+ if (!descendant2.IsEmpty())
+ {
+ numChilds++;
+ childIndex = i;
+ }
+ }
+ if (numChilds > 1)
+ {
+ node.LastMatch = node.LastMatch - subValue;
+ return;
+ }
+
+ CIndex nodePointerTemp = descendant.NodePointer;
+ if (numChilds == 1)
+ {
+ const CDescendant &descendant2 = node.Descendants[childIndex];
+ if (descendant2.IsNode())
+ m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits;
+ descendant = descendant2;
+ }
+ else
+ descendant.MakeEmpty();
+ node.NextFreeNode = m_FreeNode;
+ m_FreeNode = nodePointerTemp;
+ m_NumUsedNodes--;
+}
+
+void CPatricia::TestRemoveNodesAndNormalize()
+{
+ UInt32 subValue = _pos - _sizeHistory;
+ UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes;
+ CLZInWindow::ReduceOffsets(subValue);
+
+ #ifdef __HASH_3
+
+ UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes;
+ for(UInt32 hash = 0; hash < kHash2Size; hash++)
+ {
+ CDescendant &descendant = m_Hash2Descendants[hash];
+ if (descendant.MatchPointer != kDescendantsNotInitilized2)
+ {
+ UInt32 base = hash << 8;
+ for (UInt32 i = 0; i < 0x100; i++)
+ TestRemoveAndNormalizeDescendant(m_HashDescendants[base + i], limitPos, subValue);
+ }
+ if (descendant.MatchPointer < kMatchStartValue2)
+ continue;
+ if (descendant.MatchPointer < limitPos2)
+ descendant.MatchPointer = kDescendantEmptyValue2;
+ else
+ descendant.MatchPointer = descendant.MatchPointer - subValue;
+ }
+
+ #else
+
+ for(UInt32 hash = 0; hash < kHashSize; hash++)
+ TestRemoveAndNormalizeDescendant(m_HashDescendants[hash], limitPos, subValue);
+
+ #endif
+}
+
+#endif
+
+STDMETHODIMP_(Byte) CPatricia::GetIndexByte(Int32 index)
+{
+ return CLZInWindow::GetIndexByte(index);
+}
+
+STDMETHODIMP_(UInt32) CPatricia::GetMatchLen(Int32 index, UInt32 back, UInt32 limit)
+{
+ return CLZInWindow::GetMatchLen(index, back, limit);
+}
+
+STDMETHODIMP_(UInt32) CPatricia::GetNumAvailableBytes()
+{
+ return CLZInWindow::GetNumAvailableBytes();
+}
+
+STDMETHODIMP_(const Byte *) CPatricia::GetPointerToCurrentPos()
+{
+ return CLZInWindow::GetPointerToCurrentPos();
+}
+
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/StdAfx.h
new file mode 100644
index 00000000..3de038a4
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZ/StdAfx.h
@@ -0,0 +1,6 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMA.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMA.h
new file mode 100644
index 00000000..d53296ee
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMA.h
@@ -0,0 +1,82 @@
+// LZMA.h
+
+#ifndef __LZMA_H
+#define __LZMA_H
+
+namespace NCompress {
+namespace NLZMA {
+
+const UInt32 kNumRepDistances = 4;
+
+const int kNumStates = 12;
+
+const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
+const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+class CState
+{
+public:
+ Byte Index;
+ void Init() { Index = 0; }
+ void UpdateChar() { Index = kLiteralNextStates[Index]; }
+ void UpdateMatch() { Index = kMatchNextStates[Index]; }
+ void UpdateRep() { Index = kRepNextStates[Index]; }
+ void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
+ bool IsCharState() const { return Index < 7; }
+};
+
+const int kNumPosSlotBits = 6;
+const int kDicLogSizeMin = 0;
+const int kDicLogSizeMax = 32;
+const int kDistTableSizeMax = kDicLogSizeMax * 2;
+
+const UInt32 kNumLenToPosStates = 4;
+
+inline UInt32 GetLenToPosState(UInt32 len)
+{
+ len -= 2;
+ if (len < kNumLenToPosStates)
+ return len;
+ return kNumLenToPosStates - 1;
+}
+
+namespace NLength {
+
+const int kNumPosStatesBitsMax = 4;
+const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
+
+const int kNumPosStatesBitsEncodingMax = 4;
+const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
+
+const int kNumLowBits = 3;
+const int kNumMidBits = 3;
+const int kNumHighBits = 8;
+const UInt32 kNumLowSymbols = 1 << kNumLowBits;
+const UInt32 kNumMidSymbols = 1 << kNumMidBits;
+const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits);
+
+}
+
+const UInt32 kMatchMinLen = 2;
+const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1;
+
+const int kNumAlignBits = 4;
+const UInt32 kAlignTableSize = 1 << kNumAlignBits;
+const UInt32 kAlignMask = (kAlignTableSize - 1);
+
+const UInt32 kStartPosModelIndex = 4;
+const UInt32 kEndPosModelIndex = 14;
+const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
+
+const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2);
+
+const int kNumLitPosStatesBitsEncodingMax = 4;
+const int kNumLitContextBitsMax = 8;
+
+const int kNumMoveBits = 5;
+
+}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp
new file mode 100644
index 00000000..f672099a
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp
@@ -0,0 +1,342 @@
+// LZMADecoder.cpp
+
+#include "StdAfx.h"
+
+#include "LZMADecoder.h"
+#include "../../../Common/Defs.h"
+
+namespace NCompress {
+namespace NLZMA {
+
+const int kLenIdFinished = -1;
+const int kLenIdNeedInit = -2;
+
+void CDecoder::Init()
+{
+ {
+ for(int i = 0; i < kNumStates; i++)
+ {
+ for (UInt32 j = 0; j <= _posStateMask; j++)
+ {
+ _isMatch[i][j].Init();
+ _isRep0Long[i][j].Init();
+ }
+ _isRep[i].Init();
+ _isRepG0[i].Init();
+ _isRepG1[i].Init();
+ _isRepG2[i].Init();
+ }
+ }
+ {
+ for (UInt32 i = 0; i < kNumLenToPosStates; i++)
+ _posSlotDecoder[i].Init();
+ }
+ {
+ for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+ _posDecoders[i].Init();
+ }
+ _posAlignDecoder.Init();
+ _lenDecoder.Init(_posStateMask + 1);
+ _repMatchLenDecoder.Init(_posStateMask + 1);
+ _literalDecoder.Init();
+
+ _state.Init();
+ _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0;
+}
+
+HRESULT CDecoder::CodeSpec(UInt32 curSize)
+{
+ if (_outSizeDefined)
+ {
+ const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize();
+ if (curSize > rem)
+ curSize = (UInt32)rem;
+ }
+
+ if (_remainLen == kLenIdFinished)
+ return S_OK;
+ if (_remainLen == kLenIdNeedInit)
+ {
+ _rangeDecoder.Init();
+ Init();
+ _remainLen = 0;
+ }
+ if (curSize == 0)
+ return S_OK;
+
+ UInt32 rep0 = _reps[0];
+ UInt32 rep1 = _reps[1];
+ UInt32 rep2 = _reps[2];
+ UInt32 rep3 = _reps[3];
+ CState state = _state;
+ Byte previousByte;
+
+ while(_remainLen > 0 && curSize > 0)
+ {
+ previousByte = _outWindowStream.GetByte(rep0);
+ _outWindowStream.PutByte(previousByte);
+ _remainLen--;
+ curSize--;
+ }
+ UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
+ if (nowPos64 == 0)
+ previousByte = 0;
+ else
+ previousByte = _outWindowStream.GetByte(0);
+
+ while(curSize > 0)
+ {
+ {
+ #ifdef _NO_EXCEPTIONS
+ if (_rangeDecoder.Stream.ErrorCode != S_OK)
+ return _rangeDecoder.Stream.ErrorCode;
+ #endif
+ if (_rangeDecoder.Stream.WasFinished())
+ return S_FALSE;
+ UInt32 posState = UInt32(nowPos64) & _posStateMask;
+ if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0)
+ {
+ if(!state.IsCharState())
+ previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder,
+ (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0));
+ else
+ previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder,
+ (UInt32)nowPos64, previousByte);
+ _outWindowStream.PutByte(previousByte);
+ state.UpdateChar();
+ curSize--;
+ nowPos64++;
+ }
+ else
+ {
+ UInt32 len;
+ if(_isRep[state.Index].Decode(&_rangeDecoder) == 1)
+ {
+ len = 0;
+ if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0)
+ {
+ if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0)
+ {
+ state.UpdateShortRep();
+ len = 1;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0)
+ distance = rep1;
+ else
+ {
+ if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ if (len == 0)
+ {
+ len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen;
+ state.UpdateRep();
+ }
+ }
+ else
+ {
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState);
+ state.UpdateMatch();
+ UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ UInt32 numDirectBits = (posSlot >> 1) - 1;
+ rep0 = ((2 | (posSlot & 1)) << numDirectBits);
+
+ if (posSlot < kEndPosModelIndex)
+ rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders +
+ rep0 - posSlot - 1, &_rangeDecoder, numDirectBits);
+ else
+ {
+ rep0 += (_rangeDecoder.DecodeDirectBits(
+ numDirectBits - kNumAlignBits) << kNumAlignBits);
+ rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder);
+ if (rep0 == 0xFFFFFFFF)
+ {
+ _remainLen = kLenIdFinished;
+ return S_OK;
+ }
+ }
+ }
+ else
+ rep0 = posSlot;
+ }
+ UInt32 locLen = len;
+ if (len > curSize)
+ locLen = (UInt32)curSize;
+ if (!_outWindowStream.CopyBlock(rep0, locLen))
+ return S_FALSE;
+ previousByte = _outWindowStream.GetByte(0);
+ curSize -= locLen;
+ nowPos64 += locLen;
+ len -= locLen;
+ if (len != 0)
+ {
+ _remainLen = (Int32)len;
+ break;
+ }
+
+ #ifdef _NO_EXCEPTIONS
+ if (_outWindowStream.ErrorCode != S_OK)
+ return _outWindowStream.ErrorCode;
+ #endif
+ }
+ }
+ }
+ if (_rangeDecoder.Stream.WasFinished())
+ return S_FALSE;
+ _reps[0] = rep0;
+ _reps[1] = rep1;
+ _reps[2] = rep2;
+ _reps[3] = rep3;
+ _state = state;
+
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 *, const UInt64 *outSize,
+ ICompressProgressInfo *progress)
+{
+ SetInStream(inStream);
+ _outWindowStream.SetStream(outStream);
+ SetOutStreamSize(outSize);
+ CDecoderFlusher flusher(this);
+
+ while (true)
+ {
+ UInt32 curSize = 1 << 18;
+ RINOK(CodeSpec(curSize));
+ if (_remainLen == kLenIdFinished)
+ break;
+ if (progress != NULL)
+ {
+ UInt64 inSize = _rangeDecoder.GetProcessedSize();
+ UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
+ RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
+ }
+ if (_outSizeDefined)
+ if (_outWindowStream.GetProcessedSize() >= _outSize)
+ break;
+ }
+ flusher.NeedFlush = false;
+ return Flush();
+}
+
+
+#ifdef _NO_EXCEPTIONS
+
+#define LZMA_TRY_BEGIN
+#define LZMA_TRY_END
+
+#else
+
+#define LZMA_TRY_BEGIN try {
+#define LZMA_TRY_END } \
+ catch(const CInBufferException &e) { return e.ErrorCode; } \
+ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \
+ catch(...) { return S_FALSE; }
+
+#endif
+
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress)
+{
+ LZMA_TRY_BEGIN
+ return CodeReal(inStream, outStream, inSize, outSize, progress);
+ LZMA_TRY_END
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
+{
+ if (size < 5)
+ return E_INVALIDARG;
+ int lc = properties[0] % 9;
+ Byte remainder = (Byte)(properties[0] / 9);
+ int lp = remainder % 5;
+ int pb = remainder / 5;
+ UInt32 dictionarySize = 0;
+ for (int i = 0; i < 4; i++)
+ dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
+ return SetDecoderPropertiesRaw(lc, lp, pb, dictionarySize);
+}
+
+STDMETHODIMP CDecoder::SetDecoderPropertiesRaw(int lc, int lp, int pb, UInt32 dictionarySize)
+{
+ if (pb > NLength::kNumPosStatesBitsMax)
+ return E_INVALIDARG;
+ _posStateMask = (1 << pb) - 1;
+ if (!_outWindowStream.Create(dictionarySize))
+ return E_OUTOFMEMORY;
+ if (!_literalDecoder.Create(lp, lc))
+ return E_OUTOFMEMORY;
+ if (!_rangeDecoder.Create(1 << 20))
+ return E_OUTOFMEMORY;
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _rangeDecoder.GetProcessedSize();
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
+{
+ _rangeDecoder.SetStream(inStream);
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::ReleaseInStream()
+{
+ _rangeDecoder.ReleaseStream();
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+ if (_outSizeDefined = (outSize != NULL))
+ _outSize = *outSize;
+ _remainLen = kLenIdNeedInit;
+ _outWindowStream.Init();
+ return S_OK;
+}
+
+#ifdef _ST_MODE
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ LZMA_TRY_BEGIN
+ if (processedSize)
+ *processedSize = 0;
+ const UInt64 startPos = _outWindowStream.GetProcessedSize();
+ _outWindowStream.SetMemStream((Byte *)data);
+ RINOK(CodeSpec(size));
+ if (processedSize)
+ *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos);
+ return Flush();
+ LZMA_TRY_END
+}
+
+#endif
+
+}}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.h
new file mode 100644
index 00000000..6f5f7ecc
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMADecoder.h
@@ -0,0 +1,249 @@
+// LZMA/Decoder.h
+
+#ifndef __LZMA_DECODER_H
+#define __LZMA_DECODER_H
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/Alloc.h"
+#include "../../ICoder.h"
+#include "../LZ/LZOutWindow.h"
+#include "../RangeCoder/RangeCoderBitTree.h"
+
+#include "LZMA.h"
+
+namespace NCompress {
+namespace NLZMA {
+
+typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder;
+
+class CLiteralDecoder2
+{
+ CMyBitDecoder _decoders[0x300];
+public:
+ void Init()
+ {
+ for (int i = 0; i < 0x300; i++)
+ _decoders[i].Init();
+ }
+ Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder)
+ {
+ UInt32 symbol = 1;
+ RC_INIT_VAR
+ do
+ {
+ // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
+ RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
+ }
+ while (symbol < 0x100);
+ RC_FLUSH_VAR
+ return (Byte)symbol;
+ }
+ Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte)
+ {
+ UInt32 symbol = 1;
+ RC_INIT_VAR
+ do
+ {
+ UInt32 matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder);
+ // symbol = (symbol << 1) | bit;
+ UInt32 bit;
+ RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol,
+ bit = 0, bit = 1)
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
+ RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ RC_FLUSH_VAR
+ return (Byte)symbol;
+ }
+};
+
+class CLiteralDecoder
+{
+ CLiteralDecoder2 *_coders;
+ int _numPrevBits;
+ int _numPosBits;
+ UInt32 _posMask;
+public:
+ CLiteralDecoder(): _coders(0) {}
+ ~CLiteralDecoder() { Free(); }
+ void Free()
+ {
+ MyFree(_coders);
+ _coders = 0;
+ }
+ bool Create(int numPosBits, int numPrevBits)
+ {
+ if (_coders == 0 || (numPosBits + numPrevBits) !=
+ (_numPrevBits + _numPosBits) )
+ {
+ Free();
+ UInt32 numStates = 1 << (numPosBits + numPrevBits);
+ _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2));
+ }
+ _numPosBits = numPosBits;
+ _posMask = (1 << numPosBits) - 1;
+ _numPrevBits = numPrevBits;
+ return (_coders != 0);
+ }
+ void Init()
+ {
+ UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
+ for (UInt32 i = 0; i < numStates; i++)
+ _coders[i].Init();
+ }
+ UInt32 GetState(UInt32 pos, Byte prevByte) const
+ { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
+ Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte)
+ { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
+ Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte)
+ { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
+};
+
+namespace NLength {
+
+class CDecoder
+{
+ CMyBitDecoder _choice;
+ CMyBitDecoder _choice2;
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesMax];
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax];
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder;
+public:
+ void Init(UInt32 numPosStates)
+ {
+ _choice.Init();
+ _choice2.Init();
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
+ {
+ _lowCoder[posState].Init();
+ _midCoder[posState].Init();
+ }
+ _highCoder.Init();
+ }
+ UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState)
+ {
+ if(_choice.Decode(rangeDecoder) == 0)
+ return _lowCoder[posState].Decode(rangeDecoder);
+ if(_choice2.Decode(rangeDecoder) == 0)
+ return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder);
+ return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder);
+ }
+};
+
+}
+
+class CDecoder:
+ public ICompressCoder,
+ public ICompressSetDecoderProperties2,
+ #ifdef _ST_MODE
+ public ICompressSetInStream,
+ public ICompressSetOutStreamSize,
+ public ISequentialInStream,
+ #endif
+ public CMyUnknownImp
+{
+ CLZOutWindow _outWindowStream;
+ NRangeCoder::CDecoder _rangeDecoder;
+
+ CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax];
+ CMyBitDecoder _isRep[kNumStates];
+ CMyBitDecoder _isRepG0[kNumStates];
+ CMyBitDecoder _isRepG1[kNumStates];
+ CMyBitDecoder _isRepG2[kNumStates];
+ CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax];
+
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates];
+
+ CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex];
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder;
+
+ NLength::CDecoder _lenDecoder;
+ NLength::CDecoder _repMatchLenDecoder;
+
+ CLiteralDecoder _literalDecoder;
+
+ UInt32 _posStateMask;
+
+ ///////////////////
+ // State
+ UInt32 _reps[4];
+ CState _state;
+ Int32 _remainLen; // -1 means end of stream. // -2 means need Init
+ UInt64 _outSize;
+ bool _outSizeDefined;
+
+ void Init();
+ HRESULT CodeSpec(UInt32 size);
+public:
+
+ #ifdef _ST_MODE
+ MY_UNKNOWN_IMP4(
+ ICompressSetDecoderProperties2,
+ ICompressSetInStream,
+ ICompressSetOutStreamSize,
+ ISequentialInStream)
+ #else
+ MY_UNKNOWN_IMP1(
+ ICompressSetDecoderProperties2)
+ #endif
+
+ void ReleaseStreams()
+ {
+ _outWindowStream.ReleaseStream();
+ ReleaseInStream();
+ }
+
+ class CDecoderFlusher
+ {
+ CDecoder *_decoder;
+ public:
+ bool NeedFlush;
+ CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
+ ~CDecoderFlusher()
+ {
+ if (NeedFlush)
+ _decoder->Flush();
+ _decoder->ReleaseStreams();
+ }
+ };
+
+ HRESULT Flush() { return _outWindowStream.Flush(); }
+
+ STDMETHOD(CodeReal)(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress);
+
+ STDMETHOD(Code)(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress);
+
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ STDMETHOD(SetDecoderPropertiesRaw)(int lc, int lp, int pb, UInt32 dictionarySize);
+
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ STDMETHOD(ReleaseInStream)();
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+
+ #ifdef _ST_MODE
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ #endif
+
+ CDecoder(): _outSizeDefined(false) {}
+ virtual ~CDecoder() {}
+};
+
+}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp
new file mode 100644
index 00000000..4f20ed5a
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp
@@ -0,0 +1,1504 @@
+// LZMA/Encoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/Defs.h"
+#include "../../Common/StreamUtils.h"
+
+#include "LZMAEncoder.h"
+
+// for minimal compressing code size define these:
+// #define COMPRESS_MF_BT
+// #define COMPRESS_MF_BT4
+
+#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC)
+#define COMPRESS_MF_BT
+#define COMPRESS_MF_PAT
+#define COMPRESS_MF_HC
+#endif
+
+#ifdef COMPRESS_MF_BT
+#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B)
+#define COMPRESS_MF_BT2
+#define COMPRESS_MF_BT3
+#define COMPRESS_MF_BT4
+#define COMPRESS_MF_BT4B
+#endif
+#ifdef COMPRESS_MF_BT2
+#include "../LZ/BinTree/BinTree2.h"
+#endif
+#ifdef COMPRESS_MF_BT3
+#include "../LZ/BinTree/BinTree3.h"
+#endif
+#ifdef COMPRESS_MF_BT4
+#include "../LZ/BinTree/BinTree4.h"
+#endif
+#ifdef COMPRESS_MF_BT4B
+#include "../LZ/BinTree/BinTree4b.h"
+#endif
+#endif
+
+#ifdef COMPRESS_MF_PAT
+#include "../LZ/Patricia/Pat2.h"
+#include "../LZ/Patricia/Pat2H.h"
+#include "../LZ/Patricia/Pat3H.h"
+#include "../LZ/Patricia/Pat4H.h"
+#include "../LZ/Patricia/Pat2R.h"
+#endif
+
+#ifdef COMPRESS_MF_HC
+#include "../LZ/HashChain/HC3.h"
+#include "../LZ/HashChain/HC4.h"
+#endif
+
+#ifdef COMPRESS_MF_MT
+#include "../LZ/MT/MT.h"
+#endif
+
+namespace NCompress {
+namespace NLZMA {
+
+const int kDefaultDictionaryLogSize = 20;
+const UInt32 kNumFastBytesDefault = 0x20;
+
+enum
+{
+ kBT2,
+ kBT3,
+ kBT4,
+ kBT4B,
+ kPat2,
+ kPat2H,
+ kPat3H,
+ kPat4H,
+ kPat2R,
+ kHC3,
+ kHC4
+};
+
+static const wchar_t *kMatchFinderIDs[] =
+{
+ L"BT2",
+ L"BT3",
+ L"BT4",
+ L"BT4B",
+ L"PAT2",
+ L"PAT2H",
+ L"PAT3H",
+ L"PAT4H",
+ L"PAT2R",
+ L"HC3",
+ L"HC4"
+};
+
+Byte g_FastPos[1024];
+
+class CFastPosInit
+{
+public:
+ CFastPosInit() { Init(); }
+ void Init()
+ {
+ const Byte kFastSlots = 20;
+ int c = 2;
+ g_FastPos[0] = 0;
+ g_FastPos[1] = 1;
+
+ for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
+ {
+ UInt32 k = (1 << ((slotFast >> 1) - 1));
+ for (UInt32 j = 0; j < k; j++, c++)
+ g_FastPos[c] = slotFast;
+ }
+ }
+} g_FastPosInit;
+
+
+void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)
+{
+ UInt32 context = 1;
+ int i = 8;
+ do
+ {
+ i--;
+ UInt32 bit = (symbol >> i) & 1;
+ _encoders[context].Encode(rangeEncoder, bit);
+ context = (context << 1) | bit;
+ }
+ while(i != 0);
+}
+
+void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder,
+ Byte matchByte, Byte symbol)
+{
+ UInt32 context = 1;
+ int i = 8;
+ do
+ {
+ i--;
+ UInt32 bit = (symbol >> i) & 1;
+ UInt32 matchBit = (matchByte >> i) & 1;
+ _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);
+ context = (context << 1) | bit;
+ if (matchBit != bit)
+ {
+ while(i != 0)
+ {
+ i--;
+ UInt32 bit = (symbol >> i) & 1;
+ _encoders[context].Encode(rangeEncoder, bit);
+ context = (context << 1) | bit;
+ }
+ break;
+ }
+ }
+ while(i != 0);
+}
+
+UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const
+{
+ UInt32 price = 0;
+ UInt32 context = 1;
+ int i = 8;
+ if (matchMode)
+ {
+ do
+ {
+ i--;
+ UInt32 matchBit = (matchByte >> i) & 1;
+ UInt32 bit = (symbol >> i) & 1;
+ price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);
+ context = (context << 1) | bit;
+ if (matchBit != bit)
+ break;
+ }
+ while (i != 0);
+ }
+ while(i != 0)
+ {
+ i--;
+ UInt32 bit = (symbol >> i) & 1;
+ price += _encoders[context].GetPrice(bit);
+ context = (context << 1) | bit;
+ }
+ return price;
+};
+
+
+namespace NLength {
+
+void CEncoder::Init(UInt32 numPosStates)
+{
+ _choice.Init();
+ _choice2.Init();
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
+ {
+ _lowCoder[posState].Init();
+ _midCoder[posState].Init();
+ }
+ _highCoder.Init();
+}
+
+void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
+{
+ if(symbol < kNumLowSymbols)
+ {
+ _choice.Encode(rangeEncoder, 0);
+ _lowCoder[posState].Encode(rangeEncoder, symbol);
+ }
+ else
+ {
+ _choice.Encode(rangeEncoder, 1);
+ if(symbol < kNumLowSymbols + kNumMidSymbols)
+ {
+ _choice2.Encode(rangeEncoder, 0);
+ _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);
+ }
+ else
+ {
+ _choice2.Encode(rangeEncoder, 1);
+ _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);
+ }
+ }
+}
+
+UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const
+{
+ if(symbol < kNumLowSymbols)
+ return _choice.GetPrice0() + _lowCoder[posState].GetPrice(symbol);
+ UInt32 price = _choice.GetPrice1();
+ if(symbol < kNumLowSymbols + kNumMidSymbols)
+ {
+ price += _choice2.GetPrice0();
+ price += _midCoder[posState].GetPrice(symbol - kNumLowSymbols);
+ }
+ else
+ {
+ price += _choice2.GetPrice1();
+ price += _highCoder.GetPrice(symbol - kNumLowSymbols - kNumMidSymbols);
+ }
+ return price;
+}
+
+}
+CEncoder::CEncoder():
+ _numFastBytes(kNumFastBytesDefault),
+ _distTableSize(kDefaultDictionaryLogSize * 2),
+ _posStateBits(2),
+ _posStateMask(4 - 1),
+ _numLiteralPosStateBits(0),
+ _numLiteralContextBits(3),
+ _dictionarySize(1 << kDefaultDictionaryLogSize),
+ _dictionarySizePrev(UInt32(-1)),
+ _numFastBytesPrev(UInt32(-1)),
+ _matchFinderIndex(kBT4),
+ #ifdef COMPRESS_MF_MT
+ _multiThread(false),
+ #endif
+ _writeEndMark(false)
+{
+ _maxMode = false;
+ _fastMode = false;
+}
+
+HRESULT CEncoder::Create()
+{
+ if (!_rangeEncoder.Create(1 << 20))
+ return E_OUTOFMEMORY;
+ if (!_matchFinder)
+ {
+ switch(_matchFinderIndex)
+ {
+ #ifdef COMPRESS_MF_BT
+ #ifdef COMPRESS_MF_BT2
+ case kBT2:
+ _matchFinder = new NBT2::CMatchFinderBinTree;
+ break;
+ #endif
+ #ifdef COMPRESS_MF_BT3
+ case kBT3:
+ _matchFinder = new NBT3::CMatchFinderBinTree;
+ break;
+ #endif
+ #ifdef COMPRESS_MF_BT4
+ case kBT4:
+ _matchFinder = new NBT4::CMatchFinderBinTree;
+ break;
+ #endif
+ #ifdef COMPRESS_MF_BT4B
+ case kBT4B:
+ _matchFinder = new NBT4B::CMatchFinderBinTree;
+ break;
+ #endif
+ #endif
+
+ #ifdef COMPRESS_MF_PAT
+ case kPat2:
+ _matchFinder = new NPat2::CPatricia;
+ break;
+ case kPat2H:
+ _matchFinder = new NPat2H::CPatricia;
+ break;
+ case kPat3H:
+ _matchFinder = new NPat3H::CPatricia;
+ break;
+ case kPat4H:
+ _matchFinder = new NPat4H::CPatricia;
+ break;
+ case kPat2R:
+ _matchFinder = new NPat2R::CPatricia;
+ break;
+ #endif
+
+ #ifdef COMPRESS_MF_HC
+ case kHC3:
+ _matchFinder = new NHC3::CMatchFinderHC;
+ break;
+ case kHC4:
+ _matchFinder = new NHC4::CMatchFinderHC;
+ break;
+ #endif
+ }
+ if (_matchFinder == 0)
+ return E_OUTOFMEMORY;
+
+ #ifdef COMPRESS_MF_MT
+ if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC3 || _matchFinderIndex == kHC4)))
+ {
+ CMatchFinderMT *mfSpec = new CMatchFinderMT;
+ if (mfSpec == 0)
+ return E_OUTOFMEMORY;
+ CMyComPtr<IMatchFinder> mf = mfSpec;
+ RINOK(mfSpec->SetMatchFinder(_matchFinder));
+ _matchFinder.Release();
+ _matchFinder = mf;
+ }
+ #endif
+ }
+
+ if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))
+ return E_OUTOFMEMORY;
+
+ if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
+ return S_OK;
+ RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes,
+ kMatchMaxLen * 2 + 1 - _numFastBytes));
+ _dictionarySizePrev = _dictionarySize;
+ _numFastBytesPrev = _numFastBytes;
+ return S_OK;
+}
+
+static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString)
+{
+ while (true)
+ {
+ wchar_t c = *testString;
+ if (c >= 'a' && c <= 'z')
+ c -= 0x20;
+ if (*base != c)
+ return false;
+ if (c == 0)
+ return true;
+ base++;
+ testString++;
+ }
+}
+
+static int FindMatchFinder(const wchar_t *s)
+{
+ for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++)
+ if (AreStringsEqual(kMatchFinderIDs[m], s))
+ return m;
+ return -1;
+}
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
+ const PROPVARIANT *properties, UInt32 numProperties)
+{
+ for (UInt32 i = 0; i < numProperties; i++)
+ {
+ const PROPVARIANT &prop = properties[i];
+ switch(propIDs[i])
+ {
+ case NCoderPropID::kNumFastBytes:
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 numFastBytes = prop.ulVal;
+ if(numFastBytes < 5 || numFastBytes > kMatchMaxLen)
+ return E_INVALIDARG;
+ _numFastBytes = numFastBytes;
+ break;
+ }
+ case NCoderPropID::kAlgorithm:
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 maximize = prop.ulVal;
+ _fastMode = (maximize == 0);
+ _maxMode = (maximize >= 2);
+ break;
+ }
+ case NCoderPropID::kMatchFinder:
+ {
+ if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
+ int matchFinderIndexPrev = _matchFinderIndex;
+ int m = FindMatchFinder(prop.bstrVal);
+ if (m < 0)
+ return E_INVALIDARG;
+ _matchFinderIndex = m;
+ if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex)
+ {
+ _dictionarySizePrev = UInt32(-1);
+ _matchFinder.Release();
+ }
+ break;
+ }
+ #ifdef COMPRESS_MF_MT
+ case NCoderPropID::kMultiThread:
+ {
+ if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ bool newMultiThread = (prop.boolVal == VARIANT_TRUE);
+ if (newMultiThread != _multiThread)
+ {
+ _dictionarySizePrev = UInt32(-1);
+ _matchFinder.Release();
+ }
+ _multiThread = newMultiThread;
+ break;
+ }
+ #endif
+ case NCoderPropID::kDictionarySize:
+ {
+ const int kDicLogSizeMaxCompress = 28;
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 dictionarySize = prop.ulVal;
+ if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||
+ dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))
+ return E_INVALIDARG;
+ _dictionarySize = dictionarySize;
+ UInt32 dicLogSize;
+ for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
+ if (dictionarySize <= (UInt32(1) << dicLogSize))
+ break;
+ _distTableSize = dicLogSize * 2;
+ break;
+ }
+ case NCoderPropID::kPosStateBits:
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 value = prop.ulVal;
+ if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)
+ return E_INVALIDARG;
+ _posStateBits = value;
+ _posStateMask = (1 << _posStateBits) - 1;
+ break;
+ }
+ case NCoderPropID::kLitPosBits:
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 value = prop.ulVal;
+ if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)
+ return E_INVALIDARG;
+ _numLiteralPosStateBits = value;
+ break;
+ }
+ case NCoderPropID::kLitContextBits:
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 value = prop.ulVal;
+ if (value > (UInt32)kNumLitContextBitsMax)
+ return E_INVALIDARG;
+ _numLiteralContextBits = value;
+ break;
+ }
+ case NCoderPropID::kEndMarker:
+ {
+ if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);
+ break;
+ }
+ default:
+ return E_INVALIDARG;
+ }
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ const UInt32 kPropSize = 5;
+ Byte properties[kPropSize];
+ properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits;
+ for (int i = 0; i < 4; i++)
+ properties[1 + i] = Byte(_dictionarySize >> (8 * i));
+ return WriteStream(outStream, properties, kPropSize, NULL);
+}
+
+STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)
+{
+ _rangeEncoder.SetStream(outStream);
+ return S_OK;
+}
+
+STDMETHODIMP CEncoder::ReleaseOutStream()
+{
+ _rangeEncoder.ReleaseStream();
+ return S_OK;
+}
+
+HRESULT CEncoder::Init()
+{
+ CBaseState::Init();
+
+ // RINOK(_matchFinder->Init(inStream));
+ _rangeEncoder.Init();
+
+ for(int i = 0; i < kNumStates; i++)
+ {
+ for (UInt32 j = 0; j <= _posStateMask; j++)
+ {
+ _isMatch[i][j].Init();
+ _isRep0Long[i][j].Init();
+ }
+ _isRep[i].Init();
+ _isRepG0[i].Init();
+ _isRepG1[i].Init();
+ _isRepG2[i].Init();
+ }
+
+ _literalEncoder.Init();
+
+ // _repMatchLenEncoder.Init();
+
+ {
+ for(UInt32 i = 0; i < kNumLenToPosStates; i++)
+ _posSlotEncoder[i].Init();
+ }
+ {
+ for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+ _posEncoders[i].Init();
+ }
+
+ _lenEncoder.Init(1 << _posStateBits);
+ _repMatchLenEncoder.Init(1 << _posStateBits);
+
+ _posAlignEncoder.Init();
+
+ _longestMatchWasFound = false;
+ _optimumEndIndex = 0;
+ _optimumCurrentIndex = 0;
+ _additionalOffset = 0;
+
+ return S_OK;
+}
+
+HRESULT CEncoder::MovePos(UInt32 num)
+{
+ for (;num != 0; num--)
+ {
+ _matchFinder->DummyLongestMatch();
+ RINOK(_matchFinder->MovePos());
+ _additionalOffset++;
+ }
+ return S_OK;
+}
+
+UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
+{
+ _optimumEndIndex = cur;
+ UInt32 posMem = _optimum[cur].PosPrev;
+ UInt32 backMem = _optimum[cur].BackPrev;
+ do
+ {
+ if (_optimum[cur].Prev1IsChar)
+ {
+ _optimum[posMem].MakeAsChar();
+ _optimum[posMem].PosPrev = posMem - 1;
+ if (_optimum[cur].Prev2)
+ {
+ _optimum[posMem - 1].Prev1IsChar = false;
+ _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
+ _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
+ }
+ }
+ UInt32 posPrev = posMem;
+ UInt32 backCur = backMem;
+
+ backMem = _optimum[posPrev].BackPrev;
+ posMem = _optimum[posPrev].PosPrev;
+
+ _optimum[posPrev].BackPrev = backCur;
+ _optimum[posPrev].PosPrev = cur;
+ cur = posPrev;
+ }
+ while(cur != 0);
+ backRes = _optimum[0].BackPrev;
+ _optimumCurrentIndex = _optimum[0].PosPrev;
+ return _optimumCurrentIndex;
+}
+
+/*
+inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit)
+{
+ back++;
+ for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++);
+ return i;
+}
+*/
+
+
+/*
+Out:
+ (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal
+*/
+
+HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
+{
+ if(_optimumEndIndex != _optimumCurrentIndex)
+ {
+ const COptimal &optimum = _optimum[_optimumCurrentIndex];
+ lenRes = optimum.PosPrev - _optimumCurrentIndex;
+ backRes = optimum.BackPrev;
+ _optimumCurrentIndex = optimum.PosPrev;
+ return S_OK;
+ }
+ _optimumCurrentIndex = 0;
+ _optimumEndIndex = 0; // test it;
+
+ UInt32 lenMain;
+ if (!_longestMatchWasFound)
+ {
+ RINOK(ReadMatchDistances(lenMain));
+ }
+ else
+ {
+ lenMain = _longestMatchLength;
+ _longestMatchWasFound = false;
+ }
+
+
+ UInt32 reps[kNumRepDistances];
+ UInt32 repLens[kNumRepDistances];
+ UInt32 repMaxIndex = 0;
+ UInt32 i;
+ for(i = 0; i < kNumRepDistances; i++)
+ {
+ reps[i] = _repDistances[i];
+ repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen);
+ if (i == 0 || repLens[i] > repLens[repMaxIndex])
+ repMaxIndex = i;
+ }
+ if(repLens[repMaxIndex] >= _numFastBytes)
+ {
+ backRes = repMaxIndex;
+ lenRes = repLens[repMaxIndex];
+ return MovePos(lenRes - 1);
+ }
+
+ if(lenMain >= _numFastBytes)
+ {
+ backRes = _matchDistances[_numFastBytes] + kNumRepDistances;
+ lenRes = lenMain;
+ return MovePos(lenMain - 1);
+ }
+ Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
+
+ _optimum[0].State = _state;
+
+ Byte matchByte;
+
+ matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1);
+
+ UInt32 posState = (position & _posStateMask);
+
+ _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() +
+ _literalEncoder.GetPrice(position, _previousByte, !_state.IsCharState(), matchByte, currentByte);
+ _optimum[1].MakeAsChar();
+
+ _optimum[1].PosPrev = 0;
+
+ for (i = 0; i < kNumRepDistances; i++)
+ _optimum[0].Backs[i] = reps[i];
+
+ UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
+ UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
+
+ if(matchByte == currentByte)
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
+ if(shortRepPrice < _optimum[1].Price)
+ {
+ _optimum[1].Price = shortRepPrice;
+ _optimum[1].MakeAsShortRep();
+ }
+ }
+ if(lenMain < 2)
+ {
+ backRes = _optimum[1].BackPrev;
+ lenRes = 1;
+ return S_OK;
+ }
+
+
+ UInt32 normalMatchPrice = matchPrice +
+ _isRep[_state.Index].GetPrice0();
+
+ if (lenMain <= repLens[repMaxIndex])
+ lenMain = 0;
+
+ UInt32 len;
+ for(len = 2; len <= lenMain; len++)
+ {
+ _optimum[len].PosPrev = 0;
+ _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances;
+ _optimum[len].Price = normalMatchPrice +
+ GetPosLenPrice(_matchDistances[len], len, posState);
+ _optimum[len].Prev1IsChar = false;
+ }
+
+ if (lenMain < repLens[repMaxIndex])
+ lenMain = repLens[repMaxIndex];
+
+ for (; len <= lenMain; len++)
+ _optimum[len].Price = kIfinityPrice;
+
+ for(i = 0; i < kNumRepDistances; i++)
+ {
+ UInt32 repLen = repLens[i];
+ for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++)
+ {
+ UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState);
+ COptimal &optimum = _optimum[lenTest];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = 0;
+ optimum.BackPrev = i;
+ optimum.Prev1IsChar = false;
+ }
+ }
+ }
+
+ UInt32 cur = 0;
+ UInt32 lenEnd = lenMain;
+
+ while(true)
+ {
+ cur++;
+ if(cur == lenEnd)
+ {
+ lenRes = Backward(backRes, cur);
+ return S_OK;
+ }
+ position++;
+ COptimal &curOptimum = _optimum[cur];
+ UInt32 posPrev = curOptimum.PosPrev;
+ CState state;
+ if (curOptimum.Prev1IsChar)
+ {
+ posPrev--;
+ if (curOptimum.Prev2)
+ {
+ state = _optimum[curOptimum.PosPrev2].State;
+ if (curOptimum.BackPrev2 < kNumRepDistances)
+ state.UpdateRep();
+ else
+ state.UpdateMatch();
+ }
+ else
+ state = _optimum[posPrev].State;
+ state.UpdateChar();
+ }
+ else
+ state = _optimum[posPrev].State;
+ if (posPrev == cur - 1)
+ {
+ if (curOptimum.IsShortRep())
+ state.UpdateShortRep();
+ else
+ state.UpdateChar();
+ /*
+ if (curOptimum.Prev1IsChar)
+ for(int i = 0; i < kNumRepDistances; i++)
+ reps[i] = _optimum[posPrev].Backs[i];
+ */
+ }
+ else
+ {
+ UInt32 pos;
+ if (curOptimum.Prev1IsChar && curOptimum.Prev2)
+ {
+ posPrev = curOptimum.PosPrev2;
+ pos = curOptimum.BackPrev2;
+ state.UpdateRep();
+ }
+ else
+ {
+ pos = curOptimum.BackPrev;
+ if (pos < kNumRepDistances)
+ state.UpdateRep();
+ else
+ state.UpdateMatch();
+ }
+ const COptimal &prevOptimum = _optimum[posPrev];
+ if (pos < kNumRepDistances)
+ {
+ reps[0] = prevOptimum.Backs[pos];
+ UInt32 i;
+ for(i = 1; i <= pos; i++)
+ reps[i] = prevOptimum.Backs[i - 1];
+ for(; i < kNumRepDistances; i++)
+ reps[i] = prevOptimum.Backs[i];
+ }
+ else
+ {
+ reps[0] = (pos - kNumRepDistances);
+ for(UInt32 i = 1; i < kNumRepDistances; i++)
+ reps[i] = prevOptimum.Backs[i - 1];
+ }
+ }
+ curOptimum.State = state;
+ for(UInt32 i = 0; i < kNumRepDistances; i++)
+ curOptimum.Backs[i] = reps[i];
+ UInt32 newLen;
+ RINOK(ReadMatchDistances(newLen));
+ if(newLen >= _numFastBytes)
+ {
+ _longestMatchLength = newLen;
+ _longestMatchWasFound = true;
+ lenRes = Backward(backRes, cur);
+ return S_OK;
+ }
+ UInt32 curPrice = curOptimum.Price;
+ // Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
+ // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1);
+ const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
+ Byte currentByte = *data;
+ Byte matchByte = data[(size_t)0 - reps[0] - 1];
+
+ UInt32 posState = (position & _posStateMask);
+
+ UInt32 curAnd1Price = curPrice +
+ _isMatch[state.Index][posState].GetPrice0() +
+ _literalEncoder.GetPrice(position, data[(size_t)0 - 1], !state.IsCharState(), matchByte, currentByte);
+
+ COptimal &nextOptimum = _optimum[cur + 1];
+
+ bool nextIsChar = false;
+ if (curAnd1Price < nextOptimum.Price)
+ {
+ nextOptimum.Price = curAnd1Price;
+ nextOptimum.PosPrev = cur;
+ nextOptimum.MakeAsChar();
+ nextIsChar = true;
+ }
+
+ UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();
+ UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
+
+ if(matchByte == currentByte &&
+ !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
+ if(shortRepPrice <= nextOptimum.Price)
+ {
+ nextOptimum.Price = shortRepPrice;
+ nextOptimum.PosPrev = cur;
+ nextOptimum.MakeAsShortRep();
+ // nextIsChar = false;
+ }
+ }
+ /*
+ if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
+ continue;
+ */
+
+ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1;
+ numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull);
+ UInt32 numAvailableBytes = numAvailableBytesFull;
+
+ if (numAvailableBytes < 2)
+ continue;
+ if (numAvailableBytes > _numFastBytes)
+ numAvailableBytes = _numFastBytes;
+ if (numAvailableBytes >= 3 && !nextIsChar)
+ {
+ // try Literal + rep0
+ UInt32 backOffset = reps[0] + 1;
+ UInt32 temp;
+ for (temp = 1; temp < numAvailableBytes; temp++)
+ if (data[temp] != data[(size_t)temp - backOffset])
+ break;
+ UInt32 lenTest2 = temp - 1;
+ if (lenTest2 >= 2)
+ {
+ CState state2 = state;
+ state2.UpdateChar();
+ UInt32 posStateNext = (position + 1) & _posStateMask;
+ UInt32 nextRepMatchPrice = curAnd1Price +
+ _isMatch[state2.Index][posStateNext].GetPrice1() +
+ _isRep[state2.Index].GetPrice1();
+ // for (; lenTest2 >= 2; lenTest2--)
+ {
+ while(lenEnd < cur + 1 + lenTest2)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+ 0, lenTest2, state2, posStateNext);
+ COptimal &optimum = _optimum[cur + 1 + lenTest2];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = false;
+ }
+ }
+ }
+ }
+ for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
+ {
+ // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
+ UInt32 backOffset = reps[repIndex] + 1;
+ if (data[0] != data[(size_t)0 - backOffset] ||
+ data[1] != data[(size_t)1 - backOffset])
+ continue;
+ UInt32 lenTest;
+ for (lenTest = 2; lenTest < numAvailableBytes; lenTest++)
+ if (data[lenTest] != data[(size_t)lenTest - backOffset])
+ break;
+ UInt32 lenTestTemp = lenTest;
+ do
+ {
+ while(lenEnd < cur + lenTest)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
+ COptimal &optimum = _optimum[cur + lenTest];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur;
+ optimum.BackPrev = repIndex;
+ optimum.Prev1IsChar = false;
+ }
+ }
+ while(--lenTest >= 2);
+ lenTest = lenTestTemp;
+
+ if (_maxMode)
+ {
+ UInt32 lenTest2 = lenTest + 1;
+ UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
+ for (; lenTest2 < limit; lenTest2++)
+ if (data[lenTest2] != data[(size_t)lenTest2 - backOffset])
+ break;
+ lenTest2 -= lenTest + 1;
+ if (lenTest2 >= 2)
+ {
+ CState state2 = state;
+ state2.UpdateRep();
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
+ UInt32 curAndLenCharPrice =
+ repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
+ _isMatch[state2.Index][posStateNext].GetPrice0() +
+ _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
+ true, data[(size_t)lenTest - backOffset], data[lenTest]);
+ state2.UpdateChar();
+ posStateNext = (position + lenTest + 1) & _posStateMask;
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+
+ // for(; lenTest2 >= 2; lenTest2--)
+ {
+ UInt32 offset = lenTest + 1 + lenTest2;
+ while(lenEnd < cur + offset)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+ 0, lenTest2, state2, posStateNext);
+ COptimal &optimum = _optimum[cur + offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + lenTest + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = true;
+ optimum.PosPrev2 = cur;
+ optimum.BackPrev2 = repIndex;
+ }
+ }
+ }
+ }
+ }
+
+ // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
+ if (newLen > numAvailableBytes)
+ newLen = numAvailableBytes;
+ if (newLen >= 2)
+ {
+ if (newLen == 2 && _matchDistances[2] >= 0x80)
+ continue;
+ UInt32 normalMatchPrice = matchPrice +
+ _isRep[state.Index].GetPrice0();
+ while(lenEnd < cur + newLen)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+
+ for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--)
+ {
+ UInt32 curBack = _matchDistances[lenTest];
+ UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
+ COptimal &optimum = _optimum[cur + lenTest];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur;
+ optimum.BackPrev = curBack + kNumRepDistances;
+ optimum.Prev1IsChar = false;
+ }
+
+ if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1]))
+ {
+ // Try Match + Literal + Rep0
+ UInt32 backOffset = curBack + 1;
+ UInt32 lenTest2 = lenTest + 1;
+ UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
+ for (; lenTest2 < limit; lenTest2++)
+ if (data[lenTest2] != data[(size_t)lenTest2 - backOffset])
+ break;
+ lenTest2 -= lenTest + 1;
+ if (lenTest2 >= 2)
+ {
+ CState state2 = state;
+ state2.UpdateMatch();
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
+ UInt32 curAndLenCharPrice = curAndLenPrice +
+ _isMatch[state2.Index][posStateNext].GetPrice0() +
+ _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
+ true, data[(size_t)lenTest - backOffset], data[lenTest]);
+ state2.UpdateChar();
+ posStateNext = (position + lenTest + 1) & _posStateMask;
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+
+ // for(; lenTest2 >= 2; lenTest2--)
+ {
+ UInt32 offset = lenTest + 1 + lenTest2;
+ while(lenEnd < cur + offset)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+ 0, lenTest2, state2, posStateNext);
+ COptimal &optimum = _optimum[cur + offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + lenTest + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = true;
+ optimum.PosPrev2 = cur;
+ optimum.BackPrev2 = curBack + kNumRepDistances;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
+{
+ const int kDif = 7;
+ return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif));
+}
+
+
+HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes)
+{
+ lenRes = _matchFinder->GetLongestMatch(_matchDistances);
+ if (lenRes == _numFastBytes)
+ lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes],
+ kMatchMaxLen - lenRes);
+ _additionalOffset++;
+ return _matchFinder->MovePos();
+}
+
+HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
+{
+ UInt32 lenMain;
+ if (!_longestMatchWasFound)
+ {
+ RINOK(ReadMatchDistances(lenMain));
+ }
+ else
+ {
+ lenMain = _longestMatchLength;
+ _longestMatchWasFound = false;
+ }
+ UInt32 repLens[kNumRepDistances];
+ UInt32 repMaxIndex = 0;
+ for(UInt32 i = 0; i < kNumRepDistances; i++)
+ {
+ repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
+ if (i == 0 || repLens[i] > repLens[repMaxIndex])
+ repMaxIndex = i;
+ }
+ if(repLens[repMaxIndex] >= _numFastBytes)
+ {
+ backRes = repMaxIndex;
+ lenRes = repLens[repMaxIndex];
+ return MovePos(lenRes - 1);
+ }
+ if(lenMain >= _numFastBytes)
+ {
+ backRes = _matchDistances[_numFastBytes] + kNumRepDistances;
+ lenRes = lenMain;
+ return MovePos(lenMain - 1);
+ }
+ while (lenMain > 2)
+ {
+ if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain]))
+ break;
+ lenMain--;
+ }
+ if (lenMain == 2 && _matchDistances[2] >= 0x80)
+ lenMain = 1;
+
+ UInt32 backMain = _matchDistances[lenMain];
+ if (repLens[repMaxIndex] >= 2)
+ {
+ if (repLens[repMaxIndex] + 1 >= lenMain ||
+ repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12)))
+ {
+ backRes = repMaxIndex;
+ lenRes = repLens[repMaxIndex];
+ return MovePos(lenRes - 1);
+ }
+ }
+
+
+ if (lenMain >= 2)
+ {
+ RINOK(ReadMatchDistances(_longestMatchLength));
+ if (_longestMatchLength >= 2 &&
+ (
+ (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) ||
+ _longestMatchLength == lenMain + 1 &&
+ !ChangePair(backMain, _matchDistances[_longestMatchLength]) ||
+ _longestMatchLength > lenMain + 1 ||
+ _longestMatchLength + 1 >= lenMain && lenMain >= 3 &&
+ ChangePair(_matchDistances[lenMain - 1], backMain)
+ )
+ )
+ {
+ _longestMatchWasFound = true;
+ backRes = UInt32(-1);
+ lenRes = 1;
+ return S_OK;
+ }
+ for(UInt32 i = 0; i < kNumRepDistances; i++)
+ {
+ UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
+ if (repLen >= 2 && repLen + 1 >= lenMain)
+ {
+ _longestMatchWasFound = true;
+ backRes = UInt32(-1);
+ lenRes = 1;
+ return S_OK;
+ }
+ }
+ backRes = backMain + kNumRepDistances;
+ lenRes = lenMain;
+ return MovePos(lenMain - 2);
+ }
+ backRes = UInt32(-1);
+ lenRes = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder)
+{
+ _matchFinder = matchFinder;
+ return S_OK;
+}
+
+HRESULT CEncoder::Flush(UInt32 nowPos)
+{
+ ReleaseMFStream();
+ WriteEndMarker(nowPos & _posStateMask);
+ _rangeEncoder.FlushData();
+ return _rangeEncoder.FlushStream();
+}
+
+void CEncoder::WriteEndMarker(UInt32 posState)
+{
+ // This function for writing End Mark for stream version of LZMA.
+ // In current version this feature is not used.
+ if (!_writeEndMark)
+ return;
+
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
+ _isRep[_state.Index].Encode(&_rangeEncoder, 0);
+ _state.UpdateMatch();
+ UInt32 len = kMatchMinLen; // kMatchMaxLen;
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
+ UInt32 posSlot = (1 << kNumPosSlotBits) - 1;
+ UInt32 lenToPosState = GetLenToPosState(len);
+ _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
+ UInt32 footerBits = 30;
+ UInt32 posReduced = (UInt32(1) << footerBits) - 1;
+ _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+ _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
+}
+
+HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress)
+{
+ _needReleaseMFStream = false;
+ CCoderReleaser coderReleaser(this);
+ RINOK(SetStreams(inStream, outStream, inSize, outSize));
+ while(true)
+ {
+ UInt64 processedInSize;
+ UInt64 processedOutSize;
+ Int32 finished;
+ RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));
+ if (finished != 0)
+ return S_OK;
+ if (progress != 0)
+ {
+ RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));
+ }
+ }
+}
+
+HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize)
+{
+ _inStream = inStream;
+ _finished = false;
+ RINOK(Create());
+ RINOK(SetOutStream(outStream));
+ RINOK(Init());
+
+ // CCoderReleaser releaser(this);
+
+ /*
+ if (_matchFinder->GetNumAvailableBytes() == 0)
+ return Flush();
+ */
+
+ if (!_fastMode)
+ {
+ FillPosSlotPrices();
+ FillDistancesPrices();
+ FillAlignPrices();
+ }
+
+ _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
+ _lenEncoder.UpdateTables(1 << _posStateBits);
+ _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
+ _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
+
+ lastPosSlotFillingPos = 0;
+ nowPos64 = 0;
+ return S_OK;
+}
+
+HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
+{
+ if (_inStream != 0)
+ {
+ RINOK(_matchFinder->Init(_inStream));
+ _needReleaseMFStream = true;
+ _inStream = 0;
+ }
+
+
+ *finished = 1;
+ if (_finished)
+ return S_OK;
+ _finished = true;
+
+
+ UInt64 progressPosValuePrev = nowPos64;
+ if (nowPos64 == 0)
+ {
+ if (_matchFinder->GetNumAvailableBytes() == 0)
+ return Flush(UInt32(nowPos64));
+ UInt32 len; // it's not used
+ RINOK(ReadMatchDistances(len));
+ UInt32 posState = UInt32(nowPos64) & _posStateMask;
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
+ _state.UpdateChar();
+ Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
+ _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);
+ _previousByte = curByte;
+ _additionalOffset--;
+ nowPos64++;
+ }
+ if (_matchFinder->GetNumAvailableBytes() == 0)
+ return Flush(UInt32(nowPos64));
+ while(true)
+ {
+ #ifdef _NO_EXCEPTIONS
+ if (_rangeEncoder.Stream.ErrorCode != S_OK)
+ return _rangeEncoder.Stream.ErrorCode;
+ #endif
+ UInt32 pos;
+ UInt32 posState = UInt32(nowPos64) & _posStateMask;
+
+ UInt32 len;
+ HRESULT result;
+ if (_fastMode)
+ result = GetOptimumFast(UInt32(nowPos64), pos, len);
+ else
+ result = GetOptimum(UInt32(nowPos64), pos, len);
+ RINOK(result);
+
+ if(len == 1 && pos == 0xFFFFFFFF)
+ {
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
+ Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
+ CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte);
+ if(!_state.IsCharState())
+ {
+ Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
+ subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
+ }
+ else
+ subCoder->Encode(&_rangeEncoder, curByte);
+ _state.UpdateChar();
+ _previousByte = curByte;
+ }
+ else
+ {
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
+ if(pos < kNumRepDistances)
+ {
+ _isRep[_state.Index].Encode(&_rangeEncoder, 1);
+ if(pos == 0)
+ {
+ _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
+ if(len == 1)
+ _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0);
+ else
+ _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1);
+ }
+ else
+ {
+ _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
+ if (pos == 1)
+ _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
+ else
+ {
+ _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
+ _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
+ }
+ }
+ if (len == 1)
+ _state.UpdateShortRep();
+ else
+ {
+ _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
+ _state.UpdateRep();
+ }
+
+
+ UInt32 distance = _repDistances[pos];
+ if (pos != 0)
+ {
+ for(UInt32 i = pos; i >= 1; i--)
+ _repDistances[i] = _repDistances[i - 1];
+ _repDistances[0] = distance;
+ }
+ }
+ else
+ {
+ _isRep[_state.Index].Encode(&_rangeEncoder, 0);
+ _state.UpdateMatch();
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
+ pos -= kNumRepDistances;
+ UInt32 posSlot = GetPosSlot(pos);
+ UInt32 lenToPosState = GetLenToPosState(len);
+ _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
+
+ if (posSlot >= kStartPosModelIndex)
+ {
+ UInt32 footerBits = ((posSlot >> 1) - 1);
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+ UInt32 posReduced = pos - base;
+
+ if (posSlot < kEndPosModelIndex)
+ NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1,
+ &_rangeEncoder, footerBits, posReduced);
+ else
+ {
+ _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+ _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
+ if (!_fastMode)
+ if (--_alignPriceCount == 0)
+ FillAlignPrices();
+ }
+ }
+ UInt32 distance = pos;
+ for(UInt32 i = kNumRepDistances - 1; i >= 1; i--)
+ _repDistances[i] = _repDistances[i - 1];
+ _repDistances[0] = distance;
+ }
+ _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);
+ }
+ _additionalOffset -= len;
+ nowPos64 += len;
+ if (!_fastMode)
+ if (nowPos64 - lastPosSlotFillingPos >= (1 << 9))
+ {
+ FillPosSlotPrices();
+ FillDistancesPrices();
+ lastPosSlotFillingPos = nowPos64;
+ }
+ if (_additionalOffset == 0)
+ {
+ *inSize = nowPos64;
+ *outSize = _rangeEncoder.GetProcessedSize();
+ if (_matchFinder->GetNumAvailableBytes() == 0)
+ return Flush(UInt32(nowPos64));
+ if (nowPos64 - progressPosValuePrev >= (1 << 12))
+ {
+ _finished = false;
+ *finished = 0;
+ return S_OK;
+ }
+ }
+ }
+}
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress)
+{
+ #ifndef _NO_EXCEPTIONS
+ try
+ {
+ #endif
+ return CodeReal(inStream, outStream, inSize, outSize, progress);
+ #ifndef _NO_EXCEPTIONS
+ }
+ catch(const COutBufferException &e) { return e.ErrorCode; }
+ catch(...) { return E_FAIL; }
+ #endif
+}
+
+void CEncoder::FillPosSlotPrices()
+{
+ for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+ {
+ UInt32 posSlot;
+ for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++)
+ _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot);
+ for (; posSlot < _distTableSize; posSlot++)
+ _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) +
+ ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
+ }
+}
+
+void CEncoder::FillDistancesPrices()
+{
+ for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+ {
+ UInt32 i;
+ for (i = 0; i < kStartPosModelIndex; i++)
+ _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i];
+ for (; i < kNumFullDistances; i++)
+ {
+ UInt32 posSlot = GetPosSlot(i);
+ UInt32 footerBits = ((posSlot >> 1) - 1);
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+
+ _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] +
+ NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +
+ base - posSlot - 1, footerBits, i - base);
+
+ }
+ }
+}
+
+void CEncoder::FillAlignPrices()
+{
+ for (UInt32 i = 0; i < kAlignTableSize; i++)
+ _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
+ _alignPriceCount = kAlignTableSize;
+}
+
+}}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h
new file mode 100644
index 00000000..542994e3
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h
@@ -0,0 +1,416 @@
+// LZMA/Encoder.h
+
+#ifndef __LZMA_ENCODER_H
+#define __LZMA_ENCODER_H
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/Alloc.h"
+#include "../../ICoder.h"
+#include "../LZ/IMatchFinder.h"
+#include "../RangeCoder/RangeCoderBitTree.h"
+
+#include "LZMA.h"
+
+namespace NCompress {
+namespace NLZMA {
+
+typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder;
+
+class CBaseState
+{
+protected:
+ CState _state;
+ Byte _previousByte;
+ UInt32 _repDistances[kNumRepDistances];
+ void Init()
+ {
+ _state.Init();
+ _previousByte = 0;
+ for(UInt32 i = 0 ; i < kNumRepDistances; i++)
+ _repDistances[i] = 0;
+ }
+};
+
+struct COptimal
+{
+ CState State;
+
+ bool Prev1IsChar;
+ bool Prev2;
+
+ UInt32 PosPrev2;
+ UInt32 BackPrev2;
+
+ UInt32 Price;
+ UInt32 PosPrev; // posNext;
+ UInt32 BackPrev;
+ UInt32 Backs[kNumRepDistances];
+ void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; }
+ void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
+ bool IsShortRep() { return (BackPrev == 0); }
+};
+
+
+extern Byte g_FastPos[1024];
+inline UInt32 GetPosSlot(UInt32 pos)
+{
+ if (pos < (1 << 10))
+ return g_FastPos[pos];
+ if (pos < (1 << 19))
+ return g_FastPos[pos >> 9] + 18;
+ return g_FastPos[pos >> 18] + 36;
+}
+
+inline UInt32 GetPosSlot2(UInt32 pos)
+{
+ if (pos < (1 << 16))
+ return g_FastPos[pos >> 6] + 12;
+ if (pos < (1 << 25))
+ return g_FastPos[pos >> 15] + 30;
+ return g_FastPos[pos >> 24] + 48;
+}
+
+const UInt32 kIfinityPrice = 0xFFFFFFF;
+
+const UInt32 kNumOpts = 1 << 12;
+
+
+class CLiteralEncoder2
+{
+ CMyBitEncoder _encoders[0x300];
+public:
+ void Init()
+ {
+ for (int i = 0; i < 0x300; i++)
+ _encoders[i].Init();
+ }
+ void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol);
+ void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol);
+ UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const;
+};
+
+class CLiteralEncoder
+{
+ CLiteralEncoder2 *_coders;
+ int _numPrevBits;
+ int _numPosBits;
+ UInt32 _posMask;
+public:
+ CLiteralEncoder(): _coders(0) {}
+ ~CLiteralEncoder() { Free(); }
+ void Free()
+ {
+ MyFree(_coders);
+ _coders = 0;
+ }
+ bool Create(int numPosBits, int numPrevBits)
+ {
+ if (_coders == 0 || (numPosBits + numPrevBits) !=
+ (_numPrevBits + _numPosBits) )
+ {
+ Free();
+ UInt32 numStates = 1 << (numPosBits + numPrevBits);
+ _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2));
+ }
+ _numPosBits = numPosBits;
+ _posMask = (1 << numPosBits) - 1;
+ _numPrevBits = numPrevBits;
+ return (_coders != 0);
+ }
+ void Init()
+ {
+ UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
+ for (UInt32 i = 0; i < numStates; i++)
+ _coders[i].Init();
+ }
+ UInt32 GetState(UInt32 pos, Byte prevByte) const
+ { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
+ CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)
+ { return &_coders[GetState(pos, prevByte)]; }
+ /*
+ void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
+ Byte symbol)
+ { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); }
+ void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
+ Byte matchByte, Byte symbol)
+ { _coders[GetState(pos, prevByte)].Encode(rangeEncoder,
+ matchByte, symbol); }
+ */
+ UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const
+ { return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); }
+};
+
+namespace NLength {
+
+class CEncoder
+{
+ CMyBitEncoder _choice;
+ CMyBitEncoder _choice2;
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;
+public:
+ void Init(UInt32 numPosStates);
+ void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);
+ UInt32 GetPrice(UInt32 symbol, UInt32 posState) const;
+};
+
+const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
+
+class CPriceTableEncoder: public CEncoder
+{
+ UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax];
+ UInt32 _tableSize;
+ UInt32 _counters[kNumPosStatesEncodingMax];
+public:
+ void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
+ UInt32 GetPrice(UInt32 symbol, UInt32 posState) const
+ { return _prices[symbol][posState]; }
+ void UpdateTable(UInt32 posState)
+ {
+ for (UInt32 len = 0; len < _tableSize; len++)
+ _prices[len][posState] = CEncoder::GetPrice(len, posState);
+ _counters[posState] = _tableSize;
+ }
+ void UpdateTables(UInt32 numPosStates)
+ {
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
+ UpdateTable(posState);
+ }
+ void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
+ {
+ CEncoder::Encode(rangeEncoder, symbol, posState);
+ if (--_counters[posState] == 0)
+ UpdateTable(posState);
+ }
+};
+
+}
+
+class CEncoder :
+ public ICompressCoder,
+ public ICompressSetOutStream,
+ public ICompressSetCoderProperties,
+ public ICompressWriteCoderProperties,
+ public CBaseState,
+ public CMyUnknownImp
+{
+ COptimal _optimum[kNumOpts];
+ CMyComPtr<IMatchFinder> _matchFinder; // test it
+ NRangeCoder::CEncoder _rangeEncoder;
+
+ CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];
+ CMyBitEncoder _isRep[kNumStates];
+ CMyBitEncoder _isRepG0[kNumStates];
+ CMyBitEncoder _isRepG1[kNumStates];
+ CMyBitEncoder _isRepG2[kNumStates];
+ CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax];
+
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];
+
+ CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder;
+
+ NLength::CPriceTableEncoder _lenEncoder;
+ NLength::CPriceTableEncoder _repMatchLenEncoder;
+
+ CLiteralEncoder _literalEncoder;
+
+ UInt32 _matchDistances[kMatchMaxLen + 1];
+
+ bool _fastMode;
+ bool _maxMode;
+ UInt32 _numFastBytes;
+ UInt32 _longestMatchLength;
+
+ UInt32 _additionalOffset;
+
+ UInt32 _optimumEndIndex;
+ UInt32 _optimumCurrentIndex;
+
+ bool _longestMatchWasFound;
+
+ UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+
+ UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances];
+
+ UInt32 _alignPrices[kAlignTableSize];
+ UInt32 _alignPriceCount;
+
+ UInt32 _distTableSize;
+
+ UInt32 _posStateBits;
+ UInt32 _posStateMask;
+ UInt32 _numLiteralPosStateBits;
+ UInt32 _numLiteralContextBits;
+
+ UInt32 _dictionarySize;
+
+ UInt32 _dictionarySizePrev;
+ UInt32 _numFastBytesPrev;
+
+ UInt64 lastPosSlotFillingPos;
+ UInt64 nowPos64;
+ bool _finished;
+ ISequentialInStream *_inStream;
+
+ int _matchFinderIndex;
+ #ifdef COMPRESS_MF_MT
+ bool _multiThread;
+ #endif
+
+ bool _writeEndMark;
+
+ bool _needReleaseMFStream;
+
+ HRESULT ReadMatchDistances(UInt32 &len);
+
+ HRESULT MovePos(UInt32 num);
+ UInt32 GetRepLen1Price(CState state, UInt32 posState) const
+ {
+ return _isRepG0[state.Index].GetPrice0() +
+ _isRep0Long[state.Index][posState].GetPrice0();
+ }
+ UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
+ {
+ UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState);
+ if(repIndex == 0)
+ {
+ price += _isRepG0[state.Index].GetPrice0();
+ price += _isRep0Long[state.Index][posState].GetPrice1();
+ }
+ else
+ {
+ price += _isRepG0[state.Index].GetPrice1();
+ if (repIndex == 1)
+ price += _isRepG1[state.Index].GetPrice0();
+ else
+ {
+ price += _isRepG1[state.Index].GetPrice1();
+ price += _isRepG2[state.Index].GetPrice(repIndex - 2);
+ }
+ }
+ return price;
+ }
+ /*
+ UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const
+ {
+ if (pos >= kNumFullDistances)
+ return kIfinityPrice;
+ return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState);
+ }
+ UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const
+ {
+ UInt32 price;
+ UInt32 lenToPosState = GetLenToPosState(len);
+ if (pos < kNumFullDistances)
+ price = _distancesPrices[lenToPosState][pos];
+ else
+ price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
+ _alignPrices[pos & kAlignMask];
+ return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
+ }
+ */
+ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const
+ {
+ if (len == 2 && pos >= 0x80)
+ return kIfinityPrice;
+ UInt32 price;
+ UInt32 lenToPosState = GetLenToPosState(len);
+ if (pos < kNumFullDistances)
+ price = _distancesPrices[lenToPosState][pos];
+ else
+ price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
+ _alignPrices[pos & kAlignMask];
+ return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
+ }
+
+ UInt32 Backward(UInt32 &backRes, UInt32 cur);
+ HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
+ HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
+
+ void FillPosSlotPrices();
+ void FillDistancesPrices();
+ void FillAlignPrices();
+
+ void ReleaseMFStream()
+ {
+ if (_matchFinder && _needReleaseMFStream)
+ {
+ _matchFinder->ReleaseStream();
+ _needReleaseMFStream = false;
+ }
+ }
+
+ void ReleaseStreams()
+ {
+ ReleaseMFStream();
+ ReleaseOutStream();
+ }
+
+ HRESULT Flush(UInt32 nowPos);
+ class CCoderReleaser
+ {
+ CEncoder *_coder;
+ public:
+ CCoderReleaser(CEncoder *coder): _coder(coder) {}
+ ~CCoderReleaser()
+ {
+ _coder->ReleaseStreams();
+ }
+ };
+ friend class CCoderReleaser;
+
+ void WriteEndMarker(UInt32 posState);
+
+public:
+ CEncoder();
+ void SetWriteEndMarkerMode(bool writeEndMarker)
+ { _writeEndMark= writeEndMarker; }
+
+ HRESULT Create();
+
+ MY_UNKNOWN_IMP3(
+ ICompressSetOutStream,
+ ICompressSetCoderProperties,
+ ICompressWriteCoderProperties
+ )
+
+ HRESULT Init();
+
+ // ICompressCoder interface
+ HRESULT SetStreams(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize);
+ HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished);
+
+ HRESULT CodeReal(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress);
+
+ // ICompressCoder interface
+ STDMETHOD(Code)(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress);
+
+ // IInitMatchFinder interface
+ STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder);
+
+ // ICompressSetCoderProperties2
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
+ const PROPVARIANT *properties, UInt32 numProperties);
+
+ // ICompressWriteCoderProperties
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+
+ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
+ STDMETHOD(ReleaseOutStream)();
+
+ virtual ~CEncoder() {}
+};
+
+}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/StdAfx.h
new file mode 100644
index 00000000..83fdd22d
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp
new file mode 100644
index 00000000..41d5b489
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp
@@ -0,0 +1,523 @@
+# Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=AloneLZMA - Win32 DebugU
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "AloneLZMA.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application")
+!MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "AloneLZMA - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseU"
+# PROP BASE Intermediate_Dir "ReleaseU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseU"
+# PROP Intermediate_Dir "ReleaseU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugU"
+# PROP BASE Intermediate_Dir "DebugU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "AloneLZMA - Win32 Release"
+# Name "AloneLZMA - Win32 Debug"
+# Name "AloneLZMA - Win32 ReleaseU"
+# Name "AloneLZMA - Win32 DebugU"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Group "LZMA"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\LZMA\LZMA.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMADecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMADecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMAEncoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMAEncoder.h
+# End Source File
+# End Group
+# Begin Group "RangeCoder"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderBit.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderBit.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderBitTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderOpt.h
+# End Source File
+# End Group
+# Begin Group "LZ"
+
+# PROP Default_Filter ""
+# Begin Group "Pat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\LZ\Patricia\Pat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\Patricia\Pat2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\Patricia\Pat2H.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\Patricia\Pat2R.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\Patricia\Pat3H.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\Patricia\Pat4H.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\Patricia\PatMain.h
+# End Source File
+# End Group
+# Begin Group "BT"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTree2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTree3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTree3Z.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTree3ZMain.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTree4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTree4b.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\BinTree\BinTreeMain.h
+# End Source File
+# End Group
+# Begin Group "HC"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\LZ\HashChain\HC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\HashChain\HC2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\HashChain\HC3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\HashChain\HC4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\HashChain\HC4b.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\HashChain\HCMain.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\LZ\IMatchFinder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\LZInWindow.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\LZInWindow.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\LZOutWindow.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\LZOutWindow.h
+# End Source File
+# End Group
+# Begin Group "Branch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Branch\BranchX86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\Branch\BranchX86.h
+# End Source File
+# End Group
+# Begin Group "LZMA_C"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\LZMA_C\LzmaDecode.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA_C\LzmaDecode.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyWindows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\String.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Vector.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\ICoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaAlone.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaBench.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaBench.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRam.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRamDecode.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRamDecode.h
+# End Source File
+# End Target
+# End Project
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw
new file mode 100644
index 00000000..7402f297
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp
new file mode 100644
index 00000000..52149033
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp
@@ -0,0 +1,509 @@
+// LzmaAlone.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/MyInitGuid.h"
+
+#include <stdio.h>
+
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
+#include <fcntl.h>
+#include <io.h>
+#define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
+#else
+#define MY_SET_BINARY_MODE(file)
+#endif
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+
+#include "LzmaBench.h"
+#include "LzmaRam.h"
+
+extern "C"
+{
+#include "LzmaRamDecode.h"
+}
+
+using namespace NCommandLineParser;
+
+#ifdef _WIN32
+bool g_IsNT = false;
+static inline bool IsItWindowsNT()
+{
+ OSVERSIONINFO versionInfo;
+ versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+ if (!::GetVersionEx(&versionInfo))
+ return false;
+ return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
+
+static const char *kCantAllocate = "Can not allocate memory";
+static const char *kReadError = "Read error";
+static const char *kWriteError = "Write error";
+
+namespace NKey {
+enum Enum
+{
+ kHelp1 = 0,
+ kHelp2,
+ kMode,
+ kDictionary,
+ kFastBytes,
+ kLitContext,
+ kLitPos,
+ kPosBits,
+ kMatchFinder,
+ kEOS,
+ kStdIn,
+ kStdOut,
+ kFilter86
+};
+}
+
+static const CSwitchForm kSwitchForms[] =
+{
+ { L"?", NSwitchType::kSimple, false },
+ { L"H", NSwitchType::kSimple, false },
+ { L"A", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"D", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },
+ { L"EOS", NSwitchType::kSimple, false },
+ { L"SI", NSwitchType::kSimple, false },
+ { L"SO", NSwitchType::kSimple, false },
+ { L"F86", NSwitchType::kSimple, false }
+};
+
+static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);
+
+static void PrintHelp()
+{
+ fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n"
+ " e: encode file\n"
+ " d: decode file\n"
+ " b: Benchmark\n"
+ "<Switches>\n"
+ " -a{N}: set compression mode - [0, 2], default: 2 (max)\n"
+ " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n"
+ " -fb{N}: set number of fast bytes - [5, 273], default: 128\n"
+ " -lc{N}: set number of literal context bits - [0, 8], default: 3\n"
+ " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"
+ " -pb{N}: set number of pos bits - [0, 4], default: 2\n"
+ " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,\n"
+ " pat2h, pat3h, pat4h, hc3, hc4], default: bt4\n"
+ " -eos: write End Of Stream marker\n"
+ " -si: read data from stdin\n"
+ " -so: write data to stdout\n"
+ );
+}
+
+static void PrintHelpAndExit(const char *s)
+{
+ fprintf(stderr, "\nError: %s\n\n", s);
+ PrintHelp();
+ throw -1;
+}
+
+static void IncorrectCommand()
+{
+ PrintHelpAndExit("Incorrect command");
+}
+
+static void WriteArgumentsToStringList(int numArguments, const char *arguments[],
+ UStringVector &strings)
+{
+ for(int i = 1; i < numArguments; i++)
+ strings.Add(MultiByteToUnicodeString(arguments[i]));
+}
+
+static bool GetNumber(const wchar_t *s, UInt32 &value)
+{
+ value = 0;
+ if (MyStringLen(s) == 0)
+ return false;
+ const wchar_t *end;
+ UInt64 res = ConvertStringToUInt64(s, &end);
+ if (*end != L'\0')
+ return false;
+ if (res > 0xFFFFFFFF)
+ return false;
+ value = UInt32(res);
+ return true;
+}
+
+int main2(int n, const char *args[])
+{
+ #ifdef _WIN32
+ g_IsNT = IsItWindowsNT();
+ #endif
+
+ fprintf(stderr, "\nLZMA 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n");
+
+ if (n == 1)
+ {
+ PrintHelp();
+ return 0;
+ }
+
+ if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4)
+ {
+ fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile");
+ return 1;
+ }
+
+ UStringVector commandStrings;
+ WriteArgumentsToStringList(n, args, commandStrings);
+ CParser parser(kNumSwitches);
+ try
+ {
+ parser.ParseStrings(kSwitchForms, commandStrings);
+ }
+ catch(...)
+ {
+ IncorrectCommand();
+ }
+
+ if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
+ {
+ PrintHelp();
+ return 0;
+ }
+ const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
+
+ int paramIndex = 0;
+ if (paramIndex >= nonSwitchStrings.Size())
+ IncorrectCommand();
+ const UString &command = nonSwitchStrings[paramIndex++];
+
+ bool dictionaryIsDefined = false;
+ UInt32 dictionary = 1 << 21;
+ if(parser[NKey::kDictionary].ThereIs)
+ {
+ UInt32 dicLog;
+ if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog))
+ IncorrectCommand();
+ dictionary = 1 << dicLog;
+ dictionaryIsDefined = true;
+ }
+ UString mf = L"BT4";
+ if (parser[NKey::kMatchFinder].ThereIs)
+ mf = parser[NKey::kMatchFinder].PostStrings[0];
+
+ if (command.CompareNoCase(L"b") == 0)
+ {
+ const UInt32 kNumDefaultItereations = 10;
+ UInt32 numIterations = kNumDefaultItereations;
+ {
+ if (paramIndex < nonSwitchStrings.Size())
+ if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
+ numIterations = kNumDefaultItereations;
+ }
+ return LzmaBenchmark(stderr, numIterations, dictionary,
+ mf.CompareNoCase(L"BT4") == 0);
+ }
+
+ bool encodeMode = false;
+ if (command.CompareNoCase(L"e") == 0)
+ encodeMode = true;
+ else if (command.CompareNoCase(L"d") == 0)
+ encodeMode = false;
+ else
+ IncorrectCommand();
+
+ bool stdInMode = parser[NKey::kStdIn].ThereIs;
+ bool stdOutMode = parser[NKey::kStdOut].ThereIs;
+
+ CMyComPtr<ISequentialInStream> inStream;
+ CInFileStream *inStreamSpec = 0;
+ if (stdInMode)
+ {
+ inStream = new CStdInFileStream;
+ MY_SET_BINARY_MODE(stdin);
+ }
+ else
+ {
+ if (paramIndex >= nonSwitchStrings.Size())
+ IncorrectCommand();
+ const UString &inputName = nonSwitchStrings[paramIndex++];
+ inStreamSpec = new CInFileStream;
+ inStream = inStreamSpec;
+ if (!inStreamSpec->Open(GetSystemString(inputName)))
+ {
+ fprintf(stderr, "\nError: can not open input file %s\n",
+ (const char *)GetOemString(inputName));
+ return 1;
+ }
+ }
+
+ CMyComPtr<ISequentialOutStream> outStream;
+ if (stdOutMode)
+ {
+ outStream = new CStdOutFileStream;
+ MY_SET_BINARY_MODE(stdout);
+ }
+ else
+ {
+ if (paramIndex >= nonSwitchStrings.Size())
+ IncorrectCommand();
+ const UString &outputName = nonSwitchStrings[paramIndex++];
+ COutFileStream *outStreamSpec = new COutFileStream;
+ outStream = outStreamSpec;
+ if (!outStreamSpec->Create(GetSystemString(outputName), true))
+ {
+ fprintf(stderr, "\nError: can not open output file %s\n",
+ (const char *)GetOemString(outputName));
+ return 1;
+ }
+ }
+
+ if (parser[NKey::kFilter86].ThereIs)
+ {
+ // -f86 switch is for x86 filtered mode: BCJ + LZMA.
+ if (parser[NKey::kEOS].ThereIs || stdInMode)
+ throw "Can not use stdin in this mode";
+ UInt64 fileSize;
+ inStreamSpec->File.GetLength(fileSize);
+ if (fileSize > 0xF0000000)
+ throw "File is too big";
+ UInt32 inSize = (UInt32)fileSize;
+ Byte *inBuffer = 0;
+ if (inSize != 0)
+ {
+ inBuffer = (Byte *)MyAlloc((size_t)inSize);
+ if (inBuffer == 0)
+ throw kCantAllocate;
+ }
+
+ UInt32 processedSize;
+ if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK)
+ throw "Can not read";
+ if ((UInt32)inSize != processedSize)
+ throw "Read size error";
+
+ Byte *outBuffer = 0;
+ size_t outSizeProcessed;
+ if (encodeMode)
+ {
+ // we allocate 105% of original size for output buffer
+ size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
+ if (outSize != 0)
+ {
+ outBuffer = (Byte *)MyAlloc((size_t)outSize);
+ if (outBuffer == 0)
+ throw kCantAllocate;
+ }
+ if (!dictionaryIsDefined)
+ dictionary = 1 << 23;
+ int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed,
+ dictionary, SZ_FILTER_AUTO);
+ if (res != 0)
+ {
+ fprintf(stderr, "\nEncoder error = %d\n", (int)res);
+ return 1;
+ }
+ }
+ else
+ {
+ size_t outSize;
+ if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0)
+ throw "data error";
+ if (outSize != 0)
+ {
+ outBuffer = (Byte *)MyAlloc(outSize);
+ if (outBuffer == 0)
+ throw kCantAllocate;
+ }
+ int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free);
+ if (res != 0)
+ throw "LzmaDecoder error";
+ }
+ if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK)
+ throw kWriteError;
+ MyFree(outBuffer);
+ MyFree(inBuffer);
+ return 0;
+ }
+
+
+ UInt64 fileSize;
+ if (encodeMode)
+ {
+ NCompress::NLZMA::CEncoder *encoderSpec =
+ new NCompress::NLZMA::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ if (!dictionaryIsDefined)
+ dictionary = 1 << 23;
+
+ UInt32 posStateBits = 2;
+ UInt32 litContextBits = 3; // for normal files
+ // UInt32 litContextBits = 0; // for 32-bit data
+ UInt32 litPosBits = 0;
+ // UInt32 litPosBits = 2; // for 32-bit data
+ UInt32 algorithm = 2;
+ UInt32 numFastBytes = 128;
+
+ bool eos = parser[NKey::kEOS].ThereIs || stdInMode;
+
+ if(parser[NKey::kMode].ThereIs)
+ if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm))
+ IncorrectCommand();
+
+ if(parser[NKey::kFastBytes].ThereIs)
+ if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes))
+ IncorrectCommand();
+ if(parser[NKey::kLitContext].ThereIs)
+ if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits))
+ IncorrectCommand();
+ if(parser[NKey::kLitPos].ThereIs)
+ if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits))
+ IncorrectCommand();
+ if(parser[NKey::kPosBits].ThereIs)
+ if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits))
+ IncorrectCommand();
+
+ PROPID propIDs[] =
+ {
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kPosStateBits,
+ NCoderPropID::kLitContextBits,
+ NCoderPropID::kLitPosBits,
+ NCoderPropID::kAlgorithm,
+ NCoderPropID::kNumFastBytes,
+ NCoderPropID::kMatchFinder,
+ NCoderPropID::kEndMarker
+ };
+ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+ /*
+ NWindows::NCOM::CPropVariant properties[kNumProps];
+ properties[0] = UInt32(dictionary);
+ properties[1] = UInt32(posStateBits);
+ properties[2] = UInt32(litContextBits);
+
+ properties[3] = UInt32(litPosBits);
+ properties[4] = UInt32(algorithm);
+ properties[5] = UInt32(numFastBytes);
+ properties[6] = mf;
+ properties[7] = eos;
+ */
+ PROPVARIANT properties[kNumProps];
+ for (int p = 0; p < 6; p++)
+ properties[p].vt = VT_UI4;
+ properties[0].ulVal = UInt32(dictionary);
+ properties[1].ulVal = UInt32(posStateBits);
+ properties[2].ulVal = UInt32(litContextBits);
+ properties[3].ulVal = UInt32(litPosBits);
+ properties[4].ulVal = UInt32(algorithm);
+ properties[5].ulVal = UInt32(numFastBytes);
+
+ properties[6].vt = VT_BSTR;
+ properties[6].bstrVal = (BSTR)(const wchar_t *)mf;
+
+ properties[7].vt = VT_BOOL;
+ properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;
+
+ if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
+ IncorrectCommand();
+ encoderSpec->WriteCoderProperties(outStream);
+
+ if (eos || stdInMode)
+ fileSize = (UInt64)(Int64)-1;
+ else
+ inStreamSpec->File.GetLength(fileSize);
+
+ for (int i = 0; i < 8; i++)
+ {
+ Byte b = Byte(fileSize >> (8 * i));
+ if (outStream->Write(&b, 1, 0) != S_OK)
+ {
+ fprintf(stderr, kWriteError);
+ return 1;
+ }
+ }
+ HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
+ if (result == E_OUTOFMEMORY)
+ {
+ fprintf(stderr, "\nError: Can not allocate memory\n");
+ return 1;
+ }
+ else if (result != S_OK)
+ {
+ fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);
+ return 1;
+ }
+ }
+ else
+ {
+ NCompress::NLZMA::CDecoder *decoderSpec =
+ new NCompress::NLZMA::CDecoder;
+ CMyComPtr<ICompressCoder> decoder = decoderSpec;
+ const UInt32 kPropertiesSize = 5;
+ Byte properties[kPropertiesSize];
+ UInt32 processedSize;
+ if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK)
+ {
+ fprintf(stderr, kReadError);
+ return 1;
+ }
+ if (processedSize != kPropertiesSize)
+ {
+ fprintf(stderr, kReadError);
+ return 1;
+ }
+ if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK)
+ {
+ fprintf(stderr, "SetDecoderProperties error");
+ return 1;
+ }
+ fileSize = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ Byte b;
+ if (inStream->Read(&b, 1, &processedSize) != S_OK)
+ {
+ fprintf(stderr, kReadError);
+ return 1;
+ }
+ if (processedSize != 1)
+ {
+ fprintf(stderr, kReadError);
+ return 1;
+ }
+ fileSize |= ((UInt64)b) << (8 * i);
+ }
+ if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
+ {
+ fprintf(stderr, "Decoder error");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int main(int n, const char *args[])
+{
+ try { return main2(n, args); }
+ catch(const char *s)
+ {
+ fprintf(stderr, "\nError: %s\n", s);
+ return 1;
+ }
+ catch(...)
+ {
+ fprintf(stderr, "\nError\n");
+ return 1;
+ }
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp
new file mode 100644
index 00000000..fd6af9bd
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp
@@ -0,0 +1,508 @@
+// LzmaBench.cpp
+
+#include "StdAfx.h"
+
+#include "LzmaBench.h"
+
+#ifndef _WIN32
+#include <time.h>
+#endif
+
+#include "../../../Common/CRC.h"
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+
+static const UInt32 kAdditionalSize =
+#ifdef _WIN32_WCE
+(1 << 20);
+#else
+(6 << 20);
+#endif
+
+static const UInt32 kCompressedAdditionalSize = (1 << 10);
+static const UInt32 kMaxLzmaPropSize = 10;
+
+class CRandomGenerator
+{
+ UInt32 A1;
+ UInt32 A2;
+public:
+ CRandomGenerator() { Init(); }
+ void Init() { A1 = 362436069; A2 = 521288629;}
+ UInt32 GetRnd()
+ {
+ return
+ ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^
+ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
+ }
+};
+
+class CBitRandomGenerator
+{
+ CRandomGenerator RG;
+ UInt32 Value;
+ int NumBits;
+public:
+ void Init()
+ {
+ Value = 0;
+ NumBits = 0;
+ }
+ UInt32 GetRnd(int numBits)
+ {
+ if (NumBits > numBits)
+ {
+ UInt32 result = Value & ((1 << numBits) - 1);
+ Value >>= numBits;
+ NumBits -= numBits;
+ return result;
+ }
+ numBits -= NumBits;
+ UInt32 result = (Value << numBits);
+ Value = RG.GetRnd();
+ result |= Value & ((1 << numBits) - 1);
+ Value >>= numBits;
+ NumBits = 32 - numBits;
+ return result;
+ }
+};
+
+class CBenchRandomGenerator
+{
+ CBitRandomGenerator RG;
+ UInt32 Pos;
+public:
+ UInt32 BufferSize;
+ Byte *Buffer;
+ CBenchRandomGenerator(): Buffer(0) {}
+ ~CBenchRandomGenerator() { delete []Buffer; }
+ void Init() { RG.Init(); }
+ void Set(UInt32 bufferSize)
+ {
+ delete []Buffer;
+ Buffer = 0;
+ Buffer = new Byte[bufferSize];
+ Pos = 0;
+ BufferSize = bufferSize;
+ }
+ UInt32 GetRndBit() { return RG.GetRnd(1); }
+ /*
+ UInt32 GetLogRand(int maxLen)
+ {
+ UInt32 len = GetRnd() % (maxLen + 1);
+ return GetRnd() & ((1 << len) - 1);
+ }
+ */
+ UInt32 GetLogRandBits(int numBits)
+ {
+ UInt32 len = RG.GetRnd(numBits);
+ return RG.GetRnd(len);
+ }
+ UInt32 GetOffset()
+ {
+ if (GetRndBit() == 0)
+ return GetLogRandBits(4);
+ return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
+ }
+ UInt32 GetLen()
+ {
+ if (GetRndBit() == 0)
+ return RG.GetRnd(2);
+ if (GetRndBit() == 0)
+ return 4 + RG.GetRnd(3);
+ return 12 + RG.GetRnd(4);
+ }
+ void Generate()
+ {
+ while(Pos < BufferSize)
+ {
+ if (GetRndBit() == 0 || Pos < 1)
+ Buffer[Pos++] = Byte(RG.GetRnd(8));
+ else
+ {
+ UInt32 offset = GetOffset();
+ while (offset >= Pos)
+ offset >>= 1;
+ offset += 1;
+ UInt32 len = 2 + GetLen();
+ for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
+ Buffer[Pos] = Buffer[Pos - offset];
+ }
+ }
+ }
+};
+
+class CBenchmarkInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ const Byte *Data;
+ UInt32 Pos;
+ UInt32 Size;
+public:
+ MY_UNKNOWN_IMP
+ void Init(const Byte *data, UInt32 size)
+ {
+ Data = data;
+ Size = size;
+ Pos = 0;
+ }
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 remain = Size - Pos;
+ if (size > remain)
+ size = remain;
+ for (UInt32 i = 0; i < size; i++)
+ ((Byte *)data)[i] = Data[Pos + i];
+ Pos += size;
+ if(processedSize != NULL)
+ *processedSize = size;
+ return S_OK;
+}
+
+class CBenchmarkOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ UInt32 BufferSize;
+ FILE *_f;
+public:
+ UInt32 Pos;
+ Byte *Buffer;
+ CBenchmarkOutStream(): _f(0), Buffer(0) {}
+ virtual ~CBenchmarkOutStream() { delete []Buffer; }
+ void Init(FILE *f, UInt32 bufferSize)
+ {
+ delete []Buffer;
+ Buffer = 0;
+ Buffer = new Byte[bufferSize];
+ Pos = 0;
+ BufferSize = bufferSize;
+ _f = f;
+ }
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 i;
+ for (i = 0; i < size && Pos < BufferSize; i++)
+ Buffer[Pos++] = ((const Byte *)data)[i];
+ if(processedSize != NULL)
+ *processedSize = i;
+ if (i != size)
+ {
+ fprintf(_f, "\nERROR: Buffer is full\n");
+ return E_FAIL;
+ }
+ return S_OK;
+}
+
+class CCrcOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ CCRC CRC;
+ MY_UNKNOWN_IMP
+ void Init() { CRC.Init(); }
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ CRC.Update(data, size);
+ if(processedSize != NULL)
+ *processedSize = size;
+ return S_OK;
+}
+
+static UInt64 GetTimeCount()
+{
+ #ifdef _WIN32
+ LARGE_INTEGER value;
+ if (::QueryPerformanceCounter(&value))
+ return value.QuadPart;
+ return GetTickCount();
+ #else
+ return clock();
+ #endif
+}
+
+static UInt64 GetFreq()
+{
+ #ifdef _WIN32
+ LARGE_INTEGER value;
+ if (::QueryPerformanceFrequency(&value))
+ return value.QuadPart;
+ return 1000;
+ #else
+ return CLOCKS_PER_SEC;
+ #endif
+}
+
+struct CProgressInfo:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ UInt64 ApprovedStart;
+ UInt64 InSize;
+ UInt64 Time;
+ void Init()
+ {
+ InSize = 0;
+ Time = 0;
+ }
+ MY_UNKNOWN_IMP
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ if (*inSize >= ApprovedStart && InSize == 0)
+ {
+ Time = ::GetTimeCount();
+ InSize = *inSize;
+ }
+ return S_OK;
+}
+
+static const int kSubBits = 8;
+
+static UInt32 GetLogSize(UInt32 size)
+{
+ for (int i = kSubBits; i < 32; i++)
+ for (UInt32 j = 0; j < (1 << kSubBits); j++)
+ if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
+ return (i << kSubBits) + j;
+ return (32 << kSubBits);
+}
+
+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime)
+{
+ UInt64 freq = GetFreq();
+ UInt64 elTime = elapsedTime;
+ while(freq > 1000000)
+ {
+ freq >>= 1;
+ elTime >>= 1;
+ }
+ if (elTime == 0)
+ elTime = 1;
+ return value * freq / elTime;
+}
+
+static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4,
+ UInt64 elapsedTime, UInt64 size)
+{
+ UInt64 numCommandsForOne;
+ if (isBT4)
+ {
+ UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits);
+ numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits));
+ }
+ else
+ {
+ UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits);
+ numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits));
+ }
+ UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
+ return MyMultDiv64(numCommands, elapsedTime);
+}
+
+static UInt64 GetDecompressRating(UInt64 elapsedTime,
+ UInt64 outSize, UInt64 inSize)
+{
+ UInt64 numCommands = inSize * 250 + outSize * 21;
+ return MyMultDiv64(numCommands, elapsedTime);
+}
+
+/*
+static UInt64 GetTotalRating(
+ UInt32 dictionarySize,
+ bool isBT4,
+ UInt64 elapsedTimeEn, UInt64 sizeEn,
+ UInt64 elapsedTimeDe,
+ UInt64 inSizeDe, UInt64 outSizeDe)
+{
+ return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) +
+ GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
+}
+*/
+
+static void PrintRating(FILE *f, UInt64 rating)
+{
+ fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000));
+}
+
+static void PrintResults(
+ FILE *f,
+ UInt32 dictionarySize,
+ bool isBT4,
+ UInt64 elapsedTime,
+ UInt64 size,
+ bool decompressMode, UInt64 secondSize)
+{
+ UInt64 speed = MyMultDiv64(size, elapsedTime);
+ fprintf(f, "%6d KB/s ", (unsigned int)(speed / 1024));
+ UInt64 rating;
+ if (decompressMode)
+ rating = GetDecompressRating(elapsedTime, size, secondSize);
+ else
+ rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size);
+ PrintRating(f, rating);
+}
+
+static void ThrowError(FILE *f, HRESULT result, const char *s)
+{
+ fprintf(f, "\nError: ");
+ if (result == E_ABORT)
+ fprintf(f, "User break");
+ if (result == E_OUTOFMEMORY)
+ fprintf(f, "Can not allocate memory");
+ else
+ fprintf(f, s);
+ fprintf(f, "\n");
+}
+
+const wchar_t *bt2 = L"BT2";
+const wchar_t *bt4 = L"BT4";
+
+int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4)
+{
+ if (numIterations == 0)
+ return 0;
+ if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15))
+ {
+ fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n");
+ return 1;
+ }
+ fprintf(f, "\n Compressing Decompressing\n\n");
+ NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder;
+ CMyComPtr<ICompressCoder> decoder = decoderSpec;
+
+ CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream;
+ CMyComPtr<ISequentialOutStream> propStream = propStreamSpec;
+ propStreamSpec->Init(f, kMaxLzmaPropSize);
+
+ PROPID propIDs[] =
+ {
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kMatchFinder
+ };
+ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+ PROPVARIANT properties[kNumProps];
+ properties[0].vt = VT_UI4;
+ properties[0].ulVal = UInt32(dictionarySize);
+
+ properties[1].vt = VT_BSTR;
+ properties[1].bstrVal = isBT4 ? (BSTR)bt4: (BSTR)bt2;
+
+ const UInt32 kBufferSize = dictionarySize + kAdditionalSize;
+ const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
+
+ if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
+ {
+ fprintf(f, "\nError: Incorrect command\n");
+ return 1;
+ }
+ encoderSpec->WriteCoderProperties(propStream);
+
+ CBenchRandomGenerator rg;
+ rg.Init();
+ rg.Set(kBufferSize);
+ rg.Generate();
+ CCRC crc;
+ crc.Update(rg.Buffer, rg.BufferSize);
+
+ CProgressInfo *progressInfoSpec = new CProgressInfo;
+ CMyComPtr<ICompressProgressInfo> progressInfo = progressInfoSpec;
+
+ progressInfoSpec->ApprovedStart = dictionarySize;
+
+ UInt64 totalBenchSize = 0;
+ UInt64 totalEncodeTime = 0;
+ UInt64 totalDecodeTime = 0;
+ UInt64 totalCompressedSize = 0;
+
+ for (UInt32 i = 0; i < numIterations; i++)
+ {
+ progressInfoSpec->Init();
+ CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
+ inStreamSpec->Init(rg.Buffer, rg.BufferSize);
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+ CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream;
+ outStreamSpec->Init(f, kCompressedBufferSize);
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo);
+ UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time;
+ UInt32 compressedSize = outStreamSpec->Pos;
+ if(result != S_OK)
+ {
+ ThrowError(f, result, "Encoder Error");
+ return 1;
+ }
+ if (progressInfoSpec->InSize == 0)
+ {
+ fprintf(f, "\nError: Internal ERROR 1282\n");
+ return 1;
+ }
+
+ ///////////////////////
+ // Decompressing
+
+ CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;
+ CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;
+
+ UInt64 decodeTime;
+ for (int j = 0; j < 2; j++)
+ {
+ inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
+ crcOutStreamSpec->Init();
+
+ if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK)
+ {
+ fprintf(f, "\nError: Set Decoder Properties Error\n");
+ return 1;
+ }
+ UInt64 outSize = kBufferSize;
+ UInt64 startTime = ::GetTimeCount();
+ result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0);
+ decodeTime = ::GetTimeCount() - startTime;
+ if(result != S_OK)
+ {
+ ThrowError(f, result, "Decode Error");
+ return 1;
+ }
+ if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest())
+ {
+ fprintf(f, "\nError: CRC Error\n");
+ return 1;
+ }
+ }
+ UInt64 benchSize = kBufferSize - progressInfoSpec->InSize;
+ PrintResults(f, dictionarySize, isBT4, encodeTime, benchSize, false, 0);
+ fprintf(f, " ");
+ PrintResults(f, dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize);
+ fprintf(f, "\n");
+
+ totalBenchSize += benchSize;
+ totalEncodeTime += encodeTime;
+ totalDecodeTime += decodeTime;
+ totalCompressedSize += compressedSize;
+ }
+ fprintf(f, "---------------------------------------------------\n");
+ PrintResults(f, dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0);
+ fprintf(f, " ");
+ PrintResults(f, dictionarySize, isBT4, totalDecodeTime,
+ kBufferSize * numIterations, true, totalCompressedSize);
+ fprintf(f, " Average\n");
+ return 0;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h
new file mode 100644
index 00000000..9a1a63a5
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h
@@ -0,0 +1,11 @@
+// LzmaBench.h
+
+#ifndef __LzmaBench_h
+#define __LzmaBench_h
+
+#include <stdio.h>
+#include "../../../Common/Types.h"
+
+int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp
new file mode 100644
index 00000000..3cc264a1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp
@@ -0,0 +1,228 @@
+// LzmaRam.cpp
+
+#include "StdAfx.h"
+#include "../../../Common/Types.h"
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+#include "LzmaRam.h"
+
+extern "C"
+{
+#include "../Branch/BranchX86.h"
+}
+
+class CInStreamRam:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ const Byte *Data;
+ size_t Size;
+ size_t Pos;
+public:
+ MY_UNKNOWN_IMP
+ void Init(const Byte *data, size_t size)
+ {
+ Data = data;
+ Size = size;
+ Pos = 0;
+ }
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 remain = Size - Pos;
+ if (size > remain)
+ size = remain;
+ for (UInt32 i = 0; i < size; i++)
+ ((Byte *)data)[i] = Data[Pos + i];
+ Pos += size;
+ if(processedSize != NULL)
+ *processedSize = size;
+ return S_OK;
+}
+
+class COutStreamRam:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ size_t Size;
+public:
+ Byte *Data;
+ size_t Pos;
+ bool Overflow;
+ void Init(Byte *data, size_t size)
+ {
+ Data = data;
+ Size = size;
+ Pos = 0;
+ Overflow = false;
+ }
+ void SetPos(size_t pos)
+ {
+ Overflow = false;
+ Pos = pos;
+ }
+ MY_UNKNOWN_IMP
+ HRESULT WriteByte(Byte b)
+ {
+ if (Pos >= Size)
+ {
+ Overflow = true;
+ return E_FAIL;
+ }
+ Data[Pos++] = b;
+ return S_OK;
+ }
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 i;
+ for (i = 0; i < size && Pos < Size; i++)
+ Data[Pos++] = ((const Byte *)data)[i];
+ if(processedSize != NULL)
+ *processedSize = i;
+ if (i != size)
+ {
+ Overflow = true;
+ return E_FAIL;
+ }
+ return S_OK;
+}
+
+#define SZE_FAIL (1)
+#define SZE_OUTOFMEMORY (2)
+#define SZE_OUT_OVERFLOW (3)
+
+int LzmaRamEncode(
+ const Byte *inBuffer, size_t inSize,
+ Byte *outBuffer, size_t outSize, size_t *outSizeProcessed,
+ UInt32 dictionarySize, ESzFilterMode filterMode)
+{
+ #ifndef _NO_EXCEPTIONS
+ try {
+ #endif
+
+ *outSizeProcessed = 0;
+ const size_t kIdSize = 1;
+ const size_t kLzmaPropsSize = 5;
+ const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8;
+ if (outSize < kMinDestSize)
+ return SZE_OUT_OVERFLOW;
+ NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ PROPID propIDs[] =
+ {
+ NCoderPropID::kAlgorithm,
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kNumFastBytes,
+ };
+ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+ PROPVARIANT properties[kNumProps];
+ properties[0].vt = VT_UI4;
+ properties[1].vt = VT_UI4;
+ properties[2].vt = VT_UI4;
+ properties[0].ulVal = (UInt32)2;
+ properties[1].ulVal = (UInt32)dictionarySize;
+ properties[2].ulVal = (UInt32)64;
+
+ if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
+ return 1;
+
+ COutStreamRam *outStreamSpec = new COutStreamRam;
+ if (outStreamSpec == 0)
+ return SZE_OUTOFMEMORY;
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ CInStreamRam *inStreamSpec = new CInStreamRam;
+ if (inStreamSpec == 0)
+ return SZE_OUTOFMEMORY;
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+
+ outStreamSpec->Init(outBuffer, outSize);
+ if (outStreamSpec->WriteByte(0) != S_OK)
+ return SZE_OUT_OVERFLOW;
+
+ if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
+ return SZE_OUT_OVERFLOW;
+ if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize)
+ return 1;
+
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ UInt64 t = (UInt64)(inSize);
+ if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK)
+ return SZE_OUT_OVERFLOW;
+ }
+
+ Byte *filteredStream = 0;
+
+ bool useFilter = (filterMode != SZ_FILTER_NO);
+ if (useFilter)
+ {
+ if (inSize != 0)
+ {
+ filteredStream = (Byte *)MyAlloc(inSize);
+ if (filteredStream == 0)
+ return SZE_OUTOFMEMORY;
+ memmove(filteredStream, inBuffer, inSize);
+ }
+ UInt32 _prevMask;
+ UInt32 _prevPos;
+ x86_Convert_Init(_prevMask, _prevPos);
+ x86_Convert(filteredStream, (UInt32)inSize, 0, &_prevMask, &_prevPos, 1);
+ }
+
+ UInt32 minSize = 0;
+ int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
+ bool bestIsFiltered = false;
+ int mainResult = 0;
+ size_t startPos = outStreamSpec->Pos;
+ for (i = 0; i < numPasses; i++)
+ {
+ if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered)
+ break;
+ outStreamSpec->SetPos(startPos);
+ bool curModeIsFiltered = false;
+ if (useFilter && i == 0)
+ curModeIsFiltered = true;
+ if (numPasses > 1 && i == numPasses - 1)
+ curModeIsFiltered = true;
+
+ inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize);
+
+ HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0);
+
+ mainResult = 0;
+ if (lzmaResult == E_OUTOFMEMORY)
+ {
+ mainResult = SZE_OUTOFMEMORY;
+ break;
+ }
+ if (i == 0 || outStreamSpec->Pos <= minSize)
+ {
+ minSize = outStreamSpec->Pos;
+ bestIsFiltered = curModeIsFiltered;
+ }
+ if (outStreamSpec->Overflow)
+ mainResult = SZE_OUT_OVERFLOW;
+ else if (lzmaResult != S_OK)
+ {
+ mainResult = SZE_FAIL;
+ break;
+ }
+ }
+ *outSizeProcessed = outStreamSpec->Pos;
+ if (bestIsFiltered)
+ outBuffer[0] = 1;
+ if (useFilter)
+ MyFree(filteredStream);
+ return mainResult;
+
+ #ifndef _NO_EXCEPTIONS
+ } catch(...) { return SZE_OUTOFMEMORY; }
+ #endif
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h
new file mode 100644
index 00000000..74d584d2
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h
@@ -0,0 +1,46 @@
+// LzmaRam.h
+
+#ifndef __LzmaRam_h
+#define __LzmaRam_h
+
+#include <stdlib.h>
+#include "../../../Common/Types.h"
+
+/*
+LzmaRamEncode: BCJ + LZMA RAM->RAM compressing.
+It uses .lzma format, but it writes one additional byte to .lzma file:
+ 0: - no filter
+ 1: - x86(BCJ) filter.
+
+To provide best compression ratio dictionarySize mustbe >= inSize
+
+LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions.
+RAM Requirements:
+ RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize
+ FilterBlockSize = 0, if useFilter == false
+ FilterBlockSize = inSize, if useFilter == true
+
+ Return code:
+ 0 - OK
+ 1 - Unspecified Error
+ 2 - Memory allocating error
+ 3 - Output buffer OVERFLOW
+
+If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes:
+ 2 passes when FILTER_NO provides better compression.
+ 3 passes when FILTER_YES provides better compression.
+*/
+
+enum ESzFilterMode
+{
+ SZ_FILTER_NO,
+ SZ_FILTER_YES,
+ SZ_FILTER_AUTO
+};
+
+int LzmaRamEncode(
+ const Byte *inBuffer, size_t inSize,
+ Byte *outBuffer, size_t outSize, size_t *outSizeProcessed,
+ UInt32 dictionarySize, ESzFilterMode filterMode);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c
new file mode 100644
index 00000000..0f0f8424
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c
@@ -0,0 +1,79 @@
+/* LzmaRamDecode.c */
+
+#include "LzmaRamDecode.h"
+#ifdef _SZ_ONE_DIRECTORY
+#include "LzmaDecode.h"
+#include "BranchX86.h"
+#else
+#include "../LZMA_C/LzmaDecode.h"
+#include "../Branch/BranchX86.h"
+#endif
+
+#define LZMA_PROPS_SIZE 14
+#define LZMA_SIZE_OFFSET 6
+
+int LzmaRamGetUncompressedSize(
+ const unsigned char *inBuffer,
+ size_t inSize,
+ size_t *outSize)
+{
+ unsigned int i;
+ if (inSize < LZMA_PROPS_SIZE)
+ return 1;
+ *outSize = 0;
+ for(i = 0; i < sizeof(size_t); i++)
+ *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i);
+ for(; i < 8; i++)
+ if (inBuffer[LZMA_SIZE_OFFSET + i] != 0)
+ return 1;
+ return 0;
+}
+
+#define SZE_DATA_ERROR (1)
+#define SZE_OUTOFMEMORY (2)
+
+int LzmaRamDecompress(
+ const unsigned char *inBuffer,
+ size_t inSize,
+ unsigned char *outBuffer,
+ size_t outSize,
+ size_t *outSizeProcessed,
+ void * (*allocFunc)(size_t size),
+ void (*freeFunc)(void *))
+{
+ CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */
+ int result;
+ SizeT outSizeProcessedLoc;
+ SizeT inProcessed;
+ int useFilter;
+
+ if (inSize < LZMA_PROPS_SIZE)
+ return 1;
+ useFilter = inBuffer[0];
+
+ *outSizeProcessed = 0;
+ if (useFilter > 1)
+ return 1;
+
+ if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return 1;
+ state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return SZE_OUTOFMEMORY;
+
+ result = LzmaDecode(&state,
+ inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed,
+ outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
+ freeFunc(state.Probs);
+ if (result != LZMA_RESULT_OK)
+ return 1;
+ *outSizeProcessed = (size_t)outSizeProcessedLoc;
+ if (useFilter == 1)
+ {
+ UInt32 _prevMask;
+ UInt32 _prevPos;
+ x86_Convert_Init(_prevMask, _prevPos);
+ x86_Convert(outBuffer, (UInt32)outSizeProcessedLoc, 0, &_prevMask, &_prevPos, 0);
+ }
+ return 0;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h
new file mode 100644
index 00000000..783734a4
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h
@@ -0,0 +1,55 @@
+/* LzmaRamDecode.h */
+
+#ifndef __LzmaRamDecode_h
+#define __LzmaRamDecode_h
+
+#include <stdlib.h>
+
+/*
+LzmaRamGetUncompressedSize:
+ In:
+ inBuffer - input data
+ inSize - input data size
+ Out:
+ outSize - uncompressed size
+ Return code:
+ 0 - OK
+ 1 - Error in headers
+*/
+
+int LzmaRamGetUncompressedSize(
+ const unsigned char *inBuffer,
+ size_t inSize,
+ size_t *outSize);
+
+
+/*
+LzmaRamDecompress:
+ In:
+ inBuffer - input data
+ inSize - input data size
+ outBuffer - output data
+ outSize - output size
+ allocFunc - alloc function (can be malloc)
+ freeFunc - free function (can be free)
+ Out:
+ outSizeProcessed - processed size
+ Return code:
+ 0 - OK
+ 1 - Error in headers / data stream
+ 2 - Memory allocating error
+
+Memory requirements depend from properties of LZMA stream.
+With default lzma settings it's about 16 KB.
+*/
+
+int LzmaRamDecompress(
+ const unsigned char *inBuffer,
+ size_t inSize,
+ unsigned char *outBuffer,
+ size_t outSize,
+ size_t *outSizeProcessed,
+ void * (*allocFunc)(size_t size),
+ void (*freeFunc)(void *));
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp
new file mode 100644
index 00000000..c6d3b1fa
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h
new file mode 100644
index 00000000..83fdd22d
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile
new file mode 100644
index 00000000..5b8d0a32
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile
@@ -0,0 +1,100 @@
+PROG = lzma.exe
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ -GS-
+CFLAGS_O1 = $(CFLAGS) -O1
+CFLAGS_O2 = $(CFLAGS) -O2
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
+COMPL = $(CPP) $(CFLAGS_O1) $**
+
+
+LZMA_OBJS = \
+ $O\LzmaAlone.obj \
+ $O\LzmaBench.obj \
+ $O\LzmaRam.obj \
+
+LZMA_OPT_OBJS = \
+ $O\LZMADecoder.obj \
+ $O\LZMAEncoder.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\CRC.obj \
+ $O\CommandLineParser.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\Vector.obj
+
+7ZIP_COMMON_OBJS = \
+ $O\InBuffer.obj \
+ $O\OutBuffer.obj \
+ $O\StreamUtils.obj \
+
+LZ_OBJS = \
+ $O\LZInWindow.obj \
+ $O\LZOutWindow.obj \
+
+
+OBJS = \
+ $(LZMA_OBJS) \
+ $(LZMA_OPT_OBJS) \
+ $(COMMON_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(LZ_OBJS) \
+ $O\LzmaRamDecode.obj \
+ $O\LzmaDecode.obj \
+ $O\FileStreams.obj \
+ $O\FileIO.obj \
+ $O\RangeCoderBit.obj \
+ $O\BranchX86.obj \
+
+all: $(PROGPATH)
+
+clean:
+ -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
+
+$O:
+ if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS)
+ link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+
+
+$(LZMA_OBJS): $(*B).cpp
+ $(COMPL)
+$(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp
+ $(COMPL_O2)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+$(LZ_OBJS): ../LZ/$(*B).cpp
+ $(COMPL)
+$O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp
+ $(COMPL)
+$O\LzmaRamDecode.obj: LzmaRamDecode.c
+ $(COMPL_O1)
+$O\LzmaDecode.obj: ../LZMA_C/LzmaDecode.c
+ $(COMPL_O2)
+$O\BranchX86.obj: ../Branch/BranchX86.c
+ $(COMPL_O2)
+$O\FileStreams.obj: ../../Common/FileStreams.cpp
+ $(COMPL)
+$O\FileIO.obj: ../../../Windows/FileIO.cpp
+ $(COMPL)
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc
new file mode 100644
index 00000000..1e180742
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc
@@ -0,0 +1,113 @@
+PROG = lzma
+CXX = g++ -O2 -Wall
+CXX_C = gcc -O2 -Wall
+LIB = -lm
+RM = rm -f
+CFLAGS = -c -I ../../../
+
+OBJS = \
+ LzmaAlone.o \
+ LzmaBench.o \
+ LzmaRam.o \
+ LzmaRamDecode.o \
+ LzmaDecode.o \
+ BranchX86.o \
+ LZMADecoder.o \
+ LZMAEncoder.o \
+ LZInWindow.o \
+ LZOutWindow.o \
+ RangeCoderBit.o \
+ InBuffer.o \
+ OutBuffer.o \
+ FileStreams.o \
+ StreamUtils.o \
+ Alloc.o \
+ C_FileIO.o \
+ CommandLineParser.o \
+ CRC.o \
+ String.o \
+ StringConvert.o \
+ StringToInt.o \
+ Vector.o \
+
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
+
+LzmaAlone.o: LzmaAlone.cpp
+ $(CXX) $(CFLAGS) LzmaAlone.cpp
+
+LzmaBench.o: LzmaBench.cpp
+ $(CXX) $(CFLAGS) LzmaBench.cpp
+
+LzmaRam.o: LzmaRam.cpp
+ $(CXX) $(CFLAGS) LzmaRam.cpp
+
+LzmaRamDecode.o: LzmaRamDecode.c
+ $(CXX_C) $(CFLAGS) LzmaRamDecode.c
+
+LzmaDecode.o: ../LZMA_C/LzmaDecode.c
+ $(CXX_C) $(CFLAGS) ../LZMA_C/LzmaDecode.c
+
+BranchX86.o: ../Branch/BranchX86.c
+ $(CXX_C) $(CFLAGS) ../Branch/BranchX86.c
+
+LZMADecoder.o: ../LZMA/LZMADecoder.cpp
+ $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp
+
+LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp
+ $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp
+
+LZInWindow.o: ../LZ/LZInWindow.cpp
+ $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp
+
+LZOutWindow.o: ../LZ/LZOutWindow.cpp
+ $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp
+
+RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp
+ $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp
+
+InBuffer.o: ../../Common/InBuffer.cpp
+ $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp
+
+OutBuffer.o: ../../Common/OutBuffer.cpp
+ $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp
+
+FileStreams.o: ../../Common/FileStreams.cpp
+ $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp
+
+StreamUtils.o: ../../Common/StreamUtils.cpp
+ $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp
+
+Alloc.o: ../../../Common/Alloc.cpp
+ $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp
+
+C_FileIO.o: ../../../Common/C_FileIO.cpp
+ $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp
+
+CommandLineParser.o: ../../../Common/CommandLineParser.cpp
+ $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp
+
+CRC.o: ../../../Common/CRC.cpp
+ $(CXX) $(CFLAGS) ../../../Common/CRC.cpp
+
+MyWindows.o: ../../../Common/MyWindows.cpp
+ $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
+
+String.o: ../../../Common/String.cpp
+ $(CXX) $(CFLAGS) ../../../Common/String.cpp
+
+StringConvert.o: ../../../Common/StringConvert.cpp
+ $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp
+
+StringToInt.o: ../../../Common/StringToInt.cpp
+ $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp
+
+Vector.o: ../../../Common/Vector.cpp
+ $(CXX) $(CFLAGS) ../../../Common/Vector.cpp
+
+clean:
+ -$(RM) $(PROG) $(OBJS)
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c
new file mode 100644
index 00000000..5c9d67f7
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c
@@ -0,0 +1,588 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
+ #endif
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+
+ #endif /* _LZMA_OUT_READ */
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h
new file mode 100644
index 00000000..35e37ed0
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h
@@ -0,0 +1,131 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifndef SizeT
+#ifdef _LZMA_SYSTEM_SIZE_T
+#include <stddef.h>
+#define SizeT size_t
+#else
+#define SizeT UInt32
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ #ifdef _LZMA_OUT_READ
+ UInt32 DictionarySize;
+ #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+ #ifdef _LZMA_IN_CB
+ const unsigned char *Buffer;
+ const unsigned char *BufferLim;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ unsigned char *Dictionary;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen;
+ unsigned char TempDictionary[4];
+ #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c
new file mode 100644
index 00000000..fe24cf21
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c
@@ -0,0 +1,716 @@
+/*
+ LzmaDecodeSize.c
+ LZMA Decoder (optimized for Size version)
+
+ LZMA SDK 4.27 Copyright (c) 1999-2005 Igor Pavlov (2005-08-07)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ SizeT size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd
+ #ifndef _LZMA_IN_CB
+ , const Byte *stream, SizeT bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i != 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i != 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + 0x100 + (matchBit << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ CRangeDecoder rd;
+
+ #ifdef _LZMA_OUT_READ
+
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ rd.Range = vs->Range;
+ rd.Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ rd.Buffer = vs->Buffer;
+ rd.BufferLim = vs->BufferLim;
+ #else
+ rd.Buffer = inStream;
+ rd.BufferLim = inStream + inSize;
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #ifdef _LZMA_IN_CB
+ rd.Result = LZMA_RESULT_OK;
+ #endif
+ rd.ExtraBytes = 0;
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ #endif
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+
+ #endif /* _LZMA_OUT_READ */
+
+
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = rd.Range;
+ vs->Code = rd.Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = rd.Buffer;
+ vs->BufferLim = rd.BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(rd.Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c
new file mode 100644
index 00000000..8ddb6ee1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c
@@ -0,0 +1,521 @@
+/*
+ LzmaStateDecode.c
+ LZMA Decoder (State version)
+
+ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaStateDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/* kRequiredInBufferSize = number of required input bytes for worst case:
+ longest match with longest distance.
+ kLzmaInBufferSize must be larger than kRequiredInBufferSize
+ 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
+*/
+
+#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ return LZMA_RESULT_OK;
+ }
+}
+
+int LzmaDecode(
+ CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding)
+{
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+
+ unsigned char *Buffer = vs->Buffer;
+ int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
+ CProb *p = vs->Probs;
+
+ int state = vs->State;
+ unsigned char previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ SizeT nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ unsigned char *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ unsigned char tempDictionary[4];
+
+ (*inSizeProcessed) = 0;
+ (*outSizeProcessed) = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < 5)
+ {
+ vs->BufferSize = BufferSize;
+ return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
+ }
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RC_INIT;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ while(1)
+ {
+ int bufferPos = (int)(Buffer - vs->Buffer);
+ if (BufferSize - bufferPos < kRequiredInBufferSize)
+ {
+ int i;
+ BufferSize -= bufferPos;
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ Buffer = vs->Buffer;
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < kRequiredInBufferSize && !finishDecoding)
+ break;
+ }
+ if (nowPos >= outSize)
+ break;
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)((nowPos + globalPos) & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (unsigned char)symbol;
+
+ outStream[nowPos++] = previousByte;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ UInt32 pos;
+ UpdateBit0(prob);
+ if (distanceLimit == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ state = state < kNumLitStates ? 9 : 11;
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ if (rep0 > distanceLimit)
+ return LZMA_RESULT_DATA_ERROR;
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+
+ do
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ }
+ RC_NORMALIZE;
+
+ BufferSize -= (int)(Buffer - vs->Buffer);
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ int i;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ }
+ vs->BufferSize = BufferSize;
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = (UInt32)(globalPos + nowPos);
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+
+ (*outSizeProcessed) = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h
new file mode 100644
index 00000000..4e6aad89
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h
@@ -0,0 +1,115 @@
+/*
+ LzmaStateDecode.h
+ LZMA Decoder interface (State version)
+
+ LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMASTATEDECODE_H
+#define __LZMASTATEDECODE_H
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
+
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifndef SizeT
+#ifdef _LZMA_SYSTEM_SIZE_T
+#include <stddef.h>
+#define SizeT size_t
+#else
+#define SizeT UInt32
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ UInt32 DictionarySize;
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
+
+#define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+ unsigned char *Dictionary;
+
+ unsigned char Buffer[kLzmaInBufferSize];
+ int BufferSize;
+
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen; /* -2: decoder needs internal initialization
+ -1: stream was finished,
+ 0: ok
+ > 0: need to write RemainLen bytes as match Reps[0],
+ */
+ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */
+} CLzmaDecoderState;
+
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
+
+/* LzmaDecode: decoding from input stream to output stream.
+ If finishDecoding != 0, then there are no more bytes in input stream
+ after inStream[inSize - 1]. */
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding);
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c
new file mode 100644
index 00000000..fa791d35
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c
@@ -0,0 +1,195 @@
+/*
+LzmaStateTest.c
+Test application for LZMA Decoder (State version)
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-02)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaStateDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+#define kInBufferSize (1 << 15)
+#define kOutBufferSize (1 << 15)
+
+unsigned char g_InBuffer[kInBufferSize];
+unsigned char g_OutBuffer[kOutBufferSize];
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+ { return fread(data, 1, size, file); }
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size); }
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ int i;
+ int res = 0;
+ CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+ SizeT inAvail = 0;
+ unsigned char *inBuffer = 0;
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return PrintError(rs, kCantAllocateMessage);
+
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ {
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ if (state.Dictionary == 0)
+ {
+ free(state.Probs);
+ return PrintError(rs, kCantAllocateMessage);
+ }
+ }
+
+ /* Decompress */
+
+ LzmaDecoderInit(&state);
+
+ do
+ {
+ SizeT inProcessed, outProcessed;
+ int finishDecoding;
+ UInt32 outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = outSize;
+ if (inAvail == 0)
+ {
+ inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
+ inBuffer = g_InBuffer;
+ }
+ finishDecoding = (inAvail == 0);
+ res = LzmaDecode(&state,
+ inBuffer, inAvail, &inProcessed,
+ g_OutBuffer, outAvail, &outProcessed,
+ finishDecoding);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+
+ if (outFile != 0)
+ if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0 && finishDecoding)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+
+ free(state.Dictionary);
+ free(state.Probs);
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c
new file mode 100644
index 00000000..370b9497
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c
@@ -0,0 +1,342 @@
+/*
+LzmaTest.c
+Test application for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-05)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fread(data, 1, size, file);
+}
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size);}
+
+size_t MyWriteFile(FILE *file, const void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fwrite(data, 1, size, file);
+}
+
+int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
+ { return (MyWriteFile(file, data, size) == size); }
+
+#ifdef _LZMA_IN_CB
+#define kInBufferSize (1 << 15)
+typedef struct _CBuffer
+{
+ ILzmaInCallback InCallback;
+ FILE *File;
+ unsigned char Buffer[kInBufferSize];
+} CBuffer;
+
+int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
+{
+ CBuffer *b = (CBuffer *)object;
+ *buffer = b->Buffer;
+ *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
+ return LZMA_RESULT_OK;
+}
+CBuffer g_InBuffer;
+
+#endif
+
+#ifdef _LZMA_OUT_READ
+#define kOutBufferSize (1 << 15)
+unsigned char g_OutBuffer[kOutBufferSize];
+#endif
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+ #ifndef _LZMA_OUT_READ
+ SizeT outSizeFull;
+ unsigned char *outStream;
+ #endif
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ #ifndef _LZMA_IN_CB
+ SizeT compressedSize;
+ unsigned char *inStream;
+ #endif
+
+ CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+ int res;
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.File = inFile;
+ #endif
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ #ifndef _LZMA_IN_CB
+ {
+ long length;
+ fseek(inFile, 0, SEEK_END);
+ length = ftell(inFile);
+ fseek(inFile, 0, SEEK_SET);
+ if ((long)(SizeT)length != length)
+ return PrintError(rs, "Too big compressed stream");
+ compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
+ }
+ #endif
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ {
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ #ifndef _LZMA_OUT_READ
+ if (waitEOS)
+ return PrintError(rs, "Stream with EOS marker is not supported");
+ outSizeFull = (SizeT)outSize;
+ if (sizeof(SizeT) >= 8)
+ outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
+ else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
+ return PrintError(rs, "Too big uncompressed stream");
+ #endif
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+
+ #ifdef _LZMA_OUT_READ
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ #else
+ if (outSizeFull == 0)
+ outStream = 0;
+ else
+ outStream = (unsigned char *)malloc(outSizeFull);
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ if (compressedSize == 0)
+ inStream = 0;
+ else
+ inStream = (unsigned char *)malloc(compressedSize);
+ #endif
+
+ if (state.Probs == 0
+ #ifdef _LZMA_OUT_READ
+ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
+ #else
+ || (outStream == 0 && outSizeFull != 0)
+ #endif
+ #ifndef _LZMA_IN_CB
+ || (inStream == 0 && compressedSize != 0)
+ #endif
+ )
+ {
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return PrintError(rs, kCantAllocateMessage);
+ }
+
+ /* Decompress */
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.InCallback.Read = LzmaReadCompressed;
+ #else
+ if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
+ return PrintError(rs, kCantReadMessage);
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inAvail = compressedSize;
+ const unsigned char *inBuffer = inStream;
+ #endif
+ LzmaDecoderInit(&state);
+ do
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ SizeT outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = (SizeT)outSize;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inBuffer, inAvail, &inProcessed,
+ #endif
+ g_OutBuffer, outAvail, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ #ifndef _LZMA_IN_CB
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+ #endif
+
+ if (outFile != 0)
+ if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+ }
+
+ #else
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inStream, compressedSize, &inProcessed,
+ #endif
+ outStream, outSizeFull, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ }
+ else if (outFile != 0)
+ {
+ if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ }
+ }
+ }
+ #endif
+
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile
new file mode 100644
index 00000000..f8e193b2
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile
@@ -0,0 +1,43 @@
+PROG = lzmaDec.exe
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS-
+CFLAGS_O1 = $(CFLAGS) -O1
+CFLAGS_O2 = $(CFLAGS) -O2
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
+COMPL = $(CPP) $(CFLAGS_O1) $**
+
+
+OBJS = \
+ $O\LzmaTest.obj \
+ $O\LzmaDecode.obj \
+
+all: $(PROGPATH)
+
+clean:
+ -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
+
+$O:
+ if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS)
+ link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+
+
+$O\LzmaTest.obj: $(*B).c
+ $(COMPL)
+$O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c
+ $(COMPL_O2)
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile.gcc b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile.gcc
new file mode 100644
index 00000000..43bbef17
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_C/makefile.gcc
@@ -0,0 +1,23 @@
+PROG = lzmadec
+CXX = gcc
+LIB =
+RM = rm -f
+CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32
+
+OBJS = LzmaTest.o LzmaDecode.o
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
+
+LzmaTest.o: LzmaTest.c
+ $(CXX) $(CFLAGS) LzmaTest.c
+
+LzmaDecode.o: LzmaDecode.c
+ $(CXX) $(CFLAGS) LzmaDecode.c
+
+
+clean:
+ -$(RM) $(PROG) $(OBJS)
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/ZLib.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/ZLib.cpp
new file mode 100644
index 00000000..931c13ac
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/ZLib.cpp
@@ -0,0 +1,273 @@
+/*
+ * lzma zlib simplified wrapper
+ *
+ * Copyright (c) 2005-2006 Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * This library is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software
+ * Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * default values for encoder/decoder used by wrapper
+ */
+
+#include <zlib.h>
+
+#define ZLIB_LC 3
+#define ZLIB_LP 0
+#define ZLIB_PB 2
+
+#ifdef WIN32
+#include <initguid.h>
+#else
+#define INITGUID
+#endif
+
+#include "../../../Common/MyWindows.h"
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+
+#define STG_E_SEEKERROR ((HRESULT)0x80030019L)
+#define STG_E_MEDIUMFULL ((HRESULT)0x80030070L)
+
+class CInMemoryStream:
+ public IInStream,
+ public IStreamGetSize,
+ public CMyUnknownImp
+{
+public:
+ CInMemoryStream(const Bytef *data, UInt64 size) :
+ m_data(data), m_size(size), m_offset(0) {}
+
+ virtual ~CInMemoryStream() {}
+
+ MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize)
+ {
+ if (size > m_size - m_offset)
+ size = m_size - m_offset;
+
+ if (size) {
+ memcpy(data, m_data + m_offset, size);
+ }
+
+ m_offset += size;
+
+ if (processedSize)
+ *processedSize = size;
+
+ return S_OK;
+ }
+
+ STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize)
+ {
+ return Read(data, size, processedSize);
+ }
+
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+ {
+ UInt64 _offset;
+
+ if (seekOrigin == STREAM_SEEK_SET) _offset = offset;
+ else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset;
+ else if (seekOrigin == STREAM_SEEK_END) _offset = m_size;
+ else return STG_E_INVALIDFUNCTION;
+
+ if (_offset < 0 || _offset > m_size)
+ return STG_E_SEEKERROR;
+
+ m_offset = _offset;
+
+ if (newPosition)
+ *newPosition = m_offset;
+
+ return S_OK;
+ }
+
+ STDMETHOD(GetSize)(UInt64 *size)
+ {
+ *size = m_size;
+ return S_OK;
+ }
+protected:
+ const Bytef *m_data;
+ UInt64 m_size;
+ UInt64 m_offset;
+};
+
+class COutMemoryStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+public:
+ COutMemoryStream(Bytef *data, UInt64 maxsize) :
+ m_data(data), m_size(0), m_maxsize(maxsize), m_offset(0) {}
+ virtual ~COutMemoryStream() {}
+
+ MY_UNKNOWN_IMP1(IOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize)
+ {
+ if (size > m_maxsize - m_offset)
+ size = m_maxsize - m_offset;
+
+ if (size) {
+ memcpy(m_data + m_offset, data, size);
+ }
+
+ m_offset += size;
+
+ if (m_offset > m_size)
+ m_size = m_offset;
+
+ if (processedSize)
+ *processedSize = size;
+
+ return S_OK;
+ }
+
+ STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize)
+ {
+ return Write(data, size, processedSize);
+ }
+
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+ {
+ UInt64 _offset;
+
+ if (seekOrigin == STREAM_SEEK_SET) _offset = offset;
+ else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset;
+ else if (seekOrigin == STREAM_SEEK_END) _offset = m_size;
+ else return STG_E_INVALIDFUNCTION;
+
+ if (_offset < 0 || _offset > m_maxsize)
+ return STG_E_SEEKERROR;
+
+ m_offset = _offset;
+
+ if (newPosition)
+ *newPosition = m_offset;
+
+ return S_OK;
+ }
+
+ STDMETHOD(SetSize)(Int64 newSize)
+ {
+ if ((UInt64)newSize > m_maxsize)
+ return STG_E_MEDIUMFULL;
+
+ return S_OK;
+ }
+protected:
+ Bytef *m_data;
+ UInt64 m_size;
+ UInt64 m_maxsize;
+ UInt64 m_offset;
+};
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level))
+{
+ CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen);
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+
+ COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen);
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+
+ NCompress::NLZMA::CEncoder *encoderSpec =
+ new NCompress::NLZMA::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ PROPID propIDs[] =
+ {
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kPosStateBits,
+ NCoderPropID::kLitContextBits,
+ NCoderPropID::kLitPosBits,
+ NCoderPropID::kAlgorithm,
+ NCoderPropID::kNumFastBytes,
+ NCoderPropID::kMatchFinder,
+ NCoderPropID::kEndMarker
+ };
+ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+
+ PROPVARIANT properties[kNumProps];
+ for (int p = 0; p < 6; p++)
+ properties[p].vt = VT_UI4;
+ properties[0].ulVal = UInt32(1 << (level + 14));
+ properties[1].ulVal = UInt32(ZLIB_PB);
+ properties[2].ulVal = UInt32(ZLIB_LC); // for normal files
+ properties[3].ulVal = UInt32(ZLIB_LP); // for normal files
+ properties[4].ulVal = UInt32(2);
+ properties[5].ulVal = UInt32(128);
+
+ properties[6].vt = VT_BSTR;
+ properties[6].bstrVal = (BSTR)(const wchar_t *)L"BT4";
+
+ properties[7].vt = VT_BOOL;
+ properties[7].boolVal = VARIANT_TRUE;
+
+ if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
+ return Z_MEM_ERROR; // should not happen
+
+ HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
+ if (result == E_OUTOFMEMORY)
+ {
+ return Z_MEM_ERROR;
+ }
+ else if (result != S_OK)
+ {
+ return Z_BUF_ERROR; // should not happen
+ }
+
+ UInt64 fileSize;
+ outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize);
+ *destLen = fileSize;
+
+ return Z_OK;
+}
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen))
+{
+ CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen);
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+
+ COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen);
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+
+ NCompress::NLZMA::CDecoder *decoderSpec =
+ new NCompress::NLZMA::CDecoder;
+ CMyComPtr<ICompressCoder> decoder = decoderSpec;
+
+ if (decoderSpec->SetDecoderPropertiesRaw(ZLIB_LC,
+ ZLIB_LP, ZLIB_PB, (1 << 23)) != S_OK) return Z_DATA_ERROR;
+
+ UInt64 fileSize = *destLen;
+
+ if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
+ {
+ return Z_DATA_ERROR;
+ }
+
+ outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize);
+ *destLen = fileSize;
+
+ return Z_OK;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/makefile b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/makefile
new file mode 100644
index 00000000..bbf27459
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/LZMA_Lib/makefile
@@ -0,0 +1,92 @@
+PROG = liblzma.a
+CXX = g++ -O3 -Wall -Wno-non-virtual-dtor
+AR = ar
+RM = rm -f
+CFLAGS = -c -I ../../../
+
+OBJS = \
+ ZLib.o \
+ LZMADecoder.o \
+ LZMAEncoder.o \
+ LZInWindow.o \
+ LZOutWindow.o \
+ RangeCoderBit.o \
+ InBuffer.o \
+ OutBuffer.o \
+ FileStreams.o \
+ Alloc.o \
+ C_FileIO.o \
+ CommandLineParser.o \
+ CRC.o \
+ StreamUtils.o \
+ String.o \
+ StringConvert.o \
+ StringToInt.o \
+ Vector.o \
+
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(AR) r $(PROG) $(OBJS)
+
+ZLib.o: ZLib.cpp
+ $(CXX) $(CFLAGS) ZLib.cpp
+
+LZMADecoder.o: ../LZMA/LZMADecoder.cpp
+ $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp
+
+LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp
+ $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp
+
+LZInWindow.o: ../LZ/LZInWindow.cpp
+ $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp
+
+LZOutWindow.o: ../LZ/LZOutWindow.cpp
+ $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp
+
+RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp
+ $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp
+
+InBuffer.o: ../../Common/InBuffer.cpp
+ $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp
+
+OutBuffer.o: ../../Common/OutBuffer.cpp
+ $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp
+
+StreamUtils.o: ../../Common/StreamUtils.cpp
+ $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp
+
+FileStreams.o: ../../Common/FileStreams.cpp
+ $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp
+
+Alloc.o: ../../../Common/Alloc.cpp
+ $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp
+
+C_FileIO.o: ../../../Common/C_FileIO.cpp
+ $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp
+
+CommandLineParser.o: ../../../Common/CommandLineParser.cpp
+ $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp
+
+CRC.o: ../../../Common/CRC.cpp
+ $(CXX) $(CFLAGS) ../../../Common/CRC.cpp
+
+MyWindows.o: ../../../Common/MyWindows.cpp
+ $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
+
+String.o: ../../../Common/String.cpp
+ $(CXX) $(CFLAGS) ../../../Common/String.cpp
+
+StringConvert.o: ../../../Common/StringConvert.cpp
+ $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp
+
+StringToInt.o: ../../../Common/StringToInt.cpp
+ $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp
+
+Vector.o: ../../../Common/Vector.cpp
+ $(CXX) $(CFLAGS) ../../../Common/Vector.cpp
+
+clean:
+ -$(RM) $(PROG) $(OBJS)
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h
new file mode 100644
index 00000000..9828bc4b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h
@@ -0,0 +1,205 @@
+// Compress/RangeCoder/RangeCoder.h
+
+#ifndef __COMPRESS_RANGECODER_H
+#define __COMPRESS_RANGECODER_H
+
+#include "../../Common/InBuffer.h"
+#include "../../Common/OutBuffer.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+const int kNumTopBits = 24;
+const UInt32 kTopValue = (1 << kNumTopBits);
+
+class CEncoder
+{
+ UInt32 _cacheSize;
+ Byte _cache;
+public:
+ UInt64 Low;
+ UInt32 Range;
+ COutBuffer Stream;
+ bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
+
+ void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
+ void Init()
+ {
+ Stream.Init();
+ Low = 0;
+ Range = 0xFFFFFFFF;
+ _cacheSize = 1;
+ _cache = 0;
+ }
+
+ void FlushData()
+ {
+ // Low += 1;
+ for(int i = 0; i < 5; i++)
+ ShiftLow();
+ }
+
+ HRESULT FlushStream() { return Stream.Flush(); }
+
+ void ReleaseStream() { Stream.ReleaseStream(); }
+
+ void Encode(UInt32 start, UInt32 size, UInt32 total)
+ {
+ Low += start * (Range /= total);
+ Range *= size;
+ while (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+
+ void ShiftLow()
+ {
+ if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)
+ {
+ Byte temp = _cache;
+ do
+ {
+ Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
+ temp = 0xFF;
+ }
+ while(--_cacheSize != 0);
+ _cache = (Byte)((UInt32)Low >> 24);
+ }
+ _cacheSize++;
+ Low = (UInt32)Low << 8;
+ }
+
+ void EncodeDirectBits(UInt32 value, int numTotalBits)
+ {
+ for (int i = numTotalBits - 1; i >= 0; i--)
+ {
+ Range >>= 1;
+ if (((value >> i) & 1) == 1)
+ Low += Range;
+ if (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+ }
+
+ void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
+ {
+ UInt32 newBound = (Range >> numTotalBits) * size0;
+ if (symbol == 0)
+ Range = newBound;
+ else
+ {
+ Low += newBound;
+ Range -= newBound;
+ }
+ while (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+
+ UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }
+};
+
+class CDecoder
+{
+public:
+ CInBuffer Stream;
+ UInt32 Range;
+ UInt32 Code;
+ bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
+
+ void Normalize()
+ {
+ while (Range < kTopValue)
+ {
+ Code = (Code << 8) | Stream.ReadByte();
+ Range <<= 8;
+ }
+ }
+
+ void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
+ void Init()
+ {
+ Stream.Init();
+ Code = 0;
+ Range = 0xFFFFFFFF;
+ for(int i = 0; i < 5; i++)
+ Code = (Code << 8) | Stream.ReadByte();
+ }
+
+ void ReleaseStream() { Stream.ReleaseStream(); }
+
+ UInt32 GetThreshold(UInt32 total)
+ {
+ return (Code) / ( Range /= total);
+ }
+
+ void Decode(UInt32 start, UInt32 size)
+ {
+ Code -= start * Range;
+ Range *= size;
+ Normalize();
+ }
+
+ UInt32 DecodeDirectBits(int numTotalBits)
+ {
+ UInt32 range = Range;
+ UInt32 code = Code;
+ UInt32 result = 0;
+ for (int i = numTotalBits; i != 0; i--)
+ {
+ range >>= 1;
+ /*
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ */
+ UInt32 t = (code - range) >> 31;
+ code -= range & (t - 1);
+ result = (result << 1) | (1 - t);
+
+ if (range < kTopValue)
+ {
+ code = (code << 8) | Stream.ReadByte();
+ range <<= 8;
+ }
+ }
+ Range = range;
+ Code = code;
+ return result;
+ }
+
+ UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
+ {
+ UInt32 newBound = (Range >> numTotalBits) * size0;
+ UInt32 symbol;
+ if (Code < newBound)
+ {
+ symbol = 0;
+ Range = newBound;
+ }
+ else
+ {
+ symbol = 1;
+ Code -= newBound;
+ Range -= newBound;
+ }
+ Normalize();
+ return symbol;
+ }
+
+ UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
+};
+
+}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp
new file mode 100644
index 00000000..8d273c8f
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp
@@ -0,0 +1,80 @@
+// Compress/RangeCoder/RangeCoderBit.cpp
+
+#include "StdAfx.h"
+
+#include "RangeCoderBit.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+static CPriceTables g_PriceTables;
+
+CPriceTables::CPriceTables() { Init(); }
+
+void CPriceTables::Init()
+{
+ const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
+ for(int i = kNumBits - 1; i >= 0; i--)
+ {
+ UInt32 start = 1 << (kNumBits - i - 1);
+ UInt32 end = 1 << (kNumBits - i);
+ for (UInt32 j = start; j < end; j++)
+ ProbPrices[j] = (i << kNumBitPriceShiftBits) +
+ (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
+ }
+
+ /*
+ // simplest: bad solution
+ for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
+ ProbPrices[i] = kBitPrice;
+ */
+
+ /*
+ const double kDummyMultMid = (1.0 / kBitPrice) / 2;
+ const double kDummyMultMid = 0;
+ // float solution
+ double ln2 = log(double(2));
+ double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits));
+ for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
+ ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice);
+ */
+
+ /*
+ // experimental, slow, solution:
+ for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
+ {
+ const int kCyclesBits = 5;
+ const UInt32 kCycles = (1 << kCyclesBits);
+
+ UInt32 range = UInt32(-1);
+ UInt32 bitCount = 0;
+ for (UInt32 j = 0; j < kCycles; j++)
+ {
+ range >>= (kNumBitModelTotalBits - kNumMoveReducingBits);
+ range *= i;
+ while(range < (1 << 31))
+ {
+ range <<= 1;
+ bitCount++;
+ }
+ }
+ bitCount <<= kNumBitPriceShiftBits;
+ range -= (1 << 31);
+ for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--)
+ {
+ range <<= 1;
+ if (range > (1 << 31))
+ {
+ bitCount += (1 << k);
+ range -= (1 << 31);
+ }
+ }
+ ProbPrices[i] = (bitCount
+ // + (1 << (kCyclesBits - 1))
+ ) >> kCyclesBits;
+ }
+ */
+}
+
+}}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h
new file mode 100644
index 00000000..64538e68
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h
@@ -0,0 +1,120 @@
+// Compress/RangeCoder/RangeCoderBit.h
+
+#ifndef __COMPRESS_RANGECODER_BIT_H
+#define __COMPRESS_RANGECODER_BIT_H
+
+#include "RangeCoder.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+const int kNumBitModelTotalBits = 11;
+const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);
+
+const int kNumMoveReducingBits = 2;
+
+const int kNumBitPriceShiftBits = 6;
+const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;
+
+class CPriceTables
+{
+public:
+ static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+ static void Init();
+ CPriceTables();
+};
+
+template <int numMoveBits>
+class CBitModel
+{
+public:
+ UInt32 Prob;
+ void UpdateModel(UInt32 symbol)
+ {
+ /*
+ Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
+ Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
+ */
+ if (symbol == 0)
+ Prob += (kBitModelTotal - Prob) >> numMoveBits;
+ else
+ Prob -= (Prob) >> numMoveBits;
+ }
+public:
+ void Init() { Prob = kBitModelTotal / 2; }
+};
+
+template <int numMoveBits>
+class CBitEncoder: public CBitModel<numMoveBits>
+{
+public:
+ void Encode(CEncoder *encoder, UInt32 symbol)
+ {
+ /*
+ encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
+ this->UpdateModel(symbol);
+ */
+ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
+ if (symbol == 0)
+ {
+ encoder->Range = newBound;
+ this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
+ }
+ else
+ {
+ encoder->Low += newBound;
+ encoder->Range -= newBound;
+ this->Prob -= (this->Prob) >> numMoveBits;
+ }
+ if (encoder->Range < kTopValue)
+ {
+ encoder->Range <<= 8;
+ encoder->ShiftLow();
+ }
+ }
+ UInt32 GetPrice(UInt32 symbol) const
+ {
+ return CPriceTables::ProbPrices[
+ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
+ }
+ UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; }
+ UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; }
+};
+
+
+template <int numMoveBits>
+class CBitDecoder: public CBitModel<numMoveBits>
+{
+public:
+ UInt32 Decode(CDecoder *decoder)
+ {
+ UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;
+ if (decoder->Code < newBound)
+ {
+ decoder->Range = newBound;
+ this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
+ if (decoder->Range < kTopValue)
+ {
+ decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
+ decoder->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ decoder->Range -= newBound;
+ decoder->Code -= newBound;
+ this->Prob -= (this->Prob) >> numMoveBits;
+ if (decoder->Range < kTopValue)
+ {
+ decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
+ decoder->Range <<= 8;
+ }
+ return 1;
+ }
+ }
+};
+
+}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h
new file mode 100644
index 00000000..1fa023f3
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h
@@ -0,0 +1,161 @@
+// Compress/RangeCoder/RangeCoderBitTree.h
+
+#ifndef __COMPRESS_RANGECODER_BIT_TREE_H
+#define __COMPRESS_RANGECODER_BIT_TREE_H
+
+#include "RangeCoderBit.h"
+#include "RangeCoderOpt.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+template <int numMoveBits, int NumBitLevels>
+class CBitTreeEncoder
+{
+ CBitEncoder<numMoveBits> Models[1 << NumBitLevels];
+public:
+ void Init()
+ {
+ for(UInt32 i = 1; i < (1 << NumBitLevels); i++)
+ Models[i].Init();
+ }
+ void Encode(CEncoder *rangeEncoder, UInt32 symbol)
+ {
+ UInt32 modelIndex = 1;
+ for (int bitIndex = NumBitLevels; bitIndex != 0 ;)
+ {
+ bitIndex--;
+ UInt32 bit = (symbol >> bitIndex) & 1;
+ Models[modelIndex].Encode(rangeEncoder, bit);
+ modelIndex = (modelIndex << 1) | bit;
+ }
+ };
+ void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol)
+ {
+ UInt32 modelIndex = 1;
+ for (int i = 0; i < NumBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ Models[modelIndex].Encode(rangeEncoder, bit);
+ modelIndex = (modelIndex << 1) | bit;
+ symbol >>= 1;
+ }
+ }
+ UInt32 GetPrice(UInt32 symbol) const
+ {
+ symbol |= (1 << NumBitLevels);
+ UInt32 price = 0;
+ while (symbol != 1)
+ {
+ price += Models[symbol >> 1].GetPrice(symbol & 1);
+ symbol >>= 1;
+ }
+ return price;
+ }
+ UInt32 ReverseGetPrice(UInt32 symbol) const
+ {
+ UInt32 price = 0;
+ UInt32 modelIndex = 1;
+ for (int i = NumBitLevels; i != 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += Models[modelIndex].GetPrice(bit);
+ modelIndex = (modelIndex << 1) | bit;
+ }
+ return price;
+ }
+};
+
+template <int numMoveBits, int NumBitLevels>
+class CBitTreeDecoder
+{
+ CBitDecoder<numMoveBits> Models[1 << NumBitLevels];
+public:
+ void Init()
+ {
+ for(UInt32 i = 1; i < (1 << NumBitLevels); i++)
+ Models[i].Init();
+ }
+ UInt32 Decode(CDecoder *rangeDecoder)
+ {
+ UInt32 modelIndex = 1;
+ RC_INIT_VAR
+ for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--)
+ {
+ // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder);
+ RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex)
+ }
+ RC_FLUSH_VAR
+ return modelIndex - (1 << NumBitLevels);
+ };
+ UInt32 ReverseDecode(CDecoder *rangeDecoder)
+ {
+ UInt32 modelIndex = 1;
+ UInt32 symbol = 0;
+ RC_INIT_VAR
+ for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+ {
+ // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
+ // modelIndex <<= 1;
+ // modelIndex += bit;
+ // symbol |= (bit << bitIndex);
+ RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))
+ }
+ RC_FLUSH_VAR
+ return symbol;
+ }
+};
+
+template <int numMoveBits>
+void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models,
+ CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol)
+{
+ UInt32 modelIndex = 1;
+ for (int i = 0; i < NumBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ Models[modelIndex].Encode(rangeEncoder, bit);
+ modelIndex = (modelIndex << 1) | bit;
+ symbol >>= 1;
+ }
+}
+
+template <int numMoveBits>
+UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models,
+ UInt32 NumBitLevels, UInt32 symbol)
+{
+ UInt32 price = 0;
+ UInt32 modelIndex = 1;
+ for (int i = NumBitLevels; i != 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += Models[modelIndex].GetPrice(bit);
+ modelIndex = (modelIndex << 1) | bit;
+ }
+ return price;
+}
+
+template <int numMoveBits>
+UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models,
+ CDecoder *rangeDecoder, int NumBitLevels)
+{
+ UInt32 modelIndex = 1;
+ UInt32 symbol = 0;
+ RC_INIT_VAR
+ for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+ {
+ // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
+ // modelIndex <<= 1;
+ // modelIndex += bit;
+ // symbol |= (bit << bitIndex);
+ RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))
+ }
+ RC_FLUSH_VAR
+ return symbol;
+}
+
+}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h
new file mode 100644
index 00000000..829fc83d
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h
@@ -0,0 +1,31 @@
+// Compress/RangeCoder/RangeCoderOpt.h
+
+#ifndef __COMPRESS_RANGECODER_OPT_H
+#define __COMPRESS_RANGECODER_OPT_H
+
+#define RC_INIT_VAR \
+ UInt32 range = rangeDecoder->Range; \
+ UInt32 code = rangeDecoder->Code;
+
+#define RC_FLUSH_VAR \
+ rangeDecoder->Range = range; \
+ rangeDecoder->Code = code;
+
+#define RC_NORMALIZE \
+ if (range < NCompress::NRangeCoder::kTopValue) \
+ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; }
+
+#define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \
+ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \
+ if (code < bound) \
+ { A0; range = bound; \
+ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \
+ mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \
+ mi = (mi + mi) + 1; }} \
+ RC_NORMALIZE
+
+#define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;)
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/StdAfx.h
new file mode 100644
index 00000000..21c2fd78
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/Compress/RangeCoder/StdAfx.h
@@ -0,0 +1,6 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/ICoder.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/ICoder.h
new file mode 100644
index 00000000..ce4594a0
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/ICoder.h
@@ -0,0 +1,156 @@
+// ICoder.h
+
+#ifndef __ICODER_H
+#define __ICODER_H
+
+#include "IStream.h"
+
+// "23170F69-40C1-278A-0000-000400xx0000"
+#define CODER_INTERFACE(i, x) \
+DEFINE_GUID(IID_ ## i, \
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \
+struct i: public IUnknown
+
+CODER_INTERFACE(ICompressProgressInfo, 0x04)
+{
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;
+};
+
+CODER_INTERFACE(ICompressCoder, 0x05)
+{
+ STDMETHOD(Code)(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 *inSize,
+ const UInt64 *outSize,
+ ICompressProgressInfo *progress) PURE;
+};
+
+CODER_INTERFACE(ICompressCoder2, 0x18)
+{
+ STDMETHOD(Code)(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress) PURE;
+};
+
+namespace NCoderPropID
+{
+ enum EEnum
+ {
+ kDictionarySize = 0x400,
+ kUsedMemorySize,
+ kOrder,
+ kPosStateBits = 0x440,
+ kLitContextBits,
+ kLitPosBits,
+ kNumFastBytes = 0x450,
+ kMatchFinder,
+ kNumPasses = 0x460,
+ kAlgorithm = 0x470,
+ kMultiThread = 0x480,
+ kEndMarker = 0x490
+ };
+}
+
+CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
+{
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
+ const PROPVARIANT *properties, UInt32 numProperties) PURE;
+};
+
+/*
+CODER_INTERFACE(ICompressSetCoderProperties, 0x21)
+{
+ STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;
+};
+*/
+
+CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)
+{
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;
+};
+
+CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)
+{
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE;
+};
+
+CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)
+{
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;
+};
+
+CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)
+{
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;
+};
+
+CODER_INTERFACE(ICompressSetInStream, 0x31)
+{
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;
+ STDMETHOD(ReleaseInStream)() PURE;
+};
+
+CODER_INTERFACE(ICompressSetOutStream, 0x32)
+{
+ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;
+ STDMETHOD(ReleaseOutStream)() PURE;
+};
+
+CODER_INTERFACE(ICompressSetInStreamSize, 0x33)
+{
+ STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;
+};
+
+CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
+{
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;
+};
+
+CODER_INTERFACE(ICompressFilter, 0x40)
+{
+ STDMETHOD(Init)() PURE;
+ STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;
+ // Filter return outSize (UInt32)
+ // if (outSize <= size): Filter have converted outSize bytes
+ // if (outSize > size): Filter have not converted anything.
+ // and it needs at least outSize bytes to convert one block
+ // (it's for crypto block algorithms).
+};
+
+CODER_INTERFACE(ICryptoProperties, 0x80)
+{
+ STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;
+ STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;
+};
+
+CODER_INTERFACE(ICryptoSetPassword, 0x90)
+{
+ STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;
+};
+
+CODER_INTERFACE(ICryptoSetCRC, 0xA0)
+{
+ STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;
+};
+
+//////////////////////
+// It's for DLL file
+namespace NMethodPropID
+{
+ enum EEnum
+ {
+ kID,
+ kName,
+ kDecoder,
+ kEncoder,
+ kInStreams,
+ kOutStreams,
+ kDescription
+ };
+}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/IStream.h b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/IStream.h
new file mode 100644
index 00000000..d92b89aa
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/7zip/IStream.h
@@ -0,0 +1,62 @@
+// IStream.h
+
+#ifndef __ISTREAM_H
+#define __ISTREAM_H
+
+#include "../Common/MyUnknown.h"
+#include "../Common/Types.h"
+
+// "23170F69-40C1-278A-0000-000300xx0000"
+
+#define STREAM_INTERFACE_SUB(i, b, x) \
+DEFINE_GUID(IID_ ## i, \
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \
+struct i: public b
+
+#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)
+
+STREAM_INTERFACE(ISequentialInStream, 0x01)
+{
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
+ /*
+ Out: if size != 0, return_value = S_OK and (*processedSize == 0),
+ then there are no more bytes in stream.
+ if (size > 0) && there are bytes in stream,
+ this function must read at least 1 byte.
+ This function is allowed to read less than number of remaining bytes in stream.
+ You must call Read function in loop, if you need exact amount of data
+ */
+};
+
+STREAM_INTERFACE(ISequentialOutStream, 0x02)
+{
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
+ /*
+ if (size > 0) this function must write at least 1 byte.
+ This function is allowed to write less than "size".
+ You must call Write function in loop, if you need to write exact amount of data
+ */
+};
+
+STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)
+{
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
+};
+
+STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)
+{
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
+ STDMETHOD(SetSize)(Int64 newSize) PURE;
+};
+
+STREAM_INTERFACE(IStreamGetSize, 0x06)
+{
+ STDMETHOD(GetSize)(UInt64 *size) PURE;
+};
+
+STREAM_INTERFACE(IOutStreamFlush, 0x07)
+{
+ STDMETHOD(Flush)() PURE;
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.cpp
new file mode 100644
index 00000000..dcb331ee
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.cpp
@@ -0,0 +1,118 @@
+// Common/Alloc.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include "MyWindows.h"
+#else
+#include <stdlib.h>
+#endif
+
+#include "Alloc.h"
+
+/* #define _SZ_ALLOC_DEBUG */
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
+#ifdef _SZ_ALLOC_DEBUG
+#include <stdio.h>
+int g_allocCount = 0;
+int g_allocCountMid = 0;
+int g_allocCountBig = 0;
+#endif
+
+void *MyAlloc(size_t size) throw()
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);
+ #endif
+ return ::malloc(size);
+}
+
+void MyFree(void *address) throw()
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
+ #endif
+
+ ::free(address);
+}
+
+#ifdef _WIN32
+
+void *MidAlloc(size_t size) throw()
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
+ #endif
+ return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
+}
+
+void MidFree(void *address) throw()
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
+ #endif
+ if (address == 0)
+ return;
+ ::VirtualFree(address, 0, MEM_RELEASE);
+}
+
+static SIZE_T g_LargePageSize =
+ #ifdef _WIN64
+ (1 << 21);
+ #else
+ (1 << 22);
+ #endif
+
+typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
+
+bool SetLargePageSize()
+{
+ GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
+ ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
+ if (largePageMinimum == 0)
+ return false;
+ SIZE_T size = largePageMinimum();
+ if (size == 0 || (size & (size - 1)) != 0)
+ return false;
+ g_LargePageSize = size;
+ return true;
+}
+
+
+void *BigAlloc(size_t size) throw()
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
+ #endif
+
+ if (size >= (1 << 18))
+ {
+ void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
+ MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
+ if (res != 0)
+ return res;
+ }
+ return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
+}
+
+void BigFree(void *address) throw()
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
+ #endif
+
+ if (address == 0)
+ return;
+ ::VirtualFree(address, 0, MEM_RELEASE);
+}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.h
new file mode 100644
index 00000000..2ae3891d
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Alloc.h
@@ -0,0 +1,29 @@
+// Common/Alloc.h
+
+#ifndef __COMMON_ALLOC_H
+#define __COMMON_ALLOC_H
+
+#include <stddef.h>
+
+void *MyAlloc(size_t size) throw();
+void MyFree(void *address) throw();
+
+#ifdef _WIN32
+
+bool SetLargePageSize();
+
+void *MidAlloc(size_t size) throw();
+void MidFree(void *address) throw();
+void *BigAlloc(size_t size) throw();
+void BigFree(void *address) throw();
+
+#else
+
+#define MidAlloc(size) MyAlloc(size)
+#define MidFree(address) MyFree(address)
+#define BigAlloc(size) MyAlloc(size)
+#define BigFree(address) MyFree(address)
+
+#endif
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.cpp
new file mode 100644
index 00000000..92bc009c
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.cpp
@@ -0,0 +1,61 @@
+// Common/CRC.cpp
+
+#include "StdAfx.h"
+
+#include "CRC.h"
+
+static const UInt32 kCRCPoly = 0xEDB88320;
+
+UInt32 CCRC::Table[256];
+
+void CCRC::InitTable()
+{
+ for (UInt32 i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ for (int j = 0; j < 8; j++)
+ if (r & 1)
+ r = (r >> 1) ^ kCRCPoly;
+ else
+ r >>= 1;
+ CCRC::Table[i] = r;
+ }
+}
+
+class CCRCTableInit
+{
+public:
+ CCRCTableInit() { CCRC::InitTable(); }
+} g_CRCTableInit;
+
+void CCRC::UpdateByte(Byte b)
+{
+ _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8);
+}
+
+void CCRC::UpdateUInt16(UInt16 v)
+{
+ UpdateByte(Byte(v));
+ UpdateByte(Byte(v >> 8));
+}
+
+void CCRC::UpdateUInt32(UInt32 v)
+{
+ for (int i = 0; i < 4; i++)
+ UpdateByte((Byte)(v >> (8 * i)));
+}
+
+void CCRC::UpdateUInt64(UInt64 v)
+{
+ for (int i = 0; i < 8; i++)
+ UpdateByte((Byte)(v >> (8 * i)));
+}
+
+void CCRC::Update(const void *data, size_t size)
+{
+ UInt32 v = _value;
+ const Byte *p = (const Byte *)data;
+ for (; size > 0 ; size--, p++)
+ v = Table[((Byte)(v)) ^ *p] ^ (v >> 8);
+ _value = v;
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.h
new file mode 100644
index 00000000..c9d43d00
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CRC.h
@@ -0,0 +1,36 @@
+// Common/CRC.h
+
+#ifndef __COMMON_CRC_H
+#define __COMMON_CRC_H
+
+#include <stddef.h>
+#include "Types.h"
+
+class CCRC
+{
+ UInt32 _value;
+public:
+ static UInt32 Table[256];
+ static void InitTable();
+
+ CCRC(): _value(0xFFFFFFFF){};
+ void Init() { _value = 0xFFFFFFFF; }
+ void UpdateByte(Byte v);
+ void UpdateUInt16(UInt16 v);
+ void UpdateUInt32(UInt32 v);
+ void UpdateUInt64(UInt64 v);
+ void Update(const void *data, size_t size);
+ UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; }
+ static UInt32 CalculateDigest(const void *data, size_t size)
+ {
+ CCRC crc;
+ crc.Update(data, size);
+ return crc.GetDigest();
+ }
+ static bool VerifyDigest(UInt32 digest, const void *data, size_t size)
+ {
+ return (CalculateDigest(data, size) == digest);
+ }
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.cpp
new file mode 100644
index 00000000..48deb70a
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.cpp
@@ -0,0 +1,78 @@
+// Common/C_FileIO.h
+
+#include "C_FileIO.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+namespace NC {
+namespace NFile {
+namespace NIO {
+
+bool CFileBase::OpenBinary(const char *name, int flags)
+{
+ #ifdef O_BINARY
+ flags |= O_BINARY;
+ #endif
+ Close();
+ _handle = ::open(name, flags, 0666);
+ return _handle != -1;
+}
+
+bool CFileBase::Close()
+{
+ if(_handle == -1)
+ return true;
+ if (close(_handle) != 0)
+ return false;
+ _handle = -1;
+ return true;
+}
+
+bool CFileBase::GetLength(UInt64 &length) const
+{
+ off_t curPos = Seek(0, SEEK_CUR);
+ off_t lengthTemp = Seek(0, SEEK_END);
+ Seek(curPos, SEEK_SET);
+ length = (UInt64)lengthTemp;
+ return true;
+}
+
+off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const
+{
+ return ::lseek(_handle, distanceToMove, moveMethod);
+}
+
+/////////////////////////
+// CInFile
+
+bool CInFile::Open(const char *name)
+{
+ return CFileBase::OpenBinary(name, O_RDONLY);
+}
+
+ssize_t CInFile::Read(void *data, size_t size)
+{
+ return read(_handle, data, size);
+}
+
+/////////////////////////
+// COutFile
+
+bool COutFile::Create(const char *name, bool createAlways)
+{
+ if (createAlways)
+ {
+ Close();
+ _handle = ::creat(name, 0666);
+ return _handle != -1;
+ }
+ return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY);
+}
+
+ssize_t COutFile::Write(const void *data, size_t size)
+{
+ return write(_handle, data, size);
+}
+
+}}}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.h
new file mode 100644
index 00000000..48836a15
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/C_FileIO.h
@@ -0,0 +1,45 @@
+// Common/C_FileIO.h
+
+#ifndef __COMMON_C_FILEIO_H
+#define __COMMON_C_FILEIO_H
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "Types.h"
+#include "MyWindows.h"
+
+namespace NC {
+namespace NFile {
+namespace NIO {
+
+class CFileBase
+{
+protected:
+ int _handle;
+ bool OpenBinary(const char *name, int flags);
+public:
+ CFileBase(): _handle(-1) {};
+ ~CFileBase() { Close(); }
+ bool Close();
+ bool GetLength(UInt64 &length) const;
+ off_t Seek(off_t distanceToMove, int moveMethod) const;
+};
+
+class CInFile: public CFileBase
+{
+public:
+ bool Open(const char *name);
+ ssize_t Read(void *data, size_t size);
+};
+
+class COutFile: public CFileBase
+{
+public:
+ bool Create(const char *name, bool createAlways);
+ ssize_t Write(const void *data, size_t size);
+};
+
+}}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/ComTry.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/ComTry.h
new file mode 100644
index 00000000..98e59276
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/ComTry.h
@@ -0,0 +1,17 @@
+// ComTry.h
+
+#ifndef __COM_TRY_H
+#define __COM_TRY_H
+
+#include "MyWindows.h"
+// #include "Exception.h"
+// #include "NewHandler.h"
+
+#define COM_TRY_BEGIN try {
+#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }
+
+ // catch(const CNewException &) { return E_OUTOFMEMORY; }\
+ // catch(const CSystemException &e) { return e.ErrorCode; }\
+ // catch(...) { return E_FAIL; }
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.cpp
new file mode 100644
index 00000000..756e7166
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.cpp
@@ -0,0 +1,263 @@
+// CommandLineParser.cpp
+
+#include "StdAfx.h"
+
+#include "CommandLineParser.h"
+
+namespace NCommandLineParser {
+
+void SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
+{
+ dest1.Empty();
+ dest2.Empty();
+ bool quoteMode = false;
+ int i;
+ for (i = 0; i < src.Length(); i++)
+ {
+ wchar_t c = src[i];
+ if (c == L'\"')
+ quoteMode = !quoteMode;
+ else if (c == L' ' && !quoteMode)
+ {
+ i++;
+ break;
+ }
+ else
+ dest1 += c;
+ }
+ dest2 = src.Mid(i);
+}
+
+void SplitCommandLine(const UString &s, UStringVector &parts)
+{
+ UString sTemp = s;
+ sTemp.Trim();
+ parts.Clear();
+ while (true)
+ {
+ UString s1, s2;
+ SplitCommandLine(sTemp, s1, s2);
+ // s1.Trim();
+ // s2.Trim();
+ if (!s1.IsEmpty())
+ parts.Add(s1);
+ if (s2.IsEmpty())
+ return;
+ sTemp = s2;
+ }
+}
+
+
+static const wchar_t kSwitchID1 = '-';
+// static const wchar_t kSwitchID2 = '/';
+
+static const wchar_t kSwitchMinus = '-';
+static const wchar_t *kStopSwitchParsing = L"--";
+
+static bool IsItSwitchChar(wchar_t c)
+{
+ return (c == kSwitchID1 /*|| c == kSwitchID2 */);
+}
+
+CParser::CParser(int numSwitches):
+ _numSwitches(numSwitches)
+{
+ _switches = new CSwitchResult[_numSwitches];
+}
+
+CParser::~CParser()
+{
+ delete []_switches;
+}
+
+void CParser::ParseStrings(const CSwitchForm *switchForms,
+ const UStringVector &commandStrings)
+{
+ int numCommandStrings = commandStrings.Size();
+ bool stopSwitch = false;
+ for (int i = 0; i < numCommandStrings; i++)
+ {
+ const UString &s = commandStrings[i];
+ if (stopSwitch)
+ NonSwitchStrings.Add(s);
+ else
+ if (s == kStopSwitchParsing)
+ stopSwitch = true;
+ else
+ if (!ParseString(s, switchForms))
+ NonSwitchStrings.Add(s);
+ }
+}
+
+// if string contains switch then function updates switch structures
+// out: (string is a switch)
+bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
+{
+ int len = s.Length();
+ if (len == 0)
+ return false;
+ int pos = 0;
+ if (!IsItSwitchChar(s[pos]))
+ return false;
+ while(pos < len)
+ {
+ if (IsItSwitchChar(s[pos]))
+ pos++;
+ const int kNoLen = -1;
+ int matchedSwitchIndex = 0; // GCC Warning
+ int maxLen = kNoLen;
+ for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)
+ {
+ int switchLen = MyStringLen(switchForms[switchIndex].IDString);
+ if (switchLen <= maxLen || pos + switchLen > len)
+ continue;
+
+ UString temp = s + pos;
+ temp = temp.Left(switchLen);
+ if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)
+ // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)
+ {
+ matchedSwitchIndex = switchIndex;
+ maxLen = switchLen;
+ }
+ }
+ if (maxLen == kNoLen)
+ throw "maxLen == kNoLen";
+ CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];
+ const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];
+ if ((!switchForm.Multi) && matchedSwitch.ThereIs)
+ throw "switch must be single";
+ matchedSwitch.ThereIs = true;
+ pos += maxLen;
+ int tailSize = len - pos;
+ NSwitchType::EEnum type = switchForm.Type;
+ switch(type)
+ {
+ case NSwitchType::kPostMinus:
+ {
+ if (tailSize == 0)
+ matchedSwitch.WithMinus = false;
+ else
+ {
+ matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);
+ if (matchedSwitch.WithMinus)
+ pos++;
+ }
+ break;
+ }
+ case NSwitchType::kPostChar:
+ {
+ if (tailSize < switchForm.MinLen)
+ throw "switch is not full";
+ UString set = switchForm.PostCharSet;
+ const int kEmptyCharValue = -1;
+ if (tailSize == 0)
+ matchedSwitch.PostCharIndex = kEmptyCharValue;
+ else
+ {
+ int index = set.Find(s[pos]);
+ if (index < 0)
+ matchedSwitch.PostCharIndex = kEmptyCharValue;
+ else
+ {
+ matchedSwitch.PostCharIndex = index;
+ pos++;
+ }
+ }
+ break;
+ }
+ case NSwitchType::kLimitedPostString:
+ case NSwitchType::kUnLimitedPostString:
+ {
+ int minLen = switchForm.MinLen;
+ if (tailSize < minLen)
+ throw "switch is not full";
+ if (type == NSwitchType::kUnLimitedPostString)
+ {
+ matchedSwitch.PostStrings.Add(s.Mid(pos));
+ return true;
+ }
+ int maxLen = switchForm.MaxLen;
+ UString stringSwitch = s.Mid(pos, minLen);
+ pos += minLen;
+ for(int i = minLen; i < maxLen && pos < len; i++, pos++)
+ {
+ wchar_t c = s[pos];
+ if (IsItSwitchChar(c))
+ break;
+ stringSwitch += c;
+ }
+ matchedSwitch.PostStrings.Add(stringSwitch);
+ break;
+ }
+ case NSwitchType::kSimple:
+ break;
+ }
+ }
+ return true;
+}
+
+const CSwitchResult& CParser::operator[](size_t index) const
+{
+ return _switches[index];
+}
+
+/////////////////////////////////
+// Command parsing procedures
+
+int ParseCommand(int numCommandForms, const CCommandForm *commandForms,
+ const UString &commandString, UString &postString)
+{
+ for(int i = 0; i < numCommandForms; i++)
+ {
+ const UString id = commandForms[i].IDString;
+ if (commandForms[i].PostStringMode)
+ {
+ if(commandString.Find(id) == 0)
+ {
+ postString = commandString.Mid(id.Length());
+ return i;
+ }
+ }
+ else
+ if (commandString == id)
+ {
+ postString.Empty();
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms,
+ const UString &commandString, CIntVector &indices)
+{
+ indices.Clear();
+ int numUsedChars = 0;
+ for(int i = 0; i < numForms; i++)
+ {
+ const CCommandSubCharsSet &set = forms[i];
+ int currentIndex = -1;
+ int len = MyStringLen(set.Chars);
+ for(int j = 0; j < len; j++)
+ {
+ wchar_t c = set.Chars[j];
+ int newIndex = commandString.Find(c);
+ if (newIndex >= 0)
+ {
+ if (currentIndex >= 0)
+ return false;
+ if (commandString.Find(c, newIndex + 1) >= 0)
+ return false;
+ currentIndex = j;
+ numUsedChars++;
+ }
+ }
+ if(currentIndex == -1 && !set.EmptyAllowed)
+ return false;
+ indices.Add(currentIndex);
+ }
+ return (numUsedChars == commandString.Length());
+}
+
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.h
new file mode 100644
index 00000000..75b3589c
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/CommandLineParser.h
@@ -0,0 +1,82 @@
+// Common/CommandLineParser.h
+
+#ifndef __COMMON_COMMANDLINEPARSER_H
+#define __COMMON_COMMANDLINEPARSER_H
+
+#include "Common/String.h"
+
+namespace NCommandLineParser {
+
+void SplitCommandLine(const UString &src, UString &dest1, UString &dest2);
+void SplitCommandLine(const UString &s, UStringVector &parts);
+
+namespace NSwitchType {
+ enum EEnum
+ {
+ kSimple,
+ kPostMinus,
+ kLimitedPostString,
+ kUnLimitedPostString,
+ kPostChar
+ };
+}
+
+struct CSwitchForm
+{
+ const wchar_t *IDString;
+ NSwitchType::EEnum Type;
+ bool Multi;
+ int MinLen;
+ int MaxLen;
+ const wchar_t *PostCharSet;
+};
+
+struct CSwitchResult
+{
+ bool ThereIs;
+ bool WithMinus;
+ UStringVector PostStrings;
+ int PostCharIndex;
+ CSwitchResult(): ThereIs(false) {};
+};
+
+class CParser
+{
+ int _numSwitches;
+ CSwitchResult *_switches;
+ bool ParseString(const UString &s, const CSwitchForm *switchForms);
+public:
+ UStringVector NonSwitchStrings;
+ CParser(int numSwitches);
+ ~CParser();
+ void ParseStrings(const CSwitchForm *switchForms,
+ const UStringVector &commandStrings);
+ const CSwitchResult& operator[](size_t index) const;
+};
+
+/////////////////////////////////
+// Command parsing procedures
+
+struct CCommandForm
+{
+ wchar_t *IDString;
+ bool PostStringMode;
+};
+
+// Returns: Index of form and postString; -1, if there is no match
+int ParseCommand(int numCommandForms, const CCommandForm *commandForms,
+ const UString &commandString, UString &postString);
+
+struct CCommandSubCharsSet
+{
+ wchar_t *Chars;
+ bool EmptyAllowed;
+};
+
+// Returns: indices of finded chars; -1 if there is no match
+bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms,
+ const UString &commandString, CIntVector &indices);
+
+}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Defs.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Defs.h
new file mode 100644
index 00000000..69b8ecea
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Defs.h
@@ -0,0 +1,20 @@
+// Common/Defs.h
+
+#ifndef __COMMON_DEFS_H
+#define __COMMON_DEFS_H
+
+template <class T> inline T MyMin(T a, T b)
+ { return a < b ? a : b; }
+template <class T> inline T MyMax(T a, T b)
+ { return a > b ? a : b; }
+
+template <class T> inline int MyCompare(T a, T b)
+ { return a < b ? -1 : (a == b ? 0 : 1); }
+
+inline int BoolToInt(bool value)
+ { return (value ? 1: 0); }
+
+inline bool IntToBool(int value)
+ { return (value != 0); }
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyCom.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyCom.h
new file mode 100644
index 00000000..8476b572
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyCom.h
@@ -0,0 +1,203 @@
+// MyCom.h
+
+#ifndef __MYCOM_H
+#define __MYCOM_H
+
+#include "MyWindows.h"
+
+#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; }
+
+template <class T>
+class CMyComPtr
+{
+ T* _p;
+public:
+ // typedef T _PtrClass;
+ CMyComPtr() { _p = NULL;}
+ CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }
+ CMyComPtr(const CMyComPtr<T>& lp)
+ {
+ if ((_p = lp._p) != NULL)
+ _p->AddRef();
+ }
+ ~CMyComPtr() { if (_p) _p->Release(); }
+ void Release() { if (_p) { _p->Release(); _p = NULL; } }
+ operator T*() const { return (T*)_p; }
+ // T& operator*() const { return *_p; }
+ T** operator&() { return &_p; }
+ T* operator->() const { return _p; }
+ T* operator=(T* p)
+ {
+ if (p != 0)
+ p->AddRef();
+ if (_p)
+ _p->Release();
+ _p = p;
+ return p;
+ }
+ T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
+ bool operator!() const { return (_p == NULL); }
+ // bool operator==(T* pT) const { return _p == pT; }
+ // Compare two objects for equivalence
+ void Attach(T* p2)
+ {
+ Release();
+ _p = p2;
+ }
+ T* Detach()
+ {
+ T* pt = _p;
+ _p = NULL;
+ return pt;
+ }
+ #ifdef _WIN32
+ HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
+ {
+ return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
+ }
+ #endif
+ /*
+ HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
+ {
+ CLSID clsid;
+ HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
+ ATLASSERT(_p == NULL);
+ if (SUCCEEDED(hr))
+ hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
+ return hr;
+ }
+ */
+ template <class Q>
+ HRESULT QueryInterface(REFGUID iid, Q** pp) const
+ {
+ return _p->QueryInterface(iid, (void**)pp);
+ }
+};
+
+//////////////////////////////////////////////////////////
+
+class CMyComBSTR
+{
+public:
+ BSTR m_str;
+ CMyComBSTR() { m_str = NULL; }
+ CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); }
+ // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
+ // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }
+ CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
+ /*
+ CMyComBSTR(REFGUID src)
+ {
+ LPOLESTR szGuid;
+ StringFromCLSID(src, &szGuid);
+ m_str = ::SysAllocString(szGuid);
+ CoTaskMemFree(szGuid);
+ }
+ */
+ ~CMyComBSTR() { ::SysFreeString(m_str); }
+ CMyComBSTR& operator=(const CMyComBSTR& src)
+ {
+ if (m_str != src.m_str)
+ {
+ if (m_str)
+ ::SysFreeString(m_str);
+ m_str = src.MyCopy();
+ }
+ return *this;
+ }
+ CMyComBSTR& operator=(LPCOLESTR pSrc)
+ {
+ ::SysFreeString(m_str);
+ m_str = ::SysAllocString(pSrc);
+ return *this;
+ }
+ unsigned int Length() const { return ::SysStringLen(m_str); }
+ operator BSTR() const { return m_str; }
+ BSTR* operator&() { return &m_str; }
+ BSTR MyCopy() const
+ {
+ int byteLen = ::SysStringByteLen(m_str);
+ BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
+ memmove(res, m_str, byteLen);
+ return res;
+ }
+ void Attach(BSTR src) { m_str = src; }
+ BSTR Detach()
+ {
+ BSTR s = m_str;
+ m_str = NULL;
+ return s;
+ }
+ void Empty()
+ {
+ ::SysFreeString(m_str);
+ m_str = NULL;
+ }
+ bool operator!() const { return (m_str == NULL); }
+};
+
+
+//////////////////////////////////////////////////////////
+
+class CMyUnknownImp
+{
+public:
+ ULONG __m_RefCount;
+ CMyUnknownImp(): __m_RefCount(0) {}
+};
+
+#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
+ (REFGUID iid, void **outObject) {
+
+#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \
+ { *outObject = (void *)(i *)this; AddRef(); return S_OK; }
+
+#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }
+
+#define MY_ADDREF_RELEASE \
+STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \
+STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \
+ return __m_RefCount; delete this; return 0; }
+
+#define MY_UNKNOWN_IMP_SPEC(i) \
+ MY_QUERYINTERFACE_BEGIN \
+ i \
+ MY_QUERYINTERFACE_END \
+ MY_ADDREF_RELEASE
+
+
+#define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \
+ MY_QUERYINTERFACE_END \
+ MY_ADDREF_RELEASE
+
+#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
+ MY_QUERYINTERFACE_ENTRY(i) \
+ )
+
+#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
+ MY_QUERYINTERFACE_ENTRY(i1) \
+ MY_QUERYINTERFACE_ENTRY(i2) \
+ )
+
+#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
+ MY_QUERYINTERFACE_ENTRY(i1) \
+ MY_QUERYINTERFACE_ENTRY(i2) \
+ MY_QUERYINTERFACE_ENTRY(i3) \
+ )
+
+#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
+ MY_QUERYINTERFACE_ENTRY(i1) \
+ MY_QUERYINTERFACE_ENTRY(i2) \
+ MY_QUERYINTERFACE_ENTRY(i3) \
+ MY_QUERYINTERFACE_ENTRY(i4) \
+ )
+
+#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
+ MY_QUERYINTERFACE_ENTRY(i1) \
+ MY_QUERYINTERFACE_ENTRY(i2) \
+ MY_QUERYINTERFACE_ENTRY(i3) \
+ MY_QUERYINTERFACE_ENTRY(i4) \
+ MY_QUERYINTERFACE_ENTRY(i5) \
+ )
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyGuidDef.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyGuidDef.h
new file mode 100644
index 00000000..2cc8d199
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyGuidDef.h
@@ -0,0 +1,54 @@
+// Common/MyGuidDef.h
+
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+
+#include "Types.h"
+
+typedef struct {
+ UInt32 Data1;
+ UInt16 Data2;
+ UInt16 Data3;
+ unsigned char Data4[8];
+} GUID;
+
+#ifdef __cplusplus
+#define REFGUID const GUID &
+#else
+#define REFGUID const GUID *
+#endif
+
+#define REFCLSID REFGUID
+#define REFIID REFGUID
+
+#ifdef __cplusplus
+inline bool operator==(REFGUID g1, REFGUID g2)
+{
+ for (int i = 0; i < (int)sizeof(g1); i++)
+ if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i])
+ return false;
+ return true;
+}
+inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }
+#endif
+
+#ifdef __cplusplus
+ #define MY_EXTERN_C extern "C"
+#else
+ #define MY_EXTERN_C extern
+#endif
+
+#endif // GUID_DEFINED
+
+
+#ifdef DEFINE_GUID
+#undef DEFINE_GUID
+#endif
+
+#ifdef INITGUID
+ #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
+#else
+ #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ MY_EXTERN_C const GUID name
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyInitGuid.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyInitGuid.h
new file mode 100644
index 00000000..53b0f034
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyInitGuid.h
@@ -0,0 +1,13 @@
+// Common/MyInitGuid.h
+
+#ifndef __COMMON_MYINITGUID_H
+#define __COMMON_MYINITGUID_H
+
+#ifdef _WIN32
+#include <initguid.h>
+#else
+#define INITGUID
+#include "MyGuidDef.h"
+#endif
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyUnknown.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyUnknown.h
new file mode 100644
index 00000000..6cd32cad
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyUnknown.h
@@ -0,0 +1,24 @@
+// MyUnknown.h
+
+#ifndef __MYUNKNOWN_H
+#define __MYUNKNOWN_H
+
+#ifdef _WIN32
+
+#ifdef _WIN32_WCE
+#if (_WIN32_WCE > 300)
+#include <basetyps.h>
+#else
+#define MIDL_INTERFACE(x) struct
+#endif
+#else
+#include <basetyps.h>
+#endif
+
+#include <unknwn.h>
+
+#else
+#include "MyWindows.h"
+#endif
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyWindows.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyWindows.h
new file mode 100644
index 00000000..65a4e9e7
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/MyWindows.h
@@ -0,0 +1,183 @@
+// MyWindows.h
+
+#ifndef __MYWINDOWS_H
+#define __MYWINDOWS_H
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+#else
+
+#include <stddef.h> // for wchar_t
+#include <string.h>
+
+#include "MyGuidDef.h"
+
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef unsigned char BYTE;
+
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef unsigned short WORD;
+typedef short VARIANT_BOOL;
+
+typedef int INT;
+typedef Int32 INT32;
+typedef unsigned int UINT;
+typedef UInt32 UINT32;
+typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit
+typedef UINT32 ULONG;
+typedef UINT32 DWORD;
+
+typedef Int64 LONGLONG;
+typedef UInt64 ULONGLONG;
+
+typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;
+typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;
+
+typedef const CHAR *LPCSTR;
+typedef CHAR TCHAR;
+typedef const TCHAR *LPCTSTR;
+typedef wchar_t WCHAR;
+typedef WCHAR OLECHAR;
+typedef const WCHAR *LPCWSTR;
+typedef OLECHAR *BSTR;
+typedef const OLECHAR *LPCOLESTR;
+typedef OLECHAR *LPOLESTR;
+
+typedef struct _FILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+}FILETIME;
+
+#define HRESULT LONG
+#define FAILED(Status) ((HRESULT)(Status)<0)
+typedef ULONG PROPID;
+typedef LONG SCODE;
+
+#define S_OK ((HRESULT)0x00000000L)
+#define S_FALSE ((HRESULT)0x00000001L)
+#define E_NOINTERFACE ((HRESULT)0x80004002L)
+#define E_ABORT ((HRESULT)0x80004004L)
+#define E_FAIL ((HRESULT)0x80004005L)
+#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)
+#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)
+#define E_INVALIDARG ((HRESULT)0x80070057L)
+
+#ifdef _MSC_VER
+#define STDMETHODCALLTYPE __stdcall
+#else
+#define STDMETHODCALLTYPE
+#endif
+
+#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f
+#define STDMETHOD(f) STDMETHOD_(HRESULT, f)
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+#define STDMETHODIMP STDMETHODIMP_(HRESULT)
+
+#define PURE = 0
+
+#define MIDL_INTERFACE(x) struct
+
+struct IUnknown
+{
+ STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;
+ STDMETHOD_(ULONG, AddRef)() PURE;
+ STDMETHOD_(ULONG, Release)() PURE;
+};
+
+typedef IUnknown *LPUNKNOWN;
+
+#define VARIANT_TRUE ((VARIANT_BOOL)-1)
+#define VARIANT_FALSE ((VARIANT_BOOL)0)
+
+enum VARENUM
+{
+ VT_EMPTY = 0,
+ VT_NULL = 1,
+ VT_I2 = 2,
+ VT_I4 = 3,
+ VT_R4 = 4,
+ VT_R8 = 5,
+ VT_CY = 6,
+ VT_DATE = 7,
+ VT_BSTR = 8,
+ VT_DISPATCH = 9,
+ VT_ERROR = 10,
+ VT_BOOL = 11,
+ VT_VARIANT = 12,
+ VT_UNKNOWN = 13,
+ VT_DECIMAL = 14,
+ VT_I1 = 16,
+ VT_UI1 = 17,
+ VT_UI2 = 18,
+ VT_UI4 = 19,
+ VT_I8 = 20,
+ VT_UI8 = 21,
+ VT_INT = 22,
+ VT_UINT = 23,
+ VT_VOID = 24,
+ VT_HRESULT = 25,
+ VT_FILETIME = 64
+};
+
+typedef unsigned short VARTYPE;
+typedef WORD PROPVAR_PAD1;
+typedef WORD PROPVAR_PAD2;
+typedef WORD PROPVAR_PAD3;
+
+typedef struct tagPROPVARIANT
+{
+ VARTYPE vt;
+ PROPVAR_PAD1 wReserved1;
+ PROPVAR_PAD2 wReserved2;
+ PROPVAR_PAD3 wReserved3;
+ union
+ {
+ CHAR cVal;
+ UCHAR bVal;
+ SHORT iVal;
+ USHORT uiVal;
+ LONG lVal;
+ ULONG ulVal;
+ INT intVal;
+ UINT uintVal;
+ LARGE_INTEGER hVal;
+ ULARGE_INTEGER uhVal;
+ VARIANT_BOOL boolVal;
+ SCODE scode;
+ FILETIME filetime;
+ BSTR bstrVal;
+ };
+} PROPVARIANT;
+
+typedef PROPVARIANT tagVARIANT;
+typedef tagVARIANT VARIANT;
+typedef VARIANT VARIANTARG;
+
+MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);
+MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);
+MY_EXTERN_C void SysFreeString(BSTR bstr);
+MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);
+MY_EXTERN_C UINT SysStringLen(BSTR bstr);
+
+MY_EXTERN_C DWORD GetLastError();
+MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);
+MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);
+MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);
+
+#define CP_ACP 0
+#define CP_OEMCP 1
+
+typedef enum tagSTREAM_SEEK
+{
+ STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+} STREAM_SEEK;
+
+#endif
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.cpp
new file mode 100644
index 00000000..2f4e007b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.cpp
@@ -0,0 +1,114 @@
+// NewHandler.cpp
+
+#include "StdAfx.h"
+
+#include <stdlib.h>
+
+#include "NewHandler.h"
+
+// #define DEBUG_MEMORY_LEAK
+
+#ifndef DEBUG_MEMORY_LEAK
+
+void *
+#ifdef _MSC_VER
+__cdecl
+#endif
+operator new(size_t size)
+{
+ // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
+ void *p = ::malloc(size);
+ if (p == 0)
+ throw CNewException();
+ return p;
+}
+
+void
+#ifdef _MSC_VER
+__cdecl
+#endif
+operator delete(void *p) throw()
+{
+ /*
+ if (p == 0)
+ return;
+ ::HeapFree(::GetProcessHeap(), 0, p);
+ */
+ ::free(p);
+}
+
+#else
+
+#pragma init_seg(lib)
+const int kDebugSize = 1000000;
+static void *a[kDebugSize];
+static int index = 0;
+
+static int numAllocs = 0;
+void * __cdecl operator new(size_t size)
+{
+ numAllocs++;
+ void *p = HeapAlloc(GetProcessHeap(), 0, size);
+ if (index == 40)
+ {
+ int t = 1;
+ }
+ if (index < kDebugSize)
+ {
+ a[index] = p;
+ index++;
+ }
+ if (p == 0)
+ throw CNewException();
+ printf("Alloc %6d, size = %8d\n", numAllocs, size);
+ return p;
+}
+
+class CC
+{
+public:
+ CC()
+ {
+ for (int i = 0; i < kDebugSize; i++)
+ a[i] = 0;
+ }
+ ~CC()
+ {
+ for (int i = 0; i < kDebugSize; i++)
+ if (a[i] != 0)
+ return;
+ }
+} g_CC;
+
+
+void __cdecl operator delete(void *p)
+{
+ if (p == 0)
+ return;
+ /*
+ for (int i = 0; i < index; i++)
+ if (a[i] == p)
+ a[i] = 0;
+ */
+ HeapFree(GetProcessHeap(), 0, p);
+ numAllocs--;
+ printf("Free %d\n", numAllocs);
+}
+
+#endif
+
+/*
+int MemErrorVC(size_t)
+{
+ throw CNewException();
+ // return 1;
+}
+CNewHandlerSetter::CNewHandlerSetter()
+{
+ // MemErrorOldVCFunction = _set_new_handler(MemErrorVC);
+}
+CNewHandlerSetter::~CNewHandlerSetter()
+{
+ // _set_new_handler(MemErrorOldVCFunction);
+}
+*/
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.h
new file mode 100644
index 00000000..b3a4f7e1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/NewHandler.h
@@ -0,0 +1,14 @@
+// Common/NewHandler.h
+
+#ifndef __COMMON_NEWHANDLER_H
+#define __COMMON_NEWHANDLER_H
+
+class CNewException {};
+
+void
+#ifdef _MSC_VER
+__cdecl
+#endif
+operator delete(void *p) throw();
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StdAfx.h
new file mode 100644
index 00000000..2547611b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+// #include "MyWindows.h"
+#include "NewHandler.h"
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.cpp
new file mode 100644
index 00000000..b6c12e99
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.cpp
@@ -0,0 +1,198 @@
+// Common/String.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include "StringConvert.h"
+#else
+#include <ctype.h>
+#endif
+
+#include "Common/String.h"
+
+
+#ifdef _WIN32
+
+#ifndef _UNICODE
+
+wchar_t MyCharUpper(wchar_t c)
+{
+ if (c == 0)
+ return 0;
+ wchar_t *res = CharUpperW((LPWSTR)(unsigned int)c);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return (wchar_t)(unsigned int)res;
+ const int kBufferSize = 4;
+ char s[kBufferSize + 1];
+ int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
+ if (numChars == 0 || numChars > kBufferSize)
+ return c;
+ s[numChars] = 0;
+ ::CharUpperA(s);
+ ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
+ return c;
+}
+
+wchar_t MyCharLower(wchar_t c)
+{
+ if (c == 0)
+ return 0;
+ wchar_t *res = CharLowerW((LPWSTR)(unsigned int)c);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return (wchar_t)(unsigned int)res;
+ const int kBufferSize = 4;
+ char s[kBufferSize + 1];
+ int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
+ if (numChars == 0 || numChars > kBufferSize)
+ return c;
+ s[numChars] = 0;
+ ::CharLowerA(s);
+ ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
+ return c;
+}
+
+wchar_t * MyStringUpper(wchar_t *s)
+{
+ if (s == 0)
+ return 0;
+ wchar_t *res = CharUpperW(s);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return res;
+ AString a = UnicodeStringToMultiByte(s);
+ a.MakeUpper();
+ return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
+}
+
+wchar_t * MyStringLower(wchar_t *s)
+{
+ if (s == 0)
+ return 0;
+ wchar_t *res = CharLowerW(s);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return res;
+ AString a = UnicodeStringToMultiByte(s);
+ a.MakeLower();
+ return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
+}
+
+#endif
+
+/*
+inline int ConvertCompareResult(int r) { return r - 2; }
+
+int MyStringCollate(const wchar_t *s1, const wchar_t *s2)
+{
+ int res = CompareStringW(
+ LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1);
+ #ifdef _UNICODE
+ return ConvertCompareResult(res);
+ #else
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return ConvertCompareResult(res);
+ return MyStringCollate(UnicodeStringToMultiByte(s1),
+ UnicodeStringToMultiByte(s2));
+ #endif
+}
+
+#ifndef _WIN32_WCE
+int MyStringCollate(const char *s1, const char *s2)
+{
+ return ConvertCompareResult(CompareStringA(
+ LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1));
+}
+
+int MyStringCollateNoCase(const char *s1, const char *s2)
+{
+ return ConvertCompareResult(CompareStringA(
+ LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1));
+}
+#endif
+
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
+{
+ int res = CompareStringW(
+ LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1);
+ #ifdef _UNICODE
+ return ConvertCompareResult(res);
+ #else
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return ConvertCompareResult(res);
+ return MyStringCollateNoCase(UnicodeStringToMultiByte(s1),
+ UnicodeStringToMultiByte(s2));
+ #endif
+}
+*/
+
+#else
+
+wchar_t MyCharUpper(wchar_t c)
+{
+ return toupper(c);
+}
+
+/*
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
+{
+ while (true)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ wchar_t u1 = MyCharUpper(c1);
+ wchar_t u2 = MyCharUpper(c2);
+
+ if (u1 < u2) return -1;
+ if (u1 > u2) return 1;
+ if (u1 == 0) return 0;
+ }
+}
+*/
+
+#endif
+
+int MyStringCompare(const char *s1, const char *s2)
+{
+ while (true)
+ {
+ unsigned char c1 = (unsigned char)*s1++;
+ unsigned char c2 = (unsigned char)*s2++;
+ if (c1 < c2) return -1;
+ if (c1 > c2) return 1;
+ if (c1 == 0) return 0;
+ }
+}
+
+int MyStringCompare(const wchar_t *s1, const wchar_t *s2)
+{
+ while (true)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ if (c1 < c2) return -1;
+ if (c1 > c2) return 1;
+ if (c1 == 0) return 0;
+ }
+}
+
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2)
+{
+ while (true)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ if (c1 != c2)
+ {
+ wchar_t u1 = MyCharUpper(c1);
+ wchar_t u2 = MyCharUpper(c2);
+ if (u1 < u2) return -1;
+ if (u1 > u2) return 1;
+ }
+ if (c1 == 0) return 0;
+ }
+}
+
+#ifdef _WIN32
+int MyStringCompareNoCase(const char *s1, const char *s2)
+{
+ return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
+}
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.h
new file mode 100644
index 00000000..72a2c741
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/String.h
@@ -0,0 +1,631 @@
+// Common/String.h
+
+#ifndef __COMMON_STRING_H
+#define __COMMON_STRING_H
+
+#include <string.h>
+// #include <wchar.h>
+
+#include "Vector.h"
+
+#ifdef _WIN32
+#include "MyWindows.h"
+#endif
+
+static const char *kTrimDefaultCharSet = " \n\t";
+
+template <class T>
+inline int MyStringLen(const T *s)
+{
+ int i;
+ for (i = 0; s[i] != '\0'; i++);
+ return i;
+}
+
+template <class T>
+inline T * MyStringCopy(T *dest, const T *src)
+{
+ T *destStart = dest;
+ while((*dest++ = *src++) != 0);
+ return destStart;
+}
+
+inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)
+ { return (p + 1); }
+inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)
+ { return (p + 1); }
+inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)
+ { return (p - 1); }
+inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)
+ { return (p - 1); }
+
+#ifdef _WIN32
+
+inline char* MyStringGetNextCharPointer(char *p)
+ { return CharNextA(p); }
+inline const char* MyStringGetNextCharPointer(const char *p)
+ { return CharNextA(p); }
+
+inline char* MyStringGetPrevCharPointer(char *base, char *p)
+ { return CharPrevA(base, p); }
+inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)
+ { return CharPrevA(base, p); }
+
+inline char MyCharUpper(char c)
+ { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); }
+#ifdef _UNICODE
+inline wchar_t MyCharUpper(wchar_t c)
+ { return (wchar_t)CharUpperW((LPWSTR)c); }
+#else
+wchar_t MyCharUpper(wchar_t c);
+#endif
+
+inline char MyCharLower(char c)
+ { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); }
+#ifdef _UNICODE
+inline wchar_t MyCharLower(wchar_t c)
+ { return (wchar_t)CharLowerW((LPWSTR)c); }
+#else
+wchar_t MyCharLower(wchar_t c);
+#endif
+
+inline char * MyStringUpper(char *s) { return CharUpperA(s); }
+#ifdef _UNICODE
+inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
+#else
+wchar_t * MyStringUpper(wchar_t *s);
+#endif
+
+inline char * MyStringLower(char *s) { return CharLowerA(s); }
+#ifdef _UNICODE
+inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
+#else
+wchar_t * MyStringLower(wchar_t *s);
+#endif
+
+#else // Standard-C
+wchar_t MyCharUpper(wchar_t c);
+#endif
+
+//////////////////////////////////////
+// Compare
+
+/*
+#ifndef _WIN32_WCE
+int MyStringCollate(const char *s1, const char *s2);
+int MyStringCollateNoCase(const char *s1, const char *s2);
+#endif
+int MyStringCollate(const wchar_t *s1, const wchar_t *s2);
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2);
+*/
+
+int MyStringCompare(const char *s1, const char *s2);
+int MyStringCompare(const wchar_t *s1, const wchar_t *s2);
+
+#ifdef _WIN32
+int MyStringCompareNoCase(const char *s1, const char *s2);
+#endif
+
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);
+
+template <class T>
+class CStringBase
+{
+ void TrimLeftWithCharSet(const CStringBase &charSet)
+ {
+ const T *p = _chars;
+ while (charSet.Find(*p) >= 0 && (*p != 0))
+ p = GetNextCharPointer(p);
+ Delete(0, (int)(p - _chars));
+ }
+ void TrimRightWithCharSet(const CStringBase &charSet)
+ {
+ const T *p = _chars;
+ const T *pLast = NULL;
+ while (*p != 0)
+ {
+ if (charSet.Find(*p) >= 0)
+ {
+ if (pLast == NULL)
+ pLast = p;
+ }
+ else
+ pLast = NULL;
+ p = GetNextCharPointer(p);
+ }
+ if(pLast != NULL)
+ {
+ int i = (int)(pLast - _chars);
+ Delete(i, _length - i);
+ }
+
+ }
+ void MoveItems(int destIndex, int srcIndex)
+ {
+ memmove(_chars + destIndex, _chars + srcIndex,
+ sizeof(T) * (_length - srcIndex + 1));
+ }
+
+ void InsertSpace(int &index, int size)
+ {
+ CorrectIndex(index);
+ GrowLength(size);
+ MoveItems(index + size, index);
+ }
+
+ static T *GetNextCharPointer(T *p)
+ { return MyStringGetNextCharPointer(p); }
+ static const T *GetNextCharPointer(const T *p)
+ { return MyStringGetNextCharPointer(p); }
+ static T *GetPrevCharPointer(T *base, T *p)
+ { return MyStringGetPrevCharPointer(base, p); }
+ static const T *GetPrevCharPointer(const T *base, const T *p)
+ { return MyStringGetPrevCharPointer(base, p); }
+protected:
+ T *_chars;
+ int _length;
+ int _capacity;
+
+ void SetCapacity(int newCapacity)
+ {
+ int realCapacity = newCapacity + 1;
+ if(realCapacity == _capacity)
+ return;
+ /*
+ const int kMaxStringSize = 0x20000000;
+ #ifndef _WIN32_WCE
+ if(newCapacity > kMaxStringSize || newCapacity < _length)
+ throw 1052337;
+ #endif
+ */
+ T *newBuffer = new T[realCapacity];
+ if(_capacity > 0)
+ {
+ for (int i = 0; i < (_length + 1); i++)
+ newBuffer[i] = _chars[i];
+ delete []_chars;
+ _chars = newBuffer;
+ }
+ else
+ {
+ _chars = newBuffer;
+ _chars[0] = 0;
+ }
+ _capacity = realCapacity;
+ }
+
+ void GrowLength(int n)
+ {
+ int freeSize = _capacity - _length - 1;
+ if (n <= freeSize)
+ return;
+ int delta;
+ if (_capacity > 64)
+ delta = _capacity / 2;
+ else if (_capacity > 8)
+ delta = 16;
+ else
+ delta = 4;
+ if (freeSize + delta < n)
+ delta = n - freeSize;
+ SetCapacity(_capacity + delta);
+ }
+
+ void CorrectIndex(int &index) const
+ {
+ if (index > _length)
+ index = _length;
+ }
+
+public:
+ CStringBase(): _chars(0), _length(0), _capacity(0)
+ { SetCapacity(16 - 1); }
+ CStringBase(T c): _chars(0), _length(0), _capacity(0)
+ {
+ SetCapacity(1);
+ _chars[0] = c;
+ _chars[1] = 0;
+ _length = 1;
+ }
+ CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)
+ {
+ int length = MyStringLen(chars);
+ SetCapacity(length);
+ MyStringCopy(_chars, chars); // can be optimized by memove()
+ _length = length;
+ }
+ CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0)
+ {
+ SetCapacity(s._length);
+ MyStringCopy(_chars, s._chars);
+ _length = s._length;
+ }
+ ~CStringBase() { delete []_chars; }
+
+ operator const T*() const { return _chars;}
+
+ // The minimum size of the character buffer in characters.
+ // This value does not include space for a null terminator.
+ T* GetBuffer(int minBufLength)
+ {
+ if(minBufLength >= _capacity)
+ SetCapacity(minBufLength + 1);
+ return _chars;
+ }
+ void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
+ void ReleaseBuffer(int newLength)
+ {
+ /*
+ #ifndef _WIN32_WCE
+ if(newLength >= _capacity)
+ throw 282217;
+ #endif
+ */
+ _chars[newLength] = 0;
+ _length = newLength;
+ }
+
+ CStringBase& operator=(T c)
+ {
+ Empty();
+ SetCapacity(1);
+ _chars[0] = c;
+ _chars[1] = 0;
+ _length = 1;
+ return *this;
+ }
+ CStringBase& operator=(const T *chars)
+ {
+ Empty();
+ int length = MyStringLen(chars);
+ SetCapacity(length);
+ MyStringCopy(_chars, chars);
+ _length = length;
+ return *this;
+ }
+ CStringBase& operator=(const CStringBase& s)
+ {
+ if(&s == this)
+ return *this;
+ Empty();
+ SetCapacity(s._length);
+ MyStringCopy(_chars, s._chars);
+ _length = s._length;
+ return *this;
+ }
+
+ CStringBase& operator+=(T c)
+ {
+ GrowLength(1);
+ _chars[_length] = c;
+ _chars[++_length] = 0;
+ return *this;
+ }
+ CStringBase& operator+=(const T *s)
+ {
+ int len = MyStringLen(s);
+ GrowLength(len);
+ MyStringCopy(_chars + _length, s);
+ _length += len;
+ return *this;
+ }
+ CStringBase& operator+=(const CStringBase &s)
+ {
+ GrowLength(s._length);
+ MyStringCopy(_chars + _length, s._chars);
+ _length += s._length;
+ return *this;
+ }
+ void Empty()
+ {
+ _length = 0;
+ _chars[0] = 0;
+ }
+ int Length() const { return _length; }
+ bool IsEmpty() const { return (_length == 0); }
+
+ CStringBase Mid(int startIndex) const
+ { return Mid(startIndex, _length - startIndex); }
+ CStringBase Mid(int startIndex, int count ) const
+ {
+ if (startIndex + count > _length)
+ count = _length - startIndex;
+
+ if (startIndex == 0 && startIndex + count == _length)
+ return *this;
+
+ CStringBase<T> result;
+ result.SetCapacity(count);
+ // MyStringNCopy(result._chars, _chars + startIndex, count);
+ for (int i = 0; i < count; i++)
+ result._chars[i] = _chars[startIndex + i];
+ result._chars[count] = 0;
+ result._length = count;
+ return result;
+ }
+ CStringBase Left(int count) const
+ { return Mid(0, count); }
+ CStringBase Right(int count) const
+ {
+ if (count > _length)
+ count = _length;
+ return Mid(_length - count, count);
+ }
+
+ void MakeUpper()
+ { MyStringUpper(_chars); }
+ void MakeLower()
+ { MyStringLower(_chars); }
+
+ int Compare(const CStringBase& s) const
+ { return MyStringCompare(_chars, s._chars); }
+
+ int CompareNoCase(const CStringBase& s) const
+ { return MyStringCompareNoCase(_chars, s._chars); }
+ /*
+ int Collate(const CStringBase& s) const
+ { return MyStringCollate(_chars, s._chars); }
+ int CollateNoCase(const CStringBase& s) const
+ { return MyStringCollateNoCase(_chars, s._chars); }
+ */
+
+ int Find(T c) const { return Find(c, 0); }
+ int Find(T c, int startIndex) const
+ {
+ T *p = _chars + startIndex;
+ while (true)
+ {
+ if (*p == c)
+ return (int)(p - _chars);
+ if (*p == 0)
+ return -1;
+ p = GetNextCharPointer(p);
+ }
+ }
+ int Find(const CStringBase &s) const { return Find(s, 0); }
+ int Find(const CStringBase &s, int startIndex) const
+ {
+ if (s.IsEmpty())
+ return startIndex;
+ for (; startIndex < _length; startIndex++)
+ {
+ int j;
+ for (j = 0; j < s._length && startIndex + j < _length; j++)
+ if (_chars[startIndex+j] != s._chars[j])
+ break;
+ if (j == s._length)
+ return startIndex;
+ }
+ return -1;
+ }
+ int ReverseFind(T c) const
+ {
+ if (_length == 0)
+ return -1;
+ T *p = _chars + _length - 1;
+ while (true)
+ {
+ if (*p == c)
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p = GetPrevCharPointer(_chars, p);
+ }
+ }
+ int FindOneOf(const CStringBase &s) const
+ {
+ for(int i = 0; i < _length; i++)
+ if (s.Find(_chars[i]) >= 0)
+ return i;
+ return -1;
+ }
+
+ void TrimLeft(T c)
+ {
+ const T *p = _chars;
+ while (c == *p)
+ p = GetNextCharPointer(p);
+ Delete(0, p - _chars);
+ }
+ private:
+ CStringBase GetTrimDefaultCharSet()
+ {
+ CStringBase<T> charSet;
+ for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) /
+ sizeof(kTrimDefaultCharSet[0])); i++)
+ charSet += (T)kTrimDefaultCharSet[i];
+ return charSet;
+ }
+ public:
+
+ void TrimLeft()
+ {
+ TrimLeftWithCharSet(GetTrimDefaultCharSet());
+ }
+ void TrimRight()
+ {
+ TrimRightWithCharSet(GetTrimDefaultCharSet());
+ }
+ void TrimRight(T c)
+ {
+ const T *p = _chars;
+ const T *pLast = NULL;
+ while (*p != 0)
+ {
+ if (*p == c)
+ {
+ if (pLast == NULL)
+ pLast = p;
+ }
+ else
+ pLast = NULL;
+ p = GetNextCharPointer(p);
+ }
+ if(pLast != NULL)
+ {
+ int i = pLast - _chars;
+ Delete(i, _length - i);
+ }
+ }
+ void Trim()
+ {
+ TrimRight();
+ TrimLeft();
+ }
+
+ int Insert(int index, T c)
+ {
+ InsertSpace(index, 1);
+ _chars[index] = c;
+ _length++;
+ return _length;
+ }
+ int Insert(int index, const CStringBase &s)
+ {
+ CorrectIndex(index);
+ if (s.IsEmpty())
+ return _length;
+ int numInsertChars = s.Length();
+ InsertSpace(index, numInsertChars);
+ for(int i = 0; i < numInsertChars; i++)
+ _chars[index + i] = s[i];
+ _length += numInsertChars;
+ return _length;
+ }
+
+ // !!!!!!!!!!!!!!! test it if newChar = '\0'
+ int Replace(T oldChar, T newChar)
+ {
+ if (oldChar == newChar)
+ return 0;
+ int number = 0;
+ int pos = 0;
+ while (pos < Length())
+ {
+ pos = Find(oldChar, pos);
+ if (pos < 0)
+ break;
+ _chars[pos] = newChar;
+ pos++;
+ number++;
+ }
+ return number;
+ }
+ int Replace(const CStringBase &oldString, const CStringBase &newString)
+ {
+ if (oldString.IsEmpty())
+ return 0;
+ if (oldString == newString)
+ return 0;
+ int oldStringLength = oldString.Length();
+ int newStringLength = newString.Length();
+ int number = 0;
+ int pos = 0;
+ while (pos < _length)
+ {
+ pos = Find(oldString, pos);
+ if (pos < 0)
+ break;
+ Delete(pos, oldStringLength);
+ Insert(pos, newString);
+ pos += newStringLength;
+ number++;
+ }
+ return number;
+ }
+ int Delete(int index, int count = 1 )
+ {
+ if (index + count > _length)
+ count = _length - index;
+ if (count > 0)
+ {
+ MoveItems(index, index + count);
+ _length -= count;
+ }
+ return _length;
+ }
+};
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)
+{
+ CStringBase<T> result(s1);
+ result += s2;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s, T c)
+{
+ CStringBase<T> result(s);
+ result += c;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(T c, const CStringBase<T>& s)
+{
+ CStringBase<T> result(c);
+ result += s;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)
+{
+ CStringBase<T> result(s);
+ result += chars;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)
+{
+ CStringBase<T> result(chars);
+ result += s;
+ return result;
+}
+
+template <class T>
+bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)
+ { return (s1.Compare(s2) == 0); }
+
+template <class T>
+bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)
+ { return (s1.Compare(s2) < 0); }
+
+template <class T>
+bool operator==(const T *s1, const CStringBase<T>& s2)
+ { return (s2.Compare(s1) == 0); }
+
+template <class T>
+bool operator==(const CStringBase<T>& s1, const T *s2)
+ { return (s1.Compare(s2) == 0); }
+
+template <class T>
+bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)
+ { return (s1.Compare(s2) != 0); }
+
+template <class T>
+bool operator!=(const T *s1, const CStringBase<T>& s2)
+ { return (s2.Compare(s1) != 0); }
+
+template <class T>
+bool operator!=(const CStringBase<T>& s1, const T *s2)
+ { return (s1.Compare(s2) != 0); }
+
+typedef CStringBase<char> AString;
+typedef CStringBase<wchar_t> UString;
+
+typedef CObjectVector<AString> AStringVector;
+typedef CObjectVector<UString> UStringVector;
+
+#ifdef _UNICODE
+ typedef UString CSysString;
+#else
+ typedef AString CSysString;
+#endif
+
+typedef CObjectVector<CSysString> CSysStringVector;
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.cpp
new file mode 100644
index 00000000..4b5913ad
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.cpp
@@ -0,0 +1,93 @@
+// Common/StringConvert.cpp
+
+#include "StdAfx.h"
+
+#include "StringConvert.h"
+
+#ifndef _WIN32
+#include <stdlib.h>
+#endif
+
+#ifdef _WIN32
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)
+{
+ UString resultString;
+ if(!srcString.IsEmpty())
+ {
+ int numChars = MultiByteToWideChar(codePage, 0, srcString,
+ srcString.Length(), resultString.GetBuffer(srcString.Length()),
+ srcString.Length() + 1);
+ #ifndef _WIN32_WCE
+ if(numChars == 0)
+ throw 282228;
+ #endif
+ resultString.ReleaseBuffer(numChars);
+ }
+ return resultString;
+}
+
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)
+{
+ AString resultString;
+ if(!srcString.IsEmpty())
+ {
+ int numRequiredBytes = srcString.Length() * 2;
+ int numChars = WideCharToMultiByte(codePage, 0, srcString,
+ srcString.Length(), resultString.GetBuffer(numRequiredBytes),
+ numRequiredBytes + 1, NULL, NULL);
+ #ifndef _WIN32_WCE
+ if(numChars == 0)
+ throw 282229;
+ #endif
+ resultString.ReleaseBuffer(numChars);
+ }
+ return resultString;
+}
+
+#ifndef _WIN32_WCE
+AString SystemStringToOemString(const CSysString &srcString)
+{
+ AString result;
+ CharToOem(srcString, result.GetBuffer(srcString.Length() * 2));
+ result.ReleaseBuffer();
+ return result;
+}
+#endif
+
+#else
+
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)
+{
+ UString resultString;
+ for (int i = 0; i < srcString.Length(); i++)
+ resultString += wchar_t(srcString[i]);
+ /*
+ if(!srcString.IsEmpty())
+ {
+ int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1);
+ if (numChars < 0) throw "Your environment does not support UNICODE";
+ resultString.ReleaseBuffer(numChars);
+ }
+ */
+ return resultString;
+}
+
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)
+{
+ AString resultString;
+ for (int i = 0; i < srcString.Length(); i++)
+ resultString += char(srcString[i]);
+ /*
+ if(!srcString.IsEmpty())
+ {
+ int numRequiredBytes = srcString.Length() * 6 + 1;
+ int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes);
+ if (numChars < 0) throw "Your environment does not support UNICODE";
+ resultString.ReleaseBuffer(numChars);
+ }
+ */
+ return resultString;
+}
+
+#endif
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.h
new file mode 100644
index 00000000..921e33c7
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringConvert.h
@@ -0,0 +1,71 @@
+// Common/StringConvert.h
+
+#ifndef __COMMON_STRINGCONVERT_H
+#define __COMMON_STRINGCONVERT_H
+
+#include "MyWindows.h"
+#include "Common/String.h"
+#include "Types.h"
+
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP);
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP);
+
+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString)
+ { return unicodeString; }
+inline const UString& GetUnicodeString(const UString &unicodeString)
+ { return unicodeString; }
+inline UString GetUnicodeString(const AString &ansiString)
+ { return MultiByteToUnicodeString(ansiString); }
+inline UString GetUnicodeString(const AString &multiByteString, UINT codePage)
+ { return MultiByteToUnicodeString(multiByteString, codePage); }
+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT)
+ { return unicodeString; }
+inline const UString& GetUnicodeString(const UString &unicodeString, UINT)
+ { return unicodeString; }
+
+inline const char* GetAnsiString(const char* ansiString)
+ { return ansiString; }
+inline const AString& GetAnsiString(const AString &ansiString)
+ { return ansiString; }
+inline AString GetAnsiString(const UString &unicodeString)
+ { return UnicodeStringToMultiByte(unicodeString); }
+
+inline const char* GetOemString(const char* oemString)
+ { return oemString; }
+inline const AString& GetOemString(const AString &oemString)
+ { return oemString; }
+inline AString GetOemString(const UString &unicodeString)
+ { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); }
+
+
+#ifdef _UNICODE
+ inline const wchar_t* GetSystemString(const wchar_t* unicodeString)
+ { return unicodeString;}
+ inline const UString& GetSystemString(const UString &unicodeString)
+ { return unicodeString;}
+ inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT codePage)
+ { return unicodeString;}
+ inline const UString& GetSystemString(const UString &unicodeString, UINT codePage)
+ { return unicodeString;}
+ inline UString GetSystemString(const AString &multiByteString, UINT codePage)
+ { return MultiByteToUnicodeString(multiByteString, codePage);}
+ inline UString GetSystemString(const AString &multiByteString)
+ { return MultiByteToUnicodeString(multiByteString);}
+#else
+ inline const char* GetSystemString(const char *ansiString)
+ { return ansiString; }
+ inline const AString& GetSystemString(const AString &multiByteString, UINT)
+ { return multiByteString; }
+ inline const char * GetSystemString(const char *multiByteString, UINT)
+ { return multiByteString; }
+ inline AString GetSystemString(const UString &unicodeString)
+ { return UnicodeStringToMultiByte(unicodeString); }
+ inline AString GetSystemString(const UString &unicodeString, UINT codePage)
+ { return UnicodeStringToMultiByte(unicodeString, codePage); }
+#endif
+
+#ifndef _WIN32_WCE
+AString SystemStringToOemString(const CSysString &srcString);
+#endif
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.cpp
new file mode 100644
index 00000000..18ecad5a
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.cpp
@@ -0,0 +1,68 @@
+// Common/StringToInt.cpp
+
+#include "StdAfx.h"
+
+#include "StringToInt.h"
+
+UInt64 ConvertStringToUInt64(const char *s, const char **end)
+{
+ UInt64 result = 0;
+ while(true)
+ {
+ char c = *s;
+ if (c < '0' || c > '9')
+ {
+ if (end != NULL)
+ *end = s;
+ return result;
+ }
+ result *= 10;
+ result += (c - '0');
+ s++;
+ }
+}
+
+UInt64 ConvertOctStringToUInt64(const char *s, const char **end)
+{
+ UInt64 result = 0;
+ while(true)
+ {
+ char c = *s;
+ if (c < '0' || c > '7')
+ {
+ if (end != NULL)
+ *end = s;
+ return result;
+ }
+ result <<= 3;
+ result += (c - '0');
+ s++;
+ }
+}
+
+
+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end)
+{
+ UInt64 result = 0;
+ while(true)
+ {
+ wchar_t c = *s;
+ if (c < '0' || c > '9')
+ {
+ if (end != NULL)
+ *end = s;
+ return result;
+ }
+ result *= 10;
+ result += (c - '0');
+ s++;
+ }
+}
+
+
+Int64 ConvertStringToInt64(const char *s, const char **end)
+{
+ if (*s == '-')
+ return -(Int64)ConvertStringToUInt64(s + 1, end);
+ return ConvertStringToUInt64(s, end);
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.h
new file mode 100644
index 00000000..d5614ef5
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/StringToInt.h
@@ -0,0 +1,17 @@
+// Common/StringToInt.h
+
+#ifndef __COMMON_STRINGTOINT_H
+#define __COMMON_STRINGTOINT_H
+
+#include <string.h>
+#include "Types.h"
+
+UInt64 ConvertStringToUInt64(const char *s, const char **end);
+UInt64 ConvertOctStringToUInt64(const char *s, const char **end);
+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end);
+
+Int64 ConvertStringToInt64(const char *s, const char **end);
+
+#endif
+
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Types.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Types.h
new file mode 100644
index 00000000..52d07081
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Types.h
@@ -0,0 +1,19 @@
+// Common/Types.h
+
+#ifndef __COMMON_TYPES_H
+#define __COMMON_TYPES_H
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+typedef int Int32;
+typedef unsigned int UInt32;
+#ifdef _MSC_VER
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.cpp
new file mode 100644
index 00000000..f74d4c6c
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.cpp
@@ -0,0 +1,74 @@
+// Common/Vector.cpp
+
+#include "StdAfx.h"
+
+#include <string.h>
+
+#include "Vector.h"
+
+CBaseRecordVector::~CBaseRecordVector()
+ { delete []((unsigned char *)_items); }
+void CBaseRecordVector::Clear()
+ { DeleteFrom(0); }
+void CBaseRecordVector::DeleteBack()
+ { Delete(_size - 1); }
+void CBaseRecordVector::DeleteFrom(int index)
+ { Delete(index, _size - index); }
+
+void CBaseRecordVector::ReserveOnePosition()
+{
+ if(_size != _capacity)
+ return;
+ int delta;
+ if (_capacity > 64)
+ delta = _capacity / 2;
+ else if (_capacity > 8)
+ delta = 8;
+ else
+ delta = 4;
+ Reserve(_capacity + delta);
+}
+
+void CBaseRecordVector::Reserve(int newCapacity)
+{
+ if(newCapacity <= _capacity)
+ return;
+ /*
+ #ifndef _DEBUG
+ static const unsigned int kMaxVectorSize = 0xF0000000;
+ if(newCapacity < _size ||
+ ((unsigned int )newCapacity * (unsigned int )_itemSize) > kMaxVectorSize)
+ throw 1052354;
+ #endif
+ */
+ unsigned char *p = new unsigned char[newCapacity * _itemSize];
+ int numRecordsToMove = _capacity;
+ memmove(p, _items, _itemSize * numRecordsToMove);
+ delete [](unsigned char *)_items;
+ _items = p;
+ _capacity = newCapacity;
+}
+
+void CBaseRecordVector::MoveItems(int destIndex, int srcIndex)
+{
+ memmove(((unsigned char *)_items) + destIndex * _itemSize,
+ ((unsigned char *)_items) + srcIndex * _itemSize,
+ _itemSize * (_size - srcIndex));
+}
+
+void CBaseRecordVector::InsertOneItem(int index)
+{
+ ReserveOnePosition();
+ MoveItems(index + 1, index);
+ _size++;
+}
+
+void CBaseRecordVector::Delete(int index, int num)
+{
+ TestIndexAndCorrectNum(index, num);
+ if (num > 0)
+ {
+ MoveItems(index, index + num);
+ _size -= num;
+ }
+}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.h
new file mode 100644
index 00000000..0c7292a1
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Common/Vector.h
@@ -0,0 +1,211 @@
+// Common/Vector.h
+
+#ifndef __COMMON_VECTOR_H
+#define __COMMON_VECTOR_H
+
+#include "Defs.h"
+
+class CBaseRecordVector
+{
+ void MoveItems(int destIndex, int srcIndex);
+protected:
+ int _capacity;
+ int _size;
+ void *_items;
+ size_t _itemSize;
+
+ void ReserveOnePosition();
+ void InsertOneItem(int index);
+ void TestIndexAndCorrectNum(int index, int &num) const
+ { if (index + num > _size) num = _size - index; }
+public:
+ CBaseRecordVector(size_t itemSize):
+ _capacity(0), _size(0), _items(0), _itemSize(itemSize) {}
+ virtual ~CBaseRecordVector();
+ int Size() const { return _size; }
+ bool IsEmpty() const { return (_size == 0); }
+ void Reserve(int newCapacity);
+ virtual void Delete(int index, int num = 1);
+ void Clear();
+ void DeleteFrom(int index);
+ void DeleteBack();
+};
+
+template <class T>
+class CRecordVector: public CBaseRecordVector
+{
+public:
+ CRecordVector():CBaseRecordVector(sizeof(T)){};
+ CRecordVector(const CRecordVector &v):
+ CBaseRecordVector(sizeof(T)) { *this = v;}
+ CRecordVector& operator=(const CRecordVector &v)
+ {
+ Clear();
+ return (*this += v);
+ }
+ CRecordVector& operator+=(const CRecordVector &v)
+ {
+ int size = v.Size();
+ Reserve(Size() + size);
+ for(int i = 0; i < size; i++)
+ Add(v[i]);
+ return *this;
+ }
+ int Add(T item)
+ {
+ ReserveOnePosition();
+ ((T *)_items)[_size] = item;
+ return _size++;
+ }
+ void Insert(int index, T item)
+ {
+ InsertOneItem(index);
+ ((T *)_items)[index] = item;
+ }
+ // T* GetPointer() const { return (T*)_items; }
+ // operator const T *() const { return _items; };
+ const T& operator[](int index) const { return ((T *)_items)[index]; }
+ T& operator[](int index) { return ((T *)_items)[index]; }
+ const T& Front() const { return operator[](0); }
+ T& Front() { return operator[](0); }
+ const T& Back() const { return operator[](_size - 1); }
+ T& Back() { return operator[](_size - 1); }
+
+ void Swap(int i, int j)
+ {
+ T temp = operator[](i);
+ operator[](i) = operator[](j);
+ operator[](j) = temp;
+ }
+
+ void Sort(int left, int right)
+ {
+ if (right - left < 2)
+ return;
+ Swap(left, (left + right) / 2);
+ int last = left;
+ for (int i = left; i < right; i++)
+ if (operator[](i) < operator[](left))
+ Swap(++last, i);
+ Swap(left, last);
+ Sort(left, last);
+ Sort(last + 1, right);
+ }
+ void Sort() { Sort(0, Size()); }
+ void Sort(int left, int right, int (*compare)(const T*, const T*, void *), void *param)
+ {
+ if (right - left < 2)
+ return;
+ Swap(left, (left + right) / 2);
+ int last = left;
+ for (int i = left; i < right; i++)
+ if (compare(&operator[](i), &operator[](left), param) < 0)
+ Swap(++last, i);
+ Swap(left, last);
+ Sort(left, last, compare, param);
+ Sort(last + 1, right, compare, param);
+ }
+
+ void Sort(int (*compare)(const T*, const T*, void *), void *param)
+ {
+ Sort(0, Size(), compare, param);
+ }
+};
+
+typedef CRecordVector<int> CIntVector;
+typedef CRecordVector<unsigned int> CUIntVector;
+typedef CRecordVector<bool> CBoolVector;
+typedef CRecordVector<unsigned char> CByteVector;
+typedef CRecordVector<void *> CPointerVector;
+
+template <class T>
+class CObjectVector: public CPointerVector
+{
+public:
+ CObjectVector(){};
+ ~CObjectVector() { Clear(); }
+ CObjectVector(const CObjectVector &objectVector)
+ { *this = objectVector; }
+ CObjectVector& operator=(const CObjectVector &objectVector)
+ {
+ Clear();
+ return (*this += objectVector);
+ }
+ CObjectVector& operator+=(const CObjectVector &objectVector)
+ {
+ int size = objectVector.Size();
+ Reserve(Size() + size);
+ for(int i = 0; i < size; i++)
+ Add(objectVector[i]);
+ return *this;
+ }
+ const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); }
+ T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); }
+ T& Front() { return operator[](0); }
+ const T& Front() const { return operator[](0); }
+ T& Back() { return operator[](_size - 1); }
+ const T& Back() const { return operator[](_size - 1); }
+ int Add(const T& item)
+ { return CPointerVector::Add(new T(item)); }
+ void Insert(int index, const T& item)
+ { CPointerVector::Insert(index, new T(item)); }
+ virtual void Delete(int index, int num = 1)
+ {
+ TestIndexAndCorrectNum(index, num);
+ for(int i = 0; i < num; i++)
+ delete (T *)(((void **)_items)[index + i]);
+ CPointerVector::Delete(index, num);
+ }
+ int Find(const T& item) const
+ {
+ for(int i = 0; i < Size(); i++)
+ if (item == (*this)[i])
+ return i;
+ return -1;
+ }
+ int FindInSorted(const T& item) const
+ {
+ int left = 0, right = Size();
+ while (left != right)
+ {
+ int mid = (left + right) / 2;
+ const T& midValue = (*this)[mid];
+ if (item == midValue)
+ return mid;
+ if (item < midValue)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ return -1;
+ }
+ int AddToSorted(const T& item)
+ {
+ int left = 0, right = Size();
+ while (left != right)
+ {
+ int mid = (left + right) / 2;
+ const T& midValue = (*this)[mid];
+ if (item == midValue)
+ {
+ right = mid + 1;
+ break;
+ }
+ if (item < midValue)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ Insert(right, item);
+ return right;
+ }
+
+ void Sort(int (*compare)(void *const *, void *const *, void *), void *param)
+ { CPointerVector::Sort(compare, param); }
+
+ static int CompareObjectItems(void *const *a1, void *const *a2, void *param)
+ { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); }
+ void Sort() { CPointerVector::Sort(CompareObjectItems, 0); }
+};
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/Defs.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/Defs.h
new file mode 100644
index 00000000..1b0c97a5
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/Defs.h
@@ -0,0 +1,18 @@
+// Windows/Defs.h
+
+#ifndef __WINDOWS_DEFS_H
+#define __WINDOWS_DEFS_H
+
+inline bool BOOLToBool(BOOL value)
+ { return (value != FALSE); }
+
+inline BOOL BoolToBOOL(bool value)
+ { return (value ? TRUE: FALSE); }
+
+inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value)
+ { return (value ? VARIANT_TRUE: VARIANT_FALSE); }
+
+inline bool VARIANT_BOOLToBool(VARIANT_BOOL value)
+ { return (value != VARIANT_FALSE); }
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.cpp b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.cpp
new file mode 100644
index 00000000..20b5fc15
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.cpp
@@ -0,0 +1,245 @@
+// Windows/FileIO.cpp
+
+#include "StdAfx.h"
+
+#include "FileIO.h"
+#include "Defs.h"
+#ifndef _UNICODE
+#include "../Common/StringConvert.h"
+#endif
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+namespace NWindows {
+namespace NFile {
+namespace NIO {
+
+CFileBase::~CFileBase() { Close(); }
+
+bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess,
+ DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+{
+ Close();
+ _handle = ::CreateFile(fileName, desiredAccess, shareMode,
+ (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,
+ flagsAndAttributes, (HANDLE) NULL);
+ return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE));
+}
+
+#ifndef _UNICODE
+bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess,
+ DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+{
+ if (g_IsNT)
+ {
+ Close();
+ _handle = ::CreateFileW(fileName, desiredAccess, shareMode,
+ (LPSECURITY_ATTRIBUTES)NULL, creationDisposition,
+ flagsAndAttributes, (HANDLE) NULL);
+ return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE));
+ }
+ return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP),
+ desiredAccess, shareMode, creationDisposition, flagsAndAttributes);
+}
+#endif
+
+bool CFileBase::Close()
+{
+ if(!_fileIsOpen)
+ return true;
+ bool result = BOOLToBool(::CloseHandle(_handle));
+ _fileIsOpen = !result;
+ return result;
+}
+
+bool CFileBase::GetPosition(UInt64 &position) const
+{
+ return Seek(0, FILE_CURRENT, position);
+}
+
+bool CFileBase::GetLength(UInt64 &length) const
+{
+ DWORD sizeHigh;
+ DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh);
+ if(sizeLow == 0xFFFFFFFF)
+ if(::GetLastError() != NO_ERROR)
+ return false;
+ length = (((UInt64)sizeHigh) << 32) + sizeLow;
+ return true;
+}
+
+bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const
+{
+ LARGE_INTEGER value;
+ value.QuadPart = distanceToMove;
+ value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod);
+ if (value.LowPart == 0xFFFFFFFF)
+ if(::GetLastError() != NO_ERROR)
+ return false;
+ newPosition = value.QuadPart;
+ return true;
+}
+
+bool CFileBase::Seek(UInt64 position, UInt64 &newPosition)
+{
+ return Seek(position, FILE_BEGIN, newPosition);
+}
+
+bool CFileBase::SeekToBegin()
+{
+ UInt64 newPosition;
+ return Seek(0, newPosition);
+}
+
+bool CFileBase::SeekToEnd(UInt64 &newPosition)
+{
+ return Seek(0, FILE_END, newPosition);
+}
+
+bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const
+{
+ BY_HANDLE_FILE_INFORMATION winFileInfo;
+ if(!::GetFileInformationByHandle(_handle, &winFileInfo))
+ return false;
+ fileInfo.Attributes = winFileInfo.dwFileAttributes;
+ fileInfo.CreationTime = winFileInfo.ftCreationTime;
+ fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime;
+ fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime;
+ fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes;
+ fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow;
+ fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks;
+ fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow;
+ return true;
+}
+
+/////////////////////////
+// CInFile
+
+bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+ { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); }
+
+bool CInFile::Open(LPCTSTR fileName)
+ { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }
+
+#ifndef _UNICODE
+bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+ { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); }
+
+bool CInFile::Open(LPCWSTR fileName)
+ { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }
+#endif
+
+// ReadFile and WriteFile functions in Windows have BUG:
+// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
+// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
+// (Insufficient system resources exist to complete the requested service).
+
+static UInt32 kChunkSizeMax = (1 << 24);
+
+bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize)
+{
+ if (size > kChunkSizeMax)
+ size = kChunkSizeMax;
+ DWORD processedLoc = 0;
+ bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));
+ processedSize = (UInt32)processedLoc;
+ return res;
+}
+
+bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize)
+{
+ processedSize = 0;
+ do
+ {
+ UInt32 processedLoc = 0;
+ bool res = ReadPart(data, size, processedLoc);
+ processedSize += processedLoc;
+ if (!res)
+ return false;
+ if (processedLoc == 0)
+ return true;
+ data = (void *)((unsigned char *)data + processedLoc);
+ size -= processedLoc;
+ }
+ while (size > 0);
+ return true;
+}
+
+/////////////////////////
+// COutFile
+
+bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+ { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }
+
+static inline DWORD GetCreationDisposition(bool createAlways)
+ { return createAlways? CREATE_ALWAYS: CREATE_NEW; }
+
+bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition)
+ { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }
+
+bool COutFile::Create(LPCTSTR fileName, bool createAlways)
+ { return Open(fileName, GetCreationDisposition(createAlways)); }
+
+#ifndef _UNICODE
+
+bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+ { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }
+
+bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition)
+ { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }
+
+bool COutFile::Create(LPCWSTR fileName, bool createAlways)
+ { return Open(fileName, GetCreationDisposition(createAlways)); }
+
+#endif
+
+bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime)
+ { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); }
+
+bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime)
+ { return SetTime(NULL, NULL, lastWriteTime); }
+
+bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize)
+{
+ if (size > kChunkSizeMax)
+ size = kChunkSizeMax;
+ DWORD processedLoc = 0;
+ bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL));
+ processedSize = (UInt32)processedLoc;
+ return res;
+}
+
+bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize)
+{
+ processedSize = 0;
+ do
+ {
+ UInt32 processedLoc = 0;
+ bool res = WritePart(data, size, processedLoc);
+ processedSize += processedLoc;
+ if (!res)
+ return false;
+ if (processedLoc == 0)
+ return true;
+ data = (const void *)((const unsigned char *)data + processedLoc);
+ size -= processedLoc;
+ }
+ while (size > 0);
+ return true;
+}
+
+bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); }
+
+bool COutFile::SetLength(UInt64 length)
+{
+ UInt64 newPosition;
+ if(!Seek(length, newPosition))
+ return false;
+ if(newPosition != length)
+ return false;
+ return SetEndOfFile();
+}
+
+}}}
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.h
new file mode 100644
index 00000000..de66d7f3
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/FileIO.h
@@ -0,0 +1,98 @@
+// Windows/FileIO.h
+
+#ifndef __WINDOWS_FILEIO_H
+#define __WINDOWS_FILEIO_H
+
+#include "../Common/Types.h"
+
+namespace NWindows {
+namespace NFile {
+namespace NIO {
+
+struct CByHandleFileInfo
+{
+ DWORD Attributes;
+ FILETIME CreationTime;
+ FILETIME LastAccessTime;
+ FILETIME LastWriteTime;
+ DWORD VolumeSerialNumber;
+ UInt64 Size;
+ DWORD NumberOfLinks;
+ UInt64 FileIndex;
+};
+
+class CFileBase
+{
+protected:
+ bool _fileIsOpen;
+ HANDLE _handle;
+ bool Create(LPCTSTR fileName, DWORD desiredAccess,
+ DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+ #ifndef _UNICODE
+ bool Create(LPCWSTR fileName, DWORD desiredAccess,
+ DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+ #endif
+
+public:
+ CFileBase(): _fileIsOpen(false){};
+ virtual ~CFileBase();
+
+ virtual bool Close();
+
+ bool GetPosition(UInt64 &position) const;
+ bool GetLength(UInt64 &length) const;
+
+ bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const;
+ bool Seek(UInt64 position, UInt64 &newPosition);
+ bool SeekToBegin();
+ bool SeekToEnd(UInt64 &newPosition);
+
+ bool GetFileInformation(CByHandleFileInfo &fileInfo) const;
+};
+
+class CInFile: public CFileBase
+{
+public:
+ bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+ bool Open(LPCTSTR fileName);
+ #ifndef _UNICODE
+ bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+ bool Open(LPCWSTR fileName);
+ #endif
+ bool ReadPart(void *data, UInt32 size, UInt32 &processedSize);
+ bool Read(void *data, UInt32 size, UInt32 &processedSize);
+};
+
+class COutFile: public CFileBase
+{
+ // DWORD m_CreationDisposition;
+public:
+ // COutFile(): m_CreationDisposition(CREATE_NEW){};
+ bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+ bool Open(LPCTSTR fileName, DWORD creationDisposition);
+ bool Create(LPCTSTR fileName, bool createAlways);
+
+ #ifndef _UNICODE
+ bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+ bool Open(LPCWSTR fileName, DWORD creationDisposition);
+ bool Create(LPCWSTR fileName, bool createAlways);
+ #endif
+
+ /*
+ void SetOpenCreationDisposition(DWORD creationDisposition)
+ { m_CreationDisposition = creationDisposition; }
+ void SetOpenCreationDispositionCreateAlways()
+ { m_CreationDisposition = CREATE_ALWAYS; }
+ */
+
+ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime);
+ bool SetLastWriteTime(const FILETIME *lastWriteTime);
+ bool WritePart(const void *data, UInt32 size, UInt32 &processedSize);
+ bool Write(const void *data, UInt32 size, UInt32 &processedSize);
+ bool SetEndOfFile();
+ bool SetLength(UInt64 length);
+};
+
+}}}
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/StdAfx.h b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/StdAfx.h
new file mode 100644
index 00000000..e0f76050
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/C/Windows/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../Common/MyWindows.h"
+#include "../Common/NewHandler.h"
+
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/CPL.html b/release/src/linux/linux/scripts/squashfs/lzma/CPL.html
new file mode 100644
index 00000000..f1d3be11
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/CPL.html
@@ -0,0 +1,224 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML><HEAD><TITLE>Common Public License - v 1.0</TITLE>
+<META http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+<BODY vLink=#800000 bgColor=#ffffff>
+<P align=center><B>Common Public License - v 1.0</B>
+<P><B></B><FONT size=3></FONT>
+<P><FONT size=3></FONT><FONT size=2>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
+THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2><B>1. DEFINITIONS</B></FONT>
+<P><FONT size=2>"Contribution" means:</FONT>
+<UL><FONT size=2>a) in the case of the initial Contributor, the initial code
+ and documentation distributed under this Agreement, and<BR clear=left>b) in
+ the case of each subsequent Contributor:</FONT></UL>
+<UL><FONT size=2>i) changes to the Program, and</FONT></UL>
+<UL><FONT size=2>ii) additions to the Program;</FONT></UL>
+<UL><FONT size=2>where such changes and/or additions to the Program originate
+ from and are distributed by that particular Contributor. </FONT><FONT size=2>A
+ Contribution 'originates' from a Contributor if it was added to the Program by
+ such Contributor itself or anyone acting on such Contributor's behalf.
+ </FONT><FONT size=2>Contributions do not include additions to the Program
+ which: (i) are separate modules of software distributed in conjunction with
+ the Program under their own license agreement, and (ii) are not derivative
+ works of the Program. </FONT></UL>
+<P><FONT size=2></FONT>
+<P><FONT size=2>"Contributor" means any person or entity that distributes the
+Program.</FONT>
+<P><FONT size=2></FONT><FONT size=2></FONT>
+<P><FONT size=2>"Licensed Patents " mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program. </FONT>
+<P><FONT size=2></FONT><FONT size=2></FONT>
+<P><FONT size=2></FONT><FONT size=2>"Program" means the Contributions
+distributed in accordance with this Agreement.</FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2>"Recipient" means anyone who receives the Program under this
+Agreement, including all Contributors.</FONT>
+<P><FONT size=2><B></B></FONT>
+<P><FONT size=2><B>2. GRANT OF RIGHTS</B></FONT>
+<UL><FONT size=2></FONT><FONT size=2>a) </FONT><FONT size=2>Subject to the
+ terms of this Agreement, each Contributor hereby grants</FONT><FONT size=2>
+ Recipient a non-exclusive, worldwide, royalty-free copyright license
+ to</FONT><FONT color=#ff0000 size=2> </FONT><FONT size=2>reproduce, prepare
+ derivative works of, publicly display, publicly perform, distribute and
+ sublicense the Contribution of such Contributor, if any, and such derivative
+ works, in source code and object code form.</FONT></UL>
+<UL><FONT size=2></FONT></UL>
+<UL><FONT size=2></FONT><FONT size=2>b) Subject to the terms of this
+ Agreement, each Contributor hereby grants </FONT><FONT size=2>Recipient a
+ non-exclusive, worldwide,</FONT><FONT color=#008000 size=2> </FONT><FONT
+ size=2>royalty-free patent license under Licensed Patents to make, use, sell,
+ offer to sell, import and otherwise transfer the Contribution of such
+ Contributor, if any, in source code and object code form. This patent license
+ shall apply to the combination of the Contribution and the Program if, at the
+ time the Contribution is added by the Contributor, such addition of the
+ Contribution causes such combination to be covered by the Licensed Patents.
+ The patent license shall not apply to any other combinations which include the
+ Contribution. No hardware per se is licensed hereunder. </FONT></UL>
+<UL><FONT size=2></FONT></UL>
+<UL><FONT size=2>c) Recipient understands that although each Contributor
+ grants the licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the patent or
+ other intellectual property rights of any other entity. Each Contributor
+ disclaims any liability to Recipient for claims brought by any other entity
+ based on infringement of intellectual property rights or otherwise. As a
+ condition to exercising the rights and licenses granted hereunder, each
+ Recipient hereby assumes sole responsibility to secure any other intellectual
+ property rights needed, if any. For example, if a third party patent license
+ is required to allow Recipient to distribute the Program, it is Recipient's
+ responsibility to acquire that license before distributing the
+Program.</FONT></UL>
+<UL><FONT size=2></FONT></UL>
+<UL><FONT size=2>d) Each Contributor represents that to its knowledge it has
+ sufficient copyright rights in its Contribution, if any, to grant the
+ copyright license set forth in this Agreement. </FONT></UL>
+<UL><FONT size=2></FONT></UL>
+<P><FONT size=2><B>3. REQUIREMENTS</B></FONT>
+<P><FONT size=2><B></B>A Contributor may choose to distribute the Program in
+object code form under its own license agreement, provided that:</FONT>
+<UL><FONT size=2>a) it complies with the terms and conditions of this
+ Agreement; and</FONT></UL>
+<UL><FONT size=2>b) its license agreement:</FONT></UL>
+<UL><FONT size=2>i) effectively disclaims</FONT><FONT size=2> on behalf of all
+ Contributors all warranties and conditions, express and implied, including
+ warranties or conditions of title and non-infringement, and implied warranties
+ or conditions of merchantability and fitness for a particular purpose;
+</FONT></UL>
+<UL><FONT size=2>ii) effectively excludes on behalf of all Contributors all
+ liability for damages, including direct, indirect, special, incidental and
+ consequential damages, such as lost profits; </FONT></UL>
+<UL><FONT size=2>iii)</FONT><FONT size=2> states that any provisions which
+ differ from this Agreement are offered by that Contributor alone and not by
+ any other party; and</FONT></UL>
+<UL><FONT size=2>iv) states that source code for the Program is available from
+ such Contributor, and informs licensees how to obtain it in a reasonable
+ manner on or through a medium customarily used for software
+ exchange.</FONT><FONT color=#0000ff size=2> </FONT><FONT color=#ff0000
+ size=2></FONT></UL>
+<UL><FONT color=#ff0000 size=2></FONT><FONT size=2></FONT></UL>
+<P><FONT size=2>When the Program is made available in source code form:</FONT>
+<UL><FONT size=2>a) it must be made available under this Agreement; and
+</FONT></UL>
+<UL><FONT size=2>b) a copy of this Agreement must be included with each copy
+ of the Program. </FONT></UL>
+<P><FONT size=2></FONT><FONT color=#0000ff size=2><STRIKE></STRIKE></FONT>
+<P><FONT color=#0000ff size=2><STRIKE></STRIKE></FONT><FONT size=2>Contributors
+may not remove or alter any copyright notices contained within the Program.
+</FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent Recipients
+to identify the originator of the Contribution. </FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2><B>4. COMMERCIAL DISTRIBUTION</B></FONT>
+<P><FONT size=2>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the like.
+While this license is intended to facilitate the commercial use of the Program,
+the Contributor who includes the Program in a commercial product offering should
+do so in a manner which does not create potential liability for other
+Contributors. Therefore, if a Contributor includes the Program in a commercial
+product offering, such Contributor ("Commercial Contributor") hereby agrees to
+defend and indemnify every other Contributor ("Indemnified Contributor") against
+any losses, damages and costs (collectively "Losses") arising from claims,
+lawsuits and other legal actions brought by a third party against the
+Indemnified Contributor to the extent caused by the acts or omissions of such
+Commercial Contributor in connection with its distribution of the Program in a
+commercial product offering. The obligations in this section do not apply to any
+claims or Losses relating to any actual or alleged intellectual property
+infringement. In order to qualify, an Indemnified Contributor must: a) promptly
+notify the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial Contributor
+in, the defense and any related settlement negotiations. The Indemnified
+Contributor may participate in any such claim at its own expense.</FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2>For example, a Contributor might include the Program in a
+commercial product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance claims, or
+offers warranties related to Product X, those performance claims and warranties
+are such Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.</FONT>
+<P><FONT size=2></FONT><FONT color=#0000ff size=2></FONT>
+<P><FONT color=#0000ff size=2></FONT><FONT size=2><B>5. NO WARRANTY</B></FONT>
+<P><FONT size=2>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
+CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE. Each Recipient is</FONT><FONT size=2> solely responsible for
+determining the appropriateness of using and distributing </FONT><FONT
+size=2>the Program</FONT><FONT size=2> and assumes all risks associated with its
+exercise of rights under this Agreement</FONT><FONT size=2>, including but not
+limited to the risks and costs of program errors, compliance with applicable
+laws, damage to or loss of data, </FONT><FONT size=2>programs or equipment, and
+unavailability or interruption of operations</FONT><FONT size=2>. </FONT><FONT
+size=2></FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2></FONT><FONT size=2><B>6. DISCLAIMER OF LIABILITY</B></FONT>
+<P><FONT size=2></FONT><FONT size=2>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+</FONT><FONT size=2>(INCLUDING WITHOUT LIMITATION LOST PROFITS),</FONT><FONT
+size=2> 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</FONT>
+<P><FONT size=2></FONT><FONT size=2></FONT>
+<P><FONT size=2><B>7. GENERAL</B></FONT>
+<P><FONT size=2></FONT><FONT size=2>If any provision of this Agreement is
+invalid or unenforceable under applicable law, it shall not affect the validity
+or enforceability of the remainder of the terms of this Agreement, and without
+further action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.</FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2>If Recipient institutes patent litigation against a Contributor
+with respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that Contributor
+to such Recipient under this Agreement shall terminate as of the date such
+litigation is filed. In addition, if Recipient institutes patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Program itself (excluding combinations of the Program with
+other software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the date
+such litigation is filed. </FONT><FONT size=2></FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2>All Recipient's rights under this Agreement shall terminate if
+it fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time after
+becoming aware of such noncompliance. If all Recipient's rights under this
+Agreement terminate, Recipient agrees to cease use and distribution of the
+Program as soon as reasonably practicable. However, Recipient's obligations
+under this Agreement and any licenses granted by Recipient relating to the
+Program shall continue and survive. </FONT><FONT size=2></FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2></FONT><FONT size=2>Everyone is permitted to copy and distribute
+copies of this Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The Agreement
+Steward reserves the right to </FONT><FONT size=2>publish new versions
+(including revisions) of this Agreement from time to </FONT><FONT size=2>time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+IBM is the initial Agreement Steward. IBM may assign the responsibility to serve
+as the Agreement Steward to a suitable separate entity. </FONT><FONT size=2>Each
+new version of the Agreement will be given a distinguishing version number. The
+Program (including Contributions) may always be distributed subject to the
+version of the Agreement under which it was received. In addition, after a new
+version of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new </FONT><FONT size=2>version.
+</FONT><FONT size=2>Except as expressly stated in Sections 2(a) and 2(b) above,
+Recipient receives no rights or licenses to the intellectual property of any
+Contributor under this Agreement, whether expressly, </FONT><FONT size=2>by
+implication, estoppel or otherwise</FONT><FONT size=2>.</FONT><FONT size=2> All
+rights in the Program not expressly granted under this Agreement are
+reserved.</FONT>
+<P><FONT size=2></FONT>
+<P><FONT size=2>This Agreement is governed by the laws of the State of New York
+and the intellectual property laws of the United States of America. No party to
+this Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.</FONT>
+<P><FONT size=2></FONT><FONT size=2></FONT>
+<P><FONT size=2></FONT></P></BODY></HTML>
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/LGPL.txt b/release/src/linux/linux/scripts/squashfs/lzma/LGPL.txt
new file mode 100644
index 00000000..f3926a61
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/LGPL.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. 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.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/Methods.txt b/release/src/linux/linux/scripts/squashfs/lzma/Methods.txt
new file mode 100644
index 00000000..5d1661e4
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/Methods.txt
@@ -0,0 +1,114 @@
+Compression method IDs (4.27)
+-----------------------------
+
+Each compression method in 7z has unique binary value (ID).
+The length of ID in bytes is arbitrary but it can not exceed 15 bytes.
+
+List of defined IDs
+-------------------
+
+00 - Copy
+01 - Reserved
+02 - Common
+ 03 Swap
+ - 2 Swap2
+ - 4 Swap4
+ 04 Delta (subject to change)
+
+03 - 7z
+ 01 - LZMA
+ 01 - Version
+
+ 03 - Branch
+ 01 - x86
+ 03 - BCJ
+ 1B - BCJ2
+ 02 - PPC
+ 05 - BC_PPC_B (Big Endian)
+ 03 - Alpha
+ 01 - BC_Alpha
+ 04 - IA64
+ 01 - BC_IA64
+ 05 - ARM
+ 01 - BC_ARM
+ 06 - M68
+ 05 - BC_M68_B (Big Endian)
+ 07 - ARM Thumb
+ 01 - BC_ARMThumb
+ 08 - SPARC
+ 05 - BC_SPARC
+
+ 04 - PPMD
+ 01 - Version
+
+04 - Misc
+ 00 - Reserved
+ 01 - Zip
+ 00 - Copy (not used). Use {00} instead
+ 01 - Shrink
+ 06 - Implode
+ 08 - Deflate
+ 09 - Deflate64
+ 12 - BZip2 (not used). Use {04 02 02} instead
+ 02 - BZip
+ 02 - BZip2
+ 03 - Rar
+ 01 - Rar15
+ 02 - Rar20
+ 03 - Rar29
+ 04 - Arj
+ 01 - Arj (1,2,3)
+ 02 - Arj 4
+ 05 - Z
+ 06 - Lzh
+ 07 - Reserved for 7z
+ 08 - Cab
+
+
+06 - Crypto
+ 00 -
+ 01 - AES
+ 0x - AES-128
+ 4x - AES-192
+ 8x - AES-256
+
+ x0 - ECB
+ x1 - CBC
+ x2 - CFB
+ x3 - OFB
+
+ 07 - Reserved
+ 0F - Reserved
+
+ F0 - Misc Ciphers (Real Ciphers without hashing algo)
+
+ F1 - Misc Ciphers (Combine)
+ 01 - Zip
+ 01 - Main Zip crypto algo
+ 03 - RAR
+ 02 -
+ 03 - Rar29 AES-128 + (modified SHA-1)
+ 07 - 7z
+ 01 - AES-256 + SHA-256
+
+07 - Hash (subject to change)
+ 00 -
+ 01 - CRC
+ 02 - SHA-1
+ 03 - SHA-256
+ 04 - SHA-384
+ 05 - SHA-512
+
+ F0 - Misc Hash
+
+ F1 - Misc
+ 03 - RAR
+ 03 - Rar29 Password Hashing (modified SHA1)
+ 07 - 7z
+ 01 - SHA-256 Password Hashing
+
+
+
+
+---
+End of document
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/history.txt b/release/src/linux/linux/scripts/squashfs/lzma/history.txt
new file mode 100644
index 00000000..167fdf1e
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/history.txt
@@ -0,0 +1,147 @@
+HISTORY of the LZMA SDK
+-----------------------
+
+ Version 4.32 2005-12-09
+ --------------------------------------
+ - Java version of LZMA SDK was included
+
+
+ Version 4.30 2005-11-20
+ --------------------------------------
+ - Compression ratio was improved in -a2 mode
+ - Speed optimizations for compressing in -a2 mode
+ - -fb switch now supports values up to 273
+ - Bug in 7z_C (7zIn.c) was fixed:
+ It used Alloc/Free functions from different memory pools.
+ So if program used two memory pools, it worked incorrectly.
+ - 7z_C: .7z format supporting was improved
+ - LZMA# SDK (C#.NET version) was included
+
+
+ Version 4.27 (Updated) 2005-09-21
+ --------------------------------------
+ - Some GUIDs/interfaces in C++ were changed.
+ IStream.h:
+ ISequentialInStream::Read now works as old ReadPart
+ ISequentialOutStream::Write now works as old WritePart
+
+
+ Version 4.27 2005-08-07
+ --------------------------------------
+ - Bug in LzmaDecodeSize.c was fixed:
+ if _LZMA_IN_CB and _LZMA_OUT_READ were defined,
+ decompressing worked incorrectly.
+
+
+ Version 4.26 2005-08-05
+ --------------------------------------
+ - Fixes in 7z_C code and LzmaTest.c:
+ previous versions could work incorrectly,
+ if malloc(0) returns 0
+
+
+ Version 4.23 2005-06-29
+ --------------------------------------
+ - Small fixes in C++ code
+
+
+ Version 4.22 2005-06-10
+ --------------------------------------
+ - Small fixes
+
+
+ Version 4.21 2005-06-08
+ --------------------------------------
+ - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed
+ - New additional version of ANSI-C LZMA Decoder with zlib-like interface:
+ - LzmaStateDecode.h
+ - LzmaStateDecode.c
+ - LzmaStateTest.c
+ - ANSI-C LZMA Decoder now can decompress files larger than 4 GB
+
+
+ Version 4.17 2005-04-18
+ --------------------------------------
+ - New example for RAM->RAM compressing/decompressing:
+ LZMA + BCJ (filter for x86 code):
+ - LzmaRam.h
+ - LzmaRam.cpp
+ - LzmaRamDecode.h
+ - LzmaRamDecode.c
+ - -f86 switch for lzma.exe
+
+
+ Version 4.16 2005-03-29
+ --------------------------------------
+ - Bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder):
+ If _LZMA_OUT_READ was defined, and if encoded stream was corrupted,
+ decoder could access memory outside of allocated range.
+ - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster).
+ Old version of LZMA Decoder now is in file LzmaDecodeSize.c.
+ LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c
+ - Small speed optimization in LZMA C++ code
+ - filter for SPARC's code was added
+ - Simplified version of .7z ANSI-C Decoder was included
+
+
+ Version 4.06 2004-09-05
+ --------------------------------------
+ - Bug in v4.05 was fixed:
+ LZMA-Encoder didn't release output stream in some cases.
+
+
+ Version 4.05 2004-08-25
+ --------------------------------------
+ - Source code of filters for x86, IA-64, ARM, ARM-Thumb
+ and PowerPC code was included to SDK
+ - Some internal minor changes
+
+
+ Version 4.04 2004-07-28
+ --------------------------------------
+ - More compatibility with some C++ compilers
+
+
+ Version 4.03 2004-06-18
+ --------------------------------------
+ - "Benchmark" command was added. It measures compressing
+ and decompressing speed and shows rating values.
+ Also it checks hardware errors.
+
+
+ Version 4.02 2004-06-10
+ --------------------------------------
+ - C++ LZMA Encoder/Decoder code now is more portable
+ and it can be compiled by GCC on Linux.
+
+
+ Version 4.01 2004-02-15
+ --------------------------------------
+ - Some detection of data corruption was enabled.
+ LzmaDecode.c / RangeDecoderReadByte
+ .....
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+
+
+ Version 4.00 2004-02-13
+ --------------------------------------
+ - Original version of LZMA SDK
+
+
+
+HISTORY of the LZMA
+-------------------
+ 2001-2004: Improvements to LZMA compressing/decompressing code,
+ keeping compatibility with original LZMA format
+ 1996-2001: Development of LZMA compression format
+
+ Some milestones:
+
+ 2001-08-30: LZMA compression was added to 7-Zip
+ 1999-01-02: First version of 7-Zip was released
+
+
+End of document
diff --git a/release/src/linux/linux/scripts/squashfs/lzma/lzma.txt b/release/src/linux/linux/scripts/squashfs/lzma/lzma.txt
new file mode 100644
index 00000000..8b5825fb
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/lzma/lzma.txt
@@ -0,0 +1,637 @@
+LZMA SDK 4.32
+-------------
+
+LZMA SDK 4.32 Copyright (C) 1999-2005 Igor Pavlov
+
+LZMA SDK provides the documentation, samples, header files, libraries,
+and tools you need to develop applications that use LZMA compression.
+
+LZMA is default and general compression method of 7z format
+in 7-Zip compression program (www.7-zip.org). LZMA provides high
+compression ratio and very fast decompression.
+
+LZMA is an improved version of famous LZ77 compression algorithm.
+It was improved in way of maximum increasing of compression ratio,
+keeping high decompression speed and low memory requirements for
+decompressing.
+
+
+
+LICENSE
+-------
+
+LZMA SDK is available under any of the following licenses:
+
+1) GNU Lesser General Public License (GNU LGPL)
+2) Common Public License (CPL)
+3) Simplified license for unmodified code (read SPECIAL EXCEPTION)
+4) Proprietary license
+
+It means that you can select one of these four options and follow rules of that license.
+
+
+1,2) GNU LGPL and CPL licenses are pretty similar and both these
+licenses are classified as
+ - "Free software licenses" at http://www.gnu.org/
+ - "OSI-approved" at http://www.opensource.org/
+
+
+3) SPECIAL EXCEPTION
+
+Igor Pavlov, as the author of this code, expressly permits you
+to statically or dynamically link your code (or bind by name)
+to the files from LZMA SDK without subjecting your linked
+code to the terms of the CPL or GNU LGPL.
+Any modifications or additions to files from LZMA SDK, however,
+are subject to the GNU LGPL or CPL terms.
+
+SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code,
+while you keep LZMA SDK code unmodified.
+
+
+SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits
+you to use this code under the same terms and conditions contained in the License
+Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov.
+
+SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version
+of LZMA SDK as update for previous versions.
+
+
+SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits
+you to use code of examples (LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp,
+LzmaAlone.cs, LzmaAlone.java) as public domain code.
+
+
+4) Proprietary license
+
+LZMA SDK also can be available under a proprietary license which
+can include:
+
+1) Right to modify code without subjecting modified code to the
+terms of the CPL or GNU LGPL
+2) Technical support for code
+
+To request such proprietary license or any additional consultations,
+send email message from that page:
+http://www.7-zip.org/support.html
+
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You should have received a copy of the Common Public License
+along with this library.
+
+
+LZMA SDK Contents
+-----------------
+
+LZMA SDK includes:
+
+ - C++ source code of LZMA compressing and decompressing
+ - ANSI-C compatible source code for LZMA decompressing
+ - C# source code for LZMA compressing and decompressing
+ - Java source code for LZMA compressing and decompressing
+ - Compiled file->file LZMA compressing/decompressing program for Windows system
+
+ANSI-C LZMA decompression code was ported from original C++ sources to C.
+Also it was simplified and optimized for code size.
+But it is fully compatible with LZMA from 7-Zip.
+
+
+UNIX/Linux version
+------------------
+To compile C++ version of file->file LZMA, go to directory
+C/7zip/Compress/LZMA_Alone
+and type "make" or "make clean all" to recompile all.
+
+In some UNIX/Linux versions you must compile LZMA with static libraries.
+To compile with static libraries, change string in makefile
+LIB = -lm
+to string
+LIB = -lm -static
+
+
+Files
+---------------------
+C - C / CPP source code
+CS - C# source code
+Java - Java source code
+lzma.txt - LZMA SDK description (this file)
+7zFormat.txt - 7z Format description
+7zC.txt - 7z ANSI-C Decoder description (this file)
+methods.txt - Compression method IDs for .7z
+LGPL.txt - GNU Lesser General Public License
+CPL.html - Common Public License
+lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
+history.txt - history of the LZMA SDK
+
+
+Source code structure
+---------------------
+
+C - C / CPP files
+ Common - common files for C++ projects
+ Windows - common files for Windows related code
+ 7zip - files related to 7-Zip Project
+ Common - common files for 7-Zip
+ Compress - files related to compression/decompression
+ LZ - files related to LZ (Lempel-Ziv) compression algorithm
+ BinTree - Binary Tree Match Finder for LZ algorithm
+ HashChain - Hash Chain Match Finder for LZ algorithm
+ Patricia - Patricia Match Finder for LZ algorithm
+ RangeCoder - Range Coder (special code of compression/decompression)
+ LZMA - LZMA compression/decompression on C++
+ LZMA_Alone - file->file LZMA compression/decompression
+ LZMA_C - ANSI-C compatible LZMA decompressor
+ LzmaDecode.h - interface for LZMA decoding on ANSI-C
+ LzmaDecode.c - LZMA decoding on ANSI-C (new fastest version)
+ LzmaDecodeSize.c - LZMA decoding on ANSI-C (old size-optimized version)
+ LzmaTest.c - test application that decodes LZMA encoded file
+ LzmaStateDecode.h - interface for LZMA decoding (State version)
+ LzmaStateDecode.c - LZMA decoding on ANSI-C (State version)
+ LzmaStateTest.c - test application (State version)
+ Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
+ Archive - files related to archiving
+ 7z_C - 7z ANSI-C Decoder
+
+CS - C# files
+ 7zip
+ Common - some common files for 7-Zip
+ Compress - files related to compression/decompression
+ LZ - files related to LZ (Lempel-Ziv) compression algorithm
+ LZMA - LZMA compression/decompression
+ LzmaAlone - file->file LZMA compression/decompression
+ RangeCoder - Range Coder (special code of compression/decompression)
+
+Java - Java files
+ SevenZip
+ Compression - files related to compression/decompression
+ LZ - files related to LZ (Lempel-Ziv) compression algorithm
+ LZMA - LZMA compression/decompression
+ RangeCoder - Range Coder (special code of compression/decompression)
+
+C/C++ source code of LZMA SDK is part of 7-Zip project.
+
+You can find ANSI-C LZMA decompressing code at folder
+ C/7zip/Compress/LZMA_C
+7-Zip doesn't use that ANSI-C LZMA code and that code was developed
+specially for this SDK. And files from LZMA_C do not need files from
+other directories of SDK for compiling.
+
+7-Zip source code can be downloaded from 7-Zip's SourceForge page:
+
+ http://sourceforge.net/projects/sevenzip/
+
+
+LZMA Decompression features
+---------------------------
+ - Variable dictionary size (up to 256 MB)
+ - Estimated compressing speed: about 500 KB/s on 1 GHz CPU
+ - Estimated decompressing speed:
+ - 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon
+ - 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC
+ - Small memory requirements for decompressing (8-32 KB + DictionarySize)
+ - Small code size for decompressing: 2-8 KB (depending from
+ speed optimizations)
+
+LZMA decoder uses only integer operations and can be
+implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).
+
+Some critical operations that affect to speed of LZMA decompression:
+ 1) 32*16 bit integer multiply
+ 2) Misspredicted branches (penalty mostly depends from pipeline length)
+ 3) 32-bit shift and arithmetic operations
+
+Speed of LZMA decompressing mostly depends from CPU speed.
+Memory speed has no big meaning. But if your CPU has small data cache,
+overall weight of memory speed will slightly increase.
+
+
+How To Use
+----------
+
+Using LZMA encoder/decoder executable
+--------------------------------------
+
+Usage: LZMA <e|d> inputFile outputFile [<switches>...]
+
+ e: encode file
+
+ d: decode file
+
+ b: Benchmark. There are two tests: compressing and decompressing
+ with LZMA method. Benchmark shows rating in MIPS (million
+ instructions per second). Rating value is calculated from
+ measured speed and it is normalized with AMD Athlon XP CPU
+ results. Also Benchmark checks possible hardware errors (RAM
+ errors in most cases). Benchmark uses these settings:
+ (-a1, -d21, -fb32, -mfbt4). You can change only -d. Also you
+ can change number of iterations. Example for 30 iterations:
+ LZMA b 30
+ Default number of iterations is 10.
+
+<Switches>
+
+
+ -a{N}: set compression mode 0 = fast, 1 = normal, 2 = max
+ default: 2 (max)
+
+ d{N}: Sets Dictionary size - [0, 28], default: 23 (8MB)
+ The maximum value for dictionary size is 256 MB = 2^28 bytes.
+ Dictionary size is calculated as DictionarySize = 2^N bytes.
+ For decompressing file compressed by LZMA method with dictionary
+ size D = 2^N you need about D bytes of memory (RAM).
+
+ -fb{N}: set number of fast bytes - [5, 273], default: 128
+ Usually big number gives a little bit better compression ratio
+ and slower compression process.
+
+ -lc{N}: set number of literal context bits - [0, 8], default: 3
+ Sometimes lc=4 gives gain for big files.
+
+ -lp{N}: set number of literal pos bits - [0, 4], default: 0
+ lp switch is intended for periodical data when period is
+ equal 2^N. For example, for 32-bit (4 bytes)
+ periodical data you can use lp=2. Often it's better to set lc0,
+ if you change lp switch.
+
+ -pb{N}: set number of pos bits - [0, 4], default: 2
+ pb switch is intended for periodical data
+ when period is equal 2^N.
+
+ -mf{MF_ID}: set Match Finder. Default: bt4.
+ Compression ratio for all bt* and pat* almost the same.
+ Algorithms from hc* group doesn't provide good compression
+ ratio, but they often works pretty fast in combination with
+ fast mode (-a0). Methods from bt* group require less memory
+ than methods from pat* group. Usually bt4 works faster than
+ any pat*, but for some types of files pat* can work faster.
+
+ Memory requirements depend from dictionary size
+ (parameter "d" in table below).
+
+ MF_ID Memory Description
+
+ bt2 d*9.5 + 1MB Binary Tree with 2 bytes hashing.
+ bt3 d*9.5 + 65MB Binary Tree with 2-3(full) bytes hashing.
+ bt4 d*9.5 + 6MB Binary Tree with 2-3-4 bytes hashing.
+ bt4b d*9.5 + 34MB Binary Tree with 2-3-4(big) bytes hashing.
+ pat2r d*26 + 1MB Patricia Tree with 2-bits nodes, removing.
+ pat2 d*38 + 1MB Patricia Tree with 2-bits nodes.
+ pat2h d*38 + 77MB Patricia Tree with 2-bits nodes, 2-3 bytes hashing.
+ pat3h d*62 + 85MB Patricia Tree with 3-bits nodes, 2-3 bytes hashing.
+ pat4h d*110 +101MB Patricia Tree with 4-bits nodes, 2-3 bytes hashing.
+ hc3 d*5.5 + 1MB Hash Chain with 2-3 bytes hashing.
+ hc4 d*5.5 + 6MB Hash Chain with 2-3-4 bytes hashing.
+
+ -eos: write End Of Stream marker. By default LZMA doesn't write
+ eos marker, since LZMA decoder knows uncompressed size
+ stored in .lzma file header.
+
+ -si: Read data from stdin (it will write End Of Stream marker).
+ -so: Write data to stdout
+
+
+Examples:
+
+1) LZMA e file.bin file.lzma -d16 -lc0
+
+compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)
+and 0 literal context bits. -lc0 allows to reduce memory requirements
+for decompression.
+
+
+2) LZMA e file.bin file.lzma -lc0 -lp2
+
+compresses file.bin to file.lzma with settings suitable
+for 32-bit periodical data (for example, ARM or MIPS code).
+
+3) LZMA d file.lzma file.bin
+
+decompresses file.lzma to file.bin.
+
+
+Compression ratio hints
+-----------------------
+
+Recommendations
+---------------
+
+To increase compression ratio for LZMA compressing it's desirable
+to have aligned data (if it's possible) and also it's desirable to locate
+data in such order, where code is grouped in one place and data is
+grouped in other place (it's better than such mixing: code, data, code,
+data, ...).
+
+
+Using Filters
+-------------
+You can increase compression ratio for some data types, using
+special filters before compressing. For example, it's possible to
+increase compression ratio on 5-10% for code for those CPU ISAs:
+x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.
+
+You can find C/C++ source code of such filters in folder "7zip/Compress/Branch"
+
+You can check compression ratio gain of these filters with such
+7-Zip commands (example for ARM code):
+No filter:
+ 7z a a1.7z a.bin -m0=lzma
+
+With filter for little-endian ARM code:
+ 7z a a2.7z a.bin -m0=bc_arm -m1=lzma
+
+With filter for big-endian ARM code (using additional Swap4 filter):
+ 7z a a3.7z a.bin -m0=swap4 -m1=bc_arm -m2=lzma
+
+It works in such manner:
+Compressing = Filter_encoding + LZMA_encoding
+Decompressing = LZMA_decoding + Filter_decoding
+
+Compressing and decompressing speed of such filters is very high,
+so it will not increase decompressing time too much.
+Moreover, it reduces decompression time for LZMA_decoding,
+since compression ratio with filtering is higher.
+
+These filters convert CALL (calling procedure) instructions
+from relative offsets to absolute addresses, so such data becomes more
+compressible. Source code of these CALL filters is pretty simple
+(about 20 lines of C++), so you can convert it from C++ version yourself.
+
+For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.
+
+
+LZMA compressed file format
+---------------------------
+Offset Size Description
+ 0 1 Special LZMA properties for compressed data
+ 1 4 Dictionary size (little endian)
+ 5 8 Uncompressed size (little endian). -1 means unknown size
+ 13 Compressed data
+
+
+ANSI-C LZMA Decoder
+~~~~~~~~~~~~~~~~~~~
+
+To compile ANSI-C LZMA Decoder you can use one of the following files sets:
+1) LzmaDecode.h + LzmaDecode.c + LzmaTest.c (fastest version)
+2) LzmaDecode.h + LzmaDecodeSize.c + LzmaTest.c (old size-optimized version)
+3) LzmaStateDecode.h + LzmaStateDecode.c + LzmaStateTest.c (zlib-like interface)
+
+
+Memory requirements for LZMA decoding
+-------------------------------------
+
+LZMA decoder doesn't allocate memory itself, so you must
+allocate memory and send it to LZMA.
+
+Stack usage of LZMA decoding function for local variables is not
+larger than 200 bytes.
+
+How To decompress data
+----------------------
+
+LZMA Decoder (ANSI-C version) now supports 5 interfaces:
+1) Single-call Decompressing
+2) Single-call Decompressing with input stream callback
+3) Multi-call Decompressing with output buffer
+4) Multi-call Decompressing with input callback and output buffer
+5) Multi-call State Decompressing (zlib-like interface)
+
+Variant-5 is similar to Variant-4, but Variant-5 doesn't use callback functions.
+
+Decompressing steps
+-------------------
+
+1) read LZMA properties (5 bytes):
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+2) read uncompressed size (8 bytes, little-endian)
+
+3) Decode properties:
+
+ CLzmaDecoderState state; /* it's 24-140 bytes structure, if int is 32-bit */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+
+4) Allocate memory block for internal Structures:
+
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return PrintError(rs, kCantAllocateMessage);
+
+ LZMA decoder uses array of CProb variables as internal structure.
+ By default, CProb is unsigned_short. But you can define _LZMA_PROB32 to make
+ it unsigned_int. It can increase speed on some 32-bit CPUs, but memory
+ usage will be doubled in that case.
+
+
+5) Main Decompressing
+
+You must use one of the following interfaces:
+
+5.1 Single-call Decompressing
+-----------------------------
+When to use: RAM->RAM decompressing
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: no defines
+Memory Requirements:
+ - Input buffer: compressed size
+ - Output buffer: uncompressed size
+ - LZMA Internal Structures (~16 KB for default settings)
+
+Interface:
+ int res = LzmaDecode(&state,
+ inStream, compressedSize, &inProcessed,
+ outStream, outSize, &outProcessed);
+
+
+5.2 Single-call Decompressing with input stream callback
+--------------------------------------------------------
+When to use: File->RAM or Flash->RAM decompressing.
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: _LZMA_IN_CB
+Memory Requirements:
+ - Buffer for input stream: any size (for example, 16 KB)
+ - Output buffer: uncompressed size
+ - LZMA Internal Structures (~16 KB for default settings)
+
+Interface:
+ typedef struct _CBuffer
+ {
+ ILzmaInCallback InCallback;
+ FILE *File;
+ unsigned char Buffer[kInBufferSize];
+ } CBuffer;
+
+ int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
+ {
+ CBuffer *bo = (CBuffer *)object;
+ *buffer = bo->Buffer;
+ *size = MyReadFile(bo->File, bo->Buffer, kInBufferSize);
+ return LZMA_RESULT_OK;
+ }
+
+ CBuffer g_InBuffer;
+
+ g_InBuffer.File = inFile;
+ g_InBuffer.InCallback.Read = LzmaReadCompressed;
+ int res = LzmaDecode(&state,
+ &g_InBuffer.InCallback,
+ outStream, outSize, &outProcessed);
+
+
+5.3 Multi-call decompressing with output buffer
+-----------------------------------------------
+When to use: RAM->File decompressing
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: _LZMA_OUT_READ
+Memory Requirements:
+ - Input buffer: compressed size
+ - Buffer for output stream: any size (for example, 16 KB)
+ - LZMA Internal Structures (~16 KB for default settings)
+ - LZMA dictionary (dictionary size is encoded in stream properties)
+
+Interface:
+
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+
+ LzmaDecoderInit(&state);
+ do
+ {
+ LzmaDecode(&state,
+ inBuffer, inAvail, &inProcessed,
+ g_OutBuffer, outAvail, &outProcessed);
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+ }
+ while you need more bytes
+
+ see LzmaTest.c for more details.
+
+
+5.4 Multi-call decompressing with input callback and output buffer
+------------------------------------------------------------------
+When to use: File->File decompressing
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: _LZMA_IN_CB, _LZMA_OUT_READ
+Memory Requirements:
+ - Buffer for input stream: any size (for example, 16 KB)
+ - Buffer for output stream: any size (for example, 16 KB)
+ - LZMA Internal Structures (~16 KB for default settings)
+ - LZMA dictionary (dictionary size is encoded in stream properties)
+
+Interface:
+
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+
+ LzmaDecoderInit(&state);
+ do
+ {
+ LzmaDecode(&state,
+ &bo.InCallback,
+ g_OutBuffer, outAvail, &outProcessed);
+ }
+ while you need more bytes
+
+ see LzmaTest.c for more details:
+
+
+5.5 Multi-call State Decompressing (zlib-like interface)
+------------------------------------------------------------------
+When to use: file->file decompressing
+Compile files: LzmaStateDecode.h, LzmaStateDecode.c
+Compile defines:
+Memory Requirements:
+ - Buffer for input stream: any size (for example, 16 KB)
+ - Buffer for output stream: any size (for example, 16 KB)
+ - LZMA Internal Structures (~16 KB for default settings)
+ - LZMA dictionary (dictionary size is encoded in stream properties)
+
+Interface:
+
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+
+
+ LzmaDecoderInit(&state);
+ do
+ {
+ res = LzmaDecode(&state,
+ inBuffer, inAvail, &inProcessed,
+ g_OutBuffer, outAvail, &outProcessed,
+ finishDecoding);
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+ }
+ while you need more bytes
+
+ see LzmaStateTest.c for more details:
+
+
+6) Free all allocated blocks
+
+
+Note
+----
+LzmaDecodeSize.c is size-optimized version of LzmaDecode.c.
+But compiled code of LzmaDecodeSize.c can be larger than
+compiled code of LzmaDecode.c. So it's better to use
+LzmaDecode.c in most cases.
+
+
+EXIT codes
+-----------
+
+LZMA decoder can return one of the following codes:
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+If you use callback function for input data and you return some
+error code, LZMA Decoder also returns that code.
+
+
+
+LZMA Defines
+------------
+
+_LZMA_IN_CB - Use callback for input data
+
+_LZMA_OUT_READ - Use read function for output data
+
+_LZMA_LOC_OPT - Enable local speed optimizations inside code.
+ _LZMA_LOC_OPT is only for LzmaDecodeSize.c (size-optimized version).
+ _LZMA_LOC_OPT doesn't affect LzmaDecode.c (speed-optimized version)
+ and LzmaStateDecode.c
+
+_LZMA_PROB32 - It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case
+
+_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler
+ and long is 32-bit.
+
+_LZMA_SYSTEM_SIZE_T - Define it if you want to use system's size_t.
+ You can use it to enable 64-bit sizes supporting
+
+
+
+C++ LZMA Encoder/Decoder
+~~~~~~~~~~~~~~~~~~~~~~~~
+C++ LZMA code use COM-like interfaces. So if you want to use it,
+you can study basics of COM/OLE.
+
+By default, LZMA Encoder contains all Match Finders.
+But for compressing it's enough to have just one of them.
+So for reducing size of compressing code you can define:
+ #define COMPRESS_MF_BT
+ #define COMPRESS_MF_BT4
+and it will use only bt4 match finder.
+
+
+---
+
+http://www.7-zip.org
+http://www.7-zip.org/support.html
diff --git a/release/src/linux/linux/scripts/squashfs/mksquashfs.c b/release/src/linux/linux/scripts/squashfs/mksquashfs.c
index fbe25e6d..e773f53c 100644
--- a/release/src/linux/linux/scripts/squashfs/mksquashfs.c
+++ b/release/src/linux/linux/scripts/squashfs/mksquashfs.c
@@ -1,7 +1,8 @@
/*
* Create a squashfs filesystem. This is a highly compressed read only filesystem.
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,7 +21,9 @@
* mksquashfs.c
*/
+#define FALSE 0
#define TRUE 1
+
#include <pwd.h>
#include <grp.h>
#include <time.h>
@@ -33,44 +36,70 @@
#include <dirent.h>
#include <string.h>
#include <zlib.h>
-#include <endian.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/mman.h>
-#include "mksquashfs.h"
+#ifndef linux
+#define __BYTE_ORDER BYTE_ORDER
+#define __BIG_ENDIAN BIG_ENDIAN
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#else
+#include <endian.h>
+#endif
+
#include <squashfs_fs.h>
+#include "mksquashfs.h"
+#include "global.h"
+#include "sort.h"
#ifdef SQUASHFS_TRACE
-#define TRACE(s, args...) printf("mksquashfs: "s, ## args)
+#define TRACE(s, args...) do { \
+ printf("mksquashfs: "s, ## args); \
+ } while(0)
#else
#define TRACE(s, args...)
#endif
-#define INFO(s, args...) do { if(!silent) printf("mksquashfs: "s, ## args); } while(0)
-#define ERROR(s, args...) do { fprintf(stderr, s, ## args); } while(0)
-#define EXIT_MKSQUASHFS() do { if(restore)\
- restorefs();\
- exit(1); } while(0)
-#define BAD_ERROR(s, args...) do {\
+#define INFO(s, args...) do {\
+ if(!silent)\
+ printf("mksquashfs: "s, ## args);\
+ } while(0)
+#define ERROR(s, args...) do {\
+ fprintf(stderr, s, ## args);\
+ } while(0)
+#define EXIT_MKSQUASHFS() do {\
+ if(restore)\
+ restorefs();\
+ if(delete && destination_file && !block_device)\
+ unlink(destination_file);\
+ exit(1);\
+ } while(0)
+#define BAD_ERROR(s, args...) do {\
fprintf(stderr, "FATAL ERROR:" s, ##args);\
EXIT_MKSQUASHFS();\
- } while(0)
-
-int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0;
-int total_compressed = 0, total_uncompressed = 0;
+ } while(0)
+int delete = FALSE;
+long long total_compressed = 0, total_uncompressed = 0;
int fd;
+/* filesystem flags for building */
+int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0;
+int noI = 0, noD = 0, check_data = 0;
+int swap, silent = TRUE;
+long long global_uid = -1, global_gid = -1;
+
/* superblock attributes */
-int noI = 0, noD = 0, check_data = 0, block_size = SQUASHFS_FILE_SIZE, block_log;
+int block_size = SQUASHFS_FILE_SIZE, block_log;
unsigned short uid_count = 0, guid_count = 0;
squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS];
int block_offset;
+int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0;
/* write position within data section */
-unsigned int bytes = 0, total_bytes = 0;
+long long bytes = 0, total_bytes = 0;
/* in memory directory table - possibly compressed */
char *directory_table = NULL;
@@ -88,22 +117,38 @@ unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0;
char *data_cache = NULL;
unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0;
-/* in memory directory header */
+/* in memory directory data */
+#define I_COUNT_SIZE 128
+#define DIR_ENTRIES 32
+#define INODE_HASH_SIZE 65536
+#define INODE_HASH_MASK (INODE_HASH_SIZE - 1)
+#define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK)
+
+struct cached_dir_index {
+ squashfs_dir_index index;
+ char *name;
+};
+
struct directory {
unsigned int start_block;
unsigned int size;
unsigned char *buff;
unsigned char *p;
unsigned int entry_count;
- squashfs_dir_header *entry_count_p;
+ unsigned char *entry_count_p;
+ unsigned int i_count;
+ unsigned int i_size;
+ struct cached_dir_index *index;
+ unsigned char *index_count_p;
+ unsigned int inode_number;
};
+struct inode_info *inode_info[INODE_HASH_SIZE];
+
+/* hash tables used to do fast duplicate searches in duplicate check */
struct file_info *dupl[65536], *frag_dups[65536];
int dup_files = 0;
-int swap, silent = TRUE;
-int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0;
-
/* list of exclude dirs/files */
struct exclude_info {
dev_t st_dev;
@@ -117,18 +162,22 @@ int excluded(char *filename, struct stat *buf);
/* fragment block data structures */
int fragments = 0;
-static char *fragment_data;
-static int fragment_size = 0;
+char fragment_data[SQUASHFS_FILE_SIZE];
+int fragment_size = 0;
struct fragment {
unsigned int index;
int offset;
int size;
};
-
-
#define FRAG_SIZE 32768
squashfs_fragment_entry *fragment_table = NULL;
+
+/* current inode number for directories and non directories */
+unsigned int dir_inode_no = 1;
+unsigned int inode_no = 0;
+unsigned int root_inode_number = 0;
+
/* list of source dirs/files */
int source = 0;
char **source_path;
@@ -139,13 +188,15 @@ struct old_root_entry_info {
char name[SQUASHFS_NAME_LEN + 1];
squashfs_inode inode;
int type;
+ int inode_number;
};
+struct old_root_entry_info *old_root_entry;
/* in memory file info */
struct file_info {
- unsigned int bytes;
+ long long bytes;
unsigned short checksum;
- unsigned int start;
+ long long start;
unsigned int *block_list;
struct file_info *next;
struct fragment *fragment;
@@ -158,46 +209,51 @@ int interrupted = 0;
/* restore orignal filesystem state if appending to existing filesystem is cancelled */
jmp_buf env;
char *sdata_cache, *sdirectory_data_cache;
-unsigned int sbytes, sinode_bytes, scache_bytes, sdirectory_bytes,
+
+long long sbytes, stotal_bytes;
+
+unsigned int sinode_bytes, scache_bytes, sdirectory_bytes,
sdirectory_cache_bytes, suid_count, sguid_count,
- stotal_bytes, stotal_inode_bytes, stotal_directory_bytes,
+ stotal_inode_bytes, stotal_directory_bytes,
sinode_count, sfile_count, ssym_count, sdev_count,
- sdir_count, sdup_files;
+ sdir_count, sfifo_count, ssock_count, sdup_files;
int sfragments;
int restore = 0;
-/*flag whether destination file is a block device */
+/* flag whether destination file is a block device */
int block_device = 0;
/* flag indicating whether files are sorted using sort list(s) */
int sorted = 0;
-long long global_uid = -1, global_gid = -1;
+/* save destination file name for deleting on error */
+char *destination_file = NULL;
/* structure to used to pass in a pointer or an integer
* to duplicate buffer read helper functions.
*/
struct duplicate_buffer_handle {
- unsigned char *ptr;
- unsigned int start;
+ char *ptr;
+ long long start;
};
-struct old_root_entry_info *old_root_entry;
-void add_old_root_entry(char *name, squashfs_inode inode, int type);
+void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type);
extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source);
-extern int read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **inode_table, int *inode_bytes,
- char **data_cache, int *cache_bytes, int *cache_size, char **directory_table, int *directory_bytes,
- char **directory_data_cache, int *directory_cache_bytes, int *directory_cache_size,
- int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count,
- squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count,
- unsigned int *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory,
- void (push_directory_entry)(char *, squashfs_inode, int), squashfs_fragment_entry **fragment_table);
-squashfs_inode get_sorted_inode(struct stat *buf);
+extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table,
+ char **data_cache, char **cdirectory_table, char **directory_data_cache,
+ unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size,
+ unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count,
+ int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids,
+ unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count,
+ long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory,
+ unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode,
+ void (push_directory_entry)(char *, squashfs_inode, int, int),
+ squashfs_fragment_entry **fragment_table);
+int get_sorted_inode(squashfs_inode *inode, struct stat *buf);
int read_sort_file(char *filename, int source, char *source_path[]);
-void sort_files_and_write(int source, char *source_path[]);
-struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, int bytes, unsigned int **block_list, int *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes);
-
-#define FALSE 0
+void sort_files_and_write(struct dir_info *dir);
+struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes);
+struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *));
#define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache)))
@@ -220,6 +276,8 @@ void restorefs()
sym_count = ssym_count;
dev_count = sdev_count;
dir_count = sdir_count;
+ fifo_count = sfifo_count;
+ sock_count = ssock_count;
dup_files = sdup_files;
fragments = sfragments;
fragment_size = 0;
@@ -239,12 +297,18 @@ void sighandler()
}
+void sighandler2()
+{
+ EXIT_MKSQUASHFS();
+}
+
+
unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block)
{
unsigned long c_byte = block_size << 1;
unsigned int res;
- if(!uncompressed && (res = compress2(d, &c_byte, s, size, 9)) != Z_OK) {
+ if(!uncompressed && (res = compress2((unsigned char *) d, &c_byte, (unsigned char *) s, size, 9)) != Z_OK) {
if(res == Z_MEM_ERROR)
BAD_ERROR("zlib::compress failed, not enough memory\n");
else if(res == Z_BUF_ERROR)
@@ -281,7 +345,7 @@ squashfs_base_inode_header *get_inode(int req_size)
SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0);
TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte);
if(!swap)
- memcpy((void *) (inode_table + inode_bytes), (void *) &c_byte, sizeof(unsigned short));
+ memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short));
else
SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1);
if(check_data)
@@ -311,7 +375,7 @@ failed:
}
-void read_bytes(int fd, unsigned int byte, int bytes, char *buff)
+void read_bytes(int fd, long long byte, int bytes, char *buff)
{
off_t off = byte;
@@ -327,13 +391,10 @@ void read_bytes(int fd, unsigned int byte, int bytes, char *buff)
}
-void write_bytes(int fd, unsigned int byte, int bytes, char *buff)
+void write_bytes(int fd, long long byte, int bytes, char *buff)
{
off_t off = byte;
- if(off + bytes > ((long long)1<<32) - 1 )
- BAD_ERROR("Filesystem greater than maximum size 2^32 - 1\n");
-
if(lseek(fd, off, SEEK_SET) == -1) {
perror("Lseek on destination failed");
EXIT_MKSQUASHFS();
@@ -346,12 +407,12 @@ void write_bytes(int fd, unsigned int byte, int bytes, char *buff)
}
-unsigned int write_inodes()
+long long write_inodes()
{
unsigned short c_byte;
int avail_bytes;
char *datap = data_cache;
- unsigned int start_bytes = bytes;
+ long long start_bytes = bytes;
while(cache_bytes) {
if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) {
@@ -364,7 +425,7 @@ unsigned int write_inodes()
c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0);
TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte);
if(!swap)
- memcpy((void *) (inode_table + inode_bytes), (void *) &c_byte, sizeof(unsigned short));
+ memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short));
else
SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1);
if(check_data)
@@ -382,12 +443,12 @@ unsigned int write_inodes()
}
-unsigned int write_directories()
+long long write_directories()
{
unsigned short c_byte;
int avail_bytes;
char *directoryp = directory_data_cache;
- unsigned int start_bytes = bytes;
+ long long start_bytes = bytes;
while(directory_cache_bytes) {
if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) {
@@ -401,7 +462,7 @@ unsigned int write_directories()
c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0);
TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte);
if(!swap)
- memcpy((void *) (directory_table + directory_bytes), (void *) &c_byte, sizeof(unsigned short));
+ memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short));
else
SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1);
if(check_data)
@@ -455,81 +516,132 @@ unsigned int get_guid(squashfs_uid uid, squashfs_uid guid)
}
-squashfs_inode create_inode(char *filename, int type, int byte_size,
-squashfs_block start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment)
+int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in)
{
- squashfs_inode i_no;
- struct stat buf;
+ struct stat *buf = &dir_ent->inode->buf;
squashfs_inode_header inode_header;
squashfs_base_inode_header *inode, *base = &inode_header.base;
+ char *filename = dir_ent->pathname;
+ int nlink = dir_ent->inode->nlink;
+ int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no;
- if(filename[0] == '\0') {
- /* dummy top level directory, if multiple sources specified on command line */
- buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO;
- buf.st_uid = getuid();
- buf.st_gid = getgid();
- buf.st_mtime = time(NULL);
- } else if(lstat(filename, &buf) == -1) {
- char buffer[8192];
- sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename);
- perror(buffer);
- return SQUASHFS_INVALID;
- }
-
- base->mode = SQUASHFS_MODE(buf.st_mode);
- base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf.st_uid : global_uid);
+ base->mode = SQUASHFS_MODE(buf->st_mode);
+ base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid);
base->inode_type = type;
- base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf.st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf.st_gid : global_gid);
+ base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid);
+ base->mtime = buf->st_mtime;
+ base->inode_number = inode_number;
if(type == SQUASHFS_FILE_TYPE) {
int i;
squashfs_reg_inode_header *reg = &inode_header.reg, *inodep;
inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int));
- inodep = (squashfs_reg_inode_header *) inode ;
- reg->mtime = buf.st_mtime;
+ inodep = (squashfs_reg_inode_header *) inode;
reg->file_size = byte_size;
reg->start_block = start_block;
reg->fragment = fragment->index;
reg->offset = fragment->offset;
if(!swap) {
- memcpy((void *) inodep, (void *) reg, sizeof(*reg));
- memcpy((void *) inodep->block_list, block_list, offset * sizeof(unsigned int));
+ memcpy(inodep, reg, sizeof(*reg));
+ memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int));
} else {
SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep);
SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset);
}
- TRACE("File inode, file_size %d, start_block %x, blocks %d, fragment %d, offset %d, size %d\n", byte_size,
+ TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size,
start_block, offset, fragment->index, fragment->offset, fragment->size);
for(i = 0; i < offset; i++)
TRACE("Block %d, size %d\n", i, block_list[i]);
}
+ else if(type == SQUASHFS_LREG_TYPE) {
+ int i;
+ squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep;
+
+ inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int));
+ inodep = (squashfs_lreg_inode_header *) inode;
+ reg->nlink = nlink;
+ reg->file_size = byte_size;
+ reg->start_block = start_block;
+ reg->fragment = fragment->index;
+ reg->offset = fragment->offset;
+ if(!swap) {
+ memcpy(inodep, reg, sizeof(*reg));
+ memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int));
+ } else {
+ SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep);
+ SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset);
+ }
+ TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size,
+ start_block, offset, fragment->index, fragment->offset, fragment->size, nlink);
+ for(i = 0; i < offset; i++)
+ TRACE("Block %d, size %d\n", i, block_list[i]);
+ }
+ else if(type == SQUASHFS_LDIR_TYPE) {
+ int i;
+ unsigned char *p;
+ squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep;
+ struct cached_dir_index *index = dir_in->index;
+ unsigned int i_count = dir_in->i_count;
+ unsigned int i_size = dir_in->i_size;
+
+ if(byte_size >= 1 << 27)
+ BAD_ERROR("directory greater than 2^27-1 bytes!\n");
+
+ inode = get_inode(sizeof(*dir) + i_size);
+ inodep = (squashfs_ldir_inode_header *) inode;
+ dir->inode_type = SQUASHFS_LDIR_TYPE;
+ dir->nlink = dir_ent->dir->directory_count + 2;
+ dir->file_size = byte_size;
+ dir->offset = offset;
+ dir->start_block = start_block;
+ dir->i_count = i_count;
+ dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no;
+
+ if(!swap)
+ memcpy(inode, dir, sizeof(*dir));
+ else
+ SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode);
+ p = (unsigned char *) inodep->index;
+ for(i = 0; i < i_count; i++) {
+ if(!swap)
+ memcpy(p, &index[i].index, sizeof(squashfs_dir_index));
+ else
+ SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p);
+ memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1);
+ p += sizeof(squashfs_dir_index) + index[i].index.size + 1;
+ }
+ TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size,
+ start_block, offset, dir_ent->dir->directory_count + 2);
+ }
else if(type == SQUASHFS_DIR_TYPE) {
squashfs_dir_inode_header *dir = &inode_header.dir;
inode = get_inode(sizeof(*dir));
- dir->mtime = buf.st_mtime;
+ dir->nlink = dir_ent->dir->directory_count + 2;
dir->file_size = byte_size;
dir->offset = offset;
dir->start_block = start_block;
+ dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no;
if(!swap)
- memcpy((void *) inode, (void *) dir, sizeof(*dir));
+ memcpy(inode, dir, sizeof(*dir));
else
SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode);
- TRACE("Directory inode, file_size %d, start_block %x, offset %x\n", byte_size,
- start_block, offset);
+ TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size,
+ start_block, offset, dir_ent->dir->directory_count + 2);
}
else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) {
squashfs_dev_inode_header *dev = &inode_header.dev;
inode = get_inode(sizeof(*dev));
- dev->rdev = (unsigned short) ((major(buf.st_rdev) << 8) |
- (minor(buf.st_rdev) & 0xff));
+ dev->nlink = nlink;
+ dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) |
+ (minor(buf->st_rdev) & 0xff));
if(!swap)
- memcpy((void *) inode, (void *) dev, sizeof(*dev));
+ memcpy(inode, dev, sizeof(*dev));
else
SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode);
- TRACE("Device inode, rdev %x\n", dev->rdev);
+ TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink);
}
else if(type == SQUASHFS_SYMLINK_TYPE) {
squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep;
@@ -538,61 +650,65 @@ squashfs_block start_block, unsigned int offset, unsigned int *block_list, struc
if((byte = readlink(filename, buff, 65536)) == -1) {
perror("Error in reading symbolic link, skipping...");
- return SQUASHFS_INVALID;
+ return FALSE;
}
if(byte == 65536) {
ERROR("Symlink is greater than 65536 bytes! skipping...");
- return SQUASHFS_INVALID;
+ return FALSE;
}
inode = get_inode(sizeof(*symlink) + byte);
- inodep = (squashfs_symlink_inode_header *) inode ;
+ symlink->nlink = nlink;
+ inodep = (squashfs_symlink_inode_header *) inode;
symlink->symlink_size = byte;
if(!swap)
- memcpy((void *) inode, symlink, sizeof(*symlink));
+ memcpy(inode, symlink, sizeof(*symlink));
else
SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode);
strncpy(inodep->symlink, buff, byte);
- TRACE("Symbolic link inode, symlink_size %d\n", byte);
+ TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink);
}
else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) {
squashfs_ipc_inode_header *ipc = &inode_header.ipc;
inode = get_inode(sizeof(*ipc));
+ ipc->nlink = nlink;
if(!swap)
- memcpy((void *) inode, (void *) ipc, sizeof(*ipc));
+ memcpy(inode, ipc, sizeof(*ipc));
else
SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode);
- TRACE("ipc inode, type %s %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket");
+ TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink);
} else
- return SQUASHFS_INVALID;
+ return FALSE;
- i_no = MKINODE(inode);
+ *i_no = MKINODE(inode);
inode_count ++;
- TRACE("Created inode 0x%Lx, type %d, uid %d, guid %d\n", i_no, type, base->uid, base->guid);
+ TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid);
- return i_no;
+ return TRUE;
}
-void init_dir(struct directory *dir)
+void scan2_init_dir(struct directory *dir)
{
- if((dir->buff = (char *)malloc(SQUASHFS_METADATA_SIZE)) == NULL) {
+ if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) {
BAD_ERROR("Out of memory allocating directory buffer\n");
}
dir->size = SQUASHFS_METADATA_SIZE;
- dir->p = dir->buff;
+ dir->p = dir->index_count_p = dir->buff;
dir->entry_count = 256;
dir->entry_count_p = NULL;
+ dir->index = NULL;
+ dir->i_count = dir->i_size = 0;
}
-void add_dir(squashfs_inode inode, char *name, int type, struct directory *dir)
+void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir)
{
- char *buff;
+ unsigned char *buff;
squashfs_dir_entry idir, *idirp;
unsigned int start_block = inode >> 16;
unsigned int offset = inode & 0xffff;
@@ -603,33 +719,48 @@ void add_dir(squashfs_inode inode, char *name, int type, struct directory *dir)
ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN);
}
- if(dir->p + sizeof(squashfs_dir_entry) + size + 6 >= dir->buff + dir->size) {
- if((buff = (char *) realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) {
+ if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) {
+ if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) {
BAD_ERROR("Out of memory reallocating directory buffer\n");
}
dir->p = (dir->p - dir->buff) + buff;
if(dir->entry_count_p)
- dir->entry_count_p = (squashfs_dir_header *) (((unsigned char *) dir->entry_count_p) -
- dir->buff + buff);
+ dir->entry_count_p = (dir->entry_count_p - dir->buff + buff);
+ dir->index_count_p = dir->index_count_p - dir->buff + buff;
dir->buff = buff;
}
- if(dir->entry_count == 256 || start_block != dir->start_block) {
+ if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) {
if(dir->entry_count_p) {
squashfs_dir_header dir_header;
+ if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) {
+ if(dir->i_count % I_COUNT_SIZE == 0)
+ if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL)
+ BAD_ERROR("Out of memory in directory index table reallocation!\n");
+ dir->index[dir->i_count].index.index = dir->p - dir->buff;
+ dir->index[dir->i_count].index.size = size - 1;
+ dir->index[dir->i_count++].name = name;
+ dir->i_size += sizeof(squashfs_dir_index) + size;
+ dir->index_count_p = dir->p;
+ }
+
dir_header.count = dir->entry_count - 1;
dir_header.start_block = dir->start_block;
+ dir_header.inode_number = dir->inode_number;
if(!swap)
- memcpy((void *) dir->entry_count_p, (void *) &dir_header, sizeof(dir_header));
+ memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header));
else
- SQUASHFS_SWAP_DIR_HEADER((&dir_header), dir->entry_count_p);
+ SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p);
+
}
- dir->entry_count_p = (squashfs_dir_header *) dir->p;
+
+ dir->entry_count_p = dir->p;
dir->start_block = start_block;
dir->entry_count = 0;
+ dir->inode_number = inode_number;
dir->p += sizeof(squashfs_dir_header);
}
@@ -637,8 +768,9 @@ void add_dir(squashfs_inode inode, char *name, int type, struct directory *dir)
idir.offset = offset;
idir.type = type;
idir.size = size - 1;
+ idir.inode_number = ((long long) inode_number - dir->inode_number);
if(!swap)
- memcpy((void *) idirp, (void *) &idir, sizeof(idir));
+ memcpy(idirp, &idir, sizeof(idir));
else
SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp);
strncpy(idirp->name, name, size);
@@ -647,14 +779,48 @@ void add_dir(squashfs_inode inode, char *name, int type, struct directory *dir)
}
-squashfs_inode write_dir(char *filename, struct directory *dir)
+int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir)
{
- squashfs_inode inode;
- unsigned int dir_size;
- int data_space;
+ unsigned int dir_size = dir->p - dir->buff;
+ int data_space = (directory_cache_size - directory_cache_bytes);
+ unsigned int directory_block, directory_offset, i_count, index;
unsigned short c_byte;
- while(directory_cache_bytes >= SQUASHFS_METADATA_SIZE) {
+ if(data_space < dir_size) {
+ int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space;
+
+ if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) {
+ goto failed;
+ }
+ directory_cache_size += realloc_size;
+ }
+
+ if(dir_size) {
+ squashfs_dir_header dir_header;
+
+ dir_header.count = dir->entry_count - 1;
+ dir_header.start_block = dir->start_block;
+ dir_header.inode_number = dir->inode_number;
+ if(!swap)
+ memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header));
+ else
+ SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p);
+ memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size);
+ }
+ directory_offset = directory_cache_bytes;
+ directory_block = directory_bytes;
+ directory_cache_bytes += dir_size;
+ i_count = 0;
+ index = SQUASHFS_METADATA_SIZE - directory_offset;
+
+ while(1) {
+ while(i_count < dir->i_count && dir->index[i_count].index.index < index)
+ dir->index[i_count++].index.start_block = directory_bytes;
+ index += SQUASHFS_METADATA_SIZE;
+
+ if(directory_cache_bytes < SQUASHFS_METADATA_SIZE)
+ break;
+
if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) {
if((directory_table = (char *) realloc(directory_table,
directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) {
@@ -667,7 +833,7 @@ squashfs_inode write_dir(char *filename, struct directory *dir)
SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0);
TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte);
if(!swap)
- memcpy((void *) directory_table + directory_bytes, (void *) &c_byte, sizeof(unsigned short));
+ memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short));
else
SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1);
if(check_data)
@@ -678,39 +844,20 @@ squashfs_inode write_dir(char *filename, struct directory *dir)
directory_cache_bytes -= SQUASHFS_METADATA_SIZE;
}
- dir_size = dir->p - dir->buff;
- data_space = (directory_cache_size - directory_cache_bytes);
- if(data_space < dir_size) {
- int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space;
-
- if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) {
- goto failed;
- }
- directory_cache_size += realloc_size;
- }
-
- if(dir_size) {
- squashfs_dir_header dir_header;
-
- dir_header.count = dir->entry_count - 1;
- dir_header.start_block = dir->start_block;
- if(!swap)
- memcpy((void *) dir->entry_count_p, (void *) &dir_header, sizeof(dir_header));
- else
- SQUASHFS_SWAP_DIR_HEADER((&dir_header), dir->entry_count_p);
- memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size);
+ if(dir_info->dir_is_ldir) {
+ if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE)
+ return FALSE;
+ } else {
+ if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE)
+ return FALSE;
}
- inode = create_inode(filename, SQUASHFS_DIR_TYPE, dir_size, directory_bytes, directory_cache_bytes, NULL, NULL);
-
- directory_cache_bytes += dir_size;
-
#ifdef SQUASHFS_TRACE
if(!swap) {
unsigned char *dirp;
int count;
- TRACE("Directory contents of inode 0x%Lx\n", inode);
+ TRACE("Directory contents of inode 0x%llx\n", *inode);
dirp = dir->buff;
while(dirp < dir->p) {
char buffer[SQUASHFS_NAME_LEN + 1];
@@ -735,7 +882,7 @@ squashfs_inode write_dir(char *filename, struct directory *dir)
#endif
dir_count ++;
- return inode;
+ return TRUE;
failed:
BAD_ERROR("Out of memory in directory table reallocation!\n");
@@ -744,37 +891,35 @@ failed:
char *get_fragment(char *buffer, struct fragment *fragment)
{
- if(fragment->index == fragments || fragment->index == SQUASHFS_INVALID_BLK)
- return fragment_data + fragment->offset;
- else {
- squashfs_fragment_entry *disk_fragment = &fragment_table[fragment->index];
- int size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size), res;
- long bytes = block_size;
-
- if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) {
- char cbuffer[block_size];
-
- read_bytes(fd, disk_fragment->start_block, size, cbuffer);
-
- if((res = uncompress(buffer, &bytes, (const char *) cbuffer, size)) != Z_OK) {
- if(res == Z_MEM_ERROR)
- BAD_ERROR("zlib::uncompress failed, not enough memory\n");
- else if(res == Z_BUF_ERROR)
- BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n");
- else
- BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res);
- }
- } else
- read_bytes(fd, disk_fragment->start_block, size, buffer);
- return buffer + fragment->offset;
- }
+ squashfs_fragment_entry *disk_fragment = &fragment_table[fragment->index];
+ int size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size);
+
+ if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) {
+ int res;
+ unsigned long bytes = block_size;
+ char cbuffer[block_size];
+
+ read_bytes(fd, disk_fragment->start_block, size, cbuffer);
+
+ if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) {
+ if(res == Z_MEM_ERROR)
+ BAD_ERROR("zlib::uncompress failed, not enough memory\n");
+ else if(res == Z_BUF_ERROR)
+ BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n");
+ else
+ BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res);
+ }
+ } else
+ read_bytes(fd, disk_fragment->start_block, size, buffer);
+
+ return buffer + fragment->offset;
}
void write_fragment()
{
int compressed_size;
- unsigned char buffer[block_size << 1];
+ char buffer[block_size << 1];
if(fragment_size == 0)
return;
@@ -795,7 +940,7 @@ void write_fragment()
}
-static struct fragment empty_fragment = {SQUASHFS_INVALID_BLK, 0, 0};
+static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0};
struct fragment *get_and_fill_fragment(char *buff, int size)
{
struct fragment *ffrg;
@@ -819,9 +964,10 @@ struct fragment *get_and_fill_fragment(char *buff, int size)
}
-unsigned int write_fragment_table()
+long long write_fragment_table()
{
- unsigned int start_bytes, frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments),
+ long long start_bytes;
+ unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments),
meta_blocks = SQUASHFS_FRAGMENT_INDEXES(fragments);
char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2], buffer[frag_bytes];
squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer;
@@ -831,9 +977,9 @@ unsigned int write_fragment_table()
TRACE("write_fragment_table: fragments %d, frag_bytes %d, meta_blocks %d\n", fragments, frag_bytes, meta_blocks);
for(i = 0; i < fragments; i++, p++) {
- TRACE("write_fragment_table: fragment %d, start_block %x, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size);
+ TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size);
if(!swap)
- memcpy((void *) p, &fragment_table[i], sizeof(squashfs_fragment_entry));
+ memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry));
else
SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p);
}
@@ -842,7 +988,7 @@ unsigned int write_fragment_table()
int avail_bytes = i == meta_blocks - 1 ? frag_bytes % SQUASHFS_METADATA_SIZE : SQUASHFS_METADATA_SIZE;
c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, noF, 0);
if(!swap)
- memcpy((void *) cbuffer, (void *) &c_byte, sizeof(unsigned short));
+ memcpy(cbuffer, &c_byte, sizeof(unsigned short));
else
SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1);
if(check_data)
@@ -868,16 +1014,16 @@ unsigned int write_fragment_table()
}
-unsigned char *read_from_buffer(struct duplicate_buffer_handle *handle, unsigned int avail_bytes)
+char *read_from_buffer(struct duplicate_buffer_handle *handle, unsigned int avail_bytes)
{
- unsigned char *v = handle->ptr;
+ char *v = handle->ptr;
handle->ptr += avail_bytes;
return v;
}
char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE];
-unsigned char *read_from_file(struct duplicate_buffer_handle *handle, unsigned int avail_bytes)
+char *read_from_file(struct duplicate_buffer_handle *handle, unsigned int avail_bytes)
{
read_bytes(fd, handle->start, avail_bytes, read_from_file_buffer);
handle->start += avail_bytes;
@@ -888,7 +1034,7 @@ unsigned char *read_from_file(struct duplicate_buffer_handle *handle, unsigned i
/*
* Compute 16 bit BSD checksum over the data
*/
-unsigned short get_checksum(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *handle, int l)
+unsigned short get_checksum(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *handle, long long l)
{
unsigned short chksum = 0;
unsigned int bytes = 0;
@@ -898,7 +1044,7 @@ unsigned short get_checksum(unsigned char *(get_next_file_block)(struct duplicat
while(l) {
bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l;
l -= bytes;
- b = get_next_file_block(&position, bytes);
+ b = (unsigned char *) get_next_file_block(&position, bytes);
while(bytes--) {
chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1;
chksum += *b++;
@@ -909,14 +1055,15 @@ unsigned short get_checksum(unsigned char *(get_next_file_block)(struct duplicat
}
-static unsigned int cached_frag = -1;
-void add_file(int start, int file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes)
+int cached_frag = -1;
+void add_file(long long start, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes)
{
struct fragment *frg;
struct file_info *dupl_ptr;
char *datap;
struct duplicate_buffer_handle handle;
-
+ unsigned int *block_list = block_listp;
+
if(!duplicate_checking)
return;
@@ -926,18 +1073,23 @@ void add_file(int start, int file_bytes, unsigned int *block_listp, int blocks,
frg->index = fragment;
frg->offset = offset;
frg->size = bytes;
- if(cached_frag == fragment)
+ if(fragment == cached_frag || fragment == SQUASHFS_INVALID_FRAG)
datap = fragment_data + offset;
else
datap = get_fragment(fragment_data, frg);
handle.start = start;
if((dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &frg, datap, bytes)) != NULL)
dupl_ptr->fragment = frg;
+ else
+ free(block_list);
cached_frag = fragment;
}
-struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, int bytes, unsigned int **block_list, int *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes)
+char cached_fragment[SQUASHFS_FILE_SIZE];
+int cached_frag1 = -1;
+
+struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes)
{
unsigned short checksum = get_checksum(get_next_file_block, file_start, bytes);
struct duplicate_buffer_handle handle = { frag_data, 0 };
@@ -947,10 +1099,11 @@ struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicat
for(; dupl_ptr; dupl_ptr = dupl_ptr->next)
if(bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size && fragment_checksum == dupl_ptr->fragment_checksum) {
- unsigned char buffer1[SQUASHFS_FILE_MAX_SIZE];
- unsigned int dup_bytes = dupl_ptr->bytes, dup_start = dupl_ptr->start;
+ char buffer1[SQUASHFS_FILE_MAX_SIZE];
+ long long dup_bytes = dupl_ptr->bytes;
+ long long dup_start = dupl_ptr->start;
struct duplicate_buffer_handle position = *file_start;
- unsigned char *buffer;
+ char *buffer;
while(dup_bytes) {
int avail_bytes = dup_bytes > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : dup_bytes;
@@ -962,10 +1115,19 @@ struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicat
dup_start += avail_bytes;
}
if(dup_bytes == 0) {
- char frag_buffer1[block_size];
- char *fragment_buffer1 = get_fragment(frag_buffer1, dupl_ptr->fragment);
+ char *fragment_buffer1;
+
+ if(dupl_ptr->fragment->index == fragments || dupl_ptr->fragment->index == SQUASHFS_INVALID_FRAG)
+ fragment_buffer1 = fragment_data + dupl_ptr->fragment->offset;
+ else if(dupl_ptr->fragment->index == cached_frag1)
+ fragment_buffer1 = cached_fragment + dupl_ptr->fragment->offset;
+ else {
+ fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment);
+ cached_frag1 = dupl_ptr->fragment->index;
+ }
+
if(frag_bytes == 0 || memcmp(frag_data, fragment_buffer1, frag_bytes) == 0) {
- TRACE("Found duplicate file, start 0x%x, size %d, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start,
+ TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start,
dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum);
*block_list = dupl_ptr->block_list;
*start = dupl_ptr->start;
@@ -984,11 +1146,8 @@ struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicat
dupl_ptr->checksum = checksum;
dupl_ptr->start = *start;
dupl_ptr->fragment_checksum = fragment_checksum;
- if((dupl_ptr->block_list = (unsigned int *) malloc(blocks * sizeof(unsigned int))) == NULL) {
- BAD_ERROR("Out of memory allocating block_list\n");
- }
-
- memcpy(dupl_ptr->block_list, *block_list, blocks * sizeof(unsigned int));
+ dupl_ptr->block_list = *block_list;
+
dup_files ++;
if(bytes) {
dupl_ptr->next = dupl[checksum];
@@ -1003,18 +1162,22 @@ struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicat
#define MINALLOCBYTES (1024 * 1024)
-squashfs_inode write_file(char *filename, long long size, int *duplicate_file)
+int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file)
{
- unsigned int frag_bytes, file, start, file_bytes = 0, block = 0;
- unsigned int c_byte;
- long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size;
- unsigned int blocks = (read_size + block_size - 1) >> block_log;
- unsigned int block_list[blocks], *block_listp = block_list;
- char buff[block_size], *c_buffer;
- int allocated_blocks = blocks, i, bbytes, whole_file = 1;
+ int block = 0, i, file, whole_file = 1, status;
+ unsigned int c_byte, frag_bytes;
+ long long bbytes, file_bytes = 0, start;
+ char buff[block_size], *c_buffer = NULL, *filename = dir_ent->pathname;
struct fragment *fragment;
- struct file_info *dupl_ptr;
+ struct file_info *dupl_ptr = NULL;
struct duplicate_buffer_handle handle;
+ long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size;
+ int blocks = (read_size + block_size - 1) >> block_log, allocated_blocks = blocks;
+ unsigned int *block_list, *block_listp;
+
+ if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL)
+ BAD_ERROR("Out of memory allocating block_list\n");
+ block_listp = block_list;
if(!no_fragments && (read_size < block_size || always_use_fragments)) {
allocated_blocks = blocks = read_size >> block_log;
@@ -1023,20 +1186,19 @@ squashfs_inode write_file(char *filename, long long size, int *duplicate_file)
frag_bytes = 0;
if(size > read_size)
- ERROR("file %s truncated to %Ld bytes\n", filename, SQUASHFS_MAX_FILE_SIZE);
+ ERROR("file %s truncated to %lld bytes\n", filename, SQUASHFS_MAX_FILE_SIZE);
total_bytes += read_size;
- if((file = open(filename, O_RDONLY)) == -1) {
- perror("Error in opening file, skipping...");
- return SQUASHFS_INVALID;
- }
+ if((file = open(filename, O_RDONLY)) == -1)
+ goto read_err;
do {
- if((c_buffer = (char *) malloc((allocated_blocks + 1) << block_log)) == NULL) {
- TRACE("Out of memory allocating write_file buffer, allocated_blocks %d, blocks %d\n", allocated_blocks, blocks);
+ long long bytes = (((long long) allocated_blocks) + 1) << block_log;
+ if(bytes != ((size_t) bytes) || (c_buffer = (char *) malloc(bytes)) == NULL) {
+ TRACE("Out of memory allocating write_file buffer, allocated_blocks %ld, blocks %d\n", allocated_blocks, blocks);
whole_file = 0;
- if((allocated_blocks << (block_log - 1)) < MINALLOCBYTES)
- BAD_ERROR("Out of memory allocating write_file buffer, could not allocate %d blocks (%d Kbytes)\n", allocated_blocks, allocated_blocks << (block_log - 10));
+ if(bytes < MINALLOCBYTES)
+ BAD_ERROR("Out of memory allocating write_file buffer, could not allocate %ld blocks (%d Kbytes)\n", allocated_blocks, allocated_blocks << (block_log - 10));
allocated_blocks >>= 1;
}
} while(!c_buffer);
@@ -1089,54 +1251,19 @@ squashfs_inode write_file(char *filename, long long size, int *duplicate_file)
wr_inode:
free(c_buffer);
file_count ++;
- return create_inode(filename, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment);
+ if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1))
+ status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL);
+ else
+ status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL);
+ if(duplicate_checking == FALSE || *duplicate_file == TRUE)
+ free(block_list);
+ return status;
read_err:
perror("Error in reading file, skipping...");
free(c_buffer);
- return SQUASHFS_INVALID;
-}
-
-
-struct linuxdir {
- DIR *linuxdir;
- char pathname[8192];
-};
-
-
-void *linux_opendir(char *pathname, struct directory *dir)
-{
- struct linuxdir *linuxdir;
- if((linuxdir = malloc(sizeof(struct linuxdir))) == NULL)
- return NULL;
- if((linuxdir->linuxdir = opendir(pathname)) == NULL) {
- free(linuxdir);
- return NULL;
- }
- strcpy(linuxdir->pathname, pathname);
- return (void *) linuxdir;
-}
-
-
-int linux_readdir(void *l, char *filename, char *dir_name)
-{
- struct dirent *d_name;
- struct linuxdir *linuxdir = (struct linuxdir *)l;
-
- do {
- if((d_name = readdir(linuxdir->linuxdir)) == NULL)
- return FALSE;
- } while(strcmp(d_name->d_name, ".") == 0 || strcmp(d_name->d_name, "..") == 0);
- strcat(strcat(strcpy(filename, linuxdir->pathname), "/"), d_name->d_name);
- strcpy(dir_name, d_name->d_name);
- return TRUE;
-}
-
-
-void linux_closedir(void *linuxdir)
-{
- closedir(((struct linuxdir *)linuxdir)->linuxdir);
- free(linuxdir);
+ free(block_list);
+ return FALSE;
}
@@ -1189,100 +1316,265 @@ char *basename_r()
}
-char encomp_pathname[8192];
-int encomp_entry = 0;
+struct inode_info *lookup_inode(struct stat *buf)
+{
+ int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino);
+ struct inode_info *inode = inode_info[inode_hash];
+
+ while(inode != NULL) {
+ if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) {
+ inode->nlink ++;
+ return inode;
+ }
+ inode = inode->next;
+ }
+
+ if((inode = malloc(sizeof(struct inode_info))) == NULL)
+ BAD_ERROR("Out of memory in inode hash table entry allocation\n");
+
+ memcpy(&inode->buf, buf, sizeof(struct stat));
+ inode->inode = SQUASHFS_INVALID_BLK;
+ inode->nlink = 1;
+ if((buf->st_mode & S_IFMT) == S_IFDIR)
+ inode->inode_number = dir_inode_no ++;
+ else
+ inode->inode_number = inode_no ++;
+
+ inode->next = inode_info[inode_hash];
+ inode_info[inode_hash] = inode;
+
+ return inode;
+}
+
+
+inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir)
+{
+ if((dir->count % DIR_ENTRIES) == 0)
+ if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL)
+ BAD_ERROR("Out of memory in add_dir_entry\n");
+
+ if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL)
+ BAD_ERROR("Out of memory in linux_opendir\n");
+
+ if(sub_dir)
+ sub_dir->dir_ent = dir->list[dir->count];
+ dir->list[dir->count]->name = strdup(name);
+ dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL;
+ dir->list[dir->count]->inode = inode_info;
+ dir->list[dir->count]->dir = sub_dir;
+ dir->list[dir->count]->our_dir = dir;
+ dir->list[dir->count++]->data = data;
+ dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry);
+}
+
-void *encomp_opendir(char *pathname, struct directory *dir)
+int compare_name(const void *ent1_ptr, const void *ent2_ptr)
{
- int i;
+ struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr);
+ struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr);
+
+ return strcmp(ent1->name, ent2->name);
+}
+
+
+void sort_directory(struct dir_info *dir)
+{
+ qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name);
+
+ if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE))
+ dir->dir_is_ldir = FALSE;
+}
+
+
+struct dir_info *scan1_opendir(char *pathname)
+{
+ DIR *linuxdir;
+ struct dirent *d_name;
+ struct dir_info *dir;
- for(i = 0; i < old_root_entries; i++)
- add_dir(old_root_entry[i].inode, old_root_entry[i].name, old_root_entry[i].type, dir);
+ if((dir = malloc(sizeof(struct dir_info))) == NULL)
+ return NULL;
+
+ if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) {
+ free(dir);
+ return NULL;
+ }
+ dir->pathname = strdup(pathname);
+ dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0;
+ dir->dir_is_ldir = TRUE;
+ dir->list = NULL;
- return (void *)source_path;
+ return dir;
}
-int encomp_readdir(void *l, char *filename, char *dir_name)
+int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir)
{
+ int i, n, pass;
char *basename;
- int n, pass = 1;
+ static int index = 0;
+
+ if(dir->count < old_root_entries)
+ for(i = 0; i < old_root_entries; i++) {
+ if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
+ dir->directory_count ++;
+ add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir);
+ }
- while(encomp_entry < source) {
- if((basename = getbase(source_path[encomp_entry])) == NULL) {
- ERROR("Bad source directory %s - skipping ...\n", source_path[encomp_entry]);
- encomp_entry++;
+ while(index < source) {
+ if((basename = getbase(source_path[index])) == NULL) {
+ ERROR("Bad source directory %s - skipping ...\n", source_path[index]);
+ index ++;
continue;
}
- strcpy(filename, source_path[encomp_entry]);
strcpy(dir_name, basename);
+ pass = 1;
for(;;) {
- for(n = 0; n < old_root_entries && strcmp(old_root_entry[n].name, dir_name) != 0; n++);
- if(n == old_root_entries) {
- add_old_root_entry(dir_name, 0, 0);
- encomp_entry++;
- return TRUE;
- }
+ for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++);
+ if(n == dir->count)
+ break;
ERROR("Source directory entry %s already used! - trying ", dir_name);
sprintf(dir_name, "%s_%d", basename, pass++);
ERROR("%s\n", dir_name);
}
+ strcpy(pathname, source_path[index ++]);
+ return 1;
}
- return FALSE;
+ return 0;
+}
+
+
+int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir)
+{
+ struct dirent *d_name;
+ int i, pass;
+
+ if(dir->count < old_root_entries)
+ for(i = 0; i < old_root_entries; i++) {
+ if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
+ dir->directory_count ++;
+ add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir);
+ }
+
+ if((d_name = readdir(dir->linuxdir)) != NULL) {
+ strcpy(dir_name, d_name->d_name);
+ pass = 1;
+ for(;;) {
+ for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++);
+ if(i == dir->count)
+ break;
+ ERROR("Source directory entry %s already used! - trying ", dir_name);
+ sprintf(dir_name, "%s_%d", d_name->d_name, pass++);
+ ERROR("%s\n", dir_name);
+ }
+ strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name);
+ return 1;
+ }
+
+ return 0;
}
-void encomp_closedir(void *linuxdir)
+int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir)
{
+ struct dirent *d_name;
+
+ if((d_name = readdir(dir->linuxdir)) != NULL) {
+ strcpy(dir_name, d_name->d_name);
+ strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name);
+ return 1;
+ }
+
+ return 0;
}
-void *single_opendir(char *pathname, struct directory *dir)
+struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info)
{
- encomp_opendir(pathname, dir);
- return linux_opendir(pathname, dir);
+ int current_count;
+
+ while((current_count = dir_info->current_count++) < dir_info->count)
+ if(dir_info->list[current_count]->data)
+ add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number,
+ dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir);
+ else
+ return dir_info->list[current_count];
+ return FALSE;
}
-int single_readdir(void *l, char *filename, char *dir_name)
+void scan1_freedir(struct dir_info *dir)
{
- int i, pass = 1;
- char name[SQUASHFS_NAME_LEN + 1];
+ if(dir->pathname[0] != '\0')
+ closedir(dir->linuxdir);
+}
- if(linux_readdir(l, filename, dir_name) == FALSE)
- return FALSE;
- strcpy(name, dir_name);
- for(;;) {
- for(i = 0; i < old_root_entries && strcmp(old_root_entry[i].name, dir_name) != 0; i++);
- if(i == old_root_entries) {
- add_old_root_entry(dir_name, 0, 0);
- return TRUE;
- }
- ERROR("Source directory entry %s already used! - trying ", dir_name);
- sprintf(dir_name, "%s_%d", name, pass++);
- ERROR("%s\n", dir_name);
+void scan2_freedir(struct directory *dir)
+{
+ if(dir->index)
+ free(dir->index);
+ free(dir->buff);
+}
+
+
+void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *))
+{
+ struct dir_info *dir_info = dir_scan1(pathname, _readdir);
+ struct dir_ent *dir_ent;
+ struct inode_info *inode_info;
+
+ if(dir_info == NULL)
+ return;
+
+ if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL)
+ BAD_ERROR("Out of memory in dir_scan\n");
+
+ if((inode_info = malloc(sizeof(struct inode_info))) == NULL)
+ BAD_ERROR("Out of memory in dir_scan\n");
+
+ dir_ent->name = dir_ent->pathname = strdup(pathname);
+ dir_ent->dir = dir_info;
+ dir_ent->inode = inode_info;
+ dir_ent->our_dir = NULL;
+ dir_ent->data = NULL;
+ inode_info->nlink = 1;
+ inode_info->inode_number = root_inode_number ? root_inode_number : dir_inode_no++;
+ dir_info->dir_ent = dir_ent;
+
+ if(pathname[0] == '\0') {
+ /* dummy top level directory, if multiple sources specified on command line */
+ inode_info->buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO;
+ inode_info->buf.st_uid = getuid();
+ inode_info->buf.st_gid = getgid();
+ inode_info->buf.st_mtime = time(NULL);
+ } else if(lstat(pathname, &inode_info->buf) == -1) {
+ char buffer[8192];
+ sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname);
+ perror(buffer);
+ return;
}
+ if(sorted)
+ sort_files_and_write(dir_info);
+ dir_scan2(inode, dir_info);
}
-squashfs_inode dir_scan(char *pathname, void* (_opendir)(char *, struct directory *), int (_readdir)(void *, char *, char *),
- void (_closedir)(void *))
+struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *))
{
- void *linuxdir;
+ struct dir_info *dir, *sub_dir;
struct stat buf;
char filename[8192], dir_name[8192];
- int squashfs_type;
- squashfs_inode inode = SQUASHFS_INVALID;
- struct directory dir;
-
- init_dir(&dir);
- if((linuxdir = _opendir(pathname, &dir)) == NULL) {
+
+ if((dir = scan1_opendir(pathname)) == NULL) {
ERROR("Could not open %s, skipping...\n", pathname);
goto error;
}
-
- while(_readdir(linuxdir, filename, dir_name) != FALSE) {
+
+ while(_readdir(filename, dir_name, dir) != FALSE) {
+
+ if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)
+ continue;
if(lstat(filename, &buf) == -1) {
char buffer[8192];
@@ -1293,75 +1585,135 @@ squashfs_inode dir_scan(char *pathname, void* (_opendir)(char *, struct director
if(excluded(filename, &buf))
continue;
- switch(buf.st_mode & S_IFMT) {
- case S_IFREG: {
- int duplicate_file;
+ if((buf.st_mode & S_IFMT) == S_IFDIR) {
+ if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL)
+ continue;
+ dir->directory_count ++;
+ } else
+ sub_dir = NULL;
- squashfs_type = SQUASHFS_FILE_TYPE;
- if(!sorted) {
- inode = write_file(filename, buf.st_size, &duplicate_file);
- INFO("file %s, uncompressed size %Ld bytes, %s\n", filename, buf.st_size, duplicate_file ? "DUPLICATE" : "");
- } else
- inode = get_sorted_inode(&buf);
- break;
- }
- case S_IFDIR:
- squashfs_type = SQUASHFS_DIR_TYPE;
- inode = dir_scan(filename, linux_opendir, linux_readdir, linux_closedir);
- break;
+ add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir);
+ }
- case S_IFLNK:
- squashfs_type = SQUASHFS_SYMLINK_TYPE;
- inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL);
- INFO("symbolic link %s inode 0x%Lx\n", dir_name, inode);
- sym_count ++;
- break;
+ scan1_freedir(dir);
+ sort_directory(dir);
- case S_IFCHR:
- squashfs_type = SQUASHFS_CHRDEV_TYPE;
- inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL);
- INFO("character device %s inode 0x%Lx\n", dir_name, inode);
- dev_count ++;
- break;
+error:
+ return dir;
+}
- case S_IFBLK:
- squashfs_type = SQUASHFS_BLKDEV_TYPE;
- inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL);
- INFO("block device %s inode 0x%Lx\n", dir_name, inode);
- dev_count ++;
- break;
- case S_IFIFO:
- squashfs_type = SQUASHFS_FIFO_TYPE;
- inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL);
- INFO("fifo %s inode 0x%Lx\n", dir_name, inode);
- fifo_count ++;
- break;
+int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info)
+{
+ int squashfs_type;
+ int result = FALSE;
+ int duplicate_file;
+ char *pathname = dir_info->pathname;
+ struct directory dir;
+ struct dir_ent *dir_ent;
+
+ scan2_init_dir(&dir);
+
+ while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) {
+ struct inode_info *inode_info = dir_ent->inode;
+ struct stat *buf = &inode_info->buf;
+ char *filename = dir_ent->pathname;
+ char *dir_name = dir_ent->name;
+ unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no;
+
+ if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) {
+ switch(buf->st_mode & S_IFMT) {
+ case S_IFREG:
+ squashfs_type = SQUASHFS_FILE_TYPE;
+ result = write_file(inode, dir_ent, buf->st_size, &duplicate_file);
+ INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : "");
+ break;
- case S_IFSOCK:
- squashfs_type = SQUASHFS_SOCKET_TYPE;
- inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL);
- INFO("unix domain socket %s inode 0x%Lx\n", dir_name, inode);
- sock_count ++;
- break;
+ case S_IFDIR:
+ squashfs_type = SQUASHFS_DIR_TYPE;
+ result = dir_scan2(inode, dir_ent->dir);
+ break;
- default:
- ERROR("%s unrecognised file type, mode is %x\n", filename, buf.st_mode);
- continue;
+ case S_IFLNK:
+ squashfs_type = SQUASHFS_SYMLINK_TYPE;
+ result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL);
+ INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode);
+ sym_count ++;
+ break;
+
+ case S_IFCHR:
+ squashfs_type = SQUASHFS_CHRDEV_TYPE;
+ result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL);
+ INFO("character device %s inode 0x%llx\n", dir_name, *inode);
+ dev_count ++;
+ break;
+
+ case S_IFBLK:
+ squashfs_type = SQUASHFS_BLKDEV_TYPE;
+ result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL);
+ INFO("block device %s inode 0x%llx\n", dir_name, *inode);
+ dev_count ++;
+ break;
+
+ case S_IFIFO:
+ squashfs_type = SQUASHFS_FIFO_TYPE;
+ result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL);
+ INFO("fifo %s inode 0x%llx\n", dir_name, *inode);
+ fifo_count ++;
+ break;
+
+ case S_IFSOCK:
+ squashfs_type = SQUASHFS_SOCKET_TYPE;
+ result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL);
+ INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode);
+ sock_count ++;
+ break;
+
+ default:
+ ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode);
+ result = FALSE;
+ }
+ if(result)
+ dir_ent->inode->inode = *inode;
+ dir_ent->inode->type = squashfs_type;
+ } else {
+ *inode = dir_ent->inode->inode;
+ squashfs_type = dir_ent->inode->type;
+ switch(squashfs_type) {
+ case SQUASHFS_FILE_TYPE:
+ if(!sorted)
+ INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size);
+ break;
+ case SQUASHFS_SYMLINK_TYPE:
+ INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode);
+ break;
+ case SQUASHFS_CHRDEV_TYPE:
+ INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode);
+ break;
+ caseSQUASHFS_BLKDEV_TYPE:
+ INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode);
+ break;
+ case SQUASHFS_FIFO_TYPE:
+ INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode);
+ break;
+ case SQUASHFS_SOCKET_TYPE:
+ INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode);
+ break;
}
+ result = TRUE;
+ }
+
- if(inode != SQUASHFS_INVALID)
- add_dir(inode, dir_name, squashfs_type, &dir);
+ if(result)
+ add_dir(*inode, inode_number, dir_name, squashfs_type, &dir);
}
- _closedir(linuxdir);
- inode = write_dir(pathname, &dir);
- INFO("directory %s inode 0x%Lx\n", pathname, inode);
+ result = write_dir(inode, dir_info, &dir);
+ INFO("directory %s inode 0x%llx\n", pathname, *inode);
-error:
- free(dir.buff);
+ scan2_freedir(&dir);
- return inode;
+ return result;
}
@@ -1369,7 +1721,7 @@ unsigned int slog(unsigned int block)
{
int i;
- for(i = 9; i <= 16; i++)
+ for(i = 12; i <= 16; i++)
if(block == (1 << i))
return i;
return 0;
@@ -1425,7 +1777,7 @@ int add_exclude(char *path)
}
-void add_old_root_entry(char *name, squashfs_inode inode, int type)
+void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type)
{
if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info)
* (old_root_entries + 1))) == NULL)
@@ -1433,13 +1785,14 @@ void add_old_root_entry(char *name, squashfs_inode inode, int type)
strcpy(old_root_entry[old_root_entries].name, name);
old_root_entry[old_root_entries].inode = inode;
+ old_root_entry[old_root_entries].inode_number = inode_number;
old_root_entry[old_root_entries++].type = type;
}
#define VERSION() \
- printf("mksquashfs version 2.0\n");\
- printf("copyright (C) 2004 Phillip Lougher (plougher@users.sourceforge.net)\n\n"); \
+ printf("mksquashfs version 3.0 (2006/03/15)\n");\
+ printf("copyright (C) 2006 Phillip Lougher <phillip@lougher.org.uk>\n\n"); \
printf("This program is free software; you can redistribute it and/or\n");\
printf("modify it under the terms of the GNU General Public License\n");\
printf("as published by the Free Software Foundation; either version 2,\n");\
@@ -1450,11 +1803,12 @@ void add_old_root_entry(char *name, squashfs_inode inode, int type)
printf("GNU General Public License for more details.\n");
int main(int argc, char *argv[])
{
- struct stat buf;
+ struct stat buf, source_buf;
int i;
squashfs_super_block sBlk;
char *b, *root_name = NULL;
- int be, nopad = FALSE, delete = FALSE, keep_as_directory = FALSE, orig_be;
+ int be, nopad = FALSE, keep_as_directory = FALSE, orig_be;
+ squashfs_inode inode;
#if __BYTE_ORDER == __BIG_ENDIAN
be = TRUE;
@@ -1480,7 +1834,7 @@ int main(int argc, char *argv[])
}
if((block_log = slog(block_size)) == 0) {
- ERROR("%s: -b block size not power of two or not between 512 and 64K\n", argv[0]);
+ ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]);
exit(1);
}
} else if(strcmp(argv[i], "-ef") == 0) {
@@ -1591,40 +1945,51 @@ int main(int argc, char *argv[])
} else {
ERROR("%s: invalid option\n\n", argv[0]);
printOptions:
- ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude dirs/files]\n", argv[0]);
+ ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]);
ERROR("\nOptions are\n");
- ERROR("\t-info\t\t\t\tprint files written to filesystem\n");
- ERROR("\t-sort sort file\t\t\tsort files according to priorities in sort file. One file or dir\n");
- ERROR("\t\t\t\t\twith priority per line. Priority -32768 to 32767, default priority 0\n");
- ERROR("\t-b block size\t\t\tsize of blocks in ");
- ERROR("filesystem, default %d\n", SQUASHFS_FILE_SIZE);
- ERROR("\t-noappend\t\t\tDo not append to existing filesystem on dest, write a new filesystem\n");
- ERROR("\t\t\t\t\tThis is the default action if dest does not exist, or if no filesystem is on it\n");
- ERROR("\t-keep-as-directory\t\tIf one source directory is specified, create a root directory\n");
- ERROR("\t\t\t\t\tcontaining that directory, rather than the contents of the directory\n");
- ERROR("\t-root-becomes name\t\tWhen appending source files/directories, make the original\n");
- ERROR("\t\t\t\t\troot become a subdirectory in the new root called name, rather\n");
- ERROR("\t\t\t\t\tthan adding the new source items to the original root\n");
- ERROR("\t-noI -noInodeCompression\tdo not compress inode table\n");
- ERROR("\t-noD -noDataCompression\t\tdo not compress data blocks\n");
- ERROR("\t-noF -noFragmentCompression\tdo not compress fragment blocks\n");
- ERROR("\t-no-duplicates\t\t\tdo not perform duplicate checking\n");
- ERROR("\t-no-fragments\t\t\tdo not use fragments\n");
- ERROR("\t-always-use-fragments\t\tuse fragment blocks for files larger than block size\n");
- ERROR("\t-nopad\t\t\t\tdo not pad filesystem to a multiple of 4K\n");
- ERROR("\t-check_data\t\t\tadd checkdata for greater filesystem checks\n");
- ERROR("\t-le\t\t\t\tcreate a little endian filesystem\n");
- ERROR("\t-be\t\t\t\tcreate a big endian filesystem\n");
- ERROR("\t-ef exclude file\t\tfile is a list of exclude dirs/files - one per line\n");
- ERROR("\t-all-root\t\t\toverride file uid/gid and make all file uid/gids owned by root\n");
- ERROR("\t-root-owned\t\t\talternative name for -all-root\n");
- ERROR("\t-force-uid uid\t\t\tset all file uids to uid\n");
- ERROR("\t-force-gid gid\t\t\tset all file gids to gid\n");
- ERROR("\t-version\t\t\tprint version, licence and copyright message\n");
+ ERROR("-version\t\tprint version, licence and copyright message\n");
+ ERROR("-info\t\t\tprint files written to filesystem\n");
+ ERROR("-b <block_size>\t\tset data block to <block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE);
+ ERROR("-noI\t\t\tdo not compress inode table\n");
+ ERROR("-noD\t\t\tdo not compress data blocks\n");
+ ERROR("-noF\t\t\tdo not compress fragment blocks\n");
+ ERROR("-no-fragments\t\tdo not use fragments\n");
+ ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n");
+ ERROR("-no-duplicates\t\tdo not perform duplicate checking\n");
+ ERROR("-noappend\t\tdo not append to existing filesystem\n");
+ ERROR("-keep-as-directory\tif one source directory is specified, create a root\n");
+ ERROR("\t\t\tdirectory containing that directory, rather than the\n");
+ ERROR("\t\t\tcontents of the directory\n");
+ ERROR("-root-becomes <name>\twhen appending source files/directories, make the\n");
+ ERROR("\t\t\toriginal root become a subdirectory in the new root\n");
+ ERROR("\t\t\tcalled <name>, rather than adding the new source items\n");
+ ERROR("\t\t\tto the original root\n");
+ ERROR("-all-root\t\tmake all files owned by root\n");
+ ERROR("-force-uid uid\t\tset all file uids to uid\n");
+ ERROR("-force-gid gid\t\tset all file gids to gid\n");
+ ERROR("-le\t\t\tcreate a little endian filesystem\n");
+ ERROR("-be\t\t\tcreate a big endian filesystem\n");
+ ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n");
+ ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n");
+ ERROR("-root-owned\t\talternative name for -all-root\n");
+ ERROR("-noInodeCompression\talternative name for -noI\n");
+ ERROR("-noDataCompression\talternative name for -noD\n");
+ ERROR("-noFragmentCompression\talternative name for -noF\n");
+ ERROR("-sort <sort_file>\tsort files according to priorities in <sort_file>. One\n");
+ ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n");
+ ERROR("\t\t\t32767, default priority 0\n");
+ ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n");
exit(1);
}
}
+ for(i = 0; i < source; i++)
+ if(stat(source_path[i], &source_buf) == -1) {
+ fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno));
+ EXIT_MKSQUASHFS();
+ }
+
+ destination_file = argv[source + 1];
if(stat(argv[source + 1], &buf) == -1) {
if(errno == ENOENT) { /* Does not exist */
if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) {
@@ -1656,19 +2021,16 @@ printOptions:
exit(1);
}
- if(!delete) {
- if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) {
- if(S_ISREG(buf.st_mode)) { /* reopen truncating file */
- close(fd);
- if((fd = open(argv[source + 1], O_TRUNC | O_RDWR)) == -1) {
- perror("Could not open regular file for writing as destination");
- exit(1);
- }
- }
- delete = TRUE;
- }
+ }
+ if(!delete) {
+ if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) {
+ ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n");
+ EXIT_MKSQUASHFS();
}
+ } else {
+ signal(SIGTERM, sighandler2);
+ signal(SIGINT, sighandler2);
}
/* process the exclude files - must be done afer destination file has been possibly created */
@@ -1678,7 +2040,7 @@ printOptions:
char filename[16385];
if((fd = fopen(argv[++i], "r")) == NULL) {
perror("Could not open exclude file...");
- exit(1);
+ EXIT_MKSQUASHFS();
}
while(fscanf(fd, "%16384[^\n]\n", filename) != EOF)
add_exclude(filename);
@@ -1691,7 +2053,7 @@ printOptions:
if(i != argc) {
if(++i == argc) {
ERROR("%s: -e missing arguments\n", argv[0]);
- exit(1);
+ EXIT_MKSQUASHFS();
}
while(i < argc && add_exclude(argv[i++]));
}
@@ -1706,14 +2068,17 @@ printOptions:
else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0)
i++;
- if((fragment_data = (char *) malloc(block_size)) == NULL)
- BAD_ERROR("Out of memory allocating fragment_data");
-
if(delete) {
- printf("Creating %s filesystem on %s, block size %d.\n",
- be ? "big endian" : "little endian", argv[source + 1], block_size);
+ printf("Creating %s %d.%d filesystem on %s, block size %d.\n",
+ be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size);
bytes = sizeof(squashfs_super_block);
} else {
+ unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size,
+ inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number,
+ inode_dir_parent_inode;
+ unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset =
+ SQUASHFS_INODE_OFFSET(sBlk.root_inode);
+
be = orig_be;
block_log = slog(block_size = sBlk.block_size);
noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags);
@@ -1724,47 +2089,48 @@ printOptions:
always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags);
duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags);
- fragments = SQUASHFS_INVALID_BLK;
- if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &inode_bytes, &data_cache,
- &cache_bytes, &cache_size, &directory_table, &directory_bytes,
- &directory_data_cache, &directory_cache_bytes, &directory_cache_size,
- &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count,
- (squashfs_uid *) guids, &guid_count,
- &total_bytes, &total_inode_bytes, &total_directory_bytes, add_old_root_entry, &fragment_table)) == 0) {
+ if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache,
+ &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset,
+ &inode_dir_file_size, &root_inode_size, &inode_dir_start_block,
+ &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count,
+ (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count,
+ &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number,
+ &inode_dir_parent_inode, add_old_root_entry, &fragment_table)) == 0) {
ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n");
- exit(1);
+ EXIT_MKSQUASHFS();
}
if((fragments = sBlk.fragments))
fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry));
- printf("Appending to existing %s squashfs filesystem on %s, block size %d\n", be ? "big endian" :
- "little endian", argv[source + 1], block_size);
- printf("All -be, -le, -b, -noI, noD, noF, -check_data, no-duplicates, no-fragments and always-use-fragments options ignored\n");
+ printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" :
+ "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size);
+ printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -2.0 options ignored\n");
printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n");
- inode_size = inode_bytes;
- directory_size = directory_bytes;
-
+ compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1);
+ uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1);
+
/* save original filesystem state for restoring ... */
sfragments = fragments;
sbytes = bytes;
sinode_count = sBlk.inodes;
- inode_count = file_count + dir_count + sym_count + dev_count;
- sdata_cache = (char *)malloc(scache_bytes = cache_size);
- sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = directory_cache_size);
+ sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size);
+ sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data);
memcpy(sdata_cache, data_cache, scache_bytes);
- memcpy(sdirectory_data_cache, directory_data_cache, sdirectory_cache_bytes);
- sinode_bytes = inode_bytes;
- sdirectory_bytes = directory_bytes;
+ memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes);
+ sinode_bytes = root_inode_start;
+ sdirectory_bytes = last_directory_block;
suid_count = uid_count;
sguid_count = guid_count;
stotal_bytes = total_bytes;
stotal_inode_bytes = total_inode_bytes;
- stotal_directory_bytes = total_directory_bytes;
+ stotal_directory_bytes = total_directory_bytes + compressed_data;
sfile_count = file_count;
ssym_count = sym_count;
sdev_count = dev_count;
- sdir_count = dir_count;
+ sdir_count = dir_count + 1;
+ sfifo_count = fifo_count;
+ ssock_count = sock_count;
sdup_files = dup_files;
restore = TRUE;
if(setjmp(env))
@@ -1772,6 +2138,34 @@ printOptions:
signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0");
+
+ /* set the filesystem state up to be able to append to the original filesystem. The filesystem state
+ * differs depending on whether we're appending to the original root directory, or if the original
+ * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL)
+ */
+ inode_bytes = inode_size = root_inode_start;
+ directory_size = last_directory_block;
+ cache_size = root_inode_offset + root_inode_size;
+ directory_cache_size = inode_dir_offset + inode_dir_file_size;
+ if(root_name) {
+ root_inode_number = inode_dir_parent_inode;
+ dir_inode_no = sBlk.inodes + 2;
+ directory_bytes = last_directory_block;
+ directory_cache_bytes = uncompressed_data;
+ memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data);
+ cache_bytes = root_inode_offset + root_inode_size;
+ add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE);
+ total_directory_bytes += compressed_data;
+ dir_count ++;
+ } else {
+ root_inode_number = inode_dir_inode_number;
+ dir_inode_no = sBlk.inodes + 1;
+ directory_bytes = inode_dir_start_block;
+ directory_cache_bytes = inode_dir_offset;
+ cache_bytes = root_inode_offset;
+ }
+
+ inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count;
}
#if __BYTE_ORDER == __BIG_ENDIAN
@@ -1782,20 +2176,13 @@ printOptions:
block_offset = check_data ? 3 : 2;
- if(stat(source_path[0], &buf) == -1) {
- perror("Cannot stat source directory");
- EXIT_MKSQUASHFS();
- }
-
- if(sorted)
- sort_files_and_write(source, source_path);
-
- if(delete && !keep_as_directory && source == 1 && S_ISDIR(buf.st_mode))
- sBlk.root_inode = dir_scan(source_path[0], linux_opendir, linux_readdir, linux_closedir);
- else if(!keep_as_directory && source == 1 && S_ISDIR(buf.st_mode))
- sBlk.root_inode = dir_scan(source_path[0], single_opendir, single_readdir, linux_closedir);
+ if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode))
+ dir_scan(&inode, source_path[0], scan1_readdir);
+ else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode))
+ dir_scan(&inode, source_path[0], scan1_single_readdir);
else
- sBlk.root_inode = dir_scan("", encomp_opendir, encomp_readdir, encomp_closedir);
+ dir_scan(&inode, "", scan1_encomp_readdir);
+ sBlk.root_inode = inode;
sBlk.inodes = inode_count;
sBlk.s_magic = SQUASHFS_MAGIC;
sBlk.s_major = SQUASHFS_MAJOR;
@@ -1846,6 +2233,8 @@ restore_filesystem:
sBlk.bytes_used = bytes;
+ sBlk.unused = SQUASHFS_INVALID_BLK;
+
if(!swap)
write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk);
else {
@@ -1856,7 +2245,7 @@ restore_filesystem:
}
if(!nopad && (i = bytes & (4096 - 1))) {
- unsigned char temp[4096] = {0};
+ char temp[4096] = {0};
write_bytes(fd, bytes, 4096 - i, temp);
}
@@ -1865,7 +2254,7 @@ restore_filesystem:
sizeof(squashfs_super_block);
printf("\n%s filesystem, data block size %d, %s data, %s metadata, %s fragments\n", be ?
- "Big endian" : "Little endian", block_size, noI ? "uncompressed" : "compressed", noD ?
+ "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ?
"uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed");
printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0));
printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n",
diff --git a/release/src/linux/linux/scripts/squashfs/mksquashfs.h b/release/src/linux/linux/scripts/squashfs/mksquashfs.h
index b3d2e441..680bb388 100644
--- a/release/src/linux/linux/scripts/squashfs/mksquashfs.h
+++ b/release/src/linux/linux/scripts/squashfs/mksquashfs.h
@@ -3,7 +3,8 @@
* endian and vice versa. These are needed when creating a filesystem on a
* machine with different byte ordering to the target architecture.
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.demon.co.uK>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/release/src/linux/linux/scripts/squashfs/read_fs.c b/release/src/linux/linux/scripts/squashfs/read_fs.c
index cdb62a75..46f4a4e4 100644
--- a/release/src/linux/linux/scripts/squashfs/read_fs.c
+++ b/release/src/linux/linux/scripts/squashfs/read_fs.c
@@ -1,7 +1,8 @@
/*
* Read a squashfs filesystem. This is a highly compressed read only filesystem.
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,8 +21,8 @@
* read_fs.c
*/
-extern void read_bytes(int, unsigned int, int, char *);
-extern int add_file(int, int, unsigned int *, int, unsigned int, int, int);
+extern void read_bytes(int, long long, int, char *);
+extern int add_file(long long, long long, unsigned int *, int, unsigned int, int, int);
#define TRUE 1
#define FALSE 0
@@ -34,29 +35,41 @@ extern int add_file(int, int, unsigned int *, int, unsigned int, int, int);
#include <zlib.h>
#include <sys/mman.h>
+#ifndef linux
+#define __BYTE_ORDER BYTE_ORDER
+#define __BIG_ENDIAN BIG_ENDIAN
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#else
#include <endian.h>
-#include "read_fs.h"
+#endif
+
#include <squashfs_fs.h>
+#include "read_fs.h"
+#include "global.h"
#include <stdlib.h>
#ifdef SQUASHFS_TRACE
-#define TRACE(s, args...) printf("mksquashfs: "s, ## args)
+#define TRACE(s, args...) do { \
+ printf("mksquashfs: "s, ## args); \
+ } while(0)
#else
#define TRACE(s, args...)
#endif
-#define ERROR(s, args...) fprintf(stderr, s, ## args)
+#define ERROR(s, args...) do { \
+ fprintf(stderr, s, ## args); \
+ } while(0)
int swap;
-int read_block(int fd, int start, int *next, unsigned char *block, squashfs_super_block *sBlk)
+int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk)
{
unsigned short c_byte;
int offset = 2;
if(swap) {
- read_bytes(fd, start, 2, block);
+ read_bytes(fd, start, 2, (char *) block);
((unsigned char *) &c_byte)[1] = block[0];
((unsigned char *) &c_byte)[0] = block[1];
} else
@@ -65,14 +78,14 @@ int read_block(int fd, int start, int *next, unsigned char *block, squashfs_supe
if(SQUASHFS_CHECK_DATA(sBlk->flags))
offset = 3;
if(SQUASHFS_COMPRESSED(c_byte)) {
- unsigned char buffer[SQUASHFS_METADATA_SIZE];
+ char buffer[SQUASHFS_METADATA_SIZE];
int res;
- long bytes = SQUASHFS_METADATA_SIZE;
+ unsigned long bytes = SQUASHFS_METADATA_SIZE;
c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
read_bytes(fd, start + offset, c_byte, buffer);
- if((res = uncompress(block, &bytes, (const char *) buffer, c_byte)) != Z_OK) {
+ if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) {
if(res == Z_MEM_ERROR)
ERROR("zlib::uncompress failed, not enough memory\n");
else if(res == Z_BUF_ERROR)
@@ -86,7 +99,7 @@ int read_block(int fd, int start, int *next, unsigned char *block, squashfs_supe
return bytes;
} else {
c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
- read_bytes(fd, start + offset, c_byte, block);
+ read_bytes(fd, start + offset, c_byte, (char *) block);
if(next)
*next = start + offset + c_byte;
return c_byte;
@@ -94,30 +107,32 @@ int read_block(int fd, int start, int *next, unsigned char *block, squashfs_supe
}
-int scan_inode_table(int fd, int start, int end, int root_inode_start, squashfs_super_block *sBlk,
- squashfs_dir_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block,
- unsigned int *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count,
- int *dev_count, int *dir_count, int *fifo_count, int *sock_count)
+int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset,
+ squashfs_super_block *sBlk,
+ squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block,
+ unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory,
+ int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count)
{
unsigned char *cur_ptr;
- int bytes = 0, size = 0, files = 0;
+ int byte, bytes = 0, size = 0, files = 0;
squashfs_reg_inode_header inode;
unsigned int directory_start_block;
- TRACE("scan_inode_table: start 0x%x, end 0x%x, root_inode_start 0x%x\n", start, end, root_inode_start);
+ TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start);
while(start < end) {
if(start == root_inode_start) {
- TRACE("scan_inode_table: read compressed block 0x%x containing root inode\n", start);
+ TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start);
*root_inode_block = bytes;
}
if((size - bytes < SQUASHFS_METADATA_SIZE) &&
((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL))
return FALSE;
- TRACE("scan_inode_table: reading block 0x%x\n", start);
- if((bytes += read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) {
+ TRACE("scan_inode_table: reading block 0x%llx\n", start);
+ if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) {
free(*inode_table);
return FALSE;
}
+ bytes += byte;
}
/*
@@ -128,43 +143,112 @@ int scan_inode_table(int fd, int start, int end, int root_inode_start, squashfs_
* The root inode is ignored in the inode scan. This ensures there is
* always enough bytes left to read a regular file inode entry
*/
- bytes -= sizeof(squashfs_dir_inode_header);
+ *root_inode_size = bytes - (*root_inode_block + root_inode_offset);
+ bytes = *root_inode_block + root_inode_offset;
if(swap) {
- squashfs_dir_inode_header sinode;
- memcpy((void *)&sinode, (void *)(*inode_table + bytes), sizeof(*dir_inode));
- SQUASHFS_SWAP_DIR_INODE_HEADER(dir_inode, &sinode);
+ squashfs_base_inode_header sinode;
+ memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base));
+ SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header));
} else
- memcpy((void *)dir_inode, (void *)(*inode_table + bytes), sizeof(*dir_inode));
- directory_start_block = dir_inode->start_block;
+ memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base));
+ if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) {
+ if(swap) {
+ squashfs_dir_inode_header sinode;
+ memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir));
+ SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode);
+ } else
+ memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir));
+ directory_start_block = dir_inode->dir.start_block;
+ } else {
+ if(swap) {
+ squashfs_ldir_inode_header sinode;
+ memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir));
+ SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode);
+ } else
+ memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir));
+ directory_start_block = dir_inode->ldir.start_block;
+ }
for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) {
if(swap) {
squashfs_reg_inode_header sinode;
- memcpy((void *)&sinode, (void *)cur_ptr, sizeof(inode));
+ memcpy(&sinode, cur_ptr, sizeof(inode));
SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode);
} else
- memcpy((void *)&inode, (void *)cur_ptr, sizeof(inode));
+ memcpy(&inode, cur_ptr, sizeof(inode));
TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table,
inode.inode_type);
switch(inode.inode_type) {
case SQUASHFS_FILE_TYPE: {
- int frag_bytes = inode.fragment == SQUASHFS_INVALID_BLK ? 0 : inode.file_size % sBlk->block_size;
- int blocks = inode.fragment == SQUASHFS_INVALID_BLK ? (inode.file_size
+ int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size;
+ int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size
+ sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >>
sBlk->block_log;
- int file_bytes = 0, i, start = inode.start_block;
- unsigned int block_list[blocks];
+ long long file_bytes = 0;
+ int i, start = inode.start_block;
+ unsigned int *block_list;
+
+ TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks);
+
+ if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) {
+ ERROR("Out of memory in block list malloc\n");
+ goto failed;
+ }
+
+ cur_ptr += sizeof(inode);
+ if(swap) {
+ unsigned int sblock_list[blocks];
+ memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int));
+ SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks);
+ } else
+ memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int));
+
+ *uncompressed_file += inode.file_size;
+ (*file_count) ++;
+
+ for(i = 0; i < blocks; i++)
+ file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]);
+
+ add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes);
+ cur_ptr += blocks * sizeof(unsigned int);
+ break;
+ }
+ case SQUASHFS_LREG_TYPE: {
+ squashfs_lreg_inode_header inode;
+ int frag_bytes;
+ int blocks;
+ long long file_bytes = 0;
+ int i, start;
+ unsigned int *block_list;
- TRACE("scan_inode_table: regular file, file_size %d, blocks %d\n", inode.file_size, blocks);
+ if(swap) {
+ squashfs_lreg_inode_header sinodep;
+ memcpy(&sinodep, cur_ptr, sizeof(sinodep));
+ SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep);
+ } else
+ memcpy(&inode, cur_ptr, sizeof(inode));
+
+ TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks);
cur_ptr += sizeof(inode);
+ frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size;
+ blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size
+ + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >>
+ sBlk->block_log;
+ start = inode.start_block;
+
+ if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) {
+ ERROR("Out of memory in block list malloc\n");
+ goto failed;
+ }
+
if(swap) {
unsigned int sblock_list[blocks];
- memcpy((void *)sblock_list, (void *)cur_ptr, blocks * sizeof(unsigned int));
+ memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int));
SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks);
} else
- memcpy((void *)block_list, (void *)cur_ptr, blocks * sizeof(unsigned int));
+ memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int));
*uncompressed_file += inode.file_size;
(*file_count) ++;
@@ -181,10 +265,10 @@ int scan_inode_table(int fd, int start, int end, int root_inode_start, squashfs_
if(swap) {
squashfs_symlink_inode_header sinodep;
- memcpy((void *)&sinodep, (void *)cur_ptr, sizeof(sinodep));
+ memcpy(&sinodep, cur_ptr, sizeof(sinodep));
SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep);
} else
- memcpy((void *)&inodep, (void *)cur_ptr, sizeof(inodep));
+ memcpy(&inodep, cur_ptr, sizeof(inodep));
(*sym_count) ++;
cur_ptr += sizeof(inodep) + inodep.symlink_size;
break;
@@ -194,16 +278,42 @@ int scan_inode_table(int fd, int start, int end, int root_inode_start, squashfs_
if(swap) {
squashfs_dir_inode_header sinode;
- memcpy((void *)&sinode, (void *)cur_ptr, sizeof(dir_inode));
+ memcpy(&sinode, cur_ptr, sizeof(dir_inode));
SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode);
} else
- memcpy((void *)&dir_inode, (void *)cur_ptr, sizeof(dir_inode));
+ memcpy(&dir_inode, cur_ptr, sizeof(dir_inode));
if(dir_inode.start_block < directory_start_block)
*uncompressed_directory += dir_inode.file_size;
(*dir_count) ++;
cur_ptr += sizeof(squashfs_dir_inode_header);
break;
}
+ case SQUASHFS_LDIR_TYPE: {
+ squashfs_ldir_inode_header dir_inode;
+ int i;
+
+ if(swap) {
+ squashfs_ldir_inode_header sinode;
+ memcpy(&sinode, cur_ptr, sizeof(dir_inode));
+ SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode);
+ } else
+ memcpy(&dir_inode, cur_ptr, sizeof(dir_inode));
+ if(dir_inode.start_block < directory_start_block)
+ *uncompressed_directory += dir_inode.file_size;
+ (*dir_count) ++;
+ cur_ptr += sizeof(squashfs_ldir_inode_header);
+ for(i = 0; i < dir_inode.i_count; i++) {
+ squashfs_dir_index index;
+ if(swap) {
+ squashfs_dir_index sindex;
+ memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index));
+ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
+ } else
+ memcpy(&index, cur_ptr, sizeof(squashfs_dir_index));
+ cur_ptr += sizeof(squashfs_dir_index) + index.size + 1;
+ }
+ break;
+ }
case SQUASHFS_BLKDEV_TYPE:
case SQUASHFS_CHRDEV_TYPE:
(*dev_count) ++;
@@ -220,12 +330,16 @@ int scan_inode_table(int fd, int start, int end, int root_inode_start, squashfs_
break;
default:
ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type);
- free(*inode_table);
- return FALSE;
+ goto failed;
}
}
return files;
+
+
+failed:
+ free(*inode_table);
+ return FALSE;
}
@@ -250,11 +364,11 @@ int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source)
/* Check the MAJOR & MINOR versions */
if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
- if(sBlk->s_major == 1)
- ERROR("Filesystem on %s is a SQUASHFS 1.x filesystem. Appending\nto SQUASHFS 1.x filesystems is not supported. Please convert it to a SQUASHFS 2.0 filesystem...n", source);
+ if(sBlk->s_major < 3)
+ ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor);
else
- ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d), I support (%d: <= %d)\n",
- source, sBlk->s_major, sBlk->s_minor, SQUASHFS_MAJOR, SQUASHFS_MINOR);
+ ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n",
+ source, sBlk->s_major, sBlk->s_minor);
goto failed_mount;
}
@@ -272,16 +386,16 @@ int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source)
printf("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : "");
printf("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not");
printf("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not");
- printf("\tFilesystem size %d bytes\n", sBlk->bytes_used);
+ printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0));
printf("\tBlock size %d\n", sBlk->block_size);
printf("\tNumber of fragments %d\n", sBlk->fragments);
printf("\tNumber of inodes %d\n", sBlk->inodes);
printf("\tNumber of uids %d\n", sBlk->no_uids);
printf("\tNumber of gids %d\n", sBlk->no_guids);
- TRACE("sBlk->inode_table_start %x\n", sBlk->inode_table_start);
- TRACE("sBlk->directory_table_start %x\n", sBlk->directory_table_start);
- TRACE("sBlk->uid_start %x\n", sBlk->uid_start);
- TRACE("sBlk->fragment_table_start %x\n", sBlk->fragment_table_start);
+ TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start);
+ TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start);
+ TRACE("sBlk->uid_start %llx\n", sBlk->uid_start);
+ TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start);
printf("\n");
return TRUE;
@@ -291,24 +405,27 @@ failed_mount:
}
-unsigned char *squashfs_readdir(int fd, int root_entries, int start, int offset, int size, squashfs_super_block *sBlk,
- void (push_directory_entry)(char *, squashfs_inode, int))
+unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size,
+ unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int))
{
squashfs_dir_header dirh;
char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
unsigned char *directory_table = NULL;
- int bytes = 0, dir_count;
+ int byte, bytes = 0, dir_count;
+ long long start = sBlk->directory_table_start + directory_start_block, last_start_block;
size += offset;
if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL)
return NULL;
while(bytes < size) {
- TRACE("squashfs_readdir: reading block 0x%x, bytes read so far %d\n", start, bytes);
- if((bytes += read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) {
+ TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes);
+ last_start_block = start;
+ if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) {
free(directory_table);
return NULL;
}
+ bytes += byte;
}
if(!root_entries)
@@ -318,10 +435,10 @@ unsigned char *squashfs_readdir(int fd, int root_entries, int start, int offset,
while(bytes < size) {
if(swap) {
squashfs_dir_header sdirh;
- memcpy((void *)&sdirh, directory_table + bytes, sizeof(sdirh));
+ memcpy(&sdirh, directory_table + bytes, sizeof(sdirh));
SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
} else
- memcpy((void *)&dirh, directory_table + bytes, sizeof(dirh));
+ memcpy(&dirh, directory_table + bytes, sizeof(dirh));
dir_count = dirh.count + 1;
TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count);
@@ -330,21 +447,22 @@ unsigned char *squashfs_readdir(int fd, int root_entries, int start, int offset,
while(dir_count--) {
if(swap) {
squashfs_dir_entry sdire;
- memcpy((void *)&sdire, directory_table + bytes, sizeof(sdire));
+ memcpy(&sdire, directory_table + bytes, sizeof(sdire));
SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
} else
- memcpy((void *)dire, directory_table + bytes, sizeof(dire));
+ memcpy(dire, directory_table + bytes, sizeof(dire));
bytes += sizeof(*dire);
- memcpy((void *)dire->name, directory_table + bytes, dire->size + 1);
+ memcpy(dire->name, directory_table + bytes, dire->size + 1);
dire->name[dire->size + 1] = '\0';
TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type);
- push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dire->type);
+ push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dire->inode_number, dire->type);
bytes += dire->size + 1;
}
}
all_done:
+ *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start;
return directory_table;
}
@@ -354,7 +472,7 @@ int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_en
int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments);
squashfs_fragment_index fragment_table_index[indexes];
- TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%x\n", sBlk->fragments, indexes, sBlk->fragment_table_start);
+ TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start);
if(sBlk->fragments == 0)
return 1;
@@ -372,11 +490,10 @@ int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_en
read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index);
for(i = 0; i < indexes; i++) {
- int length = read_block(fd, fragment_table_index[i], NULL, ((char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk);
- TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length);
+ int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk);
+ TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length);
}
-
if(swap) {
squashfs_fragment_entry sfragment;
for(i = 0; i < sBlk->fragments; i++) {
@@ -389,29 +506,30 @@ int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_en
}
-int read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, int *inode_bytes,
- char **data_cache, int *cache_bytes, int *cache_size,
- char **cdirectory_table, int *directory_bytes,
- char **directory_data_cache, int *directory_cache_bytes, int *directory_cache_size,
- int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count,
- squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count,
- unsigned int *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory,
- void (push_directory_entry)(char *, squashfs_inode, int), squashfs_fragment_entry **fragment_table)
+long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table,
+ char **data_cache, char **cdirectory_table, char **directory_data_cache,
+ unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size,
+ unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count,
+ int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids,
+ unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count,
+ long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory,
+ unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode,
+ void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table)
{
unsigned char *inode_table = NULL, *directory_table;
- unsigned int start = sBlk->inode_table_start, end = sBlk->directory_table_start,
- root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode),
- root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_directory_offset;
- squashfs_dir_inode_header inode;
- unsigned int files, root_inode_block;
+ long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start +
+ SQUASHFS_INODE_BLK(sBlk->root_inode);
+ unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files;
+ squashfs_inode_header inode;
printf("Scanning existing filesystem...\n");
- if(read_fragment_table(fd, sBlk, fragment_table) == 0)
+ if(read_fragment_table(fd, sBlk, fragment_table) == 0)
goto error;
- if((files = scan_inode_table(fd, start, end, root_inode_start, sBlk, &inode, &inode_table, &root_inode_block,
- uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) {
+ if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table,
+ &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count,
+ dev_count, dir_count, fifo_count, sock_count)) == 0) {
ERROR("read_filesystem: inode table read failed\n");
goto error;
}
@@ -420,53 +538,51 @@ int read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **
printf("Read existing filesystem, %d inodes scanned\n", files);
- if(inode.inode_type == SQUASHFS_DIR_TYPE) {
- if((directory_table = squashfs_readdir(fd, !root_name, sBlk->directory_table_start + inode.start_block,
- inode.offset, inode.file_size, sBlk, push_directory_entry)) == NULL) {
+ if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) {
+ if(inode.base.inode_type == SQUASHFS_DIR_TYPE) {
+ *inode_dir_start_block = inode.dir.start_block;
+ *inode_dir_offset = inode.dir.offset;
+ *inode_dir_file_size = inode.dir.file_size - 3;
+ *inode_dir_inode_number = inode.dir.inode_number;
+ *inode_dir_parent_inode = inode.dir.parent_inode;
+ } else {
+ *inode_dir_start_block = inode.ldir.start_block;
+ *inode_dir_offset = inode.ldir.offset;
+ *inode_dir_file_size = inode.ldir.file_size - 3;
+ *inode_dir_inode_number = inode.ldir.inode_number;
+ *inode_dir_parent_inode = inode.ldir.parent_inode;
+ }
+
+ if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset,
+ *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) {
ERROR("read_filesystem: Could not read root directory\n");
goto error;
}
- if((*cinode_table = (char *) malloc(root_inode_start - start)) == NULL) {
+ root_inode_start -= start;
+ if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) {
ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n");
goto error;
}
+ read_bytes(fd, start, root_inode_start, *cinode_table);
- read_bytes(fd, start, root_inode_start - start, *cinode_table);
-
- if((*cdirectory_table = (char *) malloc(inode.start_block)) == NULL) {
- ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n");
+ if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) {
+ ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n");
goto error;
}
+ read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table);
- read_bytes(fd, sBlk->directory_table_start, inode.start_block, *cdirectory_table);
-
- *inode_bytes = root_inode_start - start;
- *directory_bytes = inode.start_block;
-
- root_inode_offset += sizeof(inode);
- root_directory_offset = inode.offset + inode.file_size;
- (*dir_count) ++;
-
- if(((*data_cache = (char *) malloc(root_inode_offset)) == NULL) ||
- ((*directory_data_cache = (char *) malloc(root_directory_offset)) == NULL)) {
- ERROR("read_filesystem: failed to alloc inode/directory caches\n");
+ if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) {
+ ERROR("read_filesystem: failed to alloc inode cache\n");
goto error;
}
+ memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size);
- memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset);
- memcpy(*directory_data_cache, directory_table, root_directory_offset);
- *cache_size = root_inode_offset;
- *directory_cache_size = root_directory_offset;
-
- if(root_name) {
- push_directory_entry(root_name, sBlk->root_inode, SQUASHFS_DIR_TYPE);
- *cache_bytes = root_inode_offset;
- *directory_cache_bytes = root_directory_offset;
- } else {
- *cache_bytes = root_inode_offset - sizeof(inode);
- *directory_cache_bytes = inode.offset;
+ if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) {
+ ERROR("read_filesystem: failed to alloc directory cache\n");
+ goto error;
}
+ memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size);
if(!swap)
read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids);
diff --git a/release/src/linux/linux/scripts/squashfs/read_fs.h b/release/src/linux/linux/scripts/squashfs/read_fs.h
index fcc39c35..1b35aed2 100644
--- a/release/src/linux/linux/scripts/squashfs/read_fs.h
+++ b/release/src/linux/linux/scripts/squashfs/read_fs.h
@@ -3,7 +3,8 @@
* endian and vice versa. These are needed when creating a filesystem on a
* machine with different byte ordering to the target architecture.
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/release/src/linux/linux/scripts/squashfs/sort.c b/release/src/linux/linux/scripts/squashfs/sort.c
index b5371280..c30093fa 100644
--- a/release/src/linux/linux/scripts/squashfs/sort.c
+++ b/release/src/linux/linux/scripts/squashfs/sort.c
@@ -1,7 +1,8 @@
/*
* Create a squashfs filesystem. This is a highly compressed read only filesystem.
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -34,20 +35,32 @@
#include <stdlib.h>
#include <squashfs_fs.h>
+#include "global.h"
+#include "sort.h"
#ifdef SQUASHFS_TRACE
-#define TRACE(s, args...) printf("mksquashfs: "s, ## args)
+#define TRACE(s, args...) do { \
+ printf("mksquashfs: "s, ## args); \
+ } while(0)
#else
#define TRACE(s, args...)
#endif
-#define INFO(s, args...) if(!silent) printf("mksquashfs: "s, ## args)
-#define ERROR(s, args...) fprintf(stderr, s, ## args)
-#define EXIT_MKSQUASHFS() exit(1)
-#define BAD_ERROR(s, args...) {\
- fprintf(stderr, "FATAL ERROR:" s, ##args);\
- EXIT_MKSQUASHFS();\
- }
+#define INFO(s, args...) do { \
+ if(!silent) printf("mksquashfs: "s, ## args); \
+ } while(0)
+#define ERROR(s, args...) do { \
+ fprintf(stderr, s, ## args); \
+ } while(0)
+#define EXIT_MKSQUASHFS() do { \
+ exit(1); \
+ } while(0)
+#define BAD_ERROR(s, args...) do {\
+ fprintf(stderr, "FATAL ERROR:" s, ##args);\
+ EXIT_MKSQUASHFS();\
+ } while(0);
+
+int mkisofs_style = -1;
struct sort_info {
dev_t st_dev;
@@ -59,66 +72,17 @@ struct sort_info {
struct sort_info *sort_info_list[65536];
struct priority_entry {
- char *filename;
- long long size;
- ino_t st_ino;
- dev_t st_dev;
+ struct dir_ent *dir;
struct priority_entry *next;
};
struct priority_entry *priority_list[65536];
-struct sorted_inode_entry {
- squashfs_inode inode;
- ino_t st_ino;
- dev_t st_dev;
- struct sorted_inode_entry *next;
-};
-
-struct sorted_inode_entry *sorted_inode_list[65536];
-
extern int silent;
-extern int excluded(char *filename, struct stat *buf);
-extern squashfs_inode write_file(char *filename, long long size, int *c_size);
-
-
-int add_to_sorted_inode_list(squashfs_inode inode, dev_t st_dev, ino_t st_ino)
-{
- int hash = st_ino & 0xffff;
- struct sorted_inode_entry *new_sorted_inode_entry;
-
- if((new_sorted_inode_entry = malloc(sizeof(struct sorted_inode_entry))) == NULL) {
- ERROR("Out of memory allocating sorted inode entry\n");
- return FALSE;
- }
-
- new_sorted_inode_entry->inode = inode;
- new_sorted_inode_entry->st_ino = st_ino;
- new_sorted_inode_entry->st_dev = st_dev;
- new_sorted_inode_entry->next = sorted_inode_list[hash];
- sorted_inode_list[hash] = new_sorted_inode_entry;
-
- return TRUE;
-}
-
-
-squashfs_inode get_sorted_inode(struct stat *buf)
-{
- int hash = buf->st_ino & 0xffff;
- struct sorted_inode_entry *sorted_inode_entry;
-
- for(sorted_inode_entry = sorted_inode_list[hash]; sorted_inode_entry; sorted_inode_entry = sorted_inode_entry->next)
- if(buf->st_ino == sorted_inode_entry->st_ino && buf->st_dev == sorted_inode_entry->st_dev)
- break;
-
- if(sorted_inode_entry)
- return sorted_inode_entry->inode;
- else
- return (squashfs_inode) 0;
-}
+extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size);
-int add_priority_list(char *filename, struct stat *buf, int priority)
+int add_priority_list(struct dir_ent *dir, int priority)
{
struct priority_entry *new_priority_entry;
@@ -128,10 +92,7 @@ int add_priority_list(char *filename, struct stat *buf, int priority)
return FALSE;
}
- new_priority_entry->filename = strdup(filename);
- new_priority_entry->size = buf->st_size;
- new_priority_entry->st_dev = buf->st_dev;
- new_priority_entry->st_ino = buf->st_ino;
+ new_priority_entry->dir = dir;;
new_priority_entry->next = priority_list[priority];
priority_list[priority] = new_priority_entry;
return TRUE;
@@ -168,8 +129,8 @@ int get_priority(char *filename, struct stat *buf, int priority)
}
int add_sort_list(char *path, int priority, int source, char *source_path[])
{
- int i;
- char buffer[4096], filename[4096];
+ int i, n;
+ char filename[4096];
struct stat buf;
TRACE("add_sort_list: filename %s, priority %d\n", path, priority);
@@ -177,71 +138,73 @@ int add_sort_list(char *path, int priority, int source, char *source_path[])
path[strlen(path) - 2] = '\0';
TRACE("add_sort_list: filename %s, priority %d\n", path, priority);
- if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) {
- if(lstat(path, &buf) == -1) {
- sprintf(buffer, "Cannot stat sort_list dir/file %s, ignoring", path);
- perror(buffer);
- return TRUE;
- }
- TRACE("adding filename %s, priority %d, st_dev %Lx, st_ino %Lx\n", path, priority, buf.st_dev, buf.st_ino);
+re_read:
+ if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) {
+ if(lstat(path, &buf) == -1)
+ goto error;
+ TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino);
ADD_ENTRY(buf, priority);
return TRUE;
}
- for(i = 0; i < source; i++) {
+ for(i = 0, n = 0; i < source; i++) {
strcat(strcat(strcpy(filename, source_path[i]), "/"), path);
if(lstat(filename, &buf) == -1) {
- if(!(errno == ENOENT || errno == ENOTDIR)) {
- sprintf(buffer, "Cannot stat sort_list dir/file %s, ignoring", filename);
- perror(buffer);
- }
+ if(!(errno == ENOENT || errno == ENOTDIR))
+ goto error;
continue;
}
ADD_ENTRY(buf, priority);
+ n ++;
}
- return TRUE;
+
+ if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) {
+ ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n");
+ ERROR("convert to mksquashfs style sortlist! A sortlist entry ");
+ ERROR("should be\neither absolute (starting with ");
+ ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it ");
+ ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with ");
+ ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist ");
+ ERROR("entry \"file\" is assumed to be inside the directory test.\n\n");
+ mkisofs_style = 1;
+ goto re_read;
+ }
+
+ mkisofs_style = 0;
+
+ if(n == 1)
+ return TRUE;
+ if(n > 1)
+ BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path);
+
+error:
+ fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path);
+ fprintf(stderr, "This is probably because you're using the wrong file\n");
+ fprintf(stderr, "path relative to the source directories\n");
+ return FALSE;
}
-void generate_file_priorities(char *pathname, int priority, struct stat *buf)
+void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf)
{
- char filename[8192];
- DIR *linuxdir;
- struct dirent *d_name;
-
- priority = get_priority(pathname, buf, priority);
-
- if((linuxdir = opendir(pathname)) == NULL) {
- ERROR("Could not open %s, skipping...\n", pathname);
- return;
- }
-
- while((d_name = readdir(linuxdir)) != NULL) {
- if(strcmp(d_name->d_name, ".") == 0 || strcmp(d_name->d_name, "..") == 0)
- continue;
- strcat(strcat(strcpy(filename, pathname), "/"), d_name->d_name);
+ priority = get_priority(dir->pathname, buf, priority);
- if(lstat(filename, buf) == -1) {
- char buffer[8192];
- sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename);
- perror(buffer);
- continue;
- }
-
- if(excluded(filename, buf))
+ while(dir->current_count < dir->count) {
+ struct dir_ent *dir_ent = dir->list[dir->current_count++];
+ struct stat *buf = &dir_ent->inode->buf;
+ if(dir_ent->data)
continue;
switch(buf->st_mode & S_IFMT) {
case S_IFREG:
- add_priority_list(filename, buf, get_priority(filename, buf, priority));
+ add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority));
break;
case S_IFDIR:
- generate_file_priorities(filename, priority, buf);
+ generate_file_priorities(dir_ent->dir, priority, buf);
break;
}
}
-
- closedir(linuxdir);
+ dir->current_count = 0;
}
@@ -265,40 +228,30 @@ int read_sort_file(char *filename, int source, char *source_path[])
}
-void sort_files_and_write(int source, char *source_path[])
+void sort_files_and_write(struct dir_info *dir)
{
- struct stat buf;
- int i, c_size;
+ int i;
struct priority_entry *entry;
squashfs_inode inode;
+ int duplicate_file;
- for(i = 0; i < source; i++) {
- if(lstat(source_path[i], &buf) == -1) {
- char buffer[8192];
- sprintf(buffer, "Cannot stat dir/file %s, ignoring", source_path[i]);
- perror(buffer);
- continue;
- }
-
- if(excluded(source_path[i], &buf))
- continue;
-
- switch(buf.st_mode & S_IFMT) {
- case S_IFREG:
- add_priority_list(source_path[i], &buf, get_priority(source_path[i], &buf, 0));
- break;
- case S_IFDIR:
- generate_file_priorities(source_path[i], 0, &buf);
- break;
- }
- }
+ generate_file_priorities(dir, 0, &dir->dir_ent->inode->buf);
- for(i = 0; i < 65536; i++)
+ for(i = 65535; i >= 0; i--)
for(entry = priority_list[i]; entry; entry = entry->next) {
- TRACE("%d: %s\n", i - 32768, entry->filename);
- inode = write_file(entry->filename, entry->size, &c_size);
- INFO("file %s, size %d bytes, inode 0x%Lx\n", entry->filename, c_size, inode);
- INFO("\t%.2f%% of uncompressed file size (%Ld bytes)\n", ((float) c_size / entry->size) * 100.0, entry->size);
- add_to_sorted_inode_list(inode, entry->st_dev, entry->st_ino);
+ TRACE("%d: %s\n", i - 32768, entry->dir->pathname);
+ if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) {
+ if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size,
+ &duplicate_file)) {
+ INFO("file %s, uncompressed size %lld bytes %s\n",
+ entry->dir->pathname,
+ entry->dir->inode->buf.st_size,
+ duplicate_file ? "DUPLICATE" : "");
+ entry->dir->inode->inode = inode;
+ entry->dir->inode->type = SQUASHFS_FILE_TYPE;
+ }
+ } else
+ INFO("file %s, uncompressed size %lld bytes LINK\n",
+ entry->dir->pathname, entry->dir->inode->buf.st_size);
}
}
diff --git a/release/src/linux/linux/scripts/squashfs/sort.h b/release/src/linux/linux/scripts/squashfs/sort.h
new file mode 100644
index 00000000..561c320b
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/sort.h
@@ -0,0 +1,56 @@
+#ifndef SORT_H
+#define SORT_H
+
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * sort.h
+ */
+
+struct dir_info {
+ char *pathname;
+ unsigned int count;
+ unsigned int directory_count;
+ unsigned int current_count;
+ unsigned int byte_count;
+ char dir_is_ldir;
+ struct dir_ent *dir_ent;
+ struct dir_ent **list;
+ DIR *linuxdir;
+};
+
+struct dir_ent {
+ char *name;
+ char *pathname;
+ struct inode_info *inode;
+ struct dir_info *dir;
+ struct dir_info *our_dir;
+ struct old_root_entry_info *data;
+};
+
+struct inode_info {
+ unsigned int nlink;
+ struct stat buf;
+ squashfs_inode inode;
+ unsigned int type;
+ unsigned int inode_number;
+ struct inode_info *next;
+};
+#endif
diff --git a/release/src/linux/linux/scripts/squashfs/squashfs_fs.h b/release/src/linux/linux/scripts/squashfs/squashfs_fs.h
index d810c596..fbbb53c1 100644
--- a/release/src/linux/linux/scripts/squashfs/squashfs_fs.h
+++ b/release/src/linux/linux/scripts/squashfs/squashfs_fs.h
@@ -1,9 +1,11 @@
#ifndef SQUASHFS_FS
#define SQUASHFS_FS
+
/*
* Squashfs
*
- * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,7 +24,7 @@
* squashfs_fs.h
*/
-#define SQUASHFS_MAJOR 2
+#define SQUASHFS_MAJOR 3
#define SQUASHFS_MINOR 0
#define SQUASHFS_MAGIC 0x73717368
#define SQUASHFS_MAGIC_SWAP 0x68737173
@@ -46,8 +48,9 @@
#define SQUASHFS_NAME_LEN 256
#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
-#define SQUASHFS_INVALID_BLK ((long long) 0xffffffff)
-#define SQUASHFS_USED_BLK ((long long) 0xfffffffe)
+#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
+#define SQUASHFS_INVALID_BLK ((long long) -1)
+#define SQUASHFS_USED_BLK ((long long) -2)
/* Filesystem flags */
#define SQUASHFS_NOI 0
@@ -57,15 +60,34 @@
#define SQUASHFS_NO_FRAG 4
#define SQUASHFS_ALWAYS_FRAG 5
#define SQUASHFS_DUPLICATE 6
+
#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
-#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, SQUASHFS_NOI)
-#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_NOD)
-#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NOF)
-#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NO_FRAG)
-#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_ALWAYS_FRAG)
-#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, SQUASHFS_DUPLICATE)
-#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_CHECK)
-#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, duplicate_checking) (noi | (nod << 1) | (check_data << 2) | (nof << 3) | (no_frag << 4) | (always_frag << 5) | (duplicate_checking << 6))
+
+#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOI)
+
+#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOD)
+
+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOF)
+
+#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NO_FRAG)
+
+#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_ALWAYS_FRAG)
+
+#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_DUPLICATE)
+
+#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_CHECK)
+
+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
+ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \
+ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
+ (duplicate_checking << 6))
/* Max number of types and file types */
#define SQUASHFS_DIR_TYPE 1
@@ -75,53 +97,74 @@
#define SQUASHFS_CHRDEV_TYPE 5
#define SQUASHFS_FIFO_TYPE 6
#define SQUASHFS_SOCKET_TYPE 7
+#define SQUASHFS_LDIR_TYPE 8
+#define SQUASHFS_LREG_TYPE 9
/* 1.0 filesystem type definitions */
#define SQUASHFS_TYPES 5
#define SQUASHFS_IPC_TYPE 0
-/* Flag whether block is compressed or uncompressed, bit is set if block is uncompressed */
+/* Flag whether block is compressed or uncompressed, bit is set if block is
+ * uncompressed */
#define SQUASHFS_COMPRESSED_BIT (1 << 15)
+
#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
- (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
+ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
-#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? \
- (B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
-#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
+ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
+ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
+
+#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
/*
- * Inode number ops. Inodes consist of a compressed block number, and an uncompressed
- * offset within that block
+ * Inode number ops. Inodes consist of a compressed block number, and an
+ * uncompressed offset within that block
*/
#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
+
#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
-#define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A) << 16)\
- + (B)))
+
+#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
+ << 16) + (B)))
/* Compute 32 bit VFS inode number from squashfs inode number */
-#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + ((b) >> 2) + 1))
+#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
+ ((b) >> 2) + 1))
+/* XXX */
/* Translate between VFS mode and squashfs mode */
#define SQUASHFS_MODE(a) ((a) & 0xfff)
/* fragment and fragment table defines */
-typedef unsigned int squashfs_fragment_index;
-#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(squashfs_fragment_entry))
-#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / SQUASHFS_METADATA_SIZE)
-#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % SQUASHFS_METADATA_SIZE)
-#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE)
-#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) * sizeof(squashfs_fragment_index))
+#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry))
+
+#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
+ SQUASHFS_METADATA_SIZE - 1) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
+ sizeof(long long))
+
#define SQUASHFS_CACHED_FRAGMENTS 3
/* cached data constants for filesystem */
#define SQUASHFS_CACHED_BLKS 8
-#define SQUASHFS_MAX_FILE_SIZE_LOG 32
-#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << (SQUASHFS_MAX_FILE_SIZE_LOG - 1))
+#define SQUASHFS_MAX_FILE_SIZE_LOG 64
+
+#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
+ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
#define SQUASHFS_MARKER_BYTE 0xff
@@ -129,19 +172,17 @@ typedef unsigned int squashfs_fragment_index;
* definitions for structures on disk
*/
-typedef unsigned int squashfs_block;
-typedef long long squashfs_inode;
-
-typedef unsigned int squashfs_uid;
+typedef long long squashfs_block_t;
+typedef long long squashfs_inode_t;
-typedef struct squashfs_super_block {
+struct squashfs_super_block {
unsigned int s_magic;
unsigned int inodes;
- unsigned int bytes_used;
- unsigned int uid_start;
- unsigned int guid_start;
- unsigned int inode_table_start;
- unsigned int directory_table_start;
+ unsigned int bytes_used_2;
+ unsigned int uid_start_2;
+ unsigned int guid_start_2;
+ unsigned int inode_table_start_2;
+ unsigned int directory_table_start_2;
unsigned int s_major:16;
unsigned int s_minor:16;
unsigned int block_size_1:16;
@@ -150,88 +191,125 @@ typedef struct squashfs_super_block {
unsigned int no_uids:8;
unsigned int no_guids:8;
unsigned int mkfs_time /* time of filesystem creation */;
- squashfs_inode root_inode;
+ squashfs_inode_t root_inode;
unsigned int block_size;
unsigned int fragments;
- unsigned int fragment_table_start;
-} __attribute__ ((packed)) squashfs_super_block;
-
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
-} __attribute__ ((packed)) squashfs_base_inode_header;
-
-typedef squashfs_base_inode_header squashfs_ipc_inode_header;
-
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
+ unsigned int fragment_table_start_2;
+ long long bytes_used;
+ long long uid_start;
+ long long guid_start;
+ long long inode_table_start;
+ long long directory_table_start;
+ long long fragment_table_start;
+ long long unused;
+} __attribute__ ((packed));
+
+struct squashfs_dir_index {
+ unsigned int index;
+ unsigned int start_block;
+ unsigned char size;
+ unsigned char name[0];
+} __attribute__ ((packed));
+
+#define SQUASHFS_BASE_INODE_HEADER \
+ unsigned int inode_type:4; \
+ unsigned int mode:12; \
+ unsigned int uid:8; \
+ unsigned int guid:8; \
+ unsigned int mtime; \
+ unsigned int inode_number;
+
+struct squashfs_base_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+} __attribute__ ((packed));
+
+struct squashfs_ipc_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
+} __attribute__ ((packed));
+
+struct squashfs_dev_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
unsigned short rdev;
-} __attribute__ ((packed)) squashfs_dev_inode_header;
+} __attribute__ ((packed));
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
+struct squashfs_symlink_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
unsigned short symlink_size;
char symlink[0];
-} __attribute__ ((packed)) squashfs_symlink_inode_header;
+} __attribute__ ((packed));
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
- unsigned int mtime;
- squashfs_block start_block;
+struct squashfs_reg_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ squashfs_block_t start_block;
unsigned int fragment;
unsigned int offset;
- unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+ unsigned int file_size;
unsigned short block_list[0];
-} __attribute__ ((packed)) squashfs_reg_inode_header;
+} __attribute__ ((packed));
-typedef struct {
- unsigned int inode_type:4;
- unsigned int mode:12; /* protection */
- unsigned int uid:8; /* index into uid table */
- unsigned int guid:8; /* index into guid table */
+struct squashfs_lreg_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
+ squashfs_block_t start_block;
+ unsigned int fragment;
+ unsigned int offset;
+ long long file_size;
+ unsigned short block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
unsigned int file_size:19;
unsigned int offset:13;
- unsigned int mtime;
- unsigned int start_block:24;
-} __attribute__ ((packed)) squashfs_dir_inode_header;
-
-typedef union {
- squashfs_base_inode_header base;
- squashfs_dev_inode_header dev;
- squashfs_symlink_inode_header symlink;
- squashfs_reg_inode_header reg;
- squashfs_dir_inode_header dir;
- squashfs_ipc_inode_header ipc;
-} squashfs_inode_header;
+ unsigned int start_block;
+ unsigned int parent_inode;
+} __attribute__ ((packed));
+
+struct squashfs_ldir_inode_header {
+ SQUASHFS_BASE_INODE_HEADER;
+ unsigned int nlink;
+ unsigned int file_size:27;
+ unsigned int offset:13;
+ unsigned int start_block;
+ unsigned int i_count:16;
+ unsigned int parent_inode;
+ struct squashfs_dir_index index[0];
+} __attribute__ ((packed));
+
+union squashfs_inode_header {
+ struct squashfs_base_inode_header base;
+ struct squashfs_dev_inode_header dev;
+ struct squashfs_symlink_inode_header symlink;
+ struct squashfs_reg_inode_header reg;
+ struct squashfs_lreg_inode_header lreg;
+ struct squashfs_dir_inode_header dir;
+ struct squashfs_ldir_inode_header ldir;
+ struct squashfs_ipc_inode_header ipc;
+};
-typedef struct {
+struct squashfs_dir_entry {
unsigned int offset:13;
unsigned int type:3;
unsigned int size:8;
+ int inode_number:16;
char name[0];
-} __attribute__ ((packed)) squashfs_dir_entry;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_dir_header {
unsigned int count:8;
- unsigned int start_block:24;
-} __attribute__ ((packed)) squashfs_dir_header;
-
-
-typedef struct {
unsigned int start_block;
+ unsigned int inode_number;
+} __attribute__ ((packed));
+
+struct squashfs_fragment_entry {
+ long long start_block;
unsigned int size;
-} __attribute__ ((packed)) squashfs_fragment_entry;
+ unsigned int unused;
+} __attribute__ ((packed));
extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
extern int squashfs_uncompress_init(void);
@@ -239,20 +317,28 @@ extern int squashfs_uncompress_exit(void);
/*
* macros to convert each packed bitfield structure from little endian to big
- * endian and vice versa. These are needed when creating or using a filesystem on a
- * machine with different byte ordering to the target architecture.
+ * endian and vice versa. These are needed when creating or using a filesystem
+ * on a machine with different byte ordering to the target architecture.
*
*/
+#define SQUASHFS_SWAP_START \
+ int bits;\
+ int b_pos;\
+ unsigned long long val;\
+ unsigned char *s;\
+ unsigned char *d;
+
#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
- SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\
- SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\
- SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\
- SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\
- SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\
+ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
+ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
+ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
+ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
+ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
@@ -264,137 +350,218 @@ extern int squashfs_uncompress_exit(void);
SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
- SQUASHFS_SWAP((s)->fragment_table_start, d, 472, 32);\
+ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
+ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
+ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
+ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
+ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
+ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
+ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
+ SQUASHFS_SWAP((s)->unused, d, 888, 64);\
}
-#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
SQUASHFS_MEMSET(s, d, n);\
SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
SQUASHFS_SWAP((s)->mode, d, 4, 12);\
SQUASHFS_SWAP((s)->uid, d, 16, 8);\
SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
}
-#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ipc_inode_header))
+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_ipc_inode_header))\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+}
#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dev_inode_header));\
- SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_dev_inode_header)); \
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
}
#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header));\
- SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_symlink_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
}
#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header));\
- SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
- SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
- SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
- SQUASHFS_SWAP((s)->offset, d, 128, 32);\
- SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_reg_inode_header));\
+ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
+ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
+ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
+}
+
+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_lreg_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
+ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
+ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
}
#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header));\
- SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
- SQUASHFS_SWAP((s)->offset, d, 51, 13);\
- SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
- SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_dir_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
+ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
+ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
+ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
+}
+
+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+ sizeof(struct squashfs_ldir_inode_header));\
+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
+ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
+ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
+ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
+ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
+}
+
+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
+ SQUASHFS_SWAP((s)->index, d, 0, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
+ SQUASHFS_SWAP((s)->size, d, 64, 8);\
}
#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
SQUASHFS_SWAP((s)->count, d, 0, 8);\
- SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
+ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
+ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
}
#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
SQUASHFS_SWAP((s)->offset, d, 0, 13);\
SQUASHFS_SWAP((s)->type, d, 13, 3);\
SQUASHFS_SWAP((s)->size, d, 16, 8);\
+ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
}
#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
- SQUASHFS_MEMSET(s, d, sizeof(squashfs_fragment_entry));\
- SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
- SQUASHFS_SWAP((s)->size, d, 32, 32);\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
+ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
+ SQUASHFS_SWAP((s)->size, d, 64, 32);\
}
#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
int entry;\
int bit_position;\
+ SQUASHFS_SWAP_START\
SQUASHFS_MEMSET(s, d, n * 2);\
- for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 16)\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 16)\
SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
}
#define SQUASHFS_SWAP_INTS(s, d, n) {\
int entry;\
int bit_position;\
+ SQUASHFS_SWAP_START\
SQUASHFS_MEMSET(s, d, n * 4);\
- for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 32)\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 32)\
SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
}
+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
+ int entry;\
+ int bit_position;\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, n * 8);\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 64)\
+ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
+}
+
#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
int entry;\
int bit_position;\
+ SQUASHFS_SWAP_START\
SQUASHFS_MEMSET(s, d, n * bits / 8);\
- for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += bits)\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ bits)\
SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
}
-#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
-#ifdef SQUASHFS_1_0_COMPATIBILITY
-typedef struct {
+struct squashfs_base_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
-} __attribute__ ((packed)) squashfs_base_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_ipc_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned int type:4;
unsigned int offset:4;
-} __attribute__ ((packed)) squashfs_ipc_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_dev_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned short rdev;
-} __attribute__ ((packed)) squashfs_dev_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_symlink_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned short symlink_size;
char symlink[0];
-} __attribute__ ((packed)) squashfs_symlink_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_reg_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
unsigned int guid:4; /* index into guid table */
unsigned int mtime;
- squashfs_block start_block;
- unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+ unsigned int start_block;
+ unsigned int file_size:32;
unsigned short block_list[0];
-} __attribute__ ((packed)) squashfs_reg_inode_header_1;
+} __attribute__ ((packed));
-typedef struct {
+struct squashfs_dir_inode_header_1 {
unsigned int inode_type:4;
unsigned int mode:12; /* protection */
unsigned int uid:4; /* index into uid table */
@@ -403,72 +570,308 @@ typedef struct {
unsigned int offset:13;
unsigned int mtime;
unsigned int start_block:24;
-} __attribute__ ((packed)) squashfs_dir_inode_header_1;
+} __attribute__ ((packed));
-#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
SQUASHFS_MEMSET(s, d, n);\
SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
SQUASHFS_SWAP((s)->mode, d, 4, 12);\
SQUASHFS_SWAP((s)->uid, d, 16, 4);\
- SQUASHFS_SWAP((s)->guid, d, 20, 4);\
+ SQUASHFS_SWAP((s)->guid, d, 20, 4);
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
}
#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_ipc_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_ipc_inode_header_1));\
SQUASHFS_SWAP((s)->type, d, 24, 4);\
SQUASHFS_SWAP((s)->offset, d, 28, 4);\
}
#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_dev_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_dev_inode_header_1));\
SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
}
#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_symlink_inode_header_1));\
SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
}
#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_reg_inode_header_1));\
SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\
}
#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
- SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header_1));\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+ sizeof(struct squashfs_dir_inode_header_1));\
SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
SQUASHFS_SWAP((s)->offset, d, 43, 13);\
SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
}
+
+#endif
+
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+
+struct squashfs_dir_index_2 {
+ unsigned int index:27;
+ unsigned int start_block:29;
+ unsigned char size;
+ unsigned char name[0];
+} __attribute__ ((packed));
+
+struct squashfs_base_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+} __attribute__ ((packed));
+
+struct squashfs_ipc_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+} __attribute__ ((packed));
+
+struct squashfs_dev_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned short rdev;
+} __attribute__ ((packed));
+
+struct squashfs_symlink_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned short symlink_size;
+ char symlink[0];
+} __attribute__ ((packed));
+
+struct squashfs_reg_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int mtime;
+ unsigned int start_block;
+ unsigned int fragment;
+ unsigned int offset;
+ unsigned int file_size:32;
+ unsigned short block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int file_size:19;
+ unsigned int offset:13;
+ unsigned int mtime;
+ unsigned int start_block:24;
+} __attribute__ ((packed));
+
+struct squashfs_ldir_inode_header_2 {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int file_size:27;
+ unsigned int offset:13;
+ unsigned int mtime;
+ unsigned int start_block:24;
+ unsigned int i_count:16;
+ struct squashfs_dir_index_2 index[0];
+} __attribute__ ((packed));
+
+union squashfs_inode_header_2 {
+ struct squashfs_base_inode_header_2 base;
+ struct squashfs_dev_inode_header_2 dev;
+ struct squashfs_symlink_inode_header_2 symlink;
+ struct squashfs_reg_inode_header_2 reg;
+ struct squashfs_dir_inode_header_2 dir;
+ struct squashfs_ldir_inode_header_2 ldir;
+ struct squashfs_ipc_inode_header_2 ipc;
+};
+
+struct squashfs_dir_header_2 {
+ unsigned int count:8;
+ unsigned int start_block:24;
+} __attribute__ ((packed));
+
+struct squashfs_dir_entry_2 {
+ unsigned int offset:13;
+ unsigned int type:3;
+ unsigned int size:8;
+ char name[0];
+} __attribute__ ((packed));
+
+struct squashfs_fragment_entry_2 {
+ unsigned int start_block;
+ unsigned int size;
+} __attribute__ ((packed));
+
+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
+ SQUASHFS_MEMSET(s, d, n);\
+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_dev_inode_header_2)); \
+ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_symlink_inode_header_2));\
+ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_reg_inode_header_2));\
+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
+ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
+ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_dir_inode_header_2));\
+ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
+ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
+ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
+}
+
+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+ sizeof(struct squashfs_ldir_inode_header_2));\
+ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
+ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
+ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
+ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
+}
+
+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
+ SQUASHFS_SWAP((s)->index, d, 0, 27);\
+ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
+ SQUASHFS_SWAP((s)->size, d, 56, 8);\
+}
+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
+ SQUASHFS_SWAP((s)->count, d, 0, 8);\
+ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
+}
+
+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
+ SQUASHFS_SWAP((s)->type, d, 13, 3);\
+ SQUASHFS_SWAP((s)->size, d, 16, 8);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
+ SQUASHFS_SWAP_START\
+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
+ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
+ SQUASHFS_SWAP((s)->size, d, 32, 32);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
+
+/* fragment and fragment table defines */
+#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
+
+#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
+ SQUASHFS_METADATA_SIZE - 1) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
+ sizeof(int))
+
#endif
#ifdef __KERNEL__
+
/*
* macros used to swap each structure entry, taking into account
- * bitfields and different bitfield placing conventions on differing architectures
+ * bitfields and different bitfield placing conventions on differing
+ * architectures
*/
+
#include <asm/byteorder.h>
+
#ifdef __BIG_ENDIAN
/* convert from little endian to big endian */
-#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos)
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+ tbits, b_pos)
#else
/* convert from big endian to little endian */
-#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos)
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+ tbits, 64 - tbits - b_pos)
#endif
#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
- int bits;\
- int b_pos = pos % 8;\
- unsigned long long val = 0;\
- unsigned char *s = (unsigned char *)p + (pos / 8);\
- unsigned char *d = ((unsigned char *) &val) + 7;\
+ b_pos = pos % 8;\
+ val = 0;\
+ s = (unsigned char *)p + (pos / 8);\
+ d = ((unsigned char *) &val) + 7;\
for(bits = 0; bits < (tbits + b_pos); bits += 8) \
*d-- = *s++;\
value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
}
+
#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
+
#endif
#endif
diff --git a/release/src/linux/linux/scripts/squashfs/unsquashfs.c b/release/src/linux/linux/scripts/squashfs/unsquashfs.c
new file mode 100644
index 00000000..dae8fd62
--- /dev/null
+++ b/release/src/linux/linux/scripts/squashfs/unsquashfs.c
@@ -0,0 +1,946 @@
+/*
+ * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem.
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * unsquash.c
+ */
+
+#define TRUE 1
+#define FALSE 0
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <zlib.h>
+#include <sys/mman.h>
+#include <utime.h>
+
+#ifndef linux
+#define __BYTE_ORDER BYTE_ORDER
+#define __BIG_ENDIAN BIG_ENDIAN
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#else
+#include <endian.h>
+#endif
+
+#include <squashfs_fs.h>
+#include "read_fs.h"
+#include "global.h"
+
+#include <stdlib.h>
+
+#ifdef SQUASHFS_TRACE
+#define TRACE(s, args...) do { \
+ printf("mksquashfs: "s, ## args); \
+ } while(0)
+#else
+#define TRACE(s, args...)
+#endif
+
+#define ERROR(s, args...) do { \
+ fprintf(stderr, s, ## args); \
+ } while(0)
+
+#define EXIT_UNSQUASH(s, args...) do { \
+ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \
+ } while(0)
+
+struct hash_table_entry {
+ int start;
+ int bytes;
+ struct hash_table_entry *next;
+};
+
+int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0;
+char *inode_table = NULL, *directory_table = NULL;
+struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536];
+int fd;
+squashfs_fragment_entry *fragment_table;
+unsigned int *uid_table, *guid_table;
+unsigned int cached_frag = SQUASHFS_INVALID_FRAG;
+char *fragment_data;
+char *file_data;
+char *data;
+unsigned int block_size;
+int lsonly = FALSE, info = FALSE;
+char **created_inode;
+
+#define CALCULATE_HASH(start) (start & 0xffff)
+
+int add_entry(struct hash_table_entry *hash_table[], int start, int bytes)
+{
+ int hash = CALCULATE_HASH(start);
+ struct hash_table_entry *hash_table_entry;
+
+ if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) {
+ ERROR("add_hash: out of memory in malloc\n");
+ return FALSE;
+ }
+
+ hash_table_entry->start = start;
+ hash_table_entry->bytes = bytes;
+ hash_table_entry->next = hash_table[hash];
+ hash_table[hash] = hash_table_entry;
+
+ return TRUE;
+}
+
+
+int lookup_entry(struct hash_table_entry *hash_table[], int start)
+{
+ int hash = CALCULATE_HASH(start);
+ struct hash_table_entry *hash_table_entry;
+
+ for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next)
+ if(hash_table_entry->start == start)
+ return hash_table_entry->bytes;
+
+ return -1;
+}
+
+
+int read_bytes(long long byte, int bytes, char *buff)
+{
+ off_t off = byte;
+
+ TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes);
+
+ if(lseek(fd, off, SEEK_SET) == -1) {
+ ERROR("Lseek failed because %s\b", strerror(errno));
+ return FALSE;
+ }
+
+ if(read(fd, buff, bytes) == -1) {
+ ERROR("Read on destination failed because %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+int read_block(long long start, long long *next, char *block, squashfs_super_block *sBlk)
+{
+ unsigned short c_byte;
+ int offset = 2;
+
+ if(swap) {
+ if(read_bytes(start, 2, block) == FALSE)
+ goto failed;
+ ((unsigned char *) &c_byte)[1] = block[0];
+ ((unsigned char *) &c_byte)[0] = block[1];
+ } else
+ if(read_bytes(start, 2, (char *)&c_byte) == FALSE)
+ goto failed;
+
+ TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed");
+
+ if(SQUASHFS_CHECK_DATA(sBlk->flags))
+ offset = 3;
+ if(SQUASHFS_COMPRESSED(c_byte)) {
+ char buffer[SQUASHFS_METADATA_SIZE];
+ int res;
+ unsigned long bytes = SQUASHFS_METADATA_SIZE;
+
+ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
+ if(read_bytes(start + offset, c_byte, buffer) == FALSE)
+ goto failed;
+
+ if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) {
+ if(res == Z_MEM_ERROR)
+ ERROR("zlib::uncompress failed, not enough memory\n");
+ else if(res == Z_BUF_ERROR)
+ ERROR("zlib::uncompress failed, not enough room in output buffer\n");
+ else
+ ERROR("zlib::uncompress failed, unknown error %d\n", res);
+ goto failed;
+ }
+ if(next)
+ *next = start + offset + c_byte;
+ return bytes;
+ } else {
+ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
+ if(read_bytes(start + offset, c_byte, block) == FALSE)
+ goto failed;
+ if(next)
+ *next = start + offset + c_byte;
+ return c_byte;
+ }
+
+failed:
+ return FALSE;
+}
+
+
+int read_data_block(long long start, unsigned int size, char *block)
+{
+ int res;
+ unsigned long bytes = block_size;
+ int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size);
+
+ TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed");
+
+ if(SQUASHFS_COMPRESSED_BLOCK(size)) {
+ if(read_bytes(start, c_byte, data) == FALSE)
+ return 0;
+
+ if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) {
+ if(res == Z_MEM_ERROR)
+ ERROR("zlib::uncompress failed, not enough memory\n");
+ else if(res == Z_BUF_ERROR)
+ ERROR("zlib::uncompress failed, not enough room in output buffer\n");
+ else
+ ERROR("zlib::uncompress failed, unknown error %d\n", res);
+ return 0;
+ }
+
+ return bytes;
+ } else {
+ if(read_bytes(start, c_byte, block) == FALSE)
+ return 0;
+
+ return c_byte;
+ }
+}
+
+
+void uncompress_inode_table(long long start, long long end, squashfs_super_block *sBlk)
+{
+ int size = 0, bytes = 0, res;
+
+ while(start < end) {
+ if((size - bytes < SQUASHFS_METADATA_SIZE) &&
+ ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL))
+ EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n");
+ TRACE("uncompress_inode_table: reading block 0x%llx\n", start);
+ add_entry(inode_table_hash, start, bytes);
+ if((res = read_block(start, &start, inode_table + bytes, sBlk)) == 0) {
+ free(inode_table);
+ EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n");
+ }
+ bytes += res;
+ }
+}
+
+
+int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid,
+unsigned int mtime, unsigned int set_mode)
+{
+ struct utimbuf times = { (time_t) mtime, (time_t) mtime };
+
+ if(utime(pathname, &times) == -1) {
+ ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno));
+ return FALSE;
+ }
+
+ if(set_mode && chmod(pathname, (mode_t) mode) == -1) {
+ ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno));
+ return FALSE;
+ }
+
+ if(geteuid() == 0) {
+ uid_t uid_value = (uid_t) uid_table[uid];
+ uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid];
+
+ if(chown(pathname, uid_value, guid_value) == -1) {
+ ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+void read_uids_guids(squashfs_super_block *sBlk)
+{
+ if((uid_table = malloc((sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int))) == NULL)
+ EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n");
+
+ guid_table = uid_table + sBlk->no_uids;
+
+ if(read_bytes(sBlk->uid_start, (sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int), (char *) uid_table) ==
+ FALSE)
+ EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n");
+}
+
+
+void read_fragment_table(squashfs_super_block *sBlk)
+{
+ int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments);
+ squashfs_fragment_index fragment_table_index[indexes];
+
+ TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start);
+ if(sBlk->fragments == 0)
+ return;
+
+ if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL)
+ EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n");
+
+ if(swap) {
+ squashfs_fragment_index sfragment_table_index[indexes];
+
+ read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index);
+ SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes);
+ } else
+ read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index);
+
+ for(i = 0; i < indexes; i++) {
+ int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk);
+ TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length);
+ }
+
+ if(swap) {
+ squashfs_fragment_entry sfragment;
+ for(i = 0; i < sBlk->fragments; i++) {
+ SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i]));
+ memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry));
+ }
+ }
+}
+
+
+char *read_fragment(unsigned int fragment)
+{
+ TRACE("read_fragment: reading fragment %d\n", fragment);
+
+ if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) {
+ squashfs_fragment_entry *fragment_entry = &fragment_table[fragment];
+ if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) {
+ ERROR("read_fragment: failed to read fragment %d\n", fragment);
+ cached_frag = SQUASHFS_INVALID_FRAG;
+ return NULL;
+ }
+ cached_frag = fragment;
+ }
+
+ return fragment_data;
+}
+
+
+int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset,
+unsigned int blocks, long long start, char *block_ptr, unsigned int mode)
+{
+ unsigned int file_fd, bytes, i;
+ unsigned int *block_list;
+
+ TRACE("write_file: regular file, blocks %d\n", blocks);
+
+ if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) {
+ ERROR("write_file: unable to malloc block list\n");
+ return FALSE;
+ }
+
+ if(swap) {
+ unsigned int sblock_list[blocks];
+ memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int));
+ SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks);
+ } else
+ memcpy(block_list, block_ptr, blocks * sizeof(unsigned int));
+
+ if((file_fd = open(pathname, O_CREAT | O_WRONLY, (mode_t) mode)) == -1) {
+ ERROR("write_file: failed to create file %s, because %s\n", pathname,
+ strerror(errno));
+ free(block_list);
+ return FALSE;
+ }
+
+ for(i = 0; i < blocks; i++) {
+ if((bytes = read_data_block(start, block_list[i], file_data)) == 0) {
+ ERROR("write_file: failed to read data block 0x%llx\n", start);
+ goto failure;
+ }
+
+ if(write(file_fd, file_data, bytes) < bytes) {
+ ERROR("write_file: failed to write data block 0x%llx\n", start);
+ goto failure;
+ }
+
+ start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]);
+ }
+
+ if(frag_bytes != 0) {
+ char *fragment_data = read_fragment(fragment);
+
+ if(fragment_data == NULL)
+ goto failure;
+
+ if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) {
+ ERROR("write_file: failed to write fragment %d\n", fragment);
+ goto failure;
+ }
+ }
+
+ close(file_fd);
+ return TRUE;
+
+failure:
+ close(file_fd);
+ free(block_list);
+ return FALSE;
+}
+
+
+int create_inode(char *pathname, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk)
+{
+ long long start = sBlk->inode_table_start + start_block;
+ squashfs_inode_header header;
+ char *block_ptr;
+ int bytes = lookup_entry(inode_table_hash, start), file_fd;
+
+ TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset);
+
+ if(bytes == -1) {
+ ERROR("create_inode: inode block 0x%llx out of range!\n", start);
+ return FALSE;
+ }
+ block_ptr = inode_table + bytes + offset;
+
+ if(swap) {
+ squashfs_base_inode_header sinode;
+ memcpy(&sinode, block_ptr, sizeof(header.base));
+ SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header));
+ } else
+ memcpy(&header.base, block_ptr, sizeof(header.base));
+
+ if(created_inode[header.base.inode_number - 1]) {
+ TRACE("create_inode: hard link\n");
+ if(link(created_inode[header.base.inode_number - 1], pathname) == -1) {
+ ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ switch(header.base.inode_type) {
+ case SQUASHFS_FILE_TYPE: {
+ unsigned int frag_bytes;
+ unsigned int blocks;
+ unsigned int offset;
+ long long start;
+ squashfs_reg_inode_header *inode = &header.reg;
+
+ if(swap) {
+ squashfs_reg_inode_header sinode;
+ memcpy(&sinode, block_ptr, sizeof(sinode));
+ SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode);
+ } else
+ memcpy(inode, block_ptr, sizeof(*inode));
+
+ frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size;
+ offset = inode->offset;
+ blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size
+ + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >>
+ sBlk->block_log;
+ start = inode->start_block;
+
+ TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks);
+
+ if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start,
+ block_ptr + sizeof(*inode), inode->mode)) {
+ set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE);
+ file_count ++;
+ }
+ break;
+ }
+ case SQUASHFS_LREG_TYPE: {
+ unsigned int frag_bytes;
+ unsigned int blocks;
+ unsigned int offset;
+ long long start;
+ squashfs_lreg_inode_header *inode = &header.lreg;
+
+ if(swap) {
+ squashfs_lreg_inode_header sinode;
+ memcpy(&sinode, block_ptr, sizeof(sinode));
+ SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode);
+ } else
+ memcpy(inode, block_ptr, sizeof(*inode));
+
+ frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size;
+ offset = inode->offset;
+ blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size
+ + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >>
+ sBlk->block_log;
+ start = inode->start_block;
+
+ TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks);
+
+ if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start,
+ block_ptr + sizeof(*inode), inode->mode)) {
+ set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE);
+ file_count ++;
+ }
+ break;
+ }
+ case SQUASHFS_SYMLINK_TYPE: {
+ squashfs_symlink_inode_header *inodep = &header.symlink;
+ char name[65536];
+
+ if(swap) {
+ squashfs_symlink_inode_header sinodep;
+ memcpy(&sinodep, block_ptr, sizeof(sinodep));
+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep);
+ } else
+ memcpy(inodep, block_ptr, sizeof(*inodep));
+
+ TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size);
+
+ strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size);
+ name[inodep->symlink_size] = '\0';
+
+ if(symlink(name, pathname) == -1) {
+ ERROR("create_inode: failed to create symlink %s, because %s\n", pathname,
+ strerror(errno));
+ break;
+ }
+
+ if(geteuid() == 0) {
+ uid_t uid_value = (uid_t) uid_table[inodep->uid];
+ uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid];
+
+ if(lchown(pathname, uid_value, guid_value) == -1)
+ ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno));
+ }
+
+ sym_count ++;
+ break;
+ }
+ case SQUASHFS_BLKDEV_TYPE:
+ case SQUASHFS_CHRDEV_TYPE: {
+ squashfs_dev_inode_header *inodep = &header.dev;
+
+ if(swap) {
+ squashfs_dev_inode_header sinodep;
+ memcpy(&sinodep, block_ptr, sizeof(sinodep));
+ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep);
+ } else
+ memcpy(inodep, block_ptr, sizeof(*inodep));
+
+ TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev);
+
+ if(geteuid() == 0) {
+ if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK,
+ makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff))
+ == -1) {
+ ERROR("create_inode: failed to create %s device %s, because %s\n",
+ inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block",
+ pathname, strerror(errno));
+ break;
+ }
+ set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE);
+ dev_count ++;
+ } else
+ ERROR("create_inode: could not create %s device %s, because you're not superuser!\n",
+ inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block",
+ pathname, strerror(errno));
+ break;
+ }
+ case SQUASHFS_FIFO_TYPE:
+ TRACE("create_inode: fifo\n");
+
+ if(mknod(pathname, S_IFIFO, 0) == -1) {
+ ERROR("create_inode: failed to create fifo %s, because %s\n",
+ pathname, strerror(errno));
+ break;
+ }
+ set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid,
+ header.base.mtime, TRUE);
+ fifo_count ++;
+ break;
+ case SQUASHFS_SOCKET_TYPE:
+ TRACE("create_inode: socket\n");
+ ERROR("create_inode: socket %s ignored\n", pathname);
+ break;
+ default:
+ ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type);
+ return FALSE;
+ }
+
+ created_inode[header.base.inode_number - 1] = strdup(pathname);
+
+ return TRUE;
+}
+
+
+void uncompress_directory_table(long long start, long long end, squashfs_super_block *sBlk)
+{
+ int bytes = 0, size = 0, res;
+
+ while(start < end) {
+ if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL)
+ EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n");
+ TRACE("uncompress_directory_table: reading block 0x%llx\n", start);
+ add_entry(directory_table_hash, start, bytes);
+ if((res = read_block(start, &start, directory_table + bytes, sBlk)) == 0)
+ EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n");
+ bytes += res;
+ }
+}
+
+
+#define DIR_ENT_SIZE 16
+
+struct dir_ent {
+ char name[SQUASHFS_NAME_LEN + 1];
+ unsigned int start_block;
+ unsigned int offset;
+ unsigned int type;
+};
+
+struct dir {
+ int dir_count;
+ int cur_entry;
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int guid;
+ unsigned int mtime;
+ struct dir_ent *dirs;
+};
+
+
+struct dir *squashfs_openddir(unsigned int block_start, unsigned int offset, squashfs_super_block *sBlk)
+{
+ squashfs_dir_header dirh;
+ char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
+ squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
+ long long start = sBlk->inode_table_start + block_start;
+ char *block_ptr;
+ int bytes = lookup_entry(inode_table_hash, start);
+ squashfs_inode_header header;
+ int dir_count, size;
+ struct dir_ent *new_dir;
+ struct dir *dir;
+
+ TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset);
+
+ if(bytes == -1) {
+ ERROR("squashfs_opendir: inode block %d not found!\n", block_start);
+ return NULL;
+ }
+ block_ptr = inode_table + bytes + offset;
+
+ if(swap) {
+ squashfs_dir_inode_header sinode;
+ memcpy(&sinode, block_ptr, sizeof(header.dir));
+ SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode);
+ } else
+ memcpy(&header.dir, block_ptr, sizeof(header.dir));
+
+ switch(header.dir.inode_type) {
+ case SQUASHFS_DIR_TYPE:
+ block_start = header.dir.start_block;
+ offset = header.dir.offset;
+ size = header.dir.file_size;
+ break;
+ case SQUASHFS_LDIR_TYPE:
+ if(swap) {
+ squashfs_ldir_inode_header sinode;
+ memcpy(&sinode, block_ptr, sizeof(header.ldir));
+ SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode);
+ } else
+ memcpy(&header.ldir, block_ptr, sizeof(header.ldir));
+ block_start = header.ldir.start_block;
+ offset = header.ldir.offset;
+ size = header.ldir.file_size;
+ break;
+ default:
+ ERROR("squashfs_opendir: inode not a directory\n");
+ return NULL;
+ }
+
+ start = sBlk->directory_table_start + block_start;
+ bytes = lookup_entry(directory_table_hash, start);
+
+ if(bytes == -1) {
+ ERROR("squashfs_opendir: directory block %d not found!\n", block_start);
+ return NULL;
+ }
+ bytes += offset;
+ size += bytes - 3;
+
+ if((dir = malloc(sizeof(struct dir))) == NULL) {
+ ERROR("squashfs_opendir: malloc failed!\n");
+ return NULL;
+ }
+
+ dir->dir_count = 0;
+ dir->cur_entry = 0;
+ dir->mode = header.dir.mode;
+ dir->uid = header.dir.uid;
+ dir->guid = header.dir.guid;
+ dir->mtime = header.dir.mtime;
+ dir->dirs = NULL;
+
+ while(bytes < size) {
+ if(swap) {
+ squashfs_dir_header sdirh;
+ memcpy(&sdirh, directory_table + bytes, sizeof(sdirh));
+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
+ } else
+ memcpy(&dirh, directory_table + bytes, sizeof(dirh));
+
+ dir_count = dirh.count + 1;
+ TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count);
+ bytes += sizeof(dirh);
+
+ while(dir_count--) {
+ if(swap) {
+ squashfs_dir_entry sdire;
+ memcpy(&sdire, directory_table + bytes, sizeof(sdire));
+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
+ } else
+ memcpy(dire, directory_table + bytes, sizeof(dire));
+ bytes += sizeof(*dire);
+
+ memcpy(dire->name, directory_table + bytes, dire->size + 1);
+ dire->name[dire->size + 1] = '\0';
+ TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type);
+ if((dir->dir_count % DIR_ENT_SIZE) == 0) {
+ if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) {
+ ERROR("squashfs_opendir: realloc failed!\n");
+ free(dir->dirs);
+ free(dir);
+ return NULL;
+ }
+ dir->dirs = new_dir;
+ }
+ strcpy(dir->dirs[dir->dir_count].name, dire->name);
+ dir->dirs[dir->dir_count].start_block = dirh.start_block;
+ dir->dirs[dir->dir_count].offset = dire->offset;
+ dir->dirs[dir->dir_count].type = dire->type;
+ dir->dir_count ++;
+ bytes += dire->size + 1;
+ }
+ }
+
+ return dir;
+}
+
+
+int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type)
+{
+ if(dir->cur_entry == dir->dir_count)
+ return FALSE;
+
+ *name = dir->dirs[dir->cur_entry].name;
+ *start_block = dir->dirs[dir->cur_entry].start_block;
+ *offset = dir->dirs[dir->cur_entry].offset;
+ *type = dir->dirs[dir->cur_entry].type;
+ dir->cur_entry ++;
+
+ return TRUE;
+}
+
+
+void squashfs_closedir(struct dir *dir)
+{
+ free(dir->dirs);
+ free(dir);
+}
+
+
+int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk)
+{
+ struct dir *dir = squashfs_openddir(start_block, offset, sBlk);
+ unsigned int type;
+ char *name, pathname[1024];
+
+ if(dir == NULL) {
+ ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset);
+ return FALSE;
+ }
+
+ if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1) {
+ ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno));
+ return FALSE;
+ }
+
+ while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) {
+ TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type);
+
+ strcat(strcat(strcpy(pathname, parent_name), "/"), name);
+
+ if(lsonly || info)
+ printf("%s\n", pathname);
+
+ if(type == SQUASHFS_DIR_TYPE)
+ dir_scan(pathname, start_block, offset, sBlk);
+ else
+ if(!lsonly)
+ create_inode(pathname, start_block, offset, sBlk);
+ }
+
+ !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, TRUE);
+
+ squashfs_closedir(dir);
+ dir_count ++;
+
+ return TRUE;
+}
+
+
+int read_super(squashfs_super_block *sBlk, char *source)
+{
+ read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk);
+
+ /* Check it is a SQUASHFS superblock */
+ swap = 0;
+ if(sBlk->s_magic != SQUASHFS_MAGIC) {
+ if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) {
+ squashfs_super_block sblk;
+ ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source);
+ SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk);
+ memcpy(sBlk, &sblk, sizeof(squashfs_super_block));
+ swap = 1;
+ } else {
+ ERROR("Can't find a SQUASHFS superblock on %s\n", source);
+ goto failed_mount;
+ }
+ }
+
+ /* Check the MAJOR & MINOR versions */
+ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
+ ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n",
+ source, sBlk->s_major, sBlk->s_minor);
+ ERROR("I only support Squashfs 3.0 filesystems! Later releases will support older Squashfs filesystems\n");
+ goto failed_mount;
+ }
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+ TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "little" : "big", source);
+#else
+ TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "big" : "little", source);
+#endif
+
+ TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
+ TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : "");
+ TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : "");
+ TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not");
+ TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : "");
+ TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not");
+ TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not");
+ TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0));
+ TRACE("\tBlock size %d\n", sBlk->block_size);
+ TRACE("\tNumber of fragments %d\n", sBlk->fragments);
+ TRACE("\tNumber of inodes %d\n", sBlk->inodes);
+ TRACE("\tNumber of uids %d\n", sBlk->no_uids);
+ TRACE("\tNumber of gids %d\n", sBlk->no_guids);
+ TRACE("sBlk->inode_table_start 0x%llx\n", sBlk->inode_table_start);
+ TRACE("sBlk->directory_table_start 0x%llx\n", sBlk->directory_table_start);
+ TRACE("sBlk->uid_start 0x%llx\n", sBlk->uid_start);
+ TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk->fragment_table_start);
+ TRACE("\n");
+
+ return TRUE;
+
+failed_mount:
+ return FALSE;
+}
+
+
+#define VERSION() \
+ printf("unsquashfs version 1.0 (2006/03/15)\n");\
+ printf("copyright (C) 2006 Phillip Lougher <phillip@lougher.org.uk>\n\n"); \
+ printf("This program is free software; you can redistribute it and/or\n");\
+ printf("modify it under the terms of the GNU General Public License\n");\
+ printf("as published by the Free Software Foundation; either version 2,\n");\
+ printf("or (at your option) any later version.\n\n");\
+ printf("This program is distributed in the hope that it will be useful,\n");\
+ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\
+ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\
+ printf("GNU General Public License for more details.\n");
+int main(int argc, char *argv[])
+{
+ squashfs_super_block sBlk;
+ char *dest = "squashfs-root";
+ int i, version = FALSE;
+
+ for(i = 1; i < argc; i++) {
+ if(*argv[i] != '-')
+ break;
+ if(strcmp(argv[i], "-version") == 0) {
+ VERSION();
+ version = TRUE;
+ } else if(strcmp(argv[i], "-info") == 0)
+ info = TRUE;
+ else if(strcmp(argv[i], "-ls") == 0)
+ lsonly = TRUE;
+ else if(strcmp(argv[i], "-dest") == 0) {
+ if(++i == argc)
+ goto options;
+ dest = argv[i];
+ }
+ }
+
+ if(i == argc) {
+ if(!version) {
+options:
+ ERROR("SYNTAX: %s [-ls | -dest] filesystem\n", argv[0]);
+ ERROR("\t-version\t\tprint version, licence and copyright information\n");
+ ERROR("\t-info\t\t\tprint files as they are unsquashed\n");
+ ERROR("\t-ls\t\t\tlist filesystem only\n");
+ ERROR("\t-dest <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n");
+ }
+ exit(1);
+ }
+
+ if((fd = open(argv[i], O_RDONLY)) == -1) {
+ ERROR("Could not open %s, because %s\n", argv[i], strerror(errno));
+ exit(1);
+ }
+
+ if(read_super(&sBlk, argv[i]) == FALSE)
+ exit(1);
+
+ block_size = sBlk.block_size;
+ if((fragment_data = malloc(block_size)) == NULL)
+ EXIT_UNSQUASH("failed to allocate fragment_data\n");
+
+ if((file_data = malloc(block_size)) == NULL)
+ EXIT_UNSQUASH("failed to allocate file_data");
+
+ if((data = malloc(block_size)) == NULL)
+ EXIT_UNSQUASH("failed to allocate datan\n");
+
+ if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL)
+ EXIT_UNSQUASH("failed to allocate created_inode\n");
+
+ memset(created_inode, 0, sBlk.inodes * sizeof(char *));
+
+ read_uids_guids(&sBlk);
+ read_fragment_table(&sBlk);
+ uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start, &sBlk);
+ uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start, &sBlk);
+
+ dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), &sBlk);
+
+ if(!lsonly) {
+ printf("\n");
+ printf("created %d files\n", file_count);
+ printf("created %d directories\n", dir_count);
+ printf("created %d symlinks\n", sym_count);
+ printf("created %d devices\n", dev_count);
+ printf("created %d fifos\n", fifo_count);
+ }
+
+}